First Commit of my working state
[simh.git] / GRI / gri_sys.c
CommitLineData
196ba1fc
PH
1/* gri_sys.c: GRI-909 simulator interface\r
2\r
3 Copyright (c) 2001-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 14-Jan-08 RMS Added GRI-99 support\r
27 18-Oct-02 RMS Fixed bug in symbolic decode (found by Hans Pufal)\r
28*/\r
29\r
30#include "gri_defs.h"\r
31#include <ctype.h>\r
32\r
33extern DEVICE cpu_dev;\r
34extern UNIT cpu_unit;\r
35extern DEVICE tti_dev, tto_dev;\r
36extern DEVICE hsr_dev, hsp_dev;\r
37extern DEVICE rtc_dev;\r
38extern REG cpu_reg[];\r
39extern uint16 M[];\r
40extern int32 sim_switches;\r
41\r
42void fprint_addr (FILE *of, uint32 val, uint32 mod, uint32 dst);\r
43\r
44/* SCP data structures and interface routines\r
45\r
46 sim_name simulator name string\r
47 sim_PC pointer to saved PC register descriptor\r
48 sim_emax maximum number of words for examine/deposit\r
49 sim_devices array of pointers to simulated devices\r
50 sim_stop_messages array of pointers to stop messages\r
51 sim_load binary loader\r
52*/\r
53\r
54char sim_name[] = "GRI-909";\r
55\r
56REG *sim_PC = &cpu_reg[0];\r
57\r
58int32 sim_emax = 2;\r
59\r
60DEVICE *sim_devices[] = {\r
61 &cpu_dev,\r
62 &tti_dev,\r
63 &tto_dev,\r
64 &hsr_dev,\r
65 &hsp_dev,\r
66 &rtc_dev,\r
67 NULL\r
68 };\r
69\r
70const char *sim_stop_messages[] = {\r
71 "Unknown error",\r
72 "Unimplemented unit",\r
73 "HALT instruction",\r
74 "Breakpoint",\r
75 "Invalid interrupt request"\r
76 };\r
77\r
78/* Binary loader\r
79\r
80 Bootstrap loader format consists of blocks separated by zeroes. Each\r
81 word in the block has three frames: a control frame (ignored) and two\r
82 data frames. The user must specify the load address. Switch -c means\r
83 continue and load all blocks until end of tape.\r
84*/\r
85\r
86t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)\r
87{\r
88int32 c;\r
89uint32 org;\r
90t_stat r;\r
91char gbuf[CBUFSIZE];\r
92\r
93if (*cptr != 0) { /* more input? */\r
94 cptr = get_glyph (cptr, gbuf, 0); /* get origin */\r
95 org = get_uint (gbuf, 8, AMASK, &r);\r
96 if (r != SCPE_OK) return r;\r
97 if (*cptr != 0) return SCPE_ARG; /* no more */\r
98 }\r
99else org = 0200; /* default 200 */\r
100\r
101for (;;) { /* until EOF */\r
102 while ((c = getc (fileref)) == 0) ; /* skip starting 0's */\r
103 if (c == EOF) break; /* EOF? done */\r
104 for ( ; c != 0; ) { /* loop until ctl = 0 */\r
105 /* ign ctrl frame */\r
106 if ((c = getc (fileref)) == EOF) /* get high byte */\r
107 return SCPE_FMT; /* EOF is error */\r
108 if (!MEM_ADDR_OK (org)) return SCPE_NXM;\r
109 M[org] = ((c & 0377) << 8); /* store high */\r
110 if ((c = getc (fileref)) == EOF) /* get low byte */\r
111 return SCPE_FMT; /* EOF is error */\r
112 M[org] = M[org] | (c & 0377); /* store low */\r
113 org = org + 1; /* incr origin */\r
114 if ((c = getc (fileref)) == EOF) /* get ctrl frame */\r
115 return SCPE_OK; /* EOF is ok */\r
116 } /* end block for */\r
117 if (!(sim_switches & SWMASK ('C'))) return SCPE_OK;\r
118 } /* end tape for */\r
119return SCPE_OK;\r
120}\r
121\r
122/* Symbol tables */\r
123\r
124#define F_V_FL 16 /* class flag */\r
125#define F_M_FL 017\r
126#define F_V_FO 000 /* function out */\r
127#define F_V_FOI 001 /* FO, impl reg */\r
128#define F_V_SF 002 /* skip function */\r
129#define F_V_SFI 003 /* SF, impl reg */\r
130#define F_V_RR 004 /* reg reg */\r
131#define F_V_ZR 005 /* zero reg */\r
132#define F_V_RS 006 /* reg self */\r
133#define F_V_JC 010 /* jump cond */\r
134#define F_V_JU 011 /* jump uncond */\r
135#define F_V_RM 012 /* reg mem */\r
136#define F_V_ZM 013 /* zero mem */\r
137#define F_V_MR 014 /* mem reg */\r
138#define F_V_MS 015 /* mem self */\r
139#define F_2WD 010 /* 2 words */\r
140\r
141#define F_FO (F_V_FO << F_V_FL)\r
142#define F_FOI (F_V_FOI << F_V_FL)\r
143#define F_SF (F_V_SF << F_V_FL)\r
144#define F_SFI (F_V_SFI << F_V_FL)\r
145#define F_RR (F_V_RR << F_V_FL)\r
146#define F_ZR (F_V_ZR << F_V_FL)\r
147#define F_RS (F_V_RS << F_V_FL)\r
148#define F_JC (F_V_JC << F_V_FL)\r
149#define F_JU (F_V_JU << F_V_FL)\r
150#define F_RM (F_V_RM << F_V_FL)\r
151#define F_ZM (F_V_ZM << F_V_FL)\r
152#define F_MR (F_V_MR << F_V_FL)\r
153#define F_MS (F_V_MS << F_V_FL)\r
154\r
155struct fnc_op {\r
156 uint32 inst; /* instr prot */\r
157 uint32 imask; /* instr mask */\r
158 uint32 oper; /* operator */\r
159 uint32 omask; /* oper mask */\r
160 };\r
161\r
162static const int32 masks[] = {\r
163 0176000, 0176077, 0000077, 0176077,\r
164 0000300, 0176300, 0000300, 0177777,\r
165 0000077, 0177777, 0000377, 0176377,\r
166 0176300, 0176377\r
167 };\r
168\r
169/* Instruction mnemonics\r
170\r
171 Order is critical, as some instructions are more precise versions of\r
172 others. For example, JU must precede JC, otherwise, JU will be decoded\r
173 as JC 0,ETZ,dst. There are some ambiguities, eg, what is 02-xxxx-06?\r
174 Priority is as follows:\r
175\r
176 FO (02-xxxx-rr)\r
177 SF (rr-xxxx-02)\r
178 MR (06-xxxx-rr)\r
179 RM (rr-xxxx-06)\r
180 JC (rr-xxxx-03)\r
181 RR \r
182*/\r
183\r
184static const char *opcode[] = {\r
185 "FOM", "FOA", "FOI", "FO", /* FOx before FO */\r
186 "SFM", "SFA", "SFI", "SF", /* SFx before SF */\r
187 "ZM", "ZMD", "ZMI", "ZMID", /* ZM before RM */\r
188 "MS", "MSD", "MSI", "MSID",\r
189 "RM", "RMD", "RMI", "RMID",\r
190 "MR", "MRD", "MRI", "MRID",\r
191 "JO", "JOD", "JN", "JND", /* JU before JC */\r
192 "JU", "JUD", "JC", "JCD",\r
193 "ZR", "ZRC", "RR", "RRC", /* ZR before RR */\r
194 "RS", "RSC",\r
195 NULL\r
196 };\r
197\r
198static const uint32 opc_val[] = {\r
199 0004000+F_FOI, 0004013+F_FOI, 0004004+F_FOI, 0004000+F_FO,\r
200 0000002+F_SFI, 0026002+F_SFI, 0010002+F_SFI, 0000002+F_SF,\r
201 0000006+F_ZM, 0000106+F_ZM, 0000206+F_ZM, 0000306+F_ZM,\r
202 0014006+F_MS, 0014106+F_MS, 0014206+F_MS, 0014306+F_MS,\r
203 0000006+F_RM, 0000106+F_RM, 0000206+F_RM, 0000306+F_RM,\r
204 0014000+F_MR, 0014100+F_MR, 0014200+F_MR, 0014300+F_MR,\r
205 0037003+F_JU, 0037103+F_JU, 0037203+F_JU, 0037303+F_JU,\r
206 0000403+F_JU, 0000503+F_JU, 0000003+F_JC, 0000103+F_JC,\r
207 0000000+F_ZR, 0000200+F_ZR, 0000000+F_RR, 0000200+F_RR,\r
208 0000000+F_RS, 0000200+F_RS\r
209 };\r
210\r
211/* Unit mnemonics. All 64 units are decoded, most just to octal integers */\r
212\r
213static const char *unsrc[64] = {\r
214 "0", "IR", "2", "TRP", "ISR", "MA", "MB", "SC", /* 00 - 07 */\r
215 "SWR", "AX", "AY", "AO", "14", "15", "16", "MSR", /* 10 - 17 */\r
216 "20", "21", "XR", "ATRP", "BSW", "BPK", "BCPA", "BCPB",/* 20 - 27 */\r
217 "GR1", "GR2", "GR3", "GR4", "GR5", "GR6", "36", "37", /* 30 - 37 */\r
218 "40", "41", "42", "43", "44", "45", "46", "47",\r
219 "50", "51", "52", "53", "54", "CDR", "56", "CADR",\r
220 "60", "61", "62", "63", "64", "65", "DWC", "DCA",\r
221 "DISK", "LPR", "72", "73", "CAS", "RTC", "HSR", "TTI" /* 70 - 77 */\r
222 };\r
223\r
224static const char *undst[64] = {\r
225 "0", "IR", "2", "TRP", "ISR", "5", "MB", "SC", /* 00 - 07 */\r
226 "SWR", "AX", "AY", "13", "EAO", "15", "16", "MSR", /* 10 - 17 */\r
227 "20", "21", "XR", "ATRP", "BSW", "BPK", "BCPA", "BCPB",/* 20 - 27 */\r
228 "GR1", "GR2", "GR3", "GR4", "GR5", "GR6", "36", "37", /* 30 - 37 */\r
229 "40", "41", "42", "43", "44", "45", "46", "47",\r
230 "50", "51", "52", "53", "54", "CDR", "56", "CADR",\r
231 "60", "61", "62", "63", "64", "65", "DWC", "DCA",\r
232 "DISK", "LPR", "72", "73", "CAS", "RTC", "HSP", "TTO" /* 70 - 77 */\r
233 };\r
234\r
235/* Operators */\r
236\r
237static const char *opname[4] = {\r
238 NULL, "P1", "L1", "R1"\r
239 };\r
240\r
241/* Conditions */\r
242\r
243static const char *cdname[8] = {\r
244 "NEVER", "ALWAYS", "ETZ", "NEZ", "LTZ", "GEZ", "LEZ", "GTZ"\r
245 };\r
246\r
247/* Function out/sense function */\r
248\r
249static const char *fname[] = {\r
250 "NOT", /* any SF */\r
251 "POK", "LNK", "BOV", /* SFM */\r
252 "SOV", "AOV", /* SFA */\r
253 "IRDY", "ORDY", /* any SF */\r
254 "CLL", "STL", "CML", "HLT", /* FOM */\r
255 "ICF", "ICO", /* FOI */\r
256 "ADD", "AND", "XOR", "OR", /* FOA */\r
257 "INP", "IRDY", "ORDY", "STRT", /* any FO */\r
258 NULL\r
259 };\r
260\r
261static const struct fnc_op fop[] = {\r
262 { 0000002, 0000077, 001, 001 }, /* NOT */\r
263 { 0000002, 0176077, 010, 010 }, /* POK */\r
264 { 0000002, 0176077, 004, 004 }, /* LNK */\r
265 { 0000002, 0176077, 002, 002 }, /* BOV */\r
266 { 0026002, 0176077, 004, 004 }, /* SOV */\r
267 { 0026002, 0176077, 002, 002 }, /* AOV */\r
268 { 0000002, 0000077, 010, 010 }, /* IRDY */\r
269 { 0000002, 0000077, 002, 002 }, /* ORDY */\r
270 { 0004000, 0176077, 001, 003 }, /* CLL */\r
271 { 0004000, 0176077, 002, 003 }, /* STL */\r
272 { 0004000, 0176077, 003, 003 }, /* CML */\r
273 { 0004000, 0176077, 004, 004 }, /* HLT */\r
274 { 0004004, 0176077, 001, 001 }, /* ICF */\r
275 { 0004004, 0176077, 002, 002 }, /* ICO */\r
276 { 0004013, 0176077, 000, 014 }, /* ADD */\r
277 { 0004013, 0176077, 004, 014 }, /* AND */\r
278 { 0004013, 0176077, 010, 014 }, /* XOR */\r
279 { 0004013, 0176077, 014, 014 }, /* OR */\r
280 { 0004000, 0176000, 011, 011 }, /* INP */\r
281 { 0004000, 0176000, 010, 010 }, /* IRDY */\r
282 { 0004000, 0176000, 002, 002 }, /* ORDY */\r
283 { 0004000, 0176000, 001, 001 } /* STRT */\r
284 };\r
285\r
286/* Print opcode field for FO, SF */\r
287\r
288void fprint_op (FILE *of, uint32 inst, uint32 op)\r
289{\r
290int32 i, nfirst;\r
291\r
292for (i = nfirst = 0; fname[i] != NULL; i++) {\r
293 if (((inst & fop[i].imask) == fop[i].inst) &&\r
294 ((op & fop[i].omask) == fop[i].oper)) {\r
295 op = op & ~fop[i].omask;\r
296 if (nfirst) fputc (' ', of);\r
297 nfirst = 1;\r
298 fprintf (of, "%s", fname[i]);\r
299 }\r
300 }\r
301if (op) fprintf (of, " %o", op);\r
302return;\r
303}\r
304\r
305/* Print address field with potential indexing */\r
306\r
307void fprint_addr (FILE *of, uint32 val, uint32 mode, uint32 dst)\r
308{\r
309if ((val & INDEX) &&\r
310 ((dst == U_SC) || (mode != MEM_IMM)))\r
311 fprintf (of, "#%o", val & AMASK);\r
312else fprintf (of, "%o", val);\r
313return;\r
314}\r
315\r
316/* Symbolic decode\r
317\r
318 Inputs:\r
319 *of = output stream\r
320 addr = current PC\r
321 *val = pointer to data\r
322 *uptr = pointer to unit \r
323 sw = switches\r
324 Outputs:\r
325 return = status code\r
326*/\r
327\r
328#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)\r
329\r
330t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,\r
331 UNIT *uptr, int32 sw)\r
332{\r
333int32 i, j;\r
334uint32 inst, src, dst, op, bop;\r
335\r
336inst = val[0];\r
337if (sw & SWMASK ('A')) { /* ASCII? */\r
338 if (inst > 0377) return SCPE_ARG;\r
339 fprintf (of, FMTASC (inst & 0177));\r
340 return SCPE_OK;\r
341 }\r
342if (sw & SWMASK ('C')) { /* characters? */\r
343 fprintf (of, FMTASC ((inst >> 8) & 0177));\r
344 fprintf (of, FMTASC (inst & 0177));\r
345 return SCPE_OK;\r
346 }\r
347if (!(sw & SWMASK ('M'))) return SCPE_ARG;\r
348\r
349/* Instruction decode */\r
350\r
351inst = val[0];\r
352src = I_GETSRC (inst); /* get fields */\r
353op = I_GETOP (inst);\r
354dst = I_GETDST (inst);\r
355bop = op >> 2; /* bus op */\r
356for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */\r
357 j = (opc_val[i] >> F_V_FL) & F_M_FL; /* get class */\r
358 if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */\r
359\r
360 switch (j) { /* case on class */\r
361\r
362 case F_V_FO: /* func out */\r
363 fprintf (of, "%s ", opcode[i]);\r
364 fprint_op (of, inst, op);\r
365 fprintf (of, ",%s", undst[dst]);\r
366 break;\r
367\r
368 case F_V_FOI: /* func out impl */\r
369 fprintf (of, "%s ", opcode[i]);\r
370 fprint_op (of, inst, op);\r
371 break;\r
372\r
373 case F_V_SF: /* skip func */\r
374 fprintf (of, "%s %s,", opcode[i], unsrc[src]);\r
375 fprint_op (of, inst, op);\r
376 break;\r
377\r
378 case F_V_SFI: /* skip func impl */\r
379 fprintf (of, "%s ", opcode[i]);\r
380 fprint_op (of, inst, op);\r
381 break;\r
382\r
383 case F_V_RR: /* reg reg */\r
384 if (strcmp (unsrc[src], undst[dst]) == 0) {\r
385 if (bop) fprintf (of, "%s %s,%s", opcode[i + 2],\r
386 unsrc[src], opname[bop]);\r
387 else fprintf (of, "%s %s", opcode[i + 2], unsrc[src]);\r
388 }\r
389 else {\r
390 if (bop) fprintf (of, "%s %s,%s,%s", opcode[i],\r
391 unsrc[src], opname[bop], undst[dst]);\r
392 else fprintf (of, "%s %s,%s", opcode[i],\r
393 unsrc[src], undst[dst]);\r
394 }\r
395 break;\r
396\r
397 case F_V_ZR: /* zero reg */\r
398 if (bop) fprintf (of, "%s %s,%s", opcode[i],\r
399 opname[bop], undst[dst]);\r
400 else fprintf (of, "%s %s", opcode[i], undst[dst]);\r
401 break;\r
402\r
403 case F_V_JC: /* jump cond */\r
404 fprintf (of, "%s %s,%s,",\r
405 opcode[i], unsrc[src], cdname[op >> 1]);\r
406 fprint_addr (of, val[1], 0, U_SC);\r
407 break;\r
408\r
409 case F_V_JU: /* jump uncond */\r
410 fprintf (of, "%s ", opcode[i]);\r
411 fprint_addr (of, val[1], 0, U_SC);\r
412 break;\r
413\r
414 case F_V_RM: /* reg mem */\r
415 if (bop) fprintf (of, "%s %s,%s,",\r
416 opcode[i], unsrc[src], opname[bop]);\r
417 else fprintf (of, "%s %s,", opcode[i], unsrc[src]);\r
418 fprint_addr (of, val[1], op & MEM_MOD, dst);\r
419 break;\r
420\r
421 case F_V_ZM: /* zero mem */\r
422 if (bop) fprintf (of, "%s %s,", opcode[i], opname[bop]);\r
423 else fprintf (of, "%s ", opcode[i]);\r
424 fprint_addr (of, val[1], op & MEM_MOD, dst);\r
425 break;\r
426\r
427 case F_V_MR: /* mem reg */\r
428 fprintf (of, "%s ", opcode[i]);\r
429 fprint_addr (of, val[1], op & MEM_MOD, dst);\r
430 if (bop) fprintf (of, ",%s,%s", opname[bop], undst[dst]);\r
431 else fprintf (of, ",%s", undst[dst]);\r
432 break;\r
433\r
434 case F_V_MS: /* mem self */\r
435 fprintf (of, "%s ", opcode[i]);\r
436 fprint_addr (of, val[1], op & MEM_MOD, dst);\r
437 if (bop) fprintf (of, ",%s", opname[bop]);\r
438 break;\r
439 } /* end case */\r
440\r
441 return (j >= F_2WD)? -1: SCPE_OK;\r
442 } /* end if */\r
443 } /* end for */\r
444return SCPE_ARG;\r
445}\r
446\r
447/* Field parse routines\r
448\r
449 get_fnc get function field\r
450 get_ma get memory address\r
451 get_sd get source or dest\r
452 get_op get optional bus operator\r
453*/\r
454\r
455char *get_fnc (char *cptr, t_value *val)\r
456{\r
457char gbuf[CBUFSIZE];\r
458int32 i;\r
459t_value d;\r
460t_stat r;\r
461uint32 inst = val[0];\r
462uint32 fncv = 0, fncm = 0;\r
463\r
464while (*cptr) {\r
465 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */\r
466 d = get_uint (gbuf, 8, 017, &r); /* octal? */\r
467 if (r == SCPE_OK) { /* ok? */\r
468 if (d & fncm) return NULL; /* already filled? */\r
469 fncv = fncv | d; /* save */\r
470 fncm = fncm | d; /* field filled */\r
471 }\r
472 else { /* symbol? */\r
473 for (i = 0; fname[i] != NULL; i++) { /* search table */\r
474 if ((strcmp (gbuf, fname[i]) == 0) && /* match for inst? */\r
475 ((inst & fop[i].imask) == fop[i].inst)) {\r
476 if (fop[i].oper & fncm) return NULL; /* already filled? */\r
477 fncm = fncm | fop[i].omask;\r
478 fncv = fncv | fop[i].oper;\r
479 break;\r
480 }\r
481 }\r
482 if (fname[i] == NULL) return NULL;\r
483 } /* end else */\r
484 } /* end while */\r
485val[0] = val[0] | (fncv << I_V_OP); /* store fnc */\r
486return cptr;\r
487}\r
488\r
489char *get_ma (char *cptr, t_value *val, char term)\r
490{\r
491char gbuf[CBUFSIZE];\r
492t_value d;\r
493t_stat r;\r
494\r
495cptr = get_glyph (cptr, gbuf, term); /* get glyph */\r
496if (gbuf[0] == '#') /* indexed? */\r
497 d = get_uint (gbuf + 1, 8, AMASK, &r) | INDEX; /* [0, 77777] */\r
498else d = get_uint (gbuf, 8, DMASK, &r); /* [0,177777] */\r
499if (r != SCPE_OK) return NULL;\r
500val[1] = d; /* second wd */\r
501return cptr;\r
502}\r
503\r
504char *get_sd (char *cptr, t_value *val, char term, t_bool src)\r
505{\r
506char gbuf[CBUFSIZE];\r
507int32 d;\r
508t_stat r;\r
509\r
510cptr = get_glyph (cptr, gbuf, term); /* get glyph */\r
511for (d = 0; d < 64; d++) { /* symbol match? */\r
512 if ((strcmp (gbuf, unsrc[d]) == 0) ||\r
513 (strcmp (gbuf, undst[d]) == 0)) break;\r
514 }\r
515if (d >= 64) { /* no, [0,63]? */\r
516 d = get_uint (gbuf, 8, 077, &r);\r
517 if (r != SCPE_OK) return NULL;\r
518 }\r
519val[0] = val[0] | (d << (src? I_V_SRC: I_V_DST)); /* or to inst */\r
520return cptr;\r
521}\r
522\r
523char *get_op (char *cptr, t_value *val, char term)\r
524{\r
525char gbuf[CBUFSIZE], *tptr;\r
526int32 i;\r
527\r
528tptr = get_glyph (cptr, gbuf, term); /* get glyph */\r
529for (i = 1; i < 4; i++) { /* symbol match? */\r
530 if (strcmp (gbuf, opname[i]) == 0) {\r
531 val[0] = val[0] | (i << (I_V_OP + 2)); /* or to inst */\r
532 return tptr;\r
533 }\r
534 }\r
535return cptr; /* original ptr */\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 i, j, k;\r
553char *tptr, gbuf[CBUFSIZE];\r
554\r
555while (isspace (*cptr)) cptr++; /* absorb spaces */\r
556if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */\r
557 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
558 val[0] = (t_value) cptr[0] & 0177;\r
559 return SCPE_OK;\r
560 }\r
561if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */\r
562 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */\r
563 val[0] = (((t_value) cptr[0] & 0177) << 8) |\r
564 ((t_value) cptr[1] & 0177);\r
565 return SCPE_OK;\r
566 }\r
567\r
568/* Instruction parse */\r
569\r
570cptr = get_glyph (cptr, gbuf, 0); /* get opcode */\r
571for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;\r
572if (opcode[i] == NULL) return SCPE_ARG;\r
573val[0] = opc_val[i] & DMASK; /* get value */\r
574j = (opc_val[i] >> F_V_FL) & F_M_FL; /* get class */\r
575\r
576switch (j) { /* case on class */\r
577\r
578 case F_V_FO: /* func out */\r
579 tptr = strchr (cptr, ','); /* find dst */\r
580 if (!tptr) return SCPE_ARG; /* none? */\r
581 *tptr = 0; /* split fields */\r
582 cptr = get_fnc (cptr, val); /* fo # */\r
583 if (!cptr) return SCPE_ARG;\r
584 cptr = get_sd (tptr + 1, val, 0, FALSE); /* dst */\r
585 break;\r
586\r
587 case F_V_FOI: /* func out impl */\r
588 cptr = get_fnc (cptr, val); /* fo # */\r
589 break;\r
590\r
591 case F_V_SF: /* skip func */\r
592 cptr = get_sd (cptr, val, ',', TRUE); /* src */\r
593 if (!cptr) return SCPE_ARG;\r
594\r
595 case F_V_SFI: /* skip func impl */\r
596 cptr = get_fnc (cptr, val); /* fo # */\r
597 break;\r
598\r
599 case F_V_RR: /* reg-reg */\r
600 cptr = get_sd (cptr, val, ',', TRUE); /* src */\r
601 if (!cptr) return SCPE_ARG;\r
602 cptr = get_op (cptr, val, ','); /* op */\r
603 if (!cptr) return SCPE_ARG;\r
604 cptr = get_sd (cptr, val, 0, FALSE); /* dst */\r
605 break;\r
606\r
607 case F_V_ZR: /* zero-reg */\r
608 cptr = get_op (cptr, val, ','); /* op */\r
609 if (!cptr) return SCPE_ARG;\r
610 cptr = get_sd (cptr, val, 0, FALSE); /* dst */\r
611 break;\r
612\r
613 case F_V_RS: /* reg self */\r
614 cptr = get_sd (cptr, val, ',', TRUE); /* src */\r
615 if (!cptr) return SCPE_ARG;\r
616 val[0] = val[0] | I_GETSRC (val[0]); /* duplicate */\r
617 cptr = get_op (cptr, val, 0); /* op */\r
618 break;\r
619\r
620 case F_V_JC: /* jump cond */\r
621 cptr = get_sd (cptr, val, ',', TRUE); /* src */\r
622 if (!cptr) return SCPE_ARG;\r
623 cptr = get_glyph (cptr, gbuf, ','); /* cond */\r
624 for (k = 0; k < 8; k++) { /* symbol? */\r
625 if (strcmp (gbuf, cdname[k]) == 0) break;\r
626 }\r
627 if (k >= 8) return SCPE_ARG;\r
628 val[0] = val[0] | (k << (I_V_OP + 1)); /* or to inst */\r
629\r
630 case F_V_JU: /* jump uncond */\r
631 cptr = get_ma (cptr, val, 0); /* addr */\r
632 break;\r
633\r
634 case F_V_RM: /* reg mem */\r
635 cptr = get_sd (cptr, val, ',', TRUE); /* src */\r
636 if (!cptr) return SCPE_ARG;\r
637 case F_V_ZM: /* zero mem */\r
638 cptr = get_op (cptr, val, ','); /* op */\r
639 if (!cptr) return SCPE_ARG;\r
640 cptr = get_ma (cptr, val, 0); /* addr */\r
641 break;\r
642\r
643 case F_V_MR: /* mem reg */\r
644 cptr = get_ma (cptr, val, ','); /* addr */\r
645 if (!cptr) return SCPE_ARG;\r
646 cptr = get_op (cptr, val, ','); /* op */\r
647 if (!cptr) return SCPE_ARG;\r
648 cptr = get_sd (cptr, val, 0, FALSE); /* dst */\r
649 break;\r
650\r
651 case F_V_MS: /* mem self */\r
652 cptr = get_ma (cptr, val, ','); /* addr */\r
653 if (!cptr) return SCPE_ARG;\r
654 cptr = get_op (cptr, val, 0); /* op */\r
655 break;\r
656 } /* end case */\r
657\r
658if (!cptr || (*cptr != 0)) return SCPE_ARG; /* junk at end? */\r
659return (j >= F_2WD)? -1: SCPE_OK;\r
660}\r