~ubuntu-branches/ubuntu/utopic/simh/utopic

« back to all changes in this revision

Viewing changes to PDP11/pdp11_sys.c

  • Committer: Bazaar Package Importer
  • Author(s): Vince Mulhollon
  • Date: 2004-04-20 20:01:26 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040420200126-ehsuleda8xcgi51h
Tags: 3.2.0-1
New upstream 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* pdp11_sys.c: PDP-11 simulator interface
 
2
 
 
3
   Copyright (c) 1993-2004, 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
 
23
   be 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
   22-Dec-03    RMS     Added second DEUNA/DELUA support
 
27
   18-Oct-03    RMS     Added DECtape off reel message
 
28
   06-May-03    RMS     Added support for second DEQNA/DELQA
 
29
   09-Jan-03    RMS     Added DELUA/DEUNA support
 
30
   17-Oct-02    RMS     Fixed bugs in branch, SOB address parsing
 
31
   09-Oct-02    RMS     Added DELQA support
 
32
   12-Sep-02    RMS     Added TMSCP, KW11P, RX211 support, RAD50 examine
 
33
   29-Nov-01    RMS     Added read only unit support
 
34
   17-Sep-01    RMS     Removed multiconsole support
 
35
   26-Aug-01    RMS     Added DZ11
 
36
   20-Aug-01    RMS     Updated bad block inquiry
 
37
   17-Jul-01    RMS     Fixed warning from VC++ 6.0
 
38
   27-May-01    RMS     Added multiconsole support
 
39
   05-Apr-01    RMS     Added support for TS11/TSV05
 
40
   14-Mar-01    RMS     Revised load/dump interface (again)
 
41
   11-Feb-01    RMS     Added DECtape support
 
42
   30-Oct-00    RMS     Added support for examine to file
 
43
   14-Apr-99    RMS     Changed t_addr to unsigned
 
44
   09-Nov-98    RMS     Fixed assignments of ROR/ROL (John Wilson)
 
45
   27-Oct-98    RMS     V2.4 load interface
 
46
   08-Oct-98    RMS     Fixed bug in bad block routine
 
47
   30-Mar-98    RMS     Fixed bug in floating point display
 
48
   12-Nov-97    RMS     Added bad block table routine
 
49
*/
 
50
 
 
51
#include "pdp11_defs.h"
 
52
#include <ctype.h>
 
53
 
 
54
extern DEVICE cpu_dev;
 
55
extern DEVICE ptr_dev, ptp_dev;
 
56
extern DEVICE tti_dev, tto_dev;
 
57
extern DEVICE lpt_dev;
 
58
extern DEVICE clk_dev, pclk_dev;
 
59
extern DEVICE dz_dev;
 
60
extern DEVICE rk_dev, rl_dev;
 
61
extern DEVICE hk_dev;
 
62
extern DEVICE rx_dev, ry_dev;
 
63
extern DEVICE rp_dev;
 
64
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
 
65
extern DEVICE dt_dev;
 
66
extern DEVICE tm_dev, ts_dev;
 
67
extern DEVICE tq_dev;
 
68
extern DEVICE xq_dev, xqb_dev;
 
69
extern DEVICE xu_dev, xub_dev;
 
70
extern UNIT cpu_unit;
 
71
extern REG cpu_reg[];
 
72
extern uint16 *M;
 
73
extern int32 saved_PC;
 
74
 
 
75
/* SCP data structures and interface routines
 
76
 
 
77
   sim_name             simulator name string
 
78
   sim_PC               pointer to saved PC register descriptor
 
79
   sim_emax             number of words for examine
 
80
   sim_devices          array of pointers to simulated devices
 
81
   sim_stop_messages    array of pointers to stop messages
 
82
   sim_load             binary loader
 
83
*/
 
84
 
 
85
char sim_name[] = "PDP-11";
 
86
 
 
87
REG *sim_PC = &cpu_reg[0];
 
88
 
 
89
int32 sim_emax = 4;
 
90
 
 
91
DEVICE *sim_devices[] = {
 
92
        &cpu_dev,
 
93
        &ptr_dev,
 
94
        &ptp_dev,
 
95
        &tti_dev,
 
96
        &tto_dev,
 
97
        &lpt_dev,
 
98
        &clk_dev,
 
99
        &pclk_dev,
 
100
        &dz_dev,
 
101
        &rk_dev,
 
102
        &rl_dev,
 
103
        &hk_dev,
 
104
        &rx_dev,
 
105
        &ry_dev,
 
106
        &rp_dev,
 
107
        &rq_dev,
 
108
        &rqb_dev,
 
109
        &rqc_dev,
 
110
        &rqd_dev,
 
111
        &dt_dev,
 
112
        &tm_dev,
 
113
        &ts_dev,
 
114
        &tq_dev,
 
115
        &xq_dev,
 
116
        &xqb_dev,
 
117
        &xu_dev,
 
118
        &xub_dev,
 
119
        NULL };
 
