1 /* hp2100_cpu1.c: HP 2100/1000 EAU simulator and UIG dispatcher
3 Copyright (c) 2005-2008, 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 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.
26 CPU1 Extended arithmetic and optional microcode dispatchers
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
43 - HP 1000 M/E/F-Series Computers Technical Reference Handbook
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)
49 Additional references are listed with the associated firmware
50 implementations, as are the HP option model numbers pertaining to the
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.
59 This module also provides generalized instruction operand processing.
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.
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).
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.
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.
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.
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.
101 #include "hp2100_defs.h"
102 #include "hp2100_cpu.h"
103 #include "hp2100_cpu1.h"
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 */
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 */
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:
129 2114 2115 2116 2100 1000-M 1000-E 1000-F
130 ------ ------ ------ ------ ------ ------ ------
131 N/A 12579A 12579A std std std std
133 The instruction codes are mapped to routines as follows:
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
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.
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.
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.
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.
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,
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.
185 t_stat
cpu_eau (uint32 IR
, uint32 intrq
)
187 t_stat reason
= SCPE_OK
;
189 uint32 rs
, qs
, sc
, v1
, v2
, t
;
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 */
196 return stop_inst
; /* fail */
198 switch ((IR
>> 8) & 0377) { /* decode IR<15:8> */
200 case 0200: /* EAU group 0 */
201 switch ((IR
>> 4) & 017) { /* decode IR<7:4> */
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 */
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;
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 */
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 */
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
;
242 case 010: /* MPY 100200 (OP_K) */
244 if (reason
= cpu_ops (OP_K
, op
, intrq
)) /* get operand */
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 */
251 O
= 0; /* no overflow */
254 default: /* others undefined */
260 case 0201: /* DIV 100400 (OP_K) */
261 if (reason
= cpu_ops (OP_K
, op
, intrq
)) /* get operand */
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 */
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 */
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 */
282 if (rs
) BR
= (~BR
+ 1) & DMASK
; /* apply rem sign */
286 case 0202: /* EAU group 2 */
287 switch ((IR
>> 4) & 017) { /* decode IR<7:4> */
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 */
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 */
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
;
309 default: /* others undefined */
315 case 0210: /* DLD 104200 (OP_D) */
316 if (reason
= cpu_ops (OP_D
, op
, intrq
)) /* get operand */
318 AR
= (op
[0].dword
>> 16) & DMASK
; /* load AR */
319 BR
= op
[0].dword
& DMASK
; /* load BR */
322 case 0211: /* DST 104400 (OP_A) */
323 if (reason
= cpu_ops (OP_A
, op
, intrq
)) /* get operand */
325 WriteW (op
[0].word
, AR
); /* store AR */
326 WriteW ((op
[0].word
+ 1) & VAMASK
, BR
); /* store BR */
329 default: /* should never get here */
330 return SCPE_IERR
; /* bad call from cpu_instr */
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
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
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.
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.
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.
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.
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.
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
395 t_stat
cpu_uig_0 (uint32 IR
, uint32 intrq
, uint32 iotrap
)
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 */
402 #if !defined (HAVE_INT64) && defined (ENABLE_DIAG) /* DBI diagnostic dispatcher wanted */
404 if ((cpu_unit
.flags
& UNIT_FFP
) == 0)
406 case 0014: /* .DAD 105014 */
407 return cpu_dbi (0105321, intrq
);
409 case 0034: /* .DSB 105034 */
410 return cpu_dbi (0105327, intrq
);
412 case 0054: /* .DMP 105054 */
413 return cpu_dbi (0105322, intrq
);
415 case 0074: /* .DDI 105074 */
416 return cpu_dbi (0105325, intrq
);
418 case 0114: /* .DSBR 105114 */
419 return cpu_dbi (0105334, intrq
);
421 case 0134: /* .DDIR 105134 */
422 return cpu_dbi (0105326, intrq
);
424 case 0203: /* .DNG 105203 */
425 return cpu_dbi (0105323, intrq
);
427 case 0204: /* .DCO 105204 */
428 return cpu_dbi (0105324, intrq
);
430 case 0210: /* .DIN 105210 */
431 return cpu_dbi (0105330, intrq
);
433 case 0211: /* .DDE 105211 */
434 return cpu_dbi (0105331, intrq
);
436 case 0212: /* .DIS 105212 */
437 return cpu_dbi (0105332, intrq
);
439 case 0213: /* .DDS 105213 */
440 return cpu_dbi (0105333, intrq
);
441 } /* otherwise, continue */
443 #endif /* end of DBI dispatcher */
446 switch ((IR
>> 4) & 017) { /* decode IR<7:4> */
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 */
460 case 010: /* 105200-105217 */
461 case 011: /* 105220-105237 */
462 return cpu_ffp (IR
, intrq
); /* Fast FORTRAN Processor */
464 case 012: /* 105240-105257 */
465 return cpu_rte_vma (IR
, intrq
); /* RTE-4/6 EMA/VMA */
467 case 014: /* 105300-105317 */
468 return cpu_ds (IR
, intrq
); /* Distributed System */
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 */
478 case 016: /* 105340-105357 */
479 return cpu_rte_os (IR
, intrq
, iotrap
); /* RTE-6 OS */
482 return stop_inst
; /* others undefined */
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):
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
501 Only 1000 systems execute these instructions.
504 t_stat
cpu_uig_1 (uint32 IR
, uint32 intrq
, uint32 iotrap
)
506 if (UNIT_CPU_TYPE
!= UNIT_TYPE_1000
) /* 1000 execution? */
507 return stop_inst
; /* no, so trap */
509 switch ((IR
>> 4) & 017) { /* decode IR<7:4> */
511 case 000: /* 105400-105417 */
512 case 001: /* 105420-105437 */
513 return cpu_iop (IR
, intrq
); /* 2000 I/O Processor */
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 */
523 case 005: /* 105520-105537 */
524 IR
= IR
^ 0000620; /* remap to 105300-105317 */
525 return cpu_ds (IR
, intrq
); /* Distributed System */
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 */
532 case 014: /* 105700-105717 */
533 case 015: /* 105720-105737 */
534 return cpu_dms (IR
, intrq
); /* Dynamic Mapping System */
536 case 016: /* 105740-105737 */
537 case 017: /* 105760-105777 */
538 return cpu_eig (IR
, intrq
); /* Extended Instruction Group */
541 return stop_inst
; /* others undefined */
545 /* Read a multiple-precision operand value. */
547 OP
ReadOp (uint32 va
, OPSIZE precision
)
552 if (precision
== in_s
)
553 operand
.word
= ReadW (va
); /* read single integer */
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 */
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
;
567 /* Write a multiple-precision operand value. */
569 void WriteOp (uint32 va
, OP operand
, OPSIZE precision
)
573 if (precision
== in_s
)
574 WriteW (va
, operand
.word
); /* write single integer */
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 */
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
;
590 /* Get instruction operands.
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.
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.
604 The following operand encodings are defined:
606 Code Operand Description Example Return
607 ------ ---------------------------------------- ----------- ------------
608 OP_NUL No operand present [inst] None
610 OP_IAR Integer constant in A register LDA I Value of I
615 OP_DAB Double integer constant in A/B registers DLD J Value of J
620 OP_FAB 2-word FP constant in A/B registers DLD F Value of F
625 OP_CON Inline 1-word constant [inst] Value of C
629 OP_VAR Inline 1-word variable [inst] Address of V
633 OP_ADR Inline address [inst] Address of A
638 OP_ADK Address of integer constant [inst] Value of K
643 OP_ADD Address of double integer constant [inst] Value of D
648 OP_ADF Address of 2-word FP constant [inst] Value of F
653 OP_ADX Address of 3-word FP constant [inst] Value of X
658 OP_ADT Address of 4-word FP constant [inst] Value of T
663 OP_ADE Address of 5-word FP constant [inst] Value of E
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.
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.
679 t_stat
cpu_ops (OP_PAT pattern
, OPS op
, uint32 irq
)
681 t_stat reason
= SCPE_OK
;
685 for (i
= 0; i
< OP_N_F
; i
++) {
686 flags
= pattern
& OP_M_FLAGS
; /* get operand pattern */
688 if (flags
>= OP_ADR
) /* address operand? */
689 if (reason
= resolve (ReadW (PC
), &MA
, irq
)) /* resolve indirects */
693 case OP_NUL
: /* null operand */
694 return reason
; /* no more, so quit */
696 case OP_IAR
: /* int in A */
697 (*op
++).word
= AR
; /* get one-word value */
700 case OP_JAB
: /* dbl-int in A/B */
701 (*op
++).dword
= (AR
<< 16) | BR
; /* get two-word value */
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 */
709 case OP_CON
: /* inline constant operand */
710 *op
++ = ReadOp (PC
, in_s
); /* get value */
713 case OP_VAR
: /* inline variable operand */
714 (*op
++).word
= PC
; /* get pointer to variable */
717 case OP_ADR
: /* inline address operand */
718 (*op
++).word
= MA
; /* get address */
721 case OP_ADK
: /* address of int constant */
722 *op
++ = ReadOp (MA
, in_s
); /* get value */
725 case OP_ADD
: /* address of dbl-int constant */
726 *op
++ = ReadOp (MA
, in_d
); /* get value */
729 case OP_ADF
: /* address of 2-word FP const */
730 *op
++ = ReadOp (MA
, fp_f
); /* get value */
733 case OP_ADX
: /* address of 3-word FP const */
734 *op
++ = ReadOp (MA
, fp_x
); /* get value */
737 case OP_ADT
: /* address of 4-word FP const */
738 *op
++ = ReadOp (MA
, fp_t
); /* get value */
741 case OP_ADE
: /* address of 5-word FP const */
742 *op
++ = ReadOp (MA
, fp_e
); /* get value */
746 return SCPE_IERR
; /* not implemented */
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 */
757 /* Print operands to the debug device.
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.
764 void fprint_ops (OP_PAT pattern
, OPS op
)
769 for (i
= 0; i
< OP_N_F
; i
++) {
770 flags
= pattern
& OP_M_FLAGS
; /* get operand pattern */
773 case OP_NUL
: /* null operand */
774 return; /* no more, so quit */
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 */
786 case OP_JAB
: /* dbl-int in A/B */
787 case OP_ADD
: /* address of dbl-int constant */
793 case OP_FAB
: /* 2-word FP in A/B */
794 case OP_ADF
: /* address of 2-word FP const */
796 ", op[%d] = (%06o, %06o)",
797 i
, op
[i
].fpk
[0], op
[i
].fpk
[1]);
800 case OP_ADX
: /* address of 3-word FP const */
802 ", op[%d] = (%06o, %06o, %06o)",
803 i
, op
[i
].fpk
[0], op
[i
].fpk
[1],
807 case OP_ADT
: /* address of 4-word FP const */
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]);
814 case OP_ADE
: /* address of 5-word FP const */
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]);
822 fprintf (sim_deb
, "UNKNOWN OPERAND TYPE"); /* not implemented */
825 pattern
= pattern
>> OP_N_FLAGS
; /* move next pattern into place */
830 /* Print CPU registers to the debug device.
832 One or more CPU registers may be printed to the debug output device, which
833 must be valid before calling.
836 void fprint_regs (char *caption
, uint32 regs
, uint32 base
)
838 static uint32 ARX
, BRX
, PRL
; /* static so addresses are constant */
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" };
844 static char format
[20] = " %s = "; /* base format string */
845 static const int eos
= 6; /* length of base format string */
848 t_bool first
= TRUE
; /* first-time through flag */
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 */
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 */
859 fputc (',', sim_deb
); /* print separator */
861 strcpy (&format
[eos
], formats
[i
]); /* copy format specifier */
862 fprintf (sim_deb
, format
, reg_names
[i
], *reg_ptrs
[i
]);
867 regs
= regs
>> 1; /* align next register flag */