Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* pdp11_sys.c: PDP-11 simulator interface\r |
2 | \r | |
3 | Copyright (c) 1993-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 | 15-May-08 RMS Added KE11-A, DC11 support\r | |
27 | Renamed DL11\r | |
28 | 04-Feb-08 RMS Modified to allow -A, -B use with 8b devices\r | |
29 | 25-Jan-08 RMS Added RC11, KG11A support from John Dundas\r | |
30 | 10-Sep-07 RMS Cleaned up binary loader\r | |
31 | 20-Dec-06 RMS Added TA11 support\r | |
32 | 12-Nov-06 RMS Fixed operand order in EIS instructions (found by W.F.J. Mueller)\r | |
33 | 14-Jul-06 RMS Reordered device list\r | |
34 | 06-Jul-06 RMS Added multiple KL11/DL11 support\r | |
35 | 26-Jun-06 RMS Added RF11 support\r | |
36 | 17-May-06 RMS Added CR11/CD11 support (from John Dundas)\r | |
37 | 16-Aug-05 RMS Fixed C++ declaration and cast problems\r | |
38 | 22-Jul-05 RMS Fixed missing , in initializer (from Doug Gwyn)\r | |
39 | 22-Dec-03 RMS Added second DEUNA/DELUA support\r | |
40 | 18-Oct-03 RMS Added DECtape off reel message\r | |
41 | 06-May-03 RMS Added support for second DEQNA/DELQA\r | |
42 | 09-Jan-03 RMS Added DELUA/DEUNA support\r | |
43 | 17-Oct-02 RMS Fixed bugs in branch, SOB address parsing\r | |
44 | 09-Oct-02 RMS Added DELQA support\r | |
45 | 12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine\r | |
46 | 29-Nov-01 RMS Added read only unit support\r | |
47 | 17-Sep-01 RMS Removed multiconsole support\r | |
48 | 26-Aug-01 RMS Added DZ11\r | |
49 | 20-Aug-01 RMS Updated bad block inquiry\r | |
50 | 17-Jul-01 RMS Fixed warning from VC++ 6.0\r | |
51 | 27-May-01 RMS Added multiconsole support\r | |
52 | 05-Apr-01 RMS Added support for TS11/TSV05\r | |
53 | 14-Mar-01 RMS Revised load/dump interface (again)\r | |
54 | 11-Feb-01 RMS Added DECtape support\r | |
55 | 30-Oct-00 RMS Added support for examine to file\r | |
56 | 14-Apr-99 RMS Changed t_addr to unsigned\r | |
57 | 09-Nov-98 RMS Fixed assignments of ROR/ROL (John Wilson)\r | |
58 | 27-Oct-98 RMS V2.4 load interface\r | |
59 | 08-Oct-98 RMS Fixed bug in bad block routine\r | |
60 | 30-Mar-98 RMS Fixed bug in floating point display\r | |
61 | 12-Nov-97 RMS Added bad block table routine\r | |
62 | */\r | |
63 | \r | |
64 | #include "pdp11_defs.h"\r | |
65 | #include <ctype.h>\r | |
66 | \r | |
67 | extern DEVICE cpu_dev;\r | |
68 | extern DEVICE sys_dev;\r | |
69 | extern DEVICE ptr_dev;\r | |
70 | extern DEVICE ptp_dev;\r | |
71 | extern DEVICE tti_dev;\r | |
72 | extern DEVICE tto_dev;\r | |
73 | extern DEVICE lpt_dev;\r | |
74 | extern DEVICE cr_dev;\r | |
75 | extern DEVICE clk_dev;\r | |
76 | extern DEVICE pclk_dev;\r | |
77 | extern DEVICE dli_dev;\r | |
78 | extern DEVICE dlo_dev;\r | |
79 | extern DEVICE dci_dev;\r | |
80 | extern DEVICE dco_dev;\r | |
81 | extern DEVICE dz_dev;\r | |
82 | extern DEVICE vh_dev;\r | |
83 | extern DEVICE dt_dev;\r | |
84 | extern DEVICE rc_dev;\r | |
85 | extern DEVICE rf_dev;\r | |
86 | extern DEVICE rk_dev;\r | |
87 | extern DEVICE rl_dev;\r | |
88 | extern DEVICE hk_dev;\r | |
89 | extern DEVICE rx_dev;\r | |
90 | extern DEVICE ry_dev;\r | |
91 | extern DEVICE mba_dev[];\r | |
92 | extern DEVICE rp_dev;\r | |
93 | extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;\r | |
94 | extern DEVICE tm_dev;\r | |
95 | extern DEVICE tq_dev;\r | |
96 | extern DEVICE ts_dev;\r | |
97 | extern DEVICE tu_dev;\r | |
98 | extern DEVICE ta_dev;\r | |
99 | extern DEVICE xq_dev, xqb_dev;\r | |
100 | extern DEVICE xu_dev, xub_dev;\r | |
101 | extern DEVICE ke_dev;\r | |
102 | extern DEVICE kg_dev;\r | |
103 | extern UNIT cpu_unit;\r | |
104 | extern REG cpu_reg[];\r | |
105 | extern uint16 *M;\r | |
106 | extern int32 saved_PC;\r | |
107 | \r | |
108 | /* SCP data structures and interface routines\r | |
109 | \r | |
110 | sim_name simulator name string\r | |
111 | sim_PC pointer to saved PC register descriptor\r | |
112 | sim_emax number of words for examine\r | |
113 | sim_devices array of pointers to simulated devices\r | |
114 | sim_stop_messages array of pointers to stop messages\r | |
115 | sim_load binary loader\r | |
116 | */\r | |
117 | \r | |
118 | char sim_name[] = "PDP-11";\r | |
119 | \r | |
120 | REG *sim_PC = &cpu_reg[0];\r | |
121 | \r | |
122 | int32 sim_emax = 4;\r | |
123 | \r | |
124 | DEVICE *sim_devices[] = {\r | |
125 | &cpu_dev,\r | |
126 | &sys_dev,\r | |
127 | &mba_dev[0],\r | |
128 | &mba_dev[1],\r | |
129 | &clk_dev,\r | |
130 | &pclk_dev,\r | |
131 | &ptr_dev,\r | |
132 | &ptp_dev,\r | |
133 | &tti_dev,\r | |
134 | &tto_dev,\r | |
135 | &cr_dev,\r | |
136 | &lpt_dev,\r | |
137 | &dli_dev,\r | |
138 | &dlo_dev,\r | |
139 | &dci_dev,\r | |
140 | &dco_dev,\r | |
141 | &dz_dev,\r | |
142 | &vh_dev,\r | |
143 | &rc_dev,\r | |
144 | &rf_dev,\r | |
145 | &rk_dev,\r | |
146 | &rl_dev,\r | |
147 | &hk_dev,\r | |
148 | &rx_dev,\r | |
149 | &ry_dev,\r | |
150 | &rp_dev,\r | |
151 | &rq_dev,\r | |
152 | &rqb_dev,\r | |
153 | &rqc_dev,\r | |
154 | &rqd_dev,\r | |
155 | &dt_dev,\r | |
156 | &tm_dev,\r | |
157 | &ts_dev,\r | |
158 | &tq_dev,\r | |
159 | &tu_dev,\r | |
160 | &ta_dev,\r | |
161 | &xq_dev,\r | |
162 | &xqb_dev,\r | |
163 | &xu_dev,\r | |
164 | &xub_dev,\r | |
165 | &ke_dev,\r | |
166 | &kg_dev,\r | |
167 | NULL\r | |
168 | };\r | |
169 | \r | |
170 | const char *sim_stop_messages[] = {\r | |
171 | "Unknown error",\r | |
172 | "Red stack trap",\r | |
173 | "Odd address trap",\r | |
174 | "Memory management trap",\r | |
175 | "Non-existent memory trap",\r | |
176 | "Parity error trap",\r | |
177 | "Privilege trap",\r | |
178 | "Illegal instruction trap",\r | |
179 | "BPT trap",\r | |
180 | "IOT trap",\r | |
181 | "EMT trap",\r | |
182 | "TRAP trap",\r | |
183 | "Trace trap",\r | |
184 | "Yellow stack trap",\r | |
185 | "Powerfail trap",\r | |
186 | "Floating point exception",\r | |
187 | "HALT instruction",\r | |
188 | "Breakpoint",\r | |
189 | "Wait state",\r | |
190 | "Trap vector fetch abort",\r | |
191 | "Trap stack push abort",\r | |
192 | "RQDX3 consistency error",\r | |
193 | "Sanity timer expired",\r | |
194 | "DECtape off reel"\r | |
195 | };\r | |
196 | \r | |
197 | /* Binary loader.\r | |
198 | \r | |
199 | Loader format consists of blocks, optionally preceded, separated, and\r | |
200 | followed by zeroes. Each block consists of:\r | |
201 | \r | |
202 | 001 ---\r | |
203 | xxx |\r | |
204 | lo_count |\r | |
205 | hi_count |\r | |
206 | lo_origin > count bytes\r | |
207 | hi_origin |\r | |
208 | data byte |\r | |
209 | : |\r | |
210 | data byte ---\r | |
211 | checksum\r | |
212 | \r | |
213 | If the byte count is exactly six, the block is the last on the tape, and\r | |
214 | there is no checksum. If the origin is not 000001, then the origin is\r | |
215 | the PC at which to start the program.\r | |
216 | */\r | |
217 | \r | |
218 | t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r | |
219 | {\r | |
220 | int32 c[6], d, i, cnt, csum;\r | |
221 | uint32 org;\r | |
222 | \r | |
223 | if ((*cptr != 0) || (flag != 0))\r | |
224 | return SCPE_ARG;\r | |
225 | do { /* block loop */\r | |
226 | csum = 0; /* init checksum */\r | |
227 | for (i = 0; i < 6; ) { /* 6 char header */\r | |
228 | if ((c[i] = getc (fileref)) == EOF)\r | |
229 | return SCPE_FMT;\r | |
230 | if ((i != 0) || (c[i] == 1)) /* 1st must be 1 */\r | |
231 | csum = csum + c[i++]; /* add into csum */\r | |
232 | }\r | |
233 | cnt = (c[3] << 8) | c[2]; /* count */\r | |
234 | org = (c[5] << 8) | c[4]; /* origin */\r | |
235 | if (cnt < 6) /* invalid? */\r | |
236 | return SCPE_FMT;\r | |
237 | if (cnt == 6) { /* end block? */\r | |
238 | if (org != 1) /* set PC? */\r | |
239 | saved_PC = org & 0177776;\r | |
240 | return SCPE_OK;\r | |
241 | }\r | |
242 | for (i = 6; i < cnt; i++) { /* exclude hdr */\r | |
243 | if ((d = getc (fileref)) == EOF) /* data char */\r | |
244 | return SCPE_FMT;\r | |
245 | csum = csum + d; /* add into csum */\r | |
246 | if (org >= MEMSIZE) /* invalid addr? */\r | |
247 | return SCPE_NXM;\r | |
248 | M[org >> 1] = (org & 1)? /* store data */\r | |
249 | (M[org >> 1] & 0377) | (d << 8):\r | |
250 | (M[org >> 1] & 0177400) | d;\r | |
251 | org = (org + 1) & 0177777; /* inc origin */\r | |
252 | }\r | |
253 | if ((d = getc (fileref)) == EOF) /* get csum */\r | |
254 | return SCPE_FMT;\r | |
255 | csum = csum + d; /* add in */\r | |
256 | } while ((csum & 0377) == 0); /* result mbz */\r | |
257 | return SCPE_CSUM;\r | |
258 | }\r | |
259 | \r | |
260 | /* Factory bad block table creation routine\r | |
261 | \r | |
262 | This routine writes a DEC standard 044 compliant bad block table on the\r | |
263 | last track of the specified unit. The bad block table consists of 10\r | |
264 | repetitions of the same table, formatted as follows:\r | |
265 | \r | |
266 | words 0-1 pack id number\r | |
267 | words 2-3 cylinder/sector/surface specifications\r | |
268 | :\r | |
269 | words n-n+1 end of table (-1,-1)\r | |
270 | \r | |
271 | Inputs:\r | |
272 | uptr = pointer to unit\r | |
273 | sec = number of sectors per surface\r | |
274 | wds = number of words per sector\r | |
275 | Outputs:\r | |
276 | sta = status code\r | |
277 | */\r | |
278 | \r | |
279 | t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds)\r | |
280 | {\r | |
281 | int32 i, da;\r | |
282 | uint16 *buf;\r | |
283 | \r | |
284 | if ((sec < 2) || (wds < 16))\r | |
285 | return SCPE_ARG;\r | |
286 | if ((uptr->flags & UNIT_ATT) == 0)\r | |
287 | return SCPE_UNATT;\r | |
288 | if (uptr->flags & UNIT_RO)\r | |
289 | return SCPE_RO;\r | |
290 | if (!get_yn ("Create bad block table on last track? [N]", FALSE))\r | |
291 | return SCPE_OK;\r | |
292 | da = (uptr->capac - (sec * wds)) * sizeof (uint16);\r | |
293 | if (fseek (uptr->fileref, da, SEEK_SET))\r | |
294 | return SCPE_IOERR;\r | |
295 | if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL)\r | |
296 | return SCPE_MEM;\r | |
297 | buf[0] = buf[1] = 012345u;\r | |
298 | buf[2] = buf[3] = 0;\r | |
299 | for (i = 4; i < wds; i++) buf[i] = 0177777u;\r | |
300 | for (i = 0; (i < sec) && (i < 10); i++)\r | |
301 | fxwrite (buf, sizeof (uint16), wds, uptr->fileref);\r | |
302 | free (buf);\r | |
303 | if (ferror (uptr->fileref))\r | |
304 | return SCPE_IOERR;\r | |
305 | return SCPE_OK;\r | |
306 | }\r | |
307 | \r | |
308 | /* Symbol tables */\r | |
309 | \r | |
310 | #define I_V_L 16 /* long mode */\r | |
311 | #define I_V_D 17 /* double mode */\r | |
312 | #define I_L (1 << I_V_L)\r | |
313 | #define I_D (1 << I_V_D)\r | |
314 | \r | |
315 | /* Warning: for literals, the class number MUST equal the field width!! */\r | |
316 | \r | |
317 | #define I_V_CL 18 /* class bits */\r | |
318 | #define I_M_CL 037 /* class mask */\r | |
319 | #define I_V_NPN 0 /* no operands */\r | |
320 | #define I_V_REG 1 /* reg */\r | |
321 | #define I_V_SOP 2 /* operand */\r | |
322 | #define I_V_3B 3 /* 3b literal */\r | |
323 | #define I_V_FOP 4 /* flt operand */\r | |
324 | #define I_V_AFOP 5 /* fac, flt operand */\r | |
325 | #define I_V_6B 6 /* 6b literal */\r | |
326 | #define I_V_BR 7 /* cond branch */\r | |
327 | #define I_V_8B 8 /* 8b literal */\r | |
328 | #define I_V_SOB 9 /* reg, disp */\r | |
329 | #define I_V_RSOP 10 /* reg, operand */\r | |
330 | #define I_V_ASOP 11 /* fac, operand */\r | |
331 | #define I_V_ASMD 12 /* fac, moded int op */\r | |
332 | #define I_V_DOP 13 /* double operand */\r | |
333 | #define I_V_CCC 14 /* CC clear */\r | |
334 | #define I_V_CCS 15 /* CC set */\r | |
335 | #define I_V_SOPR 16 /* operand, reg */\r | |
336 | #define I_NPN (I_V_NPN << I_V_CL)\r | |
337 | #define I_REG (I_V_REG << I_V_CL)\r | |
338 | #define I_3B (I_V_3B << I_V_CL)\r | |
339 | #define I_SOP (I_V_SOP << I_V_CL)\r | |
340 | #define I_FOP (I_V_FOP << I_V_CL)\r | |
341 | #define I_6B (I_V_6B << I_V_CL)\r | |
342 | #define I_BR (I_V_BR << I_V_CL)\r | |
343 | #define I_8B (I_V_8B << I_V_CL)\r | |
344 | #define I_AFOP (I_V_AFOP << I_V_CL)\r | |
345 | #define I_ASOP (I_V_ASOP << I_V_CL)\r | |
346 | #define I_RSOP (I_V_RSOP << I_V_CL)\r | |
347 | #define I_SOB (I_V_SOB << I_V_CL)\r | |
348 | #define I_ASMD (I_V_ASMD << I_V_CL)\r | |
349 | #define I_DOP (I_V_DOP << I_V_CL)\r | |
350 | #define I_CCC (I_V_CCC << I_V_CL)\r | |
351 | #define I_CCS (I_V_CCS << I_V_CL)\r | |
352 | #define I_SOPR (I_V_SOPR << I_V_CL)\r | |
353 | \r | |
354 | static const int32 masks[] = {\r | |
355 | 0177777, 0177770, 0177700, 0177770,\r | |
356 | 0177700+I_D, 0177400+I_D, 0177700, 0177400,\r | |
357 | 0177400, 0177000, 0177000, 0177400,\r | |
358 | 0177400+I_D+I_L, 0170000, 0177777, 0177777,\r | |
359 | 0177000\r | |
360 | };\r | |
361 | \r | |
362 | static const char *opcode[] = {\r | |
363 | "HALT","WAIT","RTI","BPT",\r | |
364 | "IOT","RESET","RTT","MFPT",\r | |
365 | "JMP","RTS","SPL",\r | |
366 | "NOP","CLC","CLV","CLV CLC",\r | |
367 | "CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC",\r | |
368 | "CLN","CLN CLC","CLN CLV","CLN CLV CLC",\r | |
369 | "CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC",\r | |
370 | "NOP","SEC","SEV","SEV SEC",\r | |
371 | "SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC",\r | |
372 | "SEN","SEN SEC","SEN SEV","SEN SEV SEC",\r | |
373 | "SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC",\r | |
374 | "SWAB","BR","BNE","BEQ",\r | |
375 | "BGE","BLT","BGT","BLE",\r | |
376 | "JSR",\r | |
377 | "CLR","COM","INC","DEC",\r | |
378 | "NEG","ADC","SBC","TST",\r | |
379 | "ROR","ROL","ASR","ASL",\r | |
380 | "MARK","MFPI","MTPI","SXT",\r | |
381 | "CSM", "TSTSET","WRTLCK",\r | |
382 | "MOV","CMP","BIT","BIC",\r | |
383 | "BIS","ADD",\r | |
384 | "MUL","DIV","ASH","ASHC",\r | |
385 | "XOR", \r | |
386 | "FADD","FSUB","FMUL","FDIV",\r | |
387 | "L2DR",\r | |
388 | "MOVC","MOVRC","MOVTC",\r | |
389 | "LOCC","SKPC","SCANC","SPANC",\r | |
390 | "CMPC","MATC",\r | |
391 | "ADDN","SUBN","CMPN","CVTNL",\r | |
392 | "CVTPN","CVTNP","ASHN","CVTLN",\r | |
393 | "L3DR",\r | |
394 | "ADDP","SUBP","CMPP","CVTPL",\r | |
395 | "MULP","DIVP","ASHP","CVTLP",\r | |
396 | "MOVCI","MOVRCI","MOVTCI",\r | |
397 | "LOCCI","SKPCI","SCANCI","SPANCI",\r | |
398 | "CMPCI","MATCI",\r | |
399 | "ADDNI","SUBNI","CMPNI","CVTNLI",\r | |
400 | "CVTPNI","CVTNPI","ASHNI","CVTLNI",\r | |
401 | "ADDPI","SUBPI","CMPPI","CVTPLI",\r | |
402 | "MULPI","DIVPI","ASHPI","CVTLPI",\r | |
403 | "SOB",\r | |
404 | "BPL","BMI","BHI","BLOS",\r | |
405 | "BVC","BVS","BCC","BCS",\r | |
406 | "BHIS","BLO", /* encode only */\r | |
407 | "EMT","TRAP",\r | |
408 | "CLRB","COMB","INCB","DECB",\r | |
409 | "NEGB","ADCB","SBCB","TSTB",\r | |
410 | "RORB","ROLB","ASRB","ASLB",\r | |
411 | "MTPS","MFPD","MTPD","MFPS",\r | |
412 | "MOVB","CMPB","BITB","BICB",\r | |
413 | "BISB","SUB",\r | |
414 | "CFCC","SETF","SETI","SETD","SETL",\r | |
415 | "LDFPS","STFPS","STST",\r | |
416 | "CLRF","CLRD","TSTF","TSTD",\r | |
417 | "ABSF","ABSD","NEGF","NEGD",\r | |
418 | "MULF","MULD","MODF","MODD",\r | |
419 | "ADDF","ADDD","LDF","LDD",\r | |
420 | "SUBF","SUBD","CMPF","CMPD",\r | |
421 | "STF","STD","DIVF","DIVD",\r | |
422 | "STEXP",\r | |
423 | "STCFI","STCDI","STCFL","STCDL",\r | |
424 | "STCFD","STCDF",\r | |
425 | "LDEXP",\r | |
426 | "LDCIF","LDCID","LDCLF","LDCLD",\r | |
427 | "LDCFD","LDCDF",\r | |
428 | NULL\r | |
429 | };\r | |
430 | \r | |
431 | static const int32 opc_val[] = {\r | |
432 | 0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN,\r | |
433 | 0000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN,\r | |
434 | 0000100+I_SOP, 0000200+I_REG, 0000230+I_3B,\r | |
435 | 0000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, \r | |
436 | 0000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, \r | |
437 | 0000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, \r | |
438 | 0000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, \r | |
439 | 0000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, \r | |
440 | 0000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, \r | |
441 | 0000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, \r | |
442 | 0000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, \r | |
443 | 0000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR,\r | |
444 | 0002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR,\r | |
445 | 0004000+I_RSOP,\r | |
446 | 0005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP,\r | |
447 | 0005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP,\r | |
448 | 0006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP,\r | |
449 | 0006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP,\r | |
450 | 0007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP,\r | |
451 | 0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP,\r | |
452 | 0050000+I_DOP, 0060000+I_DOP,\r | |
453 | 0070000+I_SOPR, 0071000+I_SOPR, 0072000+I_SOPR, 0073000+I_SOPR,\r | |
454 | 0074000+I_RSOP,\r | |
455 | 0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG,\r | |
456 | 0076020+I_REG,\r | |
457 | 0076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN,\r | |
458 | 0076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN,\r | |
459 | 0076044+I_NPN, 0076045+I_NPN, \r | |
460 | 0076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN,\r | |
461 | 0076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN,\r | |
462 | 0076060+I_REG,\r | |
463 | 0076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN,\r | |
464 | 0076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN,\r | |
465 | 0076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN,\r | |
466 | 0076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN,\r | |
467 | 0076144+I_NPN, 0076145+I_NPN, \r | |
468 | 0076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN,\r | |
469 | 0076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN,\r | |
470 | 0076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN,\r | |
471 | 0076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN,\r | |
472 | 0077000+I_SOB,\r | |
473 | 0100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR,\r | |
474 | 0102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR,\r | |
475 | 0103000+I_BR, 0103400+I_BR,\r | |
476 | 0104000+I_8B, 0104400+I_8B,\r | |
477 | 0105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP,\r | |
478 | 0105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP,\r | |
479 | 0106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP,\r | |
480 | 0106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP,\r | |
481 | 0110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP,\r | |
482 | 0150000+I_DOP, 0160000+I_DOP,\r | |
483 | 0170000+I_NPN, 0170001+I_NPN, 0170002+I_NPN, 0170011+I_NPN, 0170012+I_NPN,\r | |
484 | 0170100+I_SOP, 0170200+I_SOP, 0170300+I_SOP,\r | |
485 | 0170400+I_FOP, 0170400+I_FOP+I_D, 0170500+I_FOP, 0170500+I_FOP+I_D,\r | |
486 | 0170600+I_FOP, 0170600+I_FOP+I_D, 0170700+I_FOP, 0170700+I_FOP+I_D,\r | |
487 | 0171000+I_AFOP, 0171000+I_AFOP+I_D, 0171400+I_AFOP, 0171400+I_AFOP+I_D,\r | |
488 | 0172000+I_AFOP, 0172000+I_AFOP+I_D, 0172400+I_AFOP, 0172400+I_AFOP+I_D, \r | |
489 | 0173000+I_AFOP, 0173000+I_AFOP+I_D, 0173400+I_AFOP, 0173400+I_AFOP+I_D,\r | |
490 | 0174000+I_AFOP, 0174000+I_AFOP+I_D, 0174400+I_AFOP, 0174400+I_AFOP+I_D,\r | |
491 | 0175000+I_ASOP,\r | |
492 | 0175400+I_ASMD, 0175400+I_ASMD+I_D, 0175400+I_ASMD+I_L, 0175400+I_ASMD+I_D+I_L, \r | |
493 | 0176000+I_AFOP, 0176000+I_AFOP+I_D,\r | |
494 | 0176400+I_ASOP, \r | |
495 | 0177000+I_ASMD, 0177000+I_ASMD+I_D, 0177000+I_ASMD+I_L, 0177000+I_ASMD+I_D+I_L, \r | |
496 | 0177400+I_AFOP, 0177400+I_AFOP+I_D,\r | |
497 | -1\r | |
498 | };\r | |
499 | \r | |
500 | static const char *rname [] = {\r | |
501 | "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC"\r | |
502 | };\r | |
503 | \r | |
504 | static const char *fname [] = {\r | |
505 | "F0", "F1", "F2", "F3", "F4", "F5", "?6", "?7"\r | |
506 | };\r | |
507 | \r | |
508 | static const char r50_to_asc[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789";\r | |
509 | \r | |
510 | /* Specifier decode\r | |
511 | \r | |
512 | Inputs:\r | |
513 | *of = output stream\r | |
514 | addr = current PC\r | |
515 | spec = specifier\r | |
516 | nval = next word\r | |
517 | flag = TRUE if decoding for CPU\r | |
518 | iflag = TRUE if decoding integer instruction\r | |
519 | Outputs:\r | |
520 | count = -number of extra words retired\r | |
521 | */\r | |
522 | \r | |
523 | int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval,\r | |
524 | int32 flag, int32 iflag)\r | |
525 | {\r | |
526 | int32 reg, mode;\r | |
527 | static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 };\r | |
528 | static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 };\r | |
529 | \r | |
530 | reg = spec & 07;\r | |
531 | mode = ((spec >> 3) & 07);\r | |
532 | switch (mode) {\r | |
533 | \r | |
534 | case 0:\r | |
535 | if (iflag)\r | |
536 | fprintf (of, "%s", rname[reg]);\r | |
537 | else fprintf (of, "%s", fname[reg]);\r | |
538 | break;\r | |
539 | \r | |
540 | case 1:\r | |
541 | fprintf (of, "(%s)", rname[reg]);\r | |
542 | break;\r | |
543 | \r | |
544 | case 2:\r | |
545 | if (reg != 7)\r | |
546 | fprintf (of, "(%s)+", rname[reg]);\r | |
547 | else fprintf (of, "#%-o", nval);\r | |
548 | break;\r | |
549 | \r | |
550 | case 3:\r | |
551 | if (reg != 7)\r | |
552 | fprintf (of, "@(%s)+", rname[reg]);\r | |
553 | else fprintf (of, "@#%-o", nval);\r | |
554 | break;\r | |
555 | \r | |
556 | case 4:\r | |
557 | fprintf (of, "-(%s)", rname[reg]);\r | |
558 | break;\r | |
559 | \r | |
560 | case 5:\r | |
561 | fprintf (of, "@-(%s)", rname[reg]);\r | |
562 | break;\r | |
563 | \r | |
564 | case 6:\r | |
565 | if ((reg != 7) || !flag)\r | |
566 | fprintf (of, "%-o(%s)", nval, rname[reg]);\r | |
567 | else fprintf (of, "%-o", (nval + addr + 4) & 0177777);\r | |
568 | break;\r | |
569 | \r | |
570 | case 7:\r | |
571 | if ((reg != 7) || !flag)\r | |
572 | fprintf (of, "@%-o(%s)", nval, rname[reg]);\r | |
573 | else fprintf (of, "@%-o", (nval + addr + 4) & 0177777);\r | |
574 | break;\r | |
575 | } /* end case */\r | |
576 | \r | |
577 | return ((reg == 07)? pcwd[mode]: rgwd[mode]);\r | |
578 | }\r | |
579 | \r | |
580 | /* Symbolic decode\r | |
581 | \r | |
582 | Inputs:\r | |
583 | *of = output stream\r | |
584 | addr = current PC\r | |
585 | *val = values to decode\r | |
586 | *uptr = pointer to unit\r | |
587 | sw = switches\r | |
588 | Outputs:\r | |
589 | return = if >= 0, error code\r | |
590 | if < 0, number of extra words retired\r | |
591 | */\r | |
592 | \r | |
593 | t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r | |
594 | UNIT *uptr, int32 sw)\r | |
595 | {\r | |
596 | int32 cflag, i, j, c1, c2, c3, inst, fac, srcm, srcr, dstm, dstr;\r | |
597 | int32 bflag, l8b, brdisp, wd1, wd2;\r | |
598 | extern int32 FPS;\r | |
599 | \r | |
600 | bflag = 0; /* assume 16b */\r | |
601 | cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */\r | |
602 | if (!cflag) { /* not cpu? */\r | |
603 | DEVICE *dptr = find_dev_from_unit (uptr);\r | |
604 | if (dptr == NULL)\r | |
605 | return SCPE_IERR;\r | |
606 | if (dptr->dwidth < 16)\r | |
607 | bflag = 1;\r | |
608 | }\r | |
609 | \r | |
610 | if (sw & SWMASK ('A')) { /* ASCII? */\r | |
611 | if (bflag)\r | |
612 | c1 = val[0] & 0177;\r | |
613 | else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177;\r | |
614 | fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);\r | |
615 | return 0;\r | |
616 | }\r | |
617 | if (sw & SWMASK ('B')) { /* byte? */\r | |
618 | if (bflag)\r | |
619 | c1 = val[0] & 0177;\r | |
620 | else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377;\r | |
621 | fprintf (of, "%o", c1);\r | |
622 | return 0;\r | |
623 | }\r | |
624 | if (bflag) return SCPE_ARG; /* 16b only */\r | |
625 | \r | |
626 | if (sw & SWMASK ('C')) { /* character? */\r | |
627 | c1 = val[0] & 0177;\r | |
628 | c2 = (val[0] >> 8) & 0177;\r | |
629 | fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);\r | |
630 | fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);\r | |
631 | return -1;\r | |
632 | }\r | |
633 | if (sw & SWMASK ('R')) { /* radix 50? */\r | |
634 | if (val[0] > 0174777) return SCPE_ARG; /* max value */\r | |
635 | c3 = val[0] % 050;\r | |
636 | c2 = (val[0] / 050) % 050;\r | |
637 | c1 = val[0] / (050 * 050);\r | |
638 | fprintf (of, "%c%c%c", r50_to_asc[c1],\r | |
639 | r50_to_asc[c2], r50_to_asc[c3]);\r | |
640 | return -1;\r | |
641 | }\r | |
642 | if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r | |
643 | \r | |
644 | inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) |\r | |
645 | ((FPS << (I_V_D - FPS_V_D)) & I_D); /* inst + fp mode */\r | |
646 | for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r | |
647 | j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */\r | |
648 | if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */\r | |
649 | srcm = (inst >> 6) & 077; /* opr fields */\r | |
650 | srcr = srcm & 07;\r | |
651 | fac = srcm & 03;\r | |
652 | dstm = inst & 077;\r | |
653 | dstr = dstm & 07;\r | |
654 | l8b = inst & 0377;\r | |
655 | wd1 = wd2 = 0;\r | |
656 | switch (j) { /* case on class */\r | |
657 | \r | |
658 | case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */\r | |
659 | fprintf (of, "%s", opcode[i]);\r | |
660 | break;\r | |
661 | \r | |
662 | case I_V_REG: /* reg */\r | |
663 | fprintf (of, "%s %-s", opcode[i], rname[dstr]);\r | |
664 | break;\r | |
665 | \r | |
666 | case I_V_SOP: /* sop */\r | |
667 | fprintf (of, "%s ", opcode[i]);\r | |
668 | wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r | |
669 | break;\r | |
670 | \r | |
671 | case I_V_3B: /* 3b */\r | |
672 | fprintf (of, "%s %-o", opcode[i], dstr);\r | |
673 | break;\r | |
674 | \r | |
675 | case I_V_FOP: /* fop */\r | |
676 | fprintf (of, "%s ", opcode[i]);\r | |
677 | wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE);\r | |
678 | break;\r | |
679 | \r | |
680 | case I_V_AFOP: /* afop */\r | |
681 | fprintf (of, "%s %s,", opcode[i], fname[fac]);\r | |
682 | wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE);\r | |
683 | break;\r | |
684 | \r | |
685 | case I_V_6B: /* 6b */\r | |
686 | fprintf (of, "%s %-o", opcode[i], dstm);\r | |
687 | break;\r | |
688 | \r | |
689 | case I_V_BR: /* cond branch */\r | |
690 | fprintf (of, "%s ", opcode[i]);\r | |
691 | brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;\r | |
692 | if (cflag)\r | |
693 | fprintf (of, "%-o", (addr + brdisp) & 0177777);\r | |
694 | else if (brdisp < 01000)\r | |
695 | fprintf (of, ".+%-o", brdisp);\r | |
696 | else fprintf (of, ".-%-o", 0200000 - brdisp);\r | |
697 | break;\r | |
698 | \r | |
699 | case I_V_8B: /* 8b */\r | |
700 | fprintf (of, "%s %-o", opcode[i], l8b);\r | |
701 | break;\r | |
702 | \r | |
703 | case I_V_SOB: /* sob */\r | |
704 | fprintf (of, "%s %s,", opcode[i], rname[srcr]);\r | |
705 | brdisp = (dstm * 2) - 2;\r | |
706 | if (cflag)\r | |
707 | fprintf (of, "%-o", (addr - brdisp) & 0177777);\r | |
708 | else if (brdisp <= 0)\r | |
709 | fprintf (of, ".+%-o", -brdisp);\r | |
710 | else fprintf (of, ".-%-o", brdisp);\r | |
711 | break;\r | |
712 | \r | |
713 | case I_V_RSOP: /* rsop */\r | |
714 | fprintf (of, "%s %s,", opcode[i], rname[srcr]);\r | |
715 | wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r | |
716 | break;\r | |
717 | \r | |
718 | case I_V_SOPR: /* sopr */\r | |
719 | fprintf (of, "%s ", opcode[i]);\r | |
720 | wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r | |
721 | fprintf (of, ",%s", rname[srcr]);\r | |
722 | break;\r | |
723 | \r | |
724 | case I_V_ASOP: case I_V_ASMD: /* asop, asmd */\r | |
725 | fprintf (of, "%s %s,", opcode[i], fname[fac]);\r | |
726 | wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE);\r | |
727 | break;\r | |
728 | \r | |
729 | case I_V_DOP: /* dop */\r | |
730 | fprintf (of, "%s ", opcode[i]);\r | |
731 | wd1 = fprint_spec (of, addr, srcm, val[1], cflag, TRUE);\r | |
732 | fprintf (of, ",");\r | |
733 | wd2 = fprint_spec (of, addr - wd1 - wd1, dstm,\r | |
734 | val[1 - wd1], cflag, TRUE);\r | |
735 | break;\r | |
736 | } /* end case */\r | |
737 | return ((wd1 + wd2) * 2) - 1;\r | |
738 | } /* end if */\r | |
739 | } /* end for */\r | |
740 | return SCPE_ARG; /* no match */\r | |
741 | }\r | |
742 | \r | |
743 | #define A_PND 100 /* # seen */\r | |
744 | #define A_MIN 040 /* -( seen */\r | |
745 | #define A_PAR 020 /* (Rn) seen */\r | |
746 | #define A_REG 010 /* Rn seen */\r | |
747 | #define A_PLS 004 /* + seen */\r | |
748 | #define A_NUM 002 /* number seen */\r | |
749 | #define A_REL 001 /* relative addr seen */\r | |
750 | \r | |
751 | /* Register number\r | |
752 | \r | |
753 | Inputs:\r | |
754 | *cptr = pointer to input string\r | |
755 | *strings = pointer to register names\r | |
756 | mchar = character to match after register name\r | |
757 | Outputs:\r | |
758 | rnum = 0..7 if a legitimate register\r | |
759 | < 0 if error\r | |
760 | */\r | |
761 | \r | |
762 | int32 get_reg (char *cptr, const char *strings[], char mchar)\r | |
763 | {\r | |
764 | int32 i;\r | |
765 | \r | |
766 | if (*(cptr + 2) != mchar) return -1;\r | |
767 | for (i = 0; i < 8; i++) {\r | |
768 | if (strncmp (cptr, strings[i], 2) == 0)\r | |
769 | return i;\r | |
770 | }\r | |
771 | return -1;\r | |
772 | }\r | |
773 | \r | |
774 | /* Number or memory address\r | |
775 | \r | |
776 | Inputs:\r | |
777 | *cptr = pointer to input string\r | |
778 | *dptr = pointer to output displacement\r | |
779 | *pflag = pointer to accumulating flags\r | |
780 | Outputs:\r | |
781 | cptr = pointer to next character in input string\r | |
782 | NULL if parsing error\r | |
783 | \r | |
784 | Flags: 0 (no result), A_NUM (number), A_REL (relative)\r | |
785 | */\r | |
786 | \r | |
787 | char *get_addr (char *cptr, int32 *dptr, int32 *pflag)\r | |
788 | {\r | |
789 | int32 val, minus;\r | |
790 | char *tptr;\r | |
791 | \r | |
792 | minus = 0;\r | |
793 | \r | |
794 | if (*cptr == '.') { /* relative? */\r | |
795 | *pflag = *pflag | A_REL;\r | |
796 | cptr++;\r | |
797 | }\r | |
798 | if (*cptr == '+') { /* +? */\r | |
799 | *pflag = *pflag | A_NUM;\r | |
800 | cptr++;\r | |
801 | }\r | |
802 | if (*cptr == '-') { /* -? */\r | |
803 | *pflag = *pflag | A_NUM;\r | |
804 | minus = 1;\r | |
805 | cptr++;\r | |
806 | }\r | |
807 | errno = 0;\r | |
808 | val = strtoul (cptr, &tptr, 8);\r | |
809 | if (cptr == tptr) { /* no number? */\r | |
810 | if (*pflag == (A_REL + A_NUM)) /* .+, .-? */\r | |
811 | return NULL;\r | |
812 | *dptr = 0;\r | |
813 | return cptr;\r | |
814 | }\r | |
815 | if (errno || (*pflag == A_REL)) /* .n? */\r | |
816 | return NULL;\r | |
817 | *dptr = (minus? -val: val) & 0177777;\r | |
818 | *pflag = *pflag | A_NUM;\r | |
819 | return tptr;\r | |
820 | }\r | |
821 | \r | |
822 | /* Specifier decode\r | |
823 | \r | |
824 | Inputs:\r | |
825 | *cptr = pointer to input string\r | |
826 | addr = current PC\r | |
827 | n1 = 0 if no extra word used\r | |
828 | -1 if extra word used in prior decode\r | |
829 | *sptr = pointer to output specifier\r | |
830 | *dptr = pointer to output displacement\r | |
831 | cflag = true if parsing for the CPU\r | |
832 | iflag = true if integer specifier\r | |
833 | Outputs:\r | |
834 | status = = -1 extra word decoded\r | |
835 | = 0 ok\r | |
836 | = +1 error\r | |
837 | */\r | |
838 | \r | |
839 | t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr,\r | |
840 | int32 cflag, int32 iflag)\r | |
841 | {\r | |
842 | int32 reg, indir, pflag, disp;\r | |
843 | \r | |
844 | indir = 0; /* no indirect */\r | |
845 | pflag = 0;\r | |
846 | \r | |
847 | if (*cptr == '@') { /* indirect? */\r | |
848 | indir = 010;\r | |
849 | cptr++;\r | |
850 | }\r | |
851 | if (*cptr == '#') { /* literal? */\r | |
852 | pflag = pflag | A_PND;\r | |
853 | cptr++;\r | |
854 | }\r | |
855 | if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */\r | |
856 | pflag = pflag | A_MIN;\r | |
857 | cptr++;\r | |
858 | }\r | |
859 | else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1;\r | |
860 | if (*cptr == '(') { /* register index? */\r | |
861 | pflag = pflag | A_PAR;\r | |
862 | if ((reg = get_reg (cptr + 1, rname, ')')) < 0)\r | |
863 | return 1;\r | |
864 | cptr = cptr + 4;\r | |
865 | if (*cptr == '+') { /* autoincrement? */\r | |
866 | pflag = pflag | A_PLS;\r | |
867 | cptr++;\r | |
868 | }\r | |
869 | }\r | |
870 | else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) {\r | |
871 | pflag = pflag | A_REG;\r | |
872 | cptr = cptr + 2;\r | |
873 | }\r | |
874 | if (*cptr != 0) /* all done? */\r | |
875 | return 1;\r | |
876 | switch (pflag) { /* case on syntax */\r | |
877 | \r | |
878 | case A_REG: /* Rn, @Rn */\r | |
879 | *sptr = indir + reg;\r | |
880 | return 0;\r | |
881 | \r | |
882 | case A_PAR: /* (Rn), @(Rn) */\r | |
883 | if (indir) { /* @(Rn) = @0(Rn) */\r | |
884 | *sptr = 070 + reg;\r | |
885 | *dptr = 0;\r | |
886 | return -1;\r | |
887 | }\r | |
888 | else *sptr = 010 + reg;\r | |
889 | return 0;\r | |
890 | \r | |
891 | case A_PAR+A_PLS: /* (Rn)+, @(Rn)+ */\r | |
892 | *sptr = 020 + indir + reg;\r | |
893 | return 0;\r | |
894 | \r | |
895 | case A_MIN+A_PAR: /* -(Rn), @-(Rn) */\r | |
896 | *sptr = 040 + indir + reg;\r | |
897 | return 0;\r | |
898 | \r | |
899 | case A_NUM+A_PAR: /* d(Rn), @d(Rn) */\r | |
900 | *sptr = 060 + indir + reg;\r | |
901 | *dptr = disp;\r | |
902 | return -1;\r | |
903 | \r | |
904 | case A_PND+A_REL: case A_PND+A_REL+A_NUM: /* #.+n, @#.+n */\r | |
905 | if (!cflag)\r | |
906 | return 1;\r | |
907 | disp = (disp + addr) & 0177777; /* fall through */\r | |
908 | case A_PND+A_NUM: /* #n, @#n */\r | |
909 | *sptr = 027 + indir;\r | |
910 | *dptr = disp;\r | |
911 | return -1;\r | |
912 | \r | |
913 | case A_REL: case A_REL+A_NUM: /* .+n, @.+n */\r | |
914 | *sptr = 067 + indir;\r | |
915 | *dptr = (disp - 4 + (2 * n1)) & 0177777;\r | |
916 | return -1;\r | |
917 | \r | |
918 | case A_NUM: /* n, @n */\r | |
919 | if (cflag) { /* CPU - use rel */\r | |
920 | *sptr = 067 + indir;\r | |
921 | *dptr = (disp - addr - 4 + (2 * n1)) & 0177777;\r | |
922 | }\r | |
923 | else {\r | |
924 | if (indir) return 1; /* other - use abs */\r | |
925 | *sptr = 037;\r | |
926 | *dptr = disp;\r | |
927 | }\r | |
928 | return -1;\r | |
929 | \r | |
930 | default:\r | |
931 | return 1;\r | |
932 | } /* end case */\r | |
933 | }\r | |
934 | \r | |
935 | /* Symbolic input\r | |
936 | \r | |
937 | Inputs:\r | |
938 | *cptr = pointer to input string\r | |
939 | addr = current PC\r | |
940 | *uptr = pointer to unit\r | |
941 | *val = pointer to output values\r | |
942 | sw = switches\r | |
943 | Outputs:\r | |
944 | status = > 0 error code\r | |
945 | <= 0 -number of extra words\r | |
946 | */\r | |
947 | \r | |
948 | t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r | |
949 | {\r | |
950 | int32 bflag, cflag, d, i, j, reg, spec, n1, n2, disp, pflag;\r | |
951 | t_value by;\r | |
952 | t_stat r;\r | |
953 | char *tptr, gbuf[CBUFSIZE];\r | |
954 | \r | |
955 | bflag = 0; /* assume 16b */\r | |
956 | cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */\r | |
957 | if (!cflag) { /* not cpu? */\r | |
958 | DEVICE *dptr = find_dev_from_unit (uptr);\r | |
959 | if (dptr == NULL)\r | |
960 | return SCPE_IERR;\r | |
961 | if (dptr->dwidth < 16)\r | |
962 | bflag = 1;\r | |
963 | }\r | |
964 | \r | |
965 | while (isspace (*cptr)) cptr++; /* absorb spaces */\r | |
966 | if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r | |
967 | if (cptr[0] == 0) /* must have 1 char */\r | |
968 | return SCPE_ARG;\r | |
969 | if (bflag)\r | |
970 | val[0] = (t_value) cptr[0];\r | |
971 | else val[0] = (addr & 1)?\r | |
972 | (val[0] & 0377) | (((t_value) cptr[0]) << 8):\r | |
973 | (val[0] & ~0377) | ((t_value) cptr[0]);\r | |
974 | return 0;\r | |
975 | }\r | |
976 | if (sw & SWMASK ('B')) { /* byte? */\r | |
977 | by = get_uint (cptr, 8, 0377, &r); /* get byte */\r | |
978 | if (r != SCPE_OK)\r | |
979 | return SCPE_ARG;\r | |
980 | if (bflag)\r | |
981 | val[0] = by;\r | |
982 | else val[0] = (addr & 1)?\r | |
983 | (val[0] & 0377) | (by << 8):\r | |
984 | (val[0] & ~0377) | by;\r | |
985 | return 0;\r | |
986 | }\r | |
987 | if (bflag) return SCPE_ARG;\r | |
988 | \r | |
989 | if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */\r | |
990 | if (cptr[0] == 0) /* must have 1 char */\r | |
991 | return SCPE_ARG;\r | |
992 | val[0] = ((t_value) cptr[1] << 8) | (t_value) cptr[0];\r | |
993 | return -1;\r | |
994 | }\r | |
995 | if (sw & SWMASK ('R')) /* radix 50 */\r | |
996 | return SCPE_ARG;\r | |
997 | \r | |
998 | cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r | |
999 | n1 = n2 = pflag = 0;\r | |
1000 | for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r | |
1001 | if (opcode[i] == NULL)\r | |
1002 | return SCPE_ARG;\r | |
1003 | val[0] = opc_val[i] & 0177777; /* get value */\r | |
1004 | j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */\r | |
1005 | \r | |
1006 | switch (j) { /* case on class */\r | |
1007 | \r | |
1008 | case I_V_NPN: /* no operand */\r | |
1009 | break;\r | |
1010 | \r | |
1011 | case I_V_REG: /* register */\r | |
1012 | cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r | |
1013 | if ((reg = get_reg (gbuf, rname, 0)) < 0)\r | |
1014 | return SCPE_ARG;\r | |
1015 | val[0] = val[0] | reg;\r | |
1016 | break;\r | |
1017 | \r | |
1018 | case I_V_3B: case I_V_6B: case I_V_8B: /* xb literal */\r | |
1019 | cptr = get_glyph (cptr, gbuf, 0); /* get literal */\r | |
1020 | d = get_uint (gbuf, 8, (1 << j) - 1, &r);\r | |
1021 | if (r != SCPE_OK)\r | |
1022 | return SCPE_ARG;\r | |
1023 | val[0] = val[0] | d; /* put in place */\r | |
1024 | break;\r | |
1025 | \r | |
1026 | case I_V_BR: /* cond br */\r | |
1027 | cptr = get_glyph (cptr, gbuf, 0); /* get address */\r | |
1028 | tptr = get_addr (gbuf, &disp, &pflag); /* parse */\r | |
1029 | if ((tptr == NULL) || (*tptr != 0))\r | |
1030 | return SCPE_ARG;\r | |
1031 | if ((pflag & A_REL) == 0) {\r | |
1032 | if (cflag) disp = (disp - addr) & 0177777;\r | |
1033 | else return SCPE_ARG;\r | |
1034 | }\r | |
1035 | if ((disp & 1) || (disp > 0400) && (disp < 0177402))\r | |
1036 | return SCPE_ARG;\r | |
1037 | val[0] = val[0] | (((disp - 2) >> 1) & 0377);\r | |
1038 | break;\r | |
1039 | \r | |
1040 | case I_V_SOB: /* sob */\r | |
1041 | cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r | |
1042 | if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;\r | |
1043 | val[0] = val[0] | (reg << 6);\r | |
1044 | cptr = get_glyph (cptr, gbuf, 0); /* get address */\r | |
1045 | tptr = get_addr (gbuf, &disp, &pflag); /* parse */\r | |
1046 | if ((tptr == NULL) || (*tptr != 0))\r | |
1047 | return SCPE_ARG;\r | |
1048 | if ((pflag & A_REL) == 0) {\r | |
1049 | if (cflag) disp = (disp - addr) & 0177777;\r | |
1050 | else return SCPE_ARG;\r | |
1051 | }\r | |
1052 | if ((disp & 1) || ((disp > 2) && (disp < 0177604)))\r | |
1053 | return SCPE_ARG;\r | |
1054 | val[0] = val[0] | (((2 - disp) >> 1) & 077);\r | |
1055 | break;\r | |
1056 | \r | |
1057 | case I_V_RSOP: /* reg, sop */\r | |
1058 | cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r | |
1059 | if ((reg = get_reg (gbuf, rname, 0)) < 0)\r | |
1060 | return SCPE_ARG;\r | |
1061 | val[0] = val[0] | (reg << 6); /* fall through */\r | |
1062 | case I_V_SOP: /* sop */\r | |
1063 | cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r | |
1064 | if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)\r | |
1065 | return SCPE_ARG;\r | |
1066 | val[0] = val[0] | spec;\r | |
1067 | break;\r | |
1068 | \r | |
1069 | case I_V_SOPR: /* dop, reg */\r | |
1070 | cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r | |
1071 | if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)\r | |
1072 | return SCPE_ARG;\r | |
1073 | val[0] = val[0] | spec;\r | |
1074 | cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r | |
1075 | if ((reg = get_reg (gbuf, rname, 0)) < 0)\r | |
1076 | return SCPE_ARG;\r | |
1077 | val[0] = val[0] | (reg << 6);\r | |
1078 | break;\r | |
1079 | \r | |
1080 | case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */\r | |
1081 | cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r | |
1082 | if ((reg = get_reg (gbuf, fname, 0)) < 0)\r | |
1083 | return SCPE_ARG;\r | |
1084 | if (reg > 3)\r | |
1085 | return SCPE_ARG;\r | |
1086 | val[0] = val[0] | (reg << 6); /* fall through */\r | |
1087 | case I_V_FOP: /* fop */\r | |
1088 | cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r | |
1089 | if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, \r | |
1090 | (j == I_V_ASOP) || (j == I_V_ASMD))) > 0)\r | |
1091 | return SCPE_ARG;\r | |
1092 | val[0] = val[0] | spec;\r | |
1093 | break;\r | |
1094 | \r | |
1095 | case I_V_DOP: /* double op */\r | |
1096 | cptr = get_glyph (cptr, gbuf, ','); /* get glyph */\r | |
1097 | if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)\r | |
1098 | return SCPE_ARG;\r | |
1099 | val[0] = val[0] | (spec << 6);\r | |
1100 | cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r | |
1101 | if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1],\r | |
1102 | cflag, TRUE)) > 0)\r | |
1103 | return SCPE_ARG;\r | |
1104 | val[0] = val[0] | spec;\r | |
1105 | break;\r | |
1106 | \r | |
1107 | case I_V_CCC: case I_V_CCS: /* cond code oper */\r | |
1108 | for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r | |
1109 | cptr = get_glyph (cptr, gbuf, 0)) {\r | |
1110 | for (i = 0; (opcode[i] != NULL) &&\r | |
1111 | (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r | |
1112 | if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) ||\r | |
1113 | (opcode[i] == NULL))\r | |
1114 | return SCPE_ARG;\r | |
1115 | val[0] = val[0] | (opc_val[i] & 0177777);\r | |
1116 | }\r | |
1117 | break;\r | |
1118 | \r | |
1119 | default:\r | |
1120 | return SCPE_ARG;\r | |
1121 | }\r | |
1122 | \r | |
1123 | if (*cptr != 0) /* junk at end? */\r | |
1124 | return SCPE_ARG;\r | |
1125 | return ((n1 + n2) * 2) - 1;\r | |
1126 | }\r |