120
 
 
121
const char *sim_stop_messages[] = {
 
122
        "Unknown error",
 
123
        "Red stack trap",
 
124
        "Odd address trap",
 
125
        "Memory management trap",
 
126
        "Non-existent memory trap",
 
127
        "Parity error trap",
 
128
        "Privilege trap",
 
129
        "Illegal instruction trap",
 
130
        "BPT trap",
 
131
        "IOT trap",
 
132
        "EMT trap",
 
133
        "TRAP trap",
 
134
        "Trace trap",
 
135
        "Yellow stack trap",
 
136
        "Powerfail trap",
 
137
        "Floating point exception",
 
138
        "HALT instruction",
 
139
        "Breakpoint",
 
140
        "Wait state",
 
141
        "Trap vector fetch abort",
 
142
        "Trap stack push abort",
 
143
        "RQDX3 consistency error",
 
144
        "Sanity timer expired"
 
145
        "DECtape off reel"  };
 
146
 
 
147
/* Binary loader.
 
148
 
 
149
   Loader format consists of blocks, optionally preceded, separated, and
 
150
   followed by zeroes.  Each block consists of:
 
151
 
 
152
        001             ---
 
153
        xxx              |
 
154
        lo_count         |
 
155
        hi_count         |
 
156
        lo_origin        > count bytes
 
157
        hi_origin        |
 
158
        data byte        |
 
159
        :                |
 
160
        data byte       ---
 
161
        checksum
 
162
 
 
163
   If the byte count is exactly six, the block is the last on the tape, and
 
164
   there is no checksum.  If the origin is not 000001, then the origin is
 
165
   the PC at which to start the program.
 
166
*/
 
167
 
 
168
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
 
169
{
 
170
int32 csum, count, state, i;
 
171
uint32 origin;
 
172
 
 
173
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
 
174
state = csum = 0;
 
175
while ((i = getc (fileref)) != EOF) {
 
176
        csum = csum + i;                                /* add into chksum */
 
177
        switch (state) {
 
178
        case 0:                                         /* leader */
 
179
                if (i == 1) state = 1;
 
180
                else csum = 0;
 
181
                break;
 
182
        case 1:                                         /* ignore after 001 */
 
183
                state = 2;
 
184
                break;
 
185
        case 2:                                         /* low count */
 
186
                count = i;
 
187
                state = 3;
 
188
                break;
 
189
        case 3:                                         /* high count */
 
190
                count = (i << 8) | count;
 
191
                state = 4;
 
192
                break;
 
193
        case 4:                                         /* low origin */
 
194
                origin = i;
 
195
                state = 5;
 
196
                break;
 
197
        case 5:                                         /* high origin */
 
198
                origin = (i << 8) | origin;
 
199
                if (count == 6) {
 
200
                        if (origin != 1) saved_PC = origin & 0177776;
 
201
                        return SCPE_OK;  }
 
202
                count = count - 6;
 
203
                state = 6;
 
204
                break;
 
205
        case 6:                                         /* data */
 
206
                if (origin >= MEMSIZE) return SCPE_NXM;
 
207
                M[origin >> 1] = (origin & 1)?
 
208
                        (M[origin >> 1] & 0377) | (i << 8):
 
209
                        (M[origin >> 1] & 0177400) | i;
 
210
                origin = origin + 1;
 
211
                count = count - 1;
 
212
                state = state + (count == 0);
 
213
                break;
 
214
        case 7:                                         /* checksum */
 
215
                if (csum & 0377) return SCPE_CSUM;
 
216
                csum = state = 0;
 
217
                break;  }                               /* end switch */
 
218
        }                                               /* end while */
 
219
return SCPE_FMT;                                        /* unexpected eof */
 
220
}
 
221
 
 
222
/* Factory bad block table creation routine
 
223
 
 
224
   This routine writes a DEC standard 044 compliant bad block table on the
 
225
   last track of the specified unit.  The bad block table consists of 10
 
226
   repetitions of the same table, formatted as follows:
 
227
 
 
228
        words 0-1       pack id number
 
229
        words 2-3       cylinder/sector/surface specifications
 
230
         :
 
231
        words n-n+1     end of table (-1,-1)
 
232
 
 
233
   Inputs:
 
234
        uptr    =       pointer to unit
 
235
        sec     =       number of sectors per surface
 
236
        wds     =       number of words per sector
 
237
   Outputs:
 
238
        sta     =       status code
 
239
*/
 
240
 
 
241
t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds)
 
242
{
 
243
int32 i, da;
 
244
int16 *buf;
 
245
 
 
246
if ((sec < 2) || (wds < 16)) return SCPE_ARG;
 
247
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
 
248
if (uptr->flags & UNIT_RO) return SCPE_RO;
 
249
if (!get_yn ("Create bad block table on last track? [N]", FALSE)) return SCPE_OK;
 
250
da = (uptr->capac - (sec * wds)) * sizeof (int16);
 
251
if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR;
 
252
if ((buf = malloc (wds * sizeof (int16))) == NULL) return SCPE_MEM;
 
253
buf[0] = buf[1] = 012345u;
 
254
buf[2] = buf[3] = 0;
 
255
for (i = 4; i < wds; i++) buf[i] = 0177777u;
 
256
for (i = 0; (i < sec) && (i < 10); i++)
 
257
        fxwrite (buf, sizeof (int16), wds, uptr->fileref);
 
258
free (buf);
 
259
if (ferror (uptr->fileref)) return SCPE_IOERR;
 
260
return SCPE_OK;
 
261
}
 
262
 
 
263
/* Symbol tables */
 
264
 
 
265
#define I_V_L           16                              /* long mode */
 
266
#define I_V_D           17                              /* double mode */
 
267
#define I_L             (1 << I_V_L)
 
268
#define I_D             (1 << I_V_D)
 
269
 
 
270
/* Warning: for literals, the class number MUST equal the field width!! */
 
