1 /* id32_sys.c: Interdata 32b 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 25-Jan-07 RMS Fixed conflict between -h (hex) and -h (halfword)
28 18-Oct-06 RMS Re-ordered device list
29 02-Jul-04 RMS Fixed missing type in declaration
30 15-Jul-03 RMS Fixed signed/unsigned bug in get_imm
31 27-Feb-03 RMS Added relative addressing support
32 23-Dec-01 RMS Cloned from ID4 sources
33 */
34
35 #include "id_defs.h"
36 #include <ctype.h>
37
38 #define MSK_SBF 0x0100
39 #define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF))
40
41 extern DEVICE cpu_dev;
42 extern DEVICE sch_dev;
43 extern DEVICE pt_dev;
44 extern DEVICE tt_dev, ttp_dev;
45 extern DEVICE pas_dev, pasl_dev;
46 extern DEVICE lpt_dev;
47 extern DEVICE pic_dev, lfc_dev;
48 extern DEVICE dp_dev, idc_dev;
49 extern DEVICE fd_dev, mt_dev;
50 extern UNIT cpu_unit;
51 extern REG cpu_reg[];
52 extern uint32 *M;
53
54 t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
55 t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
56 extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
57 extern t_stat pt_dump (FILE *of, char *cptr, char *fnam);
58
59 /* SCP data structures and interface routines
60
61 sim_name simulator name string
62 sim_PC pointer to saved PC register descriptor
63 sim_emax number of words for examine
64 sim_devices array of pointers to simulated devices
65 sim_stop_messages array of pointers to stop messages
66 sim_load binary loader
67 */
68
69 char sim_name[] = "Interdata 32b";
70
71 REG *sim_PC = &cpu_reg[0];
72
73 int32 sim_emax = 6;
74
75 DEVICE *sim_devices[] = {
76 &cpu_dev,
77 &sch_dev,
78 &pic_dev,
79 &lfc_dev,
80 &pt_dev,
81 &tt_dev,
82 &ttp_dev,
83 &pas_dev,
84 &pasl_dev,
85 &lpt_dev,
86 &dp_dev,
87 &idc_dev,
88 &fd_dev,
89 &mt_dev,
90 NULL
91 };
92
93 const char *sim_stop_messages[] = {
94 "Unknown error",
95 "Reserved instruction",
96 "HALT instruction",
97 "Breakpoint",
98 "Wait state",
99 "Runaway VFU"
100 };
101
102 /* Binary loader -- load carriage control tape
103 Binary dump -- paper tape dump */
104
sim_load(FILE * fileref,char * cptr,char * fnam,int flag)105 t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
106 {
107 if (flag)
108 return pt_dump (fileref, cptr, fnam);
109 return lp_load (fileref, cptr, fnam);
110 }
111
112 /* Symbol tables */
113
114 #define I_V_FL 16 /* class bits */
115 #define I_M_FL 0xF /* class mask */
116 #define I_V_MR 0x0 /* mask-register */
117 #define I_V_RR 0x1 /* register-register */
118 #define I_V_R 0x2 /* register */
119 #define I_V_MX 0x3 /* mask-memory */
120 #define I_V_RX 0x4 /* register-memory */
121 #define I_V_X 0x5 /* memory */
122 #define I_V_FF 0x6 /* float reg-reg */
123 #define I_V_FX 0x7 /* float reg-mem */
124 #define I_V_SI 0x8 /* short immed */
125 #define I_V_SB 0x9 /* short branch */
126 #define I_V_SX 0xA /* short ext branch */
127 #define I_V_RI 0xB /* halfword imm */
128 #define I_V_RF 0xC /* fullword imm */
129 #define I_MR (I_V_MR << I_V_FL)
130 #define I_RR (I_V_RR << I_V_FL)
131 #define I_R (I_V_R << I_V_FL)
132 #define I_MX (I_V_MX << I_V_FL)
133 #define I_RX (I_V_RX << I_V_FL)
134 #define I_X (I_V_X << I_V_FL)
135 #define I_FF (I_V_FF << I_V_FL)
136 #define I_FX (I_V_FX << I_V_FL)
137 #define I_SI (I_V_SI << I_V_FL)
138 #define I_SB (I_V_SB << I_V_FL)
139 #define I_SX (I_V_SX << I_V_FL)
140 #define I_RI (I_V_RI << I_V_FL)
141 #define I_RF (I_V_RF << I_V_FL)
142
143 #define R_X 0 /* no R1 */
144 #define R_M 1 /* R1 mask */
145 #define R_R 2 /* R1 int reg */
146 #define R_F 3 /* R1 flt reg */
147
148 static const int32 masks[] = {
149 0xFF00, 0xFF00, 0xFFF0, 0xFF00,
150 0xFF00, 0xFFF0, 0xFF00, 0xFF00,
151 0xFF00, 0xFE00, 0xFEF0, 0xFF00,
152 0xFF00
153 };
154
155 static const uint32 r1_type[] = {
156 R_M, R_R, R_X, R_M,
157 R_R, R_X, R_F, R_F,
158 R_R, R_M, R_X, R_R,
159 R_R
160 };
161
162 static const uint32 r2_type[] = {
163 R_X, R_R, R_R, R_X,
164 R_X, R_X, R_F, R_X,
165 R_M, R_X, R_X, R_X,
166 R_X
167 };
168
169 static const char *opcode[] = {
170 "BER", "BNER","BZR", "BNZR",
171 "BPR", "BNPR","BLR", "BNLR",
172 "BMR", "BNMR","BOR", "BNOR",
173 "BCR", "BNCR","BR",
174 "BES", "BNES","BZS", "BNZS",
175 "BPS", "BNPS","BLS", "BNLS",
176 "BMS", "BNMS","BOS", "BNOS",
177 "BCS", "BNCS","BS",
178 "BE", "BNE", "BZ", "BNZ",
179 "BP", "BNP", "BL", "BNL",
180 "BM", "BNM", "BO", "BNO",
181 "BC", "BNC", "B",
182 "BALR","BTCR","BFCR",
183 "NR", "CLR", "OR", "XR",
184 "LR", "CHR", "AR", "SR",
185 "MHR", "DHR",
186 "SRLS","SLLS","CHVR",
187 "LPSWR",
188 "MR", "DR",
189 "BTBS","BTFS","BFBS","BFFS",
190 "LIS", "LCS", "AIS", "SIS",
191 "LER", "CER", "AER", "SER",
192 "MER", "DER", "FXR", "FLR",
193 "MPBSR", "PBR",
194 "EXHR",
195 "LDR", "CDR", "ADR", "SDR",
196 "MDR", "DDR", "FXDR","FLDR",
197 "STH", "BAL", "BTC", "BFC",
198 "NH", "CLH", "OH", "XH",
199 "LH", "CH", "AH", "SH",
200 "MH", "DH",
201 "ST", "AM",
202 "N", "CL", "O", "X",
203 "L", "C", "A", "S",
204 "M", "D", "CRC12","CRC16",
205 "STE", "AHM", "PB", "LRA",
206 "ATL", "ABL", "RTL", "RBL",
207 "LE", "CE", "AE", "SE",
208 "ME", "DE",
209 "STD", "STME","LME", "LHL",
210 "TBT", "SBT", "RBT", "CBT",
211 "LD", "CD", "AD", "SD",
212 "MD", "DD", "STMD","LMD",
213 "SRHLS","SLHLS","STBR","LBR",
214 "EXBR","EPSR","WBR", "RBR",
215 "WHR", "RHR", "WDR", "RDR",
216 "SSR", "OCR",
217 "BXH", "BXLE","LPSW","THI",
218 "NHI", "CLHI","OHI", "XHI",
219 "LHI", "CHI", "AHI", "SHI",
220 "SRHL","SLHL","SRHA","SLHA",
221 "STM", "LM", "STB", "LB",
222 "CLB", "AL", "WB", "RB",
223 "WH", "RH", "WD", "RD",
224 "SS", "OC",
225 "TS", "SVC", "SINT","SCP",
226 "LA", "TLATE",
227 "RRL", "RLL",
228 "SRL", "SLL", "SRA", "SLA",
229 "TI",
230 "NI", "CLI", "OI", "XI",
231 "LI", "CI", "AI", "SI",
232 NULL
233 };
234
235 static const uint32 opc_val[] = {
236 0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R,
237 0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R,
238 0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R,
239 0x0280+I_R, 0x0380+I_R, 0x0300+I_R,
240 0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX,
241 0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX,
242 0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX,
243 0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX,
244 0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X,
245 0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X,
246 0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X,
247 0x4280+I_X, 0x4380+I_X, 0x4300+I_X,
248 0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR,
249 0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR,
250 0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR,
251 0x0C00+I_RR, 0x0D00+I_RR,
252 0x1000+I_SI, 0x1100+I_SI, 0x1200+I_RR,
253 0x1800+I_RR,
254 0x1C00+I_RR, 0x1D00+I_RR,
255 0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB,
256 0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI,
257 0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF,
258 0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR,
259 0x3000+I_RR, 0x3200+I_RR,
260 0x3400+I_RR,
261 0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF,
262 0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR,
263 0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX,
264 0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX,
265 0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX,
266 0x4C00+I_RX, 0x4D00+I_RX,
267 0x5000+I_RX, 0x5100+I_RX,
268 0x5400+I_RX, 0x5500+I_RX, 0x5600+I_RX, 0x5700+I_RX,
269 0x5800+I_RX, 0x5900+I_RX, 0x5A00+I_RX, 0x5B00+I_RX,
270 0x5C00+I_RX, 0x5D00+I_RX, 0x5E00+I_RX, 0x5F00+I_RX,
271 0x6000+I_RX, 0x6100+I_RX, 0x6200+I_RX, 0x6300+I_RX,
272 0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX,
273 0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX,
274 0x6C00+I_FX, 0x6D00+I_FX,
275 0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_RX,
276 0x7400+I_RX, 0x7500+I_RX, 0x7600+I_RX, 0x7700+I_RX,
277 0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX,
278 0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX,
279 0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR,
280 0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR,
281 0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR,
282 0x9D00+I_RR, 0x9E00+I_RR,
283 0xC000+I_RX, 0xC100+I_RX, 0xC200+I_RX, 0xC300+I_RI,
284 0xC400+I_RI, 0xC500+I_RI, 0xC600+I_RI, 0xC700+I_RI,
285 0xC800+I_RI, 0xC900+I_RI, 0xCA00+I_RI, 0xCB00+I_RI,
286 0xCC00+I_RI, 0xCD00+I_RI, 0xCE00+I_RI, 0xCF00+I_RI,
287 0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX,
288 0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX,
289 0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX,
290 0xDD00+I_RX, 0xDE00+I_RX,
291 0xE000+I_RX, 0xE100+I_RX, 0xE200+I_RI, 0xE300+I_RX,
292 0xE600+I_RX, 0xE700+I_RX,
293 0xEA00+I_RI, 0xEB00+I_RI,
294 0xEC00+I_RI, 0xED00+I_RI, 0xEE00+I_RI, 0xEF00+I_RI,
295 0xF300+I_RF,
296 0xF400+I_RF, 0xF500+I_RF, 0xF600+I_RF, 0xF700+I_RF,
297 0xF800+I_RF, 0xF900+I_RF, 0xFA00+I_RF, 0xFB00+I_RF,
298 0xFFFF
299 };
300
301 /* Print an RX specifier */
302
fprint_addr(FILE * of,t_addr addr,uint32 rx,uint32 ea1,uint32 ea2)303 t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1,
304 uint32 ea2)
305 {
306 uint32 rx2;
307
308 if ((ea1 & 0xC000) == 0) { /* RX1 */
309 fprintf (of, "%-X", ea1);
310 if (rx)
311 fprintf (of, "(R%d)", rx);
312 return -3;
313 }
314 if (ea1 & 0x8000) { /* RX2 */
315 ea1 = addr + 4 + SEXT15 (ea1);
316 fprintf (of, "%-X", ea1 & VAMASK32);
317 if (rx)
318 fprintf (of, "(R%d)", rx);
319 return -3;
320 }
321 rx2 = (ea1 >> 8) & 0xF; /* RX3 */
322 fprintf (of, "%-X", ((ea1 << 16) | ea2) & VAMASK32);
323 if (rx && !rx2)
324 fprintf (of, "(R%d)", rx);
325 if (rx2)
326 fprintf (of, "(R%d,R%d)", rx, rx2);
327 return -5;
328 }
329
330 /* Symbolic decode
331
332 Inputs:
333 *of = output stream
334 addr = current PC
335 *val = values to decode
336 *uptr = pointer to unit
337 sw = switches
338 Outputs:
339 return = if >= 0, error code
340 if < 0, number of extra bytes retired
341 */
342
fprint_sym(FILE * of,t_addr addr,t_value * val,UNIT * uptr,int32 sw)343 t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
344 UNIT *uptr, int32 sw)
345 {
346 int32 bflag, c1, c2, rdx;
347 t_stat r;
348 DEVICE *dptr;
349
350 if (uptr == NULL) /* anon = CPU */
351 uptr = &cpu_unit;
352 dptr = find_dev_from_unit (uptr); /* find dev */
353 if (dptr == NULL)
354 return SCPE_IERR;
355 if (dptr->dwidth < 16) /* 8b dev? */
356 bflag = 1;
357 else bflag = 0; /* assume 16b */
358 if (sw & SWMASK ('D')) /* get radix */
359 rdx = 10;
360 else if (sw & SWMASK ('O'))
361 rdx = 8;
362 else if (sw & SWMASK ('H'))
363 rdx = 16;
364 else rdx = dptr->dradix;
365
366 if (sw & SWMASK ('A')) { /* ASCII char? */
367 if (bflag)
368 c1 = val[0] & 0x7F;
369 else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0x7F; /* get byte */
370 fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
371 return 0;
372 }
373 if (sw & SWMASK ('B')) { /* byte? */
374 if (bflag)
375 c1 = val[0] & 0xFF;
376 else c1 = (val[0] >> ((addr & 1)? 0: 8)) & 0xFF; /* get byte */
377 fprint_val (of, c1, rdx, 8, PV_RZRO);
378 return 0;
379 }
380 if (bflag) /* 16b only */
381 return SCPE_ARG;
382
383 if (sw & SWMASK ('C')) { /* string? */
384 c1 = (val[0] >> 8) & 0x7F;
385 c2 = val[0] & 0x7F;
386 fprintf (of, (c1 < 0x20)? "<%02X>": "%c", c1);
387 fprintf (of, (c2 < 0x20)? "<%02X>": "%c", c2);
388 return -1;
389 }
390 if (sw & SWMASK ('W')) { /* halfword? */
391 fprint_val (of, val[0], rdx, 16, PV_RZRO);
392 return -1;
393 }
394 if (sw & SWMASK ('M')) { /* inst format? */
395 r = fprint_sym_m (of, addr, val); /* decode inst */
396 if (r <= 0)
397 return r;
398 }
399
400 fprint_val (of, (val[0] << 16) | val[1], rdx, 32, PV_RZRO);
401 return -3;
402 }
403
404 /* Symbolic decode for -m
405
406 Inputs:
407 of = output stream
408 addr = current PC
409 *val = values to decode
410 cf = true if parsing for CPU
411 Outputs:
412 return = if >= 0, error code
413 if < 0, number of extra bytes retired
414 */
415
fprint_sym_m(FILE * of,t_addr addr,t_value * val)416 t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
417 {
418 uint32 i, j, inst, r1, r2, ea1, ea2;
419
420 inst = val[0];
421 ea1 = val[1];
422 ea2 = val[2];
423 for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
424 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
425 if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
426 r1 = (inst >> 4) & 0xF;
427 r2 = inst & 0xF;
428 fprintf (of, "%s ", opcode[i]); /* print opcode */
429 switch (j) { /* case on class */
430
431 case I_V_MR: /* mask-register */
432 fprintf (of, "%-X,R%d", r1, r2);
433 return -1;
434
435 case I_V_RR: /* register-register */
436 case I_V_FF: /* floating-floating */
437 fprintf (of, "R%d,R%d", r1, r2);
438 return -1;
439
440 case I_V_SI: /* short immediate */
441 fprintf (of, "R%d,%-X", r1, r2);
442 return -1;
443
444 case I_V_SB: /* short branch */
445 fprintf (of, "%-X,", r1);
446 case I_V_SX: /* ext short branch */
447 fprintf (of, "%-X", ((inst & MSK_SBF)?
448 (addr + r2 + r2): (addr - r2 - r2)));
449 return -1;
450
451 case I_V_R: /* register */
452 fprintf (of, "R%d", r2);
453 return -1;
454
455 case I_V_RI: /* reg-immed */
456 fprintf (of, "R%d,%-X", r1, ea1);
457 if (r2)
458 fprintf (of, "(R%d)", r2);
459 return -3;
460
461 case I_V_RF: /* reg-full imm */
462 fprintf (of, "R%d,%-X", r1, (ea1 << 16) | ea2);
463 if (r2)
464 fprintf (of, "(R%d)", r2);
465 return -5;
466
467 case I_V_MX: /* mask-memory */
468 fprintf (of, "%-X,", r1);
469 return fprint_addr (of, addr, r2, ea1, ea2);
470
471 case I_V_RX: /* register-memory */
472 case I_V_FX: /* floating-memory */
473 fprintf (of, "R%d,", r1);
474 case I_V_X: /* memory */
475 return fprint_addr (of, addr, r2, ea1, ea2);
476 } /* end case */
477 return SCPE_IERR;
478 } /* end if */
479 } /* end for */
480 return SCPE_ARG; /* no match */
481 }
482
483 /* Register number
484
485 Inputs:
486 *cptr = pointer to input string
487 **optr = pointer to pointer to next char
488 rtype = mask, integer, or float
489 Outputs:
490 rnum = output register number, -1 if error
491 */
492
get_reg(char * cptr,char ** optr,int32 rtype)493 int32 get_reg (char *cptr, char **optr, int32 rtype)
494 {
495 int32 reg;
496
497 if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
498 cptr++; /* skip */
499 if (rtype == R_M) /* cant be mask */
500 return -1;
501 }
502 if ((*cptr >= '0') && (*cptr <= '9')) {
503 reg = *cptr++ - '0';
504 if ((*cptr >= '0') && (*cptr <= '9'))
505 reg = (reg * 10) + (*cptr - '0');
506 else --cptr;
507 if (reg > 0xF)
508 return -1;
509 }
510 else if ((*cptr >= 'a') && (*cptr <= 'f'))
511 reg = (*cptr - 'a') + 10;
512 else if ((*cptr >= 'A') && (*cptr <= 'F'))
513 reg = (*cptr - 'A') + 10;
514 else return -1;
515 if ((rtype == R_F) && (reg & 1))
516 return -1;
517 *optr = cptr + 1;
518 return reg;
519 }
520
521 /* Immediate
522
523 Inputs:
524 *cptr = pointer to input string
525 *imm = pointer to output value
526 *inst = pointer to instruction
527 max = max value
528 Outputs:
529 sta = status
530 */
531
get_imm(char * cptr,uint32 * imm,uint32 * inst,uint32 max)532 t_stat get_imm (char *cptr, uint32 *imm, uint32 *inst, uint32 max)
533 {
534 char *tptr;
535 int32 idx;
536
537 errno = 0;
538 *imm = strtoul (cptr, &tptr, 16); /* get immed */
539 if (errno || (*imm > max) || (cptr == tptr))
540 return SCPE_ARG;
541 if (*tptr == '(') { /* index? */
542 if ((idx = get_reg (tptr + 1, &tptr, R_R)) < 0)
543 return SCPE_ARG;
544 if (*tptr++ != ')')
545 return SCPE_ARG;
546 *inst = *inst | idx;
547 }
548 if (*tptr != 0)
549 return SCPE_ARG;
550 return SCPE_OK;
551 }
552
553 /* Address
554
555 Inputs:
556 *cptr = pointer to input string
557 **tptr = pointer to moved pointer
558 *ea = effective address
559 addr = base address
560 Outputs:
561 status = SCPE_OK if ok, else error code
562 */
563
get_addr(char * cptr,char ** tptr,t_addr * ea,t_addr addr)564 t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_addr addr)
565 {
566 int32 sign = 1;
567
568 if (*cptr == '.') { /* relative? */
569 cptr++;
570 *ea = addr;
571 if (*cptr == '+') /* .+? */
572 cptr++;
573 else if (*cptr == '-') { /* .-? */
574 sign = -1;
575 cptr++;
576 }
577 else return SCPE_OK;
578 }
579 else *ea = 0;
580 errno = 0;
581 *ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
582 if (errno || (cptr == *tptr))
583 return SCPE_ARG;
584 return SCPE_OK;
585 }
586
587 /* Symbolic input */
588
parse_sym(char * cptr,t_addr addr,UNIT * uptr,t_value * val,int32 sw)589 t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
590 {
591 int32 bflag, by, rdx, num;
592 t_stat r;
593 DEVICE *dptr;
594
595 if (uptr == NULL) /* anon = CPU */
596 uptr = &cpu_unit;
597 dptr = find_dev_from_unit (uptr); /* find dev */
598 if (dptr == NULL)
599 return SCPE_IERR;
600 if (dptr->dwidth < 16) /* 8b dev? */
601 bflag = 1;
602 else bflag = 0; /* assume 16b */
603 if (sw & SWMASK ('D')) /* get radix */
604 rdx = 10;
605 else if (sw & SWMASK ('O'))
606 rdx = 8;
607 else if (sw & SWMASK ('H'))
608 rdx = 16;
609 else rdx = dptr->dradix;
610
611 if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
612 if (cptr[0] == 0) /* must have 1 char */
613 return SCPE_ARG;
614 if (bflag)
615 val[0] = (t_value) cptr[0];
616 else val[0] = (addr & 1)?
617 (val[0] & ~0xFF) | ((t_value) cptr[0]):
618 (val[0] & 0xFF) | (((t_value) cptr[0]) << 8);
619 return 0;
620 }
621 if (sw & SWMASK ('B')) { /* byte? */
622 by = get_uint (cptr, rdx, DMASK8, &r); /* get byte */
623 if (r != SCPE_OK)
624 return SCPE_ARG;
625 if (bflag) val[0] = by;
626 else val[0] = (addr & 1)?
627 (val[0] & ~0xFF) | by:
628 (val[0] & 0xFF) | (by << 8);
629 return 0;
630 }
631 if (bflag) /* 16b only */
632 return SCPE_ARG;
633
634 if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII chars? */
635 if (cptr[0] == 0) /* must have 1 char */
636 return SCPE_ARG;
637 val[0] = ((t_value) cptr[0] << 8) | (t_value) cptr[1];
638 return -1;
639 }
640 if (sw & SWMASK ('W')) { /* halfword? */
641 val[0] = (int32) get_uint (cptr, rdx, DMASK16, &r); /* get number */
642 if (r != SCPE_OK)
643 return r;
644 return -1;
645 }
646
647 r = parse_sym_m (cptr, addr, val); /* try to parse inst */
648 if (r <= 0)
649 return r;
650 num = (int32) get_uint (cptr, rdx, DMASK32, &r); /* get number */
651 if (r != SCPE_OK)
652 return r;
653 val[0] = (num >> 16) & DMASK16;
654 val[1] = num & DMASK16;
655 return -3;
656 }
657
658 /* Symbolic input for -m
659
660 Inputs:
661 *cptr = pointer to input string
662 addr = current PC
663 *val = pointer to output values
664 cf = true if parsing for CPU
665 Outputs:
666 status = > 0 error code
667 <= 0 -number of extra words
668 */
669
parse_sym_m(char * cptr,t_addr addr,t_value * val)670 t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
671 {
672 uint32 i, j, df, db, t, inst, vp;
673 int32 st, r1, r2, rx2;
674 t_stat r;
675 char *tptr, gbuf[CBUFSIZE];
676
677 vp = 0;
678 cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
679 for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
680 if (opcode[i] == NULL)
681 return SCPE_ARG;
682 inst = opc_val[i] & 0xFFFF; /* get value */
683 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
684 if (r1_type[j]) { /* any R1 field? */
685 cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
686 if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
687 return SCPE_ARG;
688 if (*tptr != 0)
689 return SCPE_ARG;
690 inst = inst | (r1 << 4); /* or in R1 */
691 }
692
693 cptr = get_glyph (cptr, gbuf, 0); /* get operand */
694 if (*cptr) /* should be end */
695 return SCPE_ARG;
696 switch (j) { /* case on class */
697
698 case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
699 case I_V_MR: case I_V_RR: /* mask/reg-register */
700 case I_V_R: /* register */
701 if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
702 return SCPE_ARG;
703 if (*tptr != 0)
704 return SCPE_ARG;
705 inst = inst | r2; /* or in R2 */
706 break;
707
708 case I_V_FX: /* float-memory */
709 case I_V_MX: case I_V_RX: /* mask/reg-memory */
710 case I_V_X: /* memory */
711 r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
712 if (r != SCPE_OK) /* error? */
713 return SCPE_ARG;
714 rx2 = 0; /* assume no 2nd */
715 if (*tptr == '(') { /* index? */
716 if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
717 return SCPE_ARG;
718 inst = inst | r2; /* or in R2 */
719 if (*tptr == ',') { /* 2nd index? */
720 if ((rx2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
721 return SCPE_ARG;
722 }
723 if (*tptr++ != ')') /* all done? */
724 return SCPE_ARG;
725 }
726 if (*tptr != 0)
727 return SCPE_ARG;
728 val[0] = inst; /* store inst */
729 if (rx2 == 0) { /* no 2nd? */
730 if (t < 0x4000) { /* RX1? */
731 val[1] = t; /* store ea */
732 return -3;
733 }
734 st = (t - (addr + 4)); /* displ */
735 if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */
736 t = (st & 0x7FFF) | 0x8000;
737 val[1] = t; /* store displ */
738 return -3;
739 }
740 }
741 t = (t & VAMASK32) | 0x40000000 | (rx2 << 24);
742 val[1] = (t >> 16) & DMASK16;
743 val[2] = t & DMASK16;
744 return -5;
745
746 case I_V_RI: /* 16b immediate */
747 r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */
748 if (r != SCPE_OK)
749 return r;
750 val[0] = inst;
751 val[1] = t;
752 return -3;
753
754 case I_V_RF:
755 r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */
756 if (r != SCPE_OK)
757 return r;
758 val[0] = inst;
759 val[1] = (t >> 16) & DMASK16;
760 val[2] = t & DMASK16;
761 return -5;
762
763 case I_V_SB: case I_V_SX: /* short branches */
764 r = get_addr (gbuf, &tptr, &t, addr); /* get addr */
765 if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
766 return SCPE_ARG;
767 st = t; /* signed version */
768 db = (addr - t) & 0x1F; /* back displ */
769 df = (t - addr) & 0x1F; /* fwd displ */
770 if ((t == ((addr - db) & VAMASK16)) && /* back work and */
771 ((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
772 inst = inst | (db >> 1); /* or in back displ */
773 else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
774 ((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
775 inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
776 else return SCPE_ARG;
777 } /* end case */
778
779 val[0] = inst;
780 return -1;
781 }
782