home *** CD-ROM | disk | FTP | other *** search
- /* nova_sys.c: NOVA simulator interface
-
- Copyright (c) 1993, 1994, 1995, 1996,
- Robert M Supnik, Digital Equipment Corporation
- Commercial use prohibited
- */
-
- #include "nova_defs.h"
- #include <ctype.h>
-
- extern DEVICE cpu_dev;
- extern UNIT cpu_unit;
- extern DEVICE ptr_dev, ptp_dev;
- extern DEVICE tti_dev, tto_dev;
- extern DEVICE clk_dev, lpt_dev;
- extern DEVICE dkp_dev, dsk_dev;
- extern DEVICE mta_dev;
- extern REG cpu_reg[];
- extern unsigned short M[];
- extern int saved_PC;
- extern char *get_glyph (char *cptr, char *gbuf, char term);
- extern int get_unum (char *cptr, int radix, unsigned int max,
- unsigned int *val);
-
- /* SCP data structures
-
- sim_name simulator name string
- sim_PC pointer to saved PC register descriptor
- sim_emax number of words needed 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[] = "NOVA";
-
- REG *sim_PC = &cpu_reg[0];
-
- int sim_emax = 4;
-
- DEVICE *sim_devices[] = { &cpu_dev,
- &ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
- &clk_dev, &lpt_dev, &dsk_dev, &dkp_dev,
- &mta_dev, NULL };
-
- const char *sim_stop_messages[] = {
- "Unknown error",
- "Unknown I/O instruction",
- "HALT instruction",
- "Breakpoint",
- "Infinite instruction indirect",
- "Infinite interrupt indirect" };
-
- /* Binary loader
-
- Loader format consists of blocks, optionally preceded, separated, and
- followed by zeroes. Each block consists of:
-
- lo_count
- hi_count
- lo_origin
- hi_origin
- lo_checksum
- hi_checksum
- lo_data byte ---
- hi_data byte |
- : > -count words
- lo_data byte |
- hi_data byte ---
-
- If the word count is [0,-20], then the block is normal data.
- If the word count is [-21,-n], then the block is repeated data.
- If the word count is 1, the block is the start address.
- If the word count is >1, the block is an error block.
- */
-
- int sim_load (FILE *fileref)
- {
- int data, origin, csum, count, state, i;
-
- state = 0;
- while ((i = getc (fileref)) != EOF) {
- switch (state) {
- case 0: /* leader */
- count = i;
- state = (count != 0);
- break;
- case 1: /* high count */
- csum = count = (i << 8) | count;
- state = 2;
- break;
- case 2: /* low origin */
- origin = i;
- state = 3;
- break;
- case 3: /* high origin */
- origin = (i << 8) | origin;
- csum = csum + origin;
- state = 4;
- break;
- case 4: /* low checksum */
- csum = csum + i;
- state = 5;
- break;
- case 5: /* high checksum */
- csum = csum + (i << 8);
- if (count == 1) saved_PC = origin; /* count = 1? */
- if (count <= 1) { /* count = 0/1? */
- if (csum & 0177777) return SCPE_CSUM;
- state = 0;
- break; }
- if (count < 0100000) { /* count > 1 */
- state = 8;
- break; }
- count = 0200000 - count;
- state = 6;
- break;
- case 6: /* low data */
- data = i;
- state = 7;
- break;
- case 7: /* high data */
- data = (i << 8) | data;
- csum = csum + data;
- if (count > 20) { /* large block */
- for (count = count - 1; count == 1; count--) {
- if (origin >= MEMSIZE) return SCPE_NXM;
- M[origin] = data;
- origin = origin + 1; } }
- if (origin >= MEMSIZE) return SCPE_NXM;
- M[origin] = data;
- origin = origin + 1;
- count = count - 1;
- if (count == 0) {
- if (csum & 0177777) return SCPE_CSUM;
- state = 0;
- break; }
- state = 6;
- break;
- case 8: /* error block */
- if (i == 0377) state = 0;
- break; } /* end switch */
- } /* end while */
-
- /* Ok to find end of tape between blocks or in error state */
-
- return ((state == 0) || (state == 8))? SCPE_OK: SCPE_FMT;
- }
-
- /* Symbol tables */
-
- #define I_V_FL 18 /* flag bits */
- #define I_M_FL 07 /* flag width */
- #define I_V_NPN 0 /* no operands */
- #define I_V_R 1 /* reg */
- #define I_V_D 2 /* device */
- #define I_V_RD 3 /* reg,device */
- #define I_V_M 4 /* mem addr */
- #define I_V_RM 5 /* reg, mem addr */
- #define I_V_RR 6 /* operate */
- #define I_NPN (I_V_NPN << I_V_FL)
- #define I_R (I_V_R << I_V_FL)
- #define I_D (I_V_D << I_V_FL)
- #define I_RD (I_V_RD << I_V_FL)
- #define I_M (I_V_M << I_V_FL)
- #define I_RM (I_V_RM << I_V_FL)
- #define I_RR (I_V_RR << I_V_FL)
-
- static const int masks[] = {
- 0177777, 0163777, 0177700, 0163700,
- 0174000, 0160000, 0103770 };
-
- static const char *opcode[] = {
- "JMP", "JSR", "ISZ", "DSZ",
- "LDA", "STA",
- "COM", "COMZ", "COMO", "COMC",
- "COML", "COMZL", "COMOL", "COMCL",
- "COMR", "COMZR", "COMOR", "COMCR",
- "COMS", "COMZS", "COMOS", "COMCS",
- "COM#", "COMZ#", "COMO#", "COMC#",
- "COML#", "COMZL#", "COMOL#", "COMCL#",
- "COMR#", "COMZR#", "COMOR#", "COMCR#",
- "COMS#", "COMZS#", "COMOS#", "COMCS#",
- "NEG", "NEGZ", "NEGO", "NEGC",
- "NEGL", "NEGZL", "NEGOL", "NEGCL",
- "NEGR", "NEGZR", "NEGOR", "NEGCR",
- "NEGS", "NEGZS", "NEGOS", "NEGCS",
- "NEG#", "NEGZ#", "NEGO#", "NEGC#",
- "NEGL#", "NEGZL#", "NEGOL#", "NEGCL#",
- "NEGR#", "NEGZR#", "NEGOR#", "NEGCR#",
- "NEGS#", "NEGZS#", "NEGOS#", "NEGCS#",
- "MOV", "MOVZ", "MOVO", "MOVC",
- "MOVL", "MOVZL", "MOVOL", "MOVCL",
- "MOVR", "MOVZR", "MOVOR", "MOVCR",
- "MOVS", "MOVZS", "MOVOS", "MOVCS",
- "MOV#", "MOVZ#", "MOVO#", "MOVC#",
- "MOVL#", "MOVZL#", "MOVOL#", "MOVCL#",
- "MOVR#", "MOVZR#", "MOVOR#", "MOVCR#",
- "MOVS#", "MOVZS#", "MOVOS#", "MOVCS#",
- "INC", "INCZ", "INCO", "INCC",
- "INCL", "INCZL", "INCOL", "INCCL",
- "INCR", "INCZR", "INCOR", "INCCR",
- "INCS", "INCZS", "INCOS", "INCCS",
- "INC#", "INCZ#", "INCO#", "INCC#",
- "INCL#", "INCZL#", "INCOL#", "INCCL#",
- "INCR#", "INCZR#", "INCOR#", "INCCR#",
- "INCS#", "INCZS#", "INCOS#", "INCCS#",
- "ADC", "ADCZ", "ADCO", "ADCC",
- "ADCL", "ADCZL", "ADCOL", "ADCCL",
- "ADCR", "ADCZR", "ADCOR", "ADCCR",
- "ADCS", "ADCZS", "ADCOS", "ADCCS",
- "ADC#", "ADCZ#", "ADCO#", "ADCC#",
- "ADCL#", "ADCZL#", "ADCOL#", "ADCCL#",
- "ADCR#", "ADCZR#", "ADCOR#", "ADCCR#",
- "ADCS#", "ADCZS#", "ADCOS#", "ADCCS#",
- "SUB", "SUBZ", "SUBO", "SUBC",
- "SUBL", "SUBZL", "SUBOL", "SUBCL",
- "SUBR", "SUBZR", "SUBOR", "SUBCR",
- "SUBS", "SUBZS", "SUBOS", "SUBCS",
- "SUB#", "SUBZ#", "SUBO#", "SUBC#",
- "SUBL#", "SUBZL#", "SUBOL#", "SUBCL#",
- "SUBR#", "SUBZR#", "SUBOR#", "SUBCR#",
- "SUBS#", "SUBZS#", "SUBOS#", "SUBCS#",
- "ADD", "ADDZ", "ADDO", "ADDC",
- "ADDL", "ADDZL", "ADDOL", "ADDCL",
- "ADDR", "ADDZR", "ADDOR", "ADDCR",
- "ADDS", "ADDZS", "ADDOS", "ADDCS",
- "ADD#", "ADDZ#", "ADDO#", "ADDC#",
- "ADDL#", "ADDZL#", "ADDOL#", "ADDCL#",
- "ADDR#", "ADDZR#", "ADDOR#", "ADDCR#",
- "ADDS#", "ADDZS#", "ADDOS#", "ADDCS#",
- "AND", "ANDZ", "ANDO", "ANDC",
- "ANDL", "ANDZL", "ANDOL", "ANDCL",
- "ANDR", "ANDZR", "ANDOR", "ANDCR",
- "ANDS", "ANDZS", "ANDOS", "ANDCS",
- "AND#", "ANDZ#", "ANDO#", "ANDC#",
- "ANDL#", "ANDZL#", "ANDOL#", "ANDCL#",
- "ANDR#", "ANDZR#", "ANDOR#", "ANDCR#",
- "ANDS#", "ANDZS#", "ANDOS#", "ANDCS#",
- "ION", "IOF",
- "RDSW", "INTA", "MSKO", "IORST", "HALT",
- "MUL", "DIV",
- "NIO", "NIOS", "NIOC", "NIOP",
- "DIA", "DIAS", "DIAC", "DIAP",
- "DOA", "DOAS", "DOAC", "DOAP",
- "DIB", "DIBS", "DIBC", "DIBP",
- "DOB", "DOBS", "DOBC", "DOBP",
- "DIC", "DICS", "DICC", "DICP",
- "DOC", "DOCS", "DOCC", "DOCP",
- "SKPBN", "SKPBZ", "SKPDN", "SKPDZ",
- NULL };
-
- static const opc_val[] = {
- 0000000+I_M, 0004000+I_M, 0010000+I_M, 0014000+I_M,
- 0020000+I_RM, 0040000+I_RM,
- 0100000+I_RR, 0100020+I_RR, 0100040+I_RR, 0100060+I_RR,
- 0100100+I_RR, 0100120+I_RR, 0100140+I_RR, 0100160+I_RR,
- 0100200+I_RR, 0100220+I_RR, 0100240+I_RR, 0100260+I_RR,
- 0100300+I_RR, 0100320+I_RR, 0100340+I_RR, 0100360+I_RR,
- 0100010+I_RR, 0100030+I_RR, 0100050+I_RR, 0100070+I_RR,
- 0100110+I_RR, 0100130+I_RR, 0100150+I_RR, 0100170+I_RR,
- 0100210+I_RR, 0100230+I_RR, 0100250+I_RR, 0100270+I_RR,
- 0100310+I_RR, 0100330+I_RR, 0100350+I_RR, 0100370+I_RR,
- 0100400+I_RR, 0100420+I_RR, 0100440+I_RR, 0100460+I_RR,
- 0100500+I_RR, 0100520+I_RR, 0100540+I_RR, 0100560+I_RR,
- 0100600+I_RR, 0100620+I_RR, 0100640+I_RR, 0100660+I_RR,
- 0100700+I_RR, 0100720+I_RR, 0100740+I_RR, 0100760+I_RR,
- 0100410+I_RR, 0100430+I_RR, 0100450+I_RR, 0100470+I_RR,
- 0100510+I_RR, 0100530+I_RR, 0100550+I_RR, 0100570+I_RR,
- 0100610+I_RR, 0100630+I_RR, 0100650+I_RR, 0100670+I_RR,
- 0100710+I_RR, 0100730+I_RR, 0100750+I_RR, 0100770+I_RR,
- 0101000+I_RR, 0101020+I_RR, 0101040+I_RR, 0101060+I_RR,
- 0101100+I_RR, 0101120+I_RR, 0101140+I_RR, 0101160+I_RR,
- 0101200+I_RR, 0101220+I_RR, 0101240+I_RR, 0101260+I_RR,
- 0101300+I_RR, 0101320+I_RR, 0101340+I_RR, 0101360+I_RR,
- 0101010+I_RR, 0101030+I_RR, 0101050+I_RR, 0101070+I_RR,
- 0101110+I_RR, 0101130+I_RR, 0101150+I_RR, 0101170+I_RR,
- 0101210+I_RR, 0101230+I_RR, 0101250+I_RR, 0101270+I_RR,
- 0101310+I_RR, 0101330+I_RR, 0101350+I_RR, 0101370+I_RR,
- 0101400+I_RR, 0101420+I_RR, 0101440+I_RR, 0101460+I_RR,
- 0101500+I_RR, 0101520+I_RR, 0101540+I_RR, 0101560+I_RR,
- 0101600+I_RR, 0101620+I_RR, 0101640+I_RR, 0101660+I_RR,
- 0101700+I_RR, 0101720+I_RR, 0101740+I_RR, 0101760+I_RR,
- 0101410+I_RR, 0101430+I_RR, 0101450+I_RR, 0101470+I_RR,
- 0101510+I_RR, 0101530+I_RR, 0101550+I_RR, 0101570+I_RR,
- 0101610+I_RR, 0101630+I_RR, 0101650+I_RR, 0101670+I_RR,
- 0101710+I_RR, 0101730+I_RR, 0101750+I_RR, 0101770+I_RR,
- 0102000+I_RR, 0102020+I_RR, 0102040+I_RR, 0102060+I_RR,
- 0102100+I_RR, 0102120+I_RR, 0102140+I_RR, 0102160+I_RR,
- 0102200+I_RR, 0102220+I_RR, 0102240+I_RR, 0102260+I_RR,
- 0102300+I_RR, 0102320+I_RR, 0102340+I_RR, 0102360+I_RR,
- 0102010+I_RR, 0102030+I_RR, 0102050+I_RR, 0102070+I_RR,
- 0102110+I_RR, 0102130+I_RR, 0102150+I_RR, 0102170+I_RR,
- 0102210+I_RR, 0102230+I_RR, 0102250+I_RR, 0102270+I_RR,
- 0102310+I_RR, 0102330+I_RR, 0102350+I_RR, 0102370+I_RR,
- 0102400+I_RR, 0102420+I_RR, 0102440+I_RR, 0102460+I_RR,
- 0102500+I_RR, 0102520+I_RR, 0102540+I_RR, 0102560+I_RR,
- 0102600+I_RR, 0102620+I_RR, 0102640+I_RR, 0102660+I_RR,
- 0102700+I_RR, 0102720+I_RR, 0102740+I_RR, 0102760+I_RR,
- 0102410+I_RR, 0102430+I_RR, 0102450+I_RR, 0102470+I_RR,
- 0102510+I_RR, 0102530+I_RR, 0102550+I_RR, 0102570+I_RR,
- 0102610+I_RR, 0102630+I_RR, 0102650+I_RR, 0102670+I_RR,
- 0102710+I_RR, 0102730+I_RR, 0102750+I_RR, 0102770+I_RR,
- 0103000+I_RR, 0103020+I_RR, 0103040+I_RR, 0103060+I_RR,
- 0103100+I_RR, 0103120+I_RR, 0103140+I_RR, 0103160+I_RR,
- 0103200+I_RR, 0103220+I_RR, 0103240+I_RR, 0103260+I_RR,
- 0103300+I_RR, 0103320+I_RR, 0103340+I_RR, 0103360+I_RR,
- 0103010+I_RR, 0103030+I_RR, 0103050+I_RR, 0103070+I_RR,
- 0103110+I_RR, 0103130+I_RR, 0103150+I_RR, 0103170+I_RR,
- 0103210+I_RR, 0103230+I_RR, 0103250+I_RR, 0103270+I_RR,
- 0103310+I_RR, 0103330+I_RR, 0103350+I_RR, 0103370+I_RR,
- 0103400+I_RR, 0103420+I_RR, 0103440+I_RR, 0103460+I_RR,
- 0103500+I_RR, 0103520+I_RR, 0103540+I_RR, 0103560+I_RR,
- 0103600+I_RR, 0103620+I_RR, 0103640+I_RR, 0103660+I_RR,
- 0103700+I_RR, 0103720+I_RR, 0103740+I_RR, 0103760+I_RR,
- 0103410+I_RR, 0103430+I_RR, 0103450+I_RR, 0103470+I_RR,
- 0103510+I_RR, 0103530+I_RR, 0103550+I_RR, 0103570+I_RR,
- 0103610+I_RR, 0103630+I_RR, 0103650+I_RR, 0103670+I_RR,
- 0103710+I_RR, 0103730+I_RR, 0103750+I_RR, 0103770+I_RR,
- 0060177+I_NPN, 0060277+I_NPN,
- 0060477+I_R, 0061477+I_R, 0062077+I_R, 0062677+I_NPN, 0063077+I_NPN,
- 0073301+I_NPN, 0073101+I_NPN,
- 0060000+I_D, 0060100+I_D, 0060200+I_D, 0060300+I_D,
- 0060400+I_RD, 0060500+I_RD, 0060600+I_RD, 0060700+I_RD,
- 0061000+I_RD, 0061100+I_RD, 0061200+I_RD, 0061300+I_RD,
- 0061400+I_RD, 0061500+I_RD, 0061600+I_RD, 0061700+I_RD,
- 0062000+I_RD, 0062100+I_RD, 0062200+I_RD, 0062300+I_RD,
- 0062400+I_RD, 0062500+I_RD, 0062600+I_RD, 0062700+I_RD,
- 0063000+I_RD, 0063100+I_RD, 0063200+I_RD, 0063300+I_RD,
- 0063400+I_D, 0063500+I_D, 0063600+I_D, 0063700+I_D,
- -1 };
-
- static const char *skip[] = {
- "SKP", "SZC", "SNC", "SZR", "SNR", "SEZ", "SBN",
- NULL };
-
- static const char *device[] = {
- "TTI", "TTO", "PTR", "PTP", "PLT", "CDR", "CLK", "LPT",
- "DSK", "MTA", "DCM", "ADCV", "DKP", "CAS", "CPU",
- NULL };
-
- static const int dev_val[] = {
- 010, 011, 012, 013, 014, 015, 016, 017,
- 020, 022, 024, 030, 033, 034, 077,
- -1 };
-
- /* Address decode
-
- Inputs:
- addr = current PC
- inst = instruction to decode
- cflag = true if decoding for CPU
- Outputs:
- return = error code
- */
-
- int memreff (unsigned int addr, int inst, int cflag)
- {
- int disp;
-
- if (inst & 02000) putchar ('@'); /* indirect? */
- disp = inst & 0377; /* displacement */
- switch ((inst >> 7) & 07) { /* mode'high addr */
- case 0: case 1: /* page zero */
- printf ("%-o", disp);
- break;
- case 2: /* PC rel, + */
- if (cflag) printf ("%-o", (addr + disp) & ADDRMASK);
- else printf (".+%-o", disp);
- break;
- case 3: /* PC rel, - */
- if (cflag) printf ("%-o", (addr + 0177400 + disp) & ADDRMASK);
- else printf (".-%-o", 0400 - disp);
- break;
- case 4: /* AC2 rel, + */
- printf ("%-o,2", disp);
- break;
- case 5: /* AC2 rel, - */
- printf ("-%-o,2", 0400 - disp);
- break;
- case 6: /* AC3 rel, + */
- printf ("%-o,3", disp);
- break;
- case 7: /* AC3 rel, - */
- printf ("-%-o,3", 0400 - disp);
- break; } /* end switch */
- return SCPE_OK;
- }
-
- /* Symbolic output
-
- Inputs:
- addr = current PC
- *val = pointer to values
- cflag = true if decoding for CPU
- sw = switches
- Outputs:
- status = error code
- */
-
- int print_sym (unsigned int addr, unsigned int *val, int cflag, int sw)
- {
- int i, j, c1, c2, inst, dv, src, dst, skp, dev;
-
- c1 = (val[0] >> 8) & 0177;
- c2 = val[0] & 0177;
- if (sw & SWMASK ('A')) { /* ASCII? */
- printf ((c2 < 040)? "<%03o>": "%c", c2);
- return SCPE_OK; }
- if (sw & SWMASK ('C')) { /* character? */
- printf ((c1 < 040)? "<%03o>": "%c", c1);
- printf ((c2 < 040)? "<%03o>": "%c", c2);
- return SCPE_OK; }
- if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */
-
- /* Instruction decode */
-
- inst = val[0];
- for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
- j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
- if ((opc_val[i] & 0177777) == (inst & masks[j])) { /* match? */
- src = (inst >> 13) & 03; /* opr fields */
- dst = (inst >> 11) & 03;
- skp = inst & 07;
- dev = inst & 077; /* IOT fields */
- for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ;
-
- switch (j) { /* switch on class */
- case I_V_NPN: /* no operands */
- printf ("%s", opcode[i]); /* opcode */
- break;
- case I_V_R: /* reg only */
- printf ("%s %-o", opcode[i], dst);
- break;
- case I_V_D: /* dev only */
- if (dev_val[dv] >= 0)
- printf ("%s %s", opcode[i], device[dv]);
- else printf ("%s %-o", opcode[i], dev);
- break;
- case I_V_RD: /* reg, dev */
- if (dev_val[dv] >= 0)
- printf ("%s %-o,%s", opcode[i], dst, device[dv]);
- else printf ("%s %-o,%-o", opcode[i], dst, dev);
- break;
- case I_V_M: /* addr only */
- printf ("%s ", opcode[i]);
- memreff (addr, inst, cflag);
- break;
- case I_V_RM: /* reg, addr */
- printf ("%s %-o,", opcode[i], dst);
- memreff (addr, inst, cflag);
- break;
- case I_V_RR: /* operate */
- printf ("%s %-o,%-o", opcode[i], src, dst);
- if (skp) printf (",%s", skip[skp-1]);
- break; } /* end case */
- return SCPE_OK; } /* end if */
- } /* end for */
- return SCPE_ARG;
- }
-
- /* Address parse
-
- Inputs:
- *cptr = pointer to input string
- addr = current PC
- cflag = true if parsing for CPU
- *val = pointer to output value
- Outputs:
- optr = pointer to next char in input string
- NULL if error
- */
-
- #define A_FL 001 /* CPU flag */
- #define A_NX 002 /* index seen */
- #define A_PER 004 /* period seen */
- #define A_NUM 010 /* number seen */
- #define A_SI 020 /* sign seen */
- #define A_MI 040 /* - seen */
-
- char *get_addr (char *cptr, unsigned int addr, int cflag, unsigned int *val)
- {
- int sr, pflag;
- unsigned int r, x;
- char gbuf[CBUFSIZE];
-
- *val = 0; /* clear result */
- r = 0; /* default no num */
- x = 1; /* default PC rel */
-
- pflag = cflag & A_FL; /* isolate flag */
- if (*cptr == '@') { /* indirect? */
- *val = 02000;
- cptr++; }
- if (*cptr == '.') { /* relative? */
- pflag = pflag | A_PER;
- cptr++; }
- if (*cptr == '+') { /* + sign? */
- pflag = pflag | A_SI;
- cptr++; }
- else if (*cptr == '-') { /* - sign? */
- pflag = pflag | A_MI | A_SI;
- cptr++; }
- if (*cptr != 0) { /* number? */
- cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
- if (get_unum (gbuf, 8, ADDRMASK, &r) != SCPE_OK) return NULL;
- pflag = pflag | A_NUM;
- sr = (pflag & A_MI)? (-r) & ADDRMASK: r; }
- if (*cptr != 0) { /* index? */
- cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
- if ((get_unum (gbuf, 8, 3, &x) != SCPE_OK) || (x < 2)) return NULL;
- pflag = pflag | A_NX; }
-
- /* Address parse, continued */
-
- switch (pflag & ~A_MI) { /* case on flags */
- case A_NUM: case A_NUM+A_SI: /* ~CPU, (+/-) num */
- if (sr <= 0377) *val = *val + sr;
- else return NULL;
- break;
- case A_NUM+A_FL: case A_NUM+A_SI+A_FL: /* CPU, (+/-) num */
- if (sr <= 0377) *val = *val + sr;
- else if (((sr >= ((addr - 0200) & ADDRMASK)) &&
- (sr <= ((addr + 0177) & ADDRMASK))) ||
- (sr >= (addr + 077600)))
- *val = *val + 0400 + ((sr - addr) & 0377);
- else return NULL;
- break;
- case A_PER: case A_PER+A_FL: /* .+/- num */
- case A_PER+A_SI+A_NUM: case A_PER+A_SI+A_NUM+A_FL:
- case A_NX+A_NUM: case A_NX+A_NUM+A_FL: /* (+/-) num, ndx */
- case A_NX+A_SI+A_NUM: case A_NX+A_SI+A_NUM+A_FL:
- if (((pflag & A_MI) == 0) && (r <= 0177)) *val = *val + (x << 8) + r;
- else if ((pflag & A_MI) && (r <= 0200))
- *val = *val + (x << 8) + 0400 - r;
- else return NULL;
- break;
- default:
- return NULL; } /* end case */
- return cptr;
- }
-
- /* Symbolic input
-
- Inputs:
- *cptr = pointer to input string
- addr = current PC
- cflag = true if parsing for CPU
- *val = pointer to output values
- Outputs:
- status = error status
- */
-
- int parse_sym (char *cptr, unsigned int addr, int cflag, unsigned int *val)
- {
- int i, j;
- unsigned int r;
- char gbuf[CBUFSIZE];
-
- while (isspace (*cptr)) cptr++; /* absorb spaces */
- if (cptr[0] == '\'') { /* single char? */
- if (cptr[1] == 0) return SCPE_ARG;
- val[0] = (unsigned int) cptr[1];
- return SCPE_OK; }
- if (cptr[0] == '"') { /* string? */
- if (cptr[1] == 0) return SCPE_ARG;
- val[0] = ((unsigned int) cptr[1] << 8) + (unsigned int) cptr[2];
- return SCPE_OK; }
-
- /* Instruction parse */
-
- cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
- for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
- if (opcode[i] == NULL) return SCPE_ARG;
- val[0] = opc_val[i] & 0177777; /* get value */
- j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
-
- switch (j) { /* case on class */
- case I_V_NPN: /* no operand */
- break;
- case I_V_R: /* IOT reg */
- cptr = get_glyph (cptr, gbuf, 0); /* get register */
- if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
- val[0] = val[0] | (r << 11); /* put in place */
- break;
- case I_V_RD: /* IOT reg,dev */
- cptr = get_glyph (cptr, gbuf, ','); /* get register */
- if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
- val[0] = val[0] | (r << 11); /* put in place */
- case I_V_D: /* IOT dev */
- cptr = get_glyph (cptr, gbuf, 0); /* get device */
- for (i = 0; (device[i] != NULL) && (strcmp (device[i], gbuf) != 0);
- i++);
- if (device[i] != NULL) val[0] = val[0] | dev_val[i];
- else { if (get_unum (gbuf, 8, 077, &r) != SCPE_OK) return SCPE_ARG;
- val[0] = val[0] | r; }
- break;
- case I_V_RM: /* mem reg,addr */
- cptr = get_glyph (cptr, gbuf, ','); /* get register */
- if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
- val[0] = val[0] | (r << 11); /* put in place */
- case I_V_M:
- if ((cptr = get_addr (cptr, addr, cflag, &r)) == NULL) return SCPE_ARG;
- val[0] = val[0] | r;
- break;
- case I_V_RR: /* operate */
- cptr = get_glyph (cptr, gbuf, ','); /* get register */
- if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
- val[0] = val[0] | (r << 13); /* put in place */
- cptr = get_glyph (cptr, gbuf, ','); /* get register */
- if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
- val[0] = val[0] | (r << 11); /* put in place */
- if (*cptr != 0) { /* skip? */
- cptr = get_glyph (cptr, gbuf, 0); /* get skip */
- for (i = 0; (skip[i] != NULL) &&
- (strcmp (skip[i], gbuf) != 0); i++) ;
- if (skip[i] == NULL) return SCPE_ARG;
- val[0] = val[0] | (i + 1); } /* end for */
- break; } /* end case */
- if (*cptr != 0) return SCPE_ARG; /* any leftovers? */
- return SCPE_OK;
- }
-