271
 
 
272
#define I_V_CL          18                              /* class bits */
 
273
#define I_M_CL          017                             /* class mask */
 
274
#define I_V_NPN         0                               /* no operands */
 
275
#define I_V_REG         1                               /* reg */
 
276
#define I_V_SOP         2                               /* operand */
 
277
#define I_V_3B          3                               /* 3b literal */
 
278
#define I_V_FOP         4                               /* flt operand */
 
279
#define I_V_AFOP        5                               /* fac, flt operand */
 
280
#define I_V_6B          6                               /* 6b literal */
 
281
#define I_V_BR          7                               /* cond branch */
 
282
#define I_V_8B          8                               /* 8b literal */
 
283
#define I_V_SOB         9                               /* reg, disp */
 
284
#define I_V_RSOP        10                              /* reg, operand */
 
285
#define I_V_ASOP        11                              /* fac, operand */
 
286
#define I_V_ASMD        12                              /* fac, moded int op */
 
287
#define I_V_DOP         13                              /* double operand */
 
288
#define I_V_CCC         14                              /* CC clear */
 
289
#define I_V_CCS         15                              /* CC set */
 
290
#define I_NPN           (I_V_NPN << I_V_CL)
 
291
#define I_REG           (I_V_REG << I_V_CL)
 
292
#define I_3B            (I_V_3B << I_V_CL)
 
293
#define I_SOP           (I_V_SOP << I_V_CL)
 
294
#define I_FOP           (I_V_FOP << I_V_CL)
 
295
#define I_6B            (I_V_6B << I_V_CL)
 
296
#define I_BR            (I_V_BR << I_V_CL)
 
297
#define I_8B            (I_V_8B << I_V_CL)
 
298
#define I_AFOP          (I_V_AFOP << I_V_CL)
 
299
#define I_ASOP          (I_V_ASOP << I_V_CL)
 
300
#define I_RSOP          (I_V_RSOP << I_V_CL)
 
301
#define I_SOB           (I_V_SOB << I_V_CL)
 
302
#define I_ASMD          (I_V_ASMD << I_V_CL)
 
303
#define I_DOP           (I_V_DOP << I_V_CL)
 
304
#define I_CCC           (I_V_CCC << I_V_CL)
 
305
#define I_CCS           (I_V_CCS << I_V_CL)
 
306
 
 
307
static const int32 masks[] = {
 
308
0177777, 0177770, 0177700, 0177770,
 
309
0177700+I_D, 0177400+I_D, 0177700, 0177400,
 
310
0177400, 0177000, 0177000, 0177400,
 
311
0177400+I_D+I_L, 0170000, 0177777, 0177777 };
 
312
 
 
313
static const char *opcode[] = {
 
314
"HALT","WAIT","RTI","BPT",
 
315
"IOT","RESET","RTT","MFPT",
 
316
"JMP","RTS","SPL",
 
317
"NOP","CLC","CLV","CLV CLC",
 
318
"CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC",
 
319
"CLN","CLN CLC","CLN CLV","CLN CLV CLC",
 
320
"CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC",
 
321
"NOP","SEC","SEV","SEV SEC",
 
322
"SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC",
 
323
"SEN","SEN SEC","SEN SEV","SEN SEV SEC",
 
324
"SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC",
 
325
"SWAB","BR","BNE","BEQ",
 
326
"BGE","BLT","BGT","BLE",
 
327
"JSR",
 
328
"CLR","COM","INC","DEC",
 
329
"NEG","ADC","SBC","TST",
 
330
"ROR","ROL","ASR","ASL",
 
331
"MARK","MFPI","MTPI","SXT",
 
332
"CSM",        "TSTSET","WRTLCK",
 
333
"MOV","CMP","BIT","BIC",
 
334
"BIS","ADD",
 
335
"MUL","DIV","ASH","ASHC",
 
336
"XOR",
 
337
"FADD","FSUB","FMUL","FDIV",
 
338
"L2DR",
 
339
"MOVC","MOVRC","MOVTC",
 
340
"LOCC","SKPC","SCANC","SPANC",
 
341
"CMPC","MATC",
 
342
"ADDN","SUBN","CMPN","CVTNL",
 
343
"CVTPN","CVTNP","ASHN","CVTLN",
 
344
"L3DR",
 
345
"ADDP","SUBP","CMPP","CVTPL",
 
346
"MULP","DIVP","ASHP","CVTLP",
 
347
"MOVCI","MOVRCI","MOVTCI",
 
348
"LOCCI","SKPCI","SCANCI","SPANCI",
 
349
"CMPCI","MATCI",
 
350
"ADDNI","SUBNI","CMPNI","CVTNLI",
 
351
"CVTPNI","CVTNPI","ASHNI","CVTLNI",
 
352
"ADDPI","SUBPI","CMPPI","CVTPLI",
 
353
"MULPI","DIVPI","ASHPI","CVTLPI",
 
354
"SOB",
 
355
"BPL","BMI","BHI","BLOS",
 
356
"BVC","BVS","BCC","BCS",
 
357
"BHIS","BLO",                                           /* encode only */
 
358
"EMT","TRAP",
 
359
"CLRB","COMB","INCB","DECB",
 
360
"NEGB","ADCB","SBCB","TSTB",
 
361
"RORB","ROLB","ASRB","ASLB",
 
362
"MTPS","MFPD","MTPD","MFPS",
 
363
"MOVB","CMPB","BITB","BICB",
 
364
"BISB","SUB",
 
365
"CFCC","SETF","SETI","SETD","SETL",
 
366
"LDFPS","STFPS","STST",
 
367
"CLRF","CLRD","TSTF","TSTD",
 
368
"ABSF","ABSD","NEGF","NEGD",
 
369
"MULF","MULD","MODF","MODD",
 
370
"ADDF","ADDD","LDF","LDD",
 
371
"SUBF","SUBD","CMPF","CMPD",
 
372
"STF","STD","DIVF","DIVD",
 
373
"STEXP",
 
374
"STCFI","STCDI","STCFL","STCDL",
 
375
"STCFD","STCDF",
 
376
"LDEXP",
 
377
"LDCIF","LDCID","LDCLF","LDCLD",
 
378
"LDCFD","LDCDF",
 
379
NULL };
 
