First Commit of my working state
[simh.git] / HP2100 / hp2100_cpu1.c
1 /* hp2100_cpu1.c: HP 2100/1000 EAU simulator and UIG dispatcher
2
3 Copyright (c) 2005-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 CPU1 Extended arithmetic and optional microcode dispatchers
27
28 20-Apr-08 JDB Fixed VIS and SIGNAL to depend on the FPP and HAVE_INT64
29 28-Nov-07 JDB Added fprint_ops, fprint_regs for debug printouts
30 17-Nov-07 JDB Enabled DIAG as NOP on 1000 F-Series
31 04-Jan-07 JDB Added special DBI dispatcher for non-INT64 diagnostic
32 29-Dec-06 JDB Allows RRR as NOP if 2114 (diag config test)
33 01-Dec-06 JDB Substitutes FPP for firmware FP if HAVE_INT64
34 16-Oct-06 JDB Generalized operands for F-Series FP types
35 26-Sep-06 JDB Split hp2100_cpu1.c into multiple modules to simplify extensions
36 Added iotrap parameter to UIG dispatchers for RTE microcode
37 22-Feb-05 JDB Removed EXECUTE instruction (is NOP in actual microcode)
38 21-Jan-05 JDB Reorganized CPU option and operand processing flags
39 Split code along microcode modules
40 15-Jan-05 RMS Cloned from hp2100_cpu.c
41
42 Primary references:
43 - HP 1000 M/E/F-Series Computers Technical Reference Handbook
44 (5955-0282, Mar-1980)
45 - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
46 (92851-90001, Mar-1981)
47 - Macro/1000 Reference Manual (92059-90001, Dec-1992)
48
49 Additional references are listed with the associated firmware
50 implementations, as are the HP option model numbers pertaining to the
51 applicable CPUs.
52
53 This source file contains the Extended Arithmetic Unit simulator and the User
54 Instruction Group (a.k.a. "Macro") dispatcher for the 2100 and 1000 (21MX)
55 CPUs. The UIG simulators reside in separate source files, due to the large
56 number of firmware options available for the 1000 machines. Unit flags
57 indicate which options are present in the current system.
58
59 This module also provides generalized instruction operand processing.
60
61 The microcode address space of the 2100 encompassed four modules of 256 words
62 each. The 1000 M-series expanded that to sixteen modules, and the 1000
63 E/F-series expanded that still further to sixty-four modules. Each CPU had
64 its own microinstruction set, although the micromachines of the various 1000
65 models were similar internally.
66
67 Regarding option instruction sets, there was some commonality across CPU
68 types. EAU instructions were identical across all models, and the floating
69 point set was the same on the 2100 and 1000. Other options implemented
70 proper instruction supersets (e.g., the Fast FORTRAN Processor from 2100 to
71 1000-M to 1000-E to 1000-F) or functional equivalence with differing code
72 points (the 2000 I/O Processor from 2100 to 1000 and extended-precision
73 floating-point instructions from 1000-E to 1000-F).
74
75 The 2100 decoded the EAU and UIG sets separately in hardware and supported
76 only the UIG 0 code points. Bits 7-4 of a UIG instruction decoded one of
77 sixteen entry points in the lowest-numbered module after module 0. Those
78 entry points could be used directly (as for the floating-point instructions),
79 or additional decoding based on bits 3-0 could be implemented.
80
81 The 1000 generalized the instruction decoding to a series of microcoded
82 jumps, based on the bits in the instruction. Bits 15-8 indicated the group
83 of the current instruction: EAU (200, 201, 202, 210, and 211), UIG 0 (212),
84 or UIG 1 (203 and 213). UIG 0, UIG 1, and some EAU instructions were decoded
85 further by selecting one of sixteen modules within the group via bits 7-4.
86 Finally, each UIG module decoded up to sixteen instruction entry points via
87 bits 3-0. Jump tables for all firmware options were contained in the base
88 set, so modules needed only to be concerned with decoding their individual
89 entry points within the module.
90
91 While the 2100 and 1000 hardware decoded these instruction sets differently,
92 the decoding mechanism of the simulation follows that of the 1000 E/F-series.
93 Where needed, CPU type- or model-specific behavior is simulated.
94
95 The design of the 1000 microinstruction set was such that executing an
96 instruction for which no microcode was present (e.g., executing a FFP
97 instruction when the FFP firmware was not installed) resulted in a NOP.
98 Under simulation, such execution causes an undefined instruction stop.
99 */
100
101 #include "hp2100_defs.h"
102 #include "hp2100_cpu.h"
103 #include "hp2100_cpu1.h"
104
105 #if defined (HAVE_INT64) /* int64 support available */
106 extern t_stat cpu_fpp (uint32 IR, uint32 intrq); /* Floating Point Processor */
107 extern t_stat cpu_sis (uint32 IR, uint32 intrq); /* Scientific Instruction Set */
108 extern t_stat cpu_vis (uint32 IR, uint32 intrq); /* Vector Instruction Set */
109 extern t_stat cpu_signal (uint32 IR, uint32 intrq); /* SIGNAL/1000 */
110 #else /* int64 support unavailable */
111 extern t_stat cpu_fp (uint32 IR, uint32 intrq); /* Firmware Floating Point */
112 #endif /* end of int64 support */
113
114 extern t_stat cpu_ffp (uint32 IR, uint32 intrq); /* Fast FORTRAN Processor */
115 extern t_stat cpu_ds (uint32 IR, uint32 intrq); /* Distributed Systems */
116 extern t_stat cpu_dbi (uint32 IR, uint32 intrq); /* Double integer */
117 extern t_stat cpu_rte_vma (uint32 IR, uint32 intrq); /* RTE-4/6 EMA/VMA */
118 extern t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap); /* RTE-6 OS */
119 extern t_stat cpu_iop (uint32 IR, uint32 intrq); /* 2000 I/O Processor */
120 extern t_stat cpu_dms (uint32 IR, uint32 intrq); /* Dynamic mapping system */
121 extern t_stat cpu_eig (uint32 IR, uint32 intrq); /* Extended instruction group */
122
123 /* EAU
124
125 The Extended Arithmetic Unit (EAU) adds ten instructions with double-word
126 operands, including multiply, divide, shifts, and rotates. Option
127 implementation by CPU was as follows:
128
129 2114 2115 2116 2100 1000-M 1000-E 1000-F
130 ------ ------ ------ ------ ------ ------ ------
131 N/A 12579A 12579A std std std std
132
133 The instruction codes are mapped to routines as follows:
134
135 Instr. Bits
136 Code 15-8 7-4 2116 2100 1000-M 1000-E 1000-F Note
137 ------ ---- --- ------ ------ ------ ------ ------ ---------------------
138 100000 200 00 [diag] [diag] [self test]
139 100020 200 01 ASL ASL ASL ASL ASL Bits 3-0 encode shift
140 100040 200 02 LSL LSL LSL LSL LSL Bits 3-0 encode shift
141 100060 200 03 TIMER TIMER [deterministic delay]
142 100100 200 04 RRL RRL RRL RRL RRL Bits 3-0 encode shift
143 100200 200 10 MPY MPY MPY MPY MPY
144 100400 201 xx DIV DIV DIV DIV DIV
145 101020 202 01 ASR ASR ASR ASR ASR Bits 3-0 encode shift
146 101040 202 02 LSR LSR LSR LSR LSR Bits 3-0 encode shift
147 101100 202 04 RRR RRR RRR RRR RRR Bits 3-0 encode shift
148 104200 210 xx DLD DLD DLD DLD DLD
149 104400 211 xx DST DST DST DST DST
150
151 The remaining codes for bits 7-4 are undefined and will cause a simulator
152 stop if enabled. On a real 1000-M, all undefined instructions in the 200
153 group decode as MPY, and all in the 202 group decode as NOP. On a real
154 1000-E, instruction patterns 200/05 through 200/07 and 202/03 decode as NOP;
155 all others cause erroneous execution.
156
157 EAU instruction decoding on the 1000 M-series is convoluted. The JEAU
158 microorder maps IR bits 11, 9-7 and 5-4 to bits 2-0 of the microcode jump
159 address. The map is detailed on page IC-84 of the ERD.
160
161 The 1000 E/F-series add two undocumented instructions to the 200 group: TIMER
162 and DIAG. These are described in the ERD on page IA 5-5, paragraph 5-7. The
163 M-series executes these as MPY and RRL, respectively. A third instruction,
164 EXECUTE (100120), is also described but was never implemented, and the
165 E/F-series microcode execute a NOP for this instruction code.
166
167 Notes:
168
169 1. Under simulation, TIMER, DIAG, and EXECUTE cause undefined instruction
170 stops if the CPU is set to 21xx. DIAG and EXECUTE also cause stops on
171 the 1000-M. TIMER does not, because it is used by several HP programs
172 to differentiate between M- and E/F-series machines.
173
174 2. DIAG is not implemented under simulation. On the E/F, it performs a
175 destructive test of all installed memory. Because of this, it is only
176 functional if the machine is halted, i.e., if the instruction is
177 executed with the INSTR STEP button. If it is executed in a program,
178 the result is NOP.
179
180 3. RRR is permitted and executed as NOP if the CPU is a 2114, as the
181 presence of the EAU is tested by the diagnostic configurator to
182 differentiate between 2114 and 2100/1000 CPUs.
183 */
184
185 t_stat cpu_eau (uint32 IR, uint32 intrq)
186 {
187 t_stat reason = SCPE_OK;
188 OPS op;
189 uint32 rs, qs, sc, v1, v2, t;
190 int32 sop1, sop2;
191
192 if ((cpu_unit.flags & UNIT_EAU) == 0) /* option installed? */
193 if ((UNIT_CPU_MODEL == UNIT_2114) && (IR == 0101100)) /* 2114 and RRR 16? */
194 return SCPE_OK; /* allowed as NOP */
195 else
196 return stop_inst; /* fail */
197
198 switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
199
200 case 0200: /* EAU group 0 */
201 switch ((IR >> 4) & 017) { /* decode IR<7:4> */
202
203 case 000: /* DIAG 100000 */
204 if ((UNIT_CPU_MODEL != UNIT_1000_E) && /* must be 1000 E-series */
205 (UNIT_CPU_MODEL != UNIT_1000_F)) /* or 1000 F-series */
206 return stop_inst; /* trap if not */
207 break; /* DIAG is NOP unless halted */
208
209 case 001: /* ASL 100020-100037 */
210 sc = (IR & 017)? (IR & 017): 16; /* get sc */
211 O = 0; /* clear ovflo */
212 while (sc-- != 0) { /* bit by bit */
213 t = BR << 1; /* shift B */
214 BR = (BR & SIGN) | (t & 077777) | (AR >> 15);
215 AR = (AR << 1) & DMASK;
216 if ((BR ^ t) & SIGN) O = 1;
217 }
218 break;
219
220 case 002: /* LSL 100040-100057 */
221 sc = (IR & 017)? (IR & 017): 16; /* get sc */
222 BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
223 AR = (AR << sc) & DMASK; /* BR'AR lsh left */
224 break;
225
226 case 003: /* TIMER 100060 */
227 if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
228 return stop_inst; /* trap if not */
229 if (UNIT_CPU_MODEL == UNIT_1000_M) /* 1000 M-series? */
230 goto MPY; /* decode as MPY */
231 BR = (BR + 1) & DMASK; /* increment B */
232 if (BR) PC = err_PC; /* if !=0, repeat */
233 break;
234
235 case 004: /* RRL 100100-100117 */
236 sc = (IR & 017)? (IR & 017): 16; /* get sc */
237 t = BR; /* BR'AR rot left */
238 BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
239 AR = ((AR << sc) | (t >> (16 - sc))) & DMASK;
240 break;
241
242 case 010: /* MPY 100200 (OP_K) */
243 MPY:
244 if (reason = cpu_ops (OP_K, op, intrq)) /* get operand */
245 break;
246 sop1 = SEXT (AR); /* sext AR */
247 sop2 = SEXT (op[0].word); /* sext mem */
248 sop1 = sop1 * sop2; /* signed mpy */
249 BR = (sop1 >> 16) & DMASK; /* to BR'AR */
250 AR = sop1 & DMASK;
251 O = 0; /* no overflow */
252 break;
253
254 default: /* others undefined */
255 return stop_inst;
256 }
257
258 break;
259
260 case 0201: /* DIV 100400 (OP_K) */
261 if (reason = cpu_ops (OP_K, op, intrq)) /* get operand */
262 break;
263 if (rs = qs = BR & SIGN) { /* save divd sign, neg? */
264 AR = (~AR + 1) & DMASK; /* make B'A pos */
265 BR = (~BR + (AR == 0)) & DMASK; /* make divd pos */
266 }
267 v2 = op[0].word; /* divr = mem */
268 if (v2 & SIGN) { /* neg? */
269 v2 = (~v2 + 1) & DMASK; /* make divr pos */
270 qs = qs ^ SIGN; /* sign of quotient */
271 }
272 if (BR >= v2) O = 1; /* divide work? */
273 else { /* maybe... */
274 O = 0; /* assume ok */
275 v1 = (BR << 16) | AR; /* 32b divd */
276 AR = (v1 / v2) & DMASK; /* quotient */
277 BR = (v1 % v2) & DMASK; /* remainder */
278 if (AR) { /* quotient > 0? */
279 if (qs) AR = (~AR + 1) & DMASK; /* apply quo sign */
280 if ((AR ^ qs) & SIGN) O = 1; /* still wrong? ovflo */
281 }
282 if (rs) BR = (~BR + 1) & DMASK; /* apply rem sign */
283 }
284 break;
285
286 case 0202: /* EAU group 2 */
287 switch ((IR >> 4) & 017) { /* decode IR<7:4> */
288
289 case 001: /* ASR 101020-101037 */
290 sc = (IR & 017)? (IR & 017): 16; /* get sc */
291 AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK;
292 BR = (SEXT (BR) >> sc) & DMASK; /* BR'AR ash right */
293 O = 0;
294 break;
295
296 case 002: /* LSR 101040-101057 */
297 sc = (IR & 017)? (IR & 017): 16; /* get sc */
298 AR = ((BR << (16 - sc)) | (AR >> sc)) & DMASK;
299 BR = BR >> sc; /* BR'AR log right */
300 break;
301
302 case 004: /* RRR 101100-101117 */
303 sc = (IR & 017)? (IR & 017): 16; /* get sc */
304 t = AR; /* BR'AR rot right */
305 AR = ((AR >> sc) | (BR << (16 - sc))) & DMASK;
306 BR = ((BR >> sc) | (t << (16 - sc))) & DMASK;
307 break;
308
309 default: /* others undefined */
310 return stop_inst;
311 }
312
313 break;
314
315 case 0210: /* DLD 104200 (OP_D) */
316 if (reason = cpu_ops (OP_D, op, intrq)) /* get operand */
317 break;
318 AR = (op[0].dword >> 16) & DMASK; /* load AR */
319 BR = op[0].dword & DMASK; /* load BR */
320 break;
321
322 case 0211: /* DST 104400 (OP_A) */
323 if (reason = cpu_ops (OP_A, op, intrq)) /* get operand */
324 break;
325 WriteW (op[0].word, AR); /* store AR */
326 WriteW ((op[0].word + 1) & VAMASK, BR); /* store BR */
327 break;
328
329 default: /* should never get here */
330 return SCPE_IERR; /* bad call from cpu_instr */
331 }
332
333 return reason;
334 }
335
336 /* UIG 0
337
338 The first User Instruction Group (UIG) encodes firmware options for the 2100
339 and 1000. Instruction codes 105000-105377 are assigned to microcode options
340 as follows:
341
342 Instructions Option Name 2100 1000-M 1000-E 1000-F
343 ------------- -------------------------- ------ ------ ------ ------
344 105000-105362 2000 I/O Processor opt - - -
345 105000-105137 Floating Point opt std std std
346 105200-105237 Fast FORTRAN Processor opt opt opt std
347 105240-105257 RTE-IVA/B Extended Memory - - opt opt
348 105240-105257 RTE-6/VM Virtual Memory - - opt opt
349 105300-105317 Distributed System - - opt opt
350 105320-105337 Double Integer - - opt -
351 105320-105337 Scientific Instruction Set - - - std
352 105340-105357 RTE-6/VM Operating System - - opt opt
353
354 Because the 2100 IOP microcode uses the same instruction range as the 2100 FP
355 and FFP options, it cannot coexist with them. To simplify simulation, the
356 2100 IOP instructions are remapped to the equivalent 1000 instructions and
357 dispatched to the UIG 1 module.
358
359 Note that if the 2100 IOP is installed, the only valid UIG instructions are
360 IOP instructions, as the IOP used the full 2100 microcode addressing space.
361
362 The F-Series moved the three-word extended real instructions from the FFP
363 range to the base floating-point range and added four-word double real and
364 two-word double integer instructions. The double integer instructions
365 occupied some of the vacated extended real instruction codes in the FFP, with
366 the rest assigned to the floating-point range. Consequently, many
367 instruction codes for the F-Series are different from the E-Series.
368
369 Notes:
370
371 1. Product 93585A, available from the "Specials" group, added double
372 integer microcode to the E-Series. The instruction codes were different
373 from those in the F-Series to avoid conflicting with the E-Series FFP.
374 HP manual number 93585-90007 documents the double integer instructions,
375 but no copy of this manual has been found. The Macro/1000 manual
376 (92059-090001) lists E-Series double integer instructions as occupying
377 the code points of the F-Series Scientific Instruction Set.
378
379 2. To run the double-integer instructions diagnostic in the absence of
380 64-bit integer support (and therefore of F-Series simulation), a special
381 DBI dispatcher may be enabled by defining ENABLE_DIAG during
382 compilation. This dispatcher will remap the F-Series DBI instructions
383 to the E-Series codes, so that the F-Series diagnostic may be run.
384 Because several of the F-Series DBI instruction codes replace M/E-Series
385 FFP codes, this dispatcher will only operate if FFP is disabled.
386
387 Note that enabling the dispatcher will produce non-standard FP behavior.
388 For example, any code in the range 105000-105017 normally would execute
389 a FAD instruction. With the dispatcher enabled, 105014 would execute a
390 .DAD, while the other codes would execute a FAD. Therefore, ENABLE_DIAG
391 should only be used to run the diagnostic and is not intended for
392 general use.
393 */
394
395 t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap)
396 {
397 if ((cpu_unit.flags & UNIT_IOP) && /* I/O Processor? */
398 (UNIT_CPU_TYPE == UNIT_TYPE_2100)) /* 2100 CPU? */
399 return cpu_iop (IR, intrq); /* dispatch to IOP */
400
401
402 #if !defined (HAVE_INT64) && defined (ENABLE_DIAG) /* DBI diagnostic dispatcher wanted */
403
404 if ((cpu_unit.flags & UNIT_FFP) == 0)
405 switch (IR & 0377) {
406 case 0014: /* .DAD 105014 */
407 return cpu_dbi (0105321, intrq);
408
409 case 0034: /* .DSB 105034 */
410 return cpu_dbi (0105327, intrq);
411
412 case 0054: /* .DMP 105054 */
413 return cpu_dbi (0105322, intrq);
414
415 case 0074: /* .DDI 105074 */
416 return cpu_dbi (0105325, intrq);
417
418 case 0114: /* .DSBR 105114 */
419 return cpu_dbi (0105334, intrq);
420
421 case 0134: /* .DDIR 105134 */
422 return cpu_dbi (0105326, intrq);
423
424 case 0203: /* .DNG 105203 */
425 return cpu_dbi (0105323, intrq);
426
427 case 0204: /* .DCO 105204 */
428 return cpu_dbi (0105324, intrq);
429
430 case 0210: /* .DIN 105210 */
431 return cpu_dbi (0105330, intrq);
432
433 case 0211: /* .DDE 105211 */
434 return cpu_dbi (0105331, intrq);
435
436 case 0212: /* .DIS 105212 */
437 return cpu_dbi (0105332, intrq);
438
439 case 0213: /* .DDS 105213 */
440 return cpu_dbi (0105333, intrq);
441 } /* otherwise, continue */
442
443 #endif /* end of DBI dispatcher */
444
445
446 switch ((IR >> 4) & 017) { /* decode IR<7:4> */
447
448 case 000: /* 105000-105017 */
449 case 001: /* 105020-105037 */
450 case 002: /* 105040-105057 */
451 case 003: /* 105060-105077 */
452 case 004: /* 105100-105117 */
453 case 005: /* 105120-105137 */
454 #if defined (HAVE_INT64) /* int64 support available */
455 return cpu_fpp (IR, intrq); /* Floating Point Processor */
456 #else /* int64 support unavailable */
457 return cpu_fp (IR, intrq); /* Firmware Floating Point */
458 #endif /* end of int64 support */
459
460 case 010: /* 105200-105217 */
461 case 011: /* 105220-105237 */
462 return cpu_ffp (IR, intrq); /* Fast FORTRAN Processor */
463
464 case 012: /* 105240-105257 */
465 return cpu_rte_vma (IR, intrq); /* RTE-4/6 EMA/VMA */
466
467 case 014: /* 105300-105317 */
468 return cpu_ds (IR, intrq); /* Distributed System */
469
470 case 015: /* 105320-105337 */
471 #if defined (HAVE_INT64) /* int64 support available */
472 if (UNIT_CPU_MODEL == UNIT_1000_F) /* F-series? */
473 return cpu_sis (IR, intrq); /* Scientific Instruction */
474 else /* M/E-series */
475 #endif /* end of int64 support */
476 return cpu_dbi (IR, intrq); /* Double integer */
477
478 case 016: /* 105340-105357 */
479 return cpu_rte_os (IR, intrq, iotrap); /* RTE-6 OS */
480 }
481
482 return stop_inst; /* others undefined */
483 }
484
485 /* UIG 1
486
487 The second User Instruction Group (UIG) encodes firmware options for the
488 1000. Instruction codes 101400-101777 and 105400-105777 are assigned to
489 microcode options as follows ("x" is "1" or "5" below):
490
491 Instructions Option Name 1000-M 1000-E 1000-F
492 ------------- ---------------------------- ------ ------ ------
493 10x400-10x437 2000 IOP opt opt -
494 10x460-10x477 2000 IOP opt opt -
495 10x460-10x477 Vector Instruction Set - - opt
496 105520-105537 Distributed System opt - -
497 105600-105617 SIGNAL/1000 Instruction Set - - opt
498 10x700-10x737 Dynamic Mapping System opt opt std
499 10x740-10x777 Extended Instruction Group std std std
500
501 Only 1000 systems execute these instructions.
502 */
503
504 t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap)
505 {
506 if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* 1000 execution? */
507 return stop_inst; /* no, so trap */
508
509 switch ((IR >> 4) & 017) { /* decode IR<7:4> */
510
511 case 000: /* 105400-105417 */
512 case 001: /* 105420-105437 */
513 return cpu_iop (IR, intrq); /* 2000 I/O Processor */
514
515 case 003: /* 105460-105477 */
516 #if defined (HAVE_INT64) /* int64 support available */
517 if (UNIT_CPU_MODEL == UNIT_1000_F) /* F-series? */
518 return cpu_vis (IR, intrq); /* Vector Instruction Set */
519 else /* M/E-series */
520 #endif /* end of int64 support */
521 return cpu_iop (IR, intrq); /* 2000 I/O Processor */
522
523 case 005: /* 105520-105537 */
524 IR = IR ^ 0000620; /* remap to 105300-105317 */
525 return cpu_ds (IR, intrq); /* Distributed System */
526
527 #if defined (HAVE_INT64) /* int64 support available */
528 case 010: /* 105600-105617 */
529 return cpu_signal (IR, intrq); /* SIGNAL/1000 Instructions */
530 #endif /* end of int64 support */
531
532 case 014: /* 105700-105717 */
533 case 015: /* 105720-105737 */
534 return cpu_dms (IR, intrq); /* Dynamic Mapping System */
535
536 case 016: /* 105740-105737 */
537 case 017: /* 105760-105777 */
538 return cpu_eig (IR, intrq); /* Extended Instruction Group */
539 }
540
541 return stop_inst; /* others undefined */
542 }
543
544
545 /* Read a multiple-precision operand value. */
546
547 OP ReadOp (uint32 va, OPSIZE precision)
548 {
549 OP operand;
550 uint32 i;
551
552 if (precision == in_s)
553 operand.word = ReadW (va); /* read single integer */
554
555 else if (precision == in_d)
556 operand.dword = ReadW (va) << 16 | /* read double integer */
557 ReadW ((va + 1) & VAMASK); /* merge high and low words */
558
559 else
560 for (i = 0; i < (uint32) precision; i++) { /* read fp 2 to 5 words */
561 operand.fpk[i] = ReadW (va);
562 va = (va + 1) & VAMASK;
563 }
564 return operand;
565 }
566
567 /* Write a multiple-precision operand value. */
568
569 void WriteOp (uint32 va, OP operand, OPSIZE precision)
570 {
571 uint32 i;
572
573 if (precision == in_s)
574 WriteW (va, operand.word); /* write single integer */
575
576 else if (precision == in_d) {
577 WriteW (va, (operand.dword >> 16) & DMASK); /* write double integer */
578 WriteW ((va + 1) & VAMASK, operand.dword & DMASK); /* high word, then low word */
579 }
580
581 else
582 for (i = 0; i < (uint32) precision; i++) { /* write fp 2 to 5 words */
583 WriteW (va, operand.fpk[i]);
584 va = (va + 1) & VAMASK;
585 }
586 return;
587 }
588
589
590 /* Get instruction operands.
591
592 Operands for a given instruction are specifed by an "operand pattern"
593 consisting of flags indicating the types and storage methods. The pattern
594 directs how each operand is to be retrieved and whether the operand value or
595 address is returned in the operand array.
596
597 Typically, a microcode simulation handler will define an OP_PAT array, with
598 each element containing an operand pattern corresponding to the simulated
599 instruction. Operand patterns are defined in the header file accompanying
600 this source file. After calling this function with the appropriate operand
601 pattern and a pointer to an array of OPs, operands are decoded and stored
602 sequentially in the array.
603
604 The following operand encodings are defined:
605
606 Code Operand Description Example Return
607 ------ ---------------------------------------- ----------- ------------
608 OP_NUL No operand present [inst] None
609
610 OP_IAR Integer constant in A register LDA I Value of I
611 [inst]
612 ...
613 I DEC 0
614
615 OP_DAB Double integer constant in A/B registers DLD J Value of J
616 [inst]
617 ...
618 J DEC 0,0
619
620 OP_FAB 2-word FP constant in A/B registers DLD F Value of F
621 [inst]
622 ...
623 F DEC 0.0
624
625 OP_CON Inline 1-word constant [inst] Value of C
626 C DEC 0
627 ...
628
629 OP_VAR Inline 1-word variable [inst] Address of V
630 V BSS 1
631 ...
632
633 OP_ADR Inline address [inst] Address of A
634 DEF A
635 ...
636 A EQU *
637
638 OP_ADK Address of integer constant [inst] Value of K
639 DEF K
640 ...
641 K DEC 0
642
643 OP_ADD Address of double integer constant [inst] Value of D
644 DEF D
645 ...
646 D DEC 0,0
647
648 OP_ADF Address of 2-word FP constant [inst] Value of F
649 DEF F
650 ...
651 F DEC 0.0
652
653 OP_ADX Address of 3-word FP constant [inst] Value of X
654 DEF X
655 ...
656 X DEX 0.0
657
658 OP_ADT Address of 4-word FP constant [inst] Value of T
659 DEF T
660 ...
661 T DEY 0.0
662
663 OP_ADE Address of 5-word FP constant [inst] Value of E
664 DEF E
665 ...
666 E DEC 0,0,0,0,0
667
668 Address operands, i.e., those having a DEF to the operand, will be resolved
669 to direct addresses. If an interrupt is pending and more than three levels
670 of indirection are used, the routine returns without completing operand
671 retrieval (the instruction will be retried after interrupt servicing).
672 Addresses are always resolved in the current DMS map.
673
674 An operand pattern consists of one or more operand encodings, corresponding
675 to the operands required by a given instruction. Values are returned in
676 sequence to the operand array.
677 */
678
679 t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq)
680 {
681 t_stat reason = SCPE_OK;
682 OP_PAT flags;
683 uint32 i, MA;
684
685 for (i = 0; i < OP_N_F; i++) {
686 flags = pattern & OP_M_FLAGS; /* get operand pattern */
687
688 if (flags >= OP_ADR) /* address operand? */
689 if (reason = resolve (ReadW (PC), &MA, irq)) /* resolve indirects */
690 return reason;
691
692 switch (flags) {
693 case OP_NUL: /* null operand */
694 return reason; /* no more, so quit */
695
696 case OP_IAR: /* int in A */
697 (*op++).word = AR; /* get one-word value */
698 break;
699
700 case OP_JAB: /* dbl-int in A/B */
701 (*op++).dword = (AR << 16) | BR; /* get two-word value */
702 break;
703
704 case OP_FAB: /* 2-word FP in A/B */
705 (*op).fpk[0] = AR; /* get high FP word */
706 (*op++).fpk[1] = BR; /* get low FP word */
707 break;
708
709 case OP_CON: /* inline constant operand */
710 *op++ = ReadOp (PC, in_s); /* get value */
711 break;
712
713 case OP_VAR: /* inline variable operand */
714 (*op++).word = PC; /* get pointer to variable */
715 break;
716
717 case OP_ADR: /* inline address operand */
718 (*op++).word = MA; /* get address */
719 break;
720
721 case OP_ADK: /* address of int constant */
722 *op++ = ReadOp (MA, in_s); /* get value */
723 break;
724
725 case OP_ADD: /* address of dbl-int constant */
726 *op++ = ReadOp (MA, in_d); /* get value */
727 break;
728
729 case OP_ADF: /* address of 2-word FP const */
730 *op++ = ReadOp (MA, fp_f); /* get value */
731 break;
732
733 case OP_ADX: /* address of 3-word FP const */
734 *op++ = ReadOp (MA, fp_x); /* get value */
735 break;
736
737 case OP_ADT: /* address of 4-word FP const */
738 *op++ = ReadOp (MA, fp_t); /* get value */
739 break;
740
741 case OP_ADE: /* address of 5-word FP const */
742 *op++ = ReadOp (MA, fp_e); /* get value */
743 break;
744
745 default:
746 return SCPE_IERR; /* not implemented */
747 }
748
749 if (flags >= OP_CON) /* operand after instruction? */
750 PC = (PC + 1) & VAMASK; /* yes, so bump to next */
751 pattern = pattern >> OP_N_FLAGS; /* move next pattern into place */
752 }
753 return reason;
754 }
755
756
757 /* Print operands to the debug device.
758
759 The values of an operand array are printed to the debug device. The types of
760 the operands are specified by an operand pattern. Typically, the operand
761 pattern is the same one that was used to fill the array originally.
762 */
763
764 void fprint_ops (OP_PAT pattern, OPS op)
765 {
766 OP_PAT flags;
767 uint32 i;
768
769 for (i = 0; i < OP_N_F; i++) {
770 flags = pattern & OP_M_FLAGS; /* get operand pattern */
771
772 switch (flags) {
773 case OP_NUL: /* null operand */
774 return; /* no more, so quit */
775
776 case OP_IAR: /* int in A */
777 case OP_CON: /* inline constant operand */
778 case OP_VAR: /* inline variable operand */
779 case OP_ADR: /* inline address operand */
780 case OP_ADK: /* address of int constant */
781 fprintf (sim_deb,
782 ", op[%d] = %06o",
783 i, op[i].word);
784 break;
785
786 case OP_JAB: /* dbl-int in A/B */
787 case OP_ADD: /* address of dbl-int constant */
788 fprintf (sim_deb,
789 ", op[%d] = %011o",
790 i, op[i].dword);
791 break;
792
793 case OP_FAB: /* 2-word FP in A/B */
794 case OP_ADF: /* address of 2-word FP const */
795 fprintf (sim_deb,
796 ", op[%d] = (%06o, %06o)",
797 i, op[i].fpk[0], op[i].fpk[1]);
798 break;
799
800 case OP_ADX: /* address of 3-word FP const */
801 fprintf (sim_deb,
802 ", op[%d] = (%06o, %06o, %06o)",
803 i, op[i].fpk[0], op[i].fpk[1],
804 op[i].fpk[2]);
805 break;
806
807 case OP_ADT: /* address of 4-word FP const */
808 fprintf (sim_deb,
809 ", op[%d] = (%06o, %06o, %06o, %06o)",
810 i, op[i].fpk[0], op[i].fpk[1],
811 op[i].fpk[2], op[i].fpk[3]);
812 break;
813
814 case OP_ADE: /* address of 5-word FP const */
815 fprintf (sim_deb,
816 ", op[%d] = (%06o, %06o, %06o, %06o, %06o)",
817 i, op[i].fpk[0], op[i].fpk[1],
818 op[i].fpk[2], op[i].fpk[3], op[i].fpk[4]);
819 break;
820
821 default:
822 fprintf (sim_deb, "UNKNOWN OPERAND TYPE"); /* not implemented */
823 }
824
825 pattern = pattern >> OP_N_FLAGS; /* move next pattern into place */
826 }
827 }
828
829
830 /* Print CPU registers to the debug device.
831
832 One or more CPU registers may be printed to the debug output device, which
833 must be valid before calling.
834 */
835
836 void fprint_regs (char *caption, uint32 regs, uint32 base)
837 {
838 static uint32 ARX, BRX, PRL; /* static so addresses are constant */
839
840 static const char *reg_names[] = { "CIR", "A", "B", "E", "X", "Y", "O", "P", "return" };
841 static const uint32 *reg_ptrs[] = { &intaddr, &ARX, &BRX, &E, &XR, &YR, &O, &PC, &PRL };
842 static const char *formats[] = { "%02o", "%06o", "%06o", "%01o", "%06o", "%06o", "%01o", "%06o", "P+%d" };
843
844 static char format[20] = " %s = "; /* base format string */
845 static const int eos = 6; /* length of base format string */
846
847 uint32 i;
848 t_bool first = TRUE; /* first-time through flag */
849
850 ARX = AR; /* copy 16-bit value to static variable */
851 BRX = BR; /* copy 16-bit value to static variable */
852 PRL = PC - base; /* compute value in static variable */
853
854 for (i = 0; i < REG_COUNT; i++) {
855 if (regs & 1) { /* register requested? */
856 if (first) /* first time? */
857 fputs (caption, sim_deb); /* print caption */
858 else
859 fputc (',', sim_deb); /* print separator */
860
861 strcpy (&format[eos], formats[i]); /* copy format specifier */
862 fprintf (sim_deb, format, reg_names[i], *reg_ptrs[i]);
863
864 first = FALSE;
865 }
866
867 regs = regs >> 1; /* align next register flag */
868 }
869 return;
870 }