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