1 /* s3_sys.c: IBM System/3 system interface
3 Copyright (c) 2001-2005, Charles E. Owen
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 Charles E. Owen 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 Charles E. Owen.
30 extern DEVICE cpu_dev
;
31 extern DEVICE pkb_dev
;
32 extern DEVICE cdr_dev
;
33 extern DEVICE cdp_dev
;
34 extern DEVICE stack_dev
;
35 extern DEVICE lpt_dev
;
42 extern unsigned char M
[];
43 extern int32 saved_PC
, IAR
[];
44 extern char ebcdic_to_ascii
[256];
45 char *parse_addr(char *cptr
, char *gbuf
, int32
*addr
, int32
*addrtype
);
47 int32
printf_sym (FILE *of
, char *strg
, int32 addr
, uint32
*val
,
48 UNIT
*uptr
, int32 sw
);
50 /* SCP data structures
52 sim_name simulator name string
53 sim_PC pointer to saved PC register descriptor
54 sim_emax number of words needed for examine
55 sim_devices array of pointers to simulated devices
56 sim_stop_messages array of pointers to stop messages
57 sim_load binary loader
60 char sim_name
[] = "System/3";
62 REG
*sim_PC
= &cpu_reg
[0];
66 DEVICE
*sim_devices
[] = {
80 const char *sim_stop_messages
[] = {
82 "Unknown I/O Instruction",
88 "Invalid Device Command",
92 /* This is the opcode master defintion table. Each possible opcode mnemonic
93 is defined here, with enough information to translate to and from
94 symbolic to binary machine code.
95 First field is the opcode's mnemonic
96 Second field is the hex of the right nybble of the binary opcode
97 Third field is the Q code for those with implicit Q codes
98 Fourth field is the symbolic format of the operands:
100 1 - (Q-byte),(Address)
101 2 - (Address),(Address),(Qbyte)
102 3 - (Address),(Qbyte)
103 4 - (device),(modifier),(function) -- these 3 make up qbyte
104 5 - (device),(modifier),(function),(control)
105 6 - (device),(modifier),(function),(Address)
106 7 - (displacement) -- Q byte is implicit in opcode
107 8 - (address) -- Qbyte is implicit in opcode
108 9 - (Address),(Address) -- Qbyte is implicit in opcode
109 Fifth Field is the group number:
110 0 - Command Group (left op nybble is F)
111 1 - One Address Operations A (Left Nybble C, D, or E)
112 2 - Two Address Operations (Left Nybble 0,1,2,4,5,6,8,9, or A)
113 3 - One Address Operations B (left Nybble 3, 7, or B)
115 There is duplication in this table -- IBM defines different opcodes
116 that resolve to the same binary machine instruction -- e.g. JE and
117 JZ. On input this is no problem, on output, define the one you
118 want to appear first, the second will never appear on output.
122 struct opdef opcode
[75] = {
123 "HPL", 0x00,0,0,0, /* Halt Program Level */
124 "A", 0x06,0,1,3, /* Add to Register: A R,AADD */
125 "ST", 0x04,0,1,3, /* Store Register */
126 "L", 0x05,0,1,3, /* Load Register */
127 "LA", 0x02,0,1,1, /* Load Address */
128 "ZAZ", 0x04,0,2,2, /* Zero and Add Zoned */
129 "AZ", 0x06,0,2,2, /* Add Zoned Decimal */
130 "SZ", 0x07,0,2,2, /* Subtract Zoned Decimal */
131 "ALC", 0x0E,0,2,2, /* Add Logical: ALC BADD,AADD,LEN */
132 "SLC", 0x0F,0,2,2, /* Sub Logical: SLC BADD,AADD,LEN */
133 "MVC", 0x0C,0,2,2, /* Move Chars MVX BADD,AADD,LEN */
134 "ED", 0x0A,0,2,2, /* Edit: ED BADD,AADD,LEN */
135 "ITC", 0x0B,0,2,2, /* Insert Chars: ITC BADD,AADD,LEN */
136 "CLC", 0x0D,0,2,2, /* Compare Logical: CLC BADD,AADD,LEN */
137 "MVI", 0x0C,0,3,3, /* Move Immediate */
138 "SBN", 0x0A,0,3,3, /* Set Bits On */
139 "SBF", 0x0B,0,3,3, /* Set Bits Off */
140 "CLI", 0x0D,0,3,3, /* Compare Immediate */
141 "TBN", 0x08,0,3,3, /* Test Bits On */
142 "TBF", 0x09,0,3,3, /* Test Bits Off */
143 "APL", 0x01,0,4,0, /* Advance Program Level */
144 "SIO", 0x03,0,5,0, /* Start I/O */
145 "SNS", 0x00,0,6,3, /* Sense I/O */
146 "LIO", 0x01,0,6,3, /* Load I/O */
147 "TIO", 0x01,0,6,1, /* Test I/O */
148 "J", 0x02,0,7,0, /* Jump Unconditional */
149 "J", 0x02,0x87,7,0, /* Alternate J */
150 "JH", 0x02,132,7,0, /* Jump if High */
151 "JL", 0x02,130,7,0, /* Jump if Low */
152 "JE", 0x02,129,7,0, /* Jump if Equal */
153 "JNH", 0x02,4,7,0, /* Jump if Not High */
154 "JNL", 0x02,2,7,0, /* Jump if Not Low */
155 "JNE", 0x02,1,7,0, /* Jump if Not Equal */
156 "JOZ", 0x02,136,7,0, /* Jump if Overflow Zoned */
157 "JOL", 0x02,160,7,0, /* Jump if Overflow Logical */
158 "JNOZ", 0x02,8,7,0, /* Jump if No Overflow Zoned */
159 "JNOL", 0x02,32,7,0, /* Jump if No Overflow Logical */
160 "JT", 0x02,16,7,0, /* Jump if True */
161 "JF", 0x02,144,7,0, /* Jump if False */
162 "JP", 0x02,132,7,0, /* Jump if Plus */
163 "JM", 0x02,130,7,0, /* Jump if Minus */
164 "JZ", 0x02,129,7,0, /* Jump if Zero */
165 "JNP", 0x02,4,7,0, /* Jump if Not Plus */
166 "JNM", 0x02,2,7,0, /* Jump if Not Minus */
167 "JNZ", 0x02,1,7,0, /* Jump if Not Zero */
168 "NOPJ", 0x02,0x80,7,0, /* Never Jump - NOP */
169 "B", 0x00,0x00,8,1, /* Branch Unconditional */
170 "B", 0x00,0x87,8,1, /* Alternate B */
171 "BH", 0x00,0x84,8,1, /* Branch if High */
172 "BL", 0x00,0x82,8,1, /* Branch if Low */
173 "BE", 0x00,0x81,8,1, /* Branch if Equal */
174 "BNH", 0x00,0x04,8,1, /* Branch if Not High */
175 "BNL", 0x00,0x02,8,1, /* Branch if Not Low */
176 "BNE", 0x00,0x01,8,1, /* Branch if Not Equal */
177 "BOZ", 0x00,0x88,8,1, /* Branch if Overflow Zoned */
178 "BOL", 0x00,0xA0,8,1, /* Branch if Overflow Logical */
179 "BNOZ", 0x00,0x08,8,1, /* Branch if No Overflow Zoned */
180 "BNOL", 0x00,0x20,8,1, /* Branch if No Overflow Logical */
181 "BT", 0x00,0x10,8,1, /* Branch if True */
182 "BF", 0x00,0x90,8,1, /* Branch if False */
183 "BP", 0x00,0x84,8,1, /* Branch if Plus */
184 "BM", 0x00,0x82,8,1, /* Branch if Minus */
185 "BZ", 0x00,0x81,8,1, /* Branch if Zero */
186 "BNP", 0x00,0x04,8,1, /* Branch if Not Plus */
187 "BNM", 0x00,0x02,8,1, /* Branch if Not Minus */
188 "BNZ", 0x00,0x01,8,1, /* Branch if Not Zero */
189 "NOPB", 0x00,0x80,8,1, /* Never Branch - NOP */
190 "MZZ", 0x08,0,9,2, /* Move Zone to Zone */
191 "MNZ", 0x08,1,9,2, /* Move Numeric to Zone */
192 "MZN", 0x08,2,9,2, /* Move Zone to Numeric */
193 "MNN", 0x08,3,9,2, /* Move Numeric to Numeric */
194 "MVX", 0x08,0,2,2, /* Move Hex: MVX BADD,AADD,CODE */
195 "JC", 0x02,0,3,0, /* Jump on Specified Condition bits */
196 "BC", 0x00,0,3,1, /* Branch on Specified Condition */
200 int32 regcode
[15] = { 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
201 0x80, 0xC0, 0xA0, 0x90, 0x88, 0x84, 0x82, 0x81
204 char regname
[15][8] = { "(P2IAR)",
221 /* This is the binary loader. The input file is considered to be
222 a string of literal bytes with no special format. The
223 load starts at the current value of the P1IAR.
226 int32
sim_load (FILE *fileref
, char *cptr
, char *fnam
, int flag
)
228 int32 i
, addr
= 0, cnt
= 0;
230 if ((*cptr
!= 0) || (flag
!= 0)) return SCPE_ARG
;
232 while ((i
= getc (fileref
)) != EOF
) {
237 printf ("%d Bytes loaded.\n", cnt
);
246 *val = pointer to values
247 *uptr = pointer to unit
253 int32
fprint_sym (FILE *of
, int32 addr
, uint32
*val
,
254 UNIT
*uptr
, int32 sw
)
260 r
= printf_sym(of
, strg
, addr
, val
, uptr
, sw
);
261 if (sw
& SWMASK ('A'))
264 fprintf(of
, "%s", strg
);
268 int32
printf_sym (FILE *of
, char *strg
, int32 addr
, uint32
*val
,
269 UNIT
*uptr
, int32 sw
)
271 int32 cflag
, c1
, c2
, group
, len1
, len2
, inst
, aaddr
, baddr
;
272 int32 oplen
, groupno
, i
, j
, vpos
, qbyte
, da
, m
, n
;
273 char bld
[128], bldaddr
[32], boperand
[32], aoperand
[32];
274 int32 blk
[16], blt
[16];
277 cflag
= (uptr
== NULL
) || (uptr
== &cpu_unit
);
279 if (sw
& SWMASK ('A')) {
280 for (i
= 0; i
< 16; i
++) {
281 blkadd
= addr
+ (i
*16);
282 for (j
= 0; j
< 16; j
++) {
283 blk
[j
] = M
[blkadd
+j
] & 0xff;
284 c2
= ebcdic_to_ascii
[blk
[j
]];
285 if (c2
< 040 || c2
> 0177 || blk
[j
] == 07) {
292 fprintf(of
, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ",
293 blk
[0], blk
[1], blk
[2], blk
[3], blk
[4], blk
[5], blk
[6], blk
[7],
294 blk
[8], blk
[9], blk
[10], blk
[11], blk
[12], blk
[13], blk
[14], blk
[15],
295 blt
[0], blt
[1], blt
[2], blt
[3], blt
[4], blt
[5], blt
[6], blt
[7],
296 blt
[8], blt
[9], blt
[10], blt
[11], blt
[12], blt
[13], blt
[14], blt
[15]);
298 fprintf(of
, "%X\t%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X [%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c]\n ",
299 blkadd
, blk
[0], blk
[1], blk
[2], blk
[3], blk
[4], blk
[5], blk
[6], blk
[7],
300 blk
[8], blk
[9], blk
[10], blk
[11], blk
[12], blk
[13], blk
[14], blk
[15],
301 blt
[0], blt
[1], blt
[2], blt
[3], blt
[4], blt
[5], blt
[6], blt
[7],
302 blt
[8], blt
[9], blt
[10], blt
[11], blt
[12], blt
[13], blt
[14], blt
[15]);
306 if (sw
& SWMASK ('C')) {
307 c2
= ebcdic_to_ascii
[c1
];
308 if (c2
< 040 || c2
> 0177) {
309 sprintf(strg
, "<%02X>", c1
& 0xff);
311 sprintf (strg
, "%c", c2
& 0xff);
314 if (!(sw
& SWMASK ('M'))) return SCPE_ARG
;
316 inst
= val
[0] & 0x0f;
317 len1
= (val
[0] >> 6) & 3;
318 len2
= (val
[0] >> 4) & 3;
319 group
= (val
[0] >> 4) & 0x0f;
322 /* Get total length of instruction */
328 if (len1
== 0) oplen
+= 2;
329 if (len1
== 1 || len1
== 2) oplen
++;
330 if (len2
== 0) oplen
+= 2;
331 if (len2
== 1 || len2
== 2) oplen
++;
334 /* Find which group it belongs to */
355 /* find the table entry */
357 for (i
= 0; i
< nopcode
; i
++) {
358 if (opcode
[i
].form
< 7) { /* Explicit Q */
359 if (opcode
[i
].group
== groupno
&&
360 opcode
[i
].opmask
== inst
) break;
361 } else { /* Implicit Q */
362 if (opcode
[i
].group
== groupno
&&
363 opcode
[i
].opmask
== inst
&&
364 opcode
[i
].q
== qbyte
) break;
368 /* print the opcode */
371 sprintf(strg
, "%02X", val
[0]);
374 sprintf(bld
, "%s ", opcode
[i
].op
);
376 /* Extract the addresses into aaddr and baddr */
378 strcpy(aoperand
, "ERROR");
379 strcpy(boperand
, "ERROR");
384 baddr
= ((val
[vpos
] << 8) & 0xff00) | (val
[vpos
+ 1] & 0x00ff);
385 sprintf(boperand
, "%04X", baddr
);
389 baddr
= val
[vpos
] & 255;
390 sprintf(boperand
, "(%02X,XR1)", baddr
);
394 baddr
= val
[vpos
] & 255;
395 sprintf(boperand
, "(%02X,XR2)", baddr
);
404 aaddr
= ((val
[vpos
] << 8) & 0xff00) | (val
[vpos
+ 1] & 0x00ff);
405 if (group
== 0x0C || group
== 0x0D || group
== 0x0E)
406 sprintf(boperand
, "%04X", aaddr
);
408 sprintf(aoperand
, "%04X", aaddr
);
411 aaddr
= val
[vpos
] & 255;
412 if (group
== 0x0C || group
== 0x0D || group
== 0x0E)
413 sprintf(boperand
, "(%02X,XR1)", aaddr
);
415 sprintf(aoperand
, "(%02X,XR1)", aaddr
);
418 aaddr
= val
[vpos
] & 255;
419 if (group
== 0x0C || group
== 0x0D || group
== 0x0E)
420 sprintf(boperand
, "(%02X,XR2)", aaddr
);
422 sprintf(aoperand
, "(%02X,XR2)", aaddr
);
429 /* Display the operands in the correct format */
431 da
= (qbyte
>> 4) & 0x0f;
432 m
= (qbyte
>> 3) & 0x01;
435 switch (opcode
[i
].form
) {
437 sprintf(bldaddr
, "%02X,%02X", qbyte
, val
[2]);
440 if (inst
== 2 || inst
== 4 || inst
== 5 || inst
== 6) {
441 for (i
= 0; i
< 16; i
++) {
442 if (regcode
[i
] == qbyte
)
446 sprintf(bldaddr
, "%s,%s", regname
[i
], boperand
);
448 sprintf(bldaddr
, "%02X,%s", qbyte
, boperand
);
451 sprintf(bldaddr
, "%02X,%s", qbyte
, boperand
);
455 if (inst
> 9 || inst
== 4 || inst
== 6 || inst
== 7)
456 qbyte
++; /* special +1 for length display */
457 sprintf(bldaddr
, "%s,%s,%d", boperand
, aoperand
, qbyte
);
460 if (strcmp(opcode
[i
].op
, "JC") == 0) {
461 sprintf(bldaddr
, "%04X,%02X", addr
+oplen
+val
[2], qbyte
);
463 sprintf(bldaddr
, "%s,%02X", boperand
, qbyte
);
467 sprintf(bldaddr
, "%d,%d,%d", da
, m
, n
);
470 sprintf(bldaddr
, "%d,%d,%d,%02X", da
, m
, n
, val
[2]);
473 sprintf(bldaddr
, "%d,%d,%d,%s", da
, m
, n
, boperand
);
476 sprintf(bldaddr
, "%04X", addr
+oplen
+val
[2]);
479 sprintf(bldaddr
, "%s", boperand
);
482 sprintf(bldaddr
, "%s,%s", boperand
, aoperand
);
485 sprintf(strg
, "%s%s", bld
, bldaddr
);
494 *cptr = pointer to input string
496 *uptr = pointer to unit
497 *val = pointer to output values
500 status = error status
503 int32
parse_sym (char *cptr
, int32 addr
, UNIT
*uptr
, uint32
*val
, int32 sw
)
505 int32 cflag
, i
= 0, j
, r
, oplen
, addtyp
, saveaddr
, vptr
;
508 cflag
= (uptr
== NULL
) || (uptr
== &cpu_unit
);
509 while (isspace (*cptr
)) cptr
++; /* absorb spaces */
510 if ((sw
& SWMASK ('A')) || ((*cptr
== '\'') && cptr
++)) { /* ASCII char? */
511 if (cptr
[0] == 0) return SCPE_ARG
; /* must have 1 char */
512 val
[0] = (unsigned int) cptr
[0];
515 if ((sw
& SWMASK ('C')) || ((*cptr
== '"') && cptr
++)) { /* ASCII string? */
516 if (cptr
[0] == 0) return SCPE_ARG
; /* must have 1 char */
517 val
[0] = ((unsigned int) cptr
[0] << 8) + (unsigned int) cptr
[1];
521 /* An instruction: get opcode (all characters until null, comma, left paren,
522 or numeric (including spaces).
526 if (*cptr
== ',' || *cptr
== '\0' || *cptr
== '(' ||
529 gbuf
[i
] = toupper(*cptr
);
534 /* kill trailing spaces if any */
536 for (j
= i
- 1; gbuf
[j
] == ' '; j
--) {
540 /* find opcode in table */
541 for (j
= 0; j
< nopcode
; j
++) {
542 if (strcmp(gbuf
, opcode
[j
].op
) == 0)
545 if (j
>= nopcode
) /* not found */
548 oplen
= 2; /* start with op & q */
550 val
[0] = opcode
[j
].opmask
; /* store opcode right nybble */
552 switch (opcode
[j
].form
) { /* Get operands based on operand format */
553 case 0: /* Single Byte Operand */
554 if (*cptr
== ',') cptr
++;
555 cptr
= get_glyph(cptr
, gbuf
, ','); /* Get Q Byte */
556 sscanf(gbuf
, "%x", &r
);
558 if (*cptr
== ',') cptr
++;
559 cptr
= get_glyph(cptr
, gbuf
, 0); /* Get R Byte */
560 sscanf(gbuf
, "%x", &r
);
563 val
[0] = 0xf0 | opcode
[j
].opmask
;
566 if (*cptr
== ',') cptr
++;
567 cptr
= get_glyph(cptr
, gbuf
, ',');
568 if (opcode
[j
].opmask
== 2 ||
569 opcode
[j
].opmask
== 4 ||
570 opcode
[j
].opmask
== 5 ||
571 opcode
[j
].opmask
== 6) {
572 if (isdigit(gbuf
[0])) {
573 sscanf(gbuf
, "%x", &r
);
575 for (i
= 0; i
< 16; i
++) {
576 if (strcmp(gbuf
, regname
[i
]) == 0)
586 sscanf(gbuf
, "%x", &r
);
588 if (r
> 255) return SCPE_ARG
;
590 if (*cptr
== ',') cptr
++;
591 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
594 val
[2] = (addr
>> 8) & 0x00ff;
595 val
[3] = addr
& 0xff;
597 if (opcode
[j
].group
== 1)
598 val
[0] = 0xC0 | opcode
[j
].opmask
;
600 val
[0] = 0x30 | opcode
[j
].opmask
;
603 val
[2] = addr
& 0xff;
605 if (opcode
[j
].group
== 1)
606 val
[0] = 0xD0 | opcode
[j
].opmask
;
608 val
[0] = 0x70 | opcode
[j
].opmask
;
611 val
[2] = addr
& 0xff;
613 if (opcode
[j
].group
== 1)
614 val
[0] = 0xE0 | opcode
[j
].opmask
;
616 val
[0] = 0xB0 | opcode
[j
].opmask
;
625 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
628 val
[2] = (addr
>> 8) & 0xff;
629 val
[3] = addr
& 0xff;
632 val
[0] = 0x00 | opcode
[j
].opmask
;
635 val
[2] = addr
& 0xff;
638 val
[0] = 0x40 | opcode
[j
].opmask
;
641 val
[2] = addr
& 0xff;
644 val
[0] = 0x80 | opcode
[j
].opmask
;
650 if (*cptr
== ',') cptr
++;
651 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
654 val
[vptr
] = (addr
>> 8) & 0xff;
655 val
[vptr
+1] = addr
& 0xff;
659 val
[vptr
] = addr
& 0xff;
661 val
[0] = 0x10 | val
[0];
664 val
[vptr
] = addr
& 0xff;
666 val
[0] = 0x20 | val
[0];
672 if (*cptr
== ',') cptr
++;
673 cptr
= get_glyph(cptr
, gbuf
, 0);
674 sscanf(gbuf
, "%d", &r
);
675 if (opcode
[j
].opmask
> 9 ||
676 opcode
[j
].opmask
== 4 ||
677 opcode
[j
].opmask
== 6 ||
678 opcode
[j
].opmask
== 7) r
--; /* special: length -1 */
680 if (*cptr
== ',') cptr
++;
684 if (*cptr
== ',') cptr
++;
685 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
688 if (opcode
[j
].group
== 0) { /* Group 0 form 3 is JC with explicit Q */
689 if (*cptr
== ',') cptr
++;
690 cptr
= get_glyph(cptr
, gbuf
, 0);
691 sscanf(gbuf
, "%x", &r
);
692 if ((addr
- (saveaddr
+3)) > 255 || (addr
- (saveaddr
+3)) < 1)
694 val
[2] = addr
- (saveaddr
+3);
696 val
[0] = 0xf0 | opcode
[j
].opmask
;
700 val
[2] = (addr
>> 8) & 0x00ff;
701 val
[3] = addr
& 0xff;
703 if (opcode
[j
].group
== 1)
704 val
[0] = 0xC0 | opcode
[j
].opmask
;
706 val
[0] = 0x30 | opcode
[j
].opmask
;
710 val
[2] = addr
& 0xff;
712 if (opcode
[j
].group
== 1)
713 val
[0] = 0xD0 | opcode
[j
].opmask
;
715 val
[0] = 0x70 | opcode
[j
].opmask
;
718 val
[2] = addr
& 0xff;
720 if (opcode
[j
].group
== 1)
721 val
[0] = 0xE0 | opcode
[j
].opmask
;
723 val
[0] = 0xB0 | opcode
[j
].opmask
;
729 if (*cptr
== ',') cptr
++;
730 cptr
= get_glyph(cptr
, gbuf
, 0);
731 sscanf(gbuf
, "%x", &r
);
732 if (r
> 255) return SCPE_ARG
;
736 if (*cptr
== ',') cptr
++;
737 cptr
= get_glyph(cptr
, gbuf
, ',');
738 sscanf(gbuf
, "%d", &r
);
739 if (r
> 15) return SCPE_ARG
;
740 val
[1] = (r
<< 4) & 0xf0;
741 val
[0] = 0xf0 | opcode
[j
].opmask
;
742 if (*cptr
== ',') cptr
++;
743 cptr
= get_glyph(cptr
, gbuf
, ',');
744 sscanf(gbuf
, "%d", &r
);
745 if (r
> 1) return SCPE_ARG
;
746 val
[1] |= (r
<< 3) & 0x08;
747 if (*cptr
== ',') cptr
++;
748 cptr
= get_glyph(cptr
, gbuf
, 0);
749 sscanf(gbuf
, "%d", &r
);
750 if (r
> 7) return SCPE_ARG
;
756 if (*cptr
== ',') cptr
++;
757 cptr
= get_glyph(cptr
, gbuf
, ',');
758 sscanf(gbuf
, "%d", &r
);
759 if (r
> 15) return SCPE_ARG
;
760 val
[1] = (r
<< 4) & 0xf0;
761 val
[0] = 0xf0 | opcode
[j
].opmask
;
762 if (*cptr
== ',') cptr
++;
763 cptr
= get_glyph(cptr
, gbuf
, ',');
764 sscanf(gbuf
, "%d", &r
);
765 if (r
> 1) return SCPE_ARG
;
766 val
[1] |= (r
<< 3) & 0x08;
767 if (*cptr
== ',') cptr
++;
768 cptr
= get_glyph(cptr
, gbuf
, ',');
769 sscanf(gbuf
, "%d", &r
);
770 if (r
> 7) return SCPE_ARG
;
772 if (*cptr
== ',') cptr
++;
773 cptr
= get_glyph(cptr
, gbuf
, 0);
774 sscanf(gbuf
, "%x", &r
);
775 if (r
> 255) return SCPE_ARG
;
780 if (*cptr
== ',') cptr
++;
781 cptr
= get_glyph(cptr
, gbuf
, ',');
782 sscanf(gbuf
, "%d", &r
);
783 if (r
> 15) return SCPE_ARG
;
784 val
[1] = (r
<< 4) & 0xf0;
785 if (*cptr
== ',') cptr
++;
786 cptr
= get_glyph(cptr
, gbuf
, ',');
787 sscanf(gbuf
, "%d", &r
);
788 if (r
> 1) return SCPE_ARG
;
789 val
[1] |= (r
<< 3) & 0x08;
790 if (*cptr
== ',') cptr
++;
791 cptr
= get_glyph(cptr
, gbuf
, ',');
792 sscanf(gbuf
, "%d", &r
);
793 if (r
> 7) return SCPE_ARG
;
795 if (*cptr
== ',') cptr
++;
796 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
799 val
[2] = (addr
>> 8) & 0x00ff;
800 val
[3] = addr
& 0xff;
802 if (opcode
[j
].group
== 1)
803 val
[0] = 0xC0 | opcode
[j
].opmask
;
805 val
[0] = 0x30 | opcode
[j
].opmask
;
808 val
[2] = addr
& 0xff;
810 if (opcode
[j
].group
== 1)
811 val
[0] = 0xD0 | opcode
[j
].opmask
;
813 val
[0] = 0x70 | opcode
[j
].opmask
;
816 val
[2] = addr
& 0xff;
818 if (opcode
[j
].group
== 1)
819 val
[0] = 0xE0 | opcode
[j
].opmask
;
821 val
[0] = 0xB0 | opcode
[j
].opmask
;
829 if (*cptr
== ',') cptr
++;
830 cptr
= get_glyph(cptr
, gbuf
, 0);
831 sscanf(gbuf
, "%x", &r
);
832 if ((r
- (addr
+3)) > 255 || (r
- (addr
+3)) < 1) return SCPE_ARG
;
833 val
[2] = r
- (addr
+3);
834 val
[1] = opcode
[j
].q
;
835 val
[0] = 0xf0 | opcode
[j
].opmask
;
840 if (*cptr
== ',') cptr
++;
841 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
844 val
[2] = (addr
>> 8) & 0x00ff;
845 val
[3] = addr
& 0xff;
847 val
[0] = 0xC0 | opcode
[j
].opmask
;
850 val
[2] = addr
& 0xff;
852 val
[0] = 0xD0 | opcode
[j
].opmask
;
855 val
[2] = addr
& 0xff;
857 val
[0] = 0xE0 | opcode
[j
].opmask
;
863 val
[1] = opcode
[j
].q
;
868 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
871 val
[2] = (addr
>> 8) & 0xff;
872 val
[3] = addr
& 0xff;
875 val
[0] = 0x00 | opcode
[j
].opmask
;
878 val
[2] = addr
& 0xff;
881 val
[0] = 0x40 | opcode
[j
].opmask
;
884 val
[2] = addr
& 0xff;
887 val
[0] = 0x80 | opcode
[j
].opmask
;
893 if (*cptr
== ',') cptr
++;
894 cptr
= parse_addr(cptr
, gbuf
, &addr
, &addtyp
);
897 val
[vptr
] = (addr
>> 8) & 0xff;
898 val
[vptr
+1] = addr
& 0xff;
902 val
[vptr
] = addr
& 0xff;
904 val
[0] = 0x10 | val
[0];
907 val
[vptr
] = addr
& 0xff;
909 val
[0] = 0x20 | val
[0];
915 val
[1] = opcode
[j
].q
;
925 char *parse_addr(char *cptr
, char *gbuf
, int32
*addr
, int32
*addrtype
)
930 cptr
= get_glyph(cptr
, gbuf
, ',');
931 if (gbuf
[0] == '(') { /* XR relative */
932 strcpy(temp
, gbuf
+1);
933 sscanf(temp
, "%x", addr
);
934 if (*cptr
== ',') cptr
++;
935 cptr
= get_glyph(cptr
, gbuf
, ',');
937 if (strcmp(gbuf
, "XR1)") == 0)
939 if (strcmp(gbuf
, "XR2)") == 0)
941 } else { /* Direct */
942 sscanf(gbuf
, "%x", addr
);