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

  1. /* pdp11_sys.c: PDP-11 simulator interface
  2.  
  3.    Copyright (c) 1993, 1994, 1995, 1996, Robert M Supnik,
  4.    Digital Equipment Corporation
  5.    Commercial use prohibited
  6. */
  7.  
  8. #include "pdp11_defs.h"
  9. #include <ctype.h>
  10.  
  11. extern DEVICE cpu_dev;
  12. extern DEVICE ptr_dev, ptp_dev;
  13. extern DEVICE tti_dev, tto_dev;
  14. extern DEVICE lpt_dev, clk_dev;
  15. extern DEVICE rk_dev, rx_dev;
  16. extern DEVICE rl_dev;
  17. extern REG cpu_reg[];
  18. extern unsigned short M[];
  19. extern int saved_PC;
  20. extern char *get_glyph (char *cptr, char *gbuf, char term);
  21. extern int get_unum (char *cptr, int radix, unsigned int max,
  22.     unsigned int *val);
  23.  
  24. /* SCP data structures and interface routines
  25.  
  26.    sim_name        simulator name string
  27.    sim_PC        pointer to saved PC register descriptor
  28.    sim_emax        number of words for examine
  29.    sim_devices        array of pointers to simulated devices
  30.    sim_stop_messages    array of pointers to stop messages
  31.    sim_load        binary loader
  32. */
  33.  
  34. char sim_name[] = "PDP-11";
  35.  
  36. REG *sim_PC = &cpu_reg[0];
  37.  
  38. int sim_emax = 4;
  39.  
  40. DEVICE *sim_devices[] = { &cpu_dev,
  41.     &ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
  42.     &lpt_dev, &clk_dev, &rk_dev,
  43.     &rl_dev, &rx_dev, NULL };
  44.  
  45. const char *sim_stop_messages[] = {
  46.     "Unknown error",
  47.     "Red stack trap",
  48.     "Odd address trap",
  49.     "Memory management trap",
  50.     "Non-existent memory trap",
  51.     "Parity error trap",
  52.     "Privilege trap",
  53.     "Illegal instruction trap",
  54.     "BPT trap",
  55.     "IOT trap",
  56.     "EMT trap",
  57.     "TRAP trap",
  58.     "Trace trap",
  59.     "Yellow stack trap",
  60.     "Powerfail trap",
  61.     "Floating point exception",
  62.     "HALT instruction",
  63.     "Breakpoint",
  64.     "Wait state",
  65.     "Trap vector fetch abort",
  66.     "Trap stack push abort"  };
  67.  
  68. /* Binary loader.
  69.  
  70.    Loader format consists of blocks, optionally preceded, separated, and
  71.    followed by zeroes.  Each block consists of:
  72.  
  73.     001        ---
  74.     xxx         |
  75.     lo_count     |
  76.     hi_count     |
  77.     lo_origin     > count bytes
  78.     hi_origin     |
  79.     data byte     |
  80.     :         |
  81.     data byte    ---
  82.     checksum
  83.  
  84.    If the byte count is exactly six, the block is the last on the tape, and
  85.    there is no checksum.  If the origin is not 000001, then the origin is
  86.    the PC at which to start the program.
  87. */
  88.  
  89. int sim_load (FILE *fileref)
  90. {
  91. int origin, csum, count, state, i;
  92.  
  93. state = csum = 0;
  94. while ((i = getc (fileref)) != EOF) {
  95.     csum = csum + i;                /* add into chksum */
  96.     switch (state) {
  97.     case 0:                        /* leader */
  98.         if (i == 1) state = 1;
  99.         else csum = 0;
  100.         break;
  101.     case 1:                        /* ignore after 001 */
  102.         state = 2;
  103.         break;
  104.     case 2:                        /* low count */
  105.         count = i;
  106.         state = 3;
  107.         break;
  108.     case 3:                        /* high count */
  109.         count = (i << 8) | count;
  110.         state = 4;
  111.         break;
  112.     case 4:                        /* low origin */
  113.         origin = i;
  114.         state = 5;
  115.         break;
  116.     case 5:                        /* high origin */
  117.         origin = (i << 8) | origin;
  118.         if (count == 6) {
  119.             if (origin != 1) saved_PC = origin & 0177776;
  120.             return SCPE_OK;  }
  121.         count = count - 6;
  122.         state = 6;
  123.         break;
  124.     case 6:                        /* data */
  125.         if (origin >= MEMSIZE) return SCPE_NXM;
  126.         M[origin >> 1] = (origin & 1)?
  127.             (M[origin >> 1] & 0377) | (i << 8):
  128.             (M[origin >> 1] & 0177400) | i;
  129.         count = count - 1;
  130.         state = state + (count == 0);
  131.         break;
  132.     case 7:                        /* checksum */
  133.         if (csum & 0377) return SCPE_CSUM;
  134.         csum = state = 0;
  135.         break;  }                /* end switch */
  136.     }                        /* end while */
  137. return SCPE_FMT;                    /* unexpected eof */
  138. }                            /* end sim_loader */
  139.  
  140. /* Symbol tables */
  141.  
  142. #define I_V_L        16                /* long mode */
  143. #define I_V_D        17                /* double mode */
  144. #define I_L        (1 << I_V_L)
  145. #define I_D        (1 << I_V_D)
  146.  
  147. /* Warning: for literals, the class number MUST equal the field width!! */
  148.  
  149. #define I_V_CL        18                /* class bits */
  150. #define I_M_CL        017                /* class mask */
  151. #define I_V_NPN        0                /* no operands */
  152. #define I_V_REG        1                /* reg */
  153. #define I_V_SOP        2                /* operand */
  154. #define I_V_3B        3                /* 3b literal */
  155. #define I_V_FOP        4                /* flt operand */
  156. #define I_V_AFOP    5                /* fac, flt operand */
  157. #define I_V_6B        6                /* 6b literal */
  158. #define I_V_BR        7                /* cond branch */
  159. #define I_V_8B        8                /* 8b literal */
  160. #define I_V_SOB        9                /* reg, disp */
  161. #define I_V_RSOP    10                /* reg, operand */
  162. #define I_V_ASOP    11                /* fac, operand */
  163. #define I_V_ASMD    12                /* fac, moded int op */
  164. #define I_V_DOP        13                /* double operand */
  165. #define I_V_CCC        14                /* CC clear */
  166. #define I_V_CCS        15                /* CC set */
  167. #define I_NPN        (I_V_NPN << I_V_CL)
  168. #define I_REG        (I_V_REG << I_V_CL)
  169. #define I_3B        (I_V_3B << I_V_CL)
  170. #define I_SOP        (I_V_SOP << I_V_CL)
  171. #define I_FOP        (I_V_FOP << I_V_CL)
  172. #define I_6B        (I_V_6B << I_V_CL)
  173. #define I_BR        (I_V_BR << I_V_CL)
  174. #define I_8B        (I_V_8B << I_V_CL)
  175. #define I_AFOP        (I_V_AFOP << I_V_CL)
  176. #define I_ASOP        (I_V_ASOP << I_V_CL)
  177. #define I_RSOP        (I_V_RSOP << I_V_CL)
  178. #define I_SOB        (I_V_SOB << I_V_CL)
  179. #define I_ASMD        (I_V_ASMD << I_V_CL)
  180. #define I_DOP        (I_V_DOP << I_V_CL)
  181. #define I_CCC        (I_V_CCC << I_V_CL)
  182. #define I_CCS        (I_V_CCS << I_V_CL)
  183.  
  184. static const int masks[] = {
  185. 0177777, 0177770, 0177700, 0177770,
  186. 0177700+I_D, 0177400+I_D, 0177700, 0177400,
  187. 0177400, 0177000, 0177000, 0177400,
  188. 0177400+I_D+I_L, 0170000, 0177777, 0177777 };
  189.  
  190. static const char *opcode[] = {
  191. "HALT","WAIT","RTI","BPT",
  192. "IOT","RESET","RTT","MFPT",
  193. "JMP","RTS","SPL",
  194. "NOP","CLC","CLV","CLV CLC",
  195. "CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC",
  196. "CLN","CLN CLC","CLN CLV","CLN CLV CLC",
  197. "CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC",
  198. "NOP","SEC","SEV","SEV SEC",
  199. "SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC",
  200. "SEN","SEN SEC","SEN SEV","SEN SEV SEC",
  201. "SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC",
  202. "SWAB","BR","BNE","BEQ",
  203. "BGE","BLT","BGT","BLE",
  204. "JSR",
  205. "CLR","COM","INC","DEC",
  206. "NEG","ADC","SBC","TST",
  207. "ROL","ROR","ASR","ASL",
  208. "MARK","MFPI","MTPI","SXT",
  209. "CSM",        "TSTSET","WRTLCK",
  210. "MOV","CMP","BIT","BIC",
  211. "BIS","ADD",
  212. "MUL","DIV","ASH","ASHC",
  213. "XOR",
  214. "FADD","FSUB","FMUL","FDIV",
  215. "L2DR",
  216. "MOVC","MOVRC","MOVTC",
  217. "LOCC","SKPC","SCANC","SPANC",
  218. "CMPC","MATC",
  219. "ADDN","SUBN","CMPN","CVTNL",
  220. "CVTPN","CVTNP","ASHN","CVTLN",
  221. "L3DR",
  222. "ADDP","SUBP","CMPP","CVTPL",
  223. "MULP","DIVP","ASHP","CVTLP",
  224. "MOVCI","MOVRCI","MOVTCI",
  225. "LOCCI","SKPCI","SCANCI","SPANCI",
  226. "CMPCI","MATCI",
  227. "ADDNI","SUBNI","CMPNI","CVTNLI",
  228. "CVTPNI","CVTNPI","ASHNI","CVTLNI",
  229. "ADDPI","SUBPI","CMPPI","CVTPLI",
  230. "MULPI","DIVPI","ASHPI","CVTLPI",
  231. "SOB",
  232. "BPL","BMI","BHI","BLOS",
  233. "BVC","BVS","BCC","BCS",
  234. "EMT","TRAP",
  235. "CLRB","COMB","INCB","DECB",
  236. "NEGB","ADCB","SBCB","TSTB",
  237. "ROLB","RORB","ASRB","ASLB",
  238. "MTPS","MFPD","MTPD","MFPS",
  239. "MOVB","CMPB","BITB","BICB",
  240. "BISB","SUB",
  241. "CFCC","SETF","SETI","SETD","SETL",
  242. "LDFPS","STFPS","STST",
  243. "CLRF","CLRD","TSTF","TSTD",
  244. "ABSF","ABSD","NEGF","NEGD",
  245. "MULF","MULD","MODF","MODD",
  246. "ADDF","ADDD","LDF","LDD",
  247. "SUBF","SUBD","CMPF","CMPD",
  248. "STF","STD","DIVF","DIVD",
  249. "STEXP",
  250. "STCFI","STCDI","STCFL","STCDL",
  251. "STCFD","STCDF",
  252. "LDEXP",
  253. "LDCIF","LDCID","LDCLF","LDCLD",
  254. "LDCFD","LDCDF",
  255. NULL };
  256.  
  257. static const int opc_val[] = {
  258. 0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN,
  259. 0000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN,
  260. 0000100+I_SOP, 0000200+I_REG, 0000230+I_3B,
  261. 0000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, 
  262. 0000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, 
  263. 0000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, 
  264. 0000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, 
  265. 0000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, 
  266. 0000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, 
  267. 0000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, 
  268. 0000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, 
  269. 0000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR,
  270. 0002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR,
  271. 0004000+I_RSOP,
  272. 0005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP,
  273. 0005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP,
  274. 0006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP,
  275. 0006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP,
  276. 0007000+I_SOP,                0007200+I_SOP, 0007300+I_SOP,
  277. 0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP,
  278. 0050000+I_DOP, 0060000+I_DOP,
  279. 0070000+I_RSOP, 0071000+I_RSOP, 0072000+I_RSOP, 0073000+I_RSOP,
  280. 0074000+I_RSOP,
  281. 0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG,
  282. 0076020+I_REG,
  283. 0076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN,
  284. 0076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN,
  285. 0076044+I_NPN, 0076045+I_NPN, 
  286. 0076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN,
  287. 0076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN,
  288. 0076060+I_REG,
  289. 0076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN,
  290. 0076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN,
  291. 0076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN,
  292. 0076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN,
  293. 0076144+I_NPN, 0076145+I_NPN, 
  294. 0076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN,
  295. 0076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN,
  296. 0076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN,
  297. 0076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN,
  298. 0077000+I_SOB,
  299. 0100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR,
  300. 0102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR,
  301. 0104000+I_8B, 0104400+I_8B,
  302. 0105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP,
  303. 0105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP,
  304. 0106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP,
  305. 0106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP,
  306. 0110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP,
  307. 0150000+I_DOP, 0160000+I_DOP,
  308. 0170000+I_NPN, 0170001+I_NPN, 0170002+I_NPN, 0170011+I_NPN, 0170012+I_NPN,
  309. 0170100+I_SOP, 0170200+I_SOP, 0170300+I_SOP,
  310. 0170400+I_FOP, 0170400+I_FOP+I_D, 0170500+I_FOP, 0170500+I_FOP+I_D,
  311. 0170600+I_FOP, 0170600+I_FOP+I_D, 0170700+I_FOP, 0170700+I_FOP+I_D,
  312. 0171000+I_AFOP, 0171000+I_AFOP+I_D, 0171400+I_AFOP, 0171400+I_AFOP+I_D,
  313. 0172000+I_AFOP, 0172000+I_AFOP+I_D, 0172400+I_AFOP, 0172400+I_AFOP+I_D, 
  314. 0173000+I_AFOP, 0173000+I_AFOP+I_D, 0173400+I_AFOP, 0173400+I_AFOP+I_D,
  315. 0174000+I_AFOP, 0174000+I_AFOP+I_D, 0174400+I_AFOP, 0174400+I_AFOP+I_D,
  316. 0175000+I_ASOP,
  317. 0175400+I_ASMD, 0175400+I_ASMD+I_D, 0175400+I_ASMD+I_L, 0175400+I_ASMD+I_D+I_L, 
  318. 0176000+I_AFOP, 0176000+I_AFOP+I_D,
  319. 0176400+I_ASOP, 
  320. 0177000+I_ASMD, 0177000+I_ASMD+I_D, 0177000+I_ASMD+I_L, 0177000+I_ASMD+I_D+I_L, 
  321. 0177400+I_AFOP, 0177400+I_AFOP+I_D,
  322. -1 };
  323.  
  324. static const char *rname [] =
  325. { "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" };
  326.  
  327. static const char *fname [] =
  328. { "F0", "F1", "F2", "F3", "F4", "F5", "?6", "?7" };
  329.  
  330. /* Specifier decode
  331.  
  332.    Inputs:
  333.     addr    =    current PC
  334.     spec    =    specifier
  335.     nval    =    next word
  336.     flag    =    TRUE if decoding for CPU
  337.     iflag    =    TRUE if decoding integer instruction
  338.    Outputs:
  339.     count    =    -number of extra words retired
  340. */
  341.  
  342. int specf (unsigned int addr, int spec, int nval, int flag, int iflag)
  343. {
  344. int reg;
  345.  
  346. reg = spec & 07;
  347. switch ((spec >> 3) & 07) {
  348. case 0:
  349.     if (iflag) printf ("%s", rname[reg]);
  350.     else printf ("%s", fname[reg]);
  351.     return 0;
  352. case 1:
  353.     printf ("(%s)", rname[reg]);
  354.     return 0;
  355. case 2:
  356.     if (reg != 7) {
  357.         printf ("(%s)+", rname[reg]);
  358.         return 0;  }
  359.     else {    printf ("#%-o", nval);
  360.         return -1;  }
  361. case 3:
  362.     if (reg != 7) {
  363.         printf ("@(%s)+", rname[reg]);
  364.         return 0;  }
  365.     else {    printf ("@#%-o", nval);
  366.         return -1;  }
  367. case 4:
  368.     printf ("-(%s)", rname[reg]);
  369.     return 0;
  370. case 5:
  371.     printf ("@-(%s)", rname[reg]);
  372.     return 0;
  373. case 6:
  374.     if ((reg != 7) || !flag) printf ("%-o(%s)", nval, rname[reg]);
  375.     else printf ("%-o", (nval + addr + 4) & 0177777);
  376.     return -1;
  377. case 7:
  378.     if ((reg != 7) || !flag) printf ("@%-o(%s)", nval, rname[reg]);
  379.     else printf ("@%-o", (nval + addr + 4) & 0177777);
  380.     return -1;  }                    /* end case */
  381. }
  382.  
  383. /* Symbolic decode
  384.  
  385.    Inputs:
  386.     addr    =    current PC
  387.     *val    =    values to decode
  388.     cflag    =    TRUE if decoding for CPU
  389.     sw    =    switches
  390.    Outputs:
  391.     return    =    if >= 0, error code
  392.             if < 0, number of extra words retired
  393. */
  394.  
  395. int print_sym (unsigned int addr, unsigned int *val, int cflag, int sw)
  396. {
  397. int i, j, c1, c2, inst, fac, srcm, srcr, dstm, dstr, l8b, brdisp, wd1, wd2;
  398. extern int FPS;
  399.  
  400. c1 = val[0] & 0177;
  401. c2 = (val[0] >> 8) & 0177;
  402. if (sw & SWMASK ('A')) {                /* ASCII? */
  403.     printf ((c1 < 040)? "<%03o>": "%c", c1);
  404.     return SCPE_OK;  }
  405. if (sw & SWMASK ('C')) {                /* character? */
  406.     printf ((c1 < 040)? "<%03o>": "%c", c1);
  407.     printf ((c2 < 040)? "<%03o>": "%c", c2);
  408.     return SCPE_OK;  }
  409. if (!(sw & SWMASK ('M'))) return SCPE_ARG;
  410.  
  411. inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) |
  412.     ((FPS << (I_V_D - FPS_V_D)) & I_D);        /* inst + fp mode */
  413. for (i = 0; opc_val[i] >= 0; i++) {            /* loop thru ops */
  414.     j = (opc_val[i] >> I_V_CL) & I_M_CL;        /* get class */
  415.     if ((opc_val[i] & 0777777) == (inst & masks[j])) {    /* match? */
  416.     srcm = (inst >> 6) & 077;            /* opr fields */
  417.     srcr = srcm & 07;
  418.     fac = srcm & 03;
  419.     dstm = inst & 077;
  420.     dstr = dstm & 07;
  421.     l8b = inst & 0377;
  422.  
  423. /* Instruction decode */
  424.  
  425.     switch (j) {                    /* case on class */
  426.     case I_V_NPN: case I_V_CCC: case I_V_CCS:    /* no operands */
  427.         printf ("%s", opcode[i]);
  428.         return SCPE_OK;
  429.     case I_V_REG:                    /* reg */
  430.         printf ("%s %-s", opcode[i], rname[dstr]);
  431.         return SCPE_OK;
  432.     case I_V_SOP:                    /* sop */
  433.         printf ("%s ", opcode[i]);
  434.         return specf (addr, dstm, val[1], cflag, TRUE);
  435.     case I_V_3B:                    /* 3b */
  436.         printf ("%s %-o", opcode[i], dstr);
  437.         return SCPE_OK;
  438.     case I_V_FOP:                    /* fop */
  439.         printf ("%s ", opcode[i]);
  440.         return specf (addr, dstm, val[1], cflag, FALSE);
  441.     case I_V_AFOP:                    /* afop */
  442.         printf ("%s %s,", opcode[i], fname[fac]);
  443.         return specf (addr, dstm, val[1], cflag, FALSE);
  444.     case I_V_6B:                    /* 6b */
  445.         printf ("%s %-o", opcode[i], dstm);
  446.         return SCPE_OK;
  447.     case I_V_BR:                    /* cond branch */
  448.         printf ("%s ", opcode[i]);
  449.         brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;
  450.          if (cflag) printf ("%-o", (addr + brdisp) & 0177777);
  451.         else if (brdisp < 01000) printf (".+%-o", brdisp);
  452.         else printf (".-%-o", 0200000 - brdisp);
  453.         return SCPE_OK;
  454.     case I_V_8B:                    /* 8b */
  455.         printf ("%s %-o", opcode[i], l8b);
  456.         return SCPE_OK;
  457.     case I_V_SOB:                    /* sob */
  458.         printf ("%s %s,", opcode[i], rname[srcr]);
  459.         brdisp = (dstm * 2) - 2;
  460.         if (cflag) printf ("%-o", (addr - brdisp) & 0177777);
  461.         else if (brdisp <= 0) printf (".+%-o", -brdisp);
  462.         else printf (".-%-o", brdisp);
  463.         return SCPE_OK;
  464.     case I_V_RSOP:                    /* rsop */
  465.         printf ("%s %s,", opcode[i], rname[srcr]);
  466.         return specf (addr, dstm, val[1], cflag, TRUE);
  467.     case I_V_ASOP: case I_V_ASMD:            /* asop, asmd */
  468.         printf ("%s %s,", opcode[i], fname[fac]);
  469.         return specf (addr, dstm, val[2], cflag, TRUE);
  470.     case I_V_DOP:                    /* dop */
  471.         printf ("%s ", opcode[i]);
  472.         wd1 = specf (addr, srcm, val[1], cflag, TRUE);
  473.         printf (",");
  474.         wd2 = specf (addr - wd1 - wd1, dstm, val[1 - wd1], cflag, TRUE);
  475.         return wd1 + wd2;  }            /* end case */
  476.         }                    /* end if */
  477.     }                        /* end for */
  478. return SCPE_ARG;                    /* no match */
  479. }
  480.  
  481. #define A_PND    100                    /* # seen */
  482. #define A_MIN    040                    /* -( seen */
  483. #define A_PAR    020                    /* (Rn) seen */
  484. #define A_REG    010                    /* Rn seen */
  485. #define A_PLS    004                    /* + seen */
  486. #define A_NUM    002                    /* number seen */
  487. #define A_REL    001                    /* relative addr seen */
  488.  
  489. /* Register number
  490.  
  491.    Inputs:
  492.     *cptr    =    pointer to input string
  493.     *strings =    pointer to register names
  494.     mchar    =    character to match after register name
  495.    Outputs:
  496.     rnum    =    0..7 if a legitimate register
  497.             < 0 if error
  498. */
  499.  
  500. int get_reg (char *cptr, const char *strings[], char mchar)
  501. {
  502. int i;
  503.  
  504. if (*(cptr + 2) != mchar) return -1;
  505. for (i = 0; i < 8; i++) {
  506.     if (strncmp (cptr, strings[i], 2) == 0) return i;  }
  507. return -1;
  508. }
  509.  
  510. /* Number or memory address
  511.  
  512.    Inputs:
  513.     *cptr    =    pointer to input string
  514.     *dptr    =    pointer to output displacement
  515.     *pflag    =    pointer to accumulating flags
  516.    Outputs:
  517.     cptr    =    pointer to next character in input string
  518.             NULL if parsing error
  519.  
  520.    Flags: 0 (no result), A_NUM (number), A_REL (relative)
  521. */
  522.  
  523. char *get_addr (char *cptr, int *dptr, int *pflag)
  524. {
  525. int val, minus;
  526. char *tptr;
  527.  
  528. minus = 0;
  529.  
  530. if (*cptr == '.') {                    /* relative? */
  531.     *pflag = *pflag | A_REL;
  532.     cptr++;  }
  533. if (*cptr == '+') {                    /* +? */
  534.     *pflag = *pflag | A_NUM;
  535.     cptr++;  }
  536. if (*cptr == '-') {                    /* -? */
  537.     *pflag = *pflag | A_NUM;
  538.     minus = 1;
  539.     cptr++;  }
  540. errno = 0;
  541. val = strtoul (cptr, &tptr, 8);
  542. if (cptr == tptr) {                    /* no number? */
  543.     if (*pflag != (A_REL + A_NUM)) return cptr;
  544.     else return NULL;  }
  545. if (errno || (*pflag == A_REL)) return NULL;        /* .n? */
  546. *dptr = (minus? -val: val) & 0177777;
  547. *pflag = *pflag | A_NUM;
  548. return tptr;
  549. }
  550.  
  551. /* Specifier decode
  552.  
  553.    Inputs:
  554.     *cptr    =    pointer to input string
  555.     addr    =    current PC
  556.     n1    =    0 if no extra word used
  557.             -1 if extra word used in prior decode
  558.     *sptr    =    pointer to output specifier
  559.     *dptr    =    pointer to output displacement
  560.     cflag    =    true if parsing for the CPU
  561.     iflag    =    true if integer specifier
  562.    Outputs:
  563.     status    =    = -1 extra word decoded
  564.             =  0 ok
  565.             = +1 error
  566. */
  567.  
  568. int get_spec (char *cptr, int addr, int n1, int *sptr, unsigned int *dptr,
  569.     int cflag, int iflag)
  570. {
  571. int reg, indir, pflag, disp;
  572.  
  573. indir = 0;                        /* no indirect */
  574. pflag = 0;
  575.  
  576. if (*cptr == '@') {                    /* indirect? */
  577.     indir = 010;
  578.     cptr++;  }
  579. if (*cptr == '#') {                    /* literal? */
  580.     pflag = pflag | A_PND;
  581.     cptr++;  }
  582. if (strncmp (cptr, "-(", 2) == 0) {            /* autodecrement? */
  583.     pflag = pflag | A_MIN;
  584.     cptr++;  }
  585. else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1;
  586. if (*cptr == '(') {                    /* register index? */
  587.     pflag = pflag | A_PAR;
  588.     if ((reg = get_reg (cptr + 1, rname, ')')) < 0) return 1;
  589.     cptr = cptr + 4;
  590.     if (*cptr == '+') {                /* autoincrement? */
  591.         pflag = pflag | A_PLS;
  592.         cptr++;  }  }
  593. else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) {
  594.     pflag = pflag | A_REG;
  595.     cptr = cptr + 2;  }
  596. if (*cptr != 0) return 1;                /* all done? */
  597.  
  598. /* Specifier decode, continued */
  599.  
  600. switch (pflag) {                    /* case on syntax */
  601. case A_REG:                        /* Rn, @Rn */
  602.     *sptr = indir + reg;
  603.     return 0;
  604. case A_PAR:                        /* (Rn), @(Rn) */
  605.     if (indir) {                    /* @(Rn) = @0(Rn) */
  606.         *sptr = 070 + reg;
  607.         *dptr = 0;
  608.         return -1;  }
  609.     else *sptr = 010 + reg;
  610.     return 0;
  611. case A_PAR+A_PLS:                    /* (Rn)+, @(Rn)+ */
  612.     *sptr = 020 + indir + reg;
  613.     return 0;
  614. case A_MIN+A_PAR:                    /* -(Rn), @-(Rn) */
  615.     *sptr = 040 + indir + reg;
  616.     return 0;
  617. case A_NUM+A_PAR:                    /* d(Rn), @d(Rn) */
  618.     *sptr = 060 + indir + reg;
  619.     *dptr = disp;
  620.     return -1;
  621. case A_PND+A_REL: case A_PND+A_REL+A_NUM:        /* #.+n, @#.+n */
  622.     if (!cflag) return 1;
  623.     disp = (disp + addr) & 0177777;            /* fall through */
  624. case A_PND+A_NUM:                    /* #n, @#n */
  625.     *sptr = 027 + indir;
  626.     *dptr = disp;
  627.     return -1;
  628. case A_REL: case A_REL+A_NUM:                /* .+n, @.+n */
  629.     *sptr = 067 + indir;
  630.     *dptr = (disp - 4 + (2 * n1)) & 0177777;
  631.     return -1;
  632. case A_NUM:                        /* n, @n */
  633.     if (cflag) {                    /* CPU - use rel */
  634.         *sptr = 067 + indir;
  635.         *dptr = (disp - addr - 4 + (2 * n1)) & 0177777;  }
  636.     else {    if (indir) return 1;            /* other - use abs */
  637.         *sptr = 037;
  638.         *dptr = disp;  }
  639.     return -1;
  640. default:
  641.     return 1;  }                    /* end case */
  642. }
  643.  
  644. /* Symbolic input
  645.  
  646.    Inputs:
  647.     *cptr    =    pointer to input string
  648.     addr    =    current PC
  649.     cflag    =    TRUE if parsing for the CPU
  650.     *val    =    pointer to output values
  651.    Outputs:
  652.     status    =    > 0   error code
  653.             <= 0  -number of extra words
  654. */
  655.  
  656. int parse_sym (char *cptr, unsigned int addr, int cflag, unsigned int *val)
  657. {
  658. int i, j, reg, spec, n1, n2, disp, pflag;
  659. unsigned int r;
  660. char gbuf[CBUFSIZE];
  661.  
  662. while (isspace (*cptr)) cptr++;                /* absorb spaces */
  663. if (cptr[0] == '\'') {                    /* single char? */
  664.     if (cptr[1] == 0) return SCPE_ARG;
  665.     val[0] = (unsigned int) cptr[1];
  666.     return SCPE_OK;  }
  667. if (cptr[0] == '"') {                    /* string? */
  668.     if (cptr[1] == 0) return SCPE_ARG;
  669.     val[0] = ((unsigned int) cptr[2] << 8) + (unsigned int) cptr[1];
  670.     return SCPE_OK;  }
  671.  
  672. cptr = get_glyph (cptr, gbuf, 0);            /* get opcode */
  673. n1 = n2 = pflag = 0;
  674. for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
  675. if (opcode[i] == NULL) return SCPE_ARG;
  676. val[0] = opc_val[i] & 0177777;                /* get value */
  677. j = (opc_val[i] >> I_V_CL) & I_M_CL;            /* get class */
  678.  
  679. switch (j) {                        /* case on class */
  680. case I_V_NPN:                        /* no operand */
  681.     break;
  682. case I_V_REG:                        /* register */
  683.     cptr = get_glyph (cptr, gbuf, 0);        /* get glyph */
  684.     if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
  685.     val[0] = val[0] | reg;
  686.     break;
  687. case I_V_3B: case I_V_6B: case I_V_8B:            /* xb literal */
  688.     cptr = get_glyph (cptr, gbuf, 0);        /* get literal */
  689.     if (get_unum (gbuf, 8, (1 << j) - 1, &r) != SCPE_OK) return SCPE_ARG;
  690.     val[0] = val[0] | r;                /* put in place */
  691.     break;
  692. case I_V_BR:                        /* cond br */
  693.     cptr = get_glyph (cptr, gbuf, 0);        /* get address */
  694.     if ((cptr = get_addr (gbuf, &disp, &pflag)) == NULL) return SCPE_ARG;
  695.     if ((pflag & A_REL) == 0) {
  696.         if (cflag) disp = (disp - addr) & 0177777;
  697.         else return SCPE_ARG;  }
  698.     if ((disp & 1) || (disp > 0400) && (disp < 0177402)) return SCPE_ARG;
  699.     val[0] = val[0] | (((disp - 2) >> 1) & 0377);
  700.     break;
  701. case I_V_SOB:                        /* sob */
  702.     cptr = get_glyph (cptr, gbuf, ',');        /* get glyph */
  703.     if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
  704.     val[0] = val[0] | (reg << 6);
  705.     cptr = get_glyph (cptr, gbuf, 0);        /* get address */
  706.     if ((cptr = get_addr (gbuf, &disp, &pflag)) == NULL) return SCPE_ARG;
  707.     if ((pflag & A_REL) == 0) {
  708.         if (cflag) disp = (disp - addr) & 0177777;
  709.         else return SCPE_ARG;  }
  710.     if ((disp & 1) || ((disp > 2) && (disp < 0177604))) return SCPE_ARG;
  711.     val[0] = val[0] | (((2 - disp) >> 1) & 077);
  712.     break;
  713. case I_V_RSOP:                        /* reg, sop */
  714.     cptr = get_glyph (cptr, gbuf, ',');        /* get glyph */
  715.     if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
  716.     val[0] = val[0] | (reg << 6);            /* fall through */
  717. case I_V_SOP:                        /* sop */
  718.     cptr = get_glyph (cptr, gbuf, 0);        /* get glyph */
  719.     if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)
  720.         return SCPE_ARG;
  721.     val[0] = val[0] | spec;
  722.     break;
  723. case I_V_AFOP: case I_V_ASOP: case I_V_ASMD:        /* fac, (s)fop */
  724.     cptr = get_glyph (cptr, gbuf, ',');        /* get glyph */
  725.     if ((reg = get_reg (gbuf, fname, 0)) < 0) return SCPE_ARG;
  726.     if (reg > 3) return SCPE_ARG;
  727.     val[0] = val[0] | (reg << 6);            /* fall through */
  728. case I_V_FOP:                        /* fop */
  729.     cptr = get_glyph (cptr, gbuf, 0);        /* get glyph */
  730.     if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, 
  731.         (j == I_V_ASOP) || (j == I_V_ASMD))) > 0) return SCPE_ARG;
  732.     val[0] = val[0] | spec;
  733.     break;
  734. case I_V_DOP:                        /* double op */
  735.     cptr = get_glyph (cptr, gbuf, ',');        /* get glyph */
  736.     if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)
  737.         return SCPE_ARG;
  738.     val[0] = val[0] | (spec << 6);
  739.     cptr = get_glyph (cptr, gbuf, 0);        /* get glyph */
  740.     if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1],
  741.         cflag, TRUE)) > 0) return SCPE_ARG;
  742.     val[0] = val[0] | spec;
  743.     break;
  744. case I_V_CCC: case I_V_CCS:                /* cond code oper */
  745.     for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
  746.         cptr = get_glyph (cptr, gbuf, 0)) {
  747.         for (i = 0; (opcode[i] != NULL) &&
  748.             (strcmp (opcode[i], gbuf) != 0) ; i++) ;
  749.         if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) ||
  750.             (opcode[i] == NULL)) return SCPE_ARG;
  751.         val[0] = val[0] | (opc_val[i] & 0177777);  }
  752.     break;
  753. default:
  754.     return SCPE_ARG;  }
  755. if (*cptr != 0) return SCPE_ARG;            /* junk at end? */
  756. return n1 + n2;
  757. }
  758.