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