First Commit of my working state
[simh.git] / PDP1 / pdp1_sys.c
CommitLineData
196ba1fc
PH
1/* pdp1_sys.c: PDP-1 simulator interface\r
2\r
3 Copyright (c) 1993-2007, 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 03-Jan-07 RMS Fixed bugs in block loader, char input\r
27 21-Dec-06 RMS Added 16-channel sequence break support, PDP-1D support\r
28 06-Apr-04 RMS Fixed bug in binary loader (found by Mark Crispin)\r
29 08-Feb-04 PLB Merged display support\r
30 08-Dec-03 RMS Added parallel drum support, drum mnemonics\r
31 18-Oct-03 RMS Added DECtape off reel message\r
32 01-Sep-03 RMS Added support for loading in multiple fields\r
33 22-Jul-03 RMS Updated for "hardware" RIM loader\r
34 05-Dec-02 RMS Added drum support\r
35 21-Nov-02 RMS Changed typewriter to half duplex\r
36 20-Aug-02 RMS Added DECtape support\r
37 17-Sep-01 RMS Removed multiconsole support\r
38 13-Jul-01 RMS Fixed RIM loader format\r
39 27-May-01 RMS Added multiconsole support\r
40 14-Mar-01 RMS Revised load/dump interface (again)\r
41 30-Oct-00 RMS Added support for examine to file\r
42 27-Oct-98 RMS V2.4 load interface\r
43 20-Oct-97 RMS Fixed endian-dependence in RIM loader\r
44 (found by Michael Somos)\r
45*/\r
46\r
47#include "pdp1_defs.h"\r
48#include <ctype.h>\r
49\r
50extern DEVICE cpu_dev;\r
51extern DEVICE clk_dev;\r
52extern DEVICE ptr_dev;\r
53extern DEVICE ptp_dev;\r
54extern DEVICE tti_dev;\r
55extern DEVICE tto_dev;\r
56extern DEVICE lpt_dev;\r
57extern DEVICE dt_dev;\r
58extern DEVICE drm_dev;\r
59extern DEVICE drp_dev;\r
60extern DEVICE dcs_dev, dcsl_dev;\r
61extern DEVICE dpy_dev;\r
62extern UNIT cpu_unit;\r
63extern REG cpu_reg[];\r
64extern int32 M[];\r
65extern int32 PC;\r
66extern int32 ascii_to_fiodec[], fiodec_to_ascii[];\r
67extern int32 sc_map[];\r
68extern int32 sim_switches;\r
69\r
70/* SCP data structures and interface routines\r
71\r
72 sim_name simulator name string\r
73 sim_PC pointer to saved PC register descriptor\r
74 sim_emax number of words for examine\r
75 sim_devices array of pointers to simulated devices\r
76 sim_stop_messages array of pointers to stop messages\r
77 sim_load binary loader\r
78*/\r
79\r
80char sim_name[] = "PDP-1";\r
81\r
82REG *sim_PC = &cpu_reg[0];\r
83\r
84int32 sim_emax = 1;\r
85\r
86DEVICE *sim_devices[] = {\r
87 &cpu_dev,\r
88 &clk_dev,\r
89 &ptr_dev,\r
90 &ptp_dev,\r
91 &tti_dev,\r
92 &tto_dev,\r
93 &lpt_dev,\r
94 &dt_dev,\r
95 &drm_dev,\r
96 &drp_dev,\r
97 &dcs_dev,\r
98 &dcsl_dev,\r
99/* &dpy_dev, */\r
100 NULL\r
101 };\r
102\r
103const char *sim_stop_messages[] = {\r
104 "Unknown error",\r
105 "Undefined instruction",\r
106 "HALT instruction",\r
107 "Breakpoint",\r
108 "Nested XCT's",\r
109 "Nested indirect addresses",\r
110 "Infinite I/O wait state",\r
111 "DECtape off reel"\r
112 };\r
113\r
114/* Binary loader - supports both RIM format and Macro block format */\r
115\r
116int32 pdp1_getw (FILE *inf)\r
117{\r
118int32 i, tmp, word;\r
119\r
120word = 0;\r
121for (i = 0; i < 3;) {\r
122 if ((tmp = getc (inf)) == EOF) return -1;\r
123 if (tmp & 0200) {\r
124 word = (word << 6) | (tmp & 077);\r
125 i++;\r
126 }\r
127 }\r
128return word;\r
129}\r
130\r
131t_stat rim_load (FILE *inf, int32 fld)\r
132{\r
133int32 origin, val;\r
134\r
135for (;;) {\r
136 if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r
137 if (((val & 0760000) == OP_DIO) || /* DIO? */\r
138 ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */\r
139 origin = val & DAMASK;\r
140 if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r
141 M[fld | origin] = val;\r
142 }\r
143 else if ((val & 0760000) == OP_JMP) { /* JMP? */\r
144 PC = fld | (val & DAMASK);\r
145 break;\r
146 }\r
147 else return SCPE_FMT; /* bad instr */\r
148 }\r
149return SCPE_OK; /* done */\r
150}\r
151\r
152t_stat blk_load (FILE *inf, int32 fld)\r
153{\r
154int32 val, start, count, csum;\r
155\r
156for (;;) {\r
157 if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */\r
158 if ((val & 0760000) == OP_DIO) { /* DIO? */\r
159 csum = val; /* init checksum */\r
160 start = val & DAMASK; /* starting addr */\r
161 if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r
162 if ((val & 0760000) != OP_DIO) return SCPE_FMT;\r
163 csum = csum + val;\r
164 if (csum > DMASK) csum = (csum + 1) & DMASK;\r
165 count = (val & DAMASK) - start; /* block count */\r
166 if (count <= 0) return SCPE_FMT;\r
167 while (count--) { /* loop on data */\r
168 if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r
169 csum = csum + val;\r
170 if (csum > DMASK) csum = (csum + 1) & DMASK;\r
171 M[fld | start] = val;\r
172 start = (start + 1) & DAMASK;\r
173 }\r
174 if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;\r
175 if (val != csum) return SCPE_CSUM;\r
176 }\r
177 else if ((val & 0760000) == OP_JMP) { /* JMP? */\r
178 PC = fld | (val & DAMASK);\r
179 break;\r
180 }\r
181 else return SCPE_FMT; /* bad instr */\r
182 }\r
183return SCPE_OK; /* done */\r
184}\r
185\r
186t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r
187{\r
188t_stat sta;\r
189int32 fld;\r
190\r
191if (flag != 0) return SCPE_ARG;\r
192if (cptr && (*cptr != 0)) {\r
193 fld = get_uint (cptr, 8, AMASK, &sta);\r
194 if (sta != SCPE_OK) return sta;\r
195 fld = fld & EPCMASK;\r
196 }\r
197else fld = 0;\r
198sta = rim_load (fileref, fld);\r
199if (sta != SCPE_OK) return sta;\r
200if ((sim_switches & SWMASK ('B')) || match_ext (fnam, "BIN"))\r
201 return blk_load (fileref, fld);\r
202return SCPE_OK;\r
203}\r
204\r
205/* Symbol tables */\r
206\r
207#define I_V_FL 18 /* inst class */\r
208#define I_M_FL 017 /* class mask */\r
209#define I_V_NPN 0 /* no operand */\r
210#define I_V_IOT 1 /* IOT */\r
211#define I_V_LAW 2 /* LAW */\r
212#define I_V_MRF 3 /* memory reference */\r
213#define I_V_MRI 4 /* mem ref no ind */\r
214#define I_V_OPR 5 /* OPR */\r
215#define I_V_SKP 6 /* skip */\r
216#define I_V_SHF 7 /* shift */\r
217#define I_V_SPC 8 /* special */\r
218#define I_NPN (I_V_NPN << I_V_FL) /* no operand */\r
219#define I_IOT (I_V_IOT << I_V_FL) /* IOT */\r
220#define I_LAW (I_V_LAW << I_V_FL) /* LAW */\r
221#define I_MRF (I_V_MRF << I_V_FL) /* memory reference */\r
222#define I_MRI (I_V_MRI << I_V_FL) /* mem ref no ind */\r
223#define I_OPR (I_V_OPR << I_V_FL) /* OPR */\r
224#define I_SKP (I_V_SKP << I_V_FL) /* skip */\r
225#define I_SHF (I_V_SHF << I_V_FL) /* shift */\r
226#define I_SPC (I_V_SPC << I_V_FL)\r
227\r
228static const int32 masks[] = {\r
229 0777777, 0760077, 0760000, 0760000,\r
230 0770000, 0760017, 0760077, 0777000,\r
231 0760003\r
232 };\r
233\r
234static const char *opcode[] = {\r
235 "AND", "IOR", "XOR", "XCT", /* mem refs */\r
236 "LAC", "LIO", "DAC", "DAP",\r
237 "DIP", "DIO", "DZM", "ADD",\r
238 "SUB", "IDX", "ISP", "SAD",\r
239 "SAS", "MUL", "DIV", "JMP",\r
240 "JSP", "LCH", "DCH", "TAD",\r
241\r
242 "CAL", "JDA", /* mem ref no ind */\r
243\r
244 "LAW",\r
245\r
246 "IOH", "RPA", "RPB", "RRB", /* I/O instructions */\r
247 "PPA", "PPB", "TYO", "TYI",\r
248 "DPY",\r
249 "DSC", "ASC", "ISC", "CAC",\r
250 "LSM", "ESM", "CBS",\r
251 "LEM", "EEM", "CKS",\r
252 "MSE", "MLC", "MRD", "MWR", "MRS",\r
253 "DIA", "DBA", "DWC", "DRA", "DCL",\r
254 "DRD", "DWR", "DBL", "DCN",\r
255 "DTD", "DSE", "DSP",\r
256 "LRG", "ERG", "LRM", "ERM",\r
257 "RNM", "RSM", "RCK", "CTB",\r
258 "RCH", "RCC", "TCC", "TCB",\r
259 "RRC", "SSB", "RSC",\r
260\r
261 "SKP", "SKP I", "CLO", /* base as NPNs */\r
262 "SFT", "SPC", "OPR",\r
263\r
264 "RAL", "RIL", "RCL", /* shifts */\r
265 "SAL", "SIL", "SCL",\r
266 "RAR", "RIR", "RCR",\r
267 "SAR", "SIR", "SCR",\r
268\r
269 "SZF1", "SZF2", "SZF3", /* skips */\r
270 "SZF4", "SZF5", "SZF6", "SZF7",\r
271 "SZS1", "SZS1 SZF1", "SZS1 SZF2", "SZS1 SZ3",\r
272 "SZS1 SZF4", "SZS1 SZF5", "SZS1 SZF6", "SZS1 SZF7",\r
273 "SZS2", "SZS2 SZF1", "SZS2 SZF2", "SZS2 SZ3",\r
274 "SZS2 SZF4", "SZS2 SZF5", "SZS2 SZF6", "SZS2 SZF7",\r
275 "SZS3", "SZS3 SZF1", "SZS3 SZF2", "SZS3 SZ3",\r
276 "SZS3 SZF4", "SZS3 SZF5", "SZS3 SZF6", "SZS3 SZF7",\r
277 "SZS4", "SZS4 SZF1", "SZS4 SZF2", "SZS4 SZ3",\r
278 "SZS4 SZF4", "SZS4 SZF5", "SZS4 SZF6", "SZS4 SZF7",\r
279 "SZS5", "SZS5 SZF1", "SZS5 SZF2", "SZS5 SZ3",\r
280 "SZS5 SZF4", "SZS5 SZF5", "SZS5 SZF6", "SZS5 SZF7",\r
281 "SZS6", "SZS6 SZF1", "SZS6 SZF2", "SZS6 SZ3",\r
282 "SZS6 SZF4", "SZS6 SZF5", "SZS6 SZF6", "SZS6 SZF7",\r
283 "SZS7", "SZS7 SZF1", "SZS7 SZF2", "SZS7 SZ3",\r
284 "SZS7 SZF4", "SZS7 SZF5", "SZS7 SZF6", "SZS7 SZF7",\r
285\r
286 "CLF1", "CLF2", "CLF3", /* operates */\r
287 "CLF4", "CLF5", "CLF6", "CLF7",\r
288 "STF1", "STF2", "STF3",\r
289 "STF4", "STF5", "STF6", "STF7",\r
290\r
291 "FF1", "FF2", "FF3", /* specials */\r
292\r
293 "SZA", "SPA", "SMA", /* uprog skips */\r
294 "SZO", "SPI", "SNI",\r
295 "I", /* encode only */\r
296\r
297 "LIA", "LAI", "SWP", /* uprog opers */\r
298 "LAP", "CLA", "HLT",\r
299 "CMA", "LAT", "CLI",\r
300 "CMI",\r
301\r
302 "CML", "CLL", "SZL", /* uprog specials */\r
303 "SCF", "SCI", "SCM",\r
304 "IDA", "IDC", "IFI",\r
305 "IIF",\r
306\r
307 NULL, NULL, NULL, /* decode only */\r
308 NULL,\r
309 };\r
310\r
311static const int32 opc_val[] = {\r
312 0020000+I_MRF, 0040000+I_MRF, 0060000+I_MRF, 0100000+I_MRF,\r
313 0200000+I_MRF, 0220000+I_MRF, 0240000+I_MRF, 0260000+I_MRF,\r
314 0300000+I_MRF, 0320000+I_MRF, 0340000+I_MRF, 0400000+I_MRF,\r
315 0420000+I_MRF, 0440000+I_MRF, 0460000+I_MRF, 0500000+I_MRF,\r
316 0520000+I_MRF, 0540000+I_MRF, 0560000+I_MRF, 0600000+I_MRF,\r
317 0620000+I_MRF, 0120000+I_MRF, 0140000+I_MRF, 0360000+I_MRF,\r
318\r
319 0160000+I_MRI, 0170000+I_MRI,\r
320\r
321 0700000+I_LAW,\r
322\r
323 0730000+I_NPN, 0720001+I_IOT, 0720002+I_IOT, 0720030+I_IOT,\r
324 0720005+I_IOT, 0720006+I_IOT, 0720003+I_IOT, 0720004+I_IOT,\r
325 0720007+I_IOT,\r
326 0720050+I_IOT, 0720051+I_IOT, 0720052+I_IOT, 0720053+I_NPN,\r
327 0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN,\r
328 0720074+I_NPN, 0724074+I_NPN, 0720033+I_NPN,\r
329 0720301+I_NPN, 0720401+I_NPN, 0720501+I_NPN, 0720601+I_NPN, 0720701+I_NPN, \r
330 0720061+I_NPN, 0722061+I_NPN, 0720062+I_NPN, 0722062+I_NPN, 0720063+I_NPN,\r
331 0720161+I_NPN, 0721161+I_NPN, 0720162+I_NPN, 0721162+I_NPN,\r
332 0720163+I_NPN, 0720164+I_NPN, 0721164+I_NPN,\r
333 0720010+I_NPN, 0720011+I_NPN, 0720064+I_NPN, 0720065+I_NPN,\r
334 0720066+I_IOT, 0720067+I_NPN, 0720032+I_NPN, 0720035+I_NPN,\r
335 0720022+I_NPN, 0721022+I_NPN, 0725022+I_NPN, 0724022+I_NPN,\r
336 0720122+I_NPN, 0724122+I_NPN, 0721122+I_NPN,\r
337\r
338 0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN,\r
339 0660000+I_NPN, 0740000+I_NPN, 0760000+I_NPN,\r
340\r
341 0661000+I_SHF, 0662000+I_SHF, 0663000+I_SHF,\r
342 0665000+I_SHF, 0666000+I_SHF, 0667000+I_SHF,\r
343 0671000+I_SHF, 0672000+I_SHF, 0673000+I_SHF,\r
344 0675000+I_SHF, 0676000+I_SHF, 0677000+I_SHF,\r
345\r
346 0640001+I_SKP, 0640002+I_SKP, 0640003+I_SKP,\r
347 0640004+I_SKP, 0640005+I_SKP, 0640006+I_SKP, 0640007+I_SKP,\r
348 0640010+I_SKP, 0640011+I_SKP, 0640012+I_SKP, 0640013+I_SKP,\r
349 0640014+I_SKP, 0640015+I_SKP, 0640016+I_SKP, 0640017+I_SKP,\r
350 0640020+I_SKP, 0640021+I_SKP, 0640022+I_SKP, 0640023+I_SKP,\r
351 0640024+I_SKP, 0640025+I_SKP, 0640026+I_SKP, 0640027+I_SKP,\r
352 0640030+I_SKP, 0640031+I_SKP, 0640032+I_SKP, 0640033+I_SKP,\r
353 0640034+I_SKP, 0640035+I_SKP, 0640036+I_SKP, 0640037+I_SKP,\r
354 0640040+I_SKP, 0640041+I_SKP, 0640042+I_SKP, 0640043+I_SKP,\r
355 0640044+I_SKP, 0640045+I_SKP, 0640046+I_SKP, 0640047+I_SKP,\r
356 0640050+I_SKP, 0640051+I_SKP, 0640052+I_SKP, 0640053+I_SKP,\r
357 0640054+I_SKP, 0640055+I_SKP, 0640056+I_SKP, 0640057+I_SKP,\r
358 0640060+I_SKP, 0640061+I_SKP, 0640062+I_SKP, 0640063+I_SKP,\r
359 0640064+I_SKP, 0640065+I_SKP, 0640066+I_SKP, 0640067+I_SKP,\r
360 0640070+I_SKP, 0640071+I_SKP, 0640072+I_SKP, 0640073+I_SKP,\r
361 0640074+I_SKP, 0640075+I_SKP, 0640076+I_SKP, 0640077+I_SKP,\r
362\r
363 0760001+I_OPR, 0760002+I_OPR, 0760003+I_OPR,\r
364 0760004+I_OPR, 0760005+I_OPR, 0760006+I_OPR, 0760007+I_OPR,\r
365 0760011+I_OPR, 0760012+I_OPR, 0760013+I_OPR,\r
366 0760014+I_OPR, 0760015+I_OPR, 0760016+I_OPR, 0760017+I_OPR,\r
367\r
368 0740001+I_SPC, 0740002+I_SPC, 0740003+I_OPR,\r
369\r
370 0640100+I_SKP, 0640200+I_SKP, 0640400+I_SKP,\r
371 0641000+I_SKP, 0642000+I_SKP, 0644000+I_SKP,\r
372 0010000+I_SKP, /* encode only */\r
373\r
374 0760020+I_OPR, 0760040+I_OPR, 0760060+I_NPN,\r
375 0760100+I_OPR, 0760200+I_OPR, 0760400+I_OPR,\r
376 0761000+I_OPR, 0762000+I_OPR, 0764000+I_OPR,\r
377 0770000+I_OPR,\r
378\r
379 0740004+I_SPC, 0740010+I_SPC, 0740020+I_SPC,\r
380 0740040+I_SPC, 0740100+I_SPC, 0740200+I_SPC,\r
381 0740400+I_SPC, 0741000+I_SPC, 0742000+I_SPC,\r
382 0744000+I_SPC,\r
383\r
384 0640000+I_SKP, 0740000+I_SPC, 0760000+I_OPR, /* decode only */\r
385 -1\r
386 };\r
387\r
388/* Operate or skip decode\r
389\r
390 Inputs:\r
391 *of = output stream\r
392 inst = mask bits\r
393 class = instruction class code\r
394 sp = space needed?\r
395 Outputs:\r
396 status = space needed?\r
397*/\r
398\r
399int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp)\r
400{\r
401int32 i, j;\r
402\r
403for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
404 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
405 if ((j == class) && (opc_val[i] & inst)) { /* same class? */\r
406 inst = inst & ~opc_val[i]; /* mask bit set? */\r
407 fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
408 sp = 1;\r
409 }\r
410 }\r
411return sp;\r
412}\r
413\r
414/* Symbolic decode\r
415\r
416 Inputs:\r
417 *of = output stream\r
418 addr = current PC\r
419 *val = pointer to values\r
420 *uptr = pointer to unit\r
421 sw = switches\r
422 Outputs:\r
423 return = status code\r
424*/\r
425\r
426#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)\r
427#define SIXTOASC(x) fiodec_to_ascii[x]\r
428#define ASCTOSIX(x) (ascii_to_fiodec[x] & 077)\r
429\r
430t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r
431 UNIT *uptr, int32 sw)\r
432{\r
433int32 cflag, i, j, sp, inst, disp, ma;\r
434\r
435inst = val[0];\r
436cflag = (uptr == NULL) || (uptr == &cpu_unit);\r
437if (sw & SWMASK ('A')) { /* ASCII? */\r
438 if (inst > 0377) return SCPE_ARG;\r
439 fprintf (of, FMTASC (inst & 0177));\r
440 return SCPE_OK;\r
441 }\r
442if (sw & SWMASK ('F')) {\r
443 fputc (fiodec_to_ascii[inst & 077], of);\r
444 return SCPE_OK;\r
445 }\r
446if (sw & SWMASK ('C')) { /* character? */\r
447 fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));\r
448 fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));\r
449 fprintf (of, "%c", SIXTOASC (inst & 077));\r
450 return SCPE_OK;\r
451 }\r
452if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r
453\r
454/* Instruction decode */\r
455\r
456disp = inst & 007777;\r
457ma = (addr & EPCMASK) | disp;\r
458for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
459 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
460 if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */\r
461\r
462 switch (j) { /* case on class */\r
463\r
464 case I_V_NPN: /* no operands */\r
465 fprintf (of, "%s", opcode[i]); /* opcode */\r
466 break;\r
467\r
468 case I_V_IOT: /* IOT */\r
469 disp = (inst - opc_val[i]) & 017777;\r
470 if (disp == IA) fprintf (of, "%s I", opcode[i]);\r
471 else if (disp) fprintf (of, "%s %-o", opcode[i], disp);\r
472 else fprintf (of, "%s", opcode[i]);\r
473 break;\r
474\r
475 case I_V_LAW: /* LAW */\r
476 cflag = 0; /* fall thru to MRF */\r
477 case I_V_MRF: /* mem ref */\r
478 fprintf (of, "%s%s%-o", opcode[i],\r
479 ((inst & IA)? " I ": " "), (cflag? ma: disp));\r
480 break;\r
481\r
482 case I_V_MRI: /* mem ref no ind */\r
483 fprintf (of, "%s %-o", opcode[i], (cflag? ma: disp));\r
484 break;\r
485\r
486 case I_V_OPR: /* operates */\r
487 sp = fprint_opr (of, inst & 017760, j, 0);\r
488 if (opcode[i]) fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
489 break;\r
490\r
491 case I_V_SKP: /* skips */\r
492 sp = fprint_opr (of, inst & 007700, j, 0);\r
493 if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
494 if (inst & IA) fprintf (of, sp? " I": "I");\r
495 break;\r
496\r
497 case I_V_SPC: /* specials */\r
498 sp = fprint_opr (of, inst & 007774, j, 0);\r
499 if (opcode[i]) sp = fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
500 if (inst & IA) fprintf (of, sp? " I": "I");\r
501 break;\r
502\r
503 case I_V_SHF: /* shifts */\r
504 fprintf (of, "%s %-d", opcode[i], sc_map[inst & 0777]);\r
505 break;\r
506 } /* end case */\r
507\r
508 return SCPE_OK;\r
509 } /* end if */\r
510 } /* end for */\r
511return SCPE_ARG;\r
512}\r
513\r
514/* Get 18b signed number\r
515\r
516 Inputs:\r
517 *cptr = pointer to input string\r
518 *sign = pointer to sign\r
519 *status = pointer to error status\r
520 Outputs:\r
521 val = output value\r
522*/\r
523\r
524t_value get_sint (char *cptr, int32 *sign, t_stat *status)\r
525{\r
526*sign = 1;\r
527if (*cptr == '+') {\r
528 *sign = 0;\r
529 cptr++;\r
530 }\r
531else if (*cptr == '-') {\r
532 *sign = -1;\r
533 cptr++;\r
534 }\r
535return get_uint (cptr, 8, DMASK, status);\r
536}\r
537\r
538/* Symbolic input\r
539\r
540 Inputs:\r
541 *cptr = pointer to input string\r
542 addr = current PC\r
543 uptr = pointer to unit\r
544 *val = pointer to output values\r
545 sw = switches\r
546 Outputs:\r
547 status = error status\r
548*/\r
549\r
550t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r
551{\r
552int32 cflag, d, i, j, k, sign;\r
553t_stat r;\r
554static int32 sc_enc[10] = { 0, 01, 03, 07, 017, 037, 077, 0177, 0377, 0777 };\r
555char gbuf[CBUFSIZE];\r
556\r
557cflag = (uptr == NULL) || (uptr == &cpu_unit);\r
558while (isspace (*cptr)) cptr++;\r
559for (i = 1; (i < 3) && (cptr[i] != 0); i++)\r
560 if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0;\r
561if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r
562 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
563 val[0] = (t_value) cptr[0];\r
564 return SCPE_OK;\r
565 }\r
566if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */\r
567 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
568 val[0] = ((ASCTOSIX (cptr[0]) & 077) << 12) |\r
569 ((ASCTOSIX (cptr[1]) & 077) << 6) |\r
570 (ASCTOSIX (cptr[2]) & 077);\r
571 return SCPE_OK;\r
572 }\r
573\r
574cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r
575for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
576if (opcode[i] == NULL) return SCPE_ARG;\r
577val[0] = opc_val[i] & DMASK; /* get value */\r
578j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
579\r
580switch (j) { /* case on class */\r
581\r
582 case I_V_LAW: /* LAW */\r
583 cflag = 0; /* fall through */\r
584 case I_V_MRF: case I_V_MRI: /* mem ref */\r
585 cptr = get_glyph (cptr, gbuf, 0); /* get next field */\r
586 if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */\r
587 val[0] = val[0] | IA;\r
588 cptr = get_glyph (cptr, gbuf, 0);\r
589 }\r
590 d = get_uint (gbuf, 8, AMASK, &r);\r
591 if (r != SCPE_OK) return SCPE_ARG;\r
592 if (d <= DAMASK) val[0] = val[0] | d;\r
593 else if (cflag && (((addr ^ d) & EPCMASK) == 0))\r
594 val[0] = val[0] | (d & DAMASK);\r
595 else return SCPE_ARG;\r
596 break;\r
597\r
598 case I_V_SHF: /* shift */\r
599 cptr = get_glyph (cptr, gbuf, 0);\r
600 d = get_uint (gbuf, 10, 9, &r);\r
601 if (r != SCPE_OK) return SCPE_ARG;\r
602 val[0] = val[0] | sc_enc[d];\r
603 break;\r
604\r
605 case I_V_NPN: case I_V_IOT:\r
606 case I_V_OPR: case I_V_SKP: case I_V_SPC:\r
607 for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r
608 cptr = get_glyph (cptr, gbuf, 0)) {\r
609 for (i = 0; (opcode[i] != NULL) &&\r
610 (strcmp (opcode[i], gbuf) != 0); i++) ;\r
611 if (opcode[i] != NULL) {\r
612 k = opc_val[i] & DMASK;\r
613 if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))\r
614 return SCPE_ARG;\r
615 val[0] = val[0] | k;\r
616 }\r
617 else {\r
618 d = get_sint (gbuf, &sign, &r);\r
619 if (r != SCPE_OK) return SCPE_ARG;\r
620 if (sign == 0) val[0] = val[0] + d; \r
621 else if (sign < 0) val[0] = val[0] - d;\r
622 else val[0] = val[0] | d;\r
623 }\r
624 }\r
625 break;\r
626 } /* end case */\r
627if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r
628return SCPE_OK;\r
629}\r