First Commit of my working state
[simh.git] / SDS / sds_sys.c
CommitLineData
196ba1fc
PH
1/* sds_sys.c: SDS 940 simulator interface\r
2\r
3 Copyright (c) 2001-2005, 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\r
27#include "sds_defs.h"\r
28#include <ctype.h>\r
29#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)\r
30\r
31extern DEVICE cpu_dev;\r
32extern DEVICE chan_dev;\r
33extern DEVICE ptr_dev;\r
34extern DEVICE ptp_dev;\r
35extern DEVICE tti_dev;\r
36extern DEVICE tto_dev;\r
37extern DEVICE lpt_dev;\r
38extern DEVICE rtc_dev;\r
39extern DEVICE drm_dev;\r
40extern DEVICE rad_dev;\r
41extern DEVICE dsk_dev;\r
42extern DEVICE mt_dev;\r
43extern DEVICE mux_dev, muxl_dev;\r
44extern UNIT cpu_unit;\r
45extern REG cpu_reg[];\r
46extern uint32 M[MAXMEMSIZE];\r
47\r
48/* SCP data structures and interface routines\r
49\r
50 sim_name simulator name string\r
51 sim_PC pointer to saved PC register descriptor\r
52 sim_emax number of words for examine\r
53 sim_devices array of pointers to simulated devices\r
54 sim_stop_messages array of pointers to stop messages\r
55 sim_load binary loader\r
56*/\r
57\r
58char sim_name[] = "SDS 940";\r
59\r
60REG *sim_PC = &cpu_reg[0];\r
61\r
62int32 sim_emax = 1;\r
63\r
64DEVICE *sim_devices[] = {\r
65 &cpu_dev,\r
66 &chan_dev,\r
67 &ptr_dev,\r
68 &ptp_dev,\r
69 &tti_dev,\r
70 &tto_dev,\r
71 &lpt_dev,\r
72 &rtc_dev,\r
73 &drm_dev,\r
74 &rad_dev,\r
75 &dsk_dev,\r
76 &mt_dev,\r
77 &mux_dev,\r
78 &muxl_dev,\r
79 NULL\r
80 };\r
81\r
82const char *sim_stop_messages[] = {\r
83 "Unknown error",\r
84 "IO device not ready",\r
85 "HALT instruction",\r
86 "Breakpoint",\r
87 "Invalid IO device",\r
88 "Invalid instruction",\r
89 "Invalid I/O operation",\r
90 "Nested indirects exceed limit",\r
91 "Nested EXU's exceed limit",\r
92 "Memory management trap during interrupt",\r
93 "Memory management trap during trap",\r
94 "Trap instruction not BRM",\r
95 "RTC instruction not MIN or SKR",\r
96 "Interrupt vector zero",\r
97 "Runaway carriage control tape"\r
98 };\r
99\r
100/* Character conversion tables */\r
101\r
102const char sds_to_ascii[64] = {\r
103 '0', '1', '2', '3', '4', '5', '6', '7',\r
104 '8', '9', ' ', '=', '\'', ':', '>', '%', /* 17 = check mark */\r
105 '+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',\r
106 'H', 'I', '?', '.', ')', '[', '<', '@', /* 37 = stop code */\r
107 '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\r
108 'Q', 'R', '!', '$', '*', ']', ';', '^', /* 57 = triangle */\r
109 '_', '/', 'S', 'T', 'U', 'V', 'W', 'X',\r
110 'Y', 'Z', '?', ',', '(', '~', '\\', '#' /* 72 = rec mark */\r
111 }; /* 75 = squiggle, 77 = del */\r
112\r
113const char ascii_to_sds[128] = {\r
114 -1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */\r
115 032, 072, -1, -1, -1, 052, -1, -1,\r
116 -1, -1, -1, -1, -1, -1, -1, -1,\r
117 -1, -1, -1, -1, -1, -1, -1, -1,\r
118 012, 052, -1, 077, 053, 017, -1, 014, /* 40 - 77 */\r
119 074, 034, 054, 020, 073, 040, 033, 061,\r
120 000, 001, 002, 003, 004, 005, 006, 007,\r
121 010, 011, 015, 056, 036, 013, 016, 072,\r
122 037, 021, 022, 023, 024, 025, 026, 027, /* 100 - 137 */\r
123 030, 031, 041, 042, 043, 044, 045, 046,\r
124 047, 050, 051, 062, 063, 064, 065, 066,\r
125 067, 070, 071, 035, 076, 055, 057, 060,\r
126 000, 021, 022, 023, 024, 025, 026, 027, /* 140 - 177 */\r
127 030, 031, 041, 042, 043, 044, 045, 046,\r
128 047, 050, 051, 062, 063, 064, 065, 066,\r
129 067, 070, 071, -1, -1, -1, -1, -1\r
130 };\r
131\r
132const char odd_par[64] = {\r
133 0100, 0001, 0002, 0103, 0004, 0105, 0106, 0007,\r
134 0010, 0111, 0112, 0013, 0114, 0015, 0016, 0117,\r
135 0020, 0121, 0122, 0023, 0124, 0025, 0026, 0127,\r
136 0130, 0031, 0032, 0133, 0034, 0135, 0136, 0037,\r
137 0040, 0141, 0142, 0043, 0144, 0045, 0046, 0147,\r
138 0150, 0051, 0052, 0153, 0054, 0155, 0156, 0057,\r
139 0160, 0061, 0062, 0163, 0064, 0165, 0166, 0067,\r
140 0070, 0171, 0172, 0073, 0174, 0075, 0076, 0177\r
141 };\r
142\r
143/* Load carriage control tape\r
144\r
145 A carriage control tape consists of entries of the form\r
146\r
147 (repeat count) column number,column number,column number,...\r
148\r
149 The CCT entries are stored in lpt_cct[0:lnt-1], lpt_ccl contains the\r
150 number of entries\r
151*/\r
152\r
153t_stat sim_load_cct (FILE *fileref)\r
154{\r
155int32 col, rpt, ptr, mask, cctbuf[CCT_LNT];\r
156t_stat r;\r
157extern int32 lpt_ccl, lpt_ccp, lpt_cct[CCT_LNT];\r
158char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE];\r
159\r
160ptr = 0;\r
161for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */\r
162 mask = 0;\r
163 if (*cptr == '(') { /* repeat count? */\r
164 cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */\r
165 rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */\r
166 if (r != SCPE_OK) return SCPE_FMT;\r
167 }\r
168 else rpt = 1;\r
169 while (*cptr != 0) { /* get col no's */\r
170 cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r
171 col = get_uint (gbuf, 10, 7, &r); /* column number */\r
172 if (r != SCPE_OK) return SCPE_FMT;\r
173 mask = mask | (1 << col); /* set bit */\r
174 }\r
175 for ( ; rpt > 0; rpt--) { /* store vals */\r
176 if (ptr >= CCT_LNT) return SCPE_FMT;\r
177 cctbuf[ptr++] = mask;\r
178 }\r
179 }\r
180if (ptr == 0) return SCPE_FMT;\r
181lpt_ccl = ptr;\r
182lpt_ccp = 0;\r
183for (rpt = 0; rpt < lpt_ccl; rpt++) lpt_cct[rpt] = cctbuf[rpt];\r
184return SCPE_OK;\r
185}\r
186\r
187/* Load command. -l means load a line printer tape. Otherwise, load\r
188 a bootstrap paper tape.\r
189*/\r
190\r
191int32 get_word (FILE *fileref, int32 *ldr)\r
192{\r
193int32 i, c, wd;\r
194\r
195for (i = wd = 0; i < 4; ) {\r
196 if ((c = fgetc (fileref)) == EOF) return -1;\r
197 if ((c == 0) && (*ldr == 0)) return -1;\r
198 if (c == 0) continue;\r
199 *ldr = 0;\r
200 wd = (wd << 6) | (c & 077);\r
201 i++;\r
202 }\r
203return wd;\r
204}\r
205 \r
206t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r
207{\r
208int32 i, wd, buf[8];\r
209int32 ldr = 1;\r
210extern int32 sim_switches;\r
211extern uint32 P;\r
212\r
213if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;\r
214if (sim_switches & SWMASK ('L')) return sim_load_cct (fileref);\r
215for (i = 0; i < 8; i++) { /* read boot */\r
216 if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_FMT;\r
217 buf[i] = wd;\r
218 }\r
219if ((buf[0] != 023200012) || /* 2 = WIM 12,2 */\r
220 (buf[1] != 004100002) || /* 3 = BRX 2 */\r
221 (buf[2] != 007100011) || /* 4 = LDX 11 */\r
222 (buf[3] != 023200000) || /* 5 = WIM 0,2 */\r
223 (buf[4] != 004021000) || /* 6 = SKS 21000 */\r
224 (buf[5] != 004100005)) return SCPE_FMT; /* 7 = BRX 5 */\r
225for (i = 0; i < 8; i++) M[i + 2] = buf[i]; /* copy boot */\r
226if (I_GETOP (buf[6]) == BRU) P = buf[6] & VA_MASK;\r
227for (i = buf[7] & VA_MASK; i <= VA_MASK; i++) { /* load data */\r
228 if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_OK;\r
229 M[i] = wd;\r
230 }\r
231return SCPE_NXM;\r
232}\r
233\r
234/* Symbol tables */\r
235\r
236#define I_V_FL 24 /* inst class */\r
237#define I_M_FL 017 /* class mask */\r
238#define I_V_NPN 000 /* no operand */\r
239#define I_V_PPO 001 /* POP */\r
240#define I_V_IOI 002 /* IO */\r
241#define I_V_MRF 003 /* memory reference */\r
242#define I_V_REG 004 /* register change */\r
243#define I_V_SHF 005 /* shift */\r
244#define I_V_OPO 006 /* opcode only */\r
245#define I_V_CHC 007 /* chan cmd */\r
246#define I_V_CHT 010 /* chan test */\r
247#define I_NPN (I_V_NPN << I_V_FL) \r
248#define I_PPO (I_V_PPO << I_V_FL) \r
249#define I_IOI (I_V_IOI << I_V_FL) \r
250#define I_MRF (I_V_MRF << I_V_FL) \r
251#define I_REG (I_V_REG << I_V_FL) \r
252#define I_SHF (I_V_SHF << I_V_FL) \r
253#define I_OPO (I_V_OPO << I_V_FL)\r
254#define I_CHC (I_V_CHC << I_V_FL)\r
255#define I_CHT (I_V_CHT << I_V_FL) \r
256\r
257static const int32 masks[] = {\r
258 037777777, 010000000, 017700000,\r
259 017740000, 017700000, 017774000,\r
260 017700000, 017377677, 027737677\r
261 };\r
262\r
263static const char *opcode[] = {\r
264 "POP", "EIR", "DIR",\r
265 "ROV", "REO", "OTO", "OVT",\r
266 "IDT", "IET",\r
267 "BPT4", "BPT3", "BPT2", "BPT1",\r
268 "CLAB", "ABC", "BAC", "XAB",\r
269 "XXB", "STE", "LDE", "XEE",\r
270 "CLEAR",\r
271\r
272 "HLT", "BRU", "EOM", "EOD",\r
273 "MIY", "BRI", "MIW", "POT",\r
274 "ETR", "MRG", "EOR",\r
275 "NOP", "EXU",\r
276 "YIM", "WIM", "PIN",\r
277 "STA", "STB", "STX",\r
278 "SKS", "BRX", "BRM",\r
279 "SKE", "BRR", "SKB", "SKN",\r
280 "SUB", "ADD", "SUC", "ADC",\r
281 "SKR", "MIN", "XMA", "ADM",\r
282 "MUL", "DIV",\r
283 "SKM", "LDX", "SKA", "SKG",\r
284 "SKD", "LDB", "LDA", "EAX",\r
285\r
286 "BRU*", \r
287 "MIY*", "BRI*", "MIW*", "POT*",\r
288 "ETR*", "MRG*", "EOR*",\r
289 "EXU*",\r
290 "YIM*", "WIM*", "PIN*",\r
291 "STA*", "STB*", "STX*",\r
292 "BRX*", "BRM*",\r
293 "SKE*", "BRR*", "SKB*", "SKN*",\r
294 "SUB*", "ADD*", "SUC*", "ADC*",\r
295 "SKR*", "MIN*", "XMA*", "ADM*",\r
296 "MUL*", "DIV*",\r
297 "SKM*", "LDX*", "SKA*", "SKG*",\r
298 "SKD*", "LDB*", "LDA*", "EAX*",\r
299\r
300 "RSH", "RCY", "LRSH",\r
301 "LSH", "NOD", "LCY",\r
302 "RSH*", "LSH*",\r
303\r
304 "ALC", "DSC", "ASC", "TOP",\r
305 "CAT", "CET", "CZT", "CIT",\r
306\r
307 "CLA", "CLB", "CAB", /* encode only */\r
308 "CBA", "CBX", "CXB",\r
309 "XPO", "CXA", "CAX",\r
310 "CNA", "CLX", NULL,\r
311 NULL\r
312 };\r
313\r
314static const int32 opc_val[] = {\r
315 010000000+I_PPO, 000220002+I_NPN, 000220004+I_NPN,\r
316 002200001+I_NPN, 002200010+I_NPN, 002200100+I_NPN, 002200101+I_NPN,\r
317 004020002+I_NPN, 004020004+I_NPN,\r
318 004020040+I_NPN, 004020100+I_NPN, 004020200+I_NPN, 004020400+I_NPN,\r
319 004600003+I_NPN, 004600005+I_NPN, 004600012+I_NPN, 004600014+I_NPN,\r
320 004600060+I_NPN, 004600122+I_NPN, 004600140+I_NPN, 004600160+I_NPN,\r
321 024600003+I_NPN,\r
322\r
323 000000000+I_NPN, 000100000+I_MRF, 000200000+I_IOI, 000600000+I_IOI,\r
324 001000000+I_MRF, 001100000+I_MRF, 001200000+I_MRF, 001300000+I_MRF,\r
325 001400000+I_MRF, 001600000+I_MRF, 001700000+I_MRF,\r
326 002000000+I_OPO, 002300000+I_MRF,\r
327 003000000+I_MRF, 003200000+I_MRF, 003300000+I_MRF,\r
328 003500000+I_MRF, 003600000+I_MRF, 003700000+I_MRF,\r
329 004000000+I_IOI, 004100000+I_MRF, 004300000+I_MRF,\r
330 005000000+I_MRF, 005100000+I_MRF, 005200000+I_MRF, 005300000+I_MRF,\r
331 005400000+I_MRF, 005500000+I_MRF, 005600000+I_MRF, 005700000+I_MRF,\r
332 006000000+I_MRF, 006100000+I_MRF, 006200000+I_MRF, 006300000+I_MRF,\r
333 006400000+I_MRF, 006500000+I_MRF,\r
334 007000000+I_MRF, 007100000+I_MRF, 007200000+I_MRF, 007300000+I_MRF,\r
335 007400000+I_MRF, 007500000+I_MRF, 007600000+I_MRF, 007700000+I_MRF,\r
336\r
337 000140000+I_MRF,\r
338 001040000+I_MRF, 001140000+I_MRF, 001240000+I_MRF, 001340000+I_MRF,\r
339 001440000+I_MRF, 001640000+I_MRF, 001740000+I_MRF,\r
340 002340000+I_MRF,\r
341 003040000+I_MRF, 003240000+I_MRF, 003340000+I_MRF,\r
342 003540000+I_MRF, 003640000+I_MRF, 003740000+I_MRF,\r
343 004140000+I_MRF, 004340000+I_MRF,\r
344 005040000+I_MRF, 005140000+I_MRF, 005240000+I_MRF, 005340000+I_MRF,\r
345 005440000+I_MRF, 005540000+I_MRF, 005640000+I_MRF, 005740000+I_MRF,\r
346 006040000+I_MRF, 006140000+I_MRF, 006240000+I_MRF, 006340000+I_MRF,\r
347 006440000+I_MRF, 006540000+I_MRF,\r
348 007040000+I_MRF, 007140000+I_MRF, 007240000+I_MRF, 007340000+I_MRF,\r
349 007440000+I_MRF, 007540000+I_MRF, 007640000+I_MRF, 007740000+I_MRF,\r
350\r
351 006600000+I_SHF, 006620000+I_SHF, 006624000+I_SHF,\r
352 006700000+I_SHF, 006710000+I_SHF, 006720000+I_SHF,\r
353 006640000+I_MRF, 006740000+I_MRF,\r
354\r
355 000250000+I_CHC, 000200000+I_CHC, 000212000+I_CHC, 000214000+I_CHC,\r
356 004014000+I_CHT, 004011000+I_CHT, 004012000+I_CHT, 004010400+I_CHT,\r
357\r
358 004600001+I_REG, 004600002+I_REG, 004600004+I_REG,\r
359 004600010+I_REG, 004600020+I_REG, 004600040+I_REG,\r
360 004600100+I_REG, 004600200+I_REG, 004600400+I_REG,\r
361 004601000+I_REG, 024600000+I_REG, 004600000+I_REG,\r
362 -1\r
363 };\r
364\r
365static const char *chname[] = {\r
366 "W", "Y", "C", "D", "E", "F", "G", "H", NULL\r
367 };\r
368\r
369/* Register change decode\r
370\r
371 Inputs:\r
372 *of = output stream\r
373 inst = mask bits\r
374*/\r
375\r
376void fprint_reg (FILE *of, int32 inst)\r
377{\r
378int32 i, j, sp;\r
379\r
380inst = inst & ~(I_M_OP << I_V_OP); /* clear opcode */\r
381for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
382 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
383 if ((j == I_V_REG) && (opc_val[i] & inst)) { /* reg class? */\r
384 inst = inst & ~opc_val[i]; /* mask bit set? */\r
385 fprintf (of, (sp? " %s": "%s"), opcode[i]);\r
386 sp = 1;\r
387 }\r
388 }\r
389return;\r
390}\r
391\r
392/* Symbolic decode\r
393\r
394 Inputs:\r
395 *of = output stream\r
396 addr = current PC\r
397 *val = pointer to values\r
398 *uptr = pointer to unit\r
399 sw = switches\r
400 Outputs:\r
401 return = status code\r
402*/\r
403\r
404t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r
405 UNIT *uptr, int32 sw)\r
406{\r
407int32 i, j, ch;\r
408int32 inst, op, tag, va, shf, nonop;\r
409\r
410inst = val[0]; /* get inst */\r
411op = I_GETOP (inst); /* get fields */\r
412tag = (inst >> 21) & 06;\r
413va = inst & VA_MASK;\r
414shf = inst & I_SHFMSK;\r
415nonop = inst & 077777;\r
416\r
417if (sw & SWMASK ('A')) { /* ASCII? */\r
418 if (inst > 0377) return SCPE_ARG;\r
419 fprintf (of, FMTASC (inst & 0177));\r
420 return SCPE_OK;\r
421 }\r
422if (sw & SWMASK ('C')) { /* character? */\r
423 fprintf (of, "%c", sds_to_ascii[(inst >> 18) & 077]);\r
424 fprintf (of, "%c", sds_to_ascii[(inst >> 12) & 077]);\r
425 fprintf (of, "%c", sds_to_ascii[(inst >> 6) & 077]);\r
426 fprintf (of, "%c", sds_to_ascii[inst & 077]);\r
427 return SCPE_OK;\r
428 }\r
429if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r
430\r
431/* Instruction decode */\r
432\r
433for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */\r
434 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
435 if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */\r
436\r
437 switch (j) { /* case on class */\r
438\r
439 case I_V_NPN: /* no operands */\r
440 case I_V_OPO: /* opcode only */\r
441 fprintf (of, "%s", opcode[i]); /* opcode */\r
442 break;\r
443\r
444 case I_V_SHF: /* shift */\r
445 fprintf (of, "%s %-o", opcode[i], shf);\r
446 if (tag) fprintf (of, ",%-o", tag);\r
447 break;\r
448\r
449 case I_V_PPO: /* pop */\r
450 fprintf (of, "POP %-o,%-o", op, nonop);\r
451 if (tag) fprintf (of, ",%-o", tag);\r
452 break;\r
453\r
454 case I_V_IOI: /* I/O */\r
455 fprintf (of, "%s %-o", opcode[i], nonop);\r
456 if (tag) fprintf (of, ",%-o", tag);\r
457 break;\r
458\r
459 case I_V_MRF: /* mem ref */\r
460 fprintf (of, "%s %-o", opcode[i], va);\r
461 if (tag) fprintf (of, ",%-o", tag);\r
462 break;\r
463\r
464 case I_V_REG: /* reg change */\r
465 fprint_reg (of, inst); /* decode */\r
466 break;\r
467\r
468 case I_V_CHC: /* chan cmd */\r
469 ch = I_GETEOCH (inst); /* get chan */\r
470 fprintf (of, "%s %s", opcode[i], chname[ch]);\r
471 break;\r
472\r
473 case I_V_CHT: /* chan test */\r
474 ch = I_GETSKCH (inst); /* get chan */\r
475 fprintf (of, "%s %s", opcode[i], chname[ch]);\r
476 break;\r
477 } /* end case */\r
478\r
479 return SCPE_OK;\r
480 } /* end if */\r
481 } /* end for */\r
482return SCPE_ARG;\r
483}\r
484\r
485/* Get (optional) tag\r
486\r
487 Inputs:\r
488 *cptr = pointer to input string\r
489 *tag = pointer to tag\r
490 Outputs:\r
491 cptr = updated pointer to input string\r
492*/\r
493\r
494char *get_tag (char *cptr, t_value *tag)\r
495{\r
496char *tptr, gbuf[CBUFSIZE];\r
497t_stat r;\r
498\r
499tptr = get_glyph (cptr, gbuf, 0); /* get next field */\r
500*tag = get_uint (gbuf, 8, 07, &r) << I_V_TAG; /* parse */\r
501if (r == SCPE_OK) return tptr; /* ok? advance */\r
502*tag = 0;\r
503return cptr; /* no change */\r
504}\r
505\r
506/* Symbolic input\r
507\r
508 Inputs:\r
509 *cptr = pointer to input string\r
510 addr = current PC\r
511 uptr = pointer to unit\r
512 *val = pointer to output values\r
513 sw = switches\r
514 Outputs:\r
515 status = error status\r
516*/\r
517\r
518t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)\r
519{\r
520int32 i, j, k;\r
521t_value d, tag;\r
522t_stat r;\r
523char gbuf[CBUFSIZE];\r
524\r
525while (isspace (*cptr)) cptr++;\r
526for (i = 1; (i < 4) && (cptr[i] != 0); i++)\r
527 if (cptr[i] == 0) for (j = i + 1; j <= 4; j++) cptr[j] = 0;\r
528if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r
529 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
530 val[0] = (t_value) cptr[0] | 0200;\r
531 return SCPE_OK;\r
532 }\r
533if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */\r
534 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
535 for (i = j = 0, val[0] = 0; i < 4; i++) {\r
536 if (cptr[i] == 0) j = 1; /* latch str end */\r
537 k = ascii_to_sds[cptr[i] & 0177]; /* cvt char */\r
538 if (j || (k < 0)) k = 0; /* bad, end? spc */\r
539 val[0] = (val[0] << 6) | k;\r
540 }\r
541 return SCPE_OK;\r
542 }\r
543\r
544cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r
545for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
546if (opcode[i] == NULL) return SCPE_ARG;\r
547val[0] = opc_val[i] & DMASK; /* get value */\r
548j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */\r
549\r
550switch (j) { /* case on class */\r
551\r
552 case I_V_NPN: case I_V_OPO: /* opcode only */\r
553 break;\r
554\r
555 case I_V_SHF: /* shift */\r
556 cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r
557 d = get_uint (gbuf, 8, I_SHFMSK, &r); /* shift count */\r
558 if (r != SCPE_OK) return SCPE_ARG;\r
559 cptr = get_tag (cptr, &tag); /* get opt tag */\r
560 val[0] = val[0] | d | tag;\r
561 break;\r
562\r
563 case I_V_PPO: /* pop */\r
564 cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r
565 d = get_uint (gbuf, 8, 077, &r); /* opcode */\r
566 if (r != SCPE_OK) return SCPE_ARG;\r
567 val[0] = val[0] | d; /* fall thru */\r
568\r
569 case I_V_IOI: /* I/O */\r
570 cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r
571 d = get_uint (gbuf, 8, 077777, &r); /* 15b address */\r
572 if (r != SCPE_OK) return SCPE_ARG;\r
573 cptr = get_tag (cptr, &tag); /* get opt tag */\r
574 val[0] = val[0] | d | tag;\r
575 break;\r
576\r
577 case I_V_MRF: /* mem ref */\r
578 cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r
579 d = get_uint (gbuf, 8, VA_MASK, &r); /* virt address */\r
580 if (r != SCPE_OK) return SCPE_ARG;\r
581 cptr = get_tag (cptr, &tag); /* get opt tag */\r
582 val[0] = val[0] | d | tag;\r
583 break;\r
584\r
585 case I_V_REG: /* register */\r
586 for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;\r
587 cptr = get_glyph (cptr, gbuf, 0)) {\r
588 for (i = 0; (opcode[i] != NULL) &&\r
589 (strcmp (opcode[i], gbuf) != 0); i++) ;\r
590 if (opcode[i] != NULL) {\r
591 k = opc_val[i] & DMASK;;\r
592 if (I_GETOP (k) != RCH) return SCPE_ARG;\r
593 val[0] = val[0] | k;\r
594 }\r
595 else {\r
596 d = get_uint (gbuf, 8, 077777, &r);\r
597 if (r != SCPE_OK) return SCPE_ARG;\r
598 else val[0] = val[0] | d;\r
599 }\r
600 }\r
601 break;\r
602\r
603 case I_V_CHC: case I_V_CHT: /* channel */\r
604 cptr = get_glyph (cptr, gbuf, ','); /* get next field */\r
605 for (i = 0; (chname[i] != NULL) && (strcmp (chname[i], gbuf) != 0);\r
606 i++);\r
607 if (chname[i] != NULL) d = i; /* named chan */\r
608 else {\r
609 d = get_uint (gbuf, 8, NUM_CHAN - 1, &r);\r
610 if (r != SCPE_OK) return SCPE_ARG; /* numbered chan */\r
611 }\r
612 val[0] = val[0] | ((j == I_V_CHC)? I_SETEOCH (d): I_SETSKCH (d));\r
613 break;\r
614 } /* end case */\r
615\r
616if (*cptr != 0) return SCPE_ARG; /* junk at end? */\r
617return SCPE_OK;\r
618}\r