/* hp2100_cpu.c: HP 21xx/1000 Central Processing Unit/MEM/MP/DCPC simulator Copyright (c) 1993-2016, Robert M. Supnik Copyright (c) 2017, J. David Bryan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the authors. CPU 2114C/2115A/2116C/2100A/1000-M/E/F Central Processing Unit 12731A Memory Expansion Module DMA1,DMA2 12607B/12578A/12895A Direct Memory Access DCPC1,DCPC2 12897B Dual Channel Port Controller MP 12581A/12892B Memory Protect 11-Aug-17 JDB MEM must be disabled when DMS is disabled 01-Aug-17 JDB Changed SET/SHOW CPU [NO]IDLE to use sim_*_idle routines 22-Jul-17 JDB Renamed "intaddr" to CIR; added IR 18-Jul-17 JDB Added CPU stops 11-Jul-17 JDB Moved "hp_enbdis_pair" to hp2100_sys.c Renamed "ibl_copy" to "cpu_ibl" 10-Jul-17 JDB Renamed the global routine "iogrp" to "cpu_iog" 07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool 26-Jun-17 JDB Moved I/O instruction subopcode constants from hp2100_defs.h 16-May-17 JDB Changed REG_A, REG_B to REG_X 19-Apr-17 JDB SET CPU IDLE now omits idle loop tracing 04-Apr-17 JDB Added "cpu_configuration" for symbolic ex/dep validation Rejected model change no longer changes options 21-Mar-17 JDB IOP is now illegal on the 1000 F-Series 27-Feb-17 JDB Added BBL load for 21xx machines ibl_copy no longer returns a status code 22-Feb-17 JDB Added DMA tracing 21-Feb-17 JDB Added bus tracing to the I/O dispatcher 19-Jan-17 JDB Added CPU tracing Consolidated the memory read and write routines 05-Aug-16 JDB Renamed the P register from "PC" to "PR" 13-May-16 JDB Modified for revised SCP API function parameter types 31-Dec-14 JDB Corrected devdisp data parameters 30-Dec-14 JDB Added S-register parameters to ibl_copy 24-Dec-14 JDB Added casts for explicit downward conversions 18-Mar-13 JDB Removed redundant extern declarations 05-Feb-13 JDB HLT instruction handler now relies on sim_vm_fprint_stopped 09-May-12 JDB Separated assignments from conditional expressions 13-Jan-12 JDB Minor speedup in "is_mapped" Added casts to cpu_mod, dmasio, dmapio, cpu_reset, dma_reset 07-Apr-11 JDB Fixed I/O return status bug for DMA cycles Failed I/O cycles now stop on failing instruction 28-Mar-11 JDB Tidied up signal handling 29-Oct-10 JDB Revised DMA for new multi-card paradigm Consolidated DMA reset routines DMA channels renamed from 0,1 to 1,2 to match documentation 27-Oct-10 JDB Changed I/O instructions, handlers, and DMA for revised signal model Changed I/O dispatch table to use DIB pointers 19-Oct-10 JDB Removed DMA latency counter 13-Oct-10 JDB Fixed DMA requests to enable stealing every cycle Fixed DMA priority for channel 1 over channel 2 Corrected comments for "cpu_set_idle" 30-Sep-08 JDB Breakpoints on interrupt trap cells now work 05-Sep-08 JDB VIS and IOP are now mutually exclusive on 1000-F 11-Aug-08 JDB Removed A/B shadow register variables 07-Aug-08 JDB Moved hp_setdev, hp_showdev to hp2100_sys.c Moved non-existent memory checks to WritePW 05-Aug-08 JDB Fixed mp_dms_jmp to accept lower bound, check write protection 30-Jul-08 JDB Corrected DMS violation register set conditions Refefined ABORT to pass address, moved def to hp2100_cpu.h Combined dms and dms_io routines 29-Jul-08 JDB JSB to 0/1 with W5 out and fence = 0 erroneously causes MP abort 11-Jul-08 JDB Unified I/O slot dispatch by adding DIBs for CPU, MP, and DMA 26-Jun-08 JDB Rewrote device I/O to model backplane signals EDT no longer passes DMA channel 30-Apr-08 JDB Enabled SIGNAL instructions, SIG debug flag 28-Apr-08 JDB Added SET CPU IDLE/NOIDLE, idle detection for DOS/RTE 24-Apr-08 JDB Fixed single stepping through interrupts 20-Apr-08 JDB Enabled EMA and VIS, added EMA, VIS, and SIGNAL debug flags 03-Dec-07 JDB Memory ex/dep and bkpt type default to current map mode 26-Nov-07 JDB Added SET CPU DEBUG and OS/VMA flags, enabled OS/VMA 15-Nov-07 JDB Corrected MP W5 (JSB) jumper action, SET/SHOW reversal, mp_mevff clear on interrupt with I/O instruction in trap cell 04-Nov-07 JDB Removed DBI support from 1000-M (was temporary for RTE-6/VM) 28-Apr-07 RMS Removed clock initialization 02-Mar-07 JDB EDT passes input flag and DMA channel in dat parameter 11-Jan-07 JDB Added 12578A DMA byte packing 28-Dec-06 JDB CLC 0 now sends CRS instead of CLC to devices 26-Dec-06 JDB Fixed improper IRQ deferral for 21xx CPUs Fixed improper interrupt servicing in resolve 21-Dec-06 JDB Added 21xx loader enable/disable support 16-Dec-06 JDB Added 2114 and 2115 CPU options. Added support for 12607B (2114) and 12578A (2115/6) DMA 01-Dec-06 JDB Added 1000-F CPU option (requires HAVE_INT64) SHOW CPU displays 1000-M/E instead of 21MX-M/E 16-Oct-06 JDB Moved ReadF to hp2100_cpu1.c 12-Oct-06 JDB Fixed INDMAX off-by-one error in resolve 26-Sep-06 JDB Added iotrap parameter to UIG dispatchers for RTE microcode 12-Sep-06 JDB iogrp returns NOTE_IOG to recalc interrupts resolve returns NOTE_INDINT to service held-off interrupt 16-Aug-06 JDB Added support for future microcode options, future F-Series 09-Aug-06 JDB Added double integer microcode, 1000-M/E synonyms Enhanced CPU option validity checking Added DCPC as a synonym for DMA for 21MX simulations 26-Dec-05 JDB Improved reporting in dev_conflict 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 21-Jan-05 JDB Reorganized CPU option flags 15-Jan-05 RMS Split out EAU and MAC instructions 26-Dec-04 RMS DMA reset doesn't clear alternate CTL flop (from Dave Bryan) DMA reset shouldn't clear control words (from Dave Bryan) Alternate CTL flop not visible as register (from Dave Bryan) Fixed CBS, SBS, TBS to perform virtual reads Separated A/B from M[0/1] for DMA IO (from Dave Bryan) Fixed bug in JPY (from Dave Bryan) 25-Dec-04 JDB Added SET CPU 21MX-M, 21MX-E (21MX defaults to MX-E) TIMER/EXECUTE/DIAG instructions disabled for 21MX-M T-register reflects changes in M-register when halted 25-Sep-04 JDB Moved MP into its own device; added MP option jumpers Modified DMA to allow disabling Modified SET CPU 2100/2116 to truncate memory > 32K Added -F switch to SET CPU to force memory truncation Fixed S-register behavior on 2116 Fixed LIx/MIx behavior for DMA on 2116 and 2100 Fixed LIx/MIx behavior for empty I/O card slots Modified WRU to be REG_HRO Added BRK and DEL to save console settings Fixed use of "unsigned int16" in cpu_reset Modified memory size routine to return SCPE_INCOMP if memory size truncation declined 20-Jul-04 RMS Fixed bug in breakpoint test (reported by Dave Bryan) Back up PC on instruction errors (from Dave Bryan) 14-May-04 RMS Fixed bugs and added features from Dave Bryan - SBT increments B after store - DMS console map must check dms_enb - SFS x,C and SFC x,C work - MP violation clears automatically on interrupt - SFS/SFC 5 is not gated by protection enabled - DMS enable does not disable mem prot checks - DMS status inconsistent at simulator halt - Examine/deposit are checking wrong addresses - Physical addresses are 20b not 15b - Revised DMS to use memory rather than internal format - Added instruction printout to HALT message - Added M and T internal registers - Added N, S, and U breakpoints Revised IBL facility to conform to microcode Added DMA EDT I/O pseudo-opcode Separated DMA SRQ (service request) from FLG 12-Mar-03 RMS Added logical name support 02-Feb-03 RMS Fixed last cycle bug in DMA output (found by Mike Gemeny) 22-Nov-02 RMS Added 21MX IOP support 24-Oct-02 RMS Fixed bugs in IOP and extended instructions Fixed bugs in memory protection and DMS Added clock calibration 25-Sep-02 RMS Fixed bug in DMS decode (found by Robert Alan Byer) 26-Jul-02 RMS Restructured extended instructions, added IOP support 22-Mar-02 RMS Changed to allocate memory array dynamically 11-Mar-02 RMS Cleaned up setjmp/auto variable interaction 17-Feb-02 RMS Added DMS support Fixed bugs in extended instructions 03-Feb-02 RMS Added terminal multiplexor support Changed PCQ macro to use unmodified PC Fixed flop restore logic (found by Bill McDermith) Fixed SZx,SLx,RSS bug (found by Bill McDermith) Added floating point support 16-Jan-02 RMS Added additional device support 07-Jan-02 RMS Fixed DMA register tables (found by Bill McDermith) 07-Dec-01 RMS Revised to use breakpoint package 03-Dec-01 RMS Added extended SET/SHOW support 10-Aug-01 RMS Removed register in declarations 26-Nov-00 RMS Fixed bug in dual device number routine 21-Nov-00 RMS Fixed bug in reset routine 15-Oct-00 RMS Added dynamic device number support References: - 2100A Computer Reference Manual (02100-90001, Dec-1971) - Model 2100A Computer Installation and Maintenance Manual (02100-90002, Aug-1972) - HP 1000 M/E/F-Series Computers Technical Reference Handbook (5955-0282, Mar-1980) - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation (92851-90001, Mar-1981) - HP 1000 M/E/F-Series Computers I/O Interfacing Guide (02109-90006, Sep-1980) - 12607A Direct Memory Access Operating and Service Manual (12607-90002, Jan-1970) - 12578A/12578A-01 Direct Memory Access Operating and Service Manual (12578-9001, Mar-1972) - 12892B Memory Protect Installation Manual (12892-90007, Jun-1978) - HP 1000 Computer Real-Time Systems (5091-4479, August 1992) Hewlett-Packard sold the HP 21xx/1000 family of real-time computers from 1966 through 2000. There are three major divisions within this family: the 21xx core-memory machines, the 1000 (originally 21MX) M/E/F-Series semiconductor- memory machines, and the 1000 L/A-Series machines. All machines are 16-bit accumulator-oriented CISC machines running the same base instruction set. A wide range of operating systems run on these machines, from a simple 4K word paper-tape-based monitor to a megaword multi-user, multiprogramming disc- based system and a multi-user time-shared BASIC system. This implementation is a simulator for the 2114, 2115, 2116, 2100, and 1000 M/E/F-Series machines. A large variety of CPU options, device interface cards, and peripherals are provided. High-speed I/O transfers are performed by Direct Memory Access and Dual-Channel Port Controller options. This simulator does not model the 1000 L/A-Series machines. All of the machines support a 15-bit logical address space, addressing a maximum of 32 K words, divided into 1K-word pages. Memory-referencing instructions in the base set can directly address the 1024 words of the base page (page 0) or the 1024 words of the current page (the page containing the instruction). The instructions in the extended set directly address the 32768 words in the full logical address space. The A and B accumulators may be addressed as logical addresses 0 and 1, respectively. Peripheral devices are connected to the CPU by interface cards installed in the I/O card cages present in the CPU and optional I/O extender chassis. Each slot in the card cage is assigned an address, called a select code, that may be referenced by I/O instructions in the base set. Select codes range from 0 to 77 octal, with the first eight select codes reserved for the system, providing connections for 56 possible interfaces. The 211x machines use a hardwired processor providing 70 basic instructions and up to 32K of core memory. The base instruction set is divided into the Memory Reference Group, the Shift-Rotate Group, the Alter-Skip Group, and the I/O Group. SRG instruction words may contain from one to four suboperation codes that are executed from left-to-right, and ASG instruction words may contain from one to eight suboperations. An optional Extended Arithmetic Unit may be added to the 2115 and 2116 that provides hardware multiply and divide, double-load and -store, and double-word shift and rotate instructions. The 2100 machine uses a microprogrammed processor that provides the 80 instructions of the base set and the EAU as standard equipment. Optional floating-point microcode adds six two-word single-precision instructions. User microprogramming is also supported. When used as part of an HP 2000 Time-Shared BASIC system, the CPU designated as the I/O processor may be equipped with microcode implementing 18 additional OS accelerator instructions. The 1000 M/E-Series machines also use microprogrammed processors and extend the 2100 instruction set with two new index registers, X and Y, and a new Extended Instruction Group consisting of 32 index-register instructions and 10 word-and-byte-manipulation instructions. The six 2100 floating-point instructions are also standard. The 1000 F-Series adds a hardware floating-point processor with 18 new triple- and quad-word instructions. A number of new optional microcode extensions are available with the M/E/F-Series. 1000 CPUs offer the optional Dynamic Mapping System, which provides memory mapping on a page-by-page basis. The 5-bit page number of a logical memory address selects one of 32 ten-bit map registers containing physical page numbers. The ten-bit page number combined with the ten-bit page offset yields a 20-bit physical address capable of accessing a location in a one-megaword memory. DMS provides separate maps for system and user programs, as well as for the two DCPC channels, and includes microcode that implements the 38 Dynamic Mapping Instructions used to manipulate the mapping system. Optional memory protection is accomplished by dividing the logical address space into protected and unprotected parts. When protection is enabled, any attempt to write below the fence separating the two parts is inhibited, and an interrupt to the operating system occurs, which aborts the offending user program. If the DMS option is enabled as well, protection is enhanced by specifying read and write permissions on a page-by-page basis. A note on terminology: the 1000 series of computers was originally called the 21MX at introduction. The 21MX (occasionally, 21MXM) corresponds to the 1000 M-Series, and the 21MXE (occasionally, 21XE) corresponds to the 1000 E-Series. The model numbers were changed before the introduction of the 1000 F-Series, although some internal HP documentation refers to this machine as the 21MXF. The terms MEM (Memory Expansion Module), MEU (Memory Expansion Unit), DMI (Dynamic Mapping Instructions), and DMS (Dynamic Mapping System) are used somewhat interchangeably to refer to the logical-to-physical memory address translation option provided on the 1000-Series. DMS consists of the MEM card (12731A) and the DMI firmware (13307A). However, MEM and MEU have been used interchangeably to refer to the mapping card, as have DMI and DMS to refer to the firmware instructions. These CPU hardware registers are present in all machines: Name Width Description ---- ----- ---------------------------------------------- A 16 accumulator (addressable as memory location 0) B 16 accumulator (addressable as memory location 1) P 15 program counter S 16 switch and display register M 15 memory address register T 16 memory data register E 1 extend flag (carry out) O 1 overflow flag The 1000 Series adds these CPU hardware registers: Name Width Description ---- ----- ---------------------------------------------- X 16 index register Y 16 index register The data types supported by the base instruction set are: - 8-bit unsigned byte - 16-bit unsigned integer - 16-bit two's-complement integer - 32-bit two's-complement integer - 32-bit two's-complement floating point Multi-word values are stored in memory with the most-significant words in the lowest addresses. Bytes are stored in memory with the most-significant byte in the upper half of the 16-bit word and the least-significant byte in the lower half. The instruction set is fairly irregular -- a legacy of its original implementation in hardware in the 2116 and the accretion of microprogrammed instructions in the 2100 and 1000 CPUs. Initially, there were five base-set instruction groups: 1. Memory-Reference Group (MRG) 2. Shift-Rotate Group (SRG) 3. Alter-Skip Group (ASG) 4. I/O Group (IOG) 5. Macroinstruction Group (MAC) All of the instructions added after the 2116 are in the Macroinstruction Group. The 2116 offered two hardware options that extended the instruction set. The first is the 12579A Extended Arithmetic Unit. The second is the 2152A Floating Point Processor, which is interfaced through, and therefore requires, the EAU. The EAU adds 10 instructions including integer multiply and divide and double-word loads, stores, shifts, and rotates. The FPP adds 30 floating-point arithmetic, trigonometric, logarithmic, and exponential instructions. (The 2116 FFP is not simulated.) The base set groups are decoded from bits 15-12 and 10, as follows: 15 14-12 10 Group Address Ranges -- ----- -- ----- ------------------------------- x nnn x MRG 010000-077777 and 110000-177777 0 000 0 SRG 000000-001777 and 004000-005777 0 000 1 ASG 002000-003777 and 006000-007777 1 000 1 IOG 102000-103777 and 106000-107777 1 000 0 MAC 100000-101777 and 104000-105777 Where: x = don't care n = any combination other than all zeros The MAC group is subdivided into the Extended Arithmetic Group (EAG) and the User Instruction Group (UIG), based on bits 11, 9, and 8, as follows: 11 9 8 Group Address Range -- -- -- ----- ------------- 0 0 0 EAG 100000-100377 0 0 1 EAG 100400-100777 0 1 0 EAG 101000-101377 0 1 1 UIG-1 101400-101777 1 0 0 EAG 104000-104377 1 0 1 EAG 104400-104777 1 1 0 UIG-0 105000-105377 1 1 1 UIG-1 105400-105777 All of the 2116 FPP instructions are in the UIG sets: 3 use 10144x opcodes and the rest use 1050xx and 1054xx opcodes. The 2100 decodes only UIG-0 instructions, whereas the 1000s use both UIG sets. In particular, the 105740-105777 range is used by the 1000 Extended Instruction Group (EIG), which is part of the 1000-Series base set. The 21xx and 1000 M/E/F-Series machines do not trap unimplemented instructions. In general, unimplemented EAG instructions cause erroneous execution, and unimplemented UIG instructions execute as NOP. However, there are machine-to-machine variations, and some unimplemented instructions execute as other, defined instructions. The instruction set groups are encoded as follows: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | I | mem op | P | memory address | MRG +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | I | mem op | R | P | memory address | MRG +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: I = direct/indirect (0/1) R = A/B register (0/1) P = base/current page (0/1) The "mem ops" are encoded as follows: 14-11 Mnemonic Action ----- -------- ---------------------------------------- 0010 AND A = A & M [MA] 0011 JSB M [MA] = P, P = MA + 1 0100 XOR A = A ^ M [MA] 0101 JMP P = MA 0110 IOR A = A | M [MA] 0111 ISZ M [MA] = M [MA] + 1, skip if M [MA] == 0 1000 ADA A = A + M [MA] 1001 ADB B = B + M [MA] 1010 CPA skip if A != M [MA] 1011 CPB skip if B != M [MA] 1100 LDA A = M [MA] 1101 LDB B = M [MA] 1110 STA M [MA] = A 1111 STB M [MA] = B Bits 15 and 10 encode the type of access, as follows: 15,10 Access Type Action ----- --------------------- -------------------------- 0,0 base page direct MA = I <9:0> 0,1 current page direct MA = P <14:0>'I <9:0> 1,0 base page indirect MA = M [I <9:0>] 1,1 current page indirect MA = M [P <14:10>'I <9:0>] 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 0 | 0 0 0 | R | 0 | E | op 1 | C | E | S | op 2 | SRG +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: R = A/B register (0/1) E = disable/enable op C = CLE S = SL* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 0 | 0 0 0 | R | 1 | r op | e op | E | S | L | I | Z | V | ASG +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: R = A/B register (0/1) E = SEZ S = SS* L = SL* I = IN* Z = SZ* V = RSS 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 1 | 0 0 0 | R | 1 | H | I/O op | select code | IOG +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: R = A/B register (0/1) H = hold/clear flag (0/1) An I/O group instruction controls the device specified by the select code. Depending on the opcode, the instruction may set or clear the device flag, start or stop I/O, or read or write data. 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 1 | 0 0 0 | | 0 | eau op | 0 0 0 0 0 0 | EAU +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 1 | 0 0 0 | | 0 | eau shift/rotate op | shift count | EAU +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ MAC ops decode when bits 15-12 and 10 are 1 000 0. Bits 11 and 9-0 determine the specific EAU instruction. 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 1 | 0 0 0 | R | 0 1 | module | operation | UIG +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: R = A/B register (0/1) In simulation, I/O devices are modelled by substituting software states for I/O backplane signals. The set of signals generated by I/O instructions and DMA cycles is dispatched to the target device for action. Backplane signals are processed sequentially. For example, the "STC sc,C" instruction generates the "set control" and the "clear flag" signals that are processed in that order. CPU interrupt signals are modelled as three parallel arrays: - device request priority as bit vector dev_prl [2] [31..0] - device interrupt requests as bit vector dev_irq [2] [31..0] - device service requests as bit vector dev_srq [2] [31..0] Each array forms a 64-bit vector, with bits 0-31 of the first element corresponding to select codes 00-37 octal, and bits 0-31 of the second element corresponding to select codes 40-77 octal. The HP 21xx/1000 interrupt structure is based on the PRH, PRL, IRQ, and IAK signals. PRH indicates that no higher-priority device is interrupting. PRL indicates to lower-priority devices that a given device is not interrupting. IRQ indicates that a given device is requesting an interrupt. IAK indicates that the given device's interrupt request is being acknowledged. PRH and PRL form a hardware priority chain that extends from interface to interface on the backplane. We model just PRL, as PRH is calculated from the PRLs of higher-priority devices. Typical I/O devices have a flag, flag buffer, and control flip-flops. If a device's flag, flag buffer, and control bits are set, and the device is the highest priority on the interrupt chain, it requests an interrupt by asserting IRQ. When the interrupt is acknowledged with IAK, the flag buffer is cleared, preventing further interrupt requests from that device. The combination of flag and control set blocks interrupts from lower priority devices. Service requests are used to trigger the DMA service logic. Setting the device flag typically also sets SRQ, although SRQ may be calculated independently. The simulator provides three stop conditions related to instruction execution that may be enabled with a SET CPU STOP= command: Action ------ ------------------------------------------ UNIMPL stop on an unimplemented instruction UNDEF stop on an undefined instruction UNSC stop on an access to an unused select code IOERR stop on an unreported I/O error If an enabled stop condition is detected, execution ceases with the instruction pending, and control returns to the SCP prompt. When simulation stops, execution may be resumed in two ways. If the cause of the stop has not been remedied and the stop has not been disabled, resuming execution with CONTINUE, STEP, GO, or RUN will cause the stop to occur again. Alternately, specifying the "-B" switch with any of the preceding commands will resume execution while bypassing the stop for the current instruction. The UNIMPL option stops the simulator if execution is attempted of an instruction provided by a firmware option that is not currently installed (e.g., a DAD instruction when the double-integer firmware is not installed) or of an opcode provided by an installed option but not assigned to an instruction (e.g., opcode 105335 from the double-integer firmware). Bypassing the stop will execute the instruction as a NOP (no-operation). The UNDEF option stops the simulator if execution is attempted of an instruction containing a decoded reserved bit pattern other than that defined in the Operating and Reference manual for the CPU. For example, opcodes 101700 and 105700 are not listed as DMS instructions, but they execute as XMM instructions, rather than as NOP. The intent of this stop is to catch instructions containing reserved fields with values that change the meaning of those instructions. Bypassing the stop will decode and execute the instruction in the same manner as the selected CPU. The UNSC option stops the simulator if an I/O instruction addresses a select code that is not assigned to an enabled device (equivalent to an empty hardware I/O backplane slot). Bypassing the stop will read the floating S-bus or I/O-bus for LIA/B and MIA/B instructions or do nothing for all other instructions. The IOERR option stops the simulator if an I/O error condition exists for a device that does not report this status to the CPU. For example, the paper tape reader device (PTR) does not report "no tape loaded" status, and the processor interconnect device (IPL) does not report "cable disconnected." In both cases, I/O to the device will simply hang with no indication of the problem. Enabling the IOERR option will stop the simulator with an error indication for these devices. In addition, a simulation stop will occur if an indirect addressing chain exceeds the maximum length specified by a SET CPU INDIR= command. Memory addresses may be indirect to indicate that the values point to the target addresses rather than contain the target addresses. The target of an indirect address may itself be indirect, and the CPU follows this chain of addresses until it finds a direct address. Indirect addressing is typically only one or two levels deep, but if the chain loops back on itself (e.g., if an indirect address points at itself), then instruction execution will hang. The limit may be set to any number of levels up to 32,768. This is the absolute maximum number of levels that can be created without an infinite loop -- each location in memory points to the next one except for the last, which contains the target value. In practice, anything over a few levels likely represents a programming error. The default setting is 16 levels. In addition to the CPU, this module simulates the 12578A/12607B/12895A Direct Memory Access and 12897B Dual-Channel Port Controller devices (hereafter, "DMA"). These controllers permit the CPU to transfer data directly between an I/O device and memory on a cycle-stealing basis. Depending on the CPU, the device interface, and main memory speed, DMA is capable of transferring data blocks from 1 to 32,768 words in length at rates between 500,000 and 1,000,000 words per second. The 2114 supports a single DMA channel. All other CPUs support two DMA channels. DMA is programmed by setting three control words via two select codes: 2 and 6 for channel 1, and 3 and 7 for channel 2. During simultaneous transfers, channel 1 has priority over channel 2. Otherwise, the channels are identical. Channel programming involves setting three control words, as follows: SC 06 Control Word 1 format: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | S | B | C | - - - - - - - | device select code | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: S = assert STC during each cycle B = enable byte packing and unpacking (12578A only) C = assert CLC at the end of the block transfer SC 02 Control Word 2/3 format: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | D | starting memory address | word 2 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | negative word count | word 3 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: D = transfer direction is out of/into memory (0/1) Control word 2 is stored if the control flip-flop of select code 2 is clear, i.e., if the OTA/B is preceded by CLC; control word 3 is stored if the flip-flop is set by a preceding STC. The 12607B supports 14-bit addresses and 13-bit word counts. The 12578A supports 15-bit addresses and 14-bit word counts. The 12895A and 12897B support 15-bit addresses and 16-bit word counts. DMA is started by setting the control flip-flop on select code 6. DMA completion is indicated when the flag flip-flop sets on select code 8, which causes an interrupt if enabled. This module also simulates the 12581A/12892B Memory Protect devices for the 2116 and 1000 M/E/F-Series, respectively, and the memory protect feature that is standard equipment for the 2100. MP is addressed via select code 5 and provides a fence register that holds the address of the start of unprotected memory and a violation register that holds the address of the instruction that has caused a memory protect interrupt, as follows: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 0 | starting address of unprotected memory | fence +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 0 | violating instruction address | violation +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ After setting the fence regiater with an OTA 5 or OTB 5 instruction, MP is enabled by an STC 5. This module also simulates the 12731A Memory Expansion Module for the 1000 M/E/F-Series machines. The MEM provides mapping of the 32 1024-word logical memory pages into a one-megaword physical memory. Four separate maps are provided: system, user, DCPC port A, and DCPC port B. The MEM is controlled by the associated Dynamic Mapping System instructions and contains status and violation registers, as follows: MEM Status Register: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | I | M | E | U | P | B | base page fence address | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: I = MEM disabled/enabled (0/1) at last interrupt M = System/user map (0/1) selected at last interrupt E = MEM disabled/enabled (0/1) currently U = System/user map (0/1) selected currently P = Protected mode disabled/enabled (0/1) currently B = Base-page portion mapped (0/1 = above/below the fence) MEM Violation Register: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | R | W | B | P | - - - - | S | E | M | map address | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ Where: R = Read violation W = Write violation B = Base-page violation P = Privileged instruction violation S = ME bus disabled/enabled (0/1) at violation E = MEM disabled/enabled (0/1) at violation M = System/user map (0/1) selected at violation The CPU simulator provides extensive tracing capabilities that may be enabled with the SET DEBUG and SET CPU DEBUG= commands. The trace options that may be specified are: Trace Action ----- ------------------------------------------- INSTR trace instructions executed DATA trace memory data accesses FETCH trace memory instruction fetches REG trace registers OPND trace instruction operands EXEC trace matching instruction execution states A section of an example trace is: >>CPU instr: S 0002 05735 103101 CLO >>CPU fetch: S 0002 05736 000036 instruction fetch >>CPU reg: - **** 01011 042200 A 177777, B 000000, X 177777, Y 000000, e o i >>CPU instr: S 0002 05736 000036 SLA,ELA >>CPU fetch: S 0002 05737 102101 instruction fetch >>CPU reg: - **** 01011 042200 A 177776, B 000000, X 177777, Y 000000, E o i >>CPU instr: S 0002 05737 102101 STO >>CPU fetch: S 0002 05740 002400 instruction fetch >>CPU reg: - **** 01011 042200 A 177776, B 000000, X 177777, Y 000000, E O i >>CPU instr: S 0002 05755 102100 STF 0 >>CPU fetch: S 0002 05756 102705 instruction fetch >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I >>CPU instr: S 0002 05756 102705 STC 5 >>CPU fetch: S 0002 05757 105736 instruction fetch >>CPU reg: P **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I >>CPU instr: S 0002 05757 105736 UJP 2111 >>CPU fetch: S 0002 05760 002111 instruction fetch >>CPU fetch: U 0001 02111 026111 instruction fetch >>CPU reg: P **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I >>CPU instr: U 0001 02111 026111 JMP 2111 >>CPU instr: U 0001 02111 000011 interrupt >>CPU fetch: S 0000 00011 115013 instruction fetch >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I >>CPU reg: - **** ***** ****** MPF 000000, MPV 002111, MES 163011, MEV 030000 >>CPU instr: S 0000 00011 115013 JSB 1013,I >>CPU data: S 0000 01013 005557 data read >>CPU data: S 0002 05557 002111 data write >>CPU fetch: S 0002 05560 103100 instruction fetch >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O I >>CPU instr: S 0002 05560 103100 CLF 0 >>CPU fetch: S 0002 05561 105714 instruction fetch >>CPU reg: - **** 01011 042200 A 177777, B 177777, X 177777, Y 000000, E O i >>CPU exec: ******************** >>CPU reg: P **** 01567 000000 A 100036, B 000100, X 000100, Y 074000, E o I >>CPU instr: U 0220 07063 105240 .PMAP >>CPU data: U 0000 01776 000227 unprotected read >>CPU data: U 0227 76100 000233 data read >>CPU opnd: * **** 07065 105240 return location is P+2 (no error) >>CPU fetch: U 0220 07065 127055 instruction fetch >>CPU reg: P **** 01567 000000 A 100037, B 000101, X 000100, Y 074000, e o I The INSTR option traces instruction executions and interrupts. Each instruction is printed in symbolic form before it is executed. The DATA option traces reads from and writes to memory. Each access is classified by its usage type as "data" (using the current or alternate map with access protection) or "unprotected" (using a specified map without protection). The FETCH option traces instruction fetches from memory. Reads of the additional words in a multiword instruction, such as the target address of a DLD (double load) instruction, are also classified as fetches. The REG option traces register values. Two sets of registers are printed. After executing each instruction, the working registers (A, B, E, O, S, and, for 1000 CPUs, X and Y) and the state of the interrupt system (on or off) are printed. After executing an instruction that may alter the Memory Protect or Memory Expansion Module state, the MP fence and violation registers, the MEM status and violation registers, and the current protection state are printed. The OPND option traces operand values. Some instructions that take memory and register operands that are difficult to decode from DATA or REG traces present the operand values in a higher-level format. The operand data and value presented are specific to the instruction; see the instruction executor comments for details. The EXEC option traces the execution of instructions that match user-specified criteria. When a match occurs, all CPU trace options are turned on for the duration of the execution of the matched instruction. The prior trace settings are restored when a match fails. This option allows detailed tracing of specified instructions while minimizing the log file size compared to a full instruction trace. The various trace formats are interpreted as follows: >>CPU instr: U 0045 10341 016200 LDA 11200 ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~ | | | | | | | | | +-- instruction mnemonic | | | +---------- octal data (instruction opcode) | | +------------------ octal logical address (P register) | +----------------------- octal physical page number +--------------------------- memory map (S/U/- system/user/disabled) >>CPU instr: U 0045 10341 000011 interrupt ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~ | | | | | | | | | +-- interrupt classification | | | +---------- octal device number (CIR register) | | +------------------ octal logical address at interrupt (P register) | +----------------------- octal physical page number at interrupt +--------------------------- memory map (S/U/- system/user/disabled) >>CPU fetch: - 0000 10341 016200 instruction fetch >>CPU data: U 0013 01200 123003 data read >>CPU data: S 0013 01200 017200 unprotected write ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~ | | | | | | | | | +-- memory access classification | | | +------------ octal data (memory contents) | | +-------------------- octal logical address (effective address) | +------------------------- octal physical page number +----------------------------- memory map (S/U/A/B/- system/user/port A/port B/disabled) >>CPU reg: P .... 01535 040013 A 123003, B 001340, X 000000, Y 000000, e O I ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | | | | | +-- A, B, X, Y, E, O, interrupt system registers | | | | (lower/upper case = 0/1 or off/on) | | | +------------ S register | | +-------------------- MEM fence | +------------------------- +----------------------------- protection state (P/- protected/unprotected) >>CPU reg: P .... ..... ...... MPF 00000, MPV 000000, MES 000000, MEV 000000 ~ ~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | | | | | +-- memory protect fence and violation registers | | | | memory expansion status and violation registers | | | +------------ | | +-------------------- | +------------------------- +----------------------------- protection state (P/- protected/unprotected) >>CPU opnd: . .... 36002 101475 return location is P+3 (error EM21) >>CPU opnd: . .... 22067 105355 entry is for a dynamic mapping violation ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | +-- operand-specific value | +------------ operand-specific octal data +-------------------- octal logical address (P register) Implementation notes: 1. The simulator is fast enough, compared to the run-time of the longest instructions, for interruptibility not to matter. However, the HP diagnostics explicitly test interruptibility in the EIS and DMS instructions and in long indirect address chains. Accordingly, the simulator does "just enough" to pass these tests. In particular, if an interrupt is pending but deferred at the beginning of an interruptible instruction, the interrupt is taken at the appropriate point; but there is no testing for new interrupts during execution (that is, the event timer is not called). */ #include "hp2100_defs.h" #include "hp2100_cpu.h" #include "hp2100_cpu1.h" /* External data */ extern DIB clk_dib; /* CLK DIB for idle check */ extern DIB ptr_dib; /* PTR DIB for BBL configuration */ extern const BOOT_ROM ptr_rom, dq_rom, ms_rom, ds_rom; /* boot ROMs for cpu_boot routine */ /* CPU program constants */ /* Command line switches */ #define ALL_MAPMODES (SWMASK ('S') | SWMASK ('U') | SWMASK ('P') | SWMASK ('Q')) /* RTE base-page addresses */ static const uint32 xeqt = 0001717; /* XEQT address */ static const uint32 tbg = 0001674; /* TBG address */ /* DOS base-page addresses */ static const uint32 m64 = 0000040; /* constant -64 address */ static const uint32 p64 = 0000067; /* constant +64 address */ /* CPU global SCP data definitions */ REG *sim_PC = NULL; /* the pointer to the P register */ /* CPU global data structures */ /* CPU registers */ HP_WORD ABREG [2] = { 0, 0}; /* A and B registers */ HP_WORD PR = 0; /* P register */ HP_WORD SR = 0; /* S register */ HP_WORD MR = 0; /* M register */ HP_WORD TR = 0; /* T register */ HP_WORD XR = 0; /* X register */ HP_WORD YR = 0; /* Y register */ uint32 E = 0; /* E register */ uint32 O = 0; /* O register */ HP_WORD IR = 0; /* Instruction Register */ HP_WORD CIR = 0; /* Central Interrupt Register */ /* CPU global state */ FLIP_FLOP ion = CLEAR; /* interrupt enable */ t_bool ion_defer = FALSE; /* interrupt defer */ t_stat cpu_ss_unimpl = SCPE_OK; /* status return for unimplemented instruction execution */ t_stat cpu_ss_undef = SCPE_OK; /* status return for undefined instruction execution */ t_stat cpu_ss_unsc = SCPE_OK; /* status return for I/O to an unassigned select code */ t_stat cpu_ss_ioerr = SCPE_OK; /* status return for an unreported I/O error */ t_stat cpu_ss_inhibit = SCPE_OK; /* CPU stop inhibition mask */ UNIT *cpu_ioerr_uptr = NULL; /* pointer to a unit with an unreported I/O error */ uint16 pcq [PCQ_SIZE] = { 0 }; /* PC queue (must be 16-bits wide for REG array entry) */ uint32 pcq_p = 0; /* PC queue ptr */ REG *pcq_r = NULL; /* PC queue reg ptr */ uint32 cpu_configuration; /* the current CPU option set and model */ uint32 cpu_speed = 1; /* the CPU speed, expressed as a multiplier of a real machine */ uint32 dev_prl [2] = { ~0u, ~0u }; /* device priority low bit vector */ uint32 dev_irq [2] = { 0u, 0u }; /* device interrupt request bit vector */ uint32 dev_srq [2] = { 0u, 0u }; /* device service request bit vector */ /* Main memory global state */ MEMORY_WORD *M = NULL; /* pointer to allocated memory */ /* Memory Expansion Unit global state */ uint32 dms_enb = 0; /* dms enable */ uint32 dms_ump = 0; /* dms user map */ HP_WORD dms_sr = 0; /* dms status reg */ /* CPU local state */ static HP_WORD saved_MR = 0; /* M-register value between SCP commands */ static uint32 fwanxm = 0; /* first word addr of nx mem */ static uint32 jsb_plb = 2; /* protected lower bound for JSB */ static uint32 exec_mask = 0; /* the current instruction execution trace mask */ static uint32 exec_match = D16_UMAX; /* the current instruction execution trace matching value */ static uint32 indirect_limit = 16; /* the indirect chain length limit */ /* Memory Expansion Unit local state */ static HP_WORD dms_vr = 0; /* dms violation reg */ static uint16 dms_map [MAP_NUM * MAP_LNT] = { 0 }; /* dms maps (must be 16-bits wide for REG array entry) */ /* CPU local data structures */ /* Interrupt deferral table (1000 version) */ static t_bool defer_tab [] = { /* deferral table, indexed by I/O sub-opcode */ FALSE, /* soHLT */ TRUE, /* soFLG */ TRUE, /* soSFC */ TRUE, /* soSFS */ FALSE, /* soMIX */ FALSE, /* soLIX */ FALSE, /* soOTX */ TRUE /* soCTL */ }; /* Basic Binary Loader */ static const BOOT_ROM bbl = { 0107700, 0063770, 0106501, 0004010, 0002400, 0006020, 0063771, 0073736, 0006401, 0067773, 0006006, 0027717, 0107700, 0102077, 0027700, 0017762, 0002003, 0027712, 0003104, 0073774, 0017762, 0017753, 0070001, 0073775, 0063775, 0043772, 0002040, 0027751, 0017753, 0044000, 0000000, 0002101, 0102000, 0037775, 0037774, 0027730, 0017753, 0054000, 0027711, 0102011, 0027700, 0102055, 0027700, 0000000, 0017762, 0001727, 0073776, 0017762, 0033776, 0127753, 0000000, 0103710, 0102310, 0027764, 0102510, 0127762, 0173775, 0153775, 0100100, 0177765, 0000000, 0000000, 0000000, 0000000 }; #define BBL_FWA 072 /* BBL location to store negative FWA */ /* CPU features table. The feature table is used to validate CPU feature changes within the subset of features supported by a given CPU. Features in the typical list are enabled when the CPU model is selected. If a feature appears in the typical list but NOT in the optional list, then it is standard equipment and cannot be disabled. If a feature appears in the optional list, then it may be enabled or disabled as desired by the user. */ struct FEATURE_TABLE { /* CPU model feature table: */ uint32 typ; /* - typical features */ uint32 opt; /* - optional features */ uint32 maxmem; /* - maximum memory */ }; static struct FEATURE_TABLE cpu_features [] = { /* features indexed by CPU model */ { UNIT_DMA | UNIT_MP, /* UNIT_2116 */ UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_EAU, 32 * 1024 }, { UNIT_DMA, /* UNIT_2115 */ UNIT_PFAIL | UNIT_DMA | UNIT_EAU, 8 * 1024 }, { UNIT_DMA, /* UNIT_2114 */ UNIT_PFAIL | UNIT_DMA, 16 * 1024 }, { 0, 0, 0 /* unused model */ }, { UNIT_PFAIL | UNIT_MP | UNIT_DMA | UNIT_EAU, /* UNIT_2100 */ UNIT_DMA | UNIT_FP | UNIT_IOP | UNIT_FFP, 32 * 1024 }, { 0, 0, 0 /* unused model */ }, { 0, 0, 0 /* unused model */ }, { 0, 0, 0 /* unused model */ }, { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_M */ UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | UNIT_IOP | UNIT_FFP | UNIT_DS, 1024 * 1024 }, { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_E */ UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | UNIT_IOP | UNIT_FFP | UNIT_DBI | UNIT_DS | UNIT_EMA_VMA, 1024 * 1024 }, { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | /* UNIT_1000_F */ UNIT_FFP | UNIT_DBI | UNIT_DMS, UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS | UNIT_VIS | UNIT_DS | UNIT_SIGNAL | UNIT_EMA_VMA, 1024 * 1024 } }; /* CPU local SCP support routine declarations */ static IOHANDLER cpuio; static IOHANDLER ovflio; static IOHANDLER pwrfio; static t_stat cpu_examine (t_value *eval, t_addr address, UNIT *uptr, int32 switches); static t_stat cpu_deposit (t_value value, t_addr address, UNIT *uptr, int32 switches); static t_stat cpu_reset (DEVICE *dptr); static t_stat cpu_boot (int32 unitno, DEVICE *dptr); static t_stat set_stops (UNIT *uptr, int32 option, CONST char *cptr, void *desc); static t_stat set_size (UNIT *uptr, int32 new_size, CONST char *cptr, void *desc); static t_stat set_model (UNIT *uptr, int32 new_model, CONST char *cptr, void *desc); static t_stat set_option (UNIT *uptr, int32 option, CONST char *cptr, void *desc); static t_stat clear_option (UNIT *uptr, int32 option, CONST char *cptr, void *desc); static t_stat set_loader (UNIT *uptr, int32 enable, CONST char *cptr, void *desc); static t_stat set_exec (UNIT *uptr, int32 option, CONST char *cptr, void *desc); static t_stat show_stops (FILE *st, UNIT *uptr, int32 val, CONST void *desc); static t_stat show_model (FILE *st, UNIT *uptr, int32 val, CONST void *desc); static t_stat show_exec (FILE *st, UNIT *uptr, int32 val, CONST void *desc); static t_stat show_speed (FILE *st, UNIT *uptr, int32 val, CONST void *desc); /* CPU local utility routine declarations */ static t_stat ea (HP_WORD IR, HP_WORD *address, uint32 irq); static HP_WORD srg_uop (HP_WORD value, HP_WORD operation); static t_stat machine_instruction (HP_WORD IR, t_bool iotrap, uint32 irq_pending, uint32 *idle_save); static t_bool check_deferral (uint32 irq_sc); static uint32 map_address (HP_WORD logical, int32 switches); static t_bool mem_is_empty (uint32 starting_address); /* Memory Expansion Unit local utility routine declarations */ static t_bool is_mapped (uint32 address); static uint32 meu_map (HP_WORD address, uint32 map, HP_WORD prot); /* CPU SCP data structures */ /* Device information blocks */ static DIB cpu_dib = { /* CPU select code 0 */ &cpuio, /* device interface */ CPU, /* select code */ 0 /* card index */ }; static DIB ovfl_dib = { /* Overflow select code 1 */ &ovflio, /* device interface */ OVF, /* select code */ 0 /* card index */ }; static DIB pwrf_dib = { /* Power Fail select code 4 */ &pwrfio, /* device interface */ PWR, /* select code */ 0 /* card index */ }; /* Unit list. The CPU unit holds the main memory capacity. Implementation notes: 1. The unit structure must be global for other modules to access the unit flags, which describe the installed options, and to obtain the memory size via the MEMSIZE macro, which references the "capac" field. */ UNIT cpu_unit = { UDATA (NULL, UNIT_FIX | UNIT_BINK, 0) }; /* Register list. The CPU register list exposes the machine registers for user inspection and modification. Implementation notes: 1. All registers that reference variables of type HP_WORD must have the REG_FIT flag for proper access if HP_WORD is a 16-bit type. 2. The REG_X flag indicates that the register may be displayed in symbolic form. */ static REG cpu_reg [] = { /* Macro Name Location Radix Width Offset Depth Flags */ /* ------ --------- ------------------ ----- ----- -------- ----------------- ----------------- */ { ORDATA (P, PR, 15) }, { ORDATA (A, AR, 16), REG_X }, { ORDATA (B, BR, 16), REG_X }, { ORDATA (M, MR, 15) }, { ORDATA (T, TR, 16), REG_RO | REG_X }, { ORDATA (X, XR, 16), REG_X }, { ORDATA (Y, YR, 16), REG_X }, { ORDATA (S, SR, 16), REG_X }, { FLDATA (E, E, 0) }, { FLDATA (O, O, 0) }, { ORDATA (CIR, CIR, 6) }, { FLDATA (ION, ion, 0) }, { FLDATA (ION_DEFER, ion_defer, 0) }, { FLDATA (DMSENB, dms_enb, 0) }, { FLDATA (DMSCUR, dms_ump, VA_N_PAG) }, { ORDATA (DMSSR, dms_sr, 16) }, { ORDATA (DMSVR, dms_vr, 16) }, { BRDATA (DMSMAP, dms_map, 8, 16, MAP_NUM * MAP_LNT) }, { ORDATA (IOPSP, iop_sp, 16) }, { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_CIRC | REG_RO }, { ORDATA (IR, IR, 16), REG_HRO }, { ORDATA (PCQP, pcq_p, 6), REG_HRO }, { ORDATA (JSBPLB, jsb_plb, 32), REG_HRO }, { ORDATA (SAVEDMR, saved_MR, 32), REG_HRO }, { ORDATA (FWANXM, fwanxm, 32), REG_HRO }, { ORDATA (CONFIG, cpu_configuration, 32), REG_HRO }, { ORDATA (WRU, sim_int_char, 8), REG_HRO }, { ORDATA (BRK, sim_brk_char, 8), REG_HRO }, { ORDATA (DEL, sim_del_char, 8), REG_HRO }, { BRDATA (PRL, dev_prl, 8, 32, 2), REG_HRO }, { BRDATA (IRQ, dev_irq, 8, 32, 2), REG_HRO }, { BRDATA (SRQ, dev_srq, 8, 32, 2), REG_HRO }, { NULL } }; /* Modifier list. Implementation notes: 1. The 21MX monikers are deprecated in favor of the 1000 designations. See the "HP 1000 Series Naming History" on the back inside cover of the Technical Reference Handbook. 2. Each CPU option requires three modifiers. The two regular modifiers control the setting and printing of the option, while the extended modifier controls clearing the option. The latter is necessary because the option must be checked before confirming the change, and so the option value must be passed to the validation routine. */ static MTAB cpu_mod [] = { /* Mask Value Match Value Print String Match String Validation Display Descriptor */ /* --------------- ----------- ------------ ------------ ------------- ----------- ----------------- */ { UNIT_MODEL_MASK, UNIT_2116, "", "2116", &set_model, &show_model, (void *) "2116" }, { UNIT_MODEL_MASK, UNIT_2115, "", "2115", &set_model, &show_model, (void *) "2115" }, { UNIT_MODEL_MASK, UNIT_2114, "", "2114", &set_model, &show_model, (void *) "2114" }, { UNIT_MODEL_MASK, UNIT_2100, "", "2100", &set_model, &show_model, (void *) "2100" }, { UNIT_MODEL_MASK, UNIT_1000_E, "", "1000-E", &set_model, &show_model, (void *) "1000-E" }, { UNIT_MODEL_MASK, UNIT_1000_E, NULL, "21MX-E", &set_model, &show_model, (void *) "1000-E" }, { UNIT_MODEL_MASK, UNIT_1000_M, "", "1000-M", &set_model, &show_model, (void *) "1000-M" }, { UNIT_MODEL_MASK, UNIT_1000_M, NULL, "21MX-M", &set_model, &show_model, (void *) "1000-M" }, #if defined (HAVE_INT64) { UNIT_MODEL_MASK, UNIT_1000_F, "", "1000-F", &set_model, &show_model, (void *) "1000-F" }, #endif { UNIT_EAU, UNIT_EAU, "EAU", "EAU", &set_option, NULL, NULL }, { UNIT_EAU, 0, "no EAU", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_EAU, NULL, "NOEAU", &clear_option, NULL, NULL }, { UNIT_FP, UNIT_FP, "FP", "FP", &set_option, NULL, NULL }, { UNIT_FP, 0, "no FP", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_FP, NULL, "NOFP", &clear_option, NULL, NULL }, { UNIT_IOP, UNIT_IOP, "IOP", "IOP", &set_option, NULL, NULL }, { UNIT_IOP, 0, "no IOP", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_IOP, NULL, "NOIOP", &clear_option, NULL, NULL }, { UNIT_DMS, UNIT_DMS, "DMS", "DMS", &set_option, NULL, NULL }, { UNIT_DMS, 0, "no DMS", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_DMS, NULL, "NODMS", &clear_option, NULL, NULL }, { UNIT_FFP, UNIT_FFP, "FFP", "FFP", &set_option, NULL, NULL }, { UNIT_FFP, 0, "no FFP", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_FFP, NULL, "NOFFP", &clear_option, NULL, NULL }, { UNIT_DBI, UNIT_DBI, "DBI", "DBI", &set_option, NULL, NULL }, { UNIT_DBI, 0, "no DBI", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_DBI, NULL, "NODBI", &clear_option, NULL, NULL }, { UNIT_EMA_VMA, UNIT_EMA, "EMA", "EMA", &set_option, NULL, NULL }, { MTAB_XDV, UNIT_EMA, NULL, "NOEMA", &clear_option, NULL, NULL }, { UNIT_EMA_VMA, UNIT_VMAOS, "VMA", "VMA", &set_option, NULL, NULL }, { MTAB_XDV, UNIT_VMAOS, NULL, "NOVMA", &clear_option, NULL, NULL }, { UNIT_EMA_VMA, 0, "no EMA/VMA", NULL, &set_option, NULL, NULL }, #if defined (HAVE_INT64) { UNIT_VIS, UNIT_VIS, "VIS", "VIS", &set_option, NULL, NULL }, { UNIT_VIS, 0, "no VIS", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_VIS, NULL, "NOVIS", &clear_option, NULL, NULL }, { UNIT_SIGNAL, UNIT_SIGNAL, "SIGNAL", "SIGNAL", &set_option, NULL, NULL }, { UNIT_SIGNAL, 0, "no SIGNAL", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_SIGNAL, NULL, "NOSIGNAL", &clear_option, NULL, NULL }, #endif /* Future microcode support. { UNIT_DS, UNIT_DS, "DS", "DS", &set_option, NULL, NULL }, { UNIT_DS, 0, "no DS", NULL, NULL, NULL, NULL }, { MTAB_XDV, UNIT_DS, NULL, "NODS", &clear_option, NULL, NULL }, */ /* Entry Flags Value Print String Match String Validation Display Descriptor */ /* ------------------- ----------- ------------ --------------- ------------- -------------- ---------- */ { MTAB_XDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle, NULL }, { MTAB_XDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL, NULL }, { MTAB_XDV, 1, NULL, "LOADERENABLE", &set_loader, NULL, NULL }, { MTAB_XDV, 0, NULL, "LOADERDISABLE", &set_loader, NULL, NULL }, { MTAB_XDV, 4 * 1024, NULL, "4K", &set_size, NULL, NULL }, { MTAB_XDV, 8 * 1024, NULL, "8K", &set_size, NULL, NULL }, { MTAB_XDV, 12 * 1024, NULL, "12K", &set_size, NULL, NULL }, { MTAB_XDV, 16 * 1024, NULL, "16K", &set_size, NULL, NULL }, { MTAB_XDV, 24 * 1024, NULL, "24K", &set_size, NULL, NULL }, { MTAB_XDV, 32 * 1024, NULL, "32K", &set_size, NULL, NULL }, { MTAB_XDV, 64 * 1024, NULL, "64K", &set_size, NULL, NULL }, { MTAB_XDV, 128 * 1024, NULL, "128K", &set_size, NULL, NULL }, { MTAB_XDV, 256 * 1024, NULL, "256K", &set_size, NULL, NULL }, { MTAB_XDV, 512 * 1024, NULL, "512K", &set_size, NULL, NULL }, { MTAB_XDV, 1024 * 1024, NULL, "1024K", &set_size, NULL, NULL }, { MTAB_XDV | MTAB_NMO, 1, "STOPS", "STOP", &set_stops, &show_stops, NULL }, { MTAB_XDV, 0, NULL, "NOSTOP", &set_stops, NULL, NULL }, { MTAB_XDV | MTAB_NMO, 2, "INDIR", "INDIR", &set_stops, &show_stops, NULL }, { MTAB_XDV | MTAB_NMO, 1, "EXEC", "EXEC", &set_exec, &show_exec, NULL }, { MTAB_XDV, 0, NULL, "NOEXEC", &set_exec, NULL, NULL }, { MTAB_XDV | MTAB_NMO, 0, "SPEED", NULL, NULL, &show_speed, NULL }, { 0 } }; /* Debugging trace list */ static DEBTAB cpu_deb [] = { { "INSTR", TRACE_INSTR }, /* trace instruction executions */ { "DATA", TRACE_DATA }, /* trace memory data accesses */ { "FETCH", TRACE_FETCH }, /* trace memory instruction fetches */ { "REG", TRACE_REG }, /* trace register values */ { "OPND", TRACE_OPND }, /* trace instruction operands */ { "EXEC", TRACE_EXEC }, /* trace matching instruction execution states */ { "NOOS", DEBUG_NOOS }, /* RTE-6/VM will not use OS firmware */ { NULL, 0 } }; /* Simulation stop list. The simulator can be configured to detect certain machine instruction conditions and stop execution when one of them occurs. Stops may be enabled or disabled individually with these commands: SET CPU STOP=