RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially debugged. Do NOT enable these features for normal operations. 1. New Features in 3.1-0 1.1 SCP and libraries - Added simulated Ethernet support for VMS, FreeBSD, Mac OS/X. - Added status return to tmxr_putc_ln. - Added sim_putchar_s to handle possible output stalls. 1.2 All DECtapes - Added "DECtape off reel" error stop. 1.3 All Asynchronous Consoles - Added support for output congestion stall if using a Telnet connection. 1.4 PDP-1 - Added Type 23 parallel drum support. 1.5 PDP-8 - Added instruction history. - Added TSC8-75 option support for ETOS. - Added TD8E DECtape support. 1.6 PDP-18b - Added instruction history. - Changed PDP-9, PDP-15 API default to enabled. 1.7 PDP-11 - Added support for 18b only Qbus devices. - Formalized bus and addressing definitions. - Added control to enable/disable autoconfiguration. - Added stub support for second Unibus Ethernet controller. 1.7 Interdata 32b - Added instruction history. 1.8 Eclipse - Added floating point support. - Added programmable interval timer support. 1.9 H316 - Added DMA/DMC support. - Added fixed head disk support. - Added moving head disk support. - Added magtape support. 1.10 IBM 1130 (Brian Knittel) - Added support for physical card reader, using the Cardread interface (www.ibm1130.org/sim/downloads). - Added support for physical printer (flushes output buffer after each line). 2. Bugs Fixed in 3.1-0 2.1 SCP and libraries - Fixed numerous bugs in Ethernet library. 2.2 All DECtapes - Fixed reverse checksum value in 'read all' mode. - Simplified (and sped up) timing. 2.3 PDP-8 - Fixed bug in RX28 read status (found by Charles Dickman). - Fixed RX28 double density write. 2.4 PDP-18b - Fixed autoincrement bug in PDP-4, PDP-7, PDP-9. 2.5 PDP-11/VAX - Revised RQ MB->LBN conversion for greater accuracy. - Fixed bug in IO configuration (found by David Hittner). - Fixed bug with multiple RQ RAUSER drives. - Fixed bug in second Qbus Ethernet controller interrupts. 2.6 Nova/Eclipse - Fixed bugs in DKP flag clear, map setup, map usage (Charles Owen). - Fixed bug in MT, reset completes despite I/O reset (Charles Owen). - Fixed bug in MT, space operations return word count (Charles Owen). 2.7 IBM 1130 (Brian Knittel) - Fixed bug in setting carry bit in subtract and subtract double. - Fixed timing problem in console printer simulation. 2.8 1620 - Fixed bug in branch digit (found by Dave Babcock). 3. New Features in 3.0 vs prior releases 3.1 SCP and Libraries - Added ASSIGN/DEASSIGN (logical name) commands. - Changed RESTORE to unconditionally detach files. - Added E11 and TPC format support to magtape library. - Fixed bug in SHOW CONNECTIONS. - Added USE_ADDR64 support. 3.2 All magtapes - Magtapes support SIMH format, E11 format, and TPC format (read only). - SET <tape_unit> FORMAT=format sets the specified tape unit's format. - SHOW <tape_unit> FORMAT displays the specified tape unit's format. - Tape format can also be set as part of the ATTACH command, using the -F switch. 3.3 VAX - VAX can be compiled without USE_INT64. - If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support files > 2GB. - VAX ROM has speed control (SET ROM DELAY/NODELAY). 3.4 PDP-1 - Added block loader format support to LOAD. - Changed BOOT PTR to allow loading of all of the first bank of memory. - The LOAD command takes an optional argument specifying the memory field to be loaded. - The PTR BOOT command takes its starting memory field from the TA (address switch) register. 3.5 PDP-18b Family - Added PDP-4 EAE support. - Added PDP-15 FP15 support. - Added PDP-15 XVM support. - Added PDP-15 "re-entrancy ECO". - Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. 4. Bugs Fixed in 3.0 vs prior releases 4.1 SCP and Libraries - Fixed end of file problem in dep, idep. - Fixed handling of trailing spaces in dep, idep. 4.2 VAX - Fixed CVTfi bug: integer overflow not set if exponent out of range - Fixed EMODx bugs: o First and second operands reversed o Separated fraction received wrong exponent o Overflow calculation on separated integer incorrect o Fraction not set to zero if exponent out of range - Fixed interval timer and ROM access to pass power-up self-test even on very fast host processors (fixes from Mark Pizzolato). - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.3 1401 - Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. - Fixed MCE bug, BS off by 1 if zero suppress. - Fixed chaining bug, D lost if return to SCP. - Fixed H branch, branch occurs after continue. - Added check for invalid 8 character MCW, LCA. - Fixed magtape load-mode end of record response. - Revised fetch to model hardware more closely. - Fixed tape read end-of-record handling based on real 1401. - Added diagnostic read (space forward). 4.4 Nova - Fixed DSK variable size interaction with restore. - Fixed bug in DSK set size routine. 4.5 PDP-1 - Fixed DT variable size interaction with restore. - Updated CPU, line printer, standard devices to detect indefinite I/O wait. - Fixed incorrect logical, missing activate, break in drum simulator. - Fixed bugs in instruction decoding, overprinting for line printer. - Fixed system hang if continue after PTR error. - Fixed PTR to start/stop on successive rpa instructions. 4.6 PDP-11 - Fixed DT variable size interaction with restore. - Fixed bug in MMR1 update (found by Tim Stark). - Added XQ features and fixed bugs: o Corrected XQ interrupts on IE state transition (code by Tom Evans). o Added XQ interrupt clear on soft reset. o Removed XQ interrupt when setting XL or RL (multiple people). o Added SET/SHOW XQ STATS. o Added SHOW XQ FILTERS. o Added ability to split received packet into multiple buffers. o Added explicit runt and giant packet processing. - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.7 PDP-18B - Fixed DT, RF variable size interaction with restore. - Fixed MT bug in MTTR. - Fixed bug in PDP-4 line printer overprinting. - Fixed bug in PDP-15 memory protect/skip interaction. - Fixed bug in RF set size routine. - Increased PTP TIME for PDP-15 operating systems. - Fixed priorities in PDP-15 API (differs from PDP-9). - Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9). - Fixed bug in CAF, clears API subsystem. 4.8 PDP-8 - Fixed DT, DF, RF, RX variable size interaction with restore. - Fixed MT bug in SKTR. - Fixed bug in DF, RF set size routine. 4.9 HP2100 - Fixed bug in DP (13210A controller only), DQ read status. - Fixed bug in DP, DQ seek complete. - Fixed DR drum sizes. - Fixed DR variable capacity interaction with SAVE/RESTORE. 4.10 GRI - Fixed bug in SC queue pointer management. 4.11 PDP-10 - Fixed bug in RP read header. 4.12 Ibm1130 - Fixed bugs found by APL 1130. 4.13 Altairz80 - Fixed bug in real-time clock on Windows host. 4.14 1620 - Fixed bug in immediate index add (found by Michael Short).
494 lines
13 KiB
C
494 lines
13 KiB
C
/* ibm1130_sys.c: IBM 1130 simulator interface
|
||
|
||
Based on PDP-11 simulator written by Robert M Supnik
|
||
|
||
Revision History
|
||
0.26 2002Apr24 - Added !BREAK in card deck file to stop simulator
|
||
0.25 2002Apr18 - Fixed some card reader problems. It starts the reader
|
||
properly if you attach a deck while it's waiting to a read.
|
||
0.24 2002Mar27 - Fixed BOSC bug; BOSC works in short instructions too
|
||
0.23 2002Feb26 - Added @decklist feature for ATTACH CR.
|
||
0.22 2002Feb26 - Replaced "strupr" with "upcase" for compatibility.
|
||
0.21 2002Feb25 - Some compiler compatibiity changes, couple of compiler-detected
|
||
bugs
|
||
0.01 2001Jul31 - Derived from pdp11_sys.c, which carries this disclaimer:
|
||
|
||
* (C) Copyright 2002, Brian Knittel.
|
||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||
* or modifications.
|
||
*
|
||
* This is not a supported product, but I welcome bug reports and fixes.
|
||
* Mail to simh@ibm1130.org
|
||
*/
|
||
|
||
#include "ibm1130_defs.h"
|
||
#include <ctype.h>
|
||
#include <stdarg.h>
|
||
|
||
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev;
|
||
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev;
|
||
extern DEVICE gdu_dev, console_dev;
|
||
|
||
extern UNIT cpu_unit;
|
||
extern REG cpu_reg[];
|
||
extern int32 saved_PC;
|
||
|
||
/* SCP data structures and interface routines
|
||
|
||
sim_name simulator name string
|
||
sim_PC pointer to saved PC register descriptor
|
||
sim_emax number of words for examine
|
||
sim_devices array of pointers to simulated devices
|
||
sim_stop_messages array of pointers to stop messages
|
||
sim_load binary loader
|
||
*/
|
||
|
||
char sim_name[] = "IBM 1130";
|
||
|
||
REG *sim_PC = &cpu_reg[0];
|
||
|
||
int32 sim_emax = 4;
|
||
|
||
DEVICE *sim_devices[] = {
|
||
&cpu_dev, /* the cpu */
|
||
&dsk_dev, /* disk drive(s) */
|
||
&cr_dev, /* card reader/punch */
|
||
&cp_dev,
|
||
&tti_dev, /* console keyboard, selectric printer */
|
||
&tto_dev,
|
||
&prt_dev, /* 1132 printer */
|
||
&console_dev, /* console display (windows GUI) */
|
||
&gdu_dev, /* 2250 display */
|
||
NULL
|
||
};
|
||
|
||
const char *sim_stop_messages[] = {
|
||
"Unknown error",
|
||
"Wait",
|
||
"Invalid command",
|
||
"Simulator breakpoint",
|
||
"Use of incomplete simulator function",
|
||
"Power off",
|
||
"!BREAK in card deck file",
|
||
"Phase load break",
|
||
"Program has run amok",
|
||
"Run time limit exceeded"
|
||
};
|
||
|
||
/* Loader. IPL is normally performed by card reader (boot command). This function
|
||
* loads hex data from a file for testing purposes. The format is:
|
||
*
|
||
* blank lines or lines starting with ; / or # are ignored as comments
|
||
*
|
||
* @XXXX set load addresss to hex value XXXX
|
||
* XXXX store hex word value XXXX at current load address and increment address
|
||
* ...
|
||
* =XXXX set IAR to hex value XXXX
|
||
* ZXXXX zero XXXX words and increment load address
|
||
* SXXXX set console entry switches to XXXX. This lets a program specify the
|
||
* default value for the toggle switches.
|
||
*
|
||
* Multiple @ and data sections may be entered. If more than one = or S value is specified
|
||
* the last one wins.
|
||
*
|
||
* Note: the load address @XXXX and data values XXXX can be followed by the letter
|
||
* R to indicate that the values are relocatable addresses. This is ignored in this loader,
|
||
* but the asm1130 cross assembler may put them there.
|
||
*/
|
||
|
||
t_stat my_load (FILE *fileref, char *cptr, char *fnam)
|
||
{
|
||
char line[150], *c;
|
||
int iaddr = -1, runaddr = -1, val, nwords;
|
||
|
||
while (fgets(line, sizeof(line), fileref) != NULL) {
|
||
for (c = line; *c && *c <= ' '; c++) // find first nonblank
|
||
;
|
||
|
||
if (*c == '\0' || *c == '#' || *c == '/' || *c == ';')
|
||
continue; // empty line or comment
|
||
|
||
if (*c == '@') { // set load address
|
||
if (sscanf(c+1, "%x", &iaddr) != 1)
|
||
return SCPE_FMT;
|
||
}
|
||
else if (*c == '=') {
|
||
if (sscanf(c+1, "%x", &runaddr) != 1)
|
||
return SCPE_FMT;
|
||
}
|
||
else if (*c == 's' || *c == 'S') {
|
||
if (sscanf(c+1, "%x", &val) != 1)
|
||
return SCPE_FMT;
|
||
|
||
CES = val & 0xFFFF; // preload console entry switches
|
||
}
|
||
else if (*c == 'z' || *c == 'Z') {
|
||
if (sscanf(c+1, "%x", &nwords) != 1)
|
||
return SCPE_FMT;
|
||
|
||
if (iaddr == -1)
|
||
return SCPE_FMT;
|
||
|
||
while (--nwords >= 0) {
|
||
WriteW(iaddr, 0);
|
||
iaddr++;
|
||
}
|
||
}
|
||
else if (strchr("0123456789abcdefABCDEF", *c) != NULL) {
|
||
if (sscanf(c, "%x", &val) != 1)
|
||
return SCPE_FMT;
|
||
|
||
if (iaddr == -1)
|
||
return SCPE_FMT;
|
||
|
||
WriteW(iaddr, val); // store data
|
||
iaddr++;
|
||
}
|
||
else
|
||
return SCPE_FMT; // unexpected data
|
||
}
|
||
|
||
if (runaddr != -1)
|
||
IAR = runaddr;
|
||
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_stat my_save (FILE *fileref, char *cptr, char *fnam)
|
||
{
|
||
int iaddr, nzeroes = 0, nwords = (int) (MEMSIZE/2), val;
|
||
|
||
fprintf(fileref, "=%04x\r\n", IAR);
|
||
fprintf(fileref, "@0000\r\n");
|
||
for (iaddr = 0; iaddr < nwords; iaddr++) {
|
||
val = ReadW(iaddr);
|
||
if (val == 0) // queue up zeroes
|
||
nzeroes++;
|
||
else {
|
||
if (nzeroes >= 4) { // spit out a Z directive
|
||
fprintf(fileref, "Z%04x\r\n", nzeroes);
|
||
nzeroes = 0;
|
||
}
|
||
else { // write queued zeroes literally
|
||
while (nzeroes > 0) {
|
||
fprintf(fileref, " 0000\r\n");
|
||
nzeroes--;
|
||
}
|
||
}
|
||
fprintf(fileref, " %04x\r\n", val);
|
||
}
|
||
}
|
||
if (nzeroes >= 4) { // emit any queued zeroes
|
||
fprintf(fileref, "Z%04x\r\n", nzeroes);
|
||
nzeroes = 0;
|
||
}
|
||
else {
|
||
while (nzeroes > 0) {
|
||
fprintf(fileref, " 0000\r\n");
|
||
nzeroes--;
|
||
}
|
||
}
|
||
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||
{
|
||
if (flag)
|
||
return my_save(fileref, cptr, fnam);
|
||
else
|
||
return my_load(fileref, cptr, fnam);
|
||
}
|
||
|
||
/* Specifier decode
|
||
|
||
Inputs:
|
||
*of = output stream
|
||
addr = current PC
|
||
spec = specifier
|
||
nval = next word
|
||
flag = TRUE if decoding for CPU
|
||
iflag = TRUE if decoding integer instruction
|
||
Outputs:
|
||
count = -number of extra words retired
|
||
*/
|
||
|
||
/* Symbolic decode
|
||
|
||
Inputs:
|
||
*of = output stream
|
||
addr = current PC
|
||
*val = values to decode
|
||
*uptr = pointer to unit
|
||
sw = switches
|
||
Outputs:
|
||
return = if >= 0, error code
|
||
if < 0, number of extra words retired
|
||
*/
|
||
|
||
static char *opcode[] = {
|
||
"?00 ", "XIO ", "SLA ", "SRA ",
|
||
"LDS ", "STS ", "WAIT", "?07 ",
|
||
"BSI ", "BSC ", "?0A ", "?0B ",
|
||
"LDX ", "STX ", "MDX ", "?0F ",
|
||
"A ", "AD ", "S ", "SD ",
|
||
"M ", "D ", "?16 ", "?17 ",
|
||
"LD ", "LDD ", "STO ", "STD ",
|
||
"AND ", "OR ", "EOR ", "?1F ",
|
||
};
|
||
|
||
static char relative[] = { // true if short mode displacements are IAR relative
|
||
FALSE, TRUE, FALSE, FALSE,
|
||
FALSE, TRUE, FALSE, FALSE,
|
||
TRUE, FALSE, FALSE, FALSE,
|
||
TRUE, TRUE, TRUE, FALSE,
|
||
TRUE, TRUE, TRUE, TRUE,
|
||
TRUE, TRUE, FALSE, FALSE,
|
||
TRUE, TRUE, TRUE, TRUE,
|
||
TRUE, TRUE, TRUE, FALSE
|
||
};
|
||
|
||
static char *lsopcode[] = {"SLA ", "SLCA ", "SLT ", "SLC "};
|
||
static char *rsopcode[] = {"SRA ", "?188 ", "SRT ", "RTE "};
|
||
static char tagc[] = " 123";
|
||
|
||
static int ascii_to_ebcdic_table[128] =
|
||
{
|
||
0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,
|
||
0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,
|
||
0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,
|
||
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,
|
||
|
||
0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
|
||
0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d,
|
||
0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
|
||
0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,
|
||
};
|
||
|
||
static int ebcdic_to_ascii (int ch)
|
||
{
|
||
int j;
|
||
|
||
for (j = 32; j < 128; j++)
|
||
if (ascii_to_ebcdic_table[j] == ch)
|
||
return j;
|
||
|
||
return '?';
|
||
}
|
||
|
||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
|
||
{
|
||
int32 cflag, ch, OP, F, TAG, INDIR, DSPLC, IR, eaddr;
|
||
char *mnem, tst[12];
|
||
|
||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||
|
||
// if (sw & SWMASK ('A')) { /* ASCII? not useful */
|
||
// fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||
// return SCPE_OK;
|
||
// }
|
||
|
||
if (sw & SWMASK ('C')) /* character? not useful -- make it EBCDIC */
|
||
sw |= SWMASK('E');
|
||
|
||
if (sw & SWMASK ('E')) { /* EBCDIC! */
|
||
ch = ebcdic_to_ascii((val[0] >> 8) & 0xFF); /* take high byte first */
|
||
fprintf (of, (ch < ' ')? "<%03o>": "%c", ch);
|
||
ch = ebcdic_to_ascii(val[0] & 0xFF);
|
||
fprintf (of, (ch < ' ')? "<%03o>": "%c", ch);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
if (sw & SWMASK ('H')) { /* HOLLERITH! now THIS is useful! */
|
||
ch = hollerith_to_ascii((int16) val[0]);
|
||
fprintf (of, (ch < ' ')? "<%03o>": "%c", ch);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
if (! (sw & SWMASK ('M')))
|
||
return SCPE_ARG;
|
||
|
||
IR = val[0];
|
||
OP = (IR >> 11) & 0x1F; /* opcode */
|
||
F = IR & 0x0400; /* format bit: 1 = long instr */
|
||
TAG = IR & 0x0300; /* tag bits: index reg select */
|
||
if (TAG)
|
||
TAG >>= 8;
|
||
|
||
if (F) { /* long instruction, ASSUME it's valid (have to decrement IAR if not) */
|
||
INDIR = IR & 0x0080; /* indirect bit */
|
||
DSPLC = IR & 0x007F; /* displacement or modifier */
|
||
if (DSPLC & 0x0040)
|
||
DSPLC |= ~ 0x7F; /* sign extend */
|
||
|
||
eaddr = val[1]; /* get reference address */
|
||
}
|
||
else { /* short instruction, use displacement */
|
||
INDIR = 0; /* never indirect */
|
||
DSPLC = IR & 0x00FF; /* get displacement */
|
||
if (DSPLC & 0x0080)
|
||
DSPLC |= ~ 0xFF;
|
||
|
||
eaddr = DSPLC;
|
||
if (relative[OP] && ! TAG)
|
||
eaddr += addr+1; /* turn displacement into address */
|
||
}
|
||
|
||
mnem = opcode[OP]; /* get mnemonic */
|
||
if (OP == 0x02) { /* left shifts are special */
|
||
mnem = lsopcode[(DSPLC >> 6) & 0x0003];
|
||
DSPLC &= 0x003F;
|
||
eaddr = DSPLC;
|
||
}
|
||
else if (OP == 0x03) { /* right shifts too */
|
||
mnem = rsopcode[(DSPLC >> 6) & 0x0003];
|
||
DSPLC &= 0x003F;
|
||
eaddr = DSPLC;
|
||
}
|
||
else if ((OP == 0x08 && F)|| OP == 0x09) { // BSI L and BSC any
|
||
if (OP == 0x09 && (IR & 0x40))
|
||
mnem = "BOSC";
|
||
|
||
tst[0] = '\0';
|
||
if (DSPLC & 0x20) strcat(tst, "Z");
|
||
if (DSPLC & 0x10) strcat(tst, "-");
|
||
if (DSPLC & 0x08) strcat(tst, "+");
|
||
if (DSPLC & 0x04) strcat(tst, "E");
|
||
if (DSPLC & 0x02) strcat(tst, "C");
|
||
if (DSPLC & 0x01) strcat(tst, "O");
|
||
|
||
if (F) {
|
||
fprintf(of, "%04x %s %c%c %s,%04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst, eaddr & 0xFFFF);
|
||
return -1;
|
||
}
|
||
fprintf(of, "%04x %s %c%c %s ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], tst);
|
||
return SCPE_OK;
|
||
}
|
||
else if (OP == 0x0e && TAG == 0) { // MDX with no tag => MDM or jump
|
||
if (F) {
|
||
fprintf(of, "%04x %s %c%c %04x,%x (%d) ", IR & 0xFFFF, "MDM ", (INDIR ? 'I' : 'L'), tagc[TAG], eaddr & 0xFFFF, DSPLC & 0xFFFF, DSPLC);
|
||
return -1;
|
||
}
|
||
mnem = "JMP ";
|
||
}
|
||
|
||
fprintf(of, "%04x %s %c%c %04x ", IR & 0xFFFF, mnem, F ? (INDIR ? 'I' : 'L') : ' ', tagc[TAG], eaddr & 0xFFFF);
|
||
return F ? -1 : SCPE_OK; /* inform how many words we read */
|
||
}
|
||
|
||
int32 get_reg (char *cptr, const char *strings[], char mchar)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
/* Number or memory address
|
||
|
||
Inputs:
|
||
*cptr = pointer to input string
|
||
*dptr = pointer to output displacement
|
||
*pflag = pointer to accumulating flags
|
||
Outputs:
|
||
cptr = pointer to next character in input string
|
||
NULL if parsing error
|
||
|
||
Flags: 0 (no result), A_NUM (number), A_REL (relative)
|
||
*/
|
||
|
||
char *get_addr (char *cptr, int32 *dptr, int32 *pflag)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
/* Specifier decode
|
||
|
||
Inputs:
|
||
*cptr = pointer to input string
|
||
addr = current PC
|
||
n1 = 0 if no extra word used
|
||
-1 if extra word used in prior decode
|
||
*sptr = pointer to output specifier
|
||
*dptr = pointer to output displacement
|
||
cflag = true if parsing for the CPU
|
||
iflag = true if integer specifier
|
||
Outputs:
|
||
status = = -1 extra word decoded
|
||
= 0 ok
|
||
= +1 error
|
||
*/
|
||
|
||
t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr,
|
||
int32 cflag, int32 iflag)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
/* Symbolic input
|
||
|
||
Inputs:
|
||
*cptr = pointer to input string
|
||
addr = current PC
|
||
*uptr = pointer to unit
|
||
*val = pointer to output values
|
||
sw = switches
|
||
Outputs:
|
||
status = > 0 error code
|
||
<= 0 -number of extra words
|
||
*/
|
||
|
||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||
{
|
||
return SCPE_ARG;
|
||
}
|
||
|
||
#ifndef WIN32
|
||
|
||
int strnicmp (char *a, char *b, int n)
|
||
{
|
||
int ca, cb;
|
||
|
||
for (;;) {
|
||
if (--n < 0) // still equal after n characters? quit now
|
||
return 0;
|
||
|
||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||
return *b ? -1 : 0;
|
||
|
||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||
ca -= 32;
|
||
|
||
cb = *b;
|
||
if (cb >= 'a' && cb <= 'z')
|
||
cb -= 32;
|
||
|
||
if ((ca -= cb) != 0) // if different, return comparison
|
||
return ca;
|
||
|
||
a++, b++;
|
||
}
|
||
}
|
||
|
||
int strcmpi (char *a, char *b)
|
||
{
|
||
int ca, cb;
|
||
|
||
for (;;) {
|
||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||
return *b ? -1 : 0;
|
||
|
||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||
ca -= 32;
|
||
|
||
cb = *b;
|
||
if (cb >= 'a' && cb <= 'z')
|
||
cb -= 32;
|
||
|
||
if ((ca -= cb) != 0) // if different, return comparison
|
||
return ca;
|
||
|
||
a++, b++;
|
||
}
|
||
}
|
||
|
||
#endif
|