First Commit of my working state
[simh.git] / NOVA / nova_sys.c
1 /* nova_sys.c: NOVA simulator interface
2
3 Copyright (c) 1993-2008, Robert M. Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 04-Jul-07 BKR DEC's IOF/ION changed to DG's INTDS/INTEN mnemonic,
27 Fixed QTY/ADCV device name,
28 RDSW changed to DDG's READS mnemonic,
29 fixed/enhanced 'load' command for DG-compatible binary tape format
30 26-Mar-04 RMS Fixed warning with -std=c99
31 14-Jan-04 BKR Added support for QTY and ALM
32 04-Jan-04 RMS Fixed 64b issues found by VMS 8.1
33 24-Nov-03 CEO Added symbolic support for LEF instruction
34 17-Sep-01 RMS Removed multiconsole support
35 31-May-01 RMS Added multiconsole support
36 14-Mar-01 RMS Revised load/dump interface (again)
37 22-Dec-00 RMS Added second terminal support
38 10-Dec-00 RMS Added Eclipse support
39 08-Dec-00 BKR Added plotter support
40 30-Oct-00 RMS Added support for examine to file
41 15-Oct-00 RMS Added stack, byte, trap instructions
42 14-Apr-99 RMS Changed t_addr to unsigned
43 27-Oct-98 RMS V2.4 load interface
44 24-Sep-97 RMS Fixed bug in device name table (found by Charles Owen)
45 */
46
47 #include "nova_defs.h"
48 #include <ctype.h>
49
50 extern DEVICE cpu_dev;
51 extern UNIT cpu_unit;
52 extern DEVICE ptr_dev;
53 extern DEVICE ptp_dev;
54 extern DEVICE plt_dev;
55 extern DEVICE tti_dev;
56 extern DEVICE tto_dev;
57 extern DEVICE tti1_dev;
58 extern DEVICE tto1_dev;
59 extern DEVICE clk_dev;
60 extern DEVICE lpt_dev;
61 extern DEVICE dkp_dev;
62 extern DEVICE dsk_dev;
63 extern DEVICE mta_dev;
64 extern DEVICE qty_dev;
65 extern DEVICE alm_dev;
66 extern REG cpu_reg[];
67 extern uint16 M[];
68 extern int32 saved_PC;
69 extern int32 AMASK;
70
71 #if defined (ECLIPSE)
72
73 extern DEVICE map_dev;
74 extern DEVICE fpu_dev;
75 extern DEVICE pit_dev;
76 extern int32 Usermap;
77 extern int32 MapStat;
78
79 #endif
80
81 extern int32 sim_switches;
82
83
84 /* SCP data structures
85
86 sim_name simulator name string
87 sim_PC pointer to saved PC register descriptor
88 sim_emax number of words needed for examine
89 sim_devices array of pointers to simulated devices
90 sim_stop_messages array of pointers to stop messages
91 sim_load binary loader
92 */
93
94 #if defined (ECLIPSE)
95 char sim_name[] = "ECLIPSE";
96 #else
97 char sim_name[] = "NOVA";
98 #endif
99
100 REG *sim_PC = &cpu_reg[0];
101
102 int32 sim_emax = 4;
103
104 DEVICE *sim_devices[] = {
105 &cpu_dev,
106 #if defined (ECLIPSE)
107 &map_dev,
108 &fpu_dev,
109 &pit_dev,
110 #endif
111 &ptr_dev,
112 &ptp_dev,
113 &tti_dev,
114 &tto_dev,
115 &tti1_dev,
116 &tto1_dev,
117 &clk_dev,
118 &plt_dev,
119 &lpt_dev,
120 &dsk_dev,
121 &dkp_dev,
122 &mta_dev,
123 &qty_dev,
124 &alm_dev,
125 NULL
126 };
127
128 const char *sim_stop_messages[] = {
129 "Unknown error",
130 "Unknown I/O instruction",
131 "HALT instruction",
132 "Breakpoint",
133 "Nested indirect address limit exceeded",
134 "Nested indirect interrupt or trap address limit exceeded",
135 "Read breakpoint",
136 "Write breakpoint"
137 };
138
139 /* Binary loader
140
141 Loader format consists of blocks, optionally preceded, separated, and
142 followed by zeroes. Each block consists of:
143
144 lo_count
145 hi_count
146 lo_origin
147 hi_origin
148 lo_checksum
149 hi_checksum
150 lo_data byte ---
151 hi_data byte |
152 : > -count words
153 lo_data byte |
154 hi_data byte ---
155
156 If the word count is [0,-20], then the block is normal data.
157 If the word count is [-21,-n], then the block is repeated data.
158 If the word count is 1, the block is the start address.
159 If the word count is >1, the block is an error block.
160
161 Notes:
162 'start' block terminates loading.
163 'start' block starting address 1B0 = do not auto-start, 0B0 = auto-start.
164 'start' block starting address is saved in 'save_PC' so a "continue"
165 should start the program.
166
167 specify -i switch ignores checksum errors
168
169
170 internal state machine:
171
172 0,1 get byte count (low and high), ignore leader bytes (<000>)
173 2,3 get origin
174 4,5 get checksum
175 6,7 process data block
176 8 process 'ignore' (error) block
177 */
178
179 t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
180 {
181 int32 data, csum, count, state, i;
182 int32 origin;
183 int pos ;
184 int block_start ;
185 int done ;
186
187 if ((*cptr != 0) || (flag != 0))
188 return ( SCPE_ARG ) ;
189 state = 0;
190 block_start = -1 ;
191 done = 0 ;
192 for ( pos = 0 ; (! done) && ((i=getc(fileref)) != EOF) ; ++pos )
193 {
194 i &= 0x00FF ; /* (insure no sign extension) */
195 switch (state) {
196 case 0: /* leader */
197 count = i;
198 state = (count != 0) ;
199 if ( state )
200 block_start = pos ;
201 break;
202 case 1: /* high count */
203 csum = count = (i << 8) | count ;
204 state = 2;
205 break;
206 case 2: /* low origin */
207 origin = i;
208 state = 3;
209 break ;
210
211 case 3: /* high origin */
212 origin = (i << 8) | origin;
213 csum = csum + origin;
214 state = 4;
215 break;
216 case 4: /* low checksum */
217 csum = csum + i;
218 state = 5;
219 break;
220 case 5: /* high checksum */
221 csum = (csum + (i << 8)) & 0xFFFF ;
222 if (count == 1)
223 {
224 /* 'start' block */
225 /* do any auto-start check or inhibit check */
226 saved_PC = (origin & 077777) ; /* 0B0 = auto-start program */
227 /* 1B0 = do not auto start */
228 state = 0 ; /* indicate okay state */
229 done = 1 ; /* we're done! */
230 if ( ! (origin & 0x8000) )
231 {
232 printf( "auto start @ %05o \n", (origin & 0x7FFF) ) ;
233 }
234 break ;
235 }
236 if ( ((count & 0x8000) == 0) && (count > 1))
237 {
238 /* 'ignore' block */
239 state = 8 ;
240 }
241 /* 'data' or 'repeat' block */
242 count = 0200000 - count ;
243 if ( count <= 020 )
244 {
245 /* 'data' block */
246 state = 6 ;
247 break ;
248 }
249 /* 'repeat' block (multiple data) */
250
251 if (count > 020) { /* large block */
252 for (count = count - 1; count > 1; count--) {
253 if (origin >= AMASK /* MEMSIZE? */)
254 {
255 return ( SCPE_NXM );
256 }
257 M[origin] = data;
258 origin = origin + 1;
259 }
260 state = 0 ;
261 }
262 state = 0;
263 break;
264 case 6: /* low data */
265 data = i;
266 state = 7;
267 break;
268 case 7: /* high data */
269 data = (i << 8) | data;
270 csum = (csum + data) & 0xFFFF ;
271
272 if (origin >= AMASK /* MEMSIZE? */)
273 return SCPE_NXM;
274 M[origin] = data;
275 origin = origin + 1;
276 count = count - 1;
277 if (count == 0) {
278 if ( csum )
279 {
280 printf( "checksum error: block start at %d [0x%x] \n", block_start, block_start ) ;
281 printf( "calculated: 0%o [0x%4x]\n", csum, csum ) ;
282 if ( ! (sim_switches & SWMASK('I')) )
283 return SCPE_CSUM;
284 }
285 state = 0;
286 break;
287 }
288 state = 6;
289 break;
290 case 8: /* error (ignore) block */
291 if (i == 0377)
292 state = 0; /* (wait for 'RUBOUT' char) */
293 break;
294 } /* end switch */
295 } /* end while */
296
297 /* Ok to find end of tape between blocks or in error state */
298
299 return ( ((state == 0) || (state == 8)) ? SCPE_OK : SCPE_FMT ) ;
300 }
301
302
303 /* Symbol tables */
304
305 #define I_V_FL 18 /* flag bits */
306 #define I_M_FL 037 /* flag width */
307 #define I_V_NPN 000 /* no operands */
308 #define I_V_R 001 /* reg */
309 #define I_V_D 002 /* device */
310 #define I_V_RD 003 /* reg,device */
311 #define I_V_M 004 /* mem addr */
312 #define I_V_RM 005 /* reg,mem addr */
313 #define I_V_RR 006 /* operate */
314 #define I_V_BY 007 /* Nova byte pointer */
315 #define I_V_2AC 010 /* reg,reg */
316 #define I_V_RSI 011 /* reg,short imm */
317 #define I_V_LI 012 /* long imm */
318 #define I_V_RLI 013 /* reg,long imm */
319 #define I_V_LM 014 /* long mem addr */
320 #define I_V_RLM 015 /* reg,long mem addr */
321 #define I_V_FRM 016 /* flt reg,long mem addr */
322 #define I_V_FST 017 /* flt long mem, status */
323 #define I_V_XP 020 /* XOP */
324 #define I_NPN (I_V_NPN << I_V_FL)
325 #define I_R (I_V_R << I_V_FL)
326 #define I_D (I_V_D << I_V_FL)
327 #define I_RD (I_V_RD << I_V_FL)
328 #define I_M (I_V_M << I_V_FL)
329 #define I_RM (I_V_RM << I_V_FL)
330 #define I_RR (I_V_RR << I_V_FL)
331 #define I_BY (I_V_BY << I_V_FL)
332 #define I_2AC (I_V_2AC << I_V_FL)
333 #define I_RSI (I_V_RSI << I_V_FL)
334 #define I_LI (I_V_LI << I_V_FL)
335 #define I_RLI (I_V_RLI << I_V_FL)
336 #define I_LM (I_V_LM << I_V_FL)
337 #define I_RLM (I_V_RLM << I_V_FL)
338 #define I_FRM (I_V_FRM << I_V_FL)
339 #define I_FST (I_V_FST << I_V_FL)
340 #define I_XP (I_V_XP << I_V_FL)
341
342 static const int32 masks[] = {
343 0177777, 0163777, 0177700, 0163700,
344 0174000, 0160000, 0103770, 0163477,
345 0103777, 0103777, 0177777, 0163777,
346 0176377, 0162377, 0103777, 0163777,
347 0100077
348 };
349
350 static const char *opcode[] = {
351 "JMP", "JSR", "ISZ", "DSZ",
352 "LDA", "STA",
353 #if defined (ECLIPSE)
354 "ADI", "SBI", "DAD", "DSB",
355 "IOR", "XOR", "ANC", "XCH",
356 "SGT", "SGE", "LSH", "DLSH",
357 "HXL", "HXR", "DHXL", "DHXR",
358 "BTO", "BTZ", "SBZ", "SZBO",
359 "LOB", "LRB", "COB", "LDB",
360 "STB", "PSH", "POP",
361 "LMP", "SYC",
362 "PSHR", "POPB", "BAM", "POPJ",
363 "RTN", "BLM", "DIVX",
364 "MUL", "MULS", "DIV", "DIVS",
365 "SAVE", "RSTR",
366 "XOP",
367 "FAS", "FAD", "FSS", "FSD",
368 "FMS", "FMD", "FDS", "FDD",
369 "FAMS", "FAMD", "FSMS", "FSMD",
370 "FMMS", "FMMD", "FDMS", "FDMD",
371 "FLDS", "FLDD", "FSTS", "FSTD",
372 "FLAS", "FLMD", "FFAS", "FFMD",
373 "FNOM", "FRH", "FAB", "FNEG",
374 "FSCAL", "FEXP", "FINT", "FHLV",
375 "FNS", "FSA", "FSEQ", "FSNE",
376 "FSLT", "FSGE", "FSLE", "FSGT",
377 "FSNM", "FSND", "FSNU", "FSNUD",
378 "FSNO", "FSNOD", "FSNUO", "FSNER",
379 "FSST", "FLST",
380 "FTE", "FTD", "FCLE",
381 "FPSH", "FPOP",
382 "FCMP", "FMOV",
383 "CMV", "CMP", "CTR", "CMT",
384 "EJMP", "EJSR", "EISZ", "EDSZ",
385 "ELDA", "ESTA", "ELEF",
386 "ELDB", "ESTB", "DSPA",
387 "PSHJ", "CLM", "SNB",
388 "MSP", "XCT", "HLV",
389 "IORI", "XORI", "ANDI", "ADDI",
390 #endif
391 "COM", "COMZ", "COMO", "COMC",
392 "COML", "COMZL", "COMOL", "COMCL",
393 "COMR", "COMZR", "COMOR", "COMCR",
394 "COMS", "COMZS", "COMOS", "COMCS",
395 "COM#", "COMZ#", "COMO#", "COMC#",
396 "COML#", "COMZL#", "COMOL#", "COMCL#",
397 "COMR#", "COMZR#", "COMOR#", "COMCR#",
398 "COMS#", "COMZS#", "COMOS#", "COMCS#",
399 "NEG", "NEGZ", "NEGO", "NEGC",
400 "NEGL", "NEGZL", "NEGOL", "NEGCL",
401 "NEGR", "NEGZR", "NEGOR", "NEGCR",
402 "NEGS", "NEGZS", "NEGOS", "NEGCS",
403 "NEG#", "NEGZ#", "NEGO#", "NEGC#",
404 "NEGL#", "NEGZL#", "NEGOL#", "NEGCL#",
405 "NEGR#", "NEGZR#", "NEGOR#", "NEGCR#",
406 "NEGS#", "NEGZS#", "NEGOS#", "NEGCS#",
407 "MOV", "MOVZ", "MOVO", "MOVC",
408 "MOVL", "MOVZL", "MOVOL", "MOVCL",
409 "MOVR", "MOVZR", "MOVOR", "MOVCR",
410 "MOVS", "MOVZS", "MOVOS", "MOVCS",
411 "MOV#", "MOVZ#", "MOVO#", "MOVC#",
412 "MOVL#", "MOVZL#", "MOVOL#", "MOVCL#",
413 "MOVR#", "MOVZR#", "MOVOR#", "MOVCR#",
414 "MOVS#", "MOVZS#", "MOVOS#", "MOVCS#",
415 "INC", "INCZ", "INCO", "INCC",
416 "INCL", "INCZL", "INCOL", "INCCL",
417 "INCR", "INCZR", "INCOR", "INCCR",
418 "INCS", "INCZS", "INCOS", "INCCS",
419 "INC#", "INCZ#", "INCO#", "INCC#",
420 "INCL#", "INCZL#", "INCOL#", "INCCL#",
421 "INCR#", "INCZR#", "INCOR#", "INCCR#",
422 "INCS#", "INCZS#", "INCOS#", "INCCS#",
423 "ADC", "ADCZ", "ADCO", "ADCC",
424 "ADCL", "ADCZL", "ADCOL", "ADCCL",
425 "ADCR", "ADCZR", "ADCOR", "ADCCR",
426 "ADCS", "ADCZS", "ADCOS", "ADCCS",
427 "ADC#", "ADCZ#", "ADCO#", "ADCC#",
428 "ADCL#", "ADCZL#", "ADCOL#", "ADCCL#",
429 "ADCR#", "ADCZR#", "ADCOR#", "ADCCR#",
430 "ADCS#", "ADCZS#", "ADCOS#", "ADCCS#",
431 "SUB", "SUBZ", "SUBO", "SUBC",
432 "SUBL", "SUBZL", "SUBOL", "SUBCL",
433 "SUBR", "SUBZR", "SUBOR", "SUBCR",
434 "SUBS", "SUBZS", "SUBOS", "SUBCS",
435 "SUB#", "SUBZ#", "SUBO#", "SUBC#",
436 "SUBL#", "SUBZL#", "SUBOL#", "SUBCL#",
437 "SUBR#", "SUBZR#", "SUBOR#", "SUBCR#",
438 "SUBS#", "SUBZS#", "SUBOS#", "SUBCS#",
439 "ADD", "ADDZ", "ADDO", "ADDC",
440 "ADDL", "ADDZL", "ADDOL", "ADDCL",
441 "ADDR", "ADDZR", "ADDOR", "ADDCR",
442 "ADDS", "ADDZS", "ADDOS", "ADDCS",
443 "ADD#", "ADDZ#", "ADDO#", "ADDC#",
444 "ADDL#", "ADDZL#", "ADDOL#", "ADDCL#",
445 "ADDR#", "ADDZR#", "ADDOR#", "ADDCR#",
446 "ADDS#", "ADDZS#", "ADDOS#", "ADDCS#",
447 "AND", "ANDZ", "ANDO", "ANDC",
448 "ANDL", "ANDZL", "ANDOL", "ANDCL",
449 "ANDR", "ANDZR", "ANDOR", "ANDCR",
450 "ANDS", "ANDZS", "ANDOS", "ANDCS",
451 "AND#", "ANDZ#", "ANDO#", "ANDC#",
452 "ANDL#", "ANDZL#", "ANDOL#", "ANDCL#",
453 "ANDR#", "ANDZR#", "ANDOR#", "ANDCR#",
454 "ANDS#", "ANDZS#", "ANDOS#", "ANDCS#",
455 "INTEN", "INTDS",
456 "READS", "INTA", "MSKO", "IORST", "HALT",
457 #if !defined (ECLIPSE)
458 "MUL", "DIV", "MULS", "DIVS",
459 "PSHA", "POPA", "SAV", "RET",
460 "MTSP", "MTFP", "MFSP", "MFFP",
461 "LDB", "STB",
462 #endif
463 "NIO", "NIOS", "NIOC", "NIOP",
464 "DIA", "DIAS", "DIAC", "DIAP",
465 "DOA", "DOAS", "DOAC", "DOAP",
466 "DIB", "DIBS", "DIBC", "DIBP",
467 "DOB", "DOBS", "DOBC", "DOBP",
468 "DIC", "DICS", "DICC", "DICP",
469 "DOC", "DOCS", "DOCC", "DOCP",
470 "SKPBN", "SKPBZ", "SKPDN", "SKPDZ",
471 #if defined (ECLIPSE)
472 "LEF", "LEF", "LEF", "LEF",
473 #endif
474 NULL
475 };
476
477 static const int32 opc_val[] = {
478 0000000+I_M, 0004000+I_M, 0010000+I_M, 0014000+I_M,
479 0020000+I_RM, 0040000+I_RM,
480 #if defined (ECLIPSE)
481 0100010+I_RSI, 0100110+I_RSI, 0100210+I_2AC, 0100310+I_2AC,
482 0100410+I_2AC, 0100510+I_2AC, 0100610+I_2AC, 0100710+I_2AC,
483 0101010+I_2AC, 0101110+I_2AC, 0101210+I_RSI, 0101310+I_RSI,
484 0101410+I_RSI, 0101510+I_RSI, 0101610+I_RSI, 0101710+I_RSI,
485 0102010+I_2AC, 0102110+I_2AC, 0102210+I_2AC, 0102310+I_2AC,
486 0102410+I_2AC, 0102510+I_2AC, 0102610+I_2AC, 0102710+I_2AC,
487 0103010+I_2AC, 0103110+I_2AC, 0103210+I_2AC,
488 0113410+I_NPN, 0103510+I_2AC,
489 0103710+I_NPN, 0107710+I_NPN, 0113710+I_NPN, 0117710+I_NPN,
490 0127710+I_NPN, 0133710+I_NPN, 0137710+I_NPN,
491 0143710+I_NPN, 0147710+I_NPN, 0153710+I_NPN, 0157710+I_NPN,
492 0163710+I_LI, 0167710+I_NPN,
493 0100030+I_XP,
494 0100050+I_2AC, 0100150+I_2AC, 0100250+I_2AC, 0100350+I_2AC,
495 0100450+I_2AC, 0100550+I_2AC, 0100650+I_2AC, 0100750+I_2AC,
496 0101050+I_FRM, 0101150+I_FRM, 0101250+I_FRM, 0101350+I_FRM,
497 0101450+I_FRM, 0101550+I_FRM, 0101650+I_FRM, 0101750+I_FRM,
498 0102050+I_FRM, 0102150+I_FRM, 0102250+I_FRM, 0102350+I_FRM,
499 0102450+I_2AC, 0102550+I_FRM, 0102650+I_2AC, 0102750+I_FRM,
500 0103050+I_R, 0123050+I_R, 0143050+I_R, 0163050+I_R,
501 0103150+I_R, 0123150+I_R, 0143150+I_R, 0163150+I_R,
502 0103250+I_NPN, 0107250+I_NPN, 0113250+I_NPN, 0117250+I_NPN,
503 0123250+I_NPN, 0127250+I_NPN, 0133250+I_NPN, 0137250+I_NPN,
504 0143250+I_NPN, 0147250+I_NPN, 0153250+I_NPN, 0157250+I_NPN,
505 0163250+I_NPN, 0167250+I_NPN, 0173250+I_NPN, 0177250+I_NPN,
506 0103350+I_FST, 0123350+I_FST,
507 0143350+I_NPN, 0147350+I_NPN, 0153350+I_NPN,
508 0163350+I_NPN, 0167350+I_NPN,
509 0103450+I_2AC, 0103550+I_2AC,
510 0153650+I_NPN, 0157650+I_NPN, 0163650+I_NPN, 0167650+I_NPN,
511 0102070+I_LM, 0106070+I_LM, 0112070+I_LM, 0116070+I_LM,
512 0122070+I_RLM, 0142070+I_RLM, 0162070+I_RLM,
513 0102170+I_RLM, 0122170+I_RLM, 0142170+I_RLM,
514 0102270+I_LM, 0102370+I_2AC, 0102770+I_2AC,
515 0103370+I_R, 0123370+I_R, 0143370+I_R,
516 0103770+I_RLI, 0123770+I_RLI, 0143770+I_RLI, 0163770+I_RLI,
517 #endif
518 0100000+I_RR, 0100020+I_RR, 0100040+I_RR, 0100060+I_RR,
519 0100100+I_RR, 0100120+I_RR, 0100140+I_RR, 0100160+I_RR,
520 0100200+I_RR, 0100220+I_RR, 0100240+I_RR, 0100260+I_RR,
521 0100300+I_RR, 0100320+I_RR, 0100340+I_RR, 0100360+I_RR,
522 0100010+I_RR, 0100030+I_RR, 0100050+I_RR, 0100070+I_RR,
523 0100110+I_RR, 0100130+I_RR, 0100150+I_RR, 0100170+I_RR,
524 0100210+I_RR, 0100230+I_RR, 0100250+I_RR, 0100270+I_RR,
525 0100310+I_RR, 0100330+I_RR, 0100350+I_RR, 0100370+I_RR,
526 0100400+I_RR, 0100420+I_RR, 0100440+I_RR, 0100460+I_RR,
527 0100500+I_RR, 0100520+I_RR, 0100540+I_RR, 0100560+I_RR,
528 0100600+I_RR, 0100620+I_RR, 0100640+I_RR, 0100660+I_RR,
529 0100700+I_RR, 0100720+I_RR, 0100740+I_RR, 0100760+I_RR,
530 0100410+I_RR, 0100430+I_RR, 0100450+I_RR, 0100470+I_RR,
531 0100510+I_RR, 0100530+I_RR, 0100550+I_RR, 0100570+I_RR,
532 0100610+I_RR, 0100630+I_RR, 0100650+I_RR, 0100670+I_RR,
533 0100710+I_RR, 0100730+I_RR, 0100750+I_RR, 0100770+I_RR,
534 0101000+I_RR, 0101020+I_RR, 0101040+I_RR, 0101060+I_RR,
535 0101100+I_RR, 0101120+I_RR, 0101140+I_RR, 0101160+I_RR,
536 0101200+I_RR, 0101220+I_RR, 0101240+I_RR, 0101260+I_RR,
537 0101300+I_RR, 0101320+I_RR, 0101340+I_RR, 0101360+I_RR,
538 0101010+I_RR, 0101030+I_RR, 0101050+I_RR, 0101070+I_RR,
539 0101110+I_RR, 0101130+I_RR, 0101150+I_RR, 0101170+I_RR,
540 0101210+I_RR, 0101230+I_RR, 0101250+I_RR, 0101270+I_RR,
541 0101310+I_RR, 0101330+I_RR, 0101350+I_RR, 0101370+I_RR,
542 0101400+I_RR, 0101420+I_RR, 0101440+I_RR, 0101460+I_RR,
543 0101500+I_RR, 0101520+I_RR, 0101540+I_RR, 0101560+I_RR,
544 0101600+I_RR, 0101620+I_RR, 0101640+I_RR, 0101660+I_RR,
545 0101700+I_RR, 0101720+I_RR, 0101740+I_RR, 0101760+I_RR,
546 0101410+I_RR, 0101430+I_RR, 0101450+I_RR, 0101470+I_RR,
547 0101510+I_RR, 0101530+I_RR, 0101550+I_RR, 0101570+I_RR,
548 0101610+I_RR, 0101630+I_RR, 0101650+I_RR, 0101670+I_RR,
549 0101710+I_RR, 0101730+I_RR, 0101750+I_RR, 0101770+I_RR,
550 0102000+I_RR, 0102020+I_RR, 0102040+I_RR, 0102060+I_RR,
551 0102100+I_RR, 0102120+I_RR, 0102140+I_RR, 0102160+I_RR,
552 0102200+I_RR, 0102220+I_RR, 0102240+I_RR, 0102260+I_RR,
553 0102300+I_RR, 0102320+I_RR, 0102340+I_RR, 0102360+I_RR,
554 0102010+I_RR, 0102030+I_RR, 0102050+I_RR, 0102070+I_RR,
555 0102110+I_RR, 0102130+I_RR, 0102150+I_RR, 0102170+I_RR,
556 0102210+I_RR, 0102230+I_RR, 0102250+I_RR, 0102270+I_RR,
557 0102310+I_RR, 0102330+I_RR, 0102350+I_RR, 0102370+I_RR,
558 0102400+I_RR, 0102420+I_RR, 0102440+I_RR, 0102460+I_RR,
559 0102500+I_RR, 0102520+I_RR, 0102540+I_RR, 0102560+I_RR,
560 0102600+I_RR, 0102620+I_RR, 0102640+I_RR, 0102660+I_RR,
561 0102700+I_RR, 0102720+I_RR, 0102740+I_RR, 0102760+I_RR,
562 0102410+I_RR, 0102430+I_RR, 0102450+I_RR, 0102470+I_RR,
563 0102510+I_RR, 0102530+I_RR, 0102550+I_RR, 0102570+I_RR,
564 0102610+I_RR, 0102630+I_RR, 0102650+I_RR, 0102670+I_RR,
565 0102710+I_RR, 0102730+I_RR, 0102750+I_RR, 0102770+I_RR,
566 0103000+I_RR, 0103020+I_RR, 0103040+I_RR, 0103060+I_RR,
567 0103100+I_RR, 0103120+I_RR, 0103140+I_RR, 0103160+I_RR,
568 0103200+I_RR, 0103220+I_RR, 0103240+I_RR, 0103260+I_RR,
569 0103300+I_RR, 0103320+I_RR, 0103340+I_RR, 0103360+I_RR,
570 0103010+I_RR, 0103030+I_RR, 0103050+I_RR, 0103070+I_RR,
571 0103110+I_RR, 0103130+I_RR, 0103150+I_RR, 0103170+I_RR,
572 0103210+I_RR, 0103230+I_RR, 0103250+I_RR, 0103270+I_RR,
573 0103310+I_RR, 0103330+I_RR, 0103350+I_RR, 0103370+I_RR,
574 0103400+I_RR, 0103420+I_RR, 0103440+I_RR, 0103460+I_RR,
575 0103500+I_RR, 0103520+I_RR, 0103540+I_RR, 0103560+I_RR,
576 0103600+I_RR, 0103620+I_RR, 0103640+I_RR, 0103660+I_RR,
577 0103700+I_RR, 0103720+I_RR, 0103740+I_RR, 0103760+I_RR,
578 0103410+I_RR, 0103430+I_RR, 0103450+I_RR, 0103470+I_RR,
579 0103510+I_RR, 0103530+I_RR, 0103550+I_RR, 0103570+I_RR,
580 0103610+I_RR, 0103630+I_RR, 0103650+I_RR, 0103670+I_RR,
581 0103710+I_RR, 0103730+I_RR, 0103750+I_RR, 0103770+I_RR,
582 0060177+I_NPN, 0060277+I_NPN,
583 0060477+I_R, 0061477+I_R, 0062077+I_R, 0062677+I_NPN, 0063077+I_NPN,
584 #if !defined (ECLIPSE)
585 0073301+I_NPN, 0073101+I_NPN, 0077201+I_NPN, 0077001+I_NPN,
586 0061401+I_R, 0061601+I_R, 0062401+I_NPN, 0062601+I_NPN,
587 0061001+I_R, 0060001+I_R, 0061201+I_R, 0060201+I_R,
588 0060401+I_BY, 0062001+I_BY,
589 #endif
590 0060000+I_RD, 0060100+I_RD, 0060200+I_RD, 0060300+I_RD,
591 0060400+I_RD, 0060500+I_RD, 0060600+I_RD, 0060700+I_RD,
592 0061000+I_RD, 0061100+I_RD, 0061200+I_RD, 0061300+I_RD,
593 0061400+I_RD, 0061500+I_RD, 0061600+I_RD, 0061700+I_RD,
594 0062000+I_RD, 0062100+I_RD, 0062200+I_RD, 0062300+I_RD,
595 0062400+I_RD, 0062500+I_RD, 0062600+I_RD, 0062700+I_RD,
596 0063000+I_RD, 0063100+I_RD, 0063200+I_RD, 0063300+I_RD,
597 0063400+I_D, 0063500+I_D, 0063600+I_D, 0063700+I_D,
598 #if defined (ECLIPSE)
599 0064000+I_D, 0070000+I_D, 0074000+I_D, 0076000+I_D,
600 #endif
601 -1
602 };
603
604 static const char *skip[] = {
605 "SKP", "SZC", "SNC", "SZR", "SNR", "SEZ", "SBN",
606 NULL
607 };
608
609 static const char *device[] = {
610 #if defined (ECLIPSE)
611 "ERCC", "MAP",
612 #endif
613 "TTI", "TTO", "PTR", "PTP", "RTC", "PLT", "CDR", "LPT",
614 "DSK", "MTA", "DCM", "QTY" /* "ADCV" */, "DKP", "CAS",
615 "TTI1", "TTO1", "CPU",
616 NULL
617 };
618
619 static const int32 dev_val[] = {
620 #if defined (ECLIPSE)
621 002, 003,
622 #endif
623 010, 011, 012, 013, 014, 015, 016, 017,
624 020, 022, 024, 030, 033, 034,
625 050, 051, 077,
626 -1
627 };
628
629 /* Address decode
630
631 Inputs:
632 *of = output stream
633 addr = current PC
634 ind = indirect flag
635 mode = addressing mode
636 disp = displacement
637 ext = true if extended address
638 cflag = true if decoding for CPU
639 Outputs:
640 return = error code
641 */
642
643 t_stat fprint_addr (FILE *of, t_addr addr, int32 ind, int32 mode,
644 int32 disp, t_bool ext, int32 cflag)
645 {
646 int32 dsign, dmax;
647
648 if (ext) dmax = AMASK + 1; /* get max disp */
649 else dmax = I_M_DISP + 1;
650 dsign = dmax >> 1; /* get disp sign */
651 if (ind) fprintf (of, "@"); /* indirect? */
652 switch (mode & 03) { /* mode */
653
654 case 0: /* absolute */
655 fprintf (of, "%-o", disp);
656 break;
657
658 case 1: /* PC rel */
659 if (disp & dsign) {
660 if (cflag) fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK);
661 else fprintf (of, ".-%-o", dmax - disp);
662 }
663 else {
664 if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK);
665 else fprintf (of, ".+%-o", disp);
666 }
667 break;
668
669 case 2: /* AC2 rel */
670 if (disp & dsign) fprintf (of, "-%-o,2", dmax - disp);
671 else fprintf (of, "%-o,2", disp);
672 break;
673
674 case 3: /* AC3 rel */
675 if (disp & dsign) fprintf (of, "-%-o,3", dmax - disp);
676 else fprintf (of, "%-o,3", disp);
677 break;
678 } /* end switch */
679
680 return SCPE_OK;
681 }
682
683 /* Symbolic output
684
685 Inputs:
686 *of = output stream
687 addr = current PC
688 *val = pointer to values
689 *uptr = pointer to unit
690 sw = switches
691 Outputs:
692 status = error code
693 */
694
695 t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
696 UNIT *uptr, int32 sw)
697 {
698 int32 cflag, i, j, c1, c2, inst, inst1, dv, src, dst, skp;
699 int32 ind, mode, disp, dev;
700 int32 byac, extind, extdisp, xop;
701
702 cflag = (uptr == NULL) || (uptr == &cpu_unit);
703 c1 = ((int32) val[0] >> 8) & 0177;
704 c2 = (int32) val[0] & 0177;
705 if (sw & SWMASK ('A')) { /* ASCII? */
706 fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
707 return SCPE_OK;
708 }
709 if (sw & SWMASK ('C')) { /* character? */
710 fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
711 fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
712 return SCPE_OK;
713 }
714 if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */
715
716 /* Instruction decode */
717
718 inst = (int32) val[0];
719 inst1 = (int32) val[1];
720 for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
721 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
722 if ((opc_val[i] & 0177777) == (inst & masks[j])) { /* match? */
723 src = I_GETSRC (inst); /* opr fields */
724 dst = I_GETDST (inst);
725 skp = I_GETSKP (inst);
726 ind = inst & I_IND; /* mem ref fields */
727 mode = I_GETMODE (inst);
728 disp = I_GETDISP (inst);
729 dev = I_GETDEV (inst); /* IOT fields */
730 byac = I_GETPULSE (inst); /* byte fields */
731 xop = I_GETXOP (inst); /* XOP fields */
732 extind = inst1 & A_IND; /* extended fields */
733 extdisp = inst1 & AMASK;
734 for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ;
735
736 switch (j) { /* switch on class */
737
738 case I_V_NPN: /* no operands */
739 fprintf (of, "%s", opcode[i]); /* opcode */
740 break;
741
742 case I_V_R: /* reg only */
743 fprintf (of, "%s %-o", opcode[i], dst);
744 break;
745
746 case I_V_D: /* dev only */
747 #if defined (ECLIPSE)
748 if (Usermap && (MapStat & 0100)) { /* the evil LEF mode */
749 fprintf (of, "LEF %-o,", dst);
750 fprint_addr (of, addr, ind, mode, disp, FALSE, cflag);
751 break;
752 }
753 #endif
754 if (dev_val[dv] >= 0)
755 fprintf (of, "%s %s", opcode[i], device[dv]);
756 else fprintf (of, "%s %-o", opcode[i], dev);
757 break;
758
759 case I_V_RD: /* reg, dev */
760 if (dev_val[dv] >= 0)
761 fprintf (of, "%s %-o,%s", opcode[i], dst, device[dv]);
762 else fprintf (of, "%s %-o,%-o", opcode[i], dst, dev);
763 break;
764
765 case I_V_M: /* addr only */
766 fprintf (of, "%s ", opcode[i]);
767 fprint_addr (of, addr, ind, mode, disp, FALSE, cflag);
768 break;
769
770 case I_V_RM: /* reg, addr */
771 fprintf (of, "%s %-o,", opcode[i], dst);
772 fprint_addr (of, addr, ind, mode, disp, FALSE, cflag);
773 break;
774
775 case I_V_RR: /* operate */
776 fprintf (of, "%s %-o,%-o", opcode[i], src, dst);
777 if (skp) fprintf (of, ",%s", skip[skp-1]);
778 break;
779
780 case I_V_BY: /* byte */
781 fprintf (of, "%s %-o,%-o", opcode[i], byac, dst);
782 break;
783
784 case I_V_2AC: /* reg, reg */
785 fprintf (of, "%s %-o,%-o", opcode[i], src, dst);
786 break;
787
788 case I_V_RSI: /* reg, short imm */
789 fprintf (of, "%s %-o,%-o", opcode[i], src + 1, dst);
790 break;
791
792 case I_V_LI: /* long imm */
793 fprintf (of, "%s %-o", opcode[i], inst1);
794 return -1;
795
796 case I_V_RLI: /* reg, long imm */
797 fprintf (of, "%s %-o,%-o", opcode[i], inst1, dst);
798 return -1;
799
800 case I_V_LM: /* long addr */
801 fprintf (of, "%s ", opcode[i]);
802 fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag);
803 return -1;
804
805 case I_V_RLM: /* reg, long addr */
806 fprintf (of, "%s %-o,", opcode[i], dst);
807 fprint_addr (of, addr, extind, mode, extdisp, TRUE, cflag);
808 return -1;
809
810 case I_V_FRM: /* flt reg, long addr */
811 fprintf (of, "%s %-o,", opcode[i], dst);
812 fprint_addr (of, addr, extind, src, extdisp, TRUE, cflag);
813 return -1;
814
815 case I_V_FST: /* flt status */
816 fprintf (of, "%s ", opcode[i]);
817 fprint_addr (of, addr, extind, dst, extdisp, AMASK + 1, cflag);
818 return -1;
819
820 case I_V_XP: /* XOP */
821 fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, xop);
822 break; /* end case */
823
824 default:
825 fprintf (of, "??? [%-o]", inst);
826 break;
827 }
828 return SCPE_OK;
829 } /* end if */
830 } /* end for */
831 return SCPE_ARG;
832 }
833
834 /* Address parse
835
836 Inputs:
837 *cptr = pointer to input string
838 addr = current PC
839 ext = extended address
840 cflag = true if parsing for CPU
841 val[3] = output array
842 Outputs:
843 optr = pointer to next char in input string
844 NULL if error
845 */
846
847 #define A_FL 001 /* CPU flag */
848 #define A_NX 002 /* index seen */
849 #define A_PER 004 /* period seen */
850 #define A_NUM 010 /* number seen */
851 #define A_SI 020 /* sign seen */
852 #define A_MI 040 /* - seen */
853
854 char *get_addr (char *cptr, t_addr addr, t_bool ext, int32 cflag, int32 *val)
855 {
856 int32 d, r, x, pflag;
857 char gbuf[CBUFSIZE];
858 int32 dmax, dsign;
859
860 if (ext) dmax = AMASK + 1; /* get max disp */
861 else dmax = I_M_DISP + 1;
862 dsign = dmax >> 1; /* get disp sign */
863 val[0] = 0; /* no indirect */
864 val[1] = 0; /* PC rel */
865 val[2] = 0; /* no addr */
866
867 pflag = cflag & A_FL; /* isolate flag */
868 if (*cptr == '@') { /* indirect? */
869 val[0] = 1;
870 cptr++;
871 }
872 if (*cptr == '.') { /* relative? */
873 pflag = pflag | A_PER;
874 x = 1; /* "index" is PC */
875 cptr++;
876 }
877 if (*cptr == '+') { /* + sign? */
878 pflag = pflag | A_SI;
879 cptr++;
880 }
881 else if (*cptr == '-') { /* - sign? */
882 pflag = pflag | A_MI | A_SI;
883 cptr++;
884 }
885 if (*cptr != 0) { /* number? */
886 cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
887 d = (int32) get_uint (gbuf, 8, AMASK, &r);
888 if (r != SCPE_OK) return NULL;
889 pflag = pflag | A_NUM;
890 }
891 if (*cptr != 0) { /* index? */
892 cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
893 x = (int32) get_uint (gbuf, 8, I_M_DST, &r);
894 if ((r != SCPE_OK) || (x < 2)) return NULL;
895 pflag = pflag | A_NX;
896 }
897
898 switch (pflag) { /* case on flags */
899
900 case A_NUM: case A_NUM+A_SI: /* ~CPU, (+)num */
901 if (d < dmax) val[2] = d;
902 else return NULL;
903 break;
904
905 case A_NUM+A_FL: case A_NUM+A_SI+A_FL: /* CPU, (+)num */
906 if (d < dmax) val[2] = d;
907 else if (((d >= (((int32) addr - dsign) & AMASK)) &&
908 (d < (((int32) addr + dsign) & AMASK))) ||
909 (d >= ((int32) addr + (-dsign & AMASK)))) {
910 val[1] = 1; /* PC rel */
911 val[2] = (d - addr) & (dmax - 1);
912 }
913 else return NULL;
914 break;
915
916 case A_PER: case A_PER+A_FL: /* . */
917 case A_PER+A_SI+A_NUM: case A_PER+A_SI+A_NUM+A_FL: /* . + num */
918 case A_PER+A_SI+A_MI+A_NUM: /* . - num */
919 case A_PER+A_SI+A_MI+A_NUM+A_FL:
920 case A_NX+A_NUM: case A_NX+A_NUM+A_FL: /* num, ndx */
921 case A_NX+A_SI+A_NUM: case A_NX+A_SI+A_NUM+A_FL: /* +num, ndx */
922 case A_NX+A_SI+A_MI+A_NUM: /* -num, ndx */
923 case A_NX+A_SI+A_MI+A_NUM+A_FL:
924 val[1] = x; /* set mode */
925 if (((pflag & A_MI) == 0) && (d < dsign)) val[2] = d;
926 else if ((pflag & A_MI) && (d <= dsign)) val[2] = (dmax - d);
927 else return NULL;
928 break;
929
930 default:
931 return NULL;
932 } /* end case */
933
934 return cptr;
935 }
936
937 /* Parse two registers
938
939 Inputs:
940 *cptr = input string
941 term = second terminating character
942 val = output array
943 Outputs:
944 optr = pointer to next char in input string
945 NULL if error
946 */
947
948 char *get_2reg (char *cptr, char term, int32 *val)
949 {
950 char gbuf[CBUFSIZE];
951 t_stat r;
952
953 cptr = get_glyph (cptr, gbuf, ','); /* get register */
954 val[0] = (int32) get_uint (gbuf, 8, I_M_SRC, &r);
955 if (r != SCPE_OK) return NULL;
956 cptr = get_glyph (cptr, gbuf, term); /* get register */
957 val[1] = (int32) get_uint (gbuf, 8, I_M_DST, &r);
958 if (r != SCPE_OK) return NULL;
959 return cptr;
960 }
961
962 /* Symbolic input
963
964 Inputs:
965 *cptr = pointer to input string
966 addr = current PC
967 *uptr = pointer to unit
968 *val = pointer to output values
969 sw = switches
970 Outputs:
971 status = error status
972 */
973
974 t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
975 {
976 int32 cflag, d, i, j, amd[3];
977 t_stat r, rtn;
978 char gbuf[CBUFSIZE];
979
980 cflag = (uptr == NULL) || (uptr == &cpu_unit);
981 while (isspace (*cptr)) cptr++; /* absorb spaces */
982 if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
983 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
984 val[0] = (t_value) cptr[0];
985 return SCPE_OK;
986 }
987 if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
988 if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
989 val[0] = ((t_value) cptr[0] << 8) + (t_value) cptr[1];
990 return SCPE_OK;
991 }
992
993 /* Instruction parse */
994
995 rtn = SCPE_OK; /* assume 1 word */
996 cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
997 for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
998 if (opcode[i] == NULL) return SCPE_ARG;
999 val[0] = opc_val[i] & 0177777; /* get value */
1000 j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
1001
1002 switch (j) { /* case on class */
1003
1004 case I_V_NPN: /* no operand */
1005 break;
1006
1007 case I_V_R: /* IOT reg */
1008 cptr = get_glyph (cptr, gbuf, 0); /* get register */
1009 d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
1010 if (r != SCPE_OK) return SCPE_ARG;
1011 val[0] = val[0] | (d << I_V_DST); /* put in place */
1012 break;
1013
1014 case I_V_RD: /* IOT reg,dev */
1015 cptr = get_glyph (cptr, gbuf, ','); /* get register */
1016 d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
1017 if (r != SCPE_OK) return SCPE_ARG;
1018 val[0] = val[0] | (d << I_V_DST); /* put in place */
1019 case I_V_D: /* IOT dev */
1020 cptr = get_glyph (cptr, gbuf, 0); /* get device */
1021 for (i = 0; (device[i] != NULL) &&
1022 (strcmp (device[i], gbuf) != 0); i++);
1023 if (device[i] != NULL) val[0] = val[0] | dev_val[i];
1024 else {
1025 d = (int32) get_uint (gbuf, 8, I_M_DEV, &r);
1026 if (r != SCPE_OK) return SCPE_ARG;
1027 val[0] = val[0] | (d << I_V_DEV);
1028 }
1029 break;
1030
1031 case I_V_RM: /* reg, addr */
1032 cptr = get_glyph (cptr, gbuf, ','); /* get register */
1033 d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
1034 if (r != SCPE_OK) return SCPE_ARG;
1035 val[0] = val[0] | (d << I_V_DST); /* put in place */
1036 case I_V_M: /* addr */
1037 cptr = get_addr (cptr, addr, FALSE, cflag, amd);
1038 if (cptr == NULL) return SCPE_ARG;
1039 val[0] = val[0] | (amd[0] << I_V_IND) | (amd[1] << I_V_MODE) | amd[2];
1040 break;
1041
1042 case I_V_RR: /* operate */
1043 cptr = get_2reg (cptr, ',', amd); /* get 2 reg */
1044 if (cptr == NULL) return SCPE_ARG;
1045 val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST);
1046 if (*cptr != 0) { /* skip? */
1047 cptr = get_glyph (cptr, gbuf, 0); /* get skip */
1048 for (i = 0; (skip[i] != NULL) &&
1049 (strcmp (skip[i], gbuf) != 0); i++) ;
1050 if (skip[i] == NULL) return SCPE_ARG;
1051 val[0] = val[0] | (i + 1);
1052 } /* end if */
1053 break;
1054
1055 case I_V_BY: /* byte */
1056 cptr = get_2reg (cptr, 0, amd); /* get 2 reg */
1057 if (cptr == NULL) return SCPE_ARG;
1058 val[0] = val[0] | (amd[0] << I_V_PULSE) | (amd[1] << I_V_DST);
1059 break;
1060
1061 case I_V_2AC: /* reg, reg */
1062 cptr = get_2reg (cptr, 0, amd); /* get 2 reg */
1063 if (cptr == NULL) return SCPE_ARG;
1064 val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST);
1065 break;
1066
1067 case I_V_RSI: /* reg, short imm */
1068 cptr = get_glyph (cptr, gbuf, ','); /* get immediate */
1069 d = (int32) get_uint (gbuf, 8, I_M_SRC + 1, &r);
1070 if ((d == 0) || (r != SCPE_OK)) return SCPE_ARG;
1071 val[0] = val[0] | ((d - 1) << I_V_SRC); /* put in place */
1072 cptr = get_glyph (cptr, gbuf, 0); /* get register */
1073 d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
1074 if (r != SCPE_OK) return SCPE_ARG;
1075 val[0] = val[0] | (d << I_V_DST); /* put in place */
1076 break;
1077
1078 case I_V_RLI: /* reg, long imm */
1079 cptr = get_glyph (cptr, gbuf, ','); /* get immediate */
1080 val[1] = (int32) get_uint (gbuf, 8, DMASK, &r);
1081 if (r != SCPE_OK) return SCPE_ARG;
1082 cptr = get_glyph (cptr, gbuf, 0); /* get register */
1083 d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
1084 if (r != SCPE_OK) return SCPE_ARG;
1085 val[0] = val[0] | (d << I_V_DST); /* put in place */
1086 rtn = -1;
1087 break;
1088
1089 case I_V_LI: /* long imm */
1090 cptr = get_glyph (cptr, gbuf, 0); /* get immediate */
1091 val[1] = (int32) get_uint (gbuf, 8, DMASK, &r);
1092 if (r != SCPE_OK) return SCPE_ARG;
1093 rtn = -1;
1094 break;
1095
1096 case I_V_RLM: /* reg, long mem */
1097 cptr = get_glyph (cptr, gbuf, ','); /* get register */
1098 d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
1099 if (r != SCPE_OK) return SCPE_ARG;
1100 val[0] = val[0] | (d << I_V_DST); /* put in place */
1101 case I_V_LM: /* long mem */
1102 cptr = get_addr (cptr, addr, TRUE, cflag, amd);
1103 if (cptr == NULL) return SCPE_ARG;
1104 val[0] = val[0] | (amd[1] << I_V_MODE);
1105 val[1] = (amd[0] << A_V_IND) | amd[2];
1106 rtn = -1;
1107 break;
1108
1109 case I_V_FRM: /* flt reg, long mem */
1110 cptr = get_glyph (cptr, gbuf, ','); /* get register */
1111 d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
1112 if (r != SCPE_OK) return SCPE_ARG;
1113 val[0] = val[0] | (d << I_V_DST); /* put in place */
1114 cptr = get_addr (cptr, addr, TRUE, cflag, amd);
1115 if (cptr == NULL) return SCPE_ARG;
1116 val[0] = val[0] | (amd[1] << I_V_SRC);
1117 val[1] = (amd[0] << A_V_IND) | amd[2];
1118 rtn = -1;
1119 break;
1120
1121 case I_V_FST: /* flt status */
1122 cptr = get_addr (cptr, addr, TRUE, cflag, amd);
1123 if (cptr == NULL) return SCPE_ARG;
1124 val[0] = val[0] | (amd[1] << I_V_DST);
1125 val[1] = (amd[0] << A_V_IND) | amd[2];
1126 rtn = -1;
1127 break;
1128
1129 case I_V_XP: /* XOP */
1130 cptr = get_2reg (cptr, ',', amd); /* get 2 reg */
1131 if (cptr == NULL) return SCPE_ARG;
1132 val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST);
1133 cptr = get_glyph (cptr, gbuf, 0); /* get argument */
1134 d = (int32) get_uint (gbuf, 8, I_M_XOP, &r);
1135 if (r != SCPE_OK) return SCPE_ARG;
1136 val[0] = val[0] | (d << I_V_XOP);
1137 break;
1138 } /* end case */
1139
1140 if (*cptr != 0) return SCPE_ARG; /* any leftovers? */
1141 return rtn;
1142 }