c209104a36305ad2eb43e1063052239e8bfb0878
1 /* vax_syscm.c: PDP-11 compatibility mode symbolic decode and parse
3 Copyright (c) 1993-2006, Robert M Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
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
37 /* Warning: for literals, the class number MUST equal the field width!! */
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)
68 static const int32 masks
[] = {
69 0177777, 0177770, 0177700, 0177770,
70 0177000, 0177400, 0177700, 0177000,
71 0177400, 0170000, 0177777, 0177777,
75 static const char *opcode
[] = {
76 "HALT","WAIT","RTI","BPT",
77 "IOT","RESET","RTT","MFPT",
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",
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",
97 "MUL","DIV","ASH","ASHC",
99 "FADD","FSUB","FMUL","FDIV",
101 "MOVC","MOVRC","MOVTC",
102 "LOCC","SKPC","SCANC","SPANC",
104 "ADDN","SUBN","CMPN","CVTNL",
105 "CVTPN","CVTNP","ASHN","CVTLN",
107 "ADDP","SUBP","CMPP","CVTPL",
108 "MULP","DIVP","ASHP","CVTLP",
109 "MOVCI","MOVRCI","MOVTCI",
110 "LOCCI","SKPCI","SCANCI","SPANCI",
112 "ADDNI","SUBNI","CMPNI","CVTNLI",
113 "CVTPNI","CVTNPI","ASHNI","CVTLNI",
114 "ADDPI","SUBPI","CMPPI","CVTPLI",
115 "MULPI","DIVPI","ASHPI","CVTLPI",
117 "BPL","BMI","BHI","BLOS",
118 "BVC","BVS","BCC","BCS",
119 "BHIS","BLO", /* encode only */
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",
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
,
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
,
154 0075000+I_REG
, 0075010+I_REG
, 0075020+I_REG
, 0075030+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
,
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
,
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
,
185 static const char *rname
[] = {
186 "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC"
189 static const char r50_to_asc
[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789";
198 flag = TRUE if decoding for CPU
199 iflag = TRUE if decoding integer instruction
201 count = -number of extra words retired
204 int32
fprint_spec (FILE *of
, t_addr addr
, int32 spec
, int32 nval
)
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 };
211 mode
= ((spec
>> 3) & 07);
215 fprintf (of
, "%s", rname
[reg
]);
219 fprintf (of
, "(%s)", rname
[reg
]);
223 if (reg
!= 7) fprintf (of
, "(%s)+", rname
[reg
]);
224 else fprintf (of
, "#%-X", nval
);
228 if (reg
!= 7) fprintf (of
, "@(%s)+", rname
[reg
]);
229 else fprintf (of
, "@#%-X", nval
);
233 fprintf (of
, "-(%s)", rname
[reg
]);
237 fprintf (of
, "@-(%s)", rname
[reg
]);
241 if (reg
!= 7) fprintf (of
, "%-X(%s)", nval
, rname
[reg
]);
242 else fprintf (of
, "%-X", (nval
+ addr
+ 4) & 0177777);
246 if (reg
!= 7) fprintf (of
, "@%-X(%s)", nval
, rname
[reg
]);
247 else fprintf (of
, "@%-X", (nval
+ addr
+ 4) & 0177777);
251 return ((reg
== 07)? pcwd
[mode
]: rgwd
[mode
]);
259 *val = values to decode
260 *uptr = pointer to unit
263 return = if >= 0, error code
264 if < 0, number of extra words retired
267 t_stat
fprint_sym_cm (FILE *of
, t_addr addr
, t_value
*bytes
, int32 sw
)
269 int32 i
, j
, c1
, c2
, c3
, inst
, srcm
, srcr
, dstm
, dstr
;
270 int32 l8b
, brdisp
, wd1
;
273 for (i
= j
= 0; i
< 3; i
++, j
= j
+ 2)
274 val
[i
] = (int32
) (bytes
[j
] | (bytes
[j
+ 1] << 8));
276 if (sw
& SWMASK ('R')) { /* radix 50? */
277 if (val
[0] > 0174777) return SCPE_ARG
; /* max value */
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
]);
285 if (!(sw
& SWMASK ('P')) || (addr
& 1) || (addr
> WMASK
))
288 inst
= val
[0]; /* inst */
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 */
298 switch (j
) { /* case on class */
300 case I_V_NPN
: case I_V_CCC
: case I_V_CCS
: /* no operands */
301 fprintf (of
, "%s", opcode
[i
]);
304 case I_V_REG
: /* reg */
305 fprintf (of
, "%s %-s", opcode
[i
], rname
[dstr
]);
308 case I_V_SOP
: /* sop */
309 fprintf (of
, "%s ", opcode
[i
]);
310 wd1
= fprint_spec (of
, addr
, dstm
, val
[1]);
313 case I_V_3B
: /* 3b */
314 fprintf (of
, "%s %-X", opcode
[i
], dstr
);
317 case I_V_6B
: /* 6b */
318 fprintf (of
, "%s %-X", opcode
[i
], dstm
);
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);
327 case I_V_8B
: /* 8b */
328 fprintf (of
, "%s %-X", opcode
[i
], l8b
);
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);
337 case I_V_RSOP
: /* rsop */
338 fprintf (of
, "%s %s,", opcode
[i
], rname
[srcr
]);
339 wd1
= fprint_spec (of
, addr
, dstm
, val
[1]);
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
]);
348 case I_V_DOP
: /* dop */
349 fprintf (of
, "%s ", opcode
[i
]);
350 wd1
= fprint_spec (of
, addr
, srcm
, val
[1]);
352 wd1
+= fprint_spec (of
, addr
- wd1
- wd1
, dstm
,
357 return ((wd1
* 2) - 1);
360 return SCPE_ARG
; /* no match */
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 */
374 *cptr = pointer to input string
375 mchar = character to match after register name
377 rnum = 0..7 if a legitimate register
381 int32
get_reg (char *cptr
, char mchar
)
385 if (*(cptr
+ 2) != mchar
) return -1;
386 for (i
= 0; i
< 8; i
++) {
387 if (strncmp (cptr
, rname
[i
], 2) == 0) return i
;
392 /* Number or memory address
395 *cptr = pointer to input string
396 *dptr = pointer to output displacement
397 *pflag = pointer to accumulating flags
399 cptr = pointer to next character in input string
400 NULL if parsing error
402 Flags: 0 (no result), A_NUM (number), A_REL (relative)
405 char *get_addr (char *cptr
, int32
*dptr
, int32
*pflag
)
412 if (*cptr
== '.') { /* relative? */
413 *pflag
= *pflag
| A_REL
;
416 if (*cptr
== '+') { /* +? */
417 *pflag
= *pflag
| A_NUM
;
420 if (*cptr
== '-') { /* -? */
421 *pflag
= *pflag
| A_NUM
;
426 val
= strtoul (cptr
, &tptr
, 16);
427 if (cptr
== tptr
) { /* no number? */
428 if (*pflag
== (A_REL
+ A_NUM
)) return NULL
; /* .+, .-? */
432 if (errno
|| (*pflag
== A_REL
)) return NULL
; /* .n? */
433 *dptr
= (minus
? -val
: val
) & 0177777;
434 *pflag
= *pflag
| A_NUM
;
441 *cptr = pointer to input string
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
448 status = = -1 extra word decoded
453 t_stat
get_spec (char *cptr
, int32 addr
, int32 n1
, int32
*sptr
, int32
*dptr
)
455 int32 reg
, indir
, pflag
, disp
;
457 indir
= 0; /* no indirect */
460 if (*cptr
== '@') { /* indirect? */
464 if (*cptr
== '#') { /* literal? */
465 pflag
= pflag
| A_PND
;
468 if (strncmp (cptr
, "-(", 2) == 0) { /* autodecrement? */
469 pflag
= pflag
| A_MIN
;
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;
477 if (*cptr
== '+') { /* autoincrement? */
478 pflag
= pflag
| A_PLS
;
482 else if ((reg
= get_reg (cptr
, 0)) >= 0) {
483 pflag
= pflag
| A_REG
;
486 if (*cptr
!= 0) return 1; /* all done? */
488 switch (pflag
) { /* case on syntax */
490 case A_REG
: /* Rn, @Rn */
494 case A_PAR
: /* (Rn), @(Rn) */
495 if (indir
) { /* @(Rn) = @0(Rn) */
500 else *sptr
= 010 + reg
;
503 case A_PAR
+A_PLS
: /* (Rn)+, @(Rn)+ */
504 *sptr
= 020 + indir
+ reg
;
507 case A_MIN
+A_PAR
: /* -(Rn), @-(Rn) */
508 *sptr
= 040 + indir
+ reg
;
511 case A_NUM
+A_PAR
: /* d(Rn), @d(Rn) */
512 *sptr
= 060 + indir
+ reg
;
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 */
523 case A_REL
: case A_REL
+A_NUM
: /* .+n, @.+n */
525 *dptr
= (disp
- 4 + (2 * n1
)) & 0177777;
528 case A_NUM
: /* n, @n */
530 *dptr
= (disp
- addr
- 4 + (2 * n1
)) & 0177777;
541 *cptr = pointer to input string
543 *uptr = pointer to unit
544 *val = pointer to output values
547 status = > 0 error code
548 <= 0 -number of extra words
551 t_stat
parse_sym_cm (char *cptr
, t_addr addr
, t_value
*bytes
, int32 sw
)
553 int32 d
, i
, j
, reg
, spec
, n1
, n2
, disp
, pflag
;
555 int32 ad32
= (int32
) addr
;
557 char *tptr
, gbuf
[CBUFSIZE
];
559 if (sw
& SWMASK ('R')) return SCPE_ARG
; /* radix 50 */
560 if (!(sw
& SWMASK ('P')) || (ad32
& 1) || (ad32
> WMASK
))
563 cptr
= get_glyph (cptr
, gbuf
, 0); /* get opcode */
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 */
570 switch (j
) { /* case on class */
572 case I_V_NPN
: /* no operand */
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
;
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 */
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);
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);
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)
619 val
[0] = val
[0] | spec
;
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)
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);
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)
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)
640 val
[0] = val
[0] | spec
;
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);
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
;
663 return ((2 * (n1
+ n2
)) - 1);