First Commit of my working state
[simh.git] / Interdata / id16_sys.c
1 /* id16_sys.c: Interdata 16b simulator interface
2
3 Copyright (c) 2000-2008, 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 04-Feb-08 RMS Modified to allow -A, -B use with 8b devices
27 18-Oct-06 RMS Re-ordered device list
28 26-Mar-04 RMS Fixed warning with -std=c99
29 27-Feb-03 RMS Added relative addressing support
30 */
31
32 #include "id_defs.h"
33 #include <ctype.h>
34
35 #define MSK_SBF 0x0100
36
37 extern DEVICE cpu_dev;
38 extern DEVICE sch_dev;
39 extern DEVICE pt_dev;
40 extern DEVICE tt_dev, ttp_dev;
41 extern DEVICE pas_dev, pasl_dev;
42 extern DEVICE lpt_dev;
43 extern DEVICE pic_dev, lfc_dev;
44 extern DEVICE dp_dev, idc_dev;
45 extern DEVICE fd_dev, mt_dev;
46 extern UNIT cpu_unit;
47 extern REG cpu_reg[];
48 extern uint16 *M;
49
50 t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
51 t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
52 extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
53 extern t_stat pt_dump (FILE *of, char *cptr, char *fnam);
54
55 /* SCP data structures and interface routines
56
57 sim_name simulator name string
58 sim_PC pointer to saved PC register descriptor
59 sim_emax number of words for examine
60 sim_devices array of pointers to simulated devices
61 sim_stop_messages array of pointers to stop messages
62 sim_load binary loader
63 */
64
65 char sim_name[] = "Interdata 16b";
66
67 REG *sim_PC = &cpu_reg[0];
68
69 int32 sim_emax = 2;
70
71 DEVICE *sim_devices[] = {
72 &cpu_dev,
73 &sch_dev,
74 &pic_dev,
75 &lfc_dev,
76 &pt_dev,
77 &tt_dev,
78 &ttp_dev,
79 &pas_dev,
80 &pasl_dev,
81 &lpt_dev,
82 &dp_dev,
83 &idc_dev,
84 &fd_dev,
85 &mt_dev,
86 NULL
87 };
88
89 const char *sim_stop_messages[] = {
90 "Unknown error",
91 "Reserved instruction",
92 "HALT instruction",
93 "Breakpoint",
94 "Wait state",
95 "Runaway VFU"
96 };
97
98 /* Binary loader -- load carriage control tape
99 Binary dump -- paper tape dump */
100
101 t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
102 {
103 if (flag) return pt_dump (fileref, cptr, fnam);
104 return lp_load (fileref, cptr, fnam);
105 }
106
107 /* Symbol tables */
108
109 #define I_V_FL 16 /* class bits */
110 #define I_M_FL 0xF /* class mask */
111 #define I_V_MR 0x0 /* mask-register */
112 #define I_V_RR 0x1 /* register-register */
113 #define I_V_R 0x2 /* register */
114 #define I_V_MX 0x3 /* mask-memory */
115 #define I_V_RX 0x4 /* register-memory */
116 #define I_V_X 0x5 /* memory */
117 #define I_V_FF 0x6 /* float reg-reg */
118 #define I_V_FX 0x7 /* float reg-mem */
119 #define I_V_SI 0x8 /* short immed */
120 #define I_V_SB 0x9 /* short branch */
121 #define I_V_SX 0xA /* short ext branch */
122 #define I_MR (I_V_MR << I_V_FL)
123 #define I_RR (I_V_RR << I_V_FL)
124 #define I_R (I_V_R << I_V_FL)
125 #define I_MX (I_V_MX << I_V_FL)
126 #define I_RX (I_V_RX << I_V_FL)
127 #define I_X (I_V_X << I_V_FL)
128 #define I_FF (I_V_FF << I_V_FL)
129 #define I_FX (I_V_FX << I_V_FL)
130 #define I_SI (I_V_SI << I_V_FL)
131 #define I_SB (I_V_SB << I_V_FL)
132 #define I_SX (I_V_SX << I_V_FL)
133
134 #define R_X 0 /* no reg */
135 #define R_M 1 /* reg mask */
136 #define R_R 2 /* reg int reg */
137 #define R_F 3 /* reg flt reg */
138
139 static const int32 masks[] = {
140 0xFF00, 0xFF00, 0xFFF0, 0xFF00,
141 0xFF00, 0xFFF0, 0xFF00, 0xFF00,
142 0xFF00, 0xFE00, 0xFEF0
143 };
144
145 static const uint32 r1_type[] = {
146 R_M, R_R, R_X, R_M,
147 R_R, R_X, R_F, R_F,
148 R_R, R_M, R_X
149 };
150
151 static const uint32 r2_type[] = {
152 R_X, R_R, R_R, R_X,
153 R_X, R_X, R_F, R_X,
154 R_M, R_X, R_X
155 };
156
157 static const char *opcode[] = {
158 "BER", "BNER","BZR", "BNZR",
159 "BPR", "BNPR","BLR", "BNLR",
160 "BMR", "BNMR","BOR", "BNOR",
161 "BCR", "BNCR","BR",
162 "BES", "BNES","BZS", "BNZS",
163 "BPS", "BNPS","BLS", "BNLS",
164 "BMS", "BNMS","BOS", "BNOS",
165 "BCS", "BNCS","BS",
166 "BE", "BNE", "BZ", "BNZ",
167 "BP", "BNP", "BL", "BNL",
168 "BM", "BNM", "BO", "BNO",
169 "BC", "BNC", "B",
170 "BALR","BTCR","BFCR",
171 "NHR", "CLHR","OHR", "XHR",
172 "LHR", "CHR", "AHR", "SHR",
173 "MHR", "DHR", "ACHR","SCHR",
174 "SETMR",
175 "BTBS","BTFS","BFBS","BFFS",
176 "LIS", "LCS", "AIS", "SIS",
177 "LER", "CER", "AER", "SER",
178 "MER", "DER", "FXR", "FLR",
179 "LPSR",
180 "LDR", "CDR", "ADR", "SDR",
181 "MDR", "DDR", "FXDR","FLDR",
182 "STH", "BAL", "BTC", "BFC",
183 "NH", "CLH", "OH", "XH",
184 "LH", "CH", "AH", "SH",
185 "MH", "DH", "ACH", "SCH",
186 "SETM",
187 "STE", "AHM",
188 "ATL", "ABL", "RTL", "RBL",
189 "LE", "CE", "AE", "SE",
190 "ME", "DE",
191 "STD", "STME","LME", "LPS",
192 "LD", "CD", "AD", "SD",
193 "MD", "DD", "STMD","LMD",
194 "SRLS","SLLS","STBR","LBR",
195 "EXBR","EPSR","WBR", "RBR",
196 "WHR", "RHR", "WDR", "RDR",
197 "MHUR","SSR", "OCR", "AIR",
198 "BXH", "BXLE","LPSW","THI",
199 "NHI", "CLHI","OHI", "XHI",
200 "LHI", "CHI", "AHI", "SHI",
201 "SRHL","SLHL","SRHA","SLHA",
202 "STM", "LM", "STB", "LB",
203 "CLB", "AL", "WB", "RB",
204 "WH", "RH", "WD", "RD",
205 "MHU", "SS", "OC", "AI",
206 "SVC", "SINT",
207 "RRL", "RLL",
208 "SRL", "SLL", "SRA", "SLA",
209 NULL
210 };
211
212 static const uint32 opc_val[] = {
213 0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R,
214 0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R,
215 0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R,
216 0x0280+I_R, 0x0380+I_R, 0x0300+I_R,
217 0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX,
218 0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX,
219 0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX,
220 0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX,
221 0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X,
222 0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X,
223 0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X,
224 0x4280+I_X, 0x4380+I_X, 0x4300+I_X,
225 0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR,
226 0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR,
227 0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR,
228 0x0C00+I_RR, 0x0D00+I_RR, 0x0E00+I_RR, 0x0F00+I_RR,
229 0x1300+I_RR,
230 0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB,
231 0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI,
232 0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF,
233 0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR,
234 0x3300+I_R,
235 0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF,
236 0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR,
237 0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX,
238 0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX,
239 0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX,
240 0x4C00+I_RX, 0x4D00+I_RX, 0x4E00+I_RX, 0x4F00+I_RX,
241 0x5300+I_RX,
242 0x6000+I_RX, 0x6100+I_RX,
243 0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX,
244 0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX,
245 0x6C00+I_FX, 0x6D00+I_FX,
246 0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_X,
247 0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX,
248 0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX,
249 0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR,
250 0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR,
251 0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR,
252 0x9C00+I_RR, 0x9D00+I_RR, 0x9E00+I_RR, 0x9F00+I_RR,
253 0xC000+I_RX, 0xC100+I_RX, 0xC200+I_X, 0xC300+I_RX,
254 0xC400+I_RX, 0xC500+I_RX, 0xC600+I_RX, 0xC700+I_RX,
255 0xC800+I_RX, 0xC900+I_RX, 0xCA00+I_RX, 0xCB00+I_RX,
256 0xCC00+I_RX, 0xCD00+I_RX, 0xCE00+I_RX, 0xCF00+I_RX,
257 0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX,
258 0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX,
259 0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX,
260 0xDC00+I_RX, 0xDD00+I_RX, 0xDE00+I_RX, 0xDF00+I_RX,
261 0xE100+I_RX, 0xE200+I_RX,
262 0xEA00+I_RX, 0xEB00+I_RX,
263 0xEC00+I_RX, 0xED00+I_RX, 0xEE00+I_RX, 0xEF00+I_RX,
264 0xFFFF
265 };
266
267 /* Symbolic decode
268
269 Inputs:
270 *of = output stream
271 addr = current PC
272 *val = values to decode
273 *uptr = pointer to unit
274 sw = switches
275 Outputs:
276 return = if >= 0, error code
277 if < 0, number of extra bytes retired
278 */
279
280 t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
281 UNIT *uptr, int32 sw)
282 {
283 int32 bflag, c1, c2, rdx;
284 t_stat r;
285 DEVICE *dptr;
286
287 if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
288 dptr = find_dev_from_unit (uptr); /* find dev */
289 if (dptr == NULL) return SCPE_IERR;
290 if (dptr->dwidth < 16) bflag = 1; /* 8b dev? */
291 else bflag = 0; /* assume 16b */
292 if (sw & SWMASK ('D')) rdx = 10; /* get radix */
293 else if (sw & SWMASK ('O')) rdx = 8;
294 else if (sw & SWMASK ('H')) rdx = 16;
295 else rdx = dptr->dradix;
296
297 if (sw & SWMASK ('A')) { /* ASCII char? */
298 if (bflag) c1 = val[0] & 0x7F;
299 else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
300 fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
301 return 0;
302 }
303 if (sw & SWMASK ('B')) { /* byte? */
304 if (bflag) c1 = val[0] & 0xFF;
305 else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
306 fprint_val (of, c1, rdx, 8, PV_RZRO);
307 return 0;
308 }
309 if (bflag) return SCPE_ARG; /* 16b only */
310
311 if (sw & SWMASK ('C')) { /* string? */
312 c1 = (val[0] >> 8) & 0x7F;
313 c2 = val[0] & 0x7F;
314 fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
315 fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
316 return -1;
317 }
318 if (sw & SWMASK ('F')) { /* fullword? */
319 fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO);
320 return -3;
321 }
322 if (sw & SWMASK ('M')) { /* inst format? */
323 r = fprint_sym_m (of, addr, val); /* decode inst */
324 if (r <= 0) return r;
325 }
326
327 fprint_val (of, val[0], rdx, 16, PV_RZRO);
328 return -1;
329 }
330
331 /* Symbolic decode for -m
332
333 Inputs:
334 of = output stream
335 addr = current PC
336 *val = values to decode
337 Outputs:
338 return = if >= 0, error code
339 if < 0, number of extra bytes retired
340 */
341
342 t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
343 {
344 uint32 i, j, inst, r1, r2, ea, vp;
345
346 vp = 0;
347 inst = val[0]; /* first 16b */
348 ea = val[1]; /* second 16b */
349 for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
350 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
351 if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
352 r1 = (inst >> 4) & 0xF;
353 r2 = inst & 0xF;
354 fprintf (of, "%s ", opcode[i]); /* print opcode */
355 switch (j) { /* case on class */
356
357 case I_V_MR: /* mask-register */
358 fprintf (of, "%-X,R%d", r1, r2);
359 return -1;
360
361 case I_V_RR: /* register-register */
362 case I_V_FF: /* floating-floating */
363 fprintf (of, "R%d,R%d", r1, r2);
364 return -1;
365
366 case I_V_SI: /* short immediate */
367 fprintf (of, "R%d,%-X", r1, r2);
368 return -1;
369
370 case I_V_SB: /* short branch */
371 fprintf (of, "%-X,", r1);
372 case I_V_SX: /* ext short branch */
373 fprintf (of, "%-X", ((inst & MSK_SBF)?
374 (addr + r2 + r2): (addr - r2 - r2)));
375 return -1;
376
377 case I_V_R: /* register */
378 fprintf (of, "R%d", r2);
379 return -1;
380
381 case I_V_MX: /* mask-memory */
382 fprintf (of, "%-X,%-X", r1, ea);
383 break;
384
385 case I_V_RX: /* register-memory */
386 case I_V_FX: /* floating-memory */
387 fprintf (of, "R%d,%-X", r1, ea);
388 break;
389
390 case I_V_X: /* memory */
391 fprintf (of, "%-X", ea);
392 break;
393 } /* end case */
394
395 if (r2) fprintf (of, "(R%d)", r2);
396 return -3;
397 } /* end if */
398 } /* end for */
399 return SCPE_ARG; /* no match */
400 }
401
402 /* Register number
403
404 Inputs:
405 *cptr = pointer to input string
406 **optr = pointer to pointer to next char
407 rtype = mask, integer, or float
408 Outputs:
409 rnum = output register number, -1 if error
410 */
411
412 int32 get_reg (char *cptr, char **optr, int32 rtype)
413 {
414 int32 reg;
415
416 if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
417 cptr++; /* skip */
418 if (rtype == R_M) return -1; /* cant be mask */
419 }
420 if ((*cptr >= '0') && (*cptr <= '9')) {
421 reg = *cptr++ - '0';
422 if ((*cptr >= '0') && (*cptr <= '9'))
423 reg = (reg * 10) + (*cptr - '0');
424 else --cptr;
425 if (reg > 0xF) return -1;
426 }
427 else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10;
428 else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10;
429 else return -1;
430 if ((rtype == R_F) && (reg & 1)) return -1;
431 *optr = cptr + 1;
432 return reg;
433 }
434
435 /* Address
436
437 Inputs:
438 *cptr = pointer to input string
439 **tptr = pointer to moved pointer
440 *ea = effective address
441 addr = base address
442 Outputs:
443 status = SCPE_OK if ok, else error code
444 */
445
446 t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr)
447 {
448 int32 sign = 1;
449
450 if (*cptr == '.') { /* relative? */
451 cptr++;
452 *ea = addr;
453 if (*cptr == '+') cptr++; /* .+? */
454 else if (*cptr == '-') { /* .-? */
455 sign = -1;
456 cptr++;
457 }
458 else return SCPE_OK;
459 }
460 else *ea = 0;
461 errno = 0;
462 *ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
463 if (errno || (cptr == *tptr)) return SCPE_ARG;
464 return SCPE_OK;
465 }
466
467 /* Symbolic input */
468
469 t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
470 {
471 int32 bflag, by, rdx, num;
472 t_stat r;
473 DEVICE *dptr;
474
475 if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
476 dptr = find_dev_from_unit (uptr); /* find dev */
477 if (dptr == NULL) return SCPE_IERR;
478 if (dptr->dwidth < 16) bflag = 1; /* 8b device? */
479 else bflag = 0; /* assume 16b */
480 if (sw & SWMASK ('D')) rdx = 10; /* get radix */
481 else if (sw & SWMASK ('O')) rdx = 8;
482 else if (sw & SWMASK ('H')) rdx = 16;
483 else rdx = dptr->dradix;
484
485 if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
486 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
487 if (bflag) val[0] = (t_value) cptr[0];
488 else val[0] = (addr & 1)?
489 (val[0] & ~0xFF) | ((t_value) cptr[0]):
490 (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
491 return 0;
492 }
493 if (sw & SWMASK ('B')) { /* byte? */
494 by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
495 if (r != SCPE_OK) return SCPE_ARG;
496 if (bflag) val[0] = by;
497 else val[0] = (addr & 1)?
498 (val[0] & ~0xFF) | by:
499 (val[0] & 0xFF) | (by << 8);
500 return 0;
501 }
502 if (bflag) return SCPE_ARG; /* 16b only */
503
504 if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */
505 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
506 val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
507 return -1;
508 }
509 if (sw & SWMASK ('F')) {
510 num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */
511 if (r != SCPE_OK) return r;
512 val[0] = (num >> 16) & DMASK16;
513 val[1] = num & DMASK16;
514 return -3;
515 }
516
517 r = parse_sym_m (cptr, addr, val); /* try to parse inst */
518 if (r <= 0) return r;
519 val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
520 if (r != SCPE_OK) return r;
521 return -1;
522 }
523
524 /* Symbolic input for -m
525
526 Inputs:
527 *cptr = pointer to input string
528 addr = current PC
529 *val = pointer to output values
530 cf = true if parsing for CPU
531 Outputs:
532 status = > 0 error code
533 <= 0 -number of extra words
534 */
535
536 t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
537 {
538 uint32 i, j, t, df, db, inst;
539 int32 st, r1, r2;
540 t_stat r;
541 char *tptr, gbuf[CBUFSIZE];
542
543 cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
544 for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
545 if (opcode[i] == NULL) return SCPE_ARG;
546 inst = opc_val[i] & 0xFFFF; /* get value */
547 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
548 if (r1_type[j]) { /* any R1 field? */
549 cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
550 if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
551 return SCPE_ARG;
552 if (*tptr != 0) return SCPE_ARG; /* all done? */
553 inst = inst | (r1 << 4); /* or in R1 */
554 }
555
556 cptr = get_glyph (cptr, gbuf, 0); /* get operand */
557 if (*cptr) return SCPE_ARG; /* should be end */
558 switch (j) { /* case on class */
559
560 case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
561 case I_V_MR: case I_V_RR: /* mask/reg-reg */
562 case I_V_R: /* register */
563 if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
564 return SCPE_ARG;
565 if (*tptr != 0) return SCPE_ARG; /* all done? */
566 inst = inst | r2; /* or in R2 */
567 break;
568
569 case I_V_FX: /* float-memory */
570 case I_V_MX: case I_V_RX: /* mask/reg-mem */
571 case I_V_X: /* memory */
572 r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
573 if ((r != SCPE_OK) || (t > PAMASK16)) return SCPE_ARG;
574 if (*tptr == '(') { /* index? */
575 if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
576 return SCPE_ARG;
577 if (*tptr++ != ')') return SCPE_ARG;
578 inst = inst | r2; /* or in R2 */
579 }
580 if (*tptr != 0) return SCPE_ARG;
581 val[0] = inst;
582 val[1] = t;
583 return -3;
584
585 case I_V_SB: case I_V_SX: /* short branches */
586 r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
587 if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
588 return SCPE_ARG;
589 st = t; /* signed version */
590 db = (addr - t) & 0x1F; /* back displ */
591 df = (t - addr) & 0x1F; /* fwd displ */
592 if ((t == ((addr - db) & VAMASK16)) && /* back work and */
593 ((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
594 inst = inst | (db >> 1); /* or in back displ */
595 else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
596 ((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
597 inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
598 else return SCPE_ARG;
599 break;
600 } /* end case */
601
602 val[0] = inst;
603 return -1;
604 }