380
 
 
381
static const int32 opc_val[] = {
 
382
0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN,
 
383
0000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN,
 
384
0000100+I_SOP, 0000200+I_REG, 0000230+I_3B,
 
385
0000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, 
 
386
0000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, 
 
387
0000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, 
 
388
0000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, 
 
389
0000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, 
 
390
0000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, 
 
391
0000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, 
 
392
0000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, 
 
393
0000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR,
 
394
0002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR,
 
395
0004000+I_RSOP,
 
396
0005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP,
 
397
0005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP,
 
398
0006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP,
 
399
0006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP,
 
400
0007000+I_SOP,                0007200+I_SOP, 0007300+I_SOP,
 
401
0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP,
 
402
0050000+I_DOP, 0060000+I_DOP,
 
403
0070000+I_RSOP, 0071000+I_RSOP, 0072000+I_RSOP, 0073000+I_RSOP,
 
404
0074000+I_RSOP,
 
405
0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG,
 
406
0076020+I_REG,
 
407
0076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN,
 
408
0076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN,
 
409
0076044+I_NPN, 0076045+I_NPN, 
 
410
0076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN,
 
411
0076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN,
 
412
0076060+I_REG,
 
413
0076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN,
 
414
0076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN,
 
415
0076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN,
 
416
0076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN,
 
417
0076144+I_NPN, 0076145+I_NPN, 
 
418
0076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN,
 
419
0076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN,
 
420
0076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN,
 
421
0076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN,
 
422
0077000+I_SOB,
 
423
0100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR,
 
424
0102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR,
 
425
0103000+I_BR, 0103400+I_BR,
 
426
0104000+I_8B, 0104400+I_8B,
 
427
0105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP,
 
428
0105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP,
 
429
0106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP,
 
430
0106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP,
 
431
0110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP,
 
432
0150000+I_DOP, 0160000+I_DOP,
 
433
0170000+I_NPN, 0170001+I_NPN, 0170002+I_NPN, 0170011+I_NPN, 0170012+I_NPN,
 
434
0170100+I_SOP, 0170200+I_SOP, 0170300+I_SOP,
 
435
0170400+I_FOP, 0170400+I_FOP+I_D, 0170500+I_FOP, 0170500+I_FOP+I_D,
 
436
0170600+I_FOP, 0170600+I_FOP+I_D, 0170700+I_FOP, 0170700+I_FOP+I_D,
 
437
0171000+I_AFOP, 0171000+I_AFOP+I_D, 0171400+I_AFOP, 0171400+I_AFOP+I_D,
 
438
0172000+I_AFOP, 0172000+I_AFOP+I_D, 0172400+I_AFOP, 0172400+I_AFOP+I_D, 
 
439
0173000+I_AFOP, 0173000+I_AFOP+I_D, 0173400+I_AFOP, 0173400+I_AFOP+I_D,
 
440
0174000+I_AFOP, 0174000+I_AFOP+I_D, 0174400+I_AFOP, 0174400+I_AFOP+I_D,
 
441
0175000+I_ASOP,
 
442
0175400+I_ASMD, 0175400+I_ASMD+I_D, 0175400+I_ASMD+I_L, 0175400+I_ASMD+I_D+I_L, 
 
443
0176000+I_AFOP, 0176000+I_AFOP+I_D,
 
444
0176400+I_ASOP, 
 
445
0177000+I_ASMD, 0177000+I_ASMD+I_D, 0177000+I_ASMD+I_L, 0177000+I_ASMD+I_D+I_L, 
 
446
0177400+I_AFOP, 0177400+I_AFOP+I_D,
 
447
-1 };
 
448
 
 
449
static const char *rname [] =
 
450
{ "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" };
 
451
 
 
452
static const char *fname [] =
 
453
{ "F0", "F1", "F2", "F3", "F4", "F5", "?6", "?7" };
 
454
 
 
455
static const char r50_to_asc[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789";
 
456
 
 
457
/* Specifier decode
 
458
 
 
459
   Inputs:
 
460
        *of     =       output stream
 
461
        addr    =       current PC
 
462
        spec    =       specifier
 
463
        nval    =       next word
 
464
        flag    =       TRUE if decoding for CPU
 
465
        iflag   =       TRUE if decoding integer instruction
 
466
   Outputs:
 
467
        count   =       -number of extra words retired
 
468
*/
 
469
 
 
470
int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval,
 
471
        int32 flag, int32 iflag)
 
472
{
 
473
int32 reg, mode;
 
474
static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 };
 
475
static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 };
 
