1 /* pdp10_sys.c: PDP-10 simulator interface
2 
3    Copyright (c) 1993-2011, 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    04-Apr-11    RMS     Removed DEUNA/DELUA support - never implemented
27    01-Feb-07    RMS     Added CD support
28    22-Jul-05    RMS     Fixed warning from Solaris C (from Doug Gwyn)
29    09-Jan-03    RMS     Added DEUNA/DELUA support
30    12-Sep-02    RMS     Added RX211 support
31    22-Apr-02    RMS     Removed magtape record length error
32    17-Sep-01    RMS     Removed multiconsole support
33    25-Aug-01    RMS     Enabled DZ11
34    27-May-01    RMS     Added multiconsole support
35    29-Apr-01    RMS     Fixed format for RDPCST, WRPCST
36                         Added CLRCSH for ITS
37    03-Apr-01    RMS     Added support for loading EXE files
38    19-Mar-01    RMS     Added support for loading SAV files
39    30-Oct-00    RMS     Added support for examine to file
40 */
41 
42 #include "pdp10_defs.h"
43 #include <ctype.h>
44 
45 extern DEVICE cpu_dev;
46 extern DEVICE pag_dev;
47 extern DEVICE tim_dev;
48 extern DEVICE fe_dev;
49 extern DEVICE uba_dev;
50 extern DEVICE ptr_dev;
51 extern DEVICE ptp_dev;
52 extern DEVICE rp_dev;
53 extern DEVICE tu_dev;
54 extern DEVICE dz_dev;
55 extern DEVICE ry_dev;
56 extern DEVICE cr_dev;
57 extern DEVICE lp20_dev;
58 extern UNIT cpu_unit;
59 extern REG cpu_reg[];
60 extern d10 *M;
61 extern a10 saved_PC;
62 
63 /* SCP data structures and interface routines
64 
65    sim_name             simulator name string
66    sim_PC               pointer to saved PC register descriptor
67    sim_emax             number of words for examine
68    sim_devices          array of pointers to simulated devices
69    sim_stop_messages    array of pointers to stop messages
70    sim_load             binary loader
71 */
72 
73 char sim_name[] = "PDP-10";
74 
75 REG *sim_PC = &cpu_reg[0];
76 
77 int32 sim_emax = 1;
78 
79 DEVICE *sim_devices[] = {
80     &cpu_dev,
81     &pag_dev,
82     &tim_dev,
83     &fe_dev,
84     &uba_dev,
85     &ptr_dev,
86     &ptp_dev,
87     &ry_dev,
88     &lp20_dev,
89     &cr_dev,
90     &rp_dev,
91     &tu_dev,
92     &dz_dev,
93     NULL
94     };
95 
96 const char *sim_stop_messages[] = {
97     "Unknown error",
98     "HALT instruction",
99     "Breakpoint",
100     "Illegal instruction",
101     "Illegal interrupt instruction",
102     "Paging error in interrupt",
103     "Zero vector table",
104     "NXM on UPT/EPT reference",
105     "Nested indirect address limit exceeded",
106     "Nested XCT limit exceeded",
107     "Invalid I/O controller",
108     "Address stop",
109     "Panic stop"
110      };
111 
112 /* Binary loader, supports RIM10, SAV, EXE */
113 
114 #define FMT_R   1                                       /* RIM10 */
115 #define FMT_S   2                                       /* SAV */
116 #define FMT_E   3                                       /* EXE */
117 
118 #define EXE_DIR 01776                                   /* EXE directory */
119 #define EXE_VEC 01775                                   /* EXE entry vec */
120 #define EXE_PDV 01774                                   /* EXE ignored */
121 #define EXE_END 01777                                   /* EXE end
122 
123 /* RIM10 loader
124 
125    RIM10 format is a binary paper tape format (all data frames
126    are 200 or greater).  It consists of blocks containing
127 
128         -count,,origin-1
129         word
130         :
131         word
132         checksum (includes IOWD)
133         :
134         JRST start
135 */
136 
getrimw(FILE * fileref)137 d10 getrimw (FILE *fileref)
138 {
139 int32 i, tmp;
140 d10 word;
141 
142 word = 0;
143 for (i = 0; i < 6;) {
144     if ((tmp = getc (fileref)) == EOF)
145         return -1;
146     if (tmp & 0200) {
147         word = (word << 6) | ((d10) tmp & 077);
148         i++;
149         }
150     }
151 return word;
152 }
153 
load_rim(FILE * fileref)154 t_stat load_rim (FILE *fileref)
155 {
156 d10 count, cksm, data;
157 a10 pa;
158 int32 op;
159 
160 for ( ;; ) {                                            /* loop until JRST */
161     count = cksm = getrimw (fileref);                   /* get header */
162     if (count < 0)                                      /* read err? */
163         return SCPE_FMT;
164     if (TSTS (count)) {                                 /* hdr = IOWD? */
165         for ( ; TSTS (count); count = AOB (count)) {
166             data = getrimw (fileref);                   /* get data wd */
167             if (data < 0)
168                 return SCPE_FMT;
169             cksm = cksm + data;                         /* add to cksm */
170             pa = ((a10) count + 1) & AMASK;             /* store */
171             M[pa] = data;
172             }                                           /* end for */
173         data = getrimw (fileref);                       /* get cksm */
174         if (data < 0)
175             return SCPE_FMT;
176         if ((cksm + data) & DMASK)                      /* test cksm */
177             return SCPE_CSUM;
178         }                                               /* end if count */
179     else {
180         op = GET_OP (count);                            /* not IOWD */
181         if (op != OP_JRST)                              /* JRST? */
182             return SCPE_FMT;
183         saved_PC = (a10) count & AMASK;                 /* set PC */
184         break;
185         }                                               /* end else */
186     }                                                   /* end for */
187 return SCPE_OK;
188 }
189 
190 /* SAV file loader
191 
192    SAV format is a disk file format (36b words).  It consists of
193    blocks containing:
194 
195         -count,,origin-1
196         word
197         :
198         word
199         :
200         JRST start
201 */
202 
load_sav(FILE * fileref)203 t_stat load_sav (FILE *fileref)
204 {
205 d10 count, data;
206 a10 pa;
207 int32 wc, op;
208 
209 for ( ;; ) {                                            /* loop */
210     wc = fxread (&count, sizeof (d10), 1, fileref);     /* read IOWD */
211     if (wc == 0)                                        /* done? */
212         return SCPE_OK;
213     if (TSTS (count)) {                                 /* IOWD? */
214         for ( ; TSTS (count); count = AOB (count)) {
215             wc = fxread (&data, sizeof (d10), 1, fileref);
216             if (wc == 0)
217                 return SCPE_FMT;
218             pa = ((a10) count + 1) & AMASK;             /* store data */
219             M[pa] = data;
220             }                                           /* end for */
221         }                                               /* end if  count*/
222     else {
223         op = GET_OP (count);                            /* not IOWD */
224         if (op != OP_JRST)                              /* JRST? */
225             return SCPE_FMT;
226         saved_PC = (a10) count & AMASK;                 /* set PC */
227         break;
228         }                                               /* end else */
229     }                                                   /* end for */
230 return SCPE_OK;
231 }
232 
233 /* EXE file loader
234 
235    EXE format is a disk file format (36b words).  It consists of
236    blocks containing:
237 
238         block type,,total words = n
239         n - 1 data words
240 
241    Block types are
242 
243         EXE_DIR (1776)  directory
244         EXE_VEC (1775)  entry vector
245         EXE_PDV (1774)  optional blocks
246         EXE_END (1777)  end block
247 
248    The directory blocks are the most important and contain doubleword
249    page loading information:
250 
251         word0<0:8>      =       flags
252             <9:35>      =       page in file (0 if 0 page)
253         word1<0:8>      =       repeat count - 1
254             <9:35>      =       page in memory
255 */
256 
257 #define DIRSIZ  (2 * PAG_SIZE)
258 
load_exe(FILE * fileref)259 t_stat load_exe (FILE *fileref)
260 {
261 d10 data, dirbuf[DIRSIZ], pagbuf[PAG_SIZE], entbuf[2];
262 int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc;
263 int32 fpage, mpage;
264 a10 ma;
265 
266 ndir = entvec = 0;                                      /* no dir, entvec */
267 cont = 1;
268 do {
269     wc = fxread (&data, sizeof (d10), 1, fileref);      /* read blk hdr */
270     if (wc == 0)                                        /* error? */
271         return SCPE_FMT;
272     bsz = (int32) ((data & RMASK) - 1);                 /* get count */
273     if (bsz <= 0)                                       /* zero? */
274         return SCPE_FMT;
275     bty = (int32) LRZ (data);                           /* get type */
276     switch (bty) {                                      /* case type */
277 
278     case EXE_DIR:                                       /* directory */
279         if (ndir)                                       /* got one */
280             return SCPE_FMT;
281         ndir = fxread (dirbuf, sizeof (d10), bsz, fileref);
282         if (ndir < bsz)                                 /* error */
283             return SCPE_FMT;
284         break;
285 
286     case EXE_PDV:                                       /* ??? */
287         fseek (fileref, bsz * sizeof (d10), SEEK_CUR);
288         break;
289 
290     case EXE_VEC:                                       /* entry vec */
291         if (bsz != 2)                                   /* must be 2 wds */
292             return SCPE_FMT;
293         entvec = fxread (entbuf, sizeof (d10), bsz, fileref);
294         if (entvec < 2)                                 /* error? */
295             return SCPE_FMT;
296         cont = 0;                                       /* stop */
297         break;
298 
299     case EXE_END:                                       /* end */
300         if (bsz != 0)                                   /* must be hdr */
301             return SCPE_FMT;
302         cont = 0;                                       /* stop */
303         break;
304 
305     default:
306         return SCPE_FMT;
307         }                                               /* end switch */
308     } while (cont);                                     /* end do */
309 
310 for (i = 0; i < ndir; i = i + 2) {                      /* loop thru dir */
311     fpage = (int32) (dirbuf[i] & RMASK);                /* file page */
312     mpage = (int32) (dirbuf[i + 1] & RMASK);            /* memory page */
313     rpt = (int32) ((dirbuf[i + 1] >> 27) + 1);          /* repeat count */
314     for (j = 0; j < rpt; j++, mpage++) {                /* loop thru rpts */
315         if (fpage) {                                    /* file pages? */
316             fseek (fileref, (fpage << PAG_V_PN) * sizeof (d10), SEEK_SET);
317             wc = fxread (pagbuf, sizeof (d10), PAG_SIZE, fileref);
318             if (wc < PAG_SIZE)
319                 return SCPE_FMT;
320             fpage++;
321             }
322         ma = mpage << PAG_V_PN;                         /* mem addr */
323         for (k = 0; k < PAG_SIZE; k++, ma++) {          /* copy buf to mem */
324             if (MEM_ADDR_NXM (ma))
325                 return SCPE_NXM;
326             M[ma] = fpage? (pagbuf[k] & DMASK): 0;
327             }                                           /* end copy */
328         }                                               /* end rpt */
329     }                                                   /* end directory */
330 if (entvec && entbuf[1])
331     saved_PC = (int32) entbuf[1] & RMASK;               /* start addr */
332 return SCPE_OK;
333 }
334 
335 /* Master loader */
336 
sim_load(FILE * fileref,char * cptr,char * fnam,int flag)337 t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
338 {
339 d10 data;
340 int32 wc, fmt;
341 extern int32 sim_switches;
342 
343 fmt = 0;                                                /* no fmt */
344 if (sim_switches & SWMASK ('R'))                        /* -r? */
345     fmt = FMT_R;
346 else if (sim_switches & SWMASK ('S'))                   /* -s? */
347     fmt = FMT_S;
348 else if (sim_switches & SWMASK ('E'))                   /* -e? */
349     fmt = FMT_E;
350 else if (match_ext (fnam, "RIM"))                       /* .RIM? */
351     fmt = FMT_R;
352 else if (match_ext (fnam, "SAV"))                       /* .SAV? */
353     fmt = FMT_S;
354 else if (match_ext (fnam, "EXE"))                       /* .EXE? */
355     fmt = FMT_E;
356 else {
357     wc = fxread (&data, sizeof (d10), 1, fileref);      /* read hdr */
358     if (wc == 0)                                        /* error? */
359         return SCPE_FMT;
360     if (LRZ (data) == EXE_DIR)                          /* EXE magic? */
361         fmt = FMT_E;
362     else if (TSTS (data))                               /* SAV magic? */
363         fmt = FMT_S;
364     fseek (fileref, 0, SEEK_SET);                       /* rewind */
365     }
366 
367 switch (fmt) {                                          /* case fmt */
368 
369     case FMT_R:                                         /* RIM */
370         return load_rim (fileref);
371 
372     case FMT_S:                                         /* SAV */
373         return load_sav (fileref);
374 
375     case FMT_E:                                         /* EXE */
376         return load_exe (fileref);
377         }
378 
379 printf ("Can't determine load file format\n");
380 return SCPE_FMT;
381 }
382 
383 /* Symbol tables */
384 
385 #define I_V_FL          39                              /* inst class */
386 #define I_M_FL          03                              /* class mask */
387 #define I_ITS           004000000000000                 /* ITS flag */
388 #define I_AC            000000000000000                 /* AC, address */
389 #define I_OP            010000000000000                 /* address only */
390 #define I_IO            020000000000000                 /* classic I/O */
391 #define I_V_AC          00
392 #define I_V_OP          01
393 #define I_V_IO          02
394 
395 static const d10 masks[] = {
396  0777000000000, 0777740000000,
397  0700340000000, 0777777777777
398  };
399 
400 static const char *opcode[] = {
401 "XCTR", "XCTI",                                         /* ITS only */
402 "IORDI", "IORDQ", "IORD", "IOWR", "IOWRI", "IOWRQ",
403 "IORDBI", "IORDBQ", "IORDB", "IOWRB", "IOWRBI", "IOWRBQ",
404 "CLRCSH", "RDPCST", "WRPCST",
405 "SDBR1", "SDBR2", "SDBR3", "SDBR4", "SPM",
406 "LDBR1", "LDBR2", "LDBR3", "LDBR4", "LPMR",
407 
408 "PORTAL", "JRSTF", "HALT",                              /* AC defines op */
409 "XJRSTF", "XJEN", "XPCW",
410 "JEN", "SFM", "XJRST", "IBP",
411 "JFOV", "JCRY1", "JCRY0", "JCRY", "JOV",
412 
413 "APRID", "WRAPR", "RDAPR", "WRPI", "RDPI", "RDUBR", "CLRPT", "WRUBR",
414 "WREBR", "RDEBR",
415 "RDSPB", "RDCSB", "RDPUR", "RDCSTM", "RDTIM", "RDINT", "RDHSB",
416 "WRSPB", "WRCSB", "WRPUR", "WRCSTM", "WRTIM", "WRINT", "WRHSB",
417 
418           "LUUO01", "LUUO02", "LUUO03", "LUUO04", "LUUO05", "LUUO06", "LUUO07",
419 "LUUO10", "LUUO11", "LUUO12", "LUUO13", "LUUO14", "LUUO15", "LUUO16", "LUUO17",
420 "LUUO20", "LUUO21", "LUUO22", "LUUO23", "LUUO24", "LUUO25", "LUUO26", "LUUO27",
421 "LUUO30", "LUUO31", "LUUO32", "LUUO33", "LUUO34", "LUUO35", "LUUO36", "LUUO37",
422 "MUUO40", "MUUO41", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "MUUO47",
423 "MUUO50", "MUUO51", "MUUO52", "MUUO53", "MUUO54", "MUUO55", "MUUO56", "MUUO57",
424 "MUUO60", "MUUO61", "MUUO62", "MUUO63", "MUUO64", "MUUO65", "MUUO66", "MUUO67",
425 "MUUO70", "MUUO71", "MUUO72", "MUUO73", "MUUO74", "MUUO75", "MUUO76", "MUUO77",
426 
427 "UJEN",         "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ",
428 "DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV",
429 "DMOVE", "DMOVN", "FIX", "EXTEND", "DMOVEM", "DMOVNM", "FIXR", "FLTR",
430 "UFA", "DFN", "FSC", "ADJBP", "ILDB", "LDB", "IDPB", "DPB",
431 "FAD", "FADL", "FADM", "FADB", "FADR", "FADRL", "FADRM", "FADRB",
432 "FSB", "FSBL", "FSBM", "FSBB", "FSBR", "FSBRL", "FSBRM", "FSBRB",
433 "FMP", "FMPL", "FMPM", "FMPB", "FMPR", "FMPRL", "FMPRM", "FMPRB",
434 "FDV", "FDVL", "FDVM", "FDVB", "FDVR", "FDVRL", "FDVRM", "FDVRB",
435 
436 "MOVE", "MOVEI", "MOVEM", "MOVES", "MOVS", "MOVSI", "MOVSM", "MOVSS",
437 "MOVN", "MOVNI", "MOVNM", "MOVNS", "MOVM", "MOVMI", "MOVMM", "MOVMS",
438 "IMUL", "IMULI", "IMULM", "IMULB", "MUL", "MULI", "MULM", "MULB",
439 "IDIV", "IDIVI", "IDIVM", "IDIVB", "DIV", "DIVI", "DIVM", "DIVB",
440 "ASH", "ROT", "LSH", "JFFO", "ASHC", "ROTC", "LSHC", "CIRC",
441 "EXCH", "BLT", "AOBJP", "AOBJN", "JRST", "JFCL", "XCT", "MAP",
442 "PUSHJ", "PUSH", "POP", "POPJ", "JSR", "JSP", "JSA", "JRA",
443 "ADD", "ADDI", "ADDM", "ADDB", "SUB", "SUBI", "SUBM", "SUBB",
444 
445 "CAI", "CAIL", "CAIE", "CAILE", "CAIA", "CAIGE", "CAIN", "CAIG",
446 "CAM", "CAML", "CAME", "CAMLE", "CAMA", "CAMGE", "CAMN", "CAMG",
447 "JUMP", "JUMPL", "JUMPE", "JUMPLE", "JUMPA", "JUMPGE", "JUMPN", "JUMPG",
448 "SKIP", "SKIPL", "SKIPE", "SKIPLE", "SKIPA", "SKIPGE", "SKIPN", "SKIPG",
449 "AOJ", "AOJL", "AOJE", "AOJLE", "AOJA", "AOJGE", "AOJN", "AOJG",
450 "AOS", "AOSL", "AOSE", "AOSLE", "AOSA", "AOSGE", "AOSN", "AOSG",
451 "SOJ", "SOJL", "SOJE", "SOJLE", "SOJA", "SOJGE", "SOJN", "SOJG",
452 "SOS", "SOSL", "SOSE", "SOSLE", "SOSA", "SOSGE", "SOSN", "SOSG",
453 
454 "SETZ", "SETZI", "SETZM", "SETZB", "AND", "ANDI", "ANDM", "ANDB",
455 "ANDCA", "ANDCAI", "ANDCAM", "ANDCAB", "SETM", "SETMI", "SETMM", "SETMB",
456 "ANDCM", "ANDCMI", "ANDCMM", "ANDCMB", "SETA", "SETAI", "SETAM", "SETAB",
457 "XOR", "XORI", "XORM", "XORB", "IOR", "IORI", "IORM", "IORB",
458 "ANDCB", "ANDCBI", "ANDCBM", "ANDCBB", "EQV", "EQVI", "EQVM", "EQVB",
459 "SETCA", "SETCAI", "SETCAM", "SETCAB", "ORCA", "ORCAI", "ORCAM", "ORCAB",
460 "SETCM", "SETCMI", "SETCMM", "SETCMB", "ORCM", "ORCMI", "ORCMM", "ORCMB",
461 "ORCB", "ORCBI", "ORCBM", "ORCBB", "SETO", "SETOI", "SETOM", "SETOB",
462 
463 "HLL", "HLLI", "HLLM", "HLLS", "HRL", "HRLI", "HRLM", "HRLS",
464 "HLLZ", "HLLZI", "HLLZM", "HLLZS", "HRLZ", "HRLZI", "HRLZM", "HRLZS",
465 "HLLO", "HLLOI", "HLLOM", "HLLOS", "HRLO", "HRLOI", "HRLOM", "HRLOS",
466 "HLLE", "HLLEI", "HLLEM", "HLLES", "HRLE", "HRLEI", "HRLEM", "HRLES",
467 "HRR", "HRRI", "HRRM", "HRRS", "HLR", "HLRI", "HLRM", "HLRS",
468 "HRRZ", "HRRZI", "HRRZM", "HRRZS", "HLRZ", "HLRZI", "HLRZM", "HLRZS",
469 "HRRO", "HRROI", "HRROM", "HRROS", "HLRO", "HLROI", "HLROM", "HLROS",
470 "HRRE", "HRREI", "HRREM", "HRRES", "HLRE", "HLREI", "HLREM", "HLRES",
471 
472 "TRN", "TLN", "TRNE", "TLNE", "TRNA", "TLNA", "TRNN", "TLNN",
473 "TDN", "TSN", "TDNE", "TSNE", "TDNA", "TSNA", "TDNN", "TSNN",
474 "TRZ", "TLZ", "TRZE", "TLZE", "TRZA", "TLZA", "TRZN", "TLZN",
475 "TDZ", "TSZ", "TDZE", "TSZE", "TDZA", "TSZA", "TDZN", "TSZN",
476 "TRC", "TLC", "TRCE", "TLCE", "TRCA", "TLCA", "TRCN", "TLCN",
477 "TDC", "TSC", "TDCE", "TSCE", "TDCA", "TSCA", "TDCN", "TSCN",
478 "TRO", "TLO", "TROE", "TLOE", "TROA", "TLOA", "TRON", "TLON",
479 "TDO", "TSO", "TDOE", "TSOE", "TDOA", "TSOA", "TDON", "TSON",
480 
481 "UMOVE", "UMOVEM",                                      /* KS10 I/O */
482 "TIOE", "TION", "RDIO", "WRIO",
483 "BSIO", "BCIO", "BLTBU", "BLTUB",
484 "TIOEB", "TIONB", "RDIOB", "WRIOB",
485 "BSIOB", "BCIOB",
486 
487 "BLKI", "DATAI", "BLKO", "DATAO",                       /* classic I/O */
488 "CONO",  "CONI", "CONSZ", "CONSO",
489 
490 "CLEAR", "CLEARI", "CLEARM", "CLEARB",
491 "OR", "ORI", "ORM", "ORB", "XMOVEI", "XHLLI",           /* alternate ops */
492 
493         "CMPSL", "CMPSE", "CMPSLE",                     /* extended ops */
494 "EDIT", "CMPSGE", "CMPSN", "CMPSG",
495 "CVTDBO", "CVTDBT", "CVTBDO", "CVTBDT",
496 "MOVSO", "MOVST", "MOVSLJ", "MOVSRJ",
497 "XBLT", "GSNGL", "GDBLE", "GDFIX",
498 "GFIX", "GDFIXR", "GFIXR", "DGFLTR",
499 "GFLTR", "GFSC",
500 
501 NULL
502 };
503 
504 static const d10 opc_val[] = {
505  0102000000000+I_AC+I_ITS, 0103000000000+I_AC+I_ITS,
506  0710000000000+I_AC+I_ITS, 0711000000000+I_AC+I_ITS, 0712000000000+I_AC+I_ITS,
507  0713000000000+I_AC+I_ITS, 0714000000000+I_AC+I_ITS, 0715000000000+I_AC+I_ITS,
508  0720000000000+I_AC+I_ITS, 0721000000000+I_AC+I_ITS, 0722000000000+I_AC+I_ITS,
509  0723000000000+I_AC+I_ITS, 0724000000000+I_AC+I_ITS, 0725000000000+I_AC+I_ITS,
510  0701000000000+I_OP+I_ITS, 0701440000000+I_OP+I_ITS, 0701540000000+I_OP+I_ITS,
511  0702000000000+I_OP+I_ITS, 0702040000000+I_OP+I_ITS,
512  0702100000000+I_OP+I_ITS, 0702140000000+I_OP+I_ITS, 0702340000000+I_OP+I_ITS,
513  0702400000000+I_OP+I_ITS, 0702440000000+I_OP+I_ITS,
514  0702500000000+I_OP+I_ITS, 0702540000000+I_OP+I_ITS, 0702740000000+I_OP+I_ITS,
515 
516  0254040000000+I_OP, 0254100000000+I_OP,
517  0254200000000+I_OP, 0254240000000+I_OP, 0254300000000+I_OP, 0254340000000+I_OP,
518  0254500000000+I_OP, 0254600000000+I_OP, 0254640000000+I_OP, 0133000000000+I_OP,
519  0255040000000+I_OP, 0255100000000+I_OP, 0255200000000+I_OP, 0255300000000+I_OP,
520  0255400000000+I_OP,
521 
522  0700000000000+I_OP, 0700200000000+I_OP, 0700240000000+I_OP, 0700600000000+I_OP,
523  0700640000000+I_OP, 0701040000000+I_OP, 0701100000000+I_OP, 0701140000000+I_OP,
524  0701200000000+I_OP, 0701240000000+I_OP,
525  0702000000000+I_OP, 0702040000000+I_OP, 0702100000000+I_OP, 0702140000000+I_OP,
526  0702200000000+I_OP, 0702240000000+I_OP, 0702300000000+I_OP,
527  0702400000000+I_OP, 0702440000000+I_OP, 0702500000000+I_OP, 0702540000000+I_OP,
528  0702600000000+I_OP, 0702640000000+I_OP, 0702700000000+I_OP,
529 
530                      0001000000000+I_AC, 0002000000000+I_AC, 0003000000000+I_AC,
531  0004000000000+I_AC, 0005000000000+I_AC, 0006000000000+I_AC, 0007000000000+I_AC,
532  0010000000000+I_AC, 0011000000000+I_AC, 0012000000000+I_AC, 0013000000000+I_AC,
533  0014000000000+I_AC, 0015000000000+I_AC, 0016000000000+I_AC, 0017000000000+I_AC,
534  0020000000000+I_AC, 0021000000000+I_AC, 0022000000000+I_AC, 0023000000000+I_AC,
535  0024000000000+I_AC, 0025000000000+I_AC, 0026000000000+I_AC, 0027000000000+I_AC,
536  0030000000000+I_AC, 0031000000000+I_AC, 0032000000000+I_AC, 0033000000000+I_AC,
537  0034000000000+I_AC, 0035000000000+I_AC, 0036000000000+I_AC, 0037000000000+I_AC,
538  0040000000000+I_AC, 0041000000000+I_AC, 0042000000000+I_AC, 0043000000000+I_AC,
539  0044000000000+I_AC, 0045000000000+I_AC, 0046000000000+I_AC, 0047000000000+I_AC,
540  0050000000000+I_AC, 0051000000000+I_AC, 0052000000000+I_AC, 0053000000000+I_AC,
541  0054000000000+I_AC, 0055000000000+I_AC, 0056000000000+I_AC, 0057000000000+I_AC,
542  0060000000000+I_AC, 0061000000000+I_AC, 0062000000000+I_AC, 0063000000000+I_AC,
543  0064000000000+I_AC, 0065000000000+I_AC, 0066000000000+I_AC, 0067000000000+I_AC,
544  0070000000000+I_AC, 0071000000000+I_AC, 0072000000000+I_AC, 0073000000000+I_AC,
545  0074000000000+I_AC, 0075000000000+I_AC, 0076000000000+I_AC, 0077000000000+I_AC,
546 
547  0100000000000+I_AC,                     0102000000000+I_AC, 0103000000000+I_AC,
548  0104000000000+I_AC, 0105000000000+I_AC, 0106000000000+I_AC, 0107000000000+I_AC,
549  0110000000000+I_AC, 0111000000000+I_AC, 0112000000000+I_AC, 0113000000000+I_AC,
550  0114000000000+I_AC, 0115000000000+I_AC, 0116000000000+I_AC, 0117000000000+I_AC,
551  0120000000000+I_AC, 0121000000000+I_AC, 0122000000000+I_AC, 0123000000000+I_AC,
552  0124000000000+I_AC, 0125000000000+I_AC, 0126000000000+I_AC, 0127000000000+I_AC,
553  0130000000000+I_AC, 0131000000000+I_AC, 0132000000000+I_AC, 0133000000000+I_AC,
554  0134000000000+I_AC, 0135000000000+I_AC, 0136000000000+I_AC, 0137000000000+I_AC,
555  0140000000000+I_AC, 0141000000000+I_AC, 0142000000000+I_AC, 0143000000000+I_AC,
556  0144000000000+I_AC, 0145000000000+I_AC, 0146000000000+I_AC, 0147000000000+I_AC,
557  0150000000000+I_AC, 0151000000000+I_AC, 0152000000000+I_AC, 0153000000000+I_AC,
558  0154000000000+I_AC, 0155000000000+I_AC, 0156000000000+I_AC, 0157000000000+I_AC,
559  0160000000000+I_AC, 0161000000000+I_AC, 0162000000000+I_AC, 0163000000000+I_AC,
560  0164000000000+I_AC, 0165000000000+I_AC, 0166000000000+I_AC, 0167000000000+I_AC,
561  0170000000000+I_AC, 0171000000000+I_AC, 0172000000000+I_AC, 0173000000000+I_AC,
562  0174000000000+I_AC, 0175000000000+I_AC, 0176000000000+I_AC, 0177000000000+I_AC,
563 
564  0200000000000+I_AC, 0201000000000+I_AC, 0202000000000+I_AC, 0203000000000+I_AC,
565  0204000000000+I_AC, 0205000000000+I_AC, 0206000000000+I_AC, 0207000000000+I_AC,
566  0210000000000+I_AC, 0211000000000+I_AC, 0212000000000+I_AC, 0213000000000+I_AC,
567  0214000000000+I_AC, 0215000000000+I_AC, 0216000000000+I_AC, 0217000000000+I_AC,
568  0220000000000+I_AC, 0221000000000+I_AC, 0222000000000+I_AC, 0223000000000+I_AC,
569  0224000000000+I_AC, 0225000000000+I_AC, 0226000000000+I_AC, 0227000000000+I_AC,
570  0230000000000+I_AC, 0231000000000+I_AC, 0232000000000+I_AC, 0233000000000+I_AC,
571  0234000000000+I_AC, 0235000000000+I_AC, 0236000000000+I_AC, 0237000000000+I_AC,
572  0240000000000+I_AC, 0241000000000+I_AC, 0242000000000+I_AC, 0243000000000+I_AC,
573  0244000000000+I_AC, 0245000000000+I_AC, 0246000000000+I_AC, 0247000000000+I_AC+I_ITS,
574  0250000000000+I_AC, 0251000000000+I_AC, 0252000000000+I_AC, 0253000000000+I_AC,
575  0254000000000+I_AC, 0255000000000+I_AC, 0256000000000+I_AC, 0257000000000+I_AC,
576  0260000000000+I_AC, 0261000000000+I_AC, 0262000000000+I_AC, 0263000000000+I_AC,
577  0264000000000+I_AC, 0265000000000+I_AC, 0266000000000+I_AC, 0267000000000+I_AC,
578  0270000000000+I_AC, 0271000000000+I_AC, 0272000000000+I_AC, 0273000000000+I_AC,
579  0274000000000+I_AC, 0275000000000+I_AC, 0276000000000+I_AC, 0277000000000+I_AC,
580 
581  0300000000000+I_AC, 0301000000000+I_AC, 0302000000000+I_AC, 0303000000000+I_AC,
582  0304000000000+I_AC, 0305000000000+I_AC, 0306000000000+I_AC, 0307000000000+I_AC,
583  0310000000000+I_AC, 0311000000000+I_AC, 0312000000000+I_AC, 0313000000000+I_AC,
584  0314000000000+I_AC, 0315000000000+I_AC, 0316000000000+I_AC, 0317000000000+I_AC,
585  0320000000000+I_AC, 0321000000000+I_AC, 0322000000000+I_AC, 0323000000000+I_AC,
586  0324000000000+I_AC, 0325000000000+I_AC, 0326000000000+I_AC, 0327000000000+I_AC,
587  0330000000000+I_AC, 0331000000000+I_AC, 0332000000000+I_AC, 0333000000000+I_AC,
588  0334000000000+I_AC, 0335000000000+I_AC, 0336000000000+I_AC, 0337000000000+I_AC,
589  0340000000000+I_AC, 0341000000000+I_AC, 0342000000000+I_AC, 0343000000000+I_AC,
590  0344000000000+I_AC, 0345000000000+I_AC, 0346000000000+I_AC, 0347000000000+I_AC,
591  0350000000000+I_AC, 0351000000000+I_AC, 0352000000000+I_AC, 0353000000000+I_AC,
592  0354000000000+I_AC, 0355000000000+I_AC, 0356000000000+I_AC, 0357000000000+I_AC,
593  0360000000000+I_AC, 0361000000000+I_AC, 0362000000000+I_AC, 0363000000000+I_AC,
594  0364000000000+I_AC, 0365000000000+I_AC, 0366000000000+I_AC, 0367000000000+I_AC,
595  0370000000000+I_AC, 0371000000000+I_AC, 0372000000000+I_AC, 0373000000000+I_AC,
596  0374000000000+I_AC, 0375000000000+I_AC, 0376000000000+I_AC, 0377000000000+I_AC,
597 
598  0400000000000+I_AC, 0401000000000+I_AC, 0402000000000+I_AC, 0403000000000+I_AC,
599  0404000000000+I_AC, 0405000000000+I_AC, 0406000000000+I_AC, 0407000000000+I_AC,
600  0410000000000+I_AC, 0411000000000+I_AC, 0412000000000+I_AC, 0413000000000+I_AC,
601  0414000000000+I_AC, 0415000000000+I_AC, 0416000000000+I_AC, 0417000000000+I_AC,
602  0420000000000+I_AC, 0421000000000+I_AC, 0422000000000+I_AC, 0423000000000+I_AC,
603  0424000000000+I_AC, 0425000000000+I_AC, 0426000000000+I_AC, 0427000000000+I_AC,
604  0430000000000+I_AC, 0431000000000+I_AC, 0432000000000+I_AC, 0433000000000+I_AC,
605  0434000000000+I_AC, 0435000000000+I_AC, 0436000000000+I_AC, 0437000000000+I_AC,
606  0440000000000+I_AC, 0441000000000+I_AC, 0442000000000+I_AC, 0443000000000+I_AC,
607  0444000000000+I_AC, 0445000000000+I_AC, 0446000000000+I_AC, 0447000000000+I_AC,
608  0450000000000+I_AC, 0451000000000+I_AC, 0452000000000+I_AC, 0453000000000+I_AC,
609  0454000000000+I_AC, 0455000000000+I_AC, 0456000000000+I_AC, 0457000000000+I_AC,
610  0460000000000+I_AC, 0461000000000+I_AC, 0462000000000+I_AC, 0463000000000+I_AC,
611  0464000000000+I_AC, 0465000000000+I_AC, 0466000000000+I_AC, 0467000000000+I_AC,
612  0470000000000+I_AC, 0471000000000+I_AC, 0472000000000+I_AC, 0473000000000+I_AC,
613  0474000000000+I_AC, 0475000000000+I_AC, 0476000000000+I_AC, 0477000000000+I_AC,
614 
615  0500000000000+I_AC, 0501000000000+I_AC, 0502000000000+I_AC, 0503000000000+I_AC,
616  0504000000000+I_AC, 0505000000000+I_AC, 0506000000000+I_AC, 0507000000000+I_AC,
617  0510000000000+I_AC, 0511000000000+I_AC, 0512000000000+I_AC, 0513000000000+I_AC,
618  0514000000000+I_AC, 0515000000000+I_AC, 0516000000000+I_AC, 0517000000000+I_AC,
619  0520000000000+I_AC, 0521000000000+I_AC, 0522000000000+I_AC, 0523000000000+I_AC,
620  0524000000000+I_AC, 0525000000000+I_AC, 0526000000000+I_AC, 0527000000000+I_AC,
621  0530000000000+I_AC, 0531000000000+I_AC, 0532000000000+I_AC, 0533000000000+I_AC,
622  0534000000000+I_AC, 0535000000000+I_AC, 0536000000000+I_AC, 0537000000000+I_AC,
623  0540000000000+I_AC, 0541000000000+I_AC, 0542000000000+I_AC, 0543000000000+I_AC,
624  0544000000000+I_AC, 0545000000000+I_AC, 0546000000000+I_AC, 0547000000000+I_AC,
625  0550000000000+I_AC, 0551000000000+I_AC, 0552000000000+I_AC, 0553000000000+I_AC,
626  0554000000000+I_AC, 0555000000000+I_AC, 0556000000000+I_AC, 0557000000000+I_AC,
627  0560000000000+I_AC, 0561000000000+I_AC, 0562000000000+I_AC, 0563000000000+I_AC,
628  0564000000000+I_AC, 0565000000000+I_AC, 0566000000000+I_AC, 0567000000000+I_AC,
629  0570000000000+I_AC, 0571000000000+I_AC, 0572000000000+I_AC, 0573000000000+I_AC,
630  0574000000000+I_AC, 0575000000000+I_AC, 0576000000000+I_AC, 0577000000000+I_AC,
631 
632  0600000000000+I_AC, 0601000000000+I_AC, 0602000000000+I_AC, 0603000000000+I_AC,
633  0604000000000+I_AC, 0605000000000+I_AC, 0606000000000+I_AC, 0607000000000+I_AC,
634  0610000000000+I_AC, 0611000000000+I_AC, 0612000000000+I_AC, 0613000000000+I_AC,
635  0614000000000+I_AC, 0615000000000+I_AC, 0616000000000+I_AC, 0617000000000+I_AC,
636  0620000000000+I_AC, 0621000000000+I_AC, 0622000000000+I_AC, 0623000000000+I_AC,
637  0624000000000+I_AC, 0625000000000+I_AC, 0626000000000+I_AC, 0627000000000+I_AC,
638  0630000000000+I_AC, 0631000000000+I_AC, 0632000000000+I_AC, 0633000000000+I_AC,
639  0634000000000+I_AC, 0635000000000+I_AC, 0636000000000+I_AC, 0637000000000+I_AC,
640  0640000000000+I_AC, 0641000000000+I_AC, 0642000000000+I_AC, 0643000000000+I_AC,
641  0644000000000+I_AC, 0645000000000+I_AC, 0646000000000+I_AC, 0647000000000+I_AC,
642  0650000000000+I_AC, 0651000000000+I_AC, 0652000000000+I_AC, 0653000000000+I_AC,
643  0654000000000+I_AC, 0655000000000+I_AC, 0656000000000+I_AC, 0657000000000+I_AC,
644  0660000000000+I_AC, 0661000000000+I_AC, 0662000000000+I_AC, 0663000000000+I_AC,
645  0664000000000+I_AC, 0665000000000+I_AC, 0666000000000+I_AC, 0667000000000+I_AC,
646  0670000000000+I_AC, 0671000000000+I_AC, 0672000000000+I_AC, 0673000000000+I_AC,
647  0674000000000+I_AC, 0675000000000+I_AC, 0676000000000+I_AC, 0677000000000+I_AC,
648 
649  0704000000000+I_AC, 0705000000000+I_AC,
650  0710000000000+I_AC, 0711000000000+I_AC, 0712000000000+I_AC, 0713000000000+I_AC,
651  0714000000000+I_AC, 0715000000000+I_AC, 0716000000000+I_AC, 0717000000000+I_AC,
652  0720000000000+I_AC, 0721000000000+I_AC, 0722000000000+I_AC, 0723000000000+I_AC,
653  0724000000000+I_AC, 0725000000000+I_AC,
654 
655  0700000000000+I_IO, 0700040000000+I_IO, 0700100000000+I_IO, 0700140000000+I_IO,
656  0700200000000+I_IO, 0700240000000+I_IO, 0700300000000+I_IO, 0700340000000+I_IO,
657 
658  0400000000000+I_AC, 0401000000000+I_AC, 0402000000000+I_AC, 0403000000000+I_AC,
659  0434000000000+I_AC, 0435000000000+I_AC, 0436000000000+I_AC, 0437000000000+I_AC,
660  0415000000000+I_AC, 0501000000000+I_AC,
661 
662                      0001000000000+I_AC, 0002000000000+I_AC, 0003000000000+I_AC,
663  0004000000000+I_AC, 0005000000000+I_AC, 0006000000000+I_AC, 0007000000000+I_AC,
664  0010000000000+I_AC, 0011000000000+I_AC, 0012000000000+I_AC, 0013000000000+I_AC,
665  0014000000000+I_AC, 0015000000000+I_AC, 0016000000000+I_AC, 0017000000000+I_AC,
666  0020000000000+I_AC, 0021000000000+I_AC, 0022000000000+I_AC, 0023000000000+I_AC,
667  0024000000000+I_AC, 0025000000000+I_AC, 0026000000000+I_AC, 0027000000000+I_AC,
668  0030000000000+I_AC, 0031000000000+I_AC,
669  -1
670  };
671 
672 #define NUMDEV  6
673 
674 static const char *devnam[NUMDEV] = {
675  "APR", "PI", "PAG", "CCA", "TIM", "MTR"
676  };
677 
678 /* Symbolic decode
679 
680    Inputs:
681         *of     =       output stream
682         addr    =       current PC
683         *val    =       pointer to values
684         *uptr   =       pointer to unit
685         sw      =       switches
686    Outputs:
687         return  =       status code
688 */
689 
690 #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
691 #define SIXTOASC(x) ((x) + 040)
692 
fprint_sym(FILE * of,t_addr addr,t_value * val,UNIT * uptr,int32 sw)693 t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
694     UNIT *uptr, int32 sw)
695 {
696 int32 i, j, c, cflag, ac, xr, y, dev;
697 d10 inst;
698 
699 inst = val[0];
700 cflag = (uptr == NULL) || (uptr == &cpu_unit);
701 if (sw & SWMASK ('A')) {                                /* ASCII? */
702     if (inst > 0377)
703         return SCPE_ARG;
704     fprintf (of, FMTASC ((int32) (inst & 0177)));
705     return SCPE_OK;
706     }
707 if (sw & SWMASK ('C')) {                                /* character? */
708     for (i = 30; i >= 0; i = i - 6) {
709         c = (int32) ((inst >> i) & 077);
710         fprintf (of, "%c", SIXTOASC (c));
711 		}
712     return SCPE_OK;
713     }
714 if (sw & SWMASK ('P')) {                                /* packed? */
715     for (i = 29; i >= 0; i = i - 7) {
716         c = (int32) ((inst >> i) & 0177);
717         fprintf (of, FMTASC (c));
718 		}
719     return SCPE_OK;
720     }
721 if (!(sw & SWMASK ('M')))
722     return SCPE_ARG;
723 
724 /* Instruction decode */
725 
726 ac = GET_AC (inst);
727 xr = GET_XR (inst);
728 y = GET_ADDR (inst);
729 dev = GET_DEV (inst);
730 for (i = 0; opc_val[i] >= 0; i++) {                     /* loop thru ops */
731     j = (int32) ((opc_val[i] >> I_V_FL) & I_M_FL);      /* get class */
732     if (((opc_val[i] & DMASK) == (inst & masks[j])) &&  /* match? */
733             (((opc_val[i] & I_ITS) == 0) || Q_ITS)) {
734         fprintf (of, "%s ", opcode[i]);                 /* opcode */
735         switch (j) {                                    /* case on class */
736 
737         case I_V_AC:                                    /* AC + address */
738             fprintf (of, "%-o,", ac);                   /* print AC, fall thru */
739         case I_V_OP:                                    /* address only */
740             if (inst & INST_IND)
741                 fprintf (of, "@");
742             if (xr)
743                 fprintf (of, "%-o(%-o)", y, xr);
744             else fprintf (of, "%-o", y);
745             break;
746 
747         case I_V_IO:                                    /* I/O */
748             if (dev < NUMDEV)
749                 fprintf (of, "%s,", devnam[dev]);
750             else fprintf (of, "%-o,", dev);
751             if (inst & INST_IND)
752                 fprintf (of, "@");
753             if (xr)
754                 fprintf (of, "%-o(%-o)", y, xr);
755             else fprintf (of, "%-o", y);
756             break;
757             }                                           /* end case */
758         return SCPE_OK;
759         }                                               /* end if */
760     }                                                   /* end for */
761 return SCPE_ARG;
762 }
763 
764 /* Get operand, including indirect and index
765 
766    Inputs:
767         *cptr   =       pointer to input string
768         *status =       pointer to error status
769    Outputs:
770         val     =       output value
771 */
772 
get_opnd(char * cptr,t_stat * status)773 t_value get_opnd (char *cptr, t_stat *status)
774 {
775 int32 sign = 0;
776 t_value val, xr = 0, ind = 0;
777 char *tptr;
778 
779 *status = SCPE_ARG;                                     /* assume fail */
780 if (*cptr == '@') {
781     ind = INST_IND;
782     cptr++;
783     }
784 if (*cptr == '+')
785     cptr++;
786 else if (*cptr == '-') {
787     sign = 1;
788     cptr++;
789     }
790 val = strtotv (cptr, &tptr, 8);
791 if (val > 0777777)
792     return 0;
793 if (sign)
794     val = (~val + 1) & 0777777;
795 cptr = tptr;
796 if (*cptr == '(') {
797     cptr++;
798     xr = strtotv (cptr, &tptr, 8);
799     if ((cptr == tptr) || (*tptr != ')') ||
800         (xr > AC_NUM) || (xr == 0))
801         return 0;
802     cptr = ++tptr;
803     }
804 if (*cptr == 0)
805     *status = SCPE_OK;
806 return (ind | (xr << 18) | val);
807 }
808 
809 /* Symbolic input
810 
811    Inputs:
812         *cptr   =       pointer to input string
813         addr    =       current PC
814         uptr    =       pointer to unit
815         *val    =       pointer to output values
816         sw      =       switches
817    Outputs:
818         status  =       error status
819 */
820 
parse_sym(char * cptr,t_addr addr,UNIT * uptr,t_value * val,int32 sw)821 t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
822 {
823 int32 cflag, i, j;
824 t_value ac, dev;
825 t_stat r;
826 char gbuf[CBUFSIZE];
827 
828 cflag = (uptr == NULL) || (uptr == &cpu_unit);
829 while (isspace (*cptr)) cptr++;
830 for (i = 0; i < 6; i++) {
831     if (cptr[i] == 0) {
832         for (j = i + 1; j <= 6; j++) cptr[j] = 0;
833         break;
834         }
835     }
836 if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
837     if (cptr[0] == 0)                                   /* must have 1 char */
838         return SCPE_ARG;
839     val[0] = (t_value) cptr[0];
840     return SCPE_OK;
841     }
842 if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
843     if (cptr[0] == 0)                                   /* must have 1 char */
844         return SCPE_ARG;
845     for (i = 0; i < 6; i++) {
846         val[0] = (val[0] << 6);
847         if (cptr[i]) val[0] = val[0] |
848             ((t_value) ((cptr[i] + 040) & 077));
849         }
850     return SCPE_OK;
851     }
852 if ((sw & SWMASK ('P')) || ((*cptr == '#') && cptr++)) { /* packed string? */
853     if (cptr[0] == 0)                                   /* must have 1 char */
854         return SCPE_ARG;
855     for (i = 0; i < 5; i++)
856         val[0] = (val[0] << 7) | ((t_value) cptr[i]);
857     val[0] = val[0] << 1;
858     return SCPE_OK;
859     }
860 
861 /* Instruction parse */
862 
863 cptr = get_glyph (cptr, gbuf, 0);                       /* get opcode */
864 for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
865 if (opcode[i] == NULL)
866     return SCPE_ARG;
867 val[0] = opc_val[i] & DMASK;                            /* get value */
868 j = (int32) ((opc_val[i] >> I_V_FL) & I_M_FL);          /* get class */
869 switch (j) {                                            /* case on class */
870 
871     case I_V_AC:                                        /* AC + operand */
872         if (strchr (cptr, ',')) {                       /* AC specified? */
873             cptr = get_glyph (cptr, gbuf, ',');         /* get glyph */
874             if (gbuf[0]) {                              /* can be omitted */
875                 ac = get_uint (gbuf, 8, AC_NUM - 1, &r);
876                 if (r != SCPE_OK)
877                     return SCPE_ARG;
878                 val[0] = val[0] | (ac << INST_V_AC);
879                 }
880             }                                           /* fall through */
881     case I_V_OP:                                        /* operand */
882         cptr = get_glyph (cptr, gbuf, 0);
883         val[0] = val[0] | get_opnd (gbuf, &r);
884         if (r != SCPE_OK)
885             return SCPE_ARG;
886         break;
887 
888     case I_V_IO:                                        /* I/O */
889         cptr = get_glyph (cptr, gbuf, ',');             /* get glyph */
890         for (dev = 0; (dev < NUMDEV) && (strcmp (devnam[dev], gbuf) != 0); dev++);
891         if (dev >= NUMDEV) {
892             dev = get_uint (gbuf, 8, INST_M_DEV, &r);
893             if (r != SCPE_OK)
894                 return SCPE_ARG;
895             }
896         val[0] = val[0] | (dev << INST_V_DEV);
897         cptr = get_glyph (cptr, gbuf, 0);
898         val[0] = val[0] | get_opnd (gbuf, &r);
899         if (r != SCPE_OK)
900             return SCPE_ARG;
901         break;
902         }                                               /* end case */
903 
904 if (*cptr != 0)                                         /* junk at end? */
905     return SCPE_ARG;
906 return SCPE_OK;
907 }
908