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