476
 
 
477
reg = spec & 07;
 
478
mode = ((spec >> 3) & 07);
 
479
switch (mode) {
 
480
case 0:
 
481
        if (iflag) fprintf (of, "%s", rname[reg]);
 
482
        else fprintf (of, "%s", fname[reg]);
 
483
        break;
 
484
case 1:
 
485
        fprintf (of, "(%s)", rname[reg]);
 
486
        break;
 
487
case 2:
 
488
        if (reg != 7) fprintf (of, "(%s)+", rname[reg]);
 
489
        else fprintf (of, "#%-o", nval);
 
490
        break;
 
491
case 3:
 
492
        if (reg != 7) fprintf (of, "@(%s)+", rname[reg]);
 
493
        else fprintf (of, "@#%-o", nval);
 
494
        break;
 
495
case 4:
 
496
        fprintf (of, "-(%s)", rname[reg]);
 
497
        break;
 
498
case 5:
 
499
        fprintf (of, "@-(%s)", rname[reg]);
 
500
        break;
 
501
case 6:
 
502
        if ((reg != 7) || !flag) fprintf (of, "%-o(%s)", nval, rname[reg]);
 
503
        else fprintf (of, "%-o", (nval + addr + 4) & 0177777);
 
504
        break;
 
505
case 7:
 
506
        if ((reg != 7) || !flag) fprintf (of, "@%-o(%s)", nval, rname[reg]);
 
507
        else fprintf (of, "@%-o", (nval + addr + 4) & 0177777);
 
508
        break;  }                                       /* end case */
 
509
return ((reg == 07)? pcwd[mode]: rgwd[mode]);
 
510
}
 
511
 
 
512
/* Symbolic decode
 
513
 
 
514
   Inputs:
 
515
        *of     =       output stream
 
516
        addr    =       current PC
 
517
        *val    =       values to decode
 
518
        *uptr   =       pointer to unit
 
519
        sw      =       switches
 
520
   Outputs:
 
521
        return  =       if >= 0, error code
 
522
                        if < 0, number of extra words retired
 
523
*/
 
524
 
 
525
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
 
526
        UNIT *uptr, int32 sw)
 
527
{
 
528
int32 cflag, i, j, c1, c2, c3, inst, fac, srcm, srcr, dstm, dstr;
 
529
int32 l8b, brdisp, wd1, wd2;
 
530
extern int32 FPS;
 
531
 
 
532
cflag = (uptr == NULL) || (uptr == &cpu_unit);
 
533
c1 = val[0] & 0177;
 
534
c2 = (val[0] >> 8) & 0177;
 
535
if (sw & SWMASK ('A')) {                                /* ASCII? */
 
536
        fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
 
537
        return SCPE_OK;  }
 
538
if (sw & SWMASK ('C')) {                                /* character? */
 
539
        fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
 
540
        fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
 
541
        return SCPE_OK;  }
 
542
if (sw & SWMASK ('R')) {                                /* radix 50? */
 
543
        if (val[0] > 0174777) return SCPE_ARG;          /* max value */
 
544
        c3 = val[0] % 050;
 
545
        c2 = (val[0] / 050) % 050;
 
546
        c1 = val[0] / (050 * 050);
 
547
        fprintf (of, "%c%c%c", r50_to_asc[c1],
 
548
                r50_to_asc[c2], r50_to_asc[c3]);
 
549
        return SCPE_OK;  }
 
550
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
 
551
 
 
552
inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) |
 
553
        ((FPS << (I_V_D - FPS_V_D)) & I_D);             /* inst + fp mode */
 
