home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Boot_Images / 2.11_on_rl02 / pdpsim.tz / pdpsim / nova_sys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-29  |  19.5 KB  |  623 lines

  1. /* nova_sys.c: NOVA simulator interface
  2.  
  3.    Copyright (c) 1993, 1994, 1995, 1996,
  4.    Robert M Supnik, Digital Equipment Corporation
  5.    Commercial use prohibited
  6. */
  7.  
  8. #include "nova_defs.h"
  9. #include <ctype.h>
  10.  
  11. extern DEVICE cpu_dev;
  12. extern UNIT cpu_unit;
  13. extern DEVICE ptr_dev, ptp_dev;
  14. extern DEVICE tti_dev, tto_dev;
  15. extern DEVICE clk_dev, lpt_dev;
  16. extern DEVICE dkp_dev, dsk_dev;
  17. extern DEVICE mta_dev;
  18. extern REG cpu_reg[];
  19. extern unsigned short M[];
  20. extern int saved_PC;
  21. extern char *get_glyph (char *cptr, char *gbuf, char term);
  22. extern int get_unum (char *cptr, int radix, unsigned int max,
  23.     unsigned int *val);
  24.  
  25. /* SCP data structures
  26.  
  27.    sim_name        simulator name string
  28.    sim_PC        pointer to saved PC register descriptor
  29.    sim_emax        number of words needed for examine
  30.    sim_devices        array of pointers to simulated devices
  31.    sim_stop_messages    array of pointers to stop messages
  32.    sim_load        binary loader
  33. */
  34.  
  35. char sim_name[] = "NOVA";
  36.  
  37. REG *sim_PC = &cpu_reg[0];
  38.  
  39. int sim_emax = 4;
  40.  
  41. DEVICE *sim_devices[] = { &cpu_dev,
  42.     &ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
  43.     &clk_dev, &lpt_dev, &dsk_dev, &dkp_dev,
  44.     &mta_dev, NULL };
  45.  
  46. const char *sim_stop_messages[] = {
  47.     "Unknown error",
  48.     "Unknown I/O instruction",
  49.     "HALT instruction",
  50.     "Breakpoint",
  51.     "Infinite instruction indirect",
  52.     "Infinite interrupt indirect"  };
  53.  
  54. /* Binary loader
  55.  
  56.    Loader format consists of blocks, optionally preceded, separated, and
  57.    followed by zeroes.  Each block consists of:
  58.  
  59.     lo_count
  60.     hi_count
  61.     lo_origin
  62.     hi_origin
  63.     lo_checksum
  64.     hi_checksum
  65.     lo_data byte    ---
  66.     hi_data byte     |
  67.     :         > -count words
  68.     lo_data byte     |
  69.     hi_data byte    ---
  70.  
  71.    If the word count is [0,-20], then the block is normal data.
  72.    If the word count is [-21,-n], then the block is repeated data.
  73.    If the word count is 1, the block is the start address.
  74.    If the word count is >1, the block is an error block.
  75. */
  76.  
  77. int sim_load (FILE *fileref)
  78. {
  79. int data, origin, csum, count, state, i;
  80.  
  81. state = 0;
  82. while ((i = getc (fileref)) != EOF) {
  83.     switch (state) {
  84.     case 0:                        /* leader */
  85.         count = i;
  86.         state = (count != 0);
  87.         break;
  88.     case 1:                        /* high count */
  89.         csum = count = (i << 8) | count;
  90.         state = 2;
  91.         break;
  92.     case 2:                        /* low origin */
  93.         origin = i;
  94.         state = 3;
  95.         break;
  96.     case 3:                        /* high origin */
  97.         origin = (i << 8) | origin;
  98.         csum = csum + origin;
  99.         state = 4;
  100.         break;
  101.     case 4:                        /* low checksum */
  102.         csum = csum + i;
  103.         state = 5;
  104.         break;
  105.     case 5:                        /* high checksum */
  106.         csum = csum + (i << 8);
  107.         if (count == 1) saved_PC = origin;    /* count = 1? */
  108.         if (count <= 1) {            /* count = 0/1? */
  109.             if (csum & 0177777) return SCPE_CSUM;
  110.             state = 0;
  111.             break;  }
  112.         if (count < 0100000) {            /* count > 1 */
  113.             state = 8;
  114.             break;  }
  115.         count = 0200000 - count;
  116.         state = 6;
  117.         break;
  118.     case 6:                        /* low data  */
  119.         data = i;
  120.         state = 7;
  121.         break;
  122.     case 7:                        /* high data */
  123.         data = (i << 8) | data;
  124.         csum = csum + data;
  125.         if (count > 20) {            /* large block */
  126.             for (count = count - 1; count == 1; count--) {
  127.                 if (origin >= MEMSIZE) return SCPE_NXM;
  128.                 M[origin] = data;
  129.                 origin = origin + 1;  }  }
  130.         if (origin >= MEMSIZE) return SCPE_NXM;
  131.         M[origin] = data;
  132.         origin = origin + 1;
  133.         count = count - 1;
  134.         if (count == 0) {
  135.             if (csum & 0177777) return SCPE_CSUM;
  136.             state = 0;
  137.             break;  }
  138.         state = 6;
  139.         break;
  140.     case 8:                        /* error block */
  141.         if (i == 0377) state = 0;
  142.         break;  }                /* end switch */
  143.     }                        /* end while */
  144.  
  145. /* Ok to find end of tape between blocks or in error state */
  146.  
  147. return ((state == 0) || (state == 8))? SCPE_OK: SCPE_FMT;
  148. }
  149.  
  150. /* Symbol tables */
  151.  
  152. #define I_V_FL        18                /* flag bits */
  153. #define I_M_FL        07                /* flag width */
  154. #define I_V_NPN        0                /* no operands */
  155. #define I_V_R        1                /* reg */
  156. #define I_V_D        2                /* device */
  157. #define I_V_RD        3                /* reg,device */
  158. #define I_V_M        4                /* mem addr */
  159. #define I_V_RM        5                /* reg, mem addr */
  160. #define I_V_RR        6                /* operate */
  161. #define I_NPN        (I_V_NPN << I_V_FL)
  162. #define I_R        (I_V_R << I_V_FL)
  163. #define I_D        (I_V_D << I_V_FL)
  164. #define I_RD        (I_V_RD << I_V_FL)
  165. #define I_M        (I_V_M << I_V_FL)
  166. #define I_RM        (I_V_RM << I_V_FL)
  167. #define I_RR        (I_V_RR << I_V_FL)
  168.  
  169. static const int masks[] = {
  170. 0177777, 0163777, 0177700, 0163700,
  171. 0174000, 0160000, 0103770  };
  172.  
  173. static const char *opcode[] = {
  174.  "JMP", "JSR", "ISZ", "DSZ",
  175.  "LDA", "STA",
  176.  "COM", "COMZ", "COMO", "COMC",
  177.  "COML", "COMZL", "COMOL", "COMCL",
  178.  "COMR", "COMZR", "COMOR", "COMCR",
  179.  "COMS", "COMZS", "COMOS", "COMCS",
  180.  "COM#", "COMZ#", "COMO#", "COMC#",
  181.  "COML#", "COMZL#", "COMOL#", "COMCL#",
  182.  "COMR#", "COMZR#", "COMOR#", "COMCR#",
  183.  "COMS#", "COMZS#", "COMOS#", "COMCS#",
  184.  "NEG", "NEGZ", "NEGO", "NEGC",
  185.  "NEGL", "NEGZL", "NEGOL", "NEGCL",
  186.  "NEGR", "NEGZR", "NEGOR", "NEGCR",
  187.  "NEGS", "NEGZS", "NEGOS", "NEGCS",
  188.  "NEG#", "NEGZ#", "NEGO#", "NEGC#",
  189.  "NEGL#", "NEGZL#", "NEGOL#", "NEGCL#",
  190.  "NEGR#", "NEGZR#", "NEGOR#", "NEGCR#",
  191.  "NEGS#", "NEGZS#", "NEGOS#", "NEGCS#",
  192.  "MOV", "MOVZ", "MOVO", "MOVC",
  193.  "MOVL", "MOVZL", "MOVOL", "MOVCL",
  194.  "MOVR", "MOVZR", "MOVOR", "MOVCR",
  195.  "MOVS", "MOVZS", "MOVOS", "MOVCS",
  196.  "MOV#", "MOVZ#", "MOVO#", "MOVC#",
  197.  "MOVL#", "MOVZL#", "MOVOL#", "MOVCL#",
  198.  "MOVR#", "MOVZR#", "MOVOR#", "MOVCR#",
  199.  "MOVS#", "MOVZS#", "MOVOS#", "MOVCS#",
  200.  "INC", "INCZ", "INCO", "INCC",
  201.  "INCL", "INCZL", "INCOL", "INCCL",
  202.  "INCR", "INCZR", "INCOR", "INCCR",
  203.  "INCS", "INCZS", "INCOS", "INCCS",
  204.  "INC#", "INCZ#", "INCO#", "INCC#",
  205.  "INCL#", "INCZL#", "INCOL#", "INCCL#",
  206.  "INCR#", "INCZR#", "INCOR#", "INCCR#",
  207.  "INCS#", "INCZS#", "INCOS#", "INCCS#",
  208.  "ADC", "ADCZ", "ADCO", "ADCC",
  209.  "ADCL", "ADCZL", "ADCOL", "ADCCL",
  210.  "ADCR", "ADCZR", "ADCOR", "ADCCR",
  211.  "ADCS", "ADCZS", "ADCOS", "ADCCS",
  212.  "ADC#", "ADCZ#", "ADCO#", "ADCC#",
  213.  "ADCL#", "ADCZL#", "ADCOL#", "ADCCL#",
  214.  "ADCR#", "ADCZR#", "ADCOR#", "ADCCR#",
  215.  "ADCS#", "ADCZS#", "ADCOS#", "ADCCS#",
  216.  "SUB", "SUBZ", "SUBO", "SUBC",
  217.  "SUBL", "SUBZL", "SUBOL", "SUBCL",
  218.  "SUBR", "SUBZR", "SUBOR", "SUBCR",
  219.  "SUBS", "SUBZS", "SUBOS", "SUBCS",
  220.  "SUB#", "SUBZ#", "SUBO#", "SUBC#",
  221.  "SUBL#", "SUBZL#", "SUBOL#", "SUBCL#",
  222.  "SUBR#", "SUBZR#", "SUBOR#", "SUBCR#",
  223.  "SUBS#", "SUBZS#", "SUBOS#", "SUBCS#",
  224.  "ADD", "ADDZ", "ADDO", "ADDC",
  225.  "ADDL", "ADDZL", "ADDOL", "ADDCL",
  226.  "ADDR", "ADDZR", "ADDOR", "ADDCR",
  227.  "ADDS", "ADDZS", "ADDOS", "ADDCS",
  228.  "ADD#", "ADDZ#", "ADDO#", "ADDC#",
  229.  "ADDL#", "ADDZL#", "ADDOL#", "ADDCL#",
  230.  "ADDR#", "ADDZR#", "ADDOR#", "ADDCR#",
  231.  "ADDS#", "ADDZS#", "ADDOS#", "ADDCS#",
  232.  "AND", "ANDZ", "ANDO", "ANDC",
  233.  "ANDL", "ANDZL", "ANDOL", "ANDCL",
  234.  "ANDR", "ANDZR", "ANDOR", "ANDCR",
  235.  "ANDS", "ANDZS", "ANDOS", "ANDCS",
  236.  "AND#", "ANDZ#", "ANDO#", "ANDC#",
  237.  "ANDL#", "ANDZL#", "ANDOL#", "ANDCL#",
  238.  "ANDR#", "ANDZR#", "ANDOR#", "ANDCR#",
  239.  "ANDS#", "ANDZS#", "ANDOS#", "ANDCS#",
  240.  "ION", "IOF",
  241.  "RDSW", "INTA", "MSKO", "IORST", "HALT",
  242.  "MUL", "DIV",
  243.  "NIO", "NIOS", "NIOC", "NIOP",
  244.  "DIA", "DIAS", "DIAC", "DIAP",
  245.  "DOA", "DOAS", "DOAC", "DOAP",
  246.  "DIB", "DIBS", "DIBC", "DIBP",
  247.  "DOB", "DOBS", "DOBC", "DOBP",
  248.  "DIC", "DICS", "DICC", "DICP",
  249.  "DOC", "DOCS", "DOCC", "DOCP",
  250.  "SKPBN", "SKPBZ", "SKPDN", "SKPDZ",
  251.  NULL };
  252.  
  253. static const opc_val[] = {
  254.  0000000+I_M, 0004000+I_M, 0010000+I_M, 0014000+I_M,
  255.  0020000+I_RM, 0040000+I_RM,
  256.  0100000+I_RR, 0100020+I_RR, 0100040+I_RR, 0100060+I_RR,
  257.  0100100+I_RR, 0100120+I_RR, 0100140+I_RR, 0100160+I_RR,
  258.  0100200+I_RR, 0100220+I_RR, 0100240+I_RR, 0100260+I_RR,
  259.  0100300+I_RR, 0100320+I_RR, 0100340+I_RR, 0100360+I_RR,
  260.  0100010+I_RR, 0100030+I_RR, 0100050+I_RR, 0100070+I_RR,
  261.  0100110+I_RR, 0100130+I_RR, 0100150+I_RR, 0100170+I_RR,
  262.  0100210+I_RR, 0100230+I_RR, 0100250+I_RR, 0100270+I_RR,
  263.  0100310+I_RR, 0100330+I_RR, 0100350+I_RR, 0100370+I_RR,
  264.  0100400+I_RR, 0100420+I_RR, 0100440+I_RR, 0100460+I_RR,
  265.  0100500+I_RR, 0100520+I_RR, 0100540+I_RR, 0100560+I_RR,
  266.  0100600+I_RR, 0100620+I_RR, 0100640+I_RR, 0100660+I_RR,
  267.  0100700+I_RR, 0100720+I_RR, 0100740+I_RR, 0100760+I_RR,
  268.  0100410+I_RR, 0100430+I_RR, 0100450+I_RR, 0100470+I_RR,
  269.  0100510+I_RR, 0100530+I_RR, 0100550+I_RR, 0100570+I_RR,
  270.  0100610+I_RR, 0100630+I_RR, 0100650+I_RR, 0100670+I_RR,
  271.  0100710+I_RR, 0100730+I_RR, 0100750+I_RR, 0100770+I_RR,
  272.  0101000+I_RR, 0101020+I_RR, 0101040+I_RR, 0101060+I_RR,
  273.  0101100+I_RR, 0101120+I_RR, 0101140+I_RR, 0101160+I_RR,
  274.  0101200+I_RR, 0101220+I_RR, 0101240+I_RR, 0101260+I_RR,
  275.  0101300+I_RR, 0101320+I_RR, 0101340+I_RR, 0101360+I_RR,
  276.  0101010+I_RR, 0101030+I_RR, 0101050+I_RR, 0101070+I_RR,
  277.  0101110+I_RR, 0101130+I_RR, 0101150+I_RR, 0101170+I_RR,
  278.  0101210+I_RR, 0101230+I_RR, 0101250+I_RR, 0101270+I_RR,
  279.  0101310+I_RR, 0101330+I_RR, 0101350+I_RR, 0101370+I_RR,
  280.  0101400+I_RR, 0101420+I_RR, 0101440+I_RR, 0101460+I_RR,
  281.  0101500+I_RR, 0101520+I_RR, 0101540+I_RR, 0101560+I_RR,
  282.  0101600+I_RR, 0101620+I_RR, 0101640+I_RR, 0101660+I_RR,
  283.  0101700+I_RR, 0101720+I_RR, 0101740+I_RR, 0101760+I_RR,
  284.  0101410+I_RR, 0101430+I_RR, 0101450+I_RR, 0101470+I_RR,
  285.  0101510+I_RR, 0101530+I_RR, 0101550+I_RR, 0101570+I_RR,
  286.  0101610+I_RR, 0101630+I_RR, 0101650+I_RR, 0101670+I_RR,
  287.  0101710+I_RR, 0101730+I_RR, 0101750+I_RR, 0101770+I_RR,
  288.  0102000+I_RR, 0102020+I_RR, 0102040+I_RR, 0102060+I_RR,
  289.  0102100+I_RR, 0102120+I_RR, 0102140+I_RR, 0102160+I_RR,
  290.  0102200+I_RR, 0102220+I_RR, 0102240+I_RR, 0102260+I_RR,
  291.  0102300+I_RR, 0102320+I_RR, 0102340+I_RR, 0102360+I_RR,
  292.  0102010+I_RR, 0102030+I_RR, 0102050+I_RR, 0102070+I_RR,
  293.  0102110+I_RR, 0102130+I_RR, 0102150+I_RR, 0102170+I_RR,
  294.  0102210+I_RR, 0102230+I_RR, 0102250+I_RR, 0102270+I_RR,
  295.  0102310+I_RR, 0102330+I_RR, 0102350+I_RR, 0102370+I_RR,
  296.  0102400+I_RR, 0102420+I_RR, 0102440+I_RR, 0102460+I_RR,
  297.  0102500+I_RR, 0102520+I_RR, 0102540+I_RR, 0102560+I_RR,
  298.  0102600+I_RR, 0102620+I_RR, 0102640+I_RR, 0102660+I_RR,
  299.  0102700+I_RR, 0102720+I_RR, 0102740+I_RR, 0102760+I_RR,
  300.  0102410+I_RR, 0102430+I_RR, 0102450+I_RR, 0102470+I_RR,
  301.  0102510+I_RR, 0102530+I_RR, 0102550+I_RR, 0102570+I_RR,
  302.  0102610+I_RR, 0102630+I_RR, 0102650+I_RR, 0102670+I_RR,
  303.  0102710+I_RR, 0102730+I_RR, 0102750+I_RR, 0102770+I_RR,
  304.  0103000+I_RR, 0103020+I_RR, 0103040+I_RR, 0103060+I_RR,
  305.  0103100+I_RR, 0103120+I_RR, 0103140+I_RR, 0103160+I_RR,
  306.  0103200+I_RR, 0103220+I_RR, 0103240+I_RR, 0103260+I_RR,
  307.  0103300+I_RR, 0103320+I_RR, 0103340+I_RR, 0103360+I_RR,
  308.  0103010+I_RR, 0103030+I_RR, 0103050+I_RR, 0103070+I_RR,
  309.  0103110+I_RR, 0103130+I_RR, 0103150+I_RR, 0103170+I_RR,
  310.  0103210+I_RR, 0103230+I_RR, 0103250+I_RR, 0103270+I_RR,
  311.  0103310+I_RR, 0103330+I_RR, 0103350+I_RR, 0103370+I_RR,
  312.  0103400+I_RR, 0103420+I_RR, 0103440+I_RR, 0103460+I_RR,
  313.  0103500+I_RR, 0103520+I_RR, 0103540+I_RR, 0103560+I_RR,
  314.  0103600+I_RR, 0103620+I_RR, 0103640+I_RR, 0103660+I_RR,
  315.  0103700+I_RR, 0103720+I_RR, 0103740+I_RR, 0103760+I_RR,
  316.  0103410+I_RR, 0103430+I_RR, 0103450+I_RR, 0103470+I_RR,
  317.  0103510+I_RR, 0103530+I_RR, 0103550+I_RR, 0103570+I_RR,
  318.  0103610+I_RR, 0103630+I_RR, 0103650+I_RR, 0103670+I_RR,
  319.  0103710+I_RR, 0103730+I_RR, 0103750+I_RR, 0103770+I_RR,
  320.  0060177+I_NPN, 0060277+I_NPN,
  321.  0060477+I_R, 0061477+I_R, 0062077+I_R, 0062677+I_NPN, 0063077+I_NPN,
  322.  0073301+I_NPN, 0073101+I_NPN,
  323.  0060000+I_D, 0060100+I_D, 0060200+I_D, 0060300+I_D,
  324.  0060400+I_RD, 0060500+I_RD, 0060600+I_RD, 0060700+I_RD,
  325.  0061000+I_RD, 0061100+I_RD, 0061200+I_RD, 0061300+I_RD,
  326.  0061400+I_RD, 0061500+I_RD, 0061600+I_RD, 0061700+I_RD,
  327.  0062000+I_RD, 0062100+I_RD, 0062200+I_RD, 0062300+I_RD,
  328.  0062400+I_RD, 0062500+I_RD, 0062600+I_RD, 0062700+I_RD,
  329.  0063000+I_RD, 0063100+I_RD, 0063200+I_RD, 0063300+I_RD,
  330.  0063400+I_D, 0063500+I_D, 0063600+I_D, 0063700+I_D,
  331.  -1 };
  332.  
  333. static const char *skip[] = {
  334.  "SKP", "SZC", "SNC", "SZR", "SNR", "SEZ", "SBN",
  335.  NULL };
  336.  
  337. static const char *device[] = {
  338.  "TTI", "TTO", "PTR", "PTP", "PLT", "CDR", "CLK", "LPT",
  339.  "DSK", "MTA", "DCM", "ADCV", "DKP", "CAS", "CPU",
  340.  NULL };
  341.  
  342. static const int dev_val[] = {
  343.  010, 011, 012, 013, 014, 015, 016, 017,
  344.  020, 022, 024, 030, 033, 034, 077,
  345.  -1 };
  346.  
  347. /* Address decode
  348.  
  349.    Inputs:
  350.     addr    =    current PC
  351.     inst    =    instruction to decode
  352.     cflag    =    true if decoding for CPU
  353.    Outputs:
  354.     return    =    error code
  355. */
  356.  
  357. int memreff (unsigned int addr, int inst, int cflag)
  358. {
  359. int disp;
  360.  
  361. if (inst & 02000) putchar ('@');            /* indirect? */
  362. disp = inst & 0377;                    /* displacement */
  363. switch ((inst >> 7) & 07) {                /* mode'high addr */
  364. case 0: case 1:                        /* page zero */
  365.     printf ("%-o", disp);
  366.     break;
  367. case 2:                            /* PC rel, + */
  368.     if (cflag) printf ("%-o", (addr + disp) & ADDRMASK);
  369.     else printf (".+%-o", disp);
  370.     break;
  371. case 3:                            /* PC rel, - */
  372.     if (cflag) printf ("%-o", (addr + 0177400 + disp) & ADDRMASK);
  373.     else printf (".-%-o", 0400 - disp);
  374.     break;
  375. case 4:                            /* AC2 rel, + */
  376.     printf ("%-o,2", disp);
  377.     break;
  378. case 5:                            /* AC2 rel, - */
  379.     printf ("-%-o,2", 0400 - disp);
  380.     break;
  381. case 6:                            /* AC3 rel, + */
  382.     printf ("%-o,3", disp);
  383.     break;
  384. case 7:                            /* AC3 rel, - */
  385.     printf ("-%-o,3", 0400 - disp);
  386.     break;  }                    /* end switch */
  387. return SCPE_OK;
  388. }
  389.  
  390. /* Symbolic output
  391.  
  392.    Inputs:
  393.     addr    =    current PC
  394.     *val    =    pointer to values
  395.     cflag    =    true if decoding for CPU
  396.     sw    =    switches
  397.    Outputs:
  398.     status    =    error code
  399. */
  400.  
  401. int print_sym (unsigned int addr, unsigned int *val, int cflag, int sw)
  402. {
  403. int i, j, c1, c2, inst, dv, src, dst, skp, dev;
  404.  
  405. c1 = (val[0] >> 8) & 0177;
  406. c2 = val[0] & 0177;
  407. if (sw & SWMASK ('A')) {                /* ASCII? */
  408.     printf ((c2 < 040)? "<%03o>": "%c", c2);
  409.     return SCPE_OK;  }
  410. if (sw & SWMASK ('C')) {                /* character? */
  411.     printf ((c1 < 040)? "<%03o>": "%c", c1);
  412.     printf ((c2 < 040)? "<%03o>": "%c", c2);
  413.     return SCPE_OK;  }
  414. if (!(sw & SWMASK ('M'))) return SCPE_ARG;        /* mnemonic? */
  415.  
  416. /* Instruction decode */
  417.  
  418. inst = val[0];
  419. for (i = 0; opc_val[i] >= 0; i++) {            /* loop thru ops */
  420.     j = (opc_val[i] >> I_V_FL) & I_M_FL;        /* get class */
  421.     if ((opc_val[i] & 0177777) == (inst & masks[j])) {    /* match? */
  422.     src = (inst >> 13) & 03;            /* opr fields */
  423.     dst = (inst >> 11) & 03;
  424.     skp = inst & 07;
  425.     dev = inst & 077;                /* IOT fields */
  426.     for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ;
  427.  
  428.     switch (j) {                    /* switch on class */
  429.     case I_V_NPN:                    /* no operands */
  430.         printf ("%s", opcode[i]);        /* opcode */
  431.         break;
  432.     case I_V_R:                    /* reg only */
  433.         printf ("%s %-o", opcode[i], dst);
  434.         break;
  435.     case I_V_D:                    /* dev only */
  436.         if (dev_val[dv] >= 0)
  437.             printf ("%s %s", opcode[i], device[dv]);
  438.         else printf ("%s %-o", opcode[i], dev);
  439.         break;
  440.     case I_V_RD:                    /* reg, dev */
  441.         if (dev_val[dv] >= 0)
  442.             printf ("%s %-o,%s", opcode[i], dst, device[dv]);
  443.         else printf ("%s %-o,%-o", opcode[i], dst, dev);
  444.         break;
  445.     case I_V_M:                    /* addr only */
  446.         printf ("%s ", opcode[i]);
  447.         memreff (addr, inst, cflag);
  448.         break;
  449.     case I_V_RM:                    /* reg, addr */
  450.         printf ("%s %-o,", opcode[i], dst);
  451.         memreff (addr, inst, cflag);
  452.         break;
  453.     case I_V_RR:                    /* operate */
  454.         printf ("%s %-o,%-o", opcode[i], src, dst);
  455.         if (skp) printf (",%s", skip[skp-1]);
  456.         break;  }                /* end case */
  457.     return SCPE_OK;  }                /* end if */
  458.     }                        /* end for */
  459. return SCPE_ARG;
  460. }
  461.  
  462. /* Address parse
  463.  
  464.    Inputs:
  465.     *cptr    =    pointer to input string
  466.     addr    =    current PC
  467.     cflag    =    true if parsing for CPU
  468.     *val    =    pointer to output value
  469.    Outputs:
  470.     optr    =    pointer to next char in input string
  471.             NULL if error
  472. */
  473.  
  474. #define A_FL    001                    /* CPU flag */
  475. #define A_NX    002                    /* index seen */
  476. #define A_PER    004                    /* period seen */
  477. #define A_NUM    010                    /* number seen */
  478. #define A_SI    020                    /* sign seen */
  479. #define A_MI    040                    /* - seen */
  480.  
  481. char *get_addr (char *cptr, unsigned int addr, int cflag, unsigned int *val)
  482. {
  483. int sr, pflag;
  484. unsigned int r, x;
  485. char gbuf[CBUFSIZE];
  486.  
  487. *val = 0;                        /* clear result */
  488. r = 0;                            /* default no num */
  489. x = 1;                            /* default PC rel */
  490.  
  491. pflag = cflag & A_FL;                    /* isolate flag */
  492. if (*cptr == '@') {                    /* indirect? */
  493.     *val = 02000;
  494.     cptr++;  }        
  495. if (*cptr == '.') {                    /* relative? */
  496.     pflag = pflag | A_PER;
  497.     cptr++;  }
  498. if (*cptr == '+') {                    /* + sign? */
  499.     pflag = pflag | A_SI;
  500.     cptr++;  }
  501. else if (*cptr == '-') {                /* - sign? */
  502.     pflag = pflag | A_MI | A_SI;
  503.     cptr++;  }    
  504. if (*cptr != 0) {                    /* number? */
  505.     cptr = get_glyph (cptr, gbuf, ',');        /* get glyph */
  506.     if (get_unum (gbuf, 8, ADDRMASK, &r) != SCPE_OK) return NULL;
  507.     pflag = pflag | A_NUM;
  508.     sr = (pflag & A_MI)? (-r) & ADDRMASK: r;  }
  509. if (*cptr != 0) {                    /* index? */
  510.     cptr = get_glyph (cptr, gbuf, 0);        /* get glyph */
  511.     if ((get_unum (gbuf, 8, 3, &x) != SCPE_OK) || (x < 2)) return NULL;
  512.     pflag = pflag | A_NX;  }
  513.  
  514. /* Address parse, continued */
  515.  
  516. switch (pflag & ~A_MI) {                /* case on flags */
  517. case A_NUM: case A_NUM+A_SI:                /* ~CPU, (+/-) num */
  518.     if (sr <= 0377) *val = *val + sr;
  519.     else return NULL;
  520.     break;
  521. case A_NUM+A_FL: case A_NUM+A_SI+A_FL:            /* CPU, (+/-) num */
  522.     if (sr <= 0377) *val = *val + sr;
  523.     else if (((sr >= ((addr - 0200) & ADDRMASK)) &&
  524.           (sr <= ((addr + 0177) & ADDRMASK))) ||
  525.          (sr >= (addr + 077600)))
  526.         *val = *val + 0400 + ((sr - addr) & 0377);
  527.     else return NULL;
  528.     break;
  529. case A_PER: case A_PER+A_FL:                /* .+/- num */
  530. case A_PER+A_SI+A_NUM: case A_PER+A_SI+A_NUM+A_FL:
  531. case A_NX+A_NUM: case A_NX+A_NUM+A_FL:            /* (+/-) num, ndx */
  532. case A_NX+A_SI+A_NUM: case A_NX+A_SI+A_NUM+A_FL:
  533.     if (((pflag & A_MI) == 0) && (r <= 0177)) *val = *val + (x << 8) + r;
  534.     else if ((pflag & A_MI) && (r <= 0200))
  535.         *val = *val + (x << 8) + 0400 - r;
  536.     else return NULL;
  537.     break;
  538. default:
  539.     return NULL;  }                    /* end case */
  540. return cptr;
  541. }
  542.  
  543. /* Symbolic input
  544.  
  545.    Inputs:
  546.     *cptr    =    pointer to input string
  547.     addr    =    current PC
  548.     cflag    =    true if parsing for CPU
  549.     *val    =    pointer to output values
  550.    Outputs:
  551.     status    =    error status
  552. */
  553.  
  554. int parse_sym (char *cptr, unsigned int addr, int cflag, unsigned int *val)
  555. {
  556. int i, j;
  557. unsigned int r;
  558. char gbuf[CBUFSIZE];
  559.  
  560. while (isspace (*cptr)) cptr++;                /* absorb spaces */
  561. if (cptr[0] == '\'') {                    /* single char? */
  562.     if (cptr[1] == 0) return SCPE_ARG;
  563.     val[0] = (unsigned int) cptr[1];
  564.     return SCPE_OK;  }
  565. if (cptr[0] == '"') {                    /* string? */
  566.     if (cptr[1] == 0) return SCPE_ARG;
  567.     val[0] = ((unsigned int) cptr[1] << 8) + (unsigned int) cptr[2];
  568.     return SCPE_OK;  }
  569.  
  570. /* Instruction parse */
  571.  
  572. cptr = get_glyph (cptr, gbuf, 0);            /* get opcode */
  573. for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
  574. if (opcode[i] == NULL) return SCPE_ARG;
  575. val[0] = opc_val[i] & 0177777;                /* get value */
  576. j = (opc_val[i] >> I_V_FL) & I_M_FL;            /* get class */
  577.  
  578. switch (j) {                        /* case on class */
  579. case I_V_NPN:                        /* no operand */
  580.     break;
  581. case I_V_R:                        /* IOT reg */
  582.     cptr = get_glyph (cptr, gbuf, 0);        /* get register */
  583.     if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
  584.     val[0] = val[0] | (r << 11);            /* put in place */
  585.     break;
  586. case I_V_RD:                        /* IOT reg,dev */
  587.     cptr = get_glyph (cptr, gbuf, ',');        /* get register */
  588.     if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
  589.     val[0] = val[0] | (r << 11);            /* put in place */
  590. case I_V_D:                        /* IOT dev */
  591.     cptr = get_glyph (cptr, gbuf, 0);        /* get device */
  592.     for (i = 0; (device[i] != NULL) && (strcmp (device[i], gbuf) != 0);
  593.         i++);
  594.     if (device[i] != NULL) val[0] = val[0] | dev_val[i];
  595.     else {    if (get_unum (gbuf, 8, 077, &r) != SCPE_OK) return SCPE_ARG;
  596.         val[0] = val[0] | r;  }
  597.     break;
  598. case I_V_RM:                        /* mem reg,addr */
  599.     cptr = get_glyph (cptr, gbuf, ',');        /* get register */
  600.     if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
  601.     val[0] = val[0] | (r << 11);            /* put in place */
  602. case I_V_M:
  603.     if ((cptr = get_addr (cptr, addr, cflag, &r)) == NULL) return SCPE_ARG;
  604.     val[0] = val[0] | r;
  605.     break;
  606. case I_V_RR:                        /* operate */
  607.     cptr = get_glyph (cptr, gbuf, ',');        /* get register */
  608.     if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
  609.     val[0] = val[0] | (r << 13);            /* put in place */
  610.     cptr = get_glyph (cptr, gbuf, ',');        /* get register */
  611.     if (get_unum (gbuf, 8, 3, &r) != SCPE_OK) return SCPE_ARG;
  612.     val[0] = val[0] | (r << 11);            /* put in place */
  613.     if (*cptr != 0) {                /* skip? */
  614.         cptr = get_glyph (cptr, gbuf, 0);    /* get skip */
  615.         for (i = 0; (skip[i] != NULL) &&
  616.             (strcmp (skip[i], gbuf) != 0); i++) ;
  617.         if (skip[i] == NULL) return SCPE_ARG;
  618.         val[0] = val[0] | (i + 1);  }        /* end for */
  619.     break;  }                    /* end case */
  620. if (*cptr != 0) return SCPE_ARG;            /* any leftovers? */
  621. return SCPE_OK;
  622. }
  623.