First Commit of my working state
[simh.git] / S3 / s3_sys.c
1 /* s3_sys.c: IBM System/3 system interface
2
3 Copyright (c) 2001-2005, Charles E. Owen
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 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.
25 */
26
27 #include <ctype.h>
28 #include "s3_defs.h"
29
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;
36 extern DEVICE r1_dev;
37 extern DEVICE f1_dev;
38 extern DEVICE r2_dev;
39 extern DEVICE f2_dev;
40 extern UNIT cpu_unit;
41 extern REG cpu_reg[];
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);
46
47 int32 printf_sym (FILE *of, char *strg, int32 addr, uint32 *val,
48 UNIT *uptr, int32 sw);
49
50 /* SCP data structures
51
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
58 */
59
60 char sim_name[] = "System/3";
61
62 REG *sim_PC = &cpu_reg[0];
63
64 int32 sim_emax = 6;
65
66 DEVICE *sim_devices[] = {
67 &cpu_dev,
68 &pkb_dev,
69 &cdr_dev,
70 &cdp_dev,
71 &stack_dev,
72 &lpt_dev,
73 &r1_dev,
74 &f1_dev,
75 &r2_dev,
76 &f2_dev,
77 NULL
78 };
79
80 const char *sim_stop_messages[] = {
81 "Unknown error",
82 "Unknown I/O Instruction",
83 "HALT instruction",
84 "Breakpoint",
85 "Invalid Opcode",
86 "Invalid Qbyte",
87 "Invalid Address",
88 "Invalid Device Command",
89 "ATTN Card Reader"
90 };
91
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:
99 0 - (Q-byte),(R-byte)
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)
114
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.
119 */
120
121 int32 nopcode = 75;
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 */
197 "***", 0x00,0,0,0
198 };
199
200 int32 regcode[15] = { 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
201 0x80, 0xC0, 0xA0, 0x90, 0x88, 0x84, 0x82, 0x81
202 };
203
204 char regname[15][8] = { "(P2IAR)",
205 "(P1IAR)",
206 "(IAR)",
207 "(ARR)",
208 "(PSR)",
209 "(XR2)",
210 "(XR1)",
211 "(IAR0)",
212 "(IAR1)",
213 "(IAR2)",
214 "(IAR3)",
215 "(IAR4)",
216 "(IAR5)",
217 "(IAR6)",
218 "(IAR7)"
219 };
220
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.
224 */
225
226 int32 sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
227 {
228 int32 i, addr = 0, cnt = 0;
229
230 if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
231 addr = IAR[8];
232 while ((i = getc (fileref)) != EOF) {
233 M[addr] = i & 0xff;
234 addr++;
235 cnt++;
236 } /* end while */
237 printf ("%d Bytes loaded.\n", cnt);
238 return (SCPE_OK);
239 }
240
241 /* Symbolic output
242
243 Inputs:
244 *of = output stream
245 addr = current PC
246 *val = pointer to values
247 *uptr = pointer to unit
248 sw = switches
249 Outputs:
250 status = error code
251 */
252
253 int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
254 UNIT *uptr, int32 sw)
255 {
256 int32 r;
257 char strg[256];
258
259 strcpy(strg, "");
260 r = printf_sym(of, strg, addr, val, uptr, sw);
261 if (sw & SWMASK ('A'))
262 strcpy(strg, "");
263 else
264 fprintf(of, "%s", strg);
265 return (r);
266 }
267
268 int32 printf_sym (FILE *of, char *strg, int32 addr, uint32 *val,
269 UNIT *uptr, int32 sw)
270 {
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];
275 int32 blkadd;
276
277 cflag = (uptr == NULL) || (uptr == &cpu_unit);
278 c1 = val[0] & 0xff;
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) {
286 blt[j] = '.';
287 } else {
288 blt[j] = c2;
289 }
290 }
291 if (i == 0) {
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]);
297 } else {
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]);
303 }
304 }
305 return SCPE_OK; }
306 if (sw & SWMASK ('C')) {
307 c2 = ebcdic_to_ascii[c1];
308 if (c2 < 040 || c2 > 0177) {
309 sprintf(strg, "<%02X>", c1 & 0xff);
310 } else {
311 sprintf (strg, "%c", c2 & 0xff);
312 }
313 return SCPE_OK; }
314 if (!(sw & SWMASK ('M'))) return SCPE_ARG;
315
316 inst = val[0] & 0x0f;
317 len1 = (val[0] >> 6) & 3;
318 len2 = (val[0] >> 4) & 3;
319 group = (val[0] >> 4) & 0x0f;
320 qbyte = val[1];
321
322 /* Get total length of instruction */
323
324 if (group == 0x0f) {
325 oplen = 3;
326 } else {
327 oplen = 2;
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++;
332 }
333
334 /* Find which group it belongs to */
335
336 switch (group) {
337 case 0x0f:
338 groupno = 0;
339 break;
340 case 0x0c:
341 case 0x0d:
342 case 0x0e:
343 groupno = 1;
344 break;
345 case 0x03:
346 case 0x07:
347 case 0x0b:
348 groupno = 3;
349 break;
350 default:
351 groupno = 2;
352 break;
353 }
354
355 /* find the table entry */
356
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;
365 }
366 }
367
368 /* print the opcode */
369
370 if (i >= nopcode) {
371 sprintf(strg, "%02X", val[0]);
372 oplen = 1;
373 } else {
374 sprintf(bld, "%s ", opcode[i].op);
375
376 /* Extract the addresses into aaddr and baddr */
377
378 strcpy(aoperand, "ERROR");
379 strcpy(boperand, "ERROR");
380 vpos = 2;
381 aaddr = baddr = 0;
382 switch (len1) {
383 case 0:
384 baddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff);
385 sprintf(boperand, "%04X", baddr);
386 vpos = 4;
387 break;
388 case 1:
389 baddr = val[vpos] & 255;
390 sprintf(boperand, "(%02X,XR1)", baddr);
391 vpos = 3;
392 break;
393 case 2:
394 baddr = val[vpos] & 255;
395 sprintf(boperand, "(%02X,XR2)", baddr);
396 vpos = 3;
397 break;
398 default:
399 baddr = 0;
400 break;
401 }
402 switch (len2) {
403 case 0:
404 aaddr = ((val[vpos] << 8) & 0xff00) | (val[vpos + 1] & 0x00ff);
405 if (group == 0x0C || group == 0x0D || group == 0x0E)
406 sprintf(boperand, "%04X", aaddr);
407 else
408 sprintf(aoperand, "%04X", aaddr);
409 break;
410 case 1:
411 aaddr = val[vpos] & 255;
412 if (group == 0x0C || group == 0x0D || group == 0x0E)
413 sprintf(boperand, "(%02X,XR1)", aaddr);
414 else
415 sprintf(aoperand, "(%02X,XR1)", aaddr);
416 break;
417 case 2:
418 aaddr = val[vpos] & 255;
419 if (group == 0x0C || group == 0x0D || group == 0x0E)
420 sprintf(boperand, "(%02X,XR2)", aaddr);
421 else
422 sprintf(aoperand, "(%02X,XR2)", aaddr);
423 break;
424 default:
425 aaddr = 0;
426 break;
427 }
428
429 /* Display the operands in the correct format */
430
431 da = (qbyte >> 4) & 0x0f;
432 m = (qbyte >> 3) & 0x01;
433 n = (qbyte) & 0x07;
434
435 switch (opcode[i].form) {
436 case 0:
437 sprintf(bldaddr, "%02X,%02X", qbyte, val[2]);
438 break;
439 case 1:
440 if (inst == 2 || inst == 4 || inst == 5 || inst == 6) {
441 for (i = 0; i < 16; i++) {
442 if (regcode[i] == qbyte)
443 break;
444 }
445 if (i < 16) {
446 sprintf(bldaddr, "%s,%s", regname[i], boperand);
447 } else {
448 sprintf(bldaddr, "%02X,%s", qbyte, boperand);
449 }
450 } else {
451 sprintf(bldaddr, "%02X,%s", qbyte, boperand);
452 }
453 break;
454 case 2:
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);
458 break;
459 case 3:
460 if (strcmp(opcode[i].op, "JC") == 0) {
461 sprintf(bldaddr, "%04X,%02X", addr+oplen+val[2], qbyte);
462 } else {
463 sprintf(bldaddr, "%s,%02X", boperand, qbyte);
464 }
465 break;
466 case 4:
467 sprintf(bldaddr, "%d,%d,%d", da, m, n);
468 break;
469 case 5:
470 sprintf(bldaddr, "%d,%d,%d,%02X", da, m, n, val[2]);
471 break;
472 case 6:
473 sprintf(bldaddr, "%d,%d,%d,%s", da, m, n, boperand);
474 break;
475 case 7:
476 sprintf(bldaddr, "%04X", addr+oplen+val[2]);
477 break;
478 case 8:
479 sprintf(bldaddr, "%s", boperand);
480 break;
481 default:
482 sprintf(bldaddr, "%s,%s", boperand, aoperand);
483 break;
484 }
485 sprintf(strg, "%s%s", bld, bldaddr);
486 }
487
488 return -(oplen - 1);
489 }
490
491 /* Symbolic input
492
493 Inputs:
494 *cptr = pointer to input string
495 addr = current PC
496 *uptr = pointer to unit
497 *val = pointer to output values
498 sw = switches
499 Outputs:
500 status = error status
501 */
502
503 int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw)
504 {
505 int32 cflag, i = 0, j, r, oplen, addtyp, saveaddr, vptr;
506 char gbuf[CBUFSIZE];
507
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];
513 return SCPE_OK;
514 }
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];
518 return SCPE_OK;
519 }
520
521 /* An instruction: get opcode (all characters until null, comma, left paren,
522 or numeric (including spaces).
523 */
524
525 while (1) {
526 if (*cptr == ',' || *cptr == '\0' || *cptr == '(' ||
527 isdigit(*cptr))
528 break;
529 gbuf[i] = toupper(*cptr);
530 cptr++;
531 i++;
532 }
533
534 /* kill trailing spaces if any */
535 gbuf[i] = '\0';
536 for (j = i - 1; gbuf[j] == ' '; j--) {
537 gbuf[j] = '\0';
538 }
539
540 /* find opcode in table */
541 for (j = 0; j < nopcode; j++) {
542 if (strcmp(gbuf, opcode[j].op) == 0)
543 break;
544 }
545 if (j >= nopcode) /* not found */
546 return SCPE_ARG;
547
548 oplen = 2; /* start with op & q */
549
550 val[0] = opcode[j].opmask; /* store opcode right nybble */
551
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);
557 val[1] = r;
558 if (*cptr == ',') cptr++;
559 cptr = get_glyph(cptr, gbuf, 0); /* Get R Byte */
560 sscanf(gbuf, "%x", &r);
561 val[2] = r;
562 oplen = 3;
563 val[0] = 0xf0 | opcode[j].opmask;
564 break;
565 case 1:
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);
574 } else {
575 for (i = 0; i < 16; i++) {
576 if (strcmp(gbuf, regname[i]) == 0)
577 break;
578 }
579 if (i < 16) {
580 r = regcode[i];
581 } else {
582 return SCPE_ARG;
583 }
584 }
585 } else {
586 sscanf(gbuf, "%x", &r);
587 }
588 if (r > 255) return SCPE_ARG;
589 val[1] = r;
590 if (*cptr == ',') cptr++;
591 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
592 switch(addtyp) {
593 case 0:
594 val[2] = (addr >> 8) & 0x00ff;
595 val[3] = addr & 0xff;
596 oplen = 4;
597 if (opcode[j].group == 1)
598 val[0] = 0xC0 | opcode[j].opmask;
599 else
600 val[0] = 0x30 | opcode[j].opmask;
601 break;
602 case 1:
603 val[2] = addr & 0xff;
604 oplen = 3;
605 if (opcode[j].group == 1)
606 val[0] = 0xD0 | opcode[j].opmask;
607 else
608 val[0] = 0x70 | opcode[j].opmask;
609 break;
610 case 2:
611 val[2] = addr & 0xff;
612 oplen = 3;
613 if (opcode[j].group == 1)
614 val[0] = 0xE0 | opcode[j].opmask;
615 else
616 val[0] = 0xB0 | opcode[j].opmask;
617 break;
618 default:
619 return SCPE_ARG;
620 break;
621 }
622 break;
623 case 2:
624 oplen = 2;
625 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
626 switch(addtyp) {
627 case 0:
628 val[2] = (addr >> 8) & 0xff;
629 val[3] = addr & 0xff;
630 oplen += 2;
631 vptr = 4;
632 val[0] = 0x00 | opcode[j].opmask;
633 break;
634 case 1:
635 val[2] = addr & 0xff;
636 oplen += 1;
637 vptr = 3;
638 val[0] = 0x40 | opcode[j].opmask;
639 break;
640 case 2:
641 val[2] = addr & 0xff;
642 oplen += 1;
643 vptr = 3;
644 val[0] = 0x80 | opcode[j].opmask;
645 break;
646 default:
647 return SCPE_ARG;
648 break;
649 }
650 if (*cptr == ',') cptr++;
651 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
652 switch(addtyp) {
653 case 0:
654 val[vptr] = (addr >> 8) & 0xff;
655 val[vptr+1] = addr & 0xff;
656 oplen += 2;
657 break;
658 case 1:
659 val[vptr] = addr & 0xff;
660 oplen += 1;
661 val[0] = 0x10 | val[0];
662 break;
663 case 2:
664 val[vptr] = addr & 0xff;
665 oplen += 1;
666 val[0] = 0x20 | val[0];
667 break;
668 default:
669 return SCPE_ARG;
670 break;
671 }
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 */
679 val[1] = r;
680 if (*cptr == ',') cptr++;
681 break;
682 case 3:
683 saveaddr = addr;
684 if (*cptr == ',') cptr++;
685 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
686 switch(addtyp) {
687 case 0:
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)
693 return SCPE_ARG;
694 val[2] = addr - (saveaddr+3);
695 val[1] = r;
696 val[0] = 0xf0 | opcode[j].opmask;
697 oplen = 3;
698
699 } else {
700 val[2] = (addr >> 8) & 0x00ff;
701 val[3] = addr & 0xff;
702 oplen = 4;
703 if (opcode[j].group == 1)
704 val[0] = 0xC0 | opcode[j].opmask;
705 else
706 val[0] = 0x30 | opcode[j].opmask;
707 }
708 break;
709 case 1:
710 val[2] = addr & 0xff;
711 oplen = 3;
712 if (opcode[j].group == 1)
713 val[0] = 0xD0 | opcode[j].opmask;
714 else
715 val[0] = 0x70 | opcode[j].opmask;
716 break;
717 case 2:
718 val[2] = addr & 0xff;
719 oplen = 3;
720 if (opcode[j].group == 1)
721 val[0] = 0xE0 | opcode[j].opmask;
722 else
723 val[0] = 0xB0 | opcode[j].opmask;
724 break;
725 default:
726 return SCPE_ARG;
727 break;
728 }
729 if (*cptr == ',') cptr++;
730 cptr = get_glyph(cptr, gbuf, 0);
731 sscanf(gbuf, "%x", &r);
732 if (r > 255) return SCPE_ARG;
733 val[1] = r;
734 break;
735 case 4:
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;
751 val[1] |= r & 0x07;
752 val[2] = 0;
753 oplen = 3;
754 break;
755 case 5:
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;
771 val[1] |= r & 0x07;
772 if (*cptr == ',') cptr++;
773 cptr = get_glyph(cptr, gbuf, 0);
774 sscanf(gbuf, "%x", &r);
775 if (r > 255) return SCPE_ARG;
776 val[2] = r;
777 oplen = 3;
778 break;
779 case 6:
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;
794 val[1] |= r & 0x07;
795 if (*cptr == ',') cptr++;
796 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
797 switch(addtyp) {
798 case 0:
799 val[2] = (addr >> 8) & 0x00ff;
800 val[3] = addr & 0xff;
801 oplen = 4;
802 if (opcode[j].group == 1)
803 val[0] = 0xC0 | opcode[j].opmask;
804 else
805 val[0] = 0x30 | opcode[j].opmask;
806 break;
807 case 1:
808 val[2] = addr & 0xff;
809 oplen = 3;
810 if (opcode[j].group == 1)
811 val[0] = 0xD0 | opcode[j].opmask;
812 else
813 val[0] = 0x70 | opcode[j].opmask;
814 break;
815 case 2:
816 val[2] = addr & 0xff;
817 oplen = 3;
818 if (opcode[j].group == 1)
819 val[0] = 0xE0 | opcode[j].opmask;
820 else
821 val[0] = 0xB0 | opcode[j].opmask;
822 break;
823 default:
824 return SCPE_ARG;
825 break;
826 }
827 break;
828 case 7:
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;
836 oplen = 3;
837 break;
838
839 case 8:
840 if (*cptr == ',') cptr++;
841 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
842 switch(addtyp) {
843 case 0:
844 val[2] = (addr >> 8) & 0x00ff;
845 val[3] = addr & 0xff;
846 oplen = 4;
847 val[0] = 0xC0 | opcode[j].opmask;
848 break;
849 case 1:
850 val[2] = addr & 0xff;
851 oplen = 3;
852 val[0] = 0xD0 | opcode[j].opmask;
853 break;
854 case 2:
855 val[2] = addr & 0xff;
856 oplen = 3;
857 val[0] = 0xE0 | opcode[j].opmask;
858 break;
859 default:
860 return SCPE_ARG;
861 break;
862 }
863 val[1] = opcode[j].q;
864 break;
865 case 9:
866 oplen = 2;
867 val[0] = 0;
868 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
869 switch(addtyp) {
870 case 0:
871 val[2] = (addr >> 8) & 0xff;
872 val[3] = addr & 0xff;
873 oplen += 2;
874 vptr = 4;
875 val[0] = 0x00 | opcode[j].opmask;
876 break;
877 case 1:
878 val[2] = addr & 0xff;
879 oplen += 1;
880 vptr = 3;
881 val[0] = 0x40 | opcode[j].opmask;
882 break;
883 case 2:
884 val[2] = addr & 0xff;
885 oplen += 1;
886 vptr = 3;
887 val[0] = 0x80 | opcode[j].opmask;
888 break;
889 default:
890 return SCPE_ARG;
891 break;
892 }
893 if (*cptr == ',') cptr++;
894 cptr = parse_addr(cptr, gbuf, &addr, &addtyp);
895 switch(addtyp) {
896 case 0:
897 val[vptr] = (addr >> 8) & 0xff;
898 val[vptr+1] = addr & 0xff;
899 oplen += 2;
900 break;
901 case 1:
902 val[vptr] = addr & 0xff;
903 oplen += 1;
904 val[0] = 0x10 | val[0];
905 break;
906 case 2:
907 val[vptr] = addr & 0xff;
908 oplen += 1;
909 val[0] = 0x20 | val[0];
910 break;
911 default:
912 return SCPE_ARG;
913 break;
914 }
915 val[1] = opcode[j].q;
916 break;
917 default:
918 break;
919 }
920
921
922 return (-(oplen-1));
923 }
924
925 char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype)
926 {
927 int32 nybble = 0;
928 char temp[32];
929
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, ',');
936 nybble = -1;
937 if (strcmp(gbuf, "XR1)") == 0)
938 nybble = 1;
939 if (strcmp(gbuf, "XR2)") == 0)
940 nybble = 2;
941 } else { /* Direct */
942 sscanf(gbuf, "%x", addr);
943 nybble = 0;
944 }
945 *addrtype = nybble;
946 return cptr;
947 }
948