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