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