1 /* gri_sys.c: GRI-909 simulator interface
3 Copyright (c) 2001-2008, Robert M Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
26 14-Jan-08 RMS Added GRI-99 support
27 18-Oct-02 RMS Fixed bug in symbolic decode (found by Hans Pufal)
33 extern DEVICE cpu_dev
;
35 extern DEVICE tti_dev
, tto_dev
;
36 extern DEVICE hsr_dev
, hsp_dev
;
37 extern DEVICE rtc_dev
;
40 extern int32 sim_switches
;
42 void fprint_addr (FILE *of
, uint32 val
, uint32 mod
, uint32 dst
);
44 /* SCP data structures and interface routines
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
54 char sim_name
[] = "GRI-909";
56 REG
*sim_PC
= &cpu_reg
[0];
60 DEVICE
*sim_devices
[] = {
70 const char *sim_stop_messages
[] = {
75 "Invalid interrupt request"
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.
86 t_stat
sim_load (FILE *fileref
, char *cptr
, char *fnam
, int flag
)
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 */
99 else org
= 0200; /* default 200 */
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 */
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
;
124 #define F_V_FL 16 /* class flag */
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 */
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)
156 uint32 inst
; /* instr prot */
157 uint32 imask
; /* instr mask */
158 uint32 oper
; /* operator */
159 uint32 omask
; /* oper mask */
162 static const int32 masks
[] = {
163 0176000, 0176077, 0000077, 0176077,
164 0000300, 0176300, 0000300, 0177777,
165 0000077, 0177777, 0000377, 0176377,
169 /* Instruction mnemonics
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:
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 */
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
211 /* Unit mnemonics. All 64 units are decoded, most just to octal integers */
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 */
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 */
237 static const char *opname
[4] = {
238 NULL
, "P1", "L1", "R1"
243 static const char *cdname
[8] = {
244 "NEVER", "ALWAYS", "ETZ", "NEZ", "LTZ", "GEZ", "LEZ", "GTZ"
247 /* Function out/sense function */
249 static const char *fname
[] = {
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 */
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 */
286 /* Print opcode field for FO, SF */
288 void fprint_op (FILE *of
, uint32 inst
, uint32 op
)
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
);
298 fprintf (of
, "%s", fname
[i
]);
301 if (op
) fprintf (of
, " %o", op
);
305 /* Print address field with potential indexing */
307 void fprint_addr (FILE *of
, uint32 val
, uint32 mode
, uint32 dst
)
310 ((dst
== U_SC
) || (mode
!= MEM_IMM
)))
311 fprintf (of
, "#%o", val
& AMASK
);
312 else fprintf (of
, "%o", val
);
321 *val = pointer to data
322 *uptr = pointer to unit
328 #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
330 t_stat
fprint_sym (FILE *of
, t_addr addr
, t_value
*val
,
331 UNIT
*uptr
, int32 sw
)
334 uint32 inst
, src
, dst
, op
, bop
;
337 if (sw
& SWMASK ('A')) { /* ASCII? */
338 if (inst
> 0377) return SCPE_ARG
;
339 fprintf (of
, FMTASC (inst
& 0177));
342 if (sw
& SWMASK ('C')) { /* characters? */
343 fprintf (of
, FMTASC ((inst
>> 8) & 0177));
344 fprintf (of
, FMTASC (inst
& 0177));
347 if (!(sw
& SWMASK ('M'))) return SCPE_ARG
;
349 /* Instruction decode */
352 src
= I_GETSRC (inst
); /* get fields */
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? */
360 switch (j
) { /* case on class */
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
]);
368 case F_V_FOI
: /* func out impl */
369 fprintf (of
, "%s ", opcode
[i
]);
370 fprint_op (of
, inst
, op
);
373 case F_V_SF
: /* skip func */
374 fprintf (of
, "%s %s,", opcode
[i
], unsrc
[src
]);
375 fprint_op (of
, inst
, op
);
378 case F_V_SFI
: /* skip func impl */
379 fprintf (of
, "%s ", opcode
[i
]);
380 fprint_op (of
, inst
, op
);
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
]);
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
]);
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
]);
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
);
409 case F_V_JU
: /* jump uncond */
410 fprintf (of
, "%s ", opcode
[i
]);
411 fprint_addr (of
, val
[1], 0, U_SC
);
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
);
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
);
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
]);
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
]);
441 return (j
>= F_2WD
)? -1: SCPE_OK
;
447 /* Field parse routines
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
455 char *get_fnc (char *cptr
, t_value
*val
)
461 uint32 inst
= val
[0];
462 uint32 fncv
= 0, fncm
= 0;
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 */
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
;
482 if (fname
[i
] == NULL
) return NULL
;
485 val
[0] = val
[0] | (fncv
<< I_V_OP
); /* store fnc */
489 char *get_ma (char *cptr
, t_value
*val
, char term
)
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 */
504 char *get_sd (char *cptr
, t_value
*val
, char term
, t_bool src
)
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;
515 if (d
>= 64) { /* no, [0,63]? */
516 d
= get_uint (gbuf
, 8, 077, &r
);
517 if (r
!= SCPE_OK
) return NULL
;
519 val
[0] = val
[0] | (d
<< (src
? I_V_SRC
: I_V_DST
)); /* or to inst */
523 char *get_op (char *cptr
, t_value
*val
, char term
)
525 char gbuf
[CBUFSIZE
], *tptr
;
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 */
535 return cptr
; /* original ptr */
541 *cptr = pointer to input string
543 *uptr = pointer to unit
544 *val = pointer to output values
547 status = error status
550 t_stat
parse_sym (char *cptr
, t_addr addr
, UNIT
*uptr
, t_value
*val
, int32 sw
)
553 char *tptr
, gbuf
[CBUFSIZE
];
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;
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);
568 /* Instruction parse */
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 */
576 switch (j
) { /* case on class */
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 */
587 case F_V_FOI
: /* func out impl */
588 cptr
= get_fnc (cptr
, val
); /* fo # */
591 case F_V_SF
: /* skip func */
592 cptr
= get_sd (cptr
, val
, ',', TRUE
); /* src */
593 if (!cptr
) return SCPE_ARG
;
595 case F_V_SFI
: /* skip func impl */
596 cptr
= get_fnc (cptr
, val
); /* fo # */
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 */
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 */
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 */
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;
627 if (k
>= 8) return SCPE_ARG
;
628 val
[0] = val
[0] | (k
<< (I_V_OP
+ 1)); /* or to inst */
630 case F_V_JU
: /* jump uncond */
631 cptr
= get_ma (cptr
, val
, 0); /* addr */
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 */
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 */
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 */
658 if (!cptr
|| (*cptr
!= 0)) return SCPE_ARG
; /* junk at end? */
659 return (j
>= F_2WD
)? -1: SCPE_OK
;