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