554
for (i = 0; opc_val[i] >= 0; i++) {                     /* loop thru ops */
 
555
    j = (opc_val[i] >> I_V_CL) & I_M_CL;                /* get class */
 
556
    if ((opc_val[i] & 0777777) == (inst & masks[j])) {  /* match? */
 
557
        srcm = (inst >> 6) & 077;                       /* opr fields */
 
558
        srcr = srcm & 07;
 
559
        fac = srcm & 03;
 
560
        dstm = inst & 077;
 
561
        dstr = dstm & 07;
 
562
        l8b = inst & 0377;
 
563
 
 
564
/* Instruction decode */
 
565
 
 
566
        switch (j) {                                    /* case on class */
 
567
        case I_V_NPN: case I_V_CCC: case I_V_CCS:       /* no operands */
 
568
                fprintf (of, "%s", opcode[i]);
 
569
                return SCPE_OK;
 
570
        case I_V_REG:                                   /* reg */
 
571
                fprintf (of, "%s %-s", opcode[i], rname[dstr]);
 
572
                return SCPE_OK;
 
573
        case I_V_SOP:                                   /* sop */
 
574
                fprintf (of, "%s ", opcode[i]);
 
575
                return fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
 
576
        case I_V_3B:                                    /* 3b */
 
577
                fprintf (of, "%s %-o", opcode[i], dstr);
 
578
                return SCPE_OK;
 
579
        case I_V_FOP:                                   /* fop */
 
580
                fprintf (of, "%s ", opcode[i]);
 
581
                return fprint_spec (of, addr, dstm, val[1], cflag, FALSE);
 
582
        case I_V_AFOP:                                  /* afop */
 
583
                fprintf (of, "%s %s,", opcode[i], fname[fac]);
 
584
                return fprint_spec (of, addr, dstm, val[1], cflag, FALSE);
 
585
        case I_V_6B:                                    /* 6b */
 
586
                fprintf (of, "%s %-o", opcode[i], dstm);
 
587
                return SCPE_OK;
 
588
        case I_V_BR:                                    /* cond branch */
 
589
                fprintf (of, "%s ", opcode[i]);
 
590
                brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;
 
591
                if (cflag) fprintf (of, "%-o", (addr + brdisp) & 0177777);
 
592
                else if (brdisp < 01000) fprintf (of, ".+%-o", brdisp);
 
593
                else fprintf (of, ".-%-o", 0200000 - brdisp);
 
594
                return SCPE_OK;
 
595
        case I_V_8B:                                    /* 8b */
 
596
                fprintf (of, "%s %-o", opcode[i], l8b);
 
597
                return SCPE_OK;
 
598
        case I_V_SOB:                                   /* sob */
 
599
                fprintf (of, "%s %s,", opcode[i], rname[srcr]);
 
600
                brdisp = (dstm * 2) - 2;
 
601
                if (cflag) fprintf (of, "%-o", (addr - brdisp) & 0177777);
 
602
                else if (brdisp <= 0) fprintf (of, ".+%-o", -brdisp);
 
603
                else fprintf (of, ".-%-o", brdisp);
 
604
                return SCPE_OK;
 
605
        case I_V_RSOP:                                  /* rsop */
 
606
                fprintf (of, "%s %s,", opcode[i], rname[srcr]);
 
607
                return fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
 
608
        case I_V_ASOP: case I_V_ASMD:                   /* asop, asmd */
 
609
                fprintf (of, "%s %s,", opcode[i], fname[fac]);
 
610
                return fprint_spec (of, addr, dstm, val[1], cflag, TRUE);
 
611
        case I_V_DOP:                                   /* dop */
 
612
                fprintf (of, "%s ", opcode[i]);
 
613
                wd1 = fprint_spec (of, addr, srcm, val[1], cflag, TRUE);
 
614
                fprintf (of, ",");
 
615
                wd2 = fprint_spec (of, addr - wd1 - wd1, dstm,
 
616
                        val[1 - wd1], cflag, TRUE);
 
617
                return wd1 + wd2;  }                    /* end case */
 
618
                }                                       /* end if */
 
619
        }                                               /* end for */
 
620
return SCPE_ARG;                                        /* no match */
 
621
}
 
622
 
 
623
#define A_PND   100                                     /* # seen */
 
624
#define A_MIN   040                                     /* -( seen */
 
625
#define A_PAR   020                                     /* (Rn) seen */
 
626
#define A_REG   010                                     /* Rn seen */
 
627
#define A_PLS   004                                     /* + seen */
 
628
#define A_NUM   002                                     /* number seen */
 
629
#define A_REL   001                                     /* relative addr seen */
 
630
 
 
631
/* Register number
 
632
 
 
633
   Inputs:
 
634
        *cptr   =       pointer to input string
 
635
        *strings =      pointer to register names
 
636
        mchar   =       character to match after register name
 
637
   Outputs:
 
638
        rnum    =       0..7 if a legitimate register
 
639
                        < 0 if error
 
640
*/
 
641
 
 
642
int32 get_reg (char *cptr, const char *strings[], char mchar)
 
643
{
 
644
int32 i;
 
645
 
 
646
if (*(cptr + 2) != mchar) return -1;
 
647
for (i = 0; i < 8; i++) {
 
648
        if (strncmp (cptr, strings[i], 2) == 0) return i;  }
 
649
return -1;
 
650
}
 
651
 
 
652
/* Number or memory address
 
653
 
 
654
   Inputs:
 
655
        *cptr   =       pointer to input string
 
656
        *dptr   =       pointer to output displacement
 
657
        *pflag  =       pointer to accumulating flags
 
658
   Outputs:
 
659
        cptr    =       pointer to next character in input string
 
660
                        NULL if parsing error
 
661
 
 
662
   Flags: 0 (no result), A_NUM (number), A_REL (relative)
 
663
*/
 
664
 
 
665
char *get_addr (char *cptr, int32 *dptr, int32 *pflag)
 
666
{
 
667
int32 val, minus;
 
668
char *tptr;
 
669
 
 
670
minus = 0;
 
671
 
 
672
if (*cptr == '.') {                                     /* relative? */
 
673
        *pflag = *pflag | A_REL;
 
674
        cptr++;  }
 
675
if (*cptr == '+') {                                     /* +? */
 
676
        *pflag = *pflag | A_NUM;
 
677
        cptr++;  }
 
678
if (*cptr == '-') {                                     /* -? */
 
679
        *pflag = *pflag | A_NUM;
 
680
        minus = 1;
 
681
        cptr++;  }
 
682
errno = 0;
 
683
val = strtoul (cptr, &tptr, 8);
 
684
if (cptr == tptr) {                                     /* no number? */
 
685
        if (*pflag == (A_REL + A_NUM)) return NULL;     /* .+, .-? */
 
686
        *dptr = 0;
 
687
        return cptr;  }
 
688
if (errno || (*pflag == A_REL)) return NULL;            /* .n? */
 
689
*dptr = (minus? -val: val) & 0177777;
 
690
*pflag = *pflag | A_NUM;
 
691
return tptr;
 
692
}
 
