First Commit of my working state
[simh.git] / VAX / vax_syscm.c
CommitLineData
196ba1fc
PH
1/* vax_syscm.c: PDP-11 compatibility mode symbolic decode and parse\r
2\r
3 Copyright (c) 1993-2006, Robert M Supnik\r
4\r
5 Permission is hereby granted, free of charge, to any person obtaining a\r
6 copy of this software and associated documentation files (the "Software"),\r
7 to deal in the Software without restriction, including without limitation\r
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
9 and/or sell copies of the Software, and to permit persons to whom the\r
10 Software is furnished to do so, subject to the following conditions:\r
11\r
12 The above copyright notice and this permission notice shall be included in\r
13 all copies or substantial portions of the Software.\r
14\r
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21\r
22 Except as contained in this notice, the name of Robert M Supnik shall not be\r
23 used in advertising or otherwise to promote the sale, use or other dealings\r
24 in this Software without prior written authorization from Robert M Supnik.\r
25\r
26 12-Nov-06 RMS Fixed operand order in EIS instructions (found by W.F.J. Mueller)\r
27 27-Sep-05 RMS Fixed warnings compiling with 64b addresses\r
28 15-Sep-04 RMS Cloned from pdp11_sys.c\r
29*/\r
30\r
31#include "vax_defs.h"\r
32#include <ctype.h>\r
33\r
34extern UNIT cpu_unit;\r
35\r
36/* Symbol tables */\r
37/* Warning: for literals, the class number MUST equal the field width!! */\r
38\r
39#define I_V_CL 18 /* class bits */\r
40#define I_M_CL 017 /* class mask */\r
41#define I_V_NPN 0 /* no operands */\r
42#define I_V_REG 1 /* reg */\r
43#define I_V_SOP 2 /* operand */\r
44#define I_V_3B 3 /* 3b literal */\r
45#define I_V_RSOP 4 /* reg, operand */\r
46#define I_V_BR 5 /* cond branch */\r
47#define I_V_6B 6 /* 6b literal */\r
48#define I_V_SOB 7 /* reg, disp */\r
49#define I_V_8B 8 /* 8b literal */\r
50#define I_V_DOP 9 /* double operand */\r
51#define I_V_CCC 10 /* CC clear */\r
52#define I_V_CCS 11 /* CC set */\r
53#define I_V_SOPR 12 /* operand, reg */\r
54#define I_NPN (I_V_NPN << I_V_CL)\r
55#define I_REG (I_V_REG << I_V_CL)\r
56#define I_SOP (I_V_SOP << I_V_CL)\r
57#define I_3B (I_V_3B << I_V_CL)\r
58#define I_6B (I_V_6B << I_V_CL)\r
59#define I_BR (I_V_BR << I_V_CL)\r
60#define I_8B (I_V_8B << I_V_CL)\r
61#define I_RSOP (I_V_RSOP << I_V_CL)\r
62#define I_SOB (I_V_SOB << I_V_CL)\r
63#define I_DOP (I_V_DOP << I_V_CL)\r
64#define I_CCC (I_V_CCC << I_V_CL)\r
65#define I_CCS (I_V_CCS << I_V_CL)\r
66#define I_SOPR (I_V_SOPR << I_V_CL)\r
67\r
68static const int32 masks[] = {\r
69 0177777, 0177770, 0177700, 0177770,\r
70 0177000, 0177400, 0177700, 0177000,\r
71 0177400, 0170000, 0177777, 0177777,\r
72 0177000\r
73 };\r
74\r
75static const char *opcode[] = {\r
76"HALT","WAIT","RTI","BPT",\r
77"IOT","RESET","RTT","MFPT",\r
78"JMP","RTS","SPL",\r
79"NOP","CLC","CLV","CLV CLC",\r
80"CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC",\r
81"CLN","CLN CLC","CLN CLV","CLN CLV CLC",\r
82"CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC",\r
83"NOP","SEC","SEV","SEV SEC",\r
84"SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC",\r
85"SEN","SEN SEC","SEN SEV","SEN SEV SEC",\r
86"SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC",\r
87"SWAB","BR","BNE","BEQ",\r
88"BGE","BLT","BGT","BLE",\r
89"JSR",\r
90"CLR","COM","INC","DEC",\r
91"NEG","ADC","SBC","TST",\r
92"ROR","ROL","ASR","ASL",\r
93"MARK","MFPI","MTPI","SXT",\r
94"CSM", "TSTSET","WRTLCK",\r
95"MOV","CMP","BIT","BIC",\r
96"BIS","ADD",\r
97"MUL","DIV","ASH","ASHC",\r
98"XOR",\r
99"FADD","FSUB","FMUL","FDIV",\r
100"L2DR",\r
101"MOVC","MOVRC","MOVTC",\r
102"LOCC","SKPC","SCANC","SPANC",\r
103"CMPC","MATC",\r
104"ADDN","SUBN","CMPN","CVTNL",\r
105"CVTPN","CVTNP","ASHN","CVTLN",\r
106"L3DR",\r
107"ADDP","SUBP","CMPP","CVTPL",\r
108"MULP","DIVP","ASHP","CVTLP",\r
109"MOVCI","MOVRCI","MOVTCI",\r
110"LOCCI","SKPCI","SCANCI","SPANCI",\r
111"CMPCI","MATCI",\r
112"ADDNI","SUBNI","CMPNI","CVTNLI",\r
113"CVTPNI","CVTNPI","ASHNI","CVTLNI",\r
114"ADDPI","SUBPI","CMPPI","CVTPLI",\r
115"MULPI","DIVPI","ASHPI","CVTLPI",\r
116"SOB",\r
117"BPL","BMI","BHI","BLOS",\r
118"BVC","BVS","BCC","BCS",\r
119"BHIS","BLO", /* encode only */\r
120"EMT","TRAP",\r
121"CLRB","COMB","INCB","DECB",\r
122"NEGB","ADCB","SBCB","TSTB",\r
123"RORB","ROLB","ASRB","ASLB",\r
124"MTPS","MFPD","MTPD","MFPS",\r
125"MOVB","CMPB","BITB","BICB",\r
126"BISB","SUB",\r
127NULL\r
128};\r
129\r
130static const int32 opc_val[] = {\r
1310000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN,\r
1320000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN,\r
1330000100+I_SOP, 0000200+I_REG, 0000230+I_3B,\r
1340000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, \r
1350000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, \r
1360000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, \r
1370000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, \r
1380000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, \r
1390000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, \r
1400000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, \r
1410000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, \r
1420000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR,\r
1430002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR,\r
1440004000+I_RSOP,\r
1450005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP,\r
1460005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP,\r
1470006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP,\r
1480006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP,\r
1490007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP,\r
1500010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP,\r
1510050000+I_DOP, 0060000+I_DOP,\r
1520070000+I_SOPR, 0071000+I_SOPR, 0072000+I_SOPR, 0073000+I_SOPR,\r
1530074000+I_RSOP,\r
1540075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG,\r
1550076020+I_REG,\r
1560076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN,\r
1570076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN,\r
1580076044+I_NPN, 0076045+I_NPN, \r
1590076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN,\r
1600076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN,\r
1610076060+I_REG,\r
1620076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN,\r
1630076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN,\r
1640076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN,\r
1650076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN,\r
1660076144+I_NPN, 0076145+I_NPN, \r
1670076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN,\r
1680076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN,\r
1690076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN,\r
1700076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN,\r
1710077000+I_SOB,\r
1720100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR,\r
1730102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR,\r
1740103000+I_BR, 0103400+I_BR,\r
1750104000+I_8B, 0104400+I_8B,\r
1760105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP,\r
1770105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP,\r
1780106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP,\r
1790106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP,\r
1800110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP,\r
1810150000+I_DOP, 0160000+I_DOP,\r
182-1\r
183};\r
184\r
185static const char *rname [] = {\r
186 "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC"\r
187 };\r
188\r
189static const char r50_to_asc[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789";\r
190\r
191/* Specifier decode\r
192\r
193 Inputs:\r
194 *of = output stream\r
195 addr = current PC\r
196 spec = specifier\r
197 nval = next word\r
198 flag = TRUE if decoding for CPU\r
199 iflag = TRUE if decoding integer instruction\r
200 Outputs:\r
201 count = -number of extra words retired\r
202*/\r
203\r
204int32 fprint_spec (FILE *of, t_addr addr, int32 spec, int32 nval)\r
205{\r
206int32 reg, mode;\r
207static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 };\r
208static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 };\r
209\r
210reg = spec & 07;\r
211mode = ((spec >> 3) & 07);\r
212switch (mode) {\r
213\r
214 case 0:\r
215 fprintf (of, "%s", rname[reg]);\r
216 break;\r
217\r
218 case 1:\r
219 fprintf (of, "(%s)", rname[reg]);\r
220 break;\r
221\r
222 case 2:\r
223 if (reg != 7) fprintf (of, "(%s)+", rname[reg]);\r
224 else fprintf (of, "#%-X", nval);\r
225 break;\r
226\r
227 case 3:\r
228 if (reg != 7) fprintf (of, "@(%s)+", rname[reg]);\r
229 else fprintf (of, "@#%-X", nval);\r
230 break;\r
231\r
232 case 4:\r
233 fprintf (of, "-(%s)", rname[reg]);\r
234 break;\r
235\r
236 case 5:\r
237 fprintf (of, "@-(%s)", rname[reg]);\r
238 break;\r
239\r
240 case 6:\r
241 if (reg != 7) fprintf (of, "%-X(%s)", nval, rname[reg]);\r
242 else fprintf (of, "%-X", (nval + addr + 4) & 0177777);\r
243 break;\r
244\r
245 case 7:\r
246 if (reg != 7) fprintf (of, "@%-X(%s)", nval, rname[reg]);\r
247 else fprintf (of, "@%-X", (nval + addr + 4) & 0177777);\r
248 break;\r
249 } /* end case */\r
250\r
251return ((reg == 07)? pcwd[mode]: rgwd[mode]);\r
252}\r
253\r
254/* Symbolic decode\r
255\r
256 Inputs:\r
257 *of = output stream\r
258 addr = current PC\r
259 *val = values to decode\r
260 *uptr = pointer to unit\r
261 sw = switches\r
262 Outputs:\r
263 return = if >= 0, error code\r
264 if < 0, number of extra words retired\r
265*/\r
266\r
267t_stat fprint_sym_cm (FILE *of, t_addr addr, t_value *bytes, int32 sw)\r
268{\r
269int32 i, j, c1, c2, c3, inst, srcm, srcr, dstm, dstr;\r
270int32 l8b, brdisp, wd1;\r
271uint32 val[3];\r
272\r
273for (i = j = 0; i < 3; i++, j = j + 2)\r
274 val[i] = (int32) (bytes[j] | (bytes[j + 1] << 8));\r
275 \r
276if (sw & SWMASK ('R')) { /* radix 50? */\r
277 if (val[0] > 0174777) return SCPE_ARG; /* max value */\r
278 c3 = val[0] % 050;\r
279 c2 = (val[0] / 050) % 050;\r
280 c1 = val[0] / (050 * 050);\r
281 fprintf (of, "%c%c%c", r50_to_asc[c1],\r
282 r50_to_asc[c2], r50_to_asc[c3]);\r
283 return -1;\r
284 }\r
285if (!(sw & SWMASK ('P')) || (addr & 1) || (addr > WMASK))\r
286 return SCPE_ARG;\r
287\r
288inst = val[0]; /* inst */\r
289wd1 = 0;\r
290for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
291 j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */\r
292 if ((opc_val[i] & 0177777) == (inst & masks[j])) { /* match? */\r
293 srcm = (inst >> 6) & 077; /* opr fields */\r
294 srcr = srcm & 07;\r
295 dstm = inst & 077;\r
296 dstr = dstm & 07;\r
297 l8b = inst & 0377;\r
298 switch (j) { /* case on class */\r
299\r
300 case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */\r
301 fprintf (of, "%s", opcode[i]);\r
302 break;\r
303\r
304 case I_V_REG: /* reg */\r
305 fprintf (of, "%s %-s", opcode[i], rname[dstr]);\r
306 break;\r
307\r
308 case I_V_SOP: /* sop */\r
309 fprintf (of, "%s ", opcode[i]);\r
310 wd1 = fprint_spec (of, addr, dstm, val[1]);\r
311 break;\r
312\r
313 case I_V_3B: /* 3b */\r
314 fprintf (of, "%s %-X", opcode[i], dstr);\r
315 break;\r
316\r
317 case I_V_6B: /* 6b */\r
318 fprintf (of, "%s %-X", opcode[i], dstm);\r
319 break;\r
320\r
321 case I_V_BR: /* cond branch */\r
322 fprintf (of, "%s ", opcode[i]);\r
323 brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;\r
324 fprintf (of, "%-X", (addr + brdisp) & 0177777);\r
325 break;\r
326\r
327 case I_V_8B: /* 8b */\r
328 fprintf (of, "%s %-X", opcode[i], l8b);\r
329 break;\r
330\r
331 case I_V_SOB: /* sob */\r
332 fprintf (of, "%s %s,", opcode[i], rname[srcr]);\r
333 brdisp = (dstm * 2) - 2;\r
334 fprintf (of, "%-X", (addr - brdisp) & 0177777);\r
335 break;\r
336\r
337 case I_V_RSOP: /* rsop */\r
338 fprintf (of, "%s %s,", opcode[i], rname[srcr]);\r
339 wd1 = fprint_spec (of, addr, dstm, val[1]);\r
340 break;\r
341\r
342 case I_V_SOPR: /* sopr */\r
343 fprintf (of, "%s ", opcode[i]);\r
344 wd1 = fprint_spec (of, addr, dstm, val[1]);\r
345 fprintf (of, ",%s", rname[srcr]);\r
346 break;\r
347\r
348 case I_V_DOP: /* dop */\r
349 fprintf (of, "%s ", opcode[i]);\r
350 wd1 = fprint_spec (of, addr, srcm, val[1]);\r
351 fprintf (of, ",");\r
352 wd1 += fprint_spec (of, addr - wd1 - wd1, dstm,\r
353 val[1 - wd1]);\r
354 break;\r
355 } /* end case */\r
356\r
357 return ((wd1 * 2) - 1);\r
358 } /* end if */\r
359 } /* end for */\r
360return SCPE_ARG; /* no match */\r
361}\r
362\r
363#define A_PND 100 /* # seen */\r
364#define A_MIN 040 /* -( seen */\r
365#define A_PAR 020 /* (Rn) seen */\r
366#define A_REG 010 /* Rn seen */\r
367#define A_PLS 004 /* + seen */\r
368#define A_NUM 002 /* number seen */\r
369#define A_REL 001 /* relative addr seen */\r
370\r
371/* Register number\r
372\r
373 Inputs:\r
374 *cptr = pointer to input string\r
375 mchar = character to match after register name\r
376 Outputs:\r
377 rnum = 0..7 if a legitimate register\r
378 < 0 if error\r
379*/\r
380\r
381int32 get_reg (char *cptr, char mchar)\r
382{\r
383int32 i;\r
384\r
385if (*(cptr + 2) != mchar) return -1;\r
386for (i = 0; i < 8; i++) {\r
387 if (strncmp (cptr, rname[i], 2) == 0) return i;\r
388 }\r
389return -1;\r
390}\r
391\r
392/* Number or memory address\r
393\r
394 Inputs:\r
395 *cptr = pointer to input string\r
396 *dptr = pointer to output displacement\r
397 *pflag = pointer to accumulating flags\r
398 Outputs:\r
399 cptr = pointer to next character in input string\r
400 NULL if parsing error\r
401\r
402 Flags: 0 (no result), A_NUM (number), A_REL (relative)\r
403*/\r
404\r
405char *get_addr (char *cptr, int32 *dptr, int32 *pflag)\r
406{\r
407int32 val, minus;\r
408char *tptr;\r
409\r
410minus = 0;\r
411\r
412if (*cptr == '.') { /* relative? */\r
413 *pflag = *pflag | A_REL;\r
414 cptr++;\r
415 }\r
416if (*cptr == '+') { /* +? */\r
417 *pflag = *pflag | A_NUM;\r
418 cptr++;\r
419 }\r
420if (*cptr == '-') { /* -? */\r
421 *pflag = *pflag | A_NUM;\r
422 minus = 1;\r
423 cptr++;\r
424 }\r
425errno = 0;\r
426val = strtoul (cptr, &tptr, 16);\r
427if (cptr == tptr) { /* no number? */\r
428 if (*pflag == (A_REL + A_NUM)) return NULL; /* .+, .-? */\r
429 *dptr = 0;\r
430 return cptr;\r
431 }\r
432if (errno || (*pflag == A_REL)) return NULL; /* .n? */\r
433*dptr = (minus? -val: val) & 0177777;\r
434*pflag = *pflag | A_NUM;\r
435return tptr;\r
436}\r
437\r
438/* Specifier decode\r
439\r
440 Inputs:\r
441 *cptr = pointer to input string\r
442 addr = current PC\r
443 n1 = 0 if no extra word used\r
444 -1 if extra word used in prior decode\r
445 *sptr = pointer to output specifier\r
446 *dptr = pointer to output displacement\r
447 Outputs:\r
448 status = = -1 extra word decoded\r
449 = 0 ok\r
450 = +1 error\r
451*/\r
452\r
453t_stat get_spec (char *cptr, int32 addr, int32 n1, int32 *sptr, int32 *dptr)\r
454{\r
455int32 reg, indir, pflag, disp;\r
456\r
457indir = 0; /* no indirect */\r
458pflag = 0;\r
459\r
460if (*cptr == '@') { /* indirect? */\r
461 indir = 010;\r
462 cptr++;\r
463 }\r
464if (*cptr == '#') { /* literal? */\r
465 pflag = pflag | A_PND;\r
466 cptr++;\r
467 }\r
468if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */\r
469 pflag = pflag | A_MIN;\r
470 cptr++;\r
471 }\r
472else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1;\r
473if (*cptr == '(') { /* register index? */\r
474 pflag = pflag | A_PAR;\r
475 if ((reg = get_reg (cptr + 1, ')')) < 0) return 1;\r
476 cptr = cptr + 4;\r
477 if (*cptr == '+') { /* autoincrement? */\r
478 pflag = pflag | A_PLS;\r
479 cptr++;\r
480 }\r
481 }\r
482else if ((reg = get_reg (cptr, 0)) >= 0) {\r
483 pflag = pflag | A_REG;\r
484 cptr = cptr + 2;\r
485 }\r
486if (*cptr != 0) return 1; /* all done? */\r
487\r
488switch (pflag) { /* case on syntax */\r
489\r
490 case A_REG: /* Rn, @Rn */\r
491 *sptr = indir + reg;\r
492 return 0;\r
493\r
494 case A_PAR: /* (Rn), @(Rn) */\r
495 if (indir) { /* @(Rn) = @0(Rn) */\r
496 *sptr = 070 + reg;\r
497 *dptr = 0;\r
498 return -1;\r
499 }\r
500 else *sptr = 010 + reg;\r
501 return 0;\r
502\r
503 case A_PAR+A_PLS: /* (Rn)+, @(Rn)+ */\r
504 *sptr = 020 + indir + reg;\r
505 return 0;\r
506\r
507 case A_MIN+A_PAR: /* -(Rn), @-(Rn) */\r
508 *sptr = 040 + indir + reg;\r
509 return 0;\r
510\r
511 case A_NUM+A_PAR: /* d(Rn), @d(Rn) */\r
512 *sptr = 060 + indir + reg;\r
513 *dptr = disp;\r
514 return -1;\r
515\r
516 case A_PND+A_REL: case A_PND+A_REL+A_NUM: /* #.+n, @#.+n */\r
517 disp = (disp + addr) & 0177777; /* fall through */\r
518 case A_PND+A_NUM: /* #n, @#n */\r
519 *sptr = 027 + indir;\r
520 *dptr = disp;\r
521 return -1;\r
522\r
523 case A_REL: case A_REL+A_NUM: /* .+n, @.+n */\r
524 *sptr = 067 + indir;\r
525 *dptr = (disp - 4 + (2 * n1)) & 0177777;\r
526 return -1;\r
527\r
528 case A_NUM: /* n, @n */\r
529 *sptr = 067 + indir;\r
530 *dptr = (disp - addr - 4 + (2 * n1)) & 0177777;\r
531 return -1;\r
532\r
533 default:\r
534 return 1;\r
535 } /* end case */\r
536}\r
537\r
538/* Symbolic input\r
539\r
540 Inputs:\r
541 *cptr = pointer to input string\r
542 addr = current PC\r
543 *uptr = pointer to unit\r
544 *val = pointer to output values\r
545 sw = switches\r
546 Outputs:\r
547 status = > 0 error code\r
548 <= 0 -number of extra words\r
549*/\r
550\r
551t_stat parse_sym_cm (char *cptr, t_addr addr, t_value *bytes, int32 sw)\r
552{\r
553int32 d, i, j, reg, spec, n1, n2, disp, pflag;\r
554int32 val[3];\r
555int32 ad32 = (int32) addr;\r
556t_stat r;\r
557char *tptr, gbuf[CBUFSIZE];\r
558\r
559if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */\r
560if (!(sw & SWMASK ('P')) || (ad32 & 1) || (ad32 > WMASK))\r
561 return SCPE_ARG;\r
562\r
563cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r
564n1 = n2 = pflag = 0;\r
565for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
566if (opcode[i] == NULL) return SCPE_ARG;\r
567val[0] = opc_val[i] & 0177777; /* get value */\r
568j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */\r
569\r
570switch (j) { /* case on class */\r
571\r
572 case I_V_NPN: /* no operand */\r
573 break;\r
574\r
575 case I_V_REG: /* register */\r
576 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
577 if ((reg = get_reg (gbuf, 0)) < 0) return SCPE_ARG;\r
578 val[0] = val[0] | reg;\r
579 break;\r
580\r
581 case I_V_3B: case I_V_6B: case I_V_8B: /* xb literal */\r
582 cptr = get_glyph (cptr, gbuf, 0); /* get literal */\r
583 d = (int32) get_uint (gbuf, 16, (1 << j) - 1, &r);\r
584 if (r != SCPE_OK) return SCPE_ARG;\r
585 val[0] = val[0] | d; /* put in place */\r
586 break;\r
587\r
588 case I_V_BR: /* cond br */\r
589 cptr = get_glyph (cptr, gbuf, 0); /* get address */\r
590 tptr = get_addr (gbuf, &disp, &pflag); /* parse */\r
591 if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG;\r
592 if ((pflag & A_REL) == 0)\r
593 disp = (disp - ad32) & 0177777;\r
594 if ((disp & 1) || (disp > 0400) && (disp < 0177402)) return SCPE_ARG;\r
595 val[0] = val[0] | (((disp - 2) >> 1) & 0377);\r
596 break;\r
597\r
598 case I_V_SOB: /* sob */\r
599 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
600 if ((reg = get_reg (gbuf, 0)) < 0) return SCPE_ARG;\r
601 val[0] = val[0] | (reg << 6);\r
602 cptr = get_glyph (cptr, gbuf, 0); /* get address */\r
603 tptr = get_addr (gbuf, &disp, &pflag); /* parse */\r
604 if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG;\r
605 if ((pflag & A_REL) == 0)\r
606 disp = (disp - ad32) & 0177777;\r
607 if ((disp & 1) || ((disp > 2) && (disp < 0177604))) return SCPE_ARG;\r
608 val[0] = val[0] | (((2 - disp) >> 1) & 077);\r
609 break;\r
610\r
611 case I_V_RSOP: /* reg, sop */\r
612 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
613 if ((reg = get_reg (gbuf, 0)) < 0) return SCPE_ARG;\r
614 val[0] = val[0] | (reg << 6); /* fall through */\r
615 case I_V_SOP: /* sop */\r
616 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
617 if ((n1 = get_spec (gbuf, ad32, 0, &spec, &val[1])) > 0)\r
618 return SCPE_ARG;\r
619 val[0] = val[0] | spec;\r
620 break;\r
621\r
622 case I_V_SOPR: /* dop, reg */\r
623 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
624 if ((n1 = get_spec (gbuf, ad32, 0, &spec, &val[1])) > 0)\r
625 return SCPE_ARG;\r
626 val[0] = val[0] | spec;\r
627 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
628 if ((reg = get_reg (gbuf, 0)) < 0) return SCPE_ARG;\r
629 val[0] = val[0] | (reg << 6);\r
630 break;\r
631\r
632 case I_V_DOP: /* double op */\r
633 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r
634 if ((n1 = get_spec (gbuf, ad32, 0, &spec, &val[1])) > 0)\r
635 return SCPE_ARG;\r
636 val[0] = val[0] | (spec << 6);\r
637 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
638 if ((n2 = get_spec (gbuf, ad32, n1, &spec, &val[1 - n1])) > 0)\r
639 return SCPE_ARG;\r
640 val[0] = val[0] | spec;\r
641 break;\r
642\r
643 case I_V_CCC: case I_V_CCS: /* cond code oper */\r
644 for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r
645 cptr = get_glyph (cptr, gbuf, 0)) {\r
646 for (i = 0; (opcode[i] != NULL) &&\r
647 (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
648 if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) ||\r
649 (opcode[i] == NULL)) return SCPE_ARG;\r
650 val[0] = val[0] | (opc_val[i] & 0177777);\r
651 }\r
652 break;\r
653\r
654 default:\r
655 return SCPE_ARG;\r
656 }\r
657\r
658if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r
659for (i = j = 0; i < 3; i++, j = j + 2) {\r
660 bytes[j] = val[i] & BMASK;\r
661 bytes[j + 1] = (val[i] >> 8) & BMASK;\r
662 }\r
663return ((2 * (n1 + n2)) - 1);\r
664}\r