1
/* vax_sys.c: VAX simulator interface
3
Copyright (c) 1998-2004, 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
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.
26
21-Mar-04 RMS Added RXV21 support
27
06-May-03 RMS Added support for second DELQA
28
12-Oct-02 RMS Added multiple RQ controller support
29
10-Oct-02 RMS Added DELQA support
30
21-Sep-02 RMS Extended symbolic ex/mod to all byte devices
31
06-Sep-02 RMS Added TMSCP support
32
14-Jul-02 RMS Added infinite loop message
38
extern DEVICE cpu_dev;
39
extern DEVICE tlb_dev;
40
extern DEVICE rom_dev;
41
extern DEVICE nvr_dev;
42
extern DEVICE sysd_dev;
43
extern DEVICE qba_dev;
44
extern DEVICE ptr_dev, ptp_dev;
45
extern DEVICE tti_dev, tto_dev;
46
extern DEVICE csi_dev, cso_dev;
47
extern DEVICE lpt_dev;
48
extern DEVICE clk_dev;
49
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
55
extern DEVICE xq_dev, xqb_dev;
59
extern int32 saved_PC;
60
extern int32 sim_switches;
62
extern void WriteB (int32 pa, int32 val);
63
extern void rom_wr (int32 pa, int32 val, int32 lnt);
64
t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val);
65
int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt);
66
t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val);
67
int32 parse_brdisp (char *cptr, uint32 addr, t_value *val,
68
int32 vp, int32 lnt, t_stat *r);
69
int32 parse_spec (char *cptr, uint32 addr, t_value *val,
70
int32 vp, int32 disp, t_stat *r);
71
char *parse_rnum (char *cptr, int32 *rn);
72
int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp,
73
int lnt, int32 minus);
75
/* SCP data structures and interface routines
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
85
char sim_name[] = "VAX";
87
REG *sim_PC = &cpu_reg[0];
91
DEVICE *sim_devices[] = {
119
const char *sim_stop_messages[] = {
123
"CHMx on interrupt stack",
124
"Invalid SCB vector",
125
"Exception in interrupt or exception",
126
"Process PTE in P0 or P1 space",
127
"Interrupt at undefined IPL",
130
"Sanity timer expired",
132
"Unknown abort code" };
136
The binary loader handles absolute system images, that is, system
137
images linked /SYSTEM. These are simply a byte stream, with no
138
origin or relocation information.
142
-o for memory, specify origin
145
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
149
uint32 origin, limit;
150
extern int32 ssc_cnf;
151
#define SSCCNF_BLO 0x80000000
153
if (flag) return SCPE_ARG; /* dump? */
154
if (sim_switches & SWMASK ('R')) { /* ROM? */
156
limit = ROMBASE + ROMSIZE; }
157
else if (sim_switches & SWMASK ('N')) { /* NVR? */
159
limit = NVRBASE + NVRSIZE;
160
ssc_cnf = ssc_cnf & ~SSCCNF_BLO; }
161
else { origin = 0; /* memory */
162
limit = (uint32) cpu_unit.capac;
163
if (sim_switches & SWMASK ('O')) { /* origin? */
164
origin = (int32) get_uint (cptr, 16, 0xFFFFFFFF, &r);
165
if (r != SCPE_OK) return SCPE_ARG; } }
167
while ((i = getc (fileref)) != EOF) { /* read byte stream */
168
if (origin >= limit) return SCPE_NXM; /* NXM? */
169
if (sim_switches & SWMASK ('R')) /* ROM? */
170
rom_wr (origin, i, L_BYTE); /* not writeable */
171
else WriteB (origin, i); /* store byte */
172
origin = origin + 1; }
176
/* Factory bad block table creation routine
178
This routine writes a DEC standard 044 compliant bad block table on the
179
last track of the specified unit. The bad block table consists of 10
180
repetitions of the same table, formatted as follows:
182
words 0-1 pack id number
183
words 2-3 cylinder/sector/surface specifications
185
words n-n+1 end of table (-1,-1)
188
uptr = pointer to unit
189
sec = number of sectors per surface
190
wds = number of words per sector
195
t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds)
200
if ((sec < 2) || (wds < 16)) return SCPE_ARG;
201
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
202
if (!get_yn ("Overwrite last track? [N]", FALSE)) return SCPE_OK;
203
da = (int32) (uptr->capac - (sec * wds)) * sizeof (int16);
204
if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR;
205
if ((buf = malloc (wds * sizeof (int32))) == NULL) return SCPE_MEM;
208
for (i = 2; i < wds; i++) buf[i] = 0xFFFFFFFF;
209
for (i = 0; (i < sec) && (i < 10); i++)
210
fxwrite (buf, sizeof (int32), wds, uptr->fileref);
212
if (ferror (uptr->fileref)) return SCPE_IOERR;
216
/* Dispatch/decoder table
218
The first entry contains:
219
- FPD legal flag (DR_F)
220
- number of specifiers for decode bits 2:0>
221
- number of specifiers for unimplemented instructions bits<6:4>
224
const uint16 drom[NUM_INST][MAX_SPEC + 1] = {
225
0, 0, 0, 0, 0, 0, 0, /* HALT */
226
0, 0, 0, 0, 0, 0, 0, /* NOP */
227
0, 0, 0, 0, 0, 0, 0, /* REI */
228
0, 0, 0, 0, 0, 0, 0, /* BPT */
229
0, 0, 0, 0, 0, 0, 0, /* RET */
230
0, 0, 0, 0, 0, 0, 0, /* RSB */
231
0, 0, 0, 0, 0, 0, 0, /* LDPCTX */
232
0, 0, 0, 0, 0, 0, 0, /* SVPCTX */
233
4+DR_F, RW, AB, RW, AB, 0, 0, /* CVTPS */
234
4+DR_F, RW, AB, RW, AB, 0, 0, /* CVTSP */
235
6, RL, RL, RL, RL, RL, WL, /* INDEX */
236
4+DR_F, AB, RL, RW, AB, 0, 0, /* CRC */
237
3, RB, RW, AB, 0, 0, 0, /* PROBER */
238
3, RB, RW, AB, 0, 0, 0, /* PROBEW */
239
2, AB, AB, 0, 0, 0, 0, /* INSQUE */
240
2, AB, WL, 0, 0, 0, 0, /* REMQUE */
241
1, BB, 0, 0, 0, 0, 0, /* BSBB */
242
1, BB, 0, 0, 0, 0, 0, /* BRB */
243
1, BB, 0, 0, 0, 0, 0, /* BNEQ */
244
1, BB, 0, 0, 0, 0, 0, /* BEQL */
245
1, BB, 0, 0, 0, 0, 0, /* BGTR */
246
1, BB, 0, 0, 0, 0, 0, /* BLEQ */
247
1, AB, 0, 0, 0, 0, 0, /* JSB */
248
1, AB, 0, 0, 0, 0, 0, /* JMP */
249
1, BB, 0, 0, 0, 0, 0, /* BGEQ */
250
1, BB, 0, 0, 0, 0, 0, /* BLSS */
251
1, BB, 0, 0, 0, 0, 0, /* BGTRU */
252
1, BB, 0, 0, 0, 0, 0, /* BLEQU */
253
1, BB, 0, 0, 0, 0, 0, /* BVC */
254
1, BB, 0, 0, 0, 0, 0, /* BVS */
255
1, BB, 0, 0, 0, 0, 0, /* BCC */
256
1, BB, 0, 0, 0, 0, 0, /* BCS */
257
4+DR_F, RW, AB, RW, AB, 0, 0, /* ADDP4 */
258
6+DR_F, RW, AB, RW, AB, RW, AB, /* ADDP6 */
259
4+DR_F, RW, AB, RW, AB, 0, 0, /* SUBP4 */
260
6+DR_F, RW, AB, RW, AB, RW, AB, /* SUBP6 */
261
5+DR_F, RW, AB, AB, RW, AB, 0, /* CVTPT */
262
6+DR_F, RW, AB, RW, AB, RW, AB, /* MULP6 */
263
5+DR_F, RW, AB, AB, RW, AB, 0, /* CVTTP */
264
6+DR_F, RW, AB, RW, AB, RW, AB, /* DIVP6 */
265
3+DR_F, RW, AB, AB, 0, 0, 0, /* MOVC3 */
266
3+DR_F, RW, AB, AB, 0, 0, 0, /* CMPC3 */
267
4+DR_F, RW, AB, AB, RB, 0, 0, /* SCANC */
268
4+DR_F, RW, AB, AB, RB, 0, 0, /* SPANC */
269
5+DR_F, RW, AB, RB, RW, AB, 0, /* MOVC5 */
270
5+DR_F, RW, AB, RB, RW, AB, 0, /* CMPC5 */
271
6+DR_F, RW, AB, RB, AB, RW, AB, /* MOVTC */
272
6+DR_F, RW, AB, RB, AB, RW, AB, /* MOVTUC */
273
1, BW, 0, 0, 0, 0, 0, /* BSBW */
274
1, BW, 0, 0, 0, 0, 0, /* BRW */
275
2, RW, WL, 0, 0, 0, 0, /* CVTWL */
276
2, RW, WB, 0, 0, 0, 0, /* CVTWB */
277
3+DR_F, RW, AB, AB, 0, 0, 0, /* MOVP */
278
3+DR_F, RW, AB, AB, 0, 0, 0, /* CMPP3 */
279
3+DR_F, RW, AB, WL, 0, 0, 0, /* CVTPL */
280
4+DR_F, RW, AB, RW, AB, 0, 0, /* CMPP4 */
281
4+DR_F, RW, AB, AB, AB, 0, 0, /* EDITPC */
282
4+DR_F, RW, AB, RW, AB, 0, 0, /* MATCHC */
283
3+DR_F, RB, RW, AB, 0, 0, 0, /* LOCC */
284
3+DR_F, RB, RW, AB, 0, 0, 0, /* SKPC */
285
2, RW, WL, 0, 0, 0, 0, /* MOVZWL */
286
4, RW, RW, MW, BW, 0, 0, /* ACBW */
287
2, AW, WL, 0, 0, 0, 0, /* MOVAW */
288
1, AW, 0, 0, 0, 0, 0, /* PUSHAW */
289
2, RF, ML, 0, 0, 0, 0, /* ADDF2 */
290
3, RF, RF, WL, 0, 0, 0, /* ADDF3 */
291
2, RF, ML, 0, 0, 0, 0, /* SUBF2 */
292
3, RF, RF, WL, 0, 0, 0, /* SUBF3 */
293
2, RF, ML, 0, 0, 0, 0, /* MULF2 */
294
3, RF, RF, WL, 0, 0, 0, /* MULF3 */
295
2, RF, ML, 0, 0, 0, 0, /* DIVF2 */
296
3, RF, RF, WL, 0, 0, 0, /* DIVF3 */
297
2, RF, WB, 0, 0, 0, 0, /* CVTFB */
298
2, RF, WW, 0, 0, 0, 0, /* CVTFW */
299
2, RF, WL, 0, 0, 0, 0, /* CVTFL */
300
2, RF, WL, 0, 0, 0, 0, /* CVTRFL */
301
2, RB, WL, 0, 0, 0, 0, /* CVTBF */
302
2, RW, WL, 0, 0, 0, 0, /* CVTWF */
303
2, RL, WL, 0, 0, 0, 0, /* CVTLF */
304
4, RF, RF, ML, BW, 0, 0, /* ACBF */
305
2, RF, WL, 0, 0, 0, 0, /* MOVF */
306
2, RF, RF, 0, 0, 0, 0, /* CMPF */
307
2, RF, WL, 0, 0, 0, 0, /* MNEGF */
308
1, RF, 0, 0, 0, 0, 0, /* TSTF */
309
5, RF, RB, RF, WL, WL, 0, /* EMODF */
310
3, RF, RW, AB, 0, 0, 0, /* POLYF */
311
2, RF, WQ, 0, 0, 0, 0, /* CVTFD */
312
0, 0, 0, 0, 0, 0, 0, /* reserved */
313
2, RW, WW, 0, 0, 0, 0, /* ADAWI */
314
0, 0, 0, 0, 0, 0, 0, /* reserved */
315
0, 0, 0, 0, 0, 0, 0, /* reserved */
316
0, 0, 0, 0, 0, 0, 0, /* reserved */
317
2, AB, AQ, 0, 0, 0, 0, /* INSQHI */
318
2, AB, AQ, 0, 0, 0, 0, /* INSQTI */
319
2, AQ, WL, 0, 0, 0, 0, /* REMQHI */
320
2, AQ, WL, 0, 0, 0, 0, /* REMQTI */
321
2, RD, MQ, 0, 0, 0, 0, /* ADDD2 */
322
3, RD, RD, WQ, 0, 0, 0, /* ADDD3 */
323
2, RD, MQ, 0, 0, 0, 0, /* SUBD2 */
324
3, RD, RD, WQ, 0, 0, 0, /* SUBD3 */
325
2, RD, MQ, 0, 0, 0, 0, /* MULD2 */
326
3, RD, RD, WQ, 0, 0, 0, /* MULD3 */
327
2, RD, MQ, 0, 0, 0, 0, /* DIVD2 */
328
3, RD, RD, WQ, 0, 0, 0, /* DIVD3 */
329
2, RD, WB, 0, 0, 0, 0, /* CVTDB */
330
2, RD, WW, 0, 0, 0, 0, /* CVTDW */
331
2, RD, WL, 0, 0, 0, 0, /* CVTDL */
332
2, RD, WL, 0, 0, 0, 0, /* CVTRDL */
333
2, RB, WQ, 0, 0, 0, 0, /* CVTBD */
334
2, RW, WQ, 0, 0, 0, 0, /* CVTWD */
335
2, RL, WQ, 0, 0, 0, 0, /* CVTLD */
336
4, RD, RD, MQ, BW, 0, 0, /* ACBD */
337
2, RD, WQ, 0, 0, 0, 0, /* MOVD */
338
2, RD, RD, 0, 0, 0, 0, /* CMPD */
339
2, RD, WQ, 0, 0, 0, 0, /* MNEGD */
340
1, RD, 0, 0, 0, 0, 0, /* TSTD */
341
5, RD, RB, RD, WL, WQ, 0, /* EMODD */
342
3, RD, RW, AB, 0, 0, 0, /* POLYD */
343
2, RD, WL, 0, 0, 0, 0, /* CVTDF */
344
0, 0, 0, 0, 0, 0, 0, /* reserved */
345
3, RB, RL, WL, 0, 0, 0, /* ASHL */
346
3, RB, RQ, WQ, 0, 0, 0, /* ASHQ */
347
4, RL, RL, RL, WQ, 0, 0, /* EMUL */
348
4, RL, RQ, WL, WL, 0, 0, /* EDIV */
349
1, WQ, 0, 0, 0, 0, 0, /* CLRQ */
350
2, RQ, WQ, 0, 0, 0, 0, /* MOVQ */
351
2, AQ, WL, 0, 0, 0, 0, /* MOVAQ */
352
1, AQ, 0, 0, 0, 0, 0, /* PUSHAQ */
353
2, RB, MB, 0, 0, 0, 0, /* ADDB2 */
354
3, RB, RB, WB, 0, 0, 0, /* ADDB3 */
355
2, RB, MB, 0, 0, 0, 0, /* SUBB2 */
356
3, RB, RB, WB, 0, 0, 0, /* SUBB3 */
357
2, RB, MB, 0, 0, 0, 0, /* MULB2 */
358
3, RB, RB, WB, 0, 0, 0, /* MULB3 */
359
2, RB, MB, 0, 0, 0, 0, /* DIVB2 */
360
3, RB, RB, WB, 0, 0, 0, /* DIVB3 */
361
2, RB, MB, 0, 0, 0, 0, /* BISB2 */
362
3, RB, RB, WB, 0, 0, 0, /* BISB3 */
363
2, RB, MB, 0, 0, 0, 0, /* BICB2 */
364
3, RB, RB, WB, 0, 0, 0, /* BICB3 */
365
2, RB, MB, 0, 0, 0, 0, /* XORB2 */
366
3, RB, RB, WB, 0, 0, 0, /* XORB3 */
367
2, RB, WB, 0, 0, 0, 0, /* MNEGB */
368
3, RB, RB, RB, 0, 0, 0, /* CASEB */
369
2, RB, WB, 0, 0, 0, 0, /* MOVB */
370
2, RB, RB, 0, 0, 0, 0, /* CMPB */
371
2, RB, WB, 0, 0, 0, 0, /* MCOMB */
372
2, RB, RB, 0, 0, 0, 0, /* BITB */
373
1, WB, 0, 0, 0, 0, 0, /* CLRB */
374
1, RB, 0, 0, 0, 0, 0, /* TSTB */
375
1, MB, 0, 0, 0, 0, 0, /* INCB */
376
1, MB, 0, 0, 0, 0, 0, /* DECB */
377
2, RB, WL, 0, 0, 0, 0, /* CVTBL */
378
2, RB, WW, 0, 0, 0, 0, /* CVTBW */
379
2, RB, WL, 0, 0, 0, 0, /* MOVZBL */
380
2, RB, WW, 0, 0, 0, 0, /* MOVZBW */
381
3, RB, RL, WL, 0, 0, 0, /* ROTL */
382
4, RB, RB, MB, BW, 0, 0, /* ACBB */
383
2, AB, WL, 0, 0, 0, 0, /* MOVAB */
384
1, AB, 0, 0, 0, 0, 0, /* PUSHAB */
385
2, RW, MW, 0, 0, 0, 0, /* ADDW2 */
386
3, RW, RW, WW, 0, 0, 0, /* ADDW3 */
387
2, RW, MW, 0, 0, 0, 0, /* SUBW2 */
388
3, RW, RW, WW, 0, 0, 0, /* SUBW3 */
389
2, RW, MW, 0, 0, 0, 0, /* MULW2 */
390
3, RW, RW, WW, 0, 0, 0, /* MULW3 */
391
2, RW, MW, 0, 0, 0, 0, /* DIVW2 */
392
3, RW, RW, WW, 0, 0, 0, /* DIVW3 */
393
2, RW, MW, 0, 0, 0, 0, /* BISW2 */
394
3, RW, RW, WW, 0, 0, 0, /* BISW3 */
395
2, RW, MW, 0, 0, 0, 0, /* BICW2 */
396
3, RW, RW, WW, 0, 0, 0, /* BICW3 */
397
2, RW, MW, 0, 0, 0, 0, /* XORW2 */
398
3, RW, RW, WW, 0, 0, 0, /* XORW3 */
399
2, RW, WW, 0, 0, 0, 0, /* MNEGW */
400
3, RW, RW, RW, 0, 0, 0, /* CASEW */
401
2, RW, WW, 0, 0, 0, 0, /* MOVW */
402
2, RW, RW, 0, 0, 0, 0, /* CMPW */
403
2, RW, WW, 0, 0, 0, 0, /* MCOMW */
404
2, RW, RW, 0, 0, 0, 0, /* BITW */
405
1, WW, 0, 0, 0, 0, 0, /* CLRW */
406
1, RW, 0, 0, 0, 0, 0, /* TSTW */
407
1, MW, 0, 0, 0, 0, 0, /* INCW */
408
1, MW, 0, 0, 0, 0, 0, /* DECW */
409
1, RW, 0, 0, 0, 0, 0, /* BISPSW */
410
1, RW, 0, 0, 0, 0, 0, /* BICPSW */
411
1, RW, 0, 0, 0, 0, 0, /* POPR */
412
1, RW, 0, 0, 0, 0, 0, /* PUSHR */
413
1, RW, 0, 0, 0, 0, 0, /* CHMK */
414
1, RW, 0, 0, 0, 0, 0, /* CHME */
415
1, RW, 0, 0, 0, 0, 0, /* CHMS */
416
1, RW, 0, 0, 0, 0, 0, /* CHMU */
417
2, RL, ML, 0, 0, 0, 0, /* ADDL2 */
418
3, RL, RL, WL, 0, 0, 0, /* ADDL3 */
419
2, RL, ML, 0, 0, 0, 0, /* SUBL2 */
420
3, RL, RL, WL, 0, 0, 0, /* SUBL3 */
421
2, RL, ML, 0, 0, 0, 0, /* MULL2 */
422
3, RL, RL, WL, 0, 0, 0, /* MULL3 */
423
2, RL, ML, 0, 0, 0, 0, /* DIVL2 */
424
3, RL, RL, WL, 0, 0, 0, /* DIVL3 */
425
2, RL, ML, 0, 0, 0, 0, /* BISL2 */
426
3, RL, RL, WL, 0, 0, 0, /* BISL3 */
427
2, RL, ML, 0, 0, 0, 0, /* BICL2 */
428
3, RL, RL, WL, 0, 0, 0, /* BICL3 */
429
2, RL, ML, 0, 0, 0, 0, /* XORL2 */
430
3, RL, RL, WL, 0, 0, 0, /* XORL3 */
431
2, RL, WL, 0, 0, 0, 0, /* MNEGL */
432
3, RL, RL, RL, 0, 0, 0, /* CASEL */
433
2, RL, WL, 0, 0, 0, 0, /* MOVL */
434
2, RL, RL, 0, 0, 0, 0, /* CMPL */
435
2, RL, WL, 0, 0, 0, 0, /* MCOML */
436
2, RL, RL, 0, 0, 0, 0, /* BITL */
437
1, WL, 0, 0, 0, 0, 0, /* CLRL */
438
1, RL, 0, 0, 0, 0, 0, /* TSTL */
439
1, ML, 0, 0, 0, 0, 0, /* INCL */
440
1, ML, 0, 0, 0, 0, 0, /* DECL */
441
2, RL, ML, 0, 0, 0, 0, /* ADWC */
442
2, RL, ML, 0, 0, 0, 0, /* SBWC */
443
2, RL, RL, 0, 0, 0, 0, /* MTPR */
444
2, RL, WL, 0, 0, 0, 0, /* MFPR */
445
1, WL, 0, 0, 0, 0, 0, /* MOVPSL */
446
1, RL, 0, 0, 0, 0, 0, /* PUSHL */
447
2, AL, WL, 0, 0, 0, 0, /* MOVAL */
448
1, AL, 0, 0, 0, 0, 0, /* PUSHAL */
449
3, RL, VB, BB, 0, 0, 0, /* BBS */
450
3, RL, VB, BB, 0, 0, 0, /* BBC */
451
3, RL, VB, BB, 0, 0, 0, /* BBSS */
452
3, RL, VB, BB, 0, 0, 0, /* BBCS */
453
3, RL, VB, BB, 0, 0, 0, /* BBSC */
454
3, RL, VB, BB, 0, 0, 0, /* BBCC */
455
3, RL, VB, BB, 0, 0, 0, /* BBSSI */
456
3, RL, VB, BB, 0, 0, 0, /* BBCCI */
457
2, RL, BB, 0, 0, 0, 0, /* BLBS */
458
2, RL, BB, 0, 0, 0, 0, /* BLBC */
459
4, RL, RB, VB, WL, 0, 0, /* FFS */
460
4, RL, RB, VB, WL, 0, 0, /* FFC */
461
4, RL, RB, VB, RL, 0, 0, /* CMPV */
462
4, RL, RB, VB, RL, 0, 0, /* CMPZV */
463
4, RL, RB, VB, WL, 0, 0, /* EXTV */
464
4, RL, RB, VB, WL, 0, 0, /* EXTZV */
465
4, RL, RL, RB, VB, 0, 0, /* INSV */
466
4, RL, RL, ML, BW, 0, 0, /* ACBL */
467
3, RL, ML, BB, 0, 0, 0, /* AOBLSS */
468
3, RL, ML, BB, 0, 0, 0, /* AOBLEQ */
469
2, ML, BB, 0, 0, 0, 0, /* SOBGEQ */
470
2, ML, BB, 0, 0, 0, 0, /* SOBGTR */
471
2, RL, WB, 0, 0, 0, 0, /* CVTLB */
472
2, RL, WW, 0, 0, 0, 0, /* CVTLW */
473
6+DR_F, RB, RW, AB, RB, RW, AB, /* ASHP */
474
3+DR_F, RL, RW, AB, 0, 0, 0, /* CVTLP */
475
2, AB, AB, 0, 0, 0, 0, /* CALLG */
476
2, RL, AB, 0, 0, 0, 0, /* CALLS */
477
0, 0, 0, 0, 0, 0, 0, /* XFC */
478
0, 0, 0, 0, 0, 0, 0, /* 0FD */
479
0, 0, 0, 0, 0, 0, 0, /* 0FE */
480
0, 0, 0, 0, 0, 0, 0, /* 0FF */
481
0, 0, 0, 0, 0, 0, 0, /* 100-10F */
497
0, 0, 0, 0, 0, 0, 0, /* 110-11F */
513
0, 0, 0, 0, 0, 0, 0, /* 120-12F */
529
0, 0, 0, 0, 0, 0, 0, /* 130-13F */
531
0x20, RD, OC, 0, 0, 0, 0, /* CVTDH */
532
2, RG, WL, 0, 0, 0, 0, /* CVTGF */
545
2, RG, MQ, 0, 0, 0, 0, /* ADDG2 */
546
3, RG, RG, WQ, 0, 0, 0, /* ADDG3 */
547
2, RG, MQ, 0, 0, 0, 0, /* SUBG2 */
548
3, RG, RG, WQ, 0, 0, 0, /* SUBG3 */
549
2, RG, MQ, 0, 0, 0, 0, /* MULG2 */
550
3, RG, RG, WQ, 0, 0, 0, /* MULG3 */
551
2, RG, MQ, 0, 0, 0, 0, /* DIVG2 */
552
3, RG, RG, WQ, 0, 0, 0, /* DIVG3 */
553
2, RG, WB, 0, 0, 0, 0, /* CVTGB */
554
2, RG, WW, 0, 0, 0, 0, /* CVTGW */
555
2, RG, WL, 0, 0, 0, 0, /* CVTGL */
556
2, RG, WL, 0, 0, 0, 0, /* CVTRGL */
557
2, RB, WQ, 0, 0, 0, 0, /* CVTBG */
558
2, RW, WQ, 0, 0, 0, 0, /* CVTWG */
559
2, RL, WQ, 0, 0, 0, 0, /* CVTLG */
560
4, RG, RG, MQ, BW, 0, 0, /* ACBG */
561
2, RG, WQ, 0, 0, 0, 0, /* MOVG */
562
2, RG, RG, 0, 0, 0, 0, /* CMPG */
563
2, RG, WQ, 0, 0, 0, 0, /* MNEGG */
564
1, RG, 0, 0, 0, 0, 0, /* TSTG */
565
5, RG, RW, RG, WL, WQ, 0, /* EMODG */
566
3, RG, RW, AB, 0, 0, 0, /* POLYG */
567
0x20, RG, OC, 0, 0, 0, 0, /* CVTGH */
568
0, 0, 0, 0, 0, 0, 0, /* reserved */
569
0, 0, 0, 0, 0, 0, 0, /* reserved */
570
0, 0, 0, 0, 0, 0, 0, /* reserved */
571
0, 0, 0, 0, 0, 0, 0, /* reserved */
572
0, 0, 0, 0, 0, 0, 0, /* reserved */
573
0, 0, 0, 0, 0, 0, 0, /* reserved */
574
0, 0, 0, 0, 0, 0, 0, /* reserved */
575
0, 0, 0, 0, 0, 0, 0, /* reserved */
576
0, 0, 0, 0, 0, 0, 0, /* reserved */
577
0x20, OC, OC, 0, 0, 0, 0, /* ADDH2 */
578
0x30, OC, OC, OC, 0, 0, 0, /* ADDH3 */
579
0x20, OC, OC, 0, 0, 0, 0, /* SUBH2 */
580
0x30, OC, OC, OC, 0, 0, 0, /* SUBH3 */
581
0x20, OC, OC, 0, 0, 0, 0, /* MULH2 */
582
0x30, OC, OC, OC, 0, 0, 0, /* MULH3 */
583
0x20, OC, OC, 0, 0, 0, 0, /* DIVH2 */
584
0x30, OC, OC, OC, 0, 0, 0, /* DIVH3 */
585
0x20, OC, WB, 0, 0, 0, 0, /* CVTHB */
586
0x20, OC, WW, 0, 0, 0, 0, /* CVTHW */
587
0x20, OC, WL, 0, 0, 0, 0, /* CVTHL */
588
0x20, OC, WL, 0, 0, 0, 0, /* CVTRHL */
589
0x20, RB, OC, 0, 0, 0, 0, /* CVTBH */
590
0x20, RW, OC, 0, 0, 0, 0, /* CVTWH */
591
0x20, RL, OC, 0, 0, 0, 0, /* CVTLH */
592
0x40, OC, OC, OC, BW, 0, 0, /* ACBH */
593
0x20, OC, OC, 0, 0, 0, 0, /* MOVH */
594
0x20, OC, OC, 0, 0, 0, 0, /* CMPH */
595
0x20, OC, OC, 0, 0, 0, 0, /* MNEGH */
596
0x10, OC, 0, 0, 0, 0, 0, /* TSTH */
597
0x50, OC, RW, OC, WL, OC, 0, /* EMODH */
598
0x30, OC, RW, AB, 0, 0, 0, /* POLYH */
599
0x20, OC, WQ, 0, 0, 0, 0, /* CVTHG */
600
0, 0, 0, 0, 0, 0, 0, /* reserved */
601
0, 0, 0, 0, 0, 0, 0, /* reserved */
602
0, 0, 0, 0, 0, 0, 0, /* reserved */
603
0, 0, 0, 0, 0, 0, 0, /* reserved */
604
0, 0, 0, 0, 0, 0, 0, /* reserved */
605
0x10, OC, 0, 0, 0, 0, 0, /* CLRO */
606
0x20, OC, OC, 0, 0, 0, 0, /* MOVO */
607
0x20, OC, WL, 0, 0, 0, 0, /* MOVAO*/
608
0x10, OC, 0, 0, 0, 0, 0, /* PUSHAO*/
609
0, 0, 0, 0, 0, 0, 0, /* 180-18F */
625
0, 0, 0, 0, 0, 0, 0, /* 190-19F */
633
0x20, RF, OC, 0, 0, 0, 0, /* CVTFH */
634
2, RF, WQ, 0, 0, 0, 0, /* CVTFG */
641
0, 0, 0, 0, 0, 0, 0, /* 1A0-1AF */
657
0, 0, 0, 0, 0, 0, 0, /* 1B0-1BF */
673
0, 0, 0, 0, 0, 0, 0, /* 1C0-1CF */
689
0, 0, 0, 0, 0, 0, 0, /* 1D0-1DF */
705
0, 0, 0, 0, 0, 0, 0, /* 1E0-1EF */
721
0, 0, 0, 0, 0, 0, 0, /* 1F0-1FF */
727
0x20, OC, WL, 0, 0, 0, 0, /* CVTHF */
728
0x20, OC, WQ, 0, 0, 0, 0, /* CVTHD */
736
0, 0, 0, 0, 0, 0, 0 };
738
/* Opcode mnemonics table */
740
const char *opcode[] = {
741
"HALT", "NOP", "REI", "BPT", "RET", "RSB", "LDPCTX", "SVPCTX",
742
"CVTPS", "CVTSP", "INDEX", "CRC", "PROBER", "PROBEW", "INSQUE", "REMQUE",
743
"BSBB", "BRB", "BNEQ", "BEQL", "BGTR", "BLEQ", "JSB", "JMP",
744
"BGEQ", "BLSS", "BGTRU", "BLEQU", "BVC", "BVS", "BGEQU", "BLSSU",
745
"ADDP4", "ADDP6", "SUBP4", "SUBP6", "CVTPT", "MULP6", "CVTTP", "DIVP",
746
"MOVC3", "CMPC3", "SCANC", "SPANC", "MOVC5", "CMPC5", "MOVTC", "MOVTUC",
747
"BSBW", "BRW", "CVTWL", "CVTWB", "MOVP", "CMPP3", "CVTPL", "CMPP4",
748
"EDITPC", "MATCHC", "LOCC", "SKPC", "MOVZWL", "ACBW", "MOVAW", "PUSHAW",
749
"ADDF2", "ADDF3", "SUBF2", "SUBF3", "MULF2", "MULF3", "DIVF2", "DIVF3",
750
"CVTFB", "CVTFW", "CVTFL", "CVTRFL", "CVTBF", "CVTWF", "CVTLF", "ACBF",
751
"MOVF", "CMPF", "MNEGF", "TSTF", "EMODF", "POLYF", "CVTFD", NULL,
752
"ADAWI", NULL, NULL, NULL, "INSQHI", "INSQTI", "REMQHI", "REMQTI",
753
"ADDD2", "ADDD3", "SUBD2", "SUBD3", "MULD2", "MULD3", "DIVD2", "DIVD3",
754
"CVTDB", "CVTDW", "CVTDL", "CVTRDL", "CVTBD", "CVTWD", "CVTLD", "ACBD",
755
"MOVD", "CMPD", "MNEGD", "TSTD", "EMODD", "POLYD", "CVTDF", NULL,
756
"ASHL", "ASHQ", "EMUL", "EDIV", "CLRQ", "MOVQ", "MOVAQ", "PUSHAQ",
757
"ADDB2", "ADDB3", "SUBB2", "SUBB3", "MULB2", "MULB3", "DIVB2", "DIVB3",
758
"BISB2", "BISB3", "BICB2", "BICB3", "XORB2", "XORB3", "MNEGB", "CASEB",
759
"MOVB", "CMPB", "MCOMB", "BITB", "CLRB", "TSTB", "INCB", "DECB",
760
"CVTBL", "CVTBW", "MOVZBL", "MOVZBW", "ROTL", "ACBB", "MOVAB", "PUSHAB",
761
"ADDW2", "ADDW3", "SUBW2", "SUBW3", "MULW2", "MULW3", "DIVW2", "DIVW3",
762
"BISW2", "BISW3", "BICW2", "BICW3", "XORW2", "XORW3", "MNEGW", "CASEW",
763
"MOVW", "CMPW", "MCOMW", "BITW", "CLRW", "TSTW", "INCW", "DECW",
764
"BISPSW", "BICPSW", "POPR", "PUSHR", "CHMK", "CHME", "CHMS", "CHMU",
765
"ADDL2", "ADDL3", "SUBL2", "SUBL3", "MULL2", "MULL3", "DIVL2", "DIVL3",
766
"BISL2", "BISL3", "BICL2", "BICL3", "XORL2", "XORL3", "MNEGL", "CASEL",
767
"MOVL", "CMPL", "MCOML", "BITL", "CLRL", "TSTL", "INCL", "DECL",
768
"ADWC", "SBWC", "MTPR", "MFPR", "MOVPSL", "PUSHL", "MOVAL", "PUSHAL",
769
"BBS", "BBC", "BBSS", "BBCS", "BBSC", "BBCC", "BBSSI", "BBCCI",
770
"BLBS", "BLBC", "FFS", "FFC", "CMPV", "CMPZV", "EXTV", "EXTZV",
771
"INSV", "ACBL", "AOBLSS", "AOBLEQ", "SOBGEQ", "SOBGTR", "CVTLB", "CVTLW",
772
"ASHP", "CVTLP", "CALLG", "CALLS", "XFC", NULL, NULL, NULL,
773
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 100 - 11F */
774
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
775
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
776
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
777
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 120 - 13F */
778
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
779
NULL, NULL, "CVTDH", "CVTGF", NULL, NULL, NULL, NULL,
780
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
781
"ADDG2", "ADDG3", "SUBG2", "SUBG3", "MULG2", "MULG3", "DIVG2", "DIVG3",
782
"CVTGB", "CVTGW", "CVTGL", "CVTRGL", "CVTBG", "CVTWG", "CVTLG", "ACBG",
783
"MOVG", "CMPG", "MNEGG", "TSTG", "EMODG", "POLYG", "CVTGH", NULL,
784
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
785
"ADDH2", "ADDH3", "SUBH2", "SUBH3", "MULH2", "MULH3", "DIVH2", "DIVH3",
786
"CVTHB", "CVTHW", "CVTHL", "CVTRHL", "CVTBH", "CVTWH", "CVTLH", "ACBH",
787
"MOVH", "CMPH", "MNEGH", "TSTH", "EMODH", "POLYH", "CVTHG", NULL,
788
NULL, NULL, NULL, NULL, "CLRO", "MOVO", "MOVAO", "PUSHAO",
789
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 180 - 19F */
790
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
791
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
792
"CVTFH", "CVTFG", NULL, NULL, NULL, NULL, NULL, NULL,
793
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1A0 - 1BF */
794
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
795
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
796
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
797
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1C0 - 1DF */
798
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
799
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
800
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
801
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 1E0 - 1FF */
802
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
803
NULL, NULL, NULL, NULL, NULL, NULL, "CVTHF", "CVTHD",
804
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
806
const char *altcod[] = {
807
"CLRF", "CLRD", "CLRG", "CLRH", "MOVAF", "MOVAD", "MOVAG", "MOVAH",
808
"PUSHAF", "PUSHAD", "PUSHAG", "PUSHAH", "BNEQU", "BEQLU", "BCC", "BCS",
811
const int32 altop[] = {
812
0xD4, 0x7C, 0x7C, 0x17C, 0xDE, 0x7E, 0x7E, 0x17E,
813
0xDF, 0x7F, 0x7F, 0x17F, 0x12, 0x13, 0x1E, 0x1F };
815
const char* regname[] = {
816
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
817
"R8", "R9", "R10", "R11", "AP", "FP", "SP", "PC" };
819
#define GETNUM(d,n) for (k = d = 0; k < n; k++) \
820
d = d | (((int32) val[vp++]) << (k * 8))
827
*val = values to decode
828
*uptr = pointer to unit
831
return = if >= 0, error code
832
if < 0, number of extra bytes retired
835
t_stat fprint_sym (FILE *of, t_addr exta, t_value *val,
836
UNIT *uptr, int32 sw)
838
uint32 addr = (uint32) exta;
839
int32 c, k, num, vp, lnt, rdx;
843
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
844
dptr = find_dev_from_unit (uptr); /* find dev */
845
if (dptr == NULL) return SCPE_IERR;
846
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
847
if (sw & SWMASK ('B')) lnt = 1; /* get length */
848
else if (sw & SWMASK ('W')) lnt = 2;
849
else if (sw & SWMASK ('L')) lnt = 4;
850
else lnt = (uptr == &cpu_unit)? 4: 1;
851
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
852
else if (sw & SWMASK ('O')) rdx = 8;
853
else if (sw & SWMASK ('H')) rdx = 16;
854
else rdx = dptr->dradix;
855
vp = 0; /* init ptr */
856
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
857
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
858
if ((val[0] & 0x7F) == 0) return SCPE_ARG;
859
while (vp < lnt) { /* print string */
860
if ((c = (int32) val[vp++] & 0x7F) == 0) break;
861
fprintf (of, (c < 0x20)? "<%02X>": "%c", c); }
862
return -(vp - 1); } /* return # chars */
864
if (sw & SWMASK ('M') && (uptr == &cpu_unit)) { /* inst format? */
865
r = fprint_sym_m (of, addr, val); /* decode inst */
866
if (r <= 0) return r; }
868
GETNUM (num, lnt); /* get number */
869
fprint_val (of, (uint32) num, rdx, lnt * 8, PV_RZRO);
873
/* Symbolic decode for -m
878
*val = values to decode
880
return = if >= 0, error code
881
if < 0, number of extra bytes retired
884
t_stat fprint_sym_m (FILE *of, uint32 addr, t_value *val)
886
int32 i, k, vp, inst, numspec;
887
int32 num, spec, rn, disp, index;
889
vp = 0; /* init ptr */
890
inst = (int32) val[vp++]; /* get opcode */
891
if (inst == 0xFD) inst = 0x100 | (int32) val[vp++]; /* 2 byte op? */
892
if (opcode[inst] == NULL) return SCPE_ARG; /* defined? */
893
numspec = drom[inst][0] & DR_NSPMASK; /* get # spec */
894
if (numspec == 0) numspec = (drom[inst][0] & DR_USPMASK) >> 4;
895
fprintf (of, "%s", opcode[inst]); /* print name */
896
for (i = 0; i < numspec; i++) { /* loop thru spec */
897
fputc (i? ',': ' ', of); /* separator */
898
disp = drom[inst][i + 1]; /* get drom value */
899
if (disp == BB) { /* byte br disp? */
901
fprintf (of, "%-X", SXTB (num) + addr + vp); }
902
else if (disp == BW) { /* word br disp? */
904
fprintf (of, "%-X", SXTW (num) + addr + vp); }
906
spec = (int32) val[vp++]; /* get specifier */
907
if ((spec & 0xF0) == IDX) { /* index? */
908
index = spec; /* copy, get next */
909
spec = (int32) val[vp++]; }
911
rn = spec & 0xF; /* get reg # */
912
switch (spec & 0xF0) { /* case on mode */
913
case SH0: case SH1: case SH2: case SH3: /* s^# */
914
fprintf (of, "#%-X", spec);
917
fprintf (of, "%-s", regname[rn]);
920
fprintf (of, "(%-s)", regname[rn]);
922
case ADC: /* -(Rn) */
923
fprintf (of, "-(%-s)", regname[rn]);
925
case AIN: /* (Rn)+, #n */
926
if (rn != nPC) fprintf (of, "(%-s)+", regname[rn]);
929
vp = fprint_sym_qoimm (of, val, vp, 4);
930
else if (DR_LNT (disp) == L_QUAD)
931
vp = fprint_sym_qoimm (of, val, vp, 2);
933
GETNUM (num, DR_LNT (disp));
934
fprintf (of, "#%-X", num); } }
936
case AID: /* @(Rn)+, @#n */
937
if (rn != nPC) fprintf (of, "@(%-s)+", regname[rn]);
940
fprintf (of, "@#%-X", num); }
942
case BDD: /* @b^d(r),@b^n */
944
case BDP: /* b^d(r), b^n */
946
if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTB (num));
947
else if (num & BSIGN) fprintf (of, "-%-X(%-s)",
948
-num & BMASK, regname[rn]);
949
else fprintf (of, "%-X(%-s)", num, regname[rn]);
951
case WDD: /* @w^d(r),@w^n */
953
case WDP: /* w^d(r), w^n */
955
if (rn == nPC) fprintf (of, "%-X", addr + vp + SXTW (num));
956
else if (num & WSIGN) fprintf (of, "-%-X(%-s)",
957
-num & WMASK, regname[rn]);
958
else fprintf (of, "%-X(%-s)", num, regname[rn]);
960
case LDD: /* @l^d(r),@l^n */
962
case LDP: /* l^d(r),l^n */
964
if (rn == nPC) fprintf (of, "%-X", addr + vp + num);
965
else if (num & LSIGN) fprintf (of, "-%-X(%-s)",
967
else fprintf (of, "%-X(%-s)", num, regname[rn]);
968
break; } /* end case */
969
if (index) fprintf (of, "[%-s]", regname[index & 0xF]);
975
/* Symbolic decode, quad/octa immediates
979
*val = pointer to input values
980
vp = current index into val
981
lnt = number of longwords in immediate
983
vp = updated index into val
986
int32 fprint_sym_qoimm (FILE *of, t_value *val, int32 vp, int32 lnt)
988
int32 i, k, startp, num[4];
990
for (i = 0; i < lnt; i++) { GETNUM (num[lnt - 1 - i], 4); }
991
for (i = startp = 0; i < lnt; i++) {
992
if (startp) fprintf (of, "%08X", num[i]);
993
else if (num[i] || (i == (lnt - 1))) {
994
fprintf (of, "#%-X", num[i]);
999
#define PUTNUM(d,n) for (k = 0; k < n; k++) val[vp++] = (d >> (k * 8)) & 0xFF
1004
*cptr = pointer to input string
1006
*uptr = pointer to unit
1007
*val = pointer to output values
1010
status = > 0 error code
1011
<= 0 -number of extra words
1014
t_stat parse_sym (char *cptr, t_addr exta, UNIT *uptr, t_value *val, int32 sw)
1016
uint32 addr = (uint32) exta;
1017
int32 k, rdx, lnt, num, vp;
1020
static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF };
1022
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
1023
dptr = find_dev_from_unit (uptr); /* find dev */
1024
if (dptr == NULL) return SCPE_IERR;
1025
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
1026
if (sw & SWMASK ('B')) lnt = 1; /* get length */
1027
else if (sw & SWMASK ('W')) lnt = 2;
1028
else if (sw & SWMASK ('L')) lnt = 4;
1029
else lnt = (uptr == &cpu_unit)? 4: 1;
1030
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
1031
else if (sw & SWMASK ('O')) rdx = 8;
1032
else if (sw & SWMASK ('H')) rdx = 16;
1033
else rdx = dptr->dradix;
1035
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
1036
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
1037
if (*cptr == 0) return SCPE_ARG;
1038
while ((vp < lnt) && *cptr) { /* get chars */
1039
val[vp++] = *cptr++; }
1040
return -(vp - 1); } /* return # chars */
1042
if (uptr == &cpu_unit) { /* cpu only */
1043
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
1044
if (r <= 0) return r; }
1046
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
1047
if (r != SCPE_OK) return r;
1048
PUTNUM (num, lnt); /* store */
1052
/* Symbolic input for -m
1055
*cptr = pointer to input string
1057
*val = pointer to output values
1059
status = > 0 error code
1060
<= 0 -number of extra words
1063
t_stat parse_sym_m (char *cptr, uint32 addr, t_value *val)
1065
int32 i, numspec, disp, opc, vp;
1067
char gbuf[CBUFSIZE];
1069
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
1070
for (i = 0, opc = -1; (i < NUM_INST) && (opc < 0); i++) {
1071
if (opcode[i] && strcmp (gbuf, opcode[i]) == 0) opc = i; }
1072
if (opc < 0) { /* check alternates */
1073
for (i = 0; altcod[i] && (opc < 0); i++) {
1074
if (strcmp (gbuf, altcod[i]) == 0) opc = altop[i]; } }
1075
if (opc < 0) return SCPE_ARG; /* undefined? */
1077
if (opc >= 0x100) val[vp++] = 0xFD; /* 2 byte? */
1078
val[vp++] = opc & 0xFF; /* store opcode */
1079
numspec = drom[opc][0] & DR_NSPMASK; /* get # specifiers */
1080
if (numspec == 0) numspec = (drom[opc][0] & DR_USPMASK) >> 4;
1081
for (i = 1; i <= numspec; i++) { /* loop thru specs */
1082
if (i == numspec) cptr = get_glyph (cptr, gbuf, 0);
1083
else cptr = get_glyph (cptr, gbuf, ','); /* get specifier */
1084
disp = drom[opc][i]; /* get drom value */
1085
if (disp == BB) vp = parse_brdisp (gbuf, addr, val, vp, 0, &r);
1086
else if (disp == BW) vp = parse_brdisp (gbuf, addr, val, vp, 1, &r);
1087
else vp = parse_spec (gbuf, addr, val, vp, disp, &r);
1088
if (r != SCPE_OK) return r; }
1089
if (*cptr != 0) return SCPE_ARG;
1093
/* Parse a branch displacement
1096
cptr = pointer to input buffer
1097
addr = current address
1098
val = pointer to output array
1099
vp = current pointer in output array
1100
lnt = length (0 = byte, 1 = word)
1101
r = pointer to status
1103
vp = updated output pointer
1106
int32 parse_brdisp (char *cptr, uint32 addr, t_value *val, int32 vp,
1107
int32 lnt, t_stat *r)
1111
dest = (int32) get_uint (cptr, 16, 0xFFFFFFFF, r); /* get value */
1112
num = dest - (addr + vp + lnt + 1); /* compute offset */
1113
if ((num > (lnt? 32767: 127)) || (num < (lnt? -32768: -128))) return SCPE_ARG;
1114
PUTNUM (num, lnt + 1); /* store offset */
1118
/* Parse a specifier
1121
cptr = pointer to input buffer
1122
addr = current address
1123
val = pointer to output array
1124
vp = current pointer in output array
1125
disp = specifier dispatch
1126
r = pointer to status
1128
vp = updated output pointer
1131
#define SP_IND 0x200 /* indirect */
1132
#define SP_V_FORCE 6
1133
#define SP_FS 0x040 /* S^ */
1134
#define SP_FI 0x080 /* I^ */
1135
#define SP_FB 0x0C0 /* B^ */
1136
#define SP_FW 0x100 /* W^ */
1137
#define SP_FL 0x140 /* L^ */
1138
#define SP_LIT 0x020 /* # */
1139
#define SP_PLUS 0x010 /* plus */
1140
#define SP_MINUS 0x008 /* minus */
1141
#define SP_NUM 0x004 /* number */
1142
#define SP_IDX 0x002 /* (Rn) */
1143
#define SP_POSTP 0x001 /* trailing + */
1144
#define M1C(c,v) if (*cptr == c) { cptr++; fl = fl | v; }
1145
#define SPUTNUM(v,d) if (fl & SP_MINUS) v = -v; PUTNUM (v, d)
1146
#define PARSE_LOSE { *r = SCPE_ARG; return vp; }
1147
#define SEL_LIM(p,m,u) ((fl & SP_PLUS)? (p): ((fl & SP_MINUS)? (m): (u)))
1149
int32 parse_spec (char *cptr, uint32 addr, t_value *val, int32 vp, int32 disp, t_stat *r)
1151
int32 i, k, litsize, rn, index;
1152
int32 num, dispsize, mode;
1153
int32 lit[4] = { 0 };
1156
const char *force[] = { "S^", "I^", "B^", "W^", "L^", NULL };
1158
*r = SCPE_OK; /* assume ok */
1159
M1C ('@', SP_IND); /* look for @ */
1160
if (tptr = parse_rnum (cptr, &rn)) { /* look for Rn */
1161
if (*cptr == '[') { /* look for [Rx] */
1162
cptr = parse_rnum (++cptr, &index);
1163
if ((cptr == NULL) || (*cptr++ != ']')) PARSE_LOSE;
1164
val[vp++] = index | IDX; }
1165
else val[vp++] = rn | GRN | (fl? 1: 0); /* Rn or @Rn */
1166
if (*tptr != 0) *r = SCPE_ARG; /* must be done */
1168
for (i = 0; force[i]; i++) { /* look for x^ */
1169
if (strncmp (cptr, force[i], 2) == 0) {
1171
fl = fl | ((i + 1) << SP_V_FORCE);
1173
M1C ('#', SP_LIT); /* look for # */
1174
M1C ('+', SP_PLUS); /* look for + */
1175
M1C ('-', SP_MINUS); /* look for - */
1176
for (litsize = 0;; cptr++) { /* look for mprec int */
1178
if ((c < '0') || (c > 'F') || ((c > '9') && (c < 'A'))) break;
1179
num = (c <= '9')? c - '0': c - 'A' + 10;
1181
for (i = 3; i >= 0; i--) {
1182
lit[i] = lit[i] << 4;
1183
if (i > 0) lit[i] = lit[i] | ((lit[i - 1] >> 28) & 0xF);
1184
else lit[i] = lit[i] | num;
1185
if (lit[i] && (i > litsize)) litsize = i; } }
1186
if (*cptr == '(') { /* look for (Rn) */
1187
cptr = parse_rnum (++cptr, &rn);
1188
if ((cptr == NULL) || (*cptr++ != ')')) PARSE_LOSE;
1190
M1C ('+', SP_POSTP); /* look for + */
1191
if (*cptr == '[') { /* look for [Rx] */
1192
cptr = parse_rnum (++cptr, &index);
1193
if ((cptr == NULL) || (*cptr++ != ']')) PARSE_LOSE;
1194
val[vp++] = index | IDX; }
1195
switch (fl) { /* case on state */
1196
case SP_FS|SP_LIT|SP_NUM: /* S^#n */
1197
case SP_FS|SP_LIT|SP_PLUS|SP_NUM: /* S^#+n */
1198
if ((litsize > 0) || (lit[0] & ~0x3F)) PARSE_LOSE;
1201
case SP_IDX: /* (Rn) */
1202
val[vp++] = rn | RGD;
1204
case SP_MINUS|SP_IDX: /* -(Rn) */
1205
val[vp++] = rn | ADC;
1207
case SP_IDX|SP_POSTP: /* (Rn)+ */
1208
val[vp++] = rn | AIN;
1210
case SP_LIT|SP_NUM: /* #n */
1211
case SP_LIT|SP_PLUS|SP_NUM: /* #+n */
1212
if ((litsize == 0) && ((lit[0] & ~0x3F) == 0)) {
1215
case SP_LIT|SP_MINUS|SP_NUM: /* #-n */
1216
case SP_FI|SP_LIT|SP_NUM: /* I^#n */
1217
case SP_FI|SP_LIT|SP_PLUS|SP_NUM: /* I^#+n */
1218
case SP_FI|SP_LIT|SP_MINUS|SP_NUM: /* I^#-n */
1219
val[vp++] = nPC | AIN;
1220
disp = (disp == OC)? DR_LNMASK + 1: disp & DR_LNMASK;
1221
switch (disp) { /* case spec lnt */
1222
case 00: /* check fit */
1223
if ((litsize > 0) || (lit[0] < 0) ||
1224
(lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE;
1225
SPUTNUM (lit[0], 1); /* store */
1227
case 01: /* check fit */
1228
if ((litsize > 0) || (lit[0] < 0) ||
1229
(lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE;
1230
SPUTNUM (lit[0], 2);
1232
case 02: /* check 1 lw */
1233
if (litsize > 0) PARSE_LOSE;
1234
SPUTNUM (lit[0], 4);
1236
case 03: /* check 2 lw */
1237
if (litsize > 1) PARSE_LOSE;
1238
vp = parse_sym_qoimm (lit, val, vp, 2, fl & SP_MINUS);
1241
vp = parse_sym_qoimm (lit, val, vp, 4, fl & SP_MINUS);
1242
break; } /* end case disp */
1244
case SP_IND|SP_IDX|SP_POSTP: /* @(Rn)+ */
1245
val[vp++] = rn | AID;
1247
case SP_IND|SP_LIT|SP_NUM: /* @#n */
1248
if (litsize > 0) PARSE_LOSE;
1249
val[vp++] = nPC | AID;
1252
case SP_NUM|SP_IDX: /* d(rn) */
1253
case SP_PLUS|SP_NUM|SP_IDX: /* +d(rn) */
1254
case SP_MINUS|SP_NUM|SP_IDX: /* -d(rn) */
1255
case SP_IND|SP_NUM|SP_IDX: /* @d(rn) */
1256
case SP_IND|SP_PLUS|SP_NUM|SP_IDX: /* @+d(rn) */
1257
case SP_IND|SP_MINUS|SP_NUM|SP_IDX: /* @-d(rn) */
1258
if (litsize > 0) PARSE_LOSE;
1259
dispsize = 4; /* find fit for */
1260
mode = LDP; /* displacement */
1262
if (lit[0] <= SEL_LIM (0x7F, 0x80, 0xFF)) {
1265
else if (lit[0] <= SEL_LIM (0x7FFF, 0x8000, 0xFFFF)) {
1268
val[vp++] = mode | rn | ((fl & SP_IND)? 1: 0);
1269
SPUTNUM (lit[0], dispsize);
1271
case SP_FB|SP_NUM|SP_IDX: /* B^d(rn) */
1272
case SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* B^+d(rn) */
1273
case SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* B^-d(rn) */
1274
case SP_IND|SP_FB|SP_NUM|SP_IDX: /* @B^d(rn) */
1275
case SP_IND|SP_FB|SP_PLUS|SP_NUM|SP_IDX: /* @B^+d(rn) */
1276
case SP_IND|SP_FB|SP_MINUS|SP_NUM|SP_IDX: /* @B^-d(rn) */
1277
if ((litsize > 0) || (lit[0] < 0) ||
1278
(lit[0] > SEL_LIM (0x7F, 0x80, 0xFF))) PARSE_LOSE;
1279
val[vp++] = rn | BDP | ((fl & SP_IND)? 1: 0);
1280
SPUTNUM (lit[0], 1);
1282
case SP_FW|SP_NUM|SP_IDX: /* W^d(rn) */
1283
case SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* W^+d(rn) */
1284
case SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* W^-d(rn) */
1285
case SP_IND|SP_FW|SP_NUM|SP_IDX: /* @W^d(rn) */
1286
case SP_IND|SP_FW|SP_PLUS|SP_NUM|SP_IDX: /* @W^+d(rn) */
1287
case SP_IND|SP_FW|SP_MINUS|SP_NUM|SP_IDX: /* @W^-d(rn) */
1288
if ((litsize > 0) || (lit[0] < 0) ||
1289
(lit[0] > SEL_LIM (0x7FFF, 0x8000, 0xFFFF))) PARSE_LOSE;
1290
val[vp++] = rn | WDP | ((fl & SP_IND)? 1: 0);
1291
SPUTNUM (lit[0], 2);
1293
case SP_FL|SP_NUM|SP_IDX: /* L^d(rn) */
1294
case SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* L^+d(rn) */
1295
case SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* L^-d(rn) */
1296
case SP_IND|SP_FL|SP_NUM|SP_IDX: /* @L^d(rn) */
1297
case SP_IND|SP_FL|SP_PLUS|SP_NUM|SP_IDX: /* @L^+d(rn) */
1298
case SP_IND|SP_FL|SP_MINUS|SP_NUM|SP_IDX: /* @L^-d(rn) */
1299
if ((litsize > 0) || (lit[0] < 0)) PARSE_LOSE;
1300
val[vp++] = rn | LDP | ((fl & SP_IND)? 1: 0);
1301
SPUTNUM (lit[0], 2);
1303
case SP_NUM: /* n */
1304
case SP_IND|SP_NUM: /* @n */
1305
if (litsize > 0) PARSE_LOSE;
1306
num = lit[0] - (addr + vp + 2); /* fit in byte? */
1307
if ((num >= -128) && (num <= 127)) {
1311
num = lit[0] - (addr + vp + 3); /* fit in word? */
1312
if ((num >= -32768) && (num <= 32767)) {
1316
num = lit[0] - (addr + vp + 5); /* no, use lw */
1319
val[vp++] = mode | nPC | ((fl & SP_IND)? 1: 0);
1320
PUTNUM (num, dispsize);
1322
case SP_FB|SP_NUM: /* B^n */
1323
case SP_IND|SP_FB|SP_NUM: /* @B^n */
1324
num = lit[0] - (addr + vp + 2);
1325
if ((litsize > 0) || (num > 127) || (num < -128)) PARSE_LOSE;
1326
val[vp++] = nPC | BDP | ((fl & SP_IND)? 1: 0);
1329
case SP_FW|SP_NUM: /* W^n */
1330
case SP_IND|SP_FW|SP_NUM: /* @W^n */
1331
num = lit[0] - (addr + vp + 3);
1332
if ((litsize > 0) || (num > 32767) || (num < -32768)) PARSE_LOSE;
1333
val[vp++] = nPC | WDP | ((fl & SP_IND)? 1: 0);
1336
case SP_FL|SP_NUM: /* L^n */
1337
case SP_IND|SP_FL|SP_NUM: /* @L^n */
1338
num = lit[0] - (addr + vp + 5);
1339
if (litsize > 0) PARSE_LOSE;
1340
val[vp++] = nPC | LDP | ((fl & SP_IND)? 1: 0);
1344
PARSE_LOSE; } /* end case */
1345
if (*cptr != 0) *r = SCPE_ARG; /* must be done */
1349
char *parse_rnum (char *cptr, int32 *rn)
1355
for (i = 15; i >= 0; i--) { /* chk named reg */
1356
lnt = strlen (regname[i]);
1357
if (strncmp (cptr, regname[i], lnt) == 0) {
1359
return cptr + lnt; } }
1360
if (*cptr++ != 'R') return NULL; /* look for R */
1361
regnum = strtotv (cptr, &tptr, 10); /* look for reg # */
1362
if ((cptr == tptr) || (regnum > 15)) return NULL;
1363
*rn = (int32) regnum;
1367
int32 parse_sym_qoimm (int32 *lit, t_value *val, int32 vp, int lnt, int32 minus)
1371
for (i = prev = 0; i < lnt; i++) {
1372
if (minus) prev = lit[i] = ~lit[i] + (prev == 0);
1373
PUTNUM (lit[i], 4); }