693
 
 
694
/* Specifier decode
 
695
 
 
696
   Inputs:
 
697
        *cptr   =       pointer to input string
 
698
        addr    =       current PC
 
699
        n1      =       0 if no extra word used
 
700
                        -1 if extra word used in prior decode
 
701
        *sptr   =       pointer to output specifier
 
702
        *dptr   =       pointer to output displacement
 
703
        cflag   =       true if parsing for the CPU
 
704
        iflag   =       true if integer specifier
 
705
   Outputs:
 
706
        status  =       = -1 extra word decoded
 
707
                        =  0 ok
 
708
                        = +1 error
 
709
*/
 
710
 
 
711
t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr,
 
712
        int32 cflag, int32 iflag)
 
713
{
 
714
int32 reg, indir, pflag, disp;
 
715
 
 
716
indir = 0;                                              /* no indirect */
 
717
pflag = 0;
 
718
 
 
719
if (*cptr == '@') {                                     /* indirect? */
 
720
        indir = 010;
 
721
        cptr++;  }
 
722
if (*cptr == '#') {                                     /* literal? */
 
723
        pflag = pflag | A_PND;
 
724
        cptr++;  }
 
725
if (strncmp (cptr, "-(", 2) == 0) {                     /* autodecrement? */
 
726
        pflag = pflag | A_MIN;
 
727
        cptr++;  }
 
728
else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1;
 
729
if (*cptr == '(') {                                     /* register index? */
 
730
        pflag = pflag | A_PAR;
 
731
        if ((reg = get_reg (cptr + 1, rname, ')')) < 0) return 1;
 
732
        cptr = cptr + 4;
 
733
        if (*cptr == '+') {                             /* autoincrement? */
 
734
                pflag = pflag | A_PLS;
 
735
                cptr++;  }  }
 
736
else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) {
 
737
        pflag = pflag | A_REG;
 
738
        cptr = cptr + 2;  }
 
739
if (*cptr != 0) return 1;                               /* all done? */
 
740
 
 
741
/* Specifier decode, continued */
 
742
 
 
743
switch (pflag) {                                        /* case on syntax */
 
744
case A_REG:                                             /* Rn, @Rn */
 
745
        *sptr = indir + reg;
 
746
        return 0;
 
747
case A_PAR:                                             /* (Rn), @(Rn) */
 
748
        if (indir) {                                    /* @(Rn) = @0(Rn) */
 
749
                *sptr = 070 + reg;
 
750
                *dptr = 0;
 
751
                return -1;  }
 
752
        else *sptr = 010 + reg;
 
753
        return 0;
 
754
case A_PAR+A_PLS:                                       /* (Rn)+, @(Rn)+ */
 
755
        *sptr = 020 + indir + reg;
 
756
        return 0;
 
757
case A_MIN+A_PAR:                                       /* -(Rn), @-(Rn) */
 
758
        *sptr = 040 + indir + reg;
 
759
        return 0;
 
760
case A_NUM+A_PAR:                                       /* d(Rn), @d(Rn) */
 
761
        *sptr = 060 + indir + reg;
 
762
        *dptr = disp;
 
763
        return -1;
 
764
case A_PND+A_REL: case A_PND+A_REL+A_NUM:               /* #.+n, @#.+n */
 
765
        if (!cflag) return 1;
 
766
        disp = (disp + addr) & 0177777;                 /* fall through */
 
767
case A_PND+A_NUM:                                       /* #n, @#n */
 
768
        *sptr = 027 + indir;
 
769
        *dptr = disp;
 
770
        return -1;
 
771
case A_REL: case A_REL+A_NUM:                           /* .+n, @.+n */
 
772
        *sptr = 067 + indir;
 
773
        *dptr = (disp - 4 + (2 * n1)) & 0177777;
 
774
        return -1;
 
775
case A_NUM:                                             /* n, @n */
 
776
        if (cflag) {                                    /* CPU - use rel */
 
777
                *sptr = 067 + indir;
 
778
                *dptr = (disp - addr - 4 + (2 * n1)) & 0177777;  }
 
779
        else {  if (indir) return 1;                    /* other - use abs */
 
780
                *sptr = 037;
 
781
                *dptr = disp;  }
 
782
        return -1;
 
783
default:
 
784
        return 1;  }                                    /* end case */
 
785
}
 
786
 
 
787
/* Symbolic input
 
788
 
 
789
   Inputs:
 
790
        *cptr   =       pointer to input string
 
791
        addr    =       current PC
 
792
        *uptr   =       pointer to unit
 
793
        *val    =       pointer to output values
 
794
        sw      =       switches
 
795
   Outputs:
 
796
        status  =       > 0   error code
 
797
                        <= 0  -number of extra words
 
798
*/
 
799
 
 
800
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
 
801
{
 
802
int32 cflag, d, i, j, reg, spec, n1, n2, disp, pflag;
 
803
t_stat r;
 
804
char *tptr, gbuf[CBUFSIZE];
 
805
 
 
806
cflag = (uptr == NULL) || (uptr == &cpu_unit);
 
807
while (isspace (*cptr)) cptr++;                         /* absorb spaces */
 
808
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
 
809
        if (cptr[0] == 0) return SCPE_ARG;              /* must have 1 char */
 
810
        val[0] = (t_value) cptr[0];
 
811
        return SCPE_OK;  }
 
812
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
 
813
        if (cptr[0] == 0) return SCPE_ARG;              /* must have 1 char */
 
814
        val[0] = ((t_value) cptr[1] << 8) + (t_value) cptr[0];
 
815
        return SCPE_OK;  }
 
816
if (sw & SWMASK ('R')) return SCPE_ARG;                 /* radix 50 */
 
817
 
 
818
cptr = get_glyph (cptr, gbuf, 0);                       /* get opcode */
 
819
n1 = n2 = pflag = 0;
 
820
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
 
821
if (opcode[i] == NULL) return SCPE_ARG;
 
822
val[0] = opc_val[i] & 0177777;                          /* get value */
 
823
j = (opc_val[i] >> I_V_CL) & I_M_CL;                    /* get class */
 
824
 
 
825
switch (j) {                                            /* case on class */
 
826
case I_V_NPN:                                           /* no operand */
 
827
        break;
 
828
case I_V_REG:                                           /* register */
 
829
        cptr = get_glyph (cptr, gbuf, 0);               /* get glyph */
 
830
        if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
 
831
        val[0] = val[0] | reg;
 
832
        break;
 
833
case I_V_3B: case I_V_6B: case I_V_8B:                  /* xb literal */
 
834
        cptr = get_glyph (cptr, gbuf, 0);               /* get literal */
 
835
        d = get_uint (gbuf, 8, (1 << j) - 1, &r);
 
836
        if (r != SCPE_OK) return SCPE_ARG;
 
837
        val[0] = val[0] | d;                            /* put in place */
 
838
        break;
 
839
case I_V_BR:                                            /* cond br */
 
840
        cptr = get_glyph (cptr, gbuf, 0);               /* get address */
 
841
        tptr = get_addr (gbuf, &disp, &pflag);          /* parse */
 
842
        if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG;
 
843
        if ((pflag & A_REL) == 0) {
 
844
                if (cflag) disp = (disp - addr) & 0177777;
 
845
                else return SCPE_ARG;  }
 
846
        if ((disp & 1) || (disp > 0400) && (disp < 0177402)) return SCPE_ARG;
 
847
        val[0] = val[0] | (((disp - 2) >> 1) & 0377);
 
848
        break;
 
849
case I_V_SOB:                                           /* sob */
 
850
        cptr = get_glyph (cptr, gbuf, ',');             /* get glyph */
 
851
        if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
 
852
        val[0] = val[0] | (reg << 6);
 
853
        cptr = get_glyph (cptr, gbuf, 0);               /* get address */
 
854
        tptr = get_addr (gbuf, &disp, &pflag);          /* parse */
 
855
        if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG;
 
856
        if ((pflag & A_REL) == 0) {
 
857
                if (cflag) disp = (disp - addr) & 0177777;
 
858
                else return SCPE_ARG;  }
 
859
        if ((disp & 1) || ((disp > 2) && (disp < 0177604))) return SCPE_ARG;
 
860
        val[0] = val[0] | (((2 - disp) >> 1) & 077);
 
861
        break;
 
862
case I_V_RSOP:                                          /* reg, sop */
 
863
        cptr = get_glyph (cptr, gbuf, ',');             /* get glyph */
 
864
        if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
 
865
        val[0] = val[0] | (reg << 6);                   /* fall through */
 
866
case I_V_SOP:                                           /* sop */
 
867
        cptr = get_glyph (cptr, gbuf, 0);               /* get glyph */
 
868
        if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)
 
869
                return SCPE_ARG;
 
870
        val[0] = val[0] | spec;
 
871
        break;
 
872
case I_V_AFOP: case I_V_ASOP: case I_V_ASMD:            /* fac, (s)fop */
 
873
        cptr = get_glyph (cptr, gbuf, ',');             /* get glyph */
 
874
        if ((reg = get_reg (gbuf, fname, 0)) < 0) return SCPE_ARG;
 
875
        if (reg > 3) return SCPE_ARG;
 
876
        val[0] = val[0] | (reg << 6);                   /* fall through */
 
877
case I_V_FOP:                                           /* fop */
 
878
        cptr = get_glyph (cptr, gbuf, 0);               /* get glyph */
 
879
        if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, 
 
880
                (j == I_V_ASOP) || (j == I_V_ASMD))) > 0) return SCPE_ARG;
 
881
        val[0] = val[0] | spec;
 
882
        break;
 
883
case I_V_DOP:                                           /* double op */
 
884
        cptr = get_glyph (cptr, gbuf, ',');             /* get glyph */
 
885
        if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0)
 
886
                return SCPE_ARG;
 
887
        val[0] = val[0] | (spec << 6);
 
888
        cptr = get_glyph (cptr, gbuf, 0);               /* get glyph */
 
889
        if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1],
 
890
                cflag, TRUE)) > 0) return SCPE_ARG;
 
891
        val[0] = val[0] | spec;
 
892
        break;
 
893
case I_V_CCC: case I_V_CCS:                             /* cond code oper */
 
894
        for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
 
895
                cptr = get_glyph (cptr, gbuf, 0)) {
 
896
                for (i = 0; (opcode[i] != NULL) &&
 
897
                        (strcmp (opcode[i], gbuf) != 0) ; i++) ;
 
898
                if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) ||
 
899
                        (opcode[i] == NULL)) return SCPE_ARG;
 
900
                val[0] = val[0] | (opc_val[i] & 0177777);  }
 
901
        break;
 
902
default:
 
903
        return SCPE_ARG;  }
 
904
if (*cptr != 0) return SCPE_ARG;                        /* junk at end? */
 
905
return n1 + n2;
 
906
}