1 /* hp3000_cpu.c: HP 3000 Central Processing Unit simulator
2 
3    Copyright (c) 2016-2019, J. David Bryan
4 
5    Permission is hereby granted, free of charge, to any person obtaining a copy
6    of this software and associated documentation files (the "Software"), to deal
7    in the Software without restriction, including without limitation the rights
8    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9    copies of the Software, and to permit persons to whom the Software is
10    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 THE
18    AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22    Except as contained in this notice, the name of the author shall not be used
23    in advertising or otherwise to promote the sale, use or other dealings in
24    this Software without prior written authorization from the author.
25 
26    CPU          HP 3000 Series III Central Processing Unit
27 
28    09-Dec-19    JDB     Replaced debugging macros with tracing macros
29    20-Jun-19    JDB     Added wait time to process clock trace
30    08-Apr-19    JDB     Suppress stop messages for step and breakpoints in DO files
31    07-Apr-19    JDB     Moved breakpoint test before run/halt-mode test
32    21-Feb-19    JDB     Resuming into PAUS with pending IRQ now sets P correctly
33                         Moved "debug_save" from global to "sim_instr" local
34    06-Feb-19    JDB     Corrected trace report for simulation stop
35    27-Dec-18    JDB     Revised fall through comments to comply with gcc 7
36    05-Sep-17    JDB     Removed the -B (binary display) option; use -2 instead
37                         Changed REG_A (permit any symbolic override) to REG_X
38    19-Jan-17    JDB     Added comments describing the OPND and EXEC trace options
39    29_Dec-16    JDB     Changed the status mnemonic flag from REG_S to REG_T
40    07-Nov-16    JDB     Renamed cpu_byte_to_word_ea to cpu_byte_ea
41    03-Nov-16    JDB     Added zero offsets to the cpu_call_procedure calls
42    01-Nov-16    JDB     Added per-instruction trace capability
43    24-Oct-16    JDB     Renamed SEXT macro to SEXT16
44    22-Sep-16    JDB     Moved byte_to_word_address from hp3000_cpu_base.c
45    21-Sep-16    JDB     Added CIS/NOCIS option
46    01-Sep-16    JDB     Add power fail/power restore support
47    23-Aug-16    JDB     Add module interrupt support
48    14-Jul-16    JDB     Implemented the cold dump process
49                         Changed "loading" EXEC_STATE to "waiting"
50    11-Jul-16    JDB     Change "cpu_unit" from a UNIT to an array of one UNIT
51    08-Jun-16    JDB     Corrected %d format to %u for unsigned values
52    16-May-16    JDB     ACCESS_PROPERTIES.name is now a pointer-to-constant
53    13-May-16    JDB     Modified for revised SCP API function parameter types
54    24-Mar-16    JDB     Changed memory word type from uint16 to MEMORY_WORD
55    21-Mar-16    JDB     Changed cpu_ccb_table type from uint16 to HP_WORD
56    11-Mar-16    JDB     Fixed byte EA calculations with negative indexes
57    22-Dec-15    JDB     First release version
58    01-Apr-15    JDB     First successful run of MPE-V/R through account login
59    11-Dec-12    JDB     Created
60 
61    References:
62      - HP 3000 Series II System Microprogram Listing
63          (30000-90023, August 1976)
64      - HP 3000 Series II/III System Reference Manual
65          (30000-90020, July 1978)
66      - Machine Instruction Set Reference Manual
67          (30000-90022, June 1984)
68 
69 
70    The HP 3000 is a family of general-purpose business computers that were sold
71    by Hewlett-Packard from 1972 through 2001.  There are two major divisions
72    within this family: the "classic" 16-bit, stack-oriented CISC machines, and
73    the "Precision Architecture" 32-bit, register-oriented RISC machines that
74    succeeded them.  All machines run versions of MPE, the "Multiprogramming
75    Executive" operating system.
76 
77    Within the "classic" division, there are two additional subdivisions, based
78    on the method used for peripheral connections: the original "SIO" machines,
79    and the later "HP-IB" machines.  The I/O interfacing hardware differs between
80    the two types of machines, as do the privileged I/O machine instructions.
81    The user instruction sets are identical, as are the register sets visible to
82    the programmer.  The I/O drivers are different to account for the hardware
83    differences, and therefore they run slightly different versions of MPE.
84 
85    This implementation is a simulator for the classic SIO machines.  This group
86    consists of the 3000 CX, the Series I, Series II, and Series III; the last is
87    simulated here.  The CX and Series I, which is a repackaged CX, are
88    essentially subsets of the Series II/III -- a smaller instruction set,
89    limited memory size, and lower-precision floating-point instructions.
90    Simulation of these machines may be added in the future.  Future simulation
91    of the HP-IB machines (the Series 30 through 70) is desirable, as the latest
92    MPE versions run only on these machines, but documentation on the internals
93    of the HP-IB hardware controllers is nonexistent.
94 
95    The CX and Series I support 64K 16-bit words of memory.  The Series II
96    supports up to 256K, divided into four banks of 64K words each, and the
97    Series III extends this to 1024K words using 16 banks.  Memory is divided
98    into variable-length code and data segments, with the latter containing a
99    program's global data area and stack.
100 
101    Memory protection is accomplished by checking program, data, and stack
102    accesses against segment base and limit registers, which can be set only by
103    MPE.  Bounds violations cause automatic hardware traps to a handler routine
104    within MPE.  Some violations may be permitted; for example, a Stack Overflow
105    trap may cause MPE to allocate a larger stack and then restart the
106    interrupted instruction.  Almost all memory references are position-
107    independent, so moving segments to accommodate expansion requires only
108    resetting of the segment registers to point at the new locations.  Code
109    segments are fully reentrant and shareable, and both code and data are
110    virtual, as the hardware supports absent code and data segment traps.
111 
112    The classic 3000s are stack machines.  Most of the instructions operate on
113    the value on the top of the stack (TOS) or on the TOS and the next-to-the-top
114    of the stack (NOS).  To improve execution speed, the 3000 has a set of
115    hardware registers that are accessed as the first four locations at the top
116    of the stack, while the remainder of the stack locations reside in main
117    memory.  A hardware register renamer provides fast stack pushes and pops
118    without physically copying values between registers.
119 
120    In hardware, the stack registers are referenced internally as TR0-TR3 and
121    externally as RA-RD.  An access to the RA (TOS) register is translated by the
122    renamer to access TR0, TR1, etc. depending on which internal register is
123    designated as the current top of the stack.  For example, assume that RA
124    corresponds to TR0.  To push a new value onto the top of the stack, the
125    renamer is adjusted so that RA corresponds to TR1, and the new value is
126    stored there.  In this state, RB corresponds to TR0, the previous TOS (and
127    current NOS) value.  Additional pushes rename RA as TR2 and then TR3, with RB
128    being renamed to TR1 and then TR2, and similarly for RC and RD.  The number
129    of valid TOS registers is given by the value in the SR register, and the
130    first stack location in memory is given by the value in the SM register.
131    Pops reverse the sequence: a pop with RA corresponding to TR3 renames RA to
132    TR2, RB to TR1, etc.  When all four stack registers are in use, a push will
133    copy the value in RD to the top of the memory stack (SM + 1) before the
134    registers are renamed and the new value stored into RA.  Similarly, when all
135    four stack registers are empty, a pop simply decrements the SM register,
136    effectively deleting the top of the memory stack.
137 
138    Because of the renamer, the microcode can always use RA to refer to the top
139    of the stack, regardless of which internal TR register is being used, and
140    similarly for RB-RD.  Execution of each stack instruction begins with a
141    preadjustment, if needed, that loads the TOS registers that will be used by
142    the instruction from the top of the memory stack.  For example, if only RA
143    contains a value (i.e., the SR register value is 1), the ADD instruction,
144    which adds the values in RA and RB, will load RB with the value on the top of
145    the memory stack, the SR count will be incremented, and the SM register will
146    be decremented.  On the other hand, if both RA and RB contained values (SR >=
147    2), then no preadjustment would be required before the ADD instruction
148    microcode manipulated RA and RB.
149 
150    In simulation, the renamer is implemented by physically copying the values
151    between registers, as this is much faster than mapping via array index
152    values, as the hardware does.  A set of functions provides the support to
153    implement the hardware stack operations:
154 
155      cpu_push       - empty the TOS register (SR++, caller stores into RA)
156      cpu_pop        - delete the TOS register (SR--)
157      cpu_queue_up   - move from memory to the lowest TOS register (SR++, SM--)
158      cpu_queue_down - move from the lowest TOS register to memory (SR--, SM++)
159      cpu_flush      - move all stack registers to memory (SR = 0 on return)
160      cpu_adjust_sr  - queue up until the required SR count is reached
161      cpu_mark_stack - write a stack marker to memory
162 
163    The renamer is described in US Patent 3,737,871 (Katzman, "Stack Register
164    Renamer", June 1973).
165 
166    The MPE operating system is supported by special microcode features that
167    perform code and data segment mapping, segment access bounds checking,
168    privilege checking, etc.  The layout of certain in-memory tables is known to
169    both the OS and the microcode and is used to validate execution of
170    instructions.  For instance, every stack instruction is checked for a valid
171    access within the stack segment boundaries, which are set up by the OS
172    before program dispatch.  For this reason, the 3000 cannot be operated as a
173    "bare" machine, because these tables would not have been initialized.
174    Similarly, the "cold load" process by which the OS is loaded from storage
175    media into memory is entirely in microcode, as machine instructions cannot be
176    executed until the required tables are loaded into memory.
177 
178    This OS/microcode integration means that the microcode may detect conditions
179    that make continued execution impossible.  An example would be a not-present
180    segment fault for the segment containing the disc I/O driver.  If such a
181    condition is detected, the CPU does a "system halt."  This fatal microcode
182    error, distinct from a regular programmed halt, causes operation to cease
183    until the CPU is reset.
184 
185    The CPU hardware includes a free-running 16-bit process clock that increments
186    once per millisecond whenever a user program is executing.  MPE uses the
187    process clock to charge CPU usage to programs, and thereby to users, groups,
188    and accounts.  Instructions are provided to read (RCLK) and set (SCLK) the
189    process clock.
190 
191 
192    The data types supported by the instruction set are:
193 
194      - 8-bit unsigned byte
195      - 16-bit unsigned integer ("logical" format)
196      - 16-bit two's-complement integer
197      - 32-bit two's-complement integer
198      - 32-bit sign-magnitude floating point
199      - 64-bit sign-magnitude floating point
200 
201    Multi-word values are stored in memory with the most-significant words in the
202    lowest addresses.  The stack is organized in memory from lower to higher
203    addresses, so a value on the stack has its least-significant word on the top
204    of the stack.
205 
206    Machine instructions are initially decoded by a sub-opcode contained in the
207    four highest bits, as follows (note that the HP 3000 numbers bits from
208    left-to-right, i.e., bit 0 is the MSB and bit 15 is the LSB):
209 
210        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
211      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
212      | 0   0   0   0 |   1st stack opcode    |   2nd stack opcode    |  Stack
213      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
214 
215 
216        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
217      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
218      | 0   0   0   1 | X |   shift opcode    |      shift count      |  Shift
219      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
220 
221      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
222      | 0   0   0   1 | I |   branch opcode   |+/-|  P displacement   |  Branch
223      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
224 
225      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
226      | 0   0   0   1 | X |  bit test opcode  |     bit position      |  Bit Test
227      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
228 
229 
230        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
231      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
232      | 0   0   1   0 | 0   0   0   0 |  move op  | opts/S decrement  |  Move
233      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
234 
235      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
236      | 0   0   1   0 | 0   0   0   0 |  special op   | 0   0 | sp op |  Special
237      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
238 
239      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
240      | 0   0   1   0 | 0   0   0   1 |  option set   | option subset |  Firmware
241      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
242 
243      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
244      | 0   0   1   0 |  imm opcode   |       immediate operand       |  Immediate
245      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
246 
247      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
248      | 0   0   1   0 | field opcode  |    J field    |    K field    |  Field
249      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
250 
251      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
252      | 0   0   1   0 |  register op  | SK| DB| DL| Z |STA| X | Q | S |  Register
253      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
254 
255 
256        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
257      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
258      | 0   0   1   1 | 0   0   0   0 |  I/O opcode   |    K field    |  I/O
259      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
260 
261      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
262      | 0   0   1   1 | 0   0   0   0 |  cntl opcode  | 0   0 | cn op |  Control
263      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
264 
265      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
266      | 0   0   1   1 |  program op   |            N field            |  Program
267      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
268 
269      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
270      | 0   0   1   1 | immediate op  |       immediate operand       |  Immediate
271      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
272 
273      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
274      | 0   0   1   1 |   memory op   |        P displacement         |  Memory
275      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
276 
277      The memory, loop, and branch instructions occupy the remainder of the
278      sub-opcodes (04-17):
279 
280        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
281      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
282      |   memory op   | X | I |         mode and displacement         |  Memory
283      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
284                              | 0 | 0 |     P+ displacement 0-255     |
285                              +---+---+---+---+---+---+---+---+---+---+
286                              | 0 | 1 |     P- displacement 0-255     |
287                              +---+---+---+---+---+---+---+---+---+---+
288                              | 1 | 0 |    DB+ displacement 0-255     |
289                              +---+---+---+---+---+---+---+---+---+---+
290                              | 1 | 1 | 0 |   Q+ displacement 0-127   |
291                              +---+---+---+---+---+---+---+---+---+---+
292                              | 1 | 1 | 1 | 0 | Q- displacement 0-63  |
293                              +---+---+---+---+---+---+---+---+---+---+
294                              | 1 | 1 | 1 | 1 | S- displacement 0-63  |
295                              +---+---+---+---+---+---+---+---+---+---+
296 
297      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
298      |   memory op   | X | I | s |     mode and displacement         |   Memory
299      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
300                                  | 0 |    DB+ displacement 0-255     |
301                                  +---+---+---+---+---+---+---+---+---+
302                                  | 1 | 0 |   Q+ displacement 0-127   |
303                                  +---+---+---+---+---+---+---+---+---+
304                                  | 1 | 1 | 0 | Q- displacement 0-63  |
305                                  +---+---+---+---+---+---+---+---+---+
306                                  | 1 | 1 | 1 | S- displacement 0-63  |
307                                  +---+---+---+---+---+---+---+---+---+
308 
309      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
310      | 0   1   0   1 |loop op| 0 |+/-|    P-relative displacement    |  Loop
311      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
312 
313      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
314      | 1   1   0   0 | I | 0   1 | > | = | < | P+- displacement 0-31 |  Branch
315      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
316 
317    Optional firmware extension instruction sets occupy instruction codes
318    020400-020777, except for the DMUL (020570) and DDIV (020571) instructions
319    that are part of the base set, as follows:
320 
321        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
322      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
323      | 0   0   1   0 | 0   0   0   1 | 0   1   1   1 | 1   0   0 | x |  DMUL/DDIV
324      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
325 
326      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
327      | 0   0   1   0 | 0   0   0   1 | 0   0   0   0 | 1 | ext fp op |  Extended FP
328      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
329 
330      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
331      | 0   0   1   0 | 0   0   0   1 | 0   0   0   1 |    APL op     |  APL
332      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
333 
334      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
335      | 0   0   1   0 | 0   0   0   1 | 0   0   1   1 |   COBOL op    |  COBOL
336      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
337 
338      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
339      | 0   0   1   0 | 0   0   0   1 | 1 |  options  |  decimal op   |  Decimal
340      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
341 
342    Most instructions are defined by unique 16-bit codes that specify the
343    operations, operands, addressing modes, shift counts, etc.  For each of these
344    instructions, there is only one canonical form that encodes a given
345    instruction (or instruction pair, in the case of stack instructions).  For
346    example, the octal value 140003 is the only value that encodes the "BR P+3"
347    instruction.
348 
349    There are also instruction codes that contain one or more bits designated as
350    "reserved" in the Machine Instruction Set Reference Manual.  For some of
351    these instructions, the reserved bits do not affect instruction decoding.
352    Each instruction of this type has a defined canonical form -- typically with
353    the reserved bits set to zero -- but will execute identically if one of the
354    undefined forms is used.  For example, the "MOVE" instructions define bits
355    12-13 as 00, but the bits are not decoded, so values of 01, 10, and 11 for
356    these bits will result in identical execution.  Specifically, "MOVE 0" is
357    encoded canonically as octal value 020020, but the undefined codes 020024,
358    020030, and 020034 execute "MOVE 0" as well.
359 
360    For the rest of these instructions, the reserved bits are decoded and will
361    affect the instruction interpretation.  An example of this is the "IXIT"
362    instruction.  It also defines bits 12-13 as 00 (canonical encoding 020360),
363    but in this case the bits must be 00 for the instruction to execute; any
364    other value (e.g., undefined codes 020364, 020370, or 020374) executes as a
365    "PCN" instruction, whose canonical encoding is 020362.
366 
367    Finally, some codes are not assigned to any instructions, or they are
368    assigned to instructions that are supplied by optional firmware that is not
369    present in the machine.  These instruction codes are designated as
370    "unimplemented" and will cause Unimplemented Instruction traps if they are
371    executed.  Examples are the stack operation code 072 in either the left-hand
372    or right-hand position (i.e., instruction codes 0072xx and 00xx72), codes
373    020410-020415 if the Extended Instruction Set firmware option is not
374    installed, and codes 036000-036777.
375 
376    When the simulator examines the bit patterns of instructions to execute, each
377    will fall into one of four categories:
378 
379     1. Defined (canonical) instruction encodings.
380 
381     2. Undefined (non-canonical) instruction encodings, where reserved fields
382        are "don't care" bits (e.g., MOVE).
383 
384     3. Undefined (non-canonical) instruction encodings, where reserved fields
385        are decoded (e.g., IXIT).
386 
387     4. Unimplemented instruction encodings (e.g., stack opcode 072 or EADD with
388        no EIS installed).
389 
390    When examining memory or register values in instruction-mnemonic form, the
391    names of the canonical instructions in category 1 are displayed in uppercase,
392    as are the names of the non-canonical instructions in category 2.  The
393    non-canonical instruction names in category 3 are displayed in lowercase.
394    This is to indicate to the user that the instructions that will be executed
395    may not be the ones expected from the decoding.  Instruction names in
396    category 4 that correspond to supported firmware options are displayed in
397    uppercase, regardless of whether or not the option is enabled.  Category 4
398    encodings that do not correspond to instructions are displayed in octal.
399 
400    All of the base set instructions are one word in length.  Most of the
401    firmware extension instructions occupy one word as well, although some are
402    two words long.  If the first word of a two-word instruction is valid but the
403    second is not, an Unimplemented Instruction trap will occur, with P pointing
404    to the location after the second word.
405 
406 
407    The simulator provides four stop conditions related to instruction execution
408    that may be enabled with a SET CPU STOP=<stop> command:
409 
410      <stop>  Action
411      ------  ------------------------------------
412      LOOP    stop on an infinite loop
413      PAUSE   stop on a PAUS instruction
414      UNDEF   stop on an undefined instruction
415      UNIMPL  stop on an unimplemented instruction
416 
417    If an enabled stop condition is detected, execution ceases with the
418    instruction pending, and control returns to the SCP prompt.  When simulation
419    stops, execution may be resumed in two ways.  If the cause of the stop has
420    not been remedied and the stop has not been disabled, resuming execution with
421    CONTINUE, STEP, GO, or RUN will cause the stop to occur again.  Alternately,
422    specifying the "-B" switch with any of the preceding commands will resume
423    execution while bypassing the stop for the current instruction.
424 
425    The LOOP option stops the simulator if it attempts to execute an instruction
426    that enters an infinite loop (e.g., BR P+0).  The branch instructions TBA,
427    TBX, BCC, BR, BCY, BNCY, BOV, and BNOV result in an infinite loop if the
428    branch displacement is zero and the branch condition is true.  The remaining
429    branch instructions cannot result in an infinite loop, as they all modify the
430    CPU state and so eventually reach a point where they drop out of the loop.
431 
432    The PAUSE option stops the simulator if execution of a PAUS instruction is
433    attempted.  This instruction normally suspends instruction fetching until an
434    interrupt occurs.  Clearing the stop and resuming execution suspends the
435    fetch/execute process until an external interrupt occurs.  Resuming with the
436    stop bypassed continues execution with the instruction following the PAUS;
437    this is the same action that occurs when pressing the HALT button and then
438    the RUN button in hardware.
439 
440    The UNDEF option stops the simulator if execution of a non-canonical
441    instruction from decoding category 3 (i.e., an instruction containing a
442    decoded reserved bit pattern other than that defined in the Machine
443    Instruction Set manual) is attempted.  The intent is to catch instructions
444    containing reserved fields with values that change the meaning of those
445    instructions.  Bypassing the stop will decode and execute the instruction in
446    the same manner as the HP 3000 microcode.
447 
448    The UNIMPL option stops the simulator if execution of an instruction from
449    decoding category 4 is attempted.  Bypassing the stop will cause an
450    Unimplemented Instruction trap.  Instructions that depend on the presence of
451    firmware options are implemented if the option is present and unimplemented
452    if the option is absent.  For example, instruction code 020410 executes as
453    the EADD instruction if the Extended Instruction Set is enabled but is
454    unimplemented if the EIS is disabled.  It is displayed as EADD in either
455    case.
456 
457    The instructions in category 2 whose non-canonical forms do not cause an
458    UNDEF stop are:
459 
460            Canonical  Reserved
461      Inst  Encoding     Bits    Defined As    Decoded As
462      ----  ---------  --------  -----------   -----------
463      SCAN   010600     10-15    0 0 0 0 0 0   x x x x x x
464      TNSL   011600     10-15    0 0 0 0 0 0   x x x x x x
465      MOVE   020000     12-13        0 0           x x
466      MVB    020040     12-13        0 0           x x
467      MVBL   020100        13          0             x
468      SCW    020120        13          0             x
469      MVLB   020140        13          0             x
470      SCU    020160        13          0             x
471      CMPB   020240     12-13        0 0           x x
472      RSW    020300     12-14        0 0 0         x x x
473      LLSH   020301     12-14        0 0 0         x x x
474      PLDA   020320     12-14        0 0 0         x x x
475      PSTA   020321     12-14        0 0 0         x x x
476      LSEA   020340     12-13        0 0           x x
477      SSEA   020341     12-13        0 0           x x
478      LDEA   020342     12-13        0 0           x x
479      SDEA   020343     12-13        0 0           x x
480      PAUS   030020     12-15        0 0 0 0       x x x x
481 
482    The instructions in category 3 whose non-canonical forms cause an UNDEF stop
483    are:
484 
485            Canonical  Reserved
486      Inst  Encoding     Bits    Defined As  Decoded As
487      ----  ---------  --------  ----------  ----------
488      IXIT   020360     12-15     0 0 0 0     0 0 0 0
489      LOCK   020361     12-15     0 0 0 1     n n 0 1
490      PCN    020362     12-15     0 0 1 0     n n n 0
491      UNLK   020363     12-15     0 0 1 1     n n 1 1
492 
493      SED    030040     12-15     0 0 0 x     n n n x
494 
495      XCHD   030060     12-15     0 0 0 0     0 0 0 0
496      PSDB   030061     12-15     0 0 0 1     n n 0 1
497      DISP   030062     12-15     0 0 1 0     n n n 0
498      PSEB   030063     12-15     0 0 1 1     n n 1 1
499 
500      SMSK   030100     12-15     0 0 0 0     0 0 0 0
501      SCLK   030101     12-15     0 0 0 1     n n n n
502      RMSK   030120     12-15     0 0 0 0     0 0 0 0
503      RCLK   030121     12-15     0 0 0 1     n n n n
504 
505    Where:
506 
507      x = 0 or 1
508      n = any collective value other than 0
509 
510    In hardware, the SED instruction works correctly only if opcodes 030040 and
511    030041 are used.  Opcodes 030042-030057 also decode as SED, but the status
512    register is set improperly (the I bit is cleared, bits 12-15 are rotated
513    right twice and then ORed into the status register).  In simulation, opcodes
514    030042-030057 work correctly but will cause an UNDEF simulation stop if
515    enabled.
516 
517 
518    The CPU simulator provides extensive tracing capabilities that may be enabled
519    with the SET CONSOLE DEBUG=<filename> and SET CPU DEBUG=<trace> commands.
520    The trace options that may be specified are:
521 
522      Trace  Action
523      -----  -------------------------------------------
524      INSTR  trace instructions executed
525      DATA   trace memory data accesses
526      FETCH  trace memory instruction fetches
527      REG    trace registers
528      OPND   trace memory operands
529      EXEC   trace matching instruction execution states
530      PSERV  trace process clock service events
531 
532    A section of an example trace is:
533 
534      >>CPU fetch: 00.010342  020320    instruction fetch
535      >>CPU instr: 00.010341  000300  ZROX,NOP
536      >>CPU   reg: 00.006500  000000    X 000000, M i t r o c CCG
537      >>CPU fetch: 00.010343  041100    instruction fetch
538      >>CPU instr: 00.010342  020320  PLDA
539      >>CPU  data: 00.000000  001340    absolute read
540      >>CPU   reg: 00.006500  000001    A 001340, X 000000, M i t r o c CCG
541      >>CPU fetch: 00.010344  037777    instruction fetch
542      >>CPU instr: 00.010343  041100  LOAD DB+100
543      >>CPU  data: 00.002100  123003    data read
544      >>CPU   reg: 00.006500  000002    A 123003, B 001340, X 000000, M i t r o c CCL
545      >>CPU fetch: 00.010345  023404    instruction fetch
546      >>CPU instr: 00.010344  037777  ANDI 377
547      >>CPU   reg: 00.006500  000002    A 000003, B 001340, X 000000, M i t r o c CCG
548      >>CPU fetch: 00.010346  002043    instruction fetch
549      >>CPU instr: 00.010345  023404  MPYI 4
550      >>CPU   reg: 00.006500  000002    A 000014, B 001340, X 000000, M i t r o c CCG
551      >>CPU fetch: 00.010347  020320    instruction fetch
552 
553    The INSTR option traces instruction executions.  Each instruction is printed
554    before it is executed.  The two opcodes of a stack instruction are printed
555    together before the left-hand opcode is executed.  If the right-hand opcode
556    is not NOP, it is reprinted before execution, with dashes replacing the
557    just-executed left-hand opcode.
558 
559    The DATA option traces reads from and writes to memory.  Each access is
560    classified by the memory bank register that is paired with the specified
561    offset; they are: dma, absolute, program, data, and stack.  DMA accesses
562    derive their bank addresses from the banks specified in Set Bank I/O program
563    orders.  Absolute accesses always use bank 0.  Program, data, and stack
564    accesses use the bank addresses in the PBANK, DBANK, and SBANK registers,
565    respectively.
566 
567    The FETCH option traces instruction fetches from memory.  These accesses are
568    separated from those traced by the DATA option because fetches usually are of
569    little interest except when debugging the fetch/execute sequence.  Because
570    the HP 3000 has a two-stage pipeline, fetches load the NIR (Next Instruction
571    Register) with the instruction after the instruction to be executed from the
572    CIR (Current Instruction Register).
573 
574    The REG option traces register values.  Two sets of registers are printed.
575    After executing each instruction, the currently active TOS registers, the
576    index register, and the status register are printed.  After executing an
577    instruction that may alter the base registers, the program, data, and stack
578    segment base registers are printed.
579 
580    The OPND option traces memory byte operand values.  Some instructions take
581    memory and register operands that are difficult to decode from DATA or REG
582    traces.  This option presents these operands in a higher-level format.  The
583    memory bank and address values are always those of the operands.  The operand
584    data and values printed are specific to the instruction.  For example, the
585    ALGN instruction prints its source and target operands, digit counts, and
586    fraction counts, and the EDIT instruction displays its subprogram operations.
587 
588    The EXEC option traces the execution of instructions that match
589    user-specified criteria.  When a match occurs, all CPU trace options are
590    turned on for the duration of the execution of the matched instruction.  The
591    prior trace settings are restored when a match fails.  This option allows
592    detailed tracing of specified instructions while minimizing the log file size
593    compared to a full instruction trace.
594 
595    The PSERV option traces process clock event service entries.  Each trace
596    reports whether or not the CPU was executing on the Interrupt Control Stack
597    when the process clock ticked.  Execution on the ICS implies that the
598    operating system is executing.  As the process clock ticks every millisecond,
599    enabling PSERV tracing can quickly produce a large number of trace lines.
600 
601    The various trace formats are interpreted as follows:
602 
603      >>CPU instr: 00.010341  000300  ZROX,NOP
604                   ~~ ~~~~~~  ~~~~~~  ~~~~~~~~
605                   |    |       |       |
606                   |    |       |       +-- instruction mnemonic(s)
607                   |    |       +---------- octal data (instruction opcode)
608                   |    +------------------ octal address (P)
609                   +----------------------- octal bank (PBANK)
610 
611      >>CPU instr: 00.001240  000006  external interrupt
612      >>CPU instr: 00.023736  000000  unimplemented instruction trap
613                   ~~ ~~~~~~  ~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
614                   |    |       |       |
615                   |    |       |       +-- interrupt classification
616                   |    |       +---------- parameter
617                   |    +------------------ octal address (P) at interrupt
618                   +----------------------- octal bank (PBANK) at interrupt
619 
620 
621      >>CPU  data: 00.000000  001340    absolute read
622      >>CPU  data: 00.002100  123003    data read
623                   ~~ ~~~~~~  ~~~~~~    ~~~~~~~~~~~~~
624                   |    |       |         |
625                   |    |       |         +-- memory access classification
626                   |    |       +------------ octal data (memory contents)
627                   |    +-------------------- octal address (effective address)
628                   +------------------------- octal bank (PBANK, DBANK, or SBANK)
629 
630 
631      >>CPU fetch: 00.010342  020320    instruction fetch
632                   ~~ ~~~~~~  ~~~~~~    ~~~~~~~~~~~~~~~~~
633                   |    |       |         |
634                   |    |       |         +-- memory access classification
635                   |    |       +------------ octal data (instruction opcode)
636                   |    +-------------------- octal address (P + 1)
637                   +------------------------- octal bank (PBANK)
638 
639 
640      >>CPU   reg: 00.006500  000002    A 123003, B 001340, X 000000, M i t r o c CCL
641                   ~~ ~~~~~~  ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
642                   |    |       |         |
643                   |    |       |         +-- register values (from 0-4 TOS registers, X, STA)
644                   |    |       +------------ octal stack register count (SR)
645                   |    +-------------------- octal stack memory address (SM)
646                   +------------------------- octal bank (SBANK)
647 
648      >>CPU   reg: 00.000000  000001    PB 010000, PL 025227, DL 001770, DB 002000, Q 006510, Z 007000
649                   ~~ ~~~~~~  ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
650                   |    |       |         |
651                   |    |       |         +-- base register values
652                   |    |       +------------ current code segment number (from STA)
653                   |    +-------------------- zero
654                   +------------------------- octal bank (DBANK)
655 
656      >>CPU  opnd: 00.135771  000000    DFLC '+','!'
657      >>CPU  opnd: 00.045071  000252    target fraction 3 length 6,"002222"
658                   ~~ ~~~~~~  ~~~~~~    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
659                   |    |       |         |
660                   |    |       |         +-- operand-specific value
661                   |    |       +------------ operand-specific data
662                   |    +-------------------- octal address (effective address)
663                   +------------------------- octal bank (PBANK, DBANK, or SBANK)
664 
665      >>CPU pserv: Process clock delay 3970 service entered on the user stack
666 
667    The process clock offers a user-selectable choice of calibrated or realistic
668    timing.  Calibrated timing adjusts the clock to match actual elapsed time
669    (i.e., wall-clock time).  Realistic timing bases the process-clock interval
670    on machine instructions executed, using a mean instruction time of 2.5
671    microseconds.  Running on a typical host platform, the simulator is one or
672    two orders of magnitude faster than a real HP 3000, so the number of machine
673    instructions executed for a given calibrated time interval will be
674    correspondingly greater.  When the process clock is calibrated, the current
675    simulation speed, expressed as a multiple of the speed of a real HP 3000
676    Series III, may be obtained with the SHOW CPU SPEED command.  The speed
677    reported will not be representative if the machine was executing a PAUS
678    instruction when the simulator was stopped.
679 
680    When enabled by a SET CPU IDLE command, execution of a PAUS instruction will
681    idle the simulator.  While idle, the simulator does not use any host system
682    processor time.  Idle detection requires that the process clock and system
683    clock be set to calibrated timing.  Idling is disabled by default.
684 
685 
686    Implementation notes:
687 
688     1. Three timing sources in the simulator may be calibrated to wall-clock
689        time.  These are the process clock, the system clock, and the ATC poll
690        timer.  The process clock is always enabled and running, although the
691        PCLK register only increments if the CPU is not executing on the ICS.
692        The system clock and poll timer run continuously if their respective
693        devices are enabled.  If the ATC is disabled, then the process clock
694        takes over polling for the simulation console.
695 
696        The three sources must be synchronized to allow efficient simulator
697        idling.  This is accomplished by designating the process clock as the
698        master device, which calls the SCP timer calibration routines, and
699        setting the system clock and ATC poll timer to the process clock wait.
700        All three devices will then enter their respective service routines
701        concurrently.
702 
703     2. In hardware, the process clock period is fixed at one millisecond, and
704        the system clock period, while potentially variable, is set by MPE to one
705        millisecond with an interrupt every 100 ticks.  These periods are too
706        short to allow the simulator to idle, as the host OS clock resolution is
707        typically also one millisecond.
708 
709        Therefore, the process and system clock simulators are scheduled with
710        ten-millisecond service times, and the PCLK and counter registers are
711        incremented by ten for each event service.  To present the correct values
712        when the registers are read, the counts are incremented by amounts
713        proportional to the fractions of the service intervals that have elapsed
714        when the reads occur.
715 
716     3. In simulation, the TOS renamer is implemented by permanently assigning
717        the register names RA-RD to TR [0]-TR [3], respectively, and copying the
718        contents between registers to pop and push values.  An alternate
719        implementation approach is to use a renaming register, RN, that tracks
720        the correspondence between registers and array entries, and to assign the
721        register names dynamically using modular indices, e.g., RA is TR [RN], RB
722        is TR [(RN + 1) & 3], etc.  In lieu of copying, incrementing and
723        decrementing RN is done to pop and push values.
724 
725        Both implementations were mocked up and timing measurements made.  The
726        results were that copying values is much faster than mapping via array
727        index values, so this is the implementation chosen.
728 */
729 
730 
731 
732 #include "hp3000_defs.h"
733 #include "hp3000_cpu.h"
734 #include "hp3000_cpu_ims.h"
735 #include "hp3000_mem.h"
736 #include "hp3000_io.h"
737 
738 
739 
740 /* Program constants */
741 
742 #define PCLK_PERIOD         mS (1)                      /* 1 millisecond process clock period */
743 
744 #define PCLK_MULTIPLIER     10                          /* number of hardware process clock ticks per service */
745 #define PCLK_RATE           (1000 / PCLK_MULTIPLIER)    /* process clock rate in ticks per second */
746 
747 #define UNIT_OPTS           (UNIT_EIS)                  /* the standard equipment feature set */
748 
749 #define CPU_IO_RESET        0                           /* reset CPU and all I/O devices */
750 #define IO_RESET            1                           /* reset just the I/O devices */
751 
752 #define CNTL_BASE           8                           /* the radix for the cold dump control byte */
753 #define CNTL_MAX            0377                        /* the maximum cold dump control byte value */
754 
755 #define SIO_JUMP            0000000u                    /* Jump unconditionally */
756 #define SIO_SBANK           0014000u                    /* Set bank */
757 #define SIO_ENDIN           0034000u                    /* End with interrupt */
758 #define SIO_CNTL            0040000u                    /* Control */
759 #define SIO_WRITE           0060000u                    /* Write 4096 words */
760 #define SIO_READ            0077760u                    /* Read 16 words */
761 
762 #define MS_CN_GAP           0000005u                    /* Write Gap */
763 #define MS_CN_WRR           0000004u                    /* Write Record */
764 #define MS_CN_RST           0000011u                    /* Rewind and Reset */
765 #define MS_CN_BSR           0000012u                    /* Backspace Record */
766 #define MS_CN_WFM           0000015u                    /* Write File Mark */
767 
768 #define MS_ST_PROTECTED     0001000u                    /* write protected */
769 #define MS_ST_READY         0000400u                    /* unit ready */
770 
771 #define MS_ST_MASK          (MS_ST_PROTECTED | MS_ST_READY)
772 
773 
774 /* CPU global SCP data definitions */
775 
776 DEVICE cpu_dev;                                 /* incomplete device structure */
777 
778 REG *sim_PC = NULL;                             /* the pointer to the P register */
779 
780 
781 /* CPU global data structures */
782 
783 
784 /* CPU registers */
785 
786 HP_WORD CIR    = 0;                             /* current instruction register */
787 HP_WORD NIR    = 0;                             /* next instruction register */
788 HP_WORD PB     = 0;                             /* program base register */
789 HP_WORD P      = 0;                             /* program counter register */
790 HP_WORD PL     = 0;                             /* program limit register */
791 HP_WORD PBANK  = 0;                             /* program segment bank register */
792 HP_WORD DL     = 0;                             /* data limit register */
793 HP_WORD DB     = 0;                             /* data base register */
794 HP_WORD DBANK  = 0;                             /* data segment bank register */
795 HP_WORD Q      = 0;                             /* stack marker register */
796 HP_WORD SM     = 0;                             /* stack memory register */
797 HP_WORD SR     = 0;                             /* stack register counter */
798 HP_WORD Z      = 0;                             /* stack limit register */
799 HP_WORD SBANK  = 0;                             /* stack segment bank register */
800 HP_WORD TR [4] = { 0, 0, 0, 0 };                /* top of stack registers */
801 HP_WORD X      = 0;                             /* index register */
802 HP_WORD STA    = 0;                             /* status register */
803 HP_WORD SWCH   = 0;                             /* switch register */
804 HP_WORD CPX1   = 0;                             /* run-mode interrupt flags register */
805 HP_WORD CPX2   = 0;                             /* halt-mode interrupt flags register */
806 HP_WORD MOD    = 0;                             /* module control register */
807 HP_WORD PCLK   = 0;                             /* process clock register */
808 HP_WORD CNTR   = 0;                             /* microcode counter */
809 
810 
811 /* Condition Code B lookup table.
812 
813    Byte-oriented instructions set the condition code in the status word using
814    Pattern B (CCB).  For this encoding:
815 
816      CCG = ASCII numeric character
817      CCE = ASCII alphabetic character
818      CCL = ASCII special character
819 
820    The simplest implementation of this pattern is a 256-way lookup table using
821    disjoint condition code flags.  The SET_CCB macro uses this table to set the
822    condition code appropriate for the supplied operand into the status word.
823 */
824 
825 const HP_WORD cpu_ccb_table [256] = {
826     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* NUL SOH STX ETX EOT ENQ ACK BEL */
827     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* BS  HT  LF  VT  FF  CR  SO  SI  */
828     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
829     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* CAN EM  SUB ESC FS  GS  RS  US  */
830     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* spa  !   "   #   $   %   &   '  */
831     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /*  (   )   *   +   ,   -   .   /  */
832     CFG, CFG, CFG, CFG, CFG, CFG, CFG, CFG,     /*  0   1   2   3   4   5   6   7  */
833     CFG, CFG, CFL, CFL, CFL, CFL, CFL, CFL,     /*  8   9   :   ;   <   =   >   ?  */
834     CFL, CFE, CFE, CFE, CFE, CFE, CFE, CFE,     /*  @   A   B   C   D   E   F   G  */
835     CFE, CFE, CFE, CFE, CFE, CFE, CFE, CFE,     /*  H   I   J   K   L   M   N   O  */
836     CFE, CFE, CFE, CFE, CFE, CFE, CFE, CFE,     /*  P   Q   R   S   T   U   V   W  */
837     CFE, CFE, CFE, CFL, CFL, CFL, CFL, CFL,     /*  X   Y   Z   [   \   ]   ^   _  */
838     CFL, CFE, CFE, CFE, CFE, CFE, CFE, CFE,     /*  `   a   b   c   d   e   f   g  */
839     CFE, CFE, CFE, CFE, CFE, CFE, CFE, CFE,     /*  h   i   j   k   l   m   n   o  */
840     CFE, CFE, CFE, CFE, CFE, CFE, CFE, CFE,     /*  p   q   r   s   t   u   v   w  */
841     CFE, CFE, CFE, CFL, CFL, CFL, CFL, CFL,     /*  x   y   z   {   |   }   ~  DEL */
842     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 200 - 207 */
843     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 210 - 217 */
844     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 220 - 227 */
845     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 230 - 237 */
846     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 240 - 247 */
847     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 250 - 257 */
848     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 260 - 267 */
849     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 270 - 277 */
850     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 300 - 307 */
851     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 310 - 317 */
852     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 320 - 327 */
853     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 330 - 337 */
854     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 340 - 347 */
855     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 350 - 357 */
856     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL,     /* 360 - 367 */
857     CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL      /* 370 - 377 */
858     };
859 
860 
861 /* CPU global state */
862 
863 jmp_buf     cpu_save_env;                       /* the saved environment for microcode aborts */
864 uint32      cpu_stop_flags;                     /* the simulation stop flag set */
865 
866 POWER_STATE cpu_power_state   = power_on;       /* the power supply state */
867 EXEC_STATE  cpu_micro_state   = halted;         /* the microcode execution state */
868 t_bool      cpu_base_changed  = FALSE;          /* TRUE if any base register is changed */
869 t_bool      cpu_is_calibrated = TRUE;           /* TRUE if the process clock is calibrated */
870 UNIT       *cpu_pclk_uptr     = &cpu_unit [0];  /* a (constant) pointer to the process clock unit */
871 
872 
873 /* CPU local state */
874 
875 static uint32  sim_stops      = 0;              /* the current simulation stop flag settings */
876 static uint32  cpu_speed      = 1;              /* the CPU speed, expressed as a multiplier of a real machine */
877 static uint32  pclk_increment = 1;              /* the process clock increment per event service */
878 static uint32  dump_control   = 0002006u;       /* the cold dump control word (default CNTL = 4, DEVNO = 6 */
879 static HP_WORD exec_mask      = 0;              /* the current instruction execution trace mask */
880 static HP_WORD exec_match     = D16_UMAX;       /* the current instruction execution trace matching value */
881 
882 
883 /* CPU local data structures */
884 
885 
886 /* Interrupt classification names */
887 
888 static const char *const interrupt_name [] = {  /* class names, indexed by IRQ_CLASS */
889     "integer overflow",                         /*   000 irq_Integer_Overflow */
890     "bounds violation",                         /*   001 irq_Bounds_Violation */
891     "illegal memory address error",             /*   002 irq_Illegal_Address  */
892     "non-responding module error",              /*   003 irq_Timeout          */
893     "system parity error",                      /*   004 irq_System_Parity    */
894     "address parity error",                     /*   005 irq_Address_Parity   */
895     "data parity error",                        /*   006 irq_Data_Parity      */
896     "module",                                   /*   007 irq_Module           */
897     "external",                                 /*   010 irq_External         */
898     "power fail",                               /*   011 irq_Power_Fail       */
899     "ICS trap",                                 /*   012 irq_Trap             */
900     "dispatch",                                 /*   013 irq_Dispatch         */
901     "exit"                                      /*   014 irq_IXIT             */
902     };
903 
904 
905 /* Trap classification names */
906 
907 static const char *const trap_name [] = {       /* trap names, indexed by TRAP_CLASS */
908     "no",                                       /*   000 trap_None                */
909     "bounds violation",                         /*   001 trap_Bounds_Violation    */
910     NULL,                                       /*   002 (unused)                 */
911     NULL,                                       /*   003 (unused)                 */
912     NULL,                                       /*   004 (unused)                 */
913     NULL,                                       /*   005 (unused)                 */
914     NULL,                                       /*   006 (unused)                 */
915     NULL,                                       /*   007 (unused)                 */
916     NULL,                                       /*   010 (unused)                 */
917     NULL,                                       /*   011 (unused)                 */
918     NULL,                                       /*   012 (unused)                 */
919     NULL,                                       /*   013 (unused)                 */
920     NULL,                                       /*   014 (unused)                 */
921     NULL,                                       /*   015 (unused)                 */
922     NULL,                                       /*   016 (unused)                 */
923     NULL,                                       /*   017 (unused)                 */
924     "unimplemented instruction",                /*   020 trap_Unimplemented       */
925     "STT violation",                            /*   021 trap_STT_Violation       */
926     "CST violation",                            /*   022 trap_CST_Violation       */
927     "DST violation",                            /*   023 trap_DST_Violation       */
928     "stack underflow",                          /*   024 trap_Stack_Underflow     */
929     "privileged mode violation",                /*   025 trap_Privilege_Violation */
930     NULL,                                       /*   026 (unused)                 */
931     NULL,                                       /*   027 (unused)                 */
932     "stack overflow",                           /*   030 trap_Stack_Overflow      */
933     "user",                                     /*   031 trap_User                */
934     NULL,                                       /*   032 (unused)                 */
935     NULL,                                       /*   033 (unused)                 */
936     NULL,                                       /*   034 (unused)                 */
937     NULL,                                       /*   035 (unused)                 */
938     NULL,                                       /*   036 (unused)                 */
939     "absent code segment",                      /*   037 trap_CS_Absent           */
940     "trace",                                    /*   040 trap_Trace               */
941     "STT entry uncallable",                     /*   041 trap_Uncallable          */
942     "absent data segment",                      /*   042 trap_DS_Absent           */
943     "power on",                                 /*   043 trap_Power_On            */
944     "cold load",                                /*   044 trap_Cold_Load           */
945     "system halt"                               /*   045 trap_System_Halt         */
946     };
947 
948 
949 /* CPU features table.
950 
951    The feature table is used to validate CPU feature changes within the subset
952    of features supported by a given CPU.  Features in the typical list are
953    enabled when the CPU model is selected.  If a feature appears in the typical
954    list but NOT in the optional list, then it is standard equipment and cannot
955    be disabled.  If a feature appears in the optional list, then it may be
956    enabled or disabled as desired by the user.
957 
958 
959    Implementation notes:
960 
961     1. The EIS was standard equipment for the Series II and III, so UNIT_EIS
962        should appear in their "typ" fields.  However, the EIS instructions are
963        not currently implemented, so the value is omitted below.
964 */
965 
966 struct FEATURE_TABLE {
967     uint32      typ;                            /* standard features plus typically configured options */
968     uint32      opt;                            /* complete list of optional features */
969     uint32      maxmem;                         /* maximum configurable memory in 16-bit words */
970     };
971 
972 static const struct FEATURE_TABLE cpu_features [] = {   /* features indexed by CPU_MODEL */
973   { 0,                                                  /*   UNIT_SERIES_III */
974     UNIT_CIS,
975     1024 * 1024 },
976   { 0,                                                  /*   UNIT_SERIES_II */
977     0,
978     256 * 1024 }
979   };
980 
981 
982 /* CPU local SCP support routine declarations */
983 
984 static t_stat cpu_service (UNIT   *uptr);
985 static t_stat cpu_reset   (DEVICE *dptr);
986 
987 static t_stat set_stops  (UNIT *uptr, int32 option,     char *cptr, void *desc);
988 static t_stat set_exec   (UNIT *uptr, int32 option,     char *cptr, void *desc);
989 static t_stat set_dump   (UNIT *uptr, int32 option,     char *cptr, void *desc);
990 static t_stat set_size   (UNIT *uptr, int32 new_size,   char *cptr, void *desc);
991 static t_stat set_model  (UNIT *uptr, int32 new_model,  char *cptr, void *desc);
992 static t_stat set_option (UNIT *uptr, int32 new_option, char *cptr, void *desc);
993 static t_stat set_pfars  (UNIT *uptr, int32 setting,    char *cptr, void *desc);
994 
995 static t_stat show_stops (FILE *st, UNIT *uptr, int32 val, void *desc);
996 static t_stat show_exec  (FILE *st, UNIT *uptr, int32 val, void *desc);
997 static t_stat show_dump  (FILE *st, UNIT *uptr, int32 val, void *desc);
998 static t_stat show_speed (FILE *st, UNIT *uptr, int32 val, void *desc);
999 
1000 
1001 /* CPU local utility routine declarations */
1002 
1003 static t_stat halt_mode_interrupt (HP_WORD device_number);
1004 static t_stat machine_instruction (void);
1005 
1006 
1007 /* CPU SCP data structures */
1008 
1009 
1010 /* Unit list.
1011 
1012    The CPU unit holds the main memory capacity and is used to schedule the
1013    process clock events.
1014 
1015 
1016    Implementation notes:
1017 
1018     1. The unit structure must be global for other modules to obtain the memory
1019        size via the MEMSIZE macro, which references the "capac" field.
1020 */
1021 
1022 #define UNIT_FLAGS          (UNIT_PFARS | UNIT_CALTIME)
1023 
1024 UNIT cpu_unit [] = {
1025     { UDATA (&cpu_service, UNIT_FLAGS | UNIT_FIX | UNIT_BINK | UNIT_IDLE, 0), PCLK_PERIOD * PCLK_MULTIPLIER }
1026     };
1027 
1028 
1029 /* Register list.
1030 
1031    The CPU register list exposes the machine registers for user inspection and
1032    modification.  User flags describe the permitted and default display formats,
1033    as follows:
1034 
1035      - REG_X  permits any symbolic display
1036      - REG_M  defaults to CPU instruction mnemonic display
1037      - REG_T  defaults to CPU status mnemonic display
1038 
1039 
1040  Implementation notes:
1041 
1042     1. All registers that reference variables of type HP_WORD must have the
1043        REG_FIT flag for proper access if HP_WORD is a 16-bit type.
1044 
1045     2. The CNTR register is set to the value of the SR register when the
1046        micromachine halts or pauses.  This allows the SR value to be accessed by
1047        the diagnostics.  The top-of-stack registers are flushed to main memory
1048        when the machine halts or pauses, which alters SR.
1049 */
1050 
1051 static REG cpu_reg [] = {
1052 /*    Macro   Name     Location      Radix  Width  Offset           Flags           */
1053 /*    ------  -------  ------------  -----  -----  ------  ------------------------ */
1054     { ORDATA (CIR,     CIR,                  16),          REG_M | REG_RO | REG_FIT },  /* current instruction register */
1055     { ORDATA (NIR,     NIR,                  16),          REG_M | REG_RO | REG_FIT },  /* next instruction register */
1056     { ORDATA (PB,      PB,                   16),                           REG_FIT },  /* program base register */
1057     { ORDATA (P,       P,                    16),                           REG_FIT },  /* program counter register */
1058     { ORDATA (PL,      PL,                   16),                           REG_FIT },  /* program limit register */
1059     { ORDATA (PBANK,   PBANK,                 4),                           REG_FIT },  /* program segment bank register */
1060     { ORDATA (DL,      DL,                   16),                           REG_FIT },  /* data limit register */
1061     { ORDATA (DB,      DB,                   16),                           REG_FIT },  /* data base register */
1062     { ORDATA (DBANK,   DBANK,                 4),                           REG_FIT },  /* data segment bank register */
1063     { ORDATA (Q,       Q,                    16),                           REG_FIT },  /* stack marker register */
1064     { ORDATA (SM,      SM,                   16),                           REG_FIT },  /* stack memory register */
1065     { ORDATA (SR,      SR,                    3),                           REG_FIT },  /* stack register counter */
1066     { ORDATA (Z,       Z,                    16),                           REG_FIT },  /* stack limit register */
1067     { ORDATA (SBANK,   SBANK,                 4),                           REG_FIT },  /* stack segment bank register */
1068     { ORDATA (RA,      TR [0],               16),          REG_X          | REG_FIT },  /* top of stack register */
1069     { ORDATA (RB,      TR [1],               16),          REG_X          | REG_FIT },  /* top of stack - 1 register */
1070     { ORDATA (RC,      TR [2],               16),          REG_X          | REG_FIT },  /* top of stack - 2 register */
1071     { ORDATA (RD,      TR [3],               16),          REG_X          | REG_FIT },  /* top of stack - 3 register */
1072     { ORDATA (X,       X,                    16),          REG_X          | REG_FIT },  /* index register */
1073     { ORDATA (STA,     STA,                  16),          REG_T          | REG_FIT },  /* status register */
1074     { ORDATA (SWCH,    SWCH,                 16),          REG_X          | REG_FIT },  /* switch register */
1075     { ORDATA (CPX1,    CPX1,                 16),                           REG_FIT },  /* run-mode interrupt flags */
1076     { ORDATA (CPX2,    CPX2,                 16),                           REG_FIT },  /* halt-mode interrupt flags */
1077     { ORDATA (PCLK,    PCLK,                 16),                           REG_FIT },  /* process clock register */
1078     { ORDATA (CNTR,    CNTR,                  6),                 REG_HRO | REG_FIT },  /* microcode counter */
1079     { ORDATA (MOD,     MOD,                  16),                 REG_HRO | REG_FIT },  /* module control register */
1080 
1081     { DRDATA (POWER,   cpu_power_state,       2),                 REG_HRO           },  /* system power supply state */
1082     { ORDATA (WRU,     sim_int_char,          8),                 REG_HRO           },  /* SCP interrupt character */
1083     { ORDATA (BRK,     sim_brk_char,          8),                 REG_HRO           },  /* SCP break character */
1084     { ORDATA (DEL,     sim_del_char,          8),                 REG_HRO           },  /* SCP delete character */
1085 
1086     { NULL }
1087     };
1088 
1089 
1090 /* Modifier list */
1091 
1092 static MTAB cpu_mod [] = {
1093 /*    Mask Value    Match Value      Print String         Match String  Validation   Display  Descriptor */
1094 /*    ------------  ---------------  -------------------  ------------  -----------  -------  ---------- */
1095     { UNIT_MODEL,   UNIT_SERIES_II,  "Series II",         NULL,         &set_model,  NULL,    NULL       },
1096     { UNIT_MODEL,   UNIT_SERIES_III, "Series III",        "III",        &set_model,  NULL,    NULL       },
1097 
1098     { UNIT_EIS,     UNIT_EIS,        "EIS",               NULL,         &set_option, NULL,    NULL       },
1099     { UNIT_EIS,     0,               "no EIS",            "NOEIS",      NULL,        NULL,    NULL       },
1100 
1101     { UNIT_CIS,     UNIT_CIS,        "CIS",               "CIS",        &set_option, NULL,    NULL       },
1102     { UNIT_CIS,     0,               "no CIS",            "NOCIS",      NULL,        NULL,    NULL       },
1103 
1104     { UNIT_PFARS,   UNIT_PFARS,      "auto-restart",      "ARS",        &set_pfars,  NULL,    NULL       },
1105     { UNIT_PFARS,   0,               "no auto-restart",   "NOARS",      &set_pfars,  NULL,    NULL       },
1106 
1107     { UNIT_CALTIME, UNIT_CALTIME,    "calibrated timing", "CALTIME",    NULL,        NULL,    NULL       },
1108     { UNIT_CALTIME, 0,               "realistic timing",  "REALTIME",   NULL,        NULL,    NULL       },
1109 
1110 /*    Entry Flags             Value     Print String  Match String  Validation     Display         Descriptor */
1111 /*    -------------------  -----------  ------------  ------------  -------------  --------------  ---------- */
1112     { MTAB_XDV,             128 * 1024, NULL,         "128K",       &set_size,     NULL,           NULL       },
1113     { MTAB_XDV,             256 * 1024, NULL,         "256K",       &set_size,     NULL,           NULL       },
1114     { MTAB_XDV,             384 * 1024, NULL,         "384K",       &set_size,     NULL,           NULL       },
1115     { MTAB_XDV,             512 * 1024, NULL,         "512K",       &set_size,     NULL,           NULL       },
1116     { MTAB_XDV,             768 * 1024, NULL,         "768K",       &set_size,     NULL,           NULL       },
1117     { MTAB_XDV,            1024 * 1024, NULL,         "1024K",      &set_size,     NULL,           NULL       },
1118 
1119     { MTAB_XDV,                 0,      "IDLE",       "IDLE",       &sim_set_idle, &sim_show_idle, NULL       },
1120     { MTAB_XDV,                 0,      NULL,         "NOIDLE",     &sim_clr_idle, NULL,           NULL       },
1121 
1122     { MTAB_XDV | MTAB_NMO,      0,      "DUMP",       "DUMPDEV",    &set_dump,     &show_dump,     NULL       },
1123     { MTAB_XDV,                 1,      NULL,         "DUMPCTL",    &set_dump,     NULL,           NULL       },
1124 
1125     { MTAB_XDV | MTAB_NMO,      1,      "STOPS",      "STOP",       &set_stops,    &show_stops,    NULL       },
1126     { MTAB_XDV,                 0,      NULL,         "NOSTOP",     &set_stops,    NULL,           NULL       },
1127 
1128     { MTAB_XDV | MTAB_NMO,      1,      "EXEC",       "EXEC",       &set_exec,     &show_exec,     NULL       },
1129     { MTAB_XDV,                 0,      NULL,         "NOEXEC",     &set_exec,     NULL,           NULL       },
1130 
1131     { MTAB_XDV | MTAB_NMO,      0,      "SPEED",      NULL,         NULL,          &show_speed,    NULL       },
1132 
1133     { 0 }
1134     };
1135 
1136 
1137 /* Debugging trace list */
1138 
1139 static DEBTAB cpu_deb [] = {
1140     { "INSTR", DEB_INSTR  },                    /* instructions */
1141     { "DATA",  DEB_MDATA  },                    /* memory data accesses */
1142     { "FETCH", DEB_MFETCH },                    /* memory instruction fetches */
1143     { "REG",   DEB_REG    },                    /* register values */
1144     { "OPND",  DEB_MOPND  },                    /* memory operand values */
1145     { "EXEC",  DEB_EXEC   },                    /* instruction execution states */
1146     { "PSERV", DEB_PSERV  },                    /* process clock service events */
1147     { NULL,    0          }
1148     };
1149 
1150 /* Debugging stop list */
1151 
1152 static DEBTAB cpu_stop [] = {
1153     { "LOOP",   SS_LOOP   },                    /* stop on an infinite loop */
1154     { "PAUSE",  SS_PAUSE  },                    /* stop on a PAUS instruction */
1155     { "UNDEF",  SS_UNDEF  },                    /* stop on an undefined instruction */
1156     { "UNIMPL", SS_UNIMPL },                    /* stop on an unimplemented instruction */
1157     { NULL,     0         }
1158     };
1159 
1160 
1161 /* Device descriptor */
1162 
1163 DEVICE cpu_dev = {
1164     "CPU",                                      /* device name */
1165     cpu_unit,                                   /* unit array */
1166     cpu_reg,                                    /* register array */
1167     cpu_mod,                                    /* modifier array */
1168     1,                                          /* number of units */
1169     8,                                          /* address radix */
1170     PA_WIDTH,                                   /* address width */
1171     1,                                          /* address increment */
1172     8,                                          /* data radix */
1173     16,                                         /* data width */
1174     &mem_examine,                               /* examine routine */
1175     &mem_deposit,                               /* deposit routine */
1176     &cpu_reset,                                 /* reset routine */
1177     NULL,                                       /* boot routine */
1178     NULL,                                       /* attach routine */
1179     NULL,                                       /* detach routine */
1180     NULL,                                       /* device information block pointer */
1181     DEV_DEBUG,                                  /* device flags */
1182     0,                                          /* debug control flags */
1183     cpu_deb,                                    /* debug flag name array */
1184     NULL,                                       /* memory size change routine */
1185     NULL                                        /* logical device name */
1186     };
1187 
1188 
1189 
1190 /* CPU global SCP support routines */
1191 
1192 
1193 /* Execute CPU instructions.
1194 
1195    This is the instruction decode routine for the HP 3000.  It is called from
1196    the simulator control program to execute instructions in simulated memory,
1197    starting at the simulated program counter.  It runs until the status to be
1198    returned is set to a value other than SCPE_OK.
1199 
1200    On entry, P points to the instruction to execute, and the "sim_switches"
1201    global contains any command-line switches included with the run command.  On
1202    exit, P points at the next instruction to execute (or the current
1203    instruction, in the case of a simulator stop during a PAUS instruction or
1204    after the first of two stack operations).
1205 
1206    Execution is divided into four phases.
1207 
1208    First, the instruction prelude configures the simulation state to resume
1209    execution.  This involves verifying that system power is on and there are no
1210    device conflicts (e.g., two devices with the same device number),
1211    initializing the I/O processor and channels, and setting the RUN switch if no
1212    other front panel switches are pressed.  These actions accommodate
1213    reconfiguration of the I/O device settings and program counter while the
1214    simulator was stopped.  The prelude also responds to one command-line switch:
1215    if "-B" is specified, the current set of simulation stop conditions is
1216    bypassed for the first instruction executed.  This allows, e.g., a PAUS
1217    instruction to be bypassed or an unimplemented instruction trap to be taken.
1218 
1219    Second, the microcode abort mechanism is set up.  Microcode aborts utilize
1220    the "setjmp/longjmp" mechanism to transfer control out of the instruction
1221    executors without returning through the call stack.  This allows an
1222    instruction to be aborted part-way through execution when continuation is
1223    impossible, e.g., due to a memory access violation.  It corresponds to direct
1224    microcode jumps out of the execution sequence and to the appropriate trap
1225    handlers.
1226 
1227    Third, the instruction execution loop decodes instructions and calls the
1228    individual executors in turn until a condition occurs that prevents further
1229    execution.  Examples of such conditions includes execution of a HALT
1230    instruction, a user stop request (CTRL+E) from the simulation console, a
1231    recoverable device error (such as an improperly formatted tape image), a
1232    user-specified breakpoint, and a simulation stop condition (such as execution
1233    of an unimplemented instruction).  The execution loop also polls for I/O
1234    events and device interrupts, and runs I/O channel cycles.  During
1235    instruction execution, the CIR register contains the currently executing
1236    instruction, the NIR register contains the next instruction to execute, and
1237    the P register points to the memory location two instructions ahead of the
1238    current instruction.
1239 
1240    Fourth, the instruction postlude updates the simulation state in preparation
1241    for returning to the SCP command prompt.  Devices that maintain an internal
1242    state different from their external state, such as the CPU process clock, are
1243    updated so that their internal and external states are fully consistent.
1244    This ensures that the state visible to the user during the simulation stop is
1245    correct.  It also ensures that the program counter points correctly at the
1246    next instruction to execute upon resumption.
1247 
1248    If enabled, the simulator is idled when a PAUS instruction has been executed
1249    and no service requests for the multiplexer or selector channels are active.
1250    Execution of a PAUS instruction suspends the fetch-and-execute process until
1251    an interrupt occurs or the simulator is stopped and then resumed with a GO -B
1252    or RUN -B command.
1253 
1254    The HP 3000 is a microcoded machine.  In hardware, the micromachine is always
1255    executing microinstructions, even when the CPU is "halted."  The halt/run
1256    state is simply a flip-flop setting, reflected in bit 15 of the CPX2
1257    register and the RUN light on the front panel, that determines whether the
1258    "halt-mode" or "run-mode" microprogram is currently executing.
1259 
1260    In simulation, the "cpu_micro_state" variable indicates the state of the
1261    micromachine, i.e., which section of the microcode it is executing, while
1262    CPX2 bit 15 indicates whether the macromachine is halted or running.  The
1263    micromachine may be in one of four states:
1264 
1265      - running : the run-mode fetch-and-execute microcode is executing
1266      - paused  : the run-mode PAUS instruction microcode is executing
1267      - waiting : the halt-mode cold load or dump microcode is executing
1268      - halted  : the halt-mode front panel microcode is executing
1269 
1270    Simulation provides a variety of stop conditions that break instruction
1271    execution and return to the SCP prompt with the CPU still in run mode.  These
1272    have no analog in hardware; the only way to stop the CPU is to press the HALT
1273    button on the front panel, which shifts the micromachine into halt-mode
1274    microcode execution.  When any of these conditions occur, the micromachine
1275    state is set to "halted," but the CPX2 run flag is remains set unless the
1276    stop was caused by execution of a HALT instruction.  Resuming execution with
1277    a STEP, CONT, GO, or RUN command proceeds as though the hardware RUN switch
1278    was pressed after a programmed halt.  This provides the proper semantics for
1279    seamlessly stopping and restarting instruction execution.
1280 
1281    A microcode abort is performed by executing a "longjmp" to the abort handler,
1282    which is outside of and precedes the instruction execution loop.  The value
1283    passed to "longjmp" is a 32-bit integer containing the Segment Transfer Table
1284    index of the trap handler in the lower word and an optional parameter in the
1285    upper word.  Aborts are invoked by the MICRO_ABORT macro, which takes as its
1286    parameter a trap classification value, e.g.:
1287 
1288      MICRO_ABORT (trap_Privilege_Violation);
1289      MICRO_ABORT (trap_Integer_Zero_Divide);
1290 
1291    Some aborts require an additional parameter and must be invoked by the
1292    MICRO_ABORTP macro, which takes a trap classification value and a
1293    trap-specific value as parameters.  The traps that require additional
1294    parameters are:
1295 
1296      MICRO_ABORTP (trap_CST_Violation, segment_number);
1297      MICRO_ABORTP (trap_STT_Violation, segment_number);
1298      MICRO_ABORTP (trap_CS_Absent,     label/n/0);
1299      MICRO_ABORTP (trap_DS_Absent,     DST_number);
1300      MICRO_ABORTP (trap_Uncallable,    label);
1301      MICRO_ABORTP (trap_Trace,         label/n/0);
1302      MICRO_ABORTP (trap_User,          trap_number);
1303 
1304    trap_User is not usually called explicitly via MICRO_ABORTP; rather,
1305    MICRO_ABORT is used with one of the specific user-trap identifiers, e.g.,
1306    trap_Integer_Overflow, trap_Float_Overflow, trap_Decimal_Overflow, etc., that
1307    supplies both the trap classification and the trap parameter value.
1308 
1309    In addition, user traps must be enabled by setting the T-bit in the status
1310    word.  If the T bit is not set, a user trap sets the O-bit (overflow) in the
1311    status word and resumes execution with the next instruction instead of
1312    invoking the user trap handler.
1313 
1314    When an abort occurs, an equivalent PCAL to the appropriate STT entry is set
1315    up.  Then execution drops into the instruction loop to execute the first
1316    instruction of the trap handler.
1317 
1318    When the instruction loop is exited, the CPU process clock and system clock
1319    registers are updated, the micromachine is halted, and control returns to
1320    SCP.  Upon return, P points at the next instruction to execute, i.e., the
1321    instruction that will execute when the instruction loop is reentered.
1322 
1323    If the micromachine is paused, then P is reset to point to the PAUS
1324    instruction, which will be reexecuted when the routine is reentered.  If it
1325    is running, then P is reset to point to the current instruction if the stop
1326    allows it to be rerun, or at the next instruction.
1327 
1328 
1329    Implementation notes:
1330 
1331     1. While the Microsoft VC++ "setjmp" documentation says, "All variables
1332        (except register variables) accessible to the routine receiving control
1333        contain the values they had when longjmp was called," the ISO C99
1334        standard says, "All accessible objects have values...as of the time the
1335        longjmp function was called, except that the values of objects of
1336        automatic storage duration that are local to the function containing the
1337        invocation of the corresponding setjmp macro that do not have
1338        volatile-qualified type and have been changed between the setjmp
1339        invocation and longjmp call are indeterminate."
1340 
1341        Therefore, the "device" and "status" variables are marked volatile to
1342        ensure that they are reloaded after a longjmp caused by a micrcode abort.
1343 
1344     2. In hardware, the NEXT microcode order present at the end of each
1345        instruction transfers the NIR content to the CIR, reads the memory word
1346        at P into the NIR, and increments P.  However, if an interrupt is
1347        present, then this action is omitted, and a microcode jump is performed
1348        to control store location 3, which then jumps to the microcoded interrupt
1349        handler.  In simulation, the CIR/NIR/P update is performed before the
1350        next instruction is executed, rather than after the last instruction
1351        completes, so that interrupts are handled before updating.
1352 
1353        In addition, the NEXT action is modified in hardware if the NIR contains
1354        a stack instruction with a non-NOP B stackop.  In this case, NEXT
1355        transfers the NIR content to the CIR, reads the memory word at P into the
1356        NIR, but does not increment P.  Instead, the R bit of the status register
1357        is set to indicate that a B stackop is pending.  When the NEXT at the
1358        completion of the A stackop is executed, the NIR and CIR are untouched,
1359        but P is incremented, and the R bit is cleared.  This ensures that if an
1360        interrupt or trap occurs between the stackops, P will point correctly at
1361        the next instruction to be executed.
1362 
1363        In simulation, following the hardware would require testing the NIR for a
1364        non-NOP B stackop at every pass through the instruction execution loop.
1365        To avoid this, the NEXT simulation unilaterally increments P, rather than
1366        only when a B stackop is not present, and the stack instruction executor
1367        tests for the B stackop and sets the R bit there.  However, by that time,
1368        P has already been incremented, so we decrement it there to return it to
1369        the correct value.
1370 
1371     3. The System Halt trap has no handler.  Instead, the simulator is halted,
1372        and control returns to the SCP prompt.
1373 
1374     4. The trace display for a trap reports the parameter value supplied with
1375        the microcode abort.  This is not necessarily the same as the parameter
1376        that is pushed on the stack for the trap handler.  As some traps, e.g.,
1377        trap_CST_Violation, can cause a System Halt, the placement of the trace
1378        call is dictated by the desire to report both the original trap and the
1379        System Halt trap, even though the placement results in the display of the
1380        incoming parameter value, rather than the stacked parameter value.
1381 
1382     5. The execution trace (DEB_EXEC) match test is performed in two parts to
1383        display the register values both before and after the instruction
1384        execution.  Consequently, the enable test is done before the register
1385        trace, and the disable test is done after.
1386 
1387     6. The execution test (exec_test) is set FALSE even though execution tracing
1388        is not specified.  This is done solely to reassure the compiler that the
1389        value is not clobbered by a longjmp call.
1390 
1391     7. The set of debug trace flags is restored in the postlude (and therefore
1392        also saved in the instruction prelude) to ensure that a simulation stop
1393        that occurs while an execution trace is in progress does not exit with
1394        the flags set improperly.
1395 
1396     8. The breakpoint test must be executed even when the CPU pauses to permit
1397        string breakpoint delays to expire.
1398 */
1399 
sim_instr(void)1400 t_stat sim_instr (void)
1401 {
1402 static const char *const stack_formats [] = {           /* stack register display formats, indexed by SR */
1403     BOV_FORMAT "  ",                                    /*   SR = 0 format */
1404     BOV_FORMAT "  A %06o, ",                            /*   SR = 1 format */
1405     BOV_FORMAT "  A %06o, B %06o, ",                    /*   SR = 2 format */
1406     BOV_FORMAT "  A %06o, B %06o, C %06o, ",            /*   SR = 3 format */
1407     BOV_FORMAT "  A %06o, B %06o, C %06o, D %06o, "     /*   SR = 4 format */
1408     };
1409 
1410 int        abortval;
1411 HP_WORD    label, parameter;
1412 TRAP_CLASS trap;
1413 t_bool     exec_test;
1414 volatile   uint32  debug_save;
1415 volatile   HP_WORD device;
1416 volatile   t_stat  status = SCPE_OK;
1417 
1418 
1419 /* Instruction prelude */
1420 
1421 debug_save = cpu_dev.dctrl;                             /* save the current set of debug flags for later restoration */
1422 
1423 if (sim_switches & SWMASK ('B'))                        /* if a simulation stop bypass was requested */
1424     cpu_stop_flags = SS_BYPASSED;                       /*   then clear the stop flags for the first instruction */
1425 else                                                    /* otherwise */
1426     cpu_stop_flags = sim_stops;                         /*   set the stops as indicated */
1427 
1428 if (cpu_power_state == power_off)                       /* if system power is off */
1429     status = STOP_POWER;                                /*   then execution is not possible until restoration */
1430 
1431 else if (hp_device_conflict ())                         /* otherwise if device assignment is inconsistent */
1432     status = SCPE_STOP;                                 /*   then inhibit execution */
1433 
1434 else {                                                  /* otherwise */
1435     device = iop_initialize ();                         /*   initialize the IOP */
1436     mpx_initialize ();                                  /*     and the multiplexer channel */
1437     sel_initialize ();                                  /*       and the selector channel */
1438 
1439     if ((CPX2 & CPX2_IRQ_SET) == 0)                     /* if no halt-mode interrupt is present */
1440         CPX2 |= cpx2_RUNSWCH;                           /*   then assume a RUN command via STEP/CONT */
1441     }
1442 
1443 
1444 /* Microcode abort processor */
1445 
1446 abortval = setjmp (cpu_save_env);                       /* set the microcode abort handler */
1447 
1448 if (abortval) {                                         /* if a microcode abort occurred */
1449     trap = TRAP (abortval);                             /*   then get the trap classification */
1450     parameter = PARAM (abortval);                       /*     and the optional parameter */
1451 
1452     label = TO_LABEL (LABEL_IRQ, trap);                 /* form the label from the STT number */
1453 
1454     tprintf (cpu_dev, DEB_INSTR, BOV_FORMAT "%s trap%s\n",
1455              PBANK, P - 1 & R_MASK, parameter, trap_name [trap],
1456              (trap == trap_User && !(STA & STATUS_T) ? " (disabled)" : ""));
1457 
1458     switch (trap) {                                     /* dispatch on the trap classification */
1459 
1460         case trap_None:                                 /* trap_None should never occur */
1461         case trap_System_Halt:
1462             CNTR = SR;                                  /* copy the stack register to the counter */
1463             cpu_flush ();                               /*   and flush the TOS registers to memory */
1464 
1465             RA = parameter;                             /* set RA to the parameter (system halt condition) */
1466 
1467             CPX2 = CPX2 & ~cpx2_RUN | cpx2_SYSHALT;     /* halt the CPU and set the system halt flag */
1468             status = STOP_SYSHALT;                      /*   and report the system halt condition */
1469 
1470             label = 0;                                  /* there is no trap handler for a system halt */
1471             break;
1472 
1473 
1474         case trap_CST_Violation:
1475             if (STT_SEGMENT (parameter) <= ISR_SEGMENT) /* if the trap occurred in segment 1 */
1476                 MICRO_ABORT (trap_SysHalt_CSTV_1);      /*   then the failure is fatal */
1477 
1478         /* fall through into the next trap handler */
1479 
1480         case trap_STT_Violation:
1481             if (STT_SEGMENT (parameter) <= ISR_SEGMENT) /* if the trap occurred in segment 1 */
1482                 MICRO_ABORT (trap_SysHalt_STTV_1);      /*   then the failure is fatal */
1483 
1484         /* fall through into the next trap handler */
1485 
1486         case trap_Unimplemented:
1487         case trap_DST_Violation:
1488         case trap_Stack_Underflow:
1489         case trap_Privilege_Violation:
1490         case trap_Bounds_Violation:
1491             parameter = label;                          /* the label is the parameter for these traps */
1492 
1493         /* fall through into the next trap handler */
1494 
1495         case trap_DS_Absent:
1496             cpu_flush ();                               /* flush the TOS registers to memory */
1497             cpu_mark_stack ();                          /*   and then write a stack marker */
1498 
1499         /* fall through into the next trap handler */
1500 
1501         case trap_Uncallable:
1502             break;                                      /* set up the trap handler */
1503 
1504 
1505         case trap_User:
1506             if (STA & STATUS_T) {                       /* if user traps are enabled */
1507                 STA &= ~STATUS_O;                       /*   then clear overflow status */
1508                 cpu_flush ();                           /*     and flush the TOS registers to memory */
1509                 cpu_mark_stack ();                      /*       and write a stack marker */
1510                 }                                       /*         and set up the trap handler */
1511 
1512             else {                                      /* otherwise in lieu of trapping */
1513                 STA |= STATUS_O;                        /*   set overflow status */
1514                 label = 0;                              /*     and continue execution with the next instruction */
1515                 }
1516             break;
1517 
1518 
1519         case trap_CS_Absent:
1520             if (CPX1 & cpx1_ICSFLAG)                    /* if the trap occurred while on the ICS */
1521                 MICRO_ABORT (trap_SysHalt_Absent_ICS);  /*   then the failure is fatal */
1522 
1523             else if (STT_SEGMENT (STA) <= ISR_SEGMENT)  /* otherwise if the trap occurred in segment 1 */
1524                 MICRO_ABORT (trap_SysHalt_Absent_1);    /*   then the failure is fatal */
1525             break;                                      /* otherwise set up the trap handler */
1526 
1527 
1528         case trap_Trace:
1529             if (STT_SEGMENT (STA) <= ISR_SEGMENT)       /* if the trap occurred in segment 1 */
1530                 MICRO_ABORT (trap_SysHalt_Trace_1);     /*   then the failure is fatal */
1531             break;                                      /* otherwise set up the trap handler */
1532 
1533 
1534         case trap_Cold_Load:                            /* this trap executes on the ICS */
1535             status = STOP_CLOAD;                        /* report that the cold load is complete */
1536 
1537         /* fall through into trap_Stack_Overflow */
1538 
1539         case trap_Stack_Overflow:                           /* this trap executes on the ICS */
1540             if (CPX1 & cpx1_ICSFLAG)                        /*   so if the trap occurred while on the ICS */
1541                 MICRO_ABORT (trap_SysHalt_Overflow_ICS);    /*     then the failure is fatal */
1542 
1543             cpu_setup_ics_irq (irq_Trap, trap);             /* otherwise, set up the ICS */
1544             break;                                          /*   and then the trap handler */
1545 
1546 
1547         case trap_Power_On:                             /* this trap executes on the ICS */
1548             cpu_setup_ics_irq (irq_Trap, trap);         /*   so set it up */
1549             cpu_power_state = power_on;                 /*     and return to the power-on state */
1550 
1551             if (CPX2 & cpx2_INHPFARS)                   /* if auto-restart is inhibited */
1552                 status = STOP_ARSINH;                   /*   then exit and wait for a manual restart */
1553             break;
1554         }                                               /* all cases are handled */
1555 
1556 
1557     if (label != 0) {                                   /* if the trap handler is to be called */
1558         STA = STATUS_M;                                 /*   then clear the status and enter privileged mode */
1559 
1560         SM = SM + 1 & R_MASK;                           /* increment the stack pointer */
1561         cpu_write_memory (stack, SM, parameter);        /*   and push the parameter on the stack */
1562 
1563         X = CIR;                                        /* save the current instruction for restarting */
1564 
1565         cpu_call_procedure (label, 0);                  /* set up PB, P, PL, and STA to call the procedure */
1566 
1567         cpu_base_changed = TRUE;                        /* one or more base registers have changed */
1568         }
1569 
1570     sim_interval = sim_interval - 1;                    /* count the execution cycle that aborted */
1571     }
1572 
1573 
1574 /* Instruction loop */
1575 
1576 while (status == SCPE_OK) {                             /* execute until simulator status prevents continuation */
1577 
1578     if (sim_interval <= 0) {                            /* if an event timeout has expired */
1579         status = sim_process_event ();                  /*   then call the event service */
1580 
1581         if (status != SCPE_OK)                          /* if the service failed */
1582             break;                                      /*   then abort execution and report the failure */
1583         }
1584 
1585     if (sel_request)                                    /* if a selector channel request is pending */
1586         sel_service (1);                                /*   then service it */
1587 
1588     if (mpx_request_set)                                /* if a multiplexer channel request is pending */
1589         mpx_service (1);                                /*   then service it */
1590 
1591     if (iop_interrupt_request_set                       /* if a hardware interrupt request is pending */
1592       && STA & STATUS_I                                 /*   and interrupts are enabled */
1593       && CIR != SED_1)                                  /*     and not deferred by a SED 1 instruction */
1594         device = iop_poll ();                           /*       then poll to acknowledge the request */
1595 
1596     if (cpu_micro_state != halted                       /* if the micromachine is not halted */
1597       && sim_brk_summ != 0                              /*   and a breakpoint exists */
1598       && sim_brk_test (TO_PA (PBANK, P - 1 & LA_MASK),  /*     at the next location */
1599                        BP_EXEC)) {                      /*       to be executed */
1600         status = STOP_BRKPNT;                           /*         then stop the simulation */
1601         sim_interval = sim_interval + 1;                /*           and don't count the cycle */
1602         }
1603 
1604     else if (cpu_micro_state == running)                /* otherwise if the micromachine is running */
1605         if (CPX1 & CPX1_IRQ_SET                         /*   then if a run-mode interrupt is pending */
1606           && cpu_power_state != power_failing)          /*     and power is not currently failing */
1607             cpu_run_mode_interrupt (device);            /*       then service it */
1608 
1609         else {                                              /* otherwise execute the next instruction */
1610             if (TRACING (cpu_dev, DEB_EXEC | DEB_REG)) {    /* if execution or register tracing is enabled */
1611                 if (cpu_dev.dctrl & DEB_EXEC)               /*   then if tracing execution */
1612                     if (STA & STATUS_R)                     /*     then if the right-hand stack op is pending */
1613                         exec_test =                         /*       then the execution test succeeds if */
1614                            (CIR << STACKOP_A_SHIFT          /*         the right-hand stack op */
1615                              & STACKOP_A_MASK               /*           matches the test criteria */
1616                              & exec_mask) == exec_match;    /*             for the left-hand stack op value */
1617                     else                                    /*     otherwise */
1618                         exec_test =                         /*       then the execution test succeeds if */
1619                            (NIR & exec_mask) == exec_match; /*         the next instruction matches the test criteria */
1620                 else                                        /*   otherwise */
1621                     exec_test = FALSE;                      /*     there is no execution test */
1622 
1623                 if (cpu_dev.dctrl & DEB_EXEC                /* if execution tracing is enabled */
1624                   && cpu_dev.dctrl != DEB_ALL               /*   and is currently inactive */
1625                   && exec_test) {                           /*     and the matching test succeeds */
1626                     debug_save = cpu_dev.dctrl;             /*       then save the current trace flag set */
1627                     cpu_dev.dctrl = DEB_ALL;                /*         and turn on full tracing */
1628                     }
1629 
1630                 if (cpu_dev.dctrl & DEB_REG) {              /* if register tracing is enabled */
1631                     hp_trace (&cpu_dev, DEB_REG,            /*   then output the active TOS registers */
1632                               stack_formats [SR],
1633                               SBANK, SM, SR, RA, RB, RC, RD);
1634 
1635                     fprintf (sim_deb, "X %06o, %s\n",       /* output the index and status registers */
1636                              X, fmt_status (STA));
1637 
1638                     if (cpu_base_changed) {                 /* if the base registers have been altered */
1639                         hp_trace (&cpu_dev, DEB_REG,        /*   then output the base register values */
1640                                   BOV_FORMAT "  PB %06o, PL %06o, DL %06o, DB %06o, Q %06o, Z %06o\n",
1641                                   DBANK, 0, STATUS_CS (STA),
1642                                   PB, PL, DL, DB, Q, Z);
1643 
1644                         cpu_base_changed = FALSE;           /* clear the base registers changed flag */
1645                         }
1646                     }
1647 
1648                 if (cpu_dev.dctrl & DEB_EXEC                /* if execution tracing is enabled */
1649                   && cpu_dev.dctrl == DEB_ALL               /*   and is currently active */
1650                   && ! exec_test) {                         /*     and the matching test fails */
1651                     cpu_dev.dctrl = debug_save;             /*       then restore the saved debug flag set */
1652                     hp_trace (&cpu_dev, DEB_EXEC,           /*         and add a separator to the trace log */
1653                               "*****************\n");
1654                     }
1655                 }
1656 
1657             if (!(STA & STATUS_R)) {                    /* (NEXT) if the right-hand stack op is not pending */
1658                 CIR = NIR;                              /*   then update the current instruction */
1659                 cpu_read_memory (fetch, P, &NIR);       /*     and load the next instruction */
1660                 }
1661 
1662             P = P + 1 & R_MASK;                         /* point to the following instruction */
1663 
1664             if (TRACING (cpu_dev, DEB_INSTR)) {             /* if instruction tracing is enabled */
1665                 sim_eval [0] = CIR;                         /*   then save the instruction that will be executed */
1666                 sim_eval [1] = NIR;                         /*     and the following word for evaluation */
1667 
1668                 hp_trace (&cpu_dev, DEB_INSTR, BOV_FORMAT,  /* print the address and the instruction opcode */
1669                           PBANK, P - 2 & R_MASK, CIR);      /*   as an octal value */
1670 
1671                 if (fprint_cpu (sim_deb, sim_eval, 0, SIM_SW_STOP) == SCPE_ARG) /* print the mnemonic; if that fails */
1672                     fprint_val (sim_deb, sim_eval [0], cpu_dev.dradix,          /*   then print the numeric */
1673                                 cpu_dev.dwidth, PV_RZRO);                       /*     value again */
1674 
1675                 fputc ('\n', sim_deb);                      /* end the trace with a newline */
1676                 }
1677 
1678             status = machine_instruction ();            /* execute one machine instruction */
1679 
1680             cpu_stop_flags = sim_stops;                 /* reset the stop flags as indicated */
1681             }
1682 
1683     else if (cpu_micro_state == paused) {               /* otherwise if the micromachine is paused */
1684         if (CPX1 & CPX1_IRQ_SET)                        /*   then if a run-mode interrupt is pending */
1685             cpu_run_mode_interrupt (device);            /*     then service it */
1686 
1687         else if (sim_idle_enab                          /*   otherwise if idling is enabled */
1688           && ! sel_request && mpx_request_set == 0)     /*     and there are no channel requests pending */
1689             sim_idle (TMR_PCLK, FALSE);                 /*       then idle the simulator */
1690         }
1691 
1692     else if (CPX2 & CPX2_IRQ_SET)                       /* otherwise if a halt-mode interrupt is pending */
1693         status = halt_mode_interrupt (device);          /*   then service it */
1694 
1695     sim_interval = sim_interval - 1;                    /* count the execution cycle */
1696     }                                                   /*   and continue with the instruction loop */
1697 
1698 
1699 /* Instruction postlude */
1700 
1701 cpu_dev.dctrl = debug_save;                             /* restore the flag set */
1702 
1703 cpu_update_pclk ();                                     /* update the process clock */
1704 clk_update_counter ();                                  /*   and system clock counters */
1705 
1706 if (cpu_micro_state == paused)                          /* if the micromachine is paused */
1707     P = P - 2 & R_MASK;                                 /*   then set P to point to the PAUS instruction */
1708 
1709 else if (cpu_micro_state == running)                    /* otherwise if it is running */
1710     if (status <= STOP_RERUN)                           /*   then if the instruction will be rerun when resumed */
1711         P = P - 2 & R_MASK;                             /*     then set P to point to it */
1712     else                                                /*   otherwise */
1713         P = P - 1 & R_MASK;                             /*     set P to point to the next instruction */
1714 
1715 cpu_micro_state = halted;                               /* halt the micromachine */
1716 
1717 if (cpu_power_state == power_failing                    /* if power is failing */
1718   && status == STOP_HALT)                               /*   and we executed a HALT instruction */
1719     cpu_power_state = power_off;                        /*     then power will be off when we return */
1720 
1721 if (TRACING (cpu_dev, cpu_dev.dctrl)                    /* if instruction tracing is enabled */
1722   && status <= SCPE_LAST)                               /*   and the status is valid */
1723     hp_trace (&cpu_dev, cpu_dev.dctrl,                  /*     then output the simulation stop reason */
1724               BOV_FORMAT "simulation stop: %s\n",
1725               PBANK, P, STA,
1726               status >= SCPE_BASE ? sim_error_text (status)
1727                                   : sim_stop_messages [status]);
1728 
1729 if (sim_switches & SIM_SW_HIDE                          /* if executing in a non-echoing command file */
1730   && (status == SCPE_STEP || status == STOP_BRKPNT))    /*   and a step or breakpoint stop occurs */
1731     return SCPE_OK;                                     /*     then do not report the stop reason */
1732 else                                                    /* otherwise */
1733     return status;                                      /*   return the status code that caused the stop */
1734 }
1735 
1736 
1737 /* Execute the LOAD and DUMP commands.
1738 
1739    This command processing routine implements the cold load and cold dump
1740    commands.  The syntax is:
1741 
1742      LOAD { <control/devno> }
1743      DUMP { <control/devno> }
1744 
1745    The <control/devno> is a number that is deposited into the SWCH register
1746    before invoking the CPU cold load or cold dump facility.  The CPU radix is
1747    used to interpret the number; it defaults to octal.  If the number is
1748    omitted, the SWCH register value is not altered before loading or dumping.
1749 
1750    On entry, the "arg" parameter is "Cold_Load" for a LOAD command and
1751    "Cold_Dump" for a DUMP command, and "buf" points at the remainder of the
1752    command line.  If characters exist on the command line, they are parsed,
1753    converted to a numeric value, and stored in the SWCH register.  Then the
1754    CPU's cold load/dump routine is called to set up the CPU state.  Finally, the
1755    CPU is started to begin the requested action.
1756 
1757 
1758    Implementation notes:
1759 
1760     1. The RUN command uses the RU_CONT argument instead of RU_RUN so that the
1761        run_cmd SCP routine will not reset all devices before entering the
1762        instruction executor.  The halt mode interrupt handlers for cold load and
1763        cold dump reset the simulator as appropriate for their commands (i.e.,
1764        the CPU and all I/O devices, or just the I/O devices, respectively).
1765 */
1766 
cpu_cold_cmd(int32 arg,char * buf)1767 t_stat cpu_cold_cmd (int32 arg, char *buf)
1768 {
1769 const char *cptr;
1770 char       gbuf [CBUFSIZE];
1771 t_stat     status;
1772 HP_WORD    value;
1773 
1774 if (*buf != '\0') {                                     /* if more characters exist on the command line */
1775     cptr = get_glyph (buf, gbuf, 0);                    /*   then get the next glyph */
1776 
1777     if (*cptr != '\0')                                  /* if that does not exhaust the input */
1778         return SCPE_2MARG;                              /*   then report that there are too many arguments */
1779 
1780     value = (HP_WORD) get_uint (gbuf, cpu_dev.dradix,   /* get the parameter value */
1781                                 D16_UMAX, &status);
1782 
1783     if (status == SCPE_OK)                              /* if a valid number was present */
1784         SWCH = value;                                   /*   then set it into the switch register */
1785     else                                                /* otherwise */
1786         return status;                                  /*   return the error status */
1787     }
1788 
1789 else if (arg == Cold_Dump)                              /* otherwise if no dump value was given */
1790     SWCH = dump_control;                                /*   then use the system control panel presets */
1791 
1792 cpu_front_panel (SWCH, (PANEL_TYPE) arg);               /* set up the cold load or dump microcode */
1793 
1794 return run_cmd (RU_CONT, buf);                          /* execute the halt-mode routine */
1795 }
1796 
1797 
1798 /* Execute the POWER commands.
1799 
1800    This command processing routine is called to initiate a power failure or
1801    power restoration.  The "cptr" parameter points to the power option keyword;
1802    the "arg" parameter is not used.
1803 
1804    The routine processes commands of the form:
1805 
1806      POWER { FAIL | OFF | DOWN }
1807      POWER { RESTORE | ON | UP }
1808 
1809    In simulation, the "cpu_power_state" global variable indicates the current
1810    state of system power.  The simulator starts in the power_on state.  The
1811    POWER FAIL command moves from the power_on to the power_failing state if the
1812    CPU is running, or to the power_off state if it is not.  Execution of a HALT
1813    in the power_failing state moves to the power_off state.  The POWER RESTORE
1814    command moves from the power_off to the power_returning state if the CPU is
1815    running, or to the power_on state if it is not.  Execution of the power-on
1816    trap moves from the power_returning to the power_on state.
1817 
1818    The POWER FAIL and POWER RESTORE commands are only valid in the power_on and
1819    power_off states, respectively; otherwise, they print "Command not allowed."
1820 
1821    The four enumeration values model the states of the PON (power on) and PFW
1822    (power-fail warning) hardware signals, as follows:
1823 
1824      PON  PFW  State            Simulator Action
1825      ---  ---  ---------------  ----------------------------
1826       1    0   power on         executing normally
1827       1    1   power failing    executing with cpx1_PFINTR
1828       0    1   power off        will not execute
1829       0    0   power returning  executing with trap_Power_On
1830 
1831    In microcode, the power-fail routine writes the current value of the CPX2
1832    register to the word following the last word of the ICS.  This value is used
1833    by the power-on routine to decide if the CPU was running (cpx2_RUN bit is
1834    set) or halted at the time of the power failure.  A power failure is
1835    indicated by setting the cpx1_PFINTR bit in the CPX1 register; this causes an
1836    interrupt to the power-failure routine in the operating system, which
1837    performs an orderly shutdown followed by a programmed HALT to wait for power
1838    to die.  When power is restored, the power-on trap (trap_Power_On) is set up,
1839    and then, if the PF/ARS switch is in the "enable" position, the trap is
1840    taken, which restarts the operating system and any I/O that was in progress
1841    when power failed.  If the switch is in the "disable" position, the CPU
1842    remains halted, and the trap is taken when the RUN button is pressed.
1843 
1844    The POWER commands are entered at the SCP prompt.  If the machine was running
1845    at the time of power failure, execution is resumed automatically to execute
1846    the power-fail or power-restore OS routines.  If the machine was halted when
1847    the POWER commands were entered, the machine remains halted -- just the power
1848    state changes.
1849 
1850 
1851    Implementation notes:
1852 
1853     1. In hardware, when the power fail interrupt is serviced, the microcode
1854        sets the PWR INH flip-flop, which locks out the RUN switch and inhibits
1855        all other halt-mode (CPX2) and run-mode (CPX1) interrupts until the CPU
1856        is reset.  This ensures that the software power-fail interrupt handler
1857        executes unimpeded.  In simulation, a POWER FAIL command with the CPU
1858        running sets the power-fail interrupt bit in the CPX1 register and
1859        resumes execution in the power_on state.  When the interrupt is detected
1860        by the "cpu_run_mode_interrupt" routine, the state is changed to
1861        power_failing.  In this state, run-mode interrupts are not recognized.
1862        Halt-mode interrupts need no special handling, as the power state is
1863        changed to power_off when the CPU halts.  Therefore, the CPU is never in
1864        a "halted-and-waiting-for-power-to-fade-away" state.
1865 
1866     2. The RUN command uses the RU_CONT argument instead of RU_RUN so that the
1867        run_cmd SCP routine will not reset all devices before entering the
1868        instruction executor.  The halt-mode interrupt handlers for cold load and
1869        cold dump reset the simulator as appropriate for their commands (i.e.,
1870        the CPU and all I/O devices, or just the I/O devices, respectively).
1871 
1872     3. In order to set up the power-on trap, this routine presses the RUN button
1873        and continues the simulation.  After the trap is set up in the
1874        "sim_instr" routine, the halt-mode interrupt handler checks the PF/ARS
1875        switch and stops simulation if auto-restart is disabled.
1876 */
1877 
cpu_power_cmd(int32 arg,char * cptr)1878 t_stat cpu_power_cmd (int32 arg, char *cptr)
1879 {
1880 static CTAB options [] = {
1881     { "FAIL",    NULL, power_failing   },
1882     { "RESTORE", NULL, power_returning },
1883     { "OFF",     NULL, power_failing   },
1884     { "ON",      NULL, power_returning },
1885     { "DOWN",    NULL, power_failing   },
1886     { "UP",      NULL, power_returning },
1887     { NULL }
1888     };
1889 
1890 char    gbuf [CBUFSIZE];
1891 CTAB    *ctptr;
1892 HP_WORD zi, failure_cpx2;
1893 t_stat  status;
1894 
1895 if (cptr == NULL || *cptr == '\0')                      /* if there is no option word */
1896     return SCPE_2FARG;                                  /*   then report a missing argument */
1897 
1898 cptr  = get_glyph (cptr, gbuf, 0);                      /* parse (and upshift) the option specified */
1899 ctptr = find_ctab (options, gbuf);                      /*   and look it up in the option table */
1900 
1901 if (ctptr == NULL)                                      /* if the option is not valid */
1902     status = SCPE_ARG;                                  /*   then report a bad argument */
1903 
1904 else if (*cptr != '\0')                                 /* otherwise if something follows the option */
1905     return SCPE_2MARG;                                  /*   then report too many arguments */
1906 
1907 else if (ctptr->arg == power_failing)                   /* otherwise if a power-fail option was given */
1908     if (cpu_power_state != power_on)                    /*   but the CPU power is not on */
1909         status = SCPE_NOFNC;                            /*     then the command is not allowed */
1910 
1911     else {                                              /* otherwise the failure is valid */
1912         iop_assert_PFWARN ();                           /*   so send a power-fail warning to all devices */
1913 
1914         cpu_read_memory (absolute, ICS_Z, &zi);         /* get the ICS stack limit */
1915         cpu_write_memory (absolute, zi + 1, CPX2);      /*   and save the CPX2 value in the following word */
1916 
1917         if (CPX2 & cpx2_RUN) {                          /* if the CPU is currently running */
1918             CPX1 |= cpx1_PFINTR;                        /*   then set the power-fail interrupt */
1919             CPX2 |= cpx2_RUNSWCH;                       /*     and assume a RUN command */
1920             status = run_cmd (RU_CONT, cptr);           /*       and continue execution */
1921             }
1922 
1923         else {                                          /* otherwise the CPU is currently halted */
1924             cpu_power_state = power_off;                /*   so remain halted in the "power is off" state */
1925             status = SCPE_OK;                           /*     and return command success */
1926             }
1927         }
1928 
1929 else if (ctptr->arg == power_returning)                 /* otherwise if a power-restoration option was given */
1930     if (cpu_power_state != power_off)                   /*   but the CPU power is not off */
1931         status = SCPE_NOFNC;                            /*     then the command is not allowed */
1932 
1933     else {                                              /* otherwise the restoration is valid */
1934         reset_all_p (0);                                /*   so reset all devices to their power on states */
1935 
1936         cpu_read_memory (absolute, ICS_Z, &zi);             /* get the ICS stack limit */
1937         cpu_read_memory (absolute, zi + 1, &failure_cpx2);  /*   and get the value of CPX2 at the time of failure */
1938         cpu_write_memory (absolute, zi + 1, CPX2);          /*     and replace it with the current CPX2 value */
1939 
1940         if (failure_cpx2 & cpx2_RUN) {                  /* if the CPU was running at the time of power failure */
1941             cpu_power_state = power_returning;          /*   then move to the "power is returning" state */
1942             CPX2 |= cpx2_RUNSWCH;                       /*     and assume a RUN command */
1943             status = run_cmd (RU_CONT, cptr);           /*       and continue execution */
1944             }
1945 
1946         else {                                          /* otherwise the CPU was halted when power failed */
1947             cpu_power_state = power_on;                 /*   so remain halted in the "power is on" state */
1948             status = SCPE_OK;                           /*     and return command success */
1949             }
1950         }
1951 
1952 else                                                    /* otherwise a valid option has no handler */
1953     status = SCPE_IERR;                                 /*   so report an internal error */
1954 
1955 return status;                                          /* return the operation status */
1956 }
1957 
1958 
1959 
1960 /* CPU global utility routines */
1961 
1962 
1963 /* Process a run-mode interrupt.
1964 
1965    This routine is called when one or more of the interrupt request bits are set
1966    in the CPX1 register.  The highest-priority request is identified and
1967    cleared, the interrupt classification and parameter are established, and the
1968    associated interrupt handler is set up for execution.  On return, the CPU has
1969    been configured and is ready to execute the first instruction in the handler.
1970 
1971    On entry, the routine first checks for an external interrupt alone; this is
1972    done to improve performance, as this is the most common case.  If some other
1973    interrupt is requested, or if multiple interrupts are requested, the CPX1
1974    register is scanned from MSB to LSB to identify the request.
1975 
1976 
1977    Implementation notes:
1978 
1979     1. In hardware, halting the CPU while a PAUS instruction is executing leaves
1980        P pointing to the following instruction, which is executed when the RUN
1981        button is pressed.  In simulation, this action occurs only when execution
1982        is resumed with the "-B" option to bypass the pause.  Otherwise, resuming
1983        (or stepping) continues with the PAUS instruction.
1984 
1985        If an interrupt occurs while PAUS is executing, the interrupt handler
1986        will return to the instruction following the PAUS, as though HALT and RUN
1987        had been pressed.  This occurs because the P register normally points two
1988        instructions past the instruction currently executing.  When an interrupt
1989        occurs, P is decremented to point at the instruction after the current
1990        instruction, which is the correct point of return after the interrupt
1991        service routine completes.
1992 
1993        When the simulator is stopped, P is backed up to point at the next
1994        instruction to execute.  In the case of a PAUS instruction, the "next
1995        instruction" is the same PAUS instruction.  When simulation resumes, the
1996        PAUS instruction is fetched into the NIR, and P is incremented.  If no
1997        interrupt is pending, the main instruction execution loop copies the NIR
1998        into the CIR, prefetches the instruction following the PAUS into the NIR,
1999        and increments P again, so that it points two instructions beyond the
2000        current instruction.  At this point, everything is set up properly as
2001        before the simulation stop.
2002 
2003        However, if an interrupt is pending when simulation resumes, this routine
2004        is called before the NIR-to-CIR operation is performed, so P still points
2005        one instruction beyond the PAUS.  Stacking the usual P - 1 value would
2006        cause the interrupt handler to return to the PAUS instruction instead of
2007        to the instruction following, as would have occurred had a simulation
2008        stop not been involved.
2009 
2010        Therefore, when resuming from a simulator stop, the SS_PAUSE_RESUMED flag
2011        is set in the "cpu_stop_flags" variable by the "halt_mode_interrupt"
2012        routine if a PAUS instruction is in the NIR after reloading.  If an
2013        interrupt is pending, this routine will be entered with the flag set, and
2014        we then increment P so that it is correctly set to point two instructions
2015        beyond the PAUS before handling the interrupt.  If an interrupt is not
2016        pending on resumption, the P adjustment is performed as described above,
2017        and P will be set properly when the next interrupt occurs.
2018 
2019        A special case occurs when resuming into a PAUS from a simulator stop if
2020        a higher-priority interrupt occurs immediately after handling a pending
2021        lower-priority interrupt.  In this case, this routine will be entered a
2022        second time before the instruction execution loop performs the NIR-to-CIR
2023        operation.  Although the PAUS is still in the CIR, we must not increment
2024        P a second time, because the instruction now being interrupted is not the
2025        PAUS but is the first instruction of the lower-priority interrupt routine
2026        that never had a chance to execute.  Wo do this by clearing the
2027        SS_PAUSE_RESUMED flag after the first increment.
2028 */
2029 
cpu_run_mode_interrupt(HP_WORD device_number)2030 void cpu_run_mode_interrupt (HP_WORD device_number)
2031 {
2032 HP_WORD   request_set, request_count, parameter;
2033 IRQ_CLASS class;
2034 
2035 if (cpu_stop_flags & SS_PAUSE_RESUMED) {                /* if we are resuming into a PAUS instruction */
2036     P = P + 1 & R_MASK;                                 /*   then set the return to the instruction following */
2037     cpu_stop_flags &= ~SS_PAUSE_RESUMED;                /*     and clear the flag in case of back-to-back interrupts */
2038     }
2039 
2040 cpu_micro_state = running;                              /* the micromachine may be paused but is no longer */
2041 
2042 request_set = CPX1 & CPX1_IRQ_SET;                      /* get the set of active interrupt requests */
2043 
2044 if (request_set == cpx1_EXTINTR) {                      /* if only an external request is present */
2045     class = irq_External;                               /*   (the most common case) then set the class */
2046     parameter = device_number;                          /*     and set the parameter to the device number */
2047     }
2048 
2049 else {                                                  /* otherwise scan for the class */
2050     request_count = 0;                                  /*   where CPX1.1 through CPX1.9 */
2051     request_set = D16_SIGN;                             /*     correspond to IRQ classes 1-9 */
2052 
2053     while ((CPX1 & request_set) == 0) {                 /* scan from left to right for the first request */
2054         request_count = request_count + 1;              /*   while incrementing the request number */
2055         request_set = request_set >> 1;                 /*     and shifting the current request bit */
2056         }
2057 
2058     class = (IRQ_CLASS) request_count;                  /* set the class from the request count */
2059 
2060     if (class == irq_Integer_Overflow) {                /* if an integer overflow occurred */
2061         parameter = 1;                                  /*   then set the parameter to 1 */
2062         STA &= ~STATUS_O;                               /*     and clear the overflow flag */
2063         }
2064 
2065     else if (class == irq_External)                     /* otherwise if an external interrupt occurred */
2066         parameter = device_number;                      /*   then set the parameter to the device number */
2067 
2068     else if (class == irq_Module) {                     /* otherwise if the class is a module interrupt */
2069         parameter = UPPER_BYTE (MOD);                   /*   then the parameter is the module number */
2070         MOD = 0;                                        /* clear the register to prevent a second interrupt */
2071         }
2072 
2073     else if (class == irq_Power_Fail) {                 /* otherwise if a power fail interrupt occurred */
2074         parameter = TO_LABEL (LABEL_IRQ, class);        /*   then the parameter is the label */
2075         cpu_power_state = power_failing;                /*     and system power is now failing */
2076         }
2077 
2078     else                                                /* otherwise the parameter */
2079         parameter = TO_LABEL (LABEL_IRQ, class);        /*   is the label */
2080     }
2081 
2082 CPX1 &= ~request_set;                                   /* clear the associated CPX request bit */
2083 
2084 tprintf (cpu_dev, DEB_INSTR, BOV_FORMAT "%s interrupt\n",
2085          PBANK, P - 1 & R_MASK, parameter, interrupt_name [class]);
2086 
2087 cpu_setup_irq_handler (class, parameter);               /* set up the entry into the interrupt handler */
2088 
2089 return;
2090 }
2091 
2092 
2093 /* Set up a front panel operation.
2094 
2095    This routine sets the SWCH register to the supplied value and then sets the
2096    appropriate bit in the CPX2 register.  This will cause a halt-mode interrupt
2097    when simulated execution is resumed.
2098 
2099 
2100    Implementation notes:
2101 
2102     1. We do this here to avoid having to export the registers and CPX values
2103        globally.
2104 */
2105 
cpu_front_panel(HP_WORD switch_reg,PANEL_TYPE request)2106 void cpu_front_panel (HP_WORD switch_reg, PANEL_TYPE request)
2107 {
2108 SWCH = switch_reg;                                      /* set the SWCH register value */
2109 
2110 switch (request) {                                      /* dispatch on the request type */
2111 
2112     case Run:                                           /* a run request */
2113         CPX2 |= cpx2_RUNSWCH;                           /* set the RUN switch */
2114         break;
2115 
2116     case Cold_Load:                                     /* a cold load request */
2117         CPX2 |= cpx2_LOADSWCH;                          /* set the LOAD switch */
2118         break;
2119 
2120     case Cold_Dump:                                     /* a cold dump request */
2121         CPX2 |= cpx2_DUMPSWCH;                          /* set the DUMP switch */
2122         break;
2123     }                                                   /* all cases are handled */
2124 
2125 return;
2126 }
2127 
2128 
2129 /* Update the process clock.
2130 
2131    If the process clock is currently calibrated, then the service interval is
2132    actually ten times the hardware period of 1 millisecond.  This provides
2133    sufficient event service call spacing to allow idling to work.
2134 
2135    To present the correct value when the process clock is read, this routine is
2136    called to increment the count by an amount proportional to the fraction of
2137    the service interval that has elapsed.  In addition, it is called by the CPU
2138    instruction postlude, so that the PCLK register will have the correct value
2139    if it is examined from the SCP command prompt.
2140 */
2141 
cpu_update_pclk(void)2142 void cpu_update_pclk (void)
2143 {
2144 int32 elapsed, ticks;
2145 
2146 if (cpu_is_calibrated) {                                /* if the process clock is calibrated */
2147     elapsed = cpu_unit [0].wait                         /*   then the elapsed time is the original wait time */
2148                 - sim_activate_time (&cpu_unit [0]);    /*     less the time remaining before the next service */
2149 
2150     ticks =                                             /* the adjustment is */
2151        (elapsed * PCLK_MULTIPLIER) / cpu_unit [0].wait  /*   the elapsed fraction of the multiplier */
2152          - (PCLK_MULTIPLIER - pclk_increment);          /*     less the amount of any adjustment already made */
2153 
2154     PCLK = PCLK + ticks & R_MASK;                       /* update the process clock counter with rollover */
2155     pclk_increment = pclk_increment - ticks;            /*   and reduce the amount remaining to add at service */
2156     }
2157 
2158 return;
2159 }
2160 
2161 
2162 
2163 /* CPU global instruction execution routines */
2164 
2165 
2166 /* Push the stack down.
2167 
2168    This routine implements the PUSH micro-order to create space on the stack for
2169    a new value.  On return, the new value may be stored in the RA register.
2170 
2171    If the SR register indicates that all of the TOS registers are in use, then
2172    the RD register is freed by performing a queue down.  Then the values in the
2173    TOS registers are shifted down, freeing the RA register.  Finally, SR is
2174    incremented in preparation for the store.
2175 */
2176 
cpu_push(void)2177 void cpu_push (void)
2178 {
2179 if (SR == 4)                                            /* if all TOS registers are full */
2180     cpu_queue_down ();                                  /*   then move the RD value to memory */
2181 
2182 RD = RC;                                                /* shift */
2183 RC = RB;                                                /*   the register */
2184 RB = RA;                                                /*     values down */
2185 
2186 SR = SR + 1;                                            /* increment the register-in-use count */
2187 
2188 return;
2189 }
2190 
2191 
2192 /* Pop the stack up.
2193 
2194    This routine implements the POP micro-order to delete the top-of-stack value.
2195 
2196    On entry, if the SR register indicates that all of the TOS registers are
2197    empty, then if decrementing the SM register would move it below the DB
2198    register value, and the CPU is not in privileged mode, then a Stack Underflow
2199    trap is taken.  Otherwise, the stack memory pointer is decremented.
2200 
2201    If one or more values exist in the TOS registers, the values are shifted up,
2202    deleting the previous value in the RA register, and SR is decremented.
2203 */
2204 
cpu_pop(void)2205 void cpu_pop (void)
2206 {
2207 if (SR == 0) {                                          /* if the TOS registers are empty */
2208     if (SM <= DB && NPRV)                               /*   then if SM isn't above DB and the mode is non-privileged */
2209         MICRO_ABORT (trap_Stack_Underflow);             /*     then trap with a Stack Underflow */
2210 
2211     SM = SM - 1 & R_MASK;                               /* decrement the stack memory register */
2212     }
2213 
2214 else {                                                  /* otherwise at least one TOS register is occupied */
2215     RA = RB;                                            /*   so shift */
2216     RB = RC;                                            /*     the register */
2217     RC = RD;                                            /*       values up */
2218 
2219     SR = SR - 1;                                        /* decrement the register-in-use count */
2220     }
2221 
2222 return;
2223 }
2224 
2225 
2226 /* Queue a value from memory up to the register file.
2227 
2228    This routine implements the QUP micro-order to move the value at the top of
2229    the memory stack into the bottom of the TOS register file.  There must be a
2230    free TOS register when this routine is called.
2231 
2232    On entry, if decrementing the SM register would move it below the DB register
2233    value, and the CPU is not in privileged mode, then a Stack Underflow trap is
2234    taken.  Otherwise, the value pointed to by SM is read into the first unused
2235    TOS register, SM is decremented to account for the removed value, and SR is
2236    incremented to account for the new TOS register in use.
2237 
2238 
2239    Implementation notes:
2240 
2241     1. SR must be less than 4 on entry, so that TR [SR] is the first unused TOS
2242        register.
2243 
2244     2. SM and SR must not be modified within the call to cpu_read_memory.  For
2245        example, SR++ cannot be passed as a parameter.
2246 */
2247 
cpu_queue_up(void)2248 void cpu_queue_up (void)
2249 {
2250 if (SM <= DB && NPRV)                                   /* if SM isn't above DB and the mode is non-privileged */
2251     MICRO_ABORT (trap_Stack_Underflow);                 /*   then trap with a Stack Underflow */
2252 
2253 else {                                                  /* otherwise */
2254     cpu_read_memory (stack, SM, &TR [SR]);              /*   read the value from memory into a TOS register */
2255 
2256     SM = SM - 1 & R_MASK;                               /* decrement the stack memory register */
2257     SR = SR + 1;                                        /*   and increment the register-in-use count */
2258     }
2259 
2260 return;
2261 }
2262 
2263 
2264 /* Queue a value from the register file down to memory.
2265 
2266    This routine implements the QDWN micro-order to move the value at the bottom
2267    of the TOS register file into the top of the memory stack.  There must be a
2268    TOS register in use when this routine is called.
2269 
2270    On entry, if incrementing the SM register would move it above the Z register
2271    value, then a Stack Overflow trap is taken.  Otherwise, SM is incremented to
2272    account for the new value written, SR is decremented to account for the TOS
2273    register removed from use, and the value in that TOS register is written into
2274    memory at the top of the memory stack.
2275 
2276 
2277    Implementation notes:
2278 
2279     1. SR must be greater than 0 on entry, so that TR [SR - 1] is the last TOS
2280        register in use.
2281 
2282     2. SM and SR must not be modified within the call to cpu_write_memory.  For
2283        example, SR-- cannot be passed as a parameter.
2284 */
2285 
cpu_queue_down(void)2286 void cpu_queue_down (void)
2287 {
2288 if (SM >= Z)                                            /* if SM isn't below Z */
2289     MICRO_ABORT (trap_Stack_Overflow);                  /*   then trap with a Stack Overflow */
2290 
2291 SM = SM + 1 & R_MASK;                                   /* increment the stack memory register */
2292 SR = SR - 1;                                            /*   and decrement the register-in-use count */
2293 
2294 cpu_write_memory (stack, SM, TR [SR]);                  /* write the value from a TOS register to memory */
2295 
2296 return;
2297 }
2298 
2299 
2300 /* Flush the register file.
2301 
2302    This routine implements the PSHA microcode subroutine that writes the values
2303    of all TOS registers in use to the memory stack.  As each value is written,
2304    the SM register is incremented and the SR register is decremented.  On
2305    return, the SR register value will be zero.
2306 
2307    The routine does not check for stack overflow.
2308 */
2309 
cpu_flush(void)2310 void cpu_flush (void)
2311 {
2312 while (SR > 0) {                                        /* while one or more registers are in use */
2313     SM = SM + 1 & R_MASK;                               /*   increment the stack memory register */
2314     SR = SR - 1;                                        /*     and decrement the register-in-use count */
2315 
2316     cpu_write_memory (stack, SM, TR [SR]);              /* write the value from a TOS register to memory */
2317     }
2318 
2319 return;
2320 }
2321 
2322 
2323 /* Adjust SR until it reaches a specified value.
2324 
2325    This routine implements the SRP1-SRP4 microcode subroutines that adjust the
2326    stack until the prescribed number (1-4) of TOS registers are occupied.  It
2327    performs queue ups, i.e., moves values from the top of the memory stack to
2328    the bottom of the register file, until the specified SR value is reached.
2329    Stack underflow is checked after the all of the values have been moved.  The
2330    routine assumes that at least one value must be moved.
2331 
2332 
2333    Implementation notes:
2334 
2335     1. SR must be greater than 0 on entry, so that TR [SR - 1] is the last TOS
2336        register in use.
2337 
2338     2. SM and SR must not be modified within the call to cpu_read_memory.  For
2339        example, SR++ cannot be passed as a parameter.
2340 
2341     3. The cpu_queue_up routine isn't used, as that routine checks for a stack
2342        underflow after each word is moved rather than only after the last word.
2343 */
2344 
cpu_adjust_sr(uint32 target)2345 void cpu_adjust_sr (uint32 target)
2346 {
2347 do {
2348     cpu_read_memory (stack, SM, &TR [SR]);              /* read the value from memory into a TOS register */
2349 
2350     SM = SM - 1 & R_MASK;                               /* decrement the stack memory register */
2351     SR = SR + 1;                                        /*   and increment the register-in-use count */
2352     }
2353 while (SR < target);                                    /* queue up until the requested number of registers are in use */
2354 
2355 if (SM <= DB && NPRV)                                   /* if SM isn't above DB, or the mode is non-privileged */
2356     MICRO_ABORT (trap_Stack_Underflow);                 /*   then trap with a Stack Underflow */
2357 
2358 return;
2359 }
2360 
2361 
2362 /* Write a stack marker to memory.
2363 
2364    This routine implements the STMK microcode subroutine that writes a four-word
2365    marker to the stack.  The format of the marker is as follows:
2366 
2367        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
2368      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2369      |                       X register value                        |  [Q - 3]  X
2370      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2371      |                  PB-relative return address                   |  [Q - 2]  P + 1 - PB
2372      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2373      |                     Status register value                     |  [Q - 1]  STA
2374      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2375      |                         Delta Q value                         |  [Q - 0]  S - Q
2376      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2377 
2378    After the values are written, the Q register is set to point to the marker.
2379 
2380    This routine is always entered with SR = 0, i.e., with the TOS registers
2381    flushed to the memory stack.  It does not check for stack overflow.
2382 
2383 
2384    Implementation notes:
2385 
2386     1. The PB-relative return address points to the instruction after the point
2387        of the call.  Conceptually, this is location P + 1, but because the CPU
2388        uses a two-instruction prefetch, the location is actually P - 1.
2389 */
2390 
cpu_mark_stack(void)2391 void cpu_mark_stack (void)
2392 {
2393 SM = SM + 4 & R_MASK;                                   /* adjust the stack pointer */
2394 
2395 cpu_write_memory (stack, SM - 3, X);                    /* push the index register */
2396 cpu_write_memory (stack, SM - 2, P - 1 - PB & LA_MASK); /*   and delta P */
2397 cpu_write_memory (stack, SM - 1, STA);                  /*     and the status register */
2398 cpu_write_memory (stack, SM - 0, SM - Q & LA_MASK);     /*       and delta Q */
2399 
2400 Q = SM;                                                 /* set Q to point to the new stack marker */
2401 
2402 return;
2403 }
2404 
2405 
2406 /* Calculate an effective memory address.
2407 
2408    This routine calculates the effective address for a memory reference or
2409    branch instruction.  On entry, "mode_disp" contains the mode, displacement,
2410    index, and indirect fields of the instruction, "classification" and "offset"
2411    point to variables to receive the corresponding values, and "selector" points
2412    to a variable to receive the byte selection ("upper" or "lower") for byte-
2413    addressable instructions or is NULL for word-addressable instructions.  On
2414    exit, "classification" is set to the memory access classification, "offset"
2415    is set to the address offset within the memory bank implied by the
2416    classification, and "selector" is set to indicate the byte referenced if the
2417    pointer is non-NULL.
2418 
2419    The mode and displacement fields of the instruction encode an address
2420    relative to one of the base registers P, DB, Q, or S, as follows:
2421 
2422        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
2423      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2424      |   memory op   | X | I |         mode and displacement         |
2425      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2426                              | 0 | 0 |     P+ displacement 0-255     |
2427                              +---+---+---+---+---+---+---+---+---+---+
2428                              | 0 | 1 |     P- displacement 0-255     |
2429                              +---+---+---+---+---+---+---+---+---+---+
2430                              | 1 | 0 |    DB+ displacement 0-255     |
2431                              +---+---+---+---+---+---+---+---+---+---+
2432                              | 1 | 1 | 0 |   Q+ displacement 0-127   |
2433                              +---+---+---+---+---+---+---+---+---+---+
2434                              | 1 | 1 | 1 | 0 | Q- displacement 0-63  |
2435                              +---+---+---+---+---+---+---+---+---+---+
2436                              | 1 | 1 | 1 | 1 | S- displacement 0-63  |
2437                              +---+---+---+---+---+---+---+---+---+---+
2438 
2439    The displacement encoded in the instruction is an unsigned value that is
2440    added to or subtracted from the indicated base register.
2441 
2442    If the X and I fields are both 0, the addressing is direct.  If the X field
2443    is 1, the addressing is indexed.  If the I field is 1, the addressing is
2444    indirect.  If both fields are 1, the addressing is indirect indexed, with
2445    indirection performed before indexing.
2446 
2447    To improve execution speed in hardware, a preadder is implemented that sums
2448    the offset contained in certain bits of the CIR with the index register (if
2449    enabled).  The primary use is to save a microinstruction cycle during memory
2450    reference instructions, which must add a base register, the offset in the
2451    CIR, and potentially the X register (either directly or shifted left or right
2452    by one place for LDD/STD or LDB/STB, respectively).  The preadder also serves
2453    to hold other counts obtained from the CIR, e.g., shift counts, although in
2454    these cases, the addition function is not used.
2455 
2456    This routine simulates the preadder as part of the effective address
2457    calculation.  The calculations employed for word addressing are:
2458 
2459      Direct word addressing:
2460        ea = PBANK.(P + displacement)
2461        ea = DBANK.(DB + displacement)
2462        ea = SBANK.(Q,S + displacement)
2463 
2464      Direct indexed word addressing:
2465        ea = PBANK.(P + displacement + X)
2466        ea = DBANK.(DB + displacement + X)
2467        ea = SBANK.(Q,S + displacement + X)
2468 
2469      Indirect word addressing:
2470        ea = PBANK.(P + displacement + M [PBANK.(P + displacement)])
2471        ea = DBANK.(DB + M [DBANK.(DB + displacement)])
2472        ea = DBANK.(DB + M [SBANK.(Q,S + displacement)])
2473 
2474      Indirect indexed word addressing:
2475        ea = PBANK.(P + displacement + M [PBANK.(P + displacement)] + X)
2476        ea = DBANK.(DB + M [DBANK.(DB + displacement)] + X)
2477        ea = DBANK.(DB + M [SBANK.(Q,S + displacement)] + X)
2478 
2479    The indirect cell contains either a self-relative, P-relative address or a
2480    DB-relative address, even for S or Q-relative modes.  Indirect branches with
2481    DB/Q/S-relative mode are offsets from PB, not DB.
2482 
2483    The effective address calculations employed for byte addressing are:
2484 
2485      Direct byte addressing:
2486        ea = DBANK.(DB + displacement).byte [0]
2487        ea = SBANK.(Q,S + displacement).byte [0]
2488 
2489      Direct indexed byte addressing:
2490        ea = DBANK.(DB + displacement + X / 2).byte [X & 1]
2491        ea = SBANK.(Q,S + displacement + X / 2).byte [X & 1]
2492 
2493      Indirect byte addressing:
2494        ea,I = DBANK.(DB + M [DBANK.(DB + displacement)] / 2).byte [cell & 1]
2495        ea,I = DBANK.(DB + M [SBANK.(Q,S + displacement)] / 2).byte [cell & 1]
2496 
2497      Indirect indexed byte addressing:
2498        ea,I = DBANK.(DB + (M [DBANK.(DB + displacement)] + X) / 2).byte [cell + X & 1]
2499        ea,I = DBANK.(DB + (M [SBANK.(Q,S + displacement)] + X) / 2).byte [cell + X & 1]
2500 
2501    For all modes, the displacement is a word address, whereas the indirect cell
2502    and index register contain byte offsets.  For direct addressing, the byte
2503    selected is byte 0.  For all other modes, the byte selected is the byte at
2504    (offset & 1), where the offset is the index register value, the indirect cell
2505    value, or the sum of the two.
2506 
2507    Byte offsets into data segments present problems, in that negative offsets
2508    are permitted (to access the DL-to-DB area), but there are not enough bits to
2509    represent all locations unambiguously in the potential -32K to +32K word
2510    offset range.  Therefore, a byte offset with bit 0 = 1 can represent either a
2511    positive or negative word offset from DB, depending on the interpretation.
2512    The HP 3000 adopts the convention that if the address resulting from a
2513    positive-offset interpretation does not fall within the DL-to-S range, then
2514    32K is added to the address, effectively changing the interpretation from a
2515    positive to a negative offset.  If this new address does not fall within the
2516    DL-to-S range, a Bounds Violation trap occurs if the mode is non-privileged.
2517 
2518    The reinterpretation as a negative offset is performed only if the CPU is not
2519    in split-stack mode (where either DBANK is different from SBANK, or DB does
2520    not lie between DL and Z), as extra data segments do not permit negative-DB
2521    addressing.  Reinterpretation is also not used for code segments, as negative
2522    offsets from PB are not permitted.
2523 
2524 
2525    Implementation notes:
2526 
2527     1. On entry, the program counter points to the instruction following the
2528        next instruction (i.e., the NIR location + 1).  However, P-relative
2529        offsets are calculated from the current instruction (CIR location).
2530        Therefore, we decrement P by two before adding the offset.
2531 
2532        In hardware, P-relative addresses obtained from the preadder are offset
2533        from P + 1, whereas P-relative addresses obtained by summing with
2534        P-register values obtained directly from the S-Bus are offset from P + 2.
2535        This is because the P-register increment that occurs as part of a NEXT
2536        micro-order is coincident with the R-Bus and S-Bus register loads; both
2537        operations occur when the NXT+1 signal asserts.  Therefore, the microcode
2538        handling P-relative memory reference address resolution subtracts one to
2539        get the P value corresponding to the CIR, whereas branches on overflow,
2540        carry, etc. subtract two.
2541 
2542     2. If the mode is indirect, this routine handles bounds checks and TOS
2543        register accesses on the initial address.
2544 
2545     3. The System Reference Manual states that byte offsets are interpreted as
2546        negative if the effective address does not lie between DL and Z.
2547        However, the Series II microcode actually uses DL and S for the limits.
2548 
2549     4. This routine calculates the effective address for the memory address
2550        instructions.  These instructions always bounds-check their accesses, and
2551        data and stack accesses are mapped to the TOS registers if the effective
2552        address lies between SM and SM + SR within the stack bank.
2553 */
2554 
cpu_ea(HP_WORD mode_disp,ACCESS_CLASS * classification,HP_WORD * offset,BYTE_SELECTOR * selector)2555 void cpu_ea (HP_WORD mode_disp, ACCESS_CLASS *classification, HP_WORD *offset, BYTE_SELECTOR *selector)
2556 {
2557 HP_WORD      base, displacement;
2558 ACCESS_CLASS class;
2559 
2560 switch ((mode_disp & MODE_MASK) >> MODE_SHIFT) {        /* dispatch on the addressing mode */
2561 
2562     case 000:
2563     case 001:
2564     case 002:
2565     case 003:                                           /* positive P-relative displacement */
2566         base = P - 2 + (mode_disp & DISPL_255_MASK);    /* add the displacement to the base */
2567         class = program_checked;                        /*   and classify as a program reference */
2568         break;
2569 
2570     case 004:
2571     case 005:
2572     case 006:
2573     case 007:                                           /* negative P-relative displacement */
2574         base = P - 2 - (mode_disp & DISPL_255_MASK);    /* subtract the displacement from the base */
2575         class = program_checked;                        /*   and classify as a program reference */
2576         break;
2577 
2578     case 010:
2579     case 011:
2580     case 012:
2581     case 013:                                           /* positive DB-relative displacement */
2582         base = DB + (mode_disp & DISPL_255_MASK);       /* add the displacement to the base */
2583         class = data_mapped_checked;                    /*   and classify as a data reference */
2584         break;
2585 
2586     case 014:
2587     case 015:                                           /* positive Q-relative displacement */
2588         base = Q + (mode_disp & DISPL_127_MASK);        /* add the displacement to the base */
2589         class = stack_checked;                          /*   and classify as a stack reference */
2590         break;
2591 
2592     case 016:                                           /* negative Q-relative displacement */
2593         base = Q - (mode_disp & DISPL_63_MASK);         /* subtract the displacement from the base */
2594         class = stack_checked;                          /*   and classify as a stack reference */
2595         break;
2596 
2597     case 017:                                           /* negative S-relative displacement */
2598         base = SM + SR - (mode_disp & DISPL_63_MASK);   /* subtract the displacement from the base */
2599         class = stack_checked;                          /*   and classify as a stack reference */
2600         break;
2601     }                                                   /* all cases are handled */
2602 
2603 
2604 if (!(mode_disp & I_FLAG_BIT_5))                            /* if the mode is direct */
2605     displacement = 0;                                       /*   then there's no displacement */
2606 
2607 else {                                                      /* otherwise the mode is indirect */
2608     cpu_read_memory (class, base & LA_MASK, &displacement); /*   so get the displacement value */
2609 
2610     if ((CIR & BR_MASK) == BR_DBQS_I) {                     /* if this a DB/Q/S-relative indirect BR instruction */
2611         base = PB;                                          /*   then PB is the base for the displacement */
2612         class = program_checked;                            /* reclassify as a program reference */
2613         }
2614 
2615     else if (class != program_checked) {                    /* otherwise if it is a data or stack reference */
2616         base = DB;                                          /*   then DB is the base for the displacement */
2617         class = data_mapped_checked;                        /* reclassify as a data reference */
2618         }
2619                                                         /* otherwise, this is a program reference */
2620     }                                                   /*   which is self-referential */
2621 
2622 if ((CIR & LSDX_MASK) == LDD_X                          /* if the mode */
2623   || (CIR & LSDX_MASK) == STD_X)                        /*   is double-word indexed */
2624     displacement = displacement + X * 2 & DV_MASK;      /*     then add the doubled index to the displacement */
2625 
2626 else if (mode_disp & X_FLAG)                            /* otherwise if the mode is indexed */
2627     displacement = displacement + X & DV_MASK;          /*   then add the index to the displacement */
2628 
2629 if (selector == NULL)                                   /* if a word address is requested */
2630     base = base + displacement;                         /*   then add in the word displacement */
2631 
2632 else if ((mode_disp & (X_FLAG | I_FLAG_BIT_5)) == 0)    /* otherwise if a direct byte address is requested */
2633     *selector = upper;                                  /*   then it references the upper byte */
2634 
2635 else {                                                  /* otherwise an indexed or indirect byte address is requested */
2636     if (displacement & 1)                               /*   so if the byte displacement is odd */
2637         *selector = lower;                              /*     then the lower byte was requested */
2638     else                                                /*   otherwise it is even */
2639         *selector = upper;                              /*     and the upper byte was requested */
2640 
2641     base = base + (displacement >> 1) & LA_MASK;        /* convert the displacement from byte to word and add */
2642 
2643     if (DBANK == SBANK && DL <= DB && DB <= Z           /* if not in split-stack mode */
2644      && (base < DL || base > SM + SR))                  /*   and the word address is out of range */
2645         base = base ^ D16_SIGN;                         /*     then add 32K to swap the offset polarity */
2646     }
2647 
2648 *offset = base & LA_MASK;                               /* set the */
2649 *classification = class;                                /*   return values */
2650 
2651 return;
2652 }
2653 
2654 
2655 /* Convert a data- or program-relative byte address to a word effective address.
2656 
2657    The supplied byte offset from DB or PB is converted to a memory address,
2658    bounds-checked if requested, and returned.  If the supplied block length is
2659    not zero, the converted address is assumed to be the starting address of a
2660    block, and an ending address, based on the block length, is calculated and
2661    bounds-checked if requested.  If either address lies outside of the segment
2662    associated with the access class, a Bounds Violation trap occurs, unless a
2663    privileged data access is requested.
2664 
2665    The "class" parameter indicates whether the offset is from DB or PB and
2666    must be "data", "data_checked", "program", or "program_checked".  No other
2667    access classes are supported.  In particular, "data_mapped" and
2668    "data_mapped_checked" are not allowed, as callers of this routine never map
2669    accesses to the TOS registers.
2670 
2671    Byte offsets into data segments present problems, in that negative offsets
2672    are permitted (to access the DL-to-DB area), but there are not enough bits to
2673    represent all locations unambiguously in the potential -32K to +32K word
2674    offset range.  Therefore, a byte offset with bit 0 = 1 can represent either a
2675    positive or negative word offset from DB, depending on the interpretation.
2676    The HP 3000 adopts the convention that if the address resulting from a
2677    positive-offset interpretation does not fall within the DL-to-S range, then
2678    32K is added to the address, effectively changing the interpretation from a
2679    positive to a negative offset.  If this new address does not fall within the
2680    DL-to-S range, a Bounds Violation trap occurs if the mode is non-privileged.
2681 
2682    The reinterpretation as a negative offset is performed only if the CPU is not
2683    in split-stack mode (where either DBANK is different from SBANK, or DB does
2684    not lie between DL and Z), as extra data segments do not permit negative-DB
2685    addressing.  Reinterpretation is also not used for code segments, as negative
2686    offsets from PB are not permitted.
2687 
2688 
2689    Implementation notes:
2690 
2691     1. This routine implements the DBBC microcode subroutine.
2692 */
2693 
cpu_byte_ea(ACCESS_CLASS class,uint32 byte_offset,uint32 block_length)2694 uint32 cpu_byte_ea (ACCESS_CLASS class, uint32 byte_offset, uint32 block_length)
2695 {
2696 uint32 starting_word, ending_word, increment;
2697 
2698 if (block_length & D16_SIGN)                            /* if the block length is negative */
2699     increment = 0177777;                                /*   then the memory increment is negative also */
2700 else                                                    /* otherwise */
2701     increment = 1;                                      /*   the increment is positive */
2702 
2703 if (class == program || class == program_checked) {     /* if this is a program access */
2704     starting_word = PB + (byte_offset >> 1) & LA_MASK;  /*   then determine the starting word address */
2705 
2706     if (class == program_checked                        /* if checking is requested */
2707       && starting_word < PB || starting_word > PL)      /*   and the starting address is out of range */
2708         MICRO_ABORT (trap_Bounds_Violation);            /*     then trap for a bounds violation */
2709 
2710     if (block_length != 0) {                            /* if a block length was supplied */
2711         ending_word =                                   /*   then determine the ending address */
2712            starting_word + ((block_length - increment + (byte_offset & 1)) >> 1) & LA_MASK;
2713 
2714         if (class == program_checked                    /* if checking is requested */
2715           && ending_word < PB || ending_word > PL)      /*   and the ending address is out of range */
2716             MICRO_ABORT (trap_Bounds_Violation);        /*     then trap for a bounds violation */
2717         }
2718     }
2719 
2720 else {                                                  /* otherwise this is a data address */
2721     starting_word = DB + (byte_offset >> 1) & LA_MASK;  /*   so determine the starting word address */
2722 
2723     if (DBANK == SBANK && DL <= DB && DB <= Z           /* if not in split-stack mode */
2724       && (starting_word < DL || starting_word > SM)) {  /*   and the word address is out of range */
2725         starting_word = starting_word ^ D16_SIGN;       /*     then add 32K and try again */
2726 
2727         if (class == data_checked && NPRV                   /* if checking is requested and non-privileged */
2728           && (starting_word < DL || starting_word > SM))    /*   and still out of range */
2729             MICRO_ABORT (trap_Bounds_Violation);            /*     then trap for a bounds violation */
2730         }
2731 
2732     if (block_length != 0) {                            /* if a block length was supplied */
2733         ending_word =                                   /*   then determine the ending word address */
2734            starting_word + ((block_length - increment + (byte_offset & 1)) >> 1) & LA_MASK;
2735 
2736         if (class == data_checked && NPRV               /* if checking is requested and non-privileged */
2737           && (ending_word < DL || ending_word > SM))    /*   and the address is out of range */
2738             MICRO_ABORT (trap_Bounds_Violation);        /*     then trap for a bounds violation */
2739         }
2740     }
2741 
2742 
2743 return starting_word;                                   /* return the starting word address */
2744 }
2745 
2746 
2747 /* Set up the entry into an interrupt handler.
2748 
2749    This routine prepares the CPU state to execute an interrupt handling
2750    procedure.  On entry, "class" is the classification of the current interrupt,
2751    and "parameter" is the parameter associated with the interrupt.  On exit, the
2752    stack has been set up correctly, and the PB, P, PL, and status registers have
2753    been set up for entry into the interrupt procedure.
2754 
2755    Run-mode interrupts are classified as external or internal and ICS or
2756    non-ICS.  External interrupts are those originating with the device
2757    controllers, and internal interrupts are conditions detected by the microcode
2758    (e.g., a bounds violation or arithmetic overflow).  ICS interrupts execute
2759    their handlers on the system's Interrupt Control Stack.  Non-ICS interrupts
2760    execute on the user's stack.
2761 
2762    Of the run-mode interrupts, the External, System Parity Error, Address
2763    Parity Error, Data Parity Error, and Module interrupts execute on the ICS.
2764    All other interrupts execute on the user's stack.  The routine begins by
2765    determining whether an ICS or non-ICS interrupt is indicated.  The
2766    appropriate stack is established, and the stack marker is written to preserve
2767    the state of the interrupted routine.  The label of the handler procedure is
2768    obtained, and then the procedure designated by the label is set up.  On
2769    return, the first instruction of the handler is ready to execute.
2770 
2771 
2772    Implementation notes:
2773 
2774     1. This routine implements various execution paths through the microcode
2775        labeled as INT0 through INT7.
2776 
2777     2. This routine is also called directly by the IXIT instruction executor if
2778        an external interrupt is pending.  This is handled as an external
2779        interrupt but is classified differently so that the teardown and rebuild
2780        of the stack may be avoided to improve performance.
2781 */
2782 
cpu_setup_irq_handler(IRQ_CLASS class,HP_WORD parameter)2783 void cpu_setup_irq_handler (IRQ_CLASS class, HP_WORD parameter)
2784 {
2785 HP_WORD label;
2786 
2787 if (class == irq_External || class == irq_IXIT) {       /* if entry is for an external interrupt */
2788     if (class == irq_External)                          /*   then if it was detected during normal execution */
2789         cpu_setup_ics_irq (class, 0);                   /*     then set it up on the ICS */
2790     else                                                /*   otherwise it was detected during IXIT */
2791         SM = Q + 2 & R_MASK;                            /*     so the ICS is already set up */
2792 
2793     DBANK = 0;                                          /* all handlers are in bank 0 */
2794     STA = STATUS_M | STATUS_I;                          /* enter privileged mode with interrupts enabled */
2795 
2796     cpu_read_memory (stack, parameter * 4 + 2, &DB);    /* read the DB value */
2797     cpu_read_memory (stack, parameter * 4 + 1, &label); /*   and the procedure label from the DRT */
2798     }
2799 
2800 else if (class >= irq_System_Parity                     /* otherwise if entry is for */
2801   && class <= irq_Power_Fail) {                         /*   another ICS interrupt */
2802     cpu_setup_ics_irq (class, 0);                       /*     then set it up on the ICS */
2803 
2804     label = TO_LABEL (LABEL_IRQ, class);                /* form the label for the specified classification */
2805 
2806     STA = STATUS_M;                                     /* clear status and enter privileged mode */
2807     }
2808 
2809 else {                                                  /* otherwise entry is for a non-ICS interrupt */
2810     if (class == irq_Integer_Overflow)                  /* if this is an integer overflow interrupt */
2811         label = TO_LABEL (LABEL_IRQ, trap_User);        /*   then form the label for a user trap */
2812     else                                                /* otherwise form the label */
2813         label = TO_LABEL (LABEL_IRQ, class);            /*   for the specified classification */
2814 
2815     cpu_flush ();                                       /* flush the TOS registers to memory */
2816     cpu_mark_stack ();                                  /*   and write a stack marker */
2817 
2818     STA = STATUS_M;                                     /* clear status and enter privileged mode */
2819     }
2820 
2821 SM = SM + 1 & R_MASK;                                   /* increment the stack pointer */
2822 cpu_write_memory (stack, SM, parameter);                /*   and push the parameter on the stack */
2823 
2824 X = CIR;                                                /* save the CIR in the index register */
2825 
2826 cpu_call_procedure (label, 0);                          /* set up to call the interrupt handling procedure */
2827 
2828 return;
2829 }
2830 
2831 
2832 /* Set up an interrupt on the Interrupt Control Stack.
2833 
2834    This routine prepares the Interrupt Control Stack (ICS) to support interrupt
2835    processing.  It is called from the run-time interrupt routine for ICS
2836    interrupts, the microcode abort routine for ICS traps, and from the DISP and
2837    PSEB instruction executors before entering the dispatcher.  On entry, "class"
2838    is the interrupt classification, and, if the class is "irq_Trap", then "trap"
2839    is the trap classification.  The trap classification is ignored for
2840    interrupts, including the dispatcher start interrupt.
2841 
2842    Unless entry is for a Cold Load trap, the routine begins by writing a
2843    six-word stack marker.  This special ICS marker extends the standard marker
2844    by adding the DBANK and DB values as follows:
2845 
2846        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
2847      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2848      |                       X register value                        |  [Q - 3]  X
2849      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2850      |                  PB-relative return address                   |  [Q - 2]  P + 1 - PB
2851      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2852      |                     Status register value                     |  [Q - 1]  STA
2853      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2854      | D |                     Delta Q value                         |  [Q - 0]  S - Q
2855      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2856      |                         DB-Bank value                         |  [Q + 1]  DBANK
2857      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2858      |                           DB value                            |  [Q + 2]  DB
2859      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2860 
2861    Where:
2862 
2863      D = the dispatcher was interrupted
2864 
2865    After the values are written, the Q register is set to point to the marker.
2866    The stack bank register is then cleared, as the ICS is always located in
2867    memory bank 0.
2868 
2869    If the interrupt or trap occurred while executing on the ICS, and the
2870    dispatcher was running at the time, the "dispatcher running" bit in the CPX1
2871    register is cleared, and the D-bit is set in the delta-Q value word of the
2872    stack marker.  This bit will be used during interrupt exit to decide whether
2873    to restart the dispatcher.
2874 
2875    If the CPU was executing on the user's stack, the "ICS flag" bit in CPX1 is
2876    set, the Q register is reset to point at the permanent dispatcher stack
2877    marker established by the operating system, and the Z register is reset to
2878    the stack limit established by the OS for the ICS; the values are obtained
2879    from reserved memory locations 5 and 6, respectively.  The ICS DB value is
2880    read from the ICS global area that precedes the dispatcher stack marker and
2881    is used to write the stack-DB-relative S value back to the global area.
2882 
2883    Finally, the stack pointer is set to point just above the stack marker.
2884 
2885 
2886    Implementation notes:
2887 
2888     1. This routine implements various execution paths through the microcode
2889        labeled as INT1 through INT5.
2890 */
2891 
cpu_setup_ics_irq(IRQ_CLASS class,TRAP_CLASS trap)2892 void cpu_setup_ics_irq (IRQ_CLASS class, TRAP_CLASS trap)
2893 {
2894 HP_WORD delta_q, stack_db;
2895 
2896 if (class != irq_Trap                                   /* if this is not */
2897   || trap != trap_Cold_Load && trap != trap_Power_On) { /*   a cold load or power on trap entry */
2898     cpu_flush ();                                       /*     then flush the TOS registers to memory */
2899     cpu_mark_stack ();                                  /*       and write a four-word stack marker */
2900 
2901     cpu_write_memory (stack, SM + 1 & LA_MASK, DBANK);  /* add DBANK and DB to the stack */
2902     cpu_write_memory (stack, SM + 2 & LA_MASK, DB);     /*   to form a six-word ICS marker */
2903     }
2904 
2905 SBANK = 0;                                              /* the ICS is always located in bank 0 */
2906 
2907 if (CPX1 & cpx1_ICSFLAG) {                              /* if execution is currently on the ICS */
2908     if (CPX1 & cpx1_DISPFLAG) {                         /*   then if the dispatcher was interrupted */
2909         CPX1 &= ~cpx1_DISPFLAG;                         /*     then clear the dispatcher flag */
2910 
2911         cpu_read_memory (stack, Q, &delta_q);           /* get the delta Q value from the stack marker */
2912         cpu_write_memory (stack, Q, delta_q | STMK_D);  /*   and set the dispatcher-interrupted flag */
2913         }
2914     }
2915 
2916 else {                                                  /* otherwise execution is on the user's stack */
2917     CPX1 |= cpx1_ICSFLAG;                               /*   so set the ICS flag */
2918 
2919     cpu_read_memory (stack, ICS_Q, &Q);                 /* set Q = QI */
2920     cpu_read_memory (stack, ICS_Z, &Z);                 /* set Z = ZI */
2921 
2922     cpu_read_memory (stack, Q - 4 & LA_MASK,            /* read the stack DB value */
2923                      &stack_db);
2924 
2925     cpu_write_memory (stack, Q - 6 & LA_MASK,           /* write the stack-DB-relative S value */
2926                       SM + 2 - stack_db & DV_MASK);     /*   which is meaningless for a cold load or power on */
2927 
2928     SR = 0;                                             /* invalidate the stack registers for a cold load */
2929     DL = D16_UMAX;                                      /*   and set the data limit */
2930     }
2931 
2932 SM = Q + 2 & R_MASK;                                    /* set S above the stack marker */
2933 
2934 return;
2935 }
2936 
2937 
2938 /* Set up a code segment.
2939 
2940    This routine is called to set up a code segment in preparation for calling or
2941    exiting a procedure located in a segment different from the currently
2942    executing segment.  On entry, "label" indicates the segment number containing
2943    the procedure.  On exit, the new status register value and the first word of
2944    the Code Segment Table entry are returned to the variables pointed to by
2945    "status" and "entry_0", respectively.
2946 
2947    The routine begins by reading the CST pointer.  The CST is split into two
2948    parts: a base table, and an extension table.  The table to use is determined
2949    by the requested segment number.  Segment numbers 0 and 192, corresponding to
2950    the first entries of the two tables, are reserved and cause a CST Violation
2951    trap if specified.
2952 
2953    The CST entry corresponding to the segment number is examined to set the
2954    program bank, base, and limit registers (the segment length stored in the
2955    table is number of quad-words, which must be multiplied by four to get the
2956    size in words).  The new status register value is set up and returned, along
2957    with the first word of the CST entry.
2958 
2959 
2960    Implementation notes:
2961 
2962     1. This routine implements the microcode SSEG subroutine.
2963 
2964     2. Passing -1 as a parameter to trap_CST_Violation ensures that the segment
2965        number >= 2 check will pass and the trap handler will be invoked.
2966 
2967     3. The Series II microcode sets PBANK and PB unilaterally but sets PL only
2968        if the code segment is not absent.  An absent segment entry contains the
2969        disc address in words 3 and 4 instead of the bank address and base
2970        address, so PBANK and PB will contain invalid values in this case.  It is
2971        not clear why the microcode avoids setting PL; the microinstruction in
2972        question also sets Flag 2, so conditioning PL may be just a side effect.
2973        In any case, we duplicate the firmware behavior here.
2974 
2975     4. This routine is only used locally, but we leave it as a global entry to
2976        support future firmware extensions that may need to call it.
2977 */
2978 
cpu_setup_code_segment(HP_WORD label,HP_WORD * status,HP_WORD * entry_0)2979 void cpu_setup_code_segment (HP_WORD label, HP_WORD *status, HP_WORD *entry_0)
2980 {
2981 HP_WORD cst_pointer, cst_size, cst_entry, cst_bank, segment_number, entry_number;
2982 
2983 segment_number = STT_SEGMENT (label);                       /* isolate the segment number from the label */
2984 
2985 if (segment_number < CST_RESERVED) {                        /* if the target segment is in the base table */
2986     cpu_read_memory (absolute, CSTB_POINTER, &cst_pointer); /*   then read the CST base pointer */
2987     entry_number = segment_number;                          /*     and set the entry number */
2988     }
2989 
2990 else {                                                      /* otherwise it is in the extension table */
2991     cpu_read_memory (absolute, CSTX_POINTER, &cst_pointer); /*   so read the CST extension pointer */
2992     entry_number = segment_number - CST_RESERVED;           /*     and set the entry number */
2993     }
2994 
2995 if (entry_number == 0)                                  /* segment numbers 0 and 192 do not exist */
2996     MICRO_ABORTP (trap_CST_Violation, -1);              /*   so trap for a violation if either is specified */
2997 
2998 cpu_read_memory (absolute, cst_pointer, &cst_size);     /* read the table size */
2999 
3000 if (entry_number > cst_size)                            /* if the entry is outside of the table */
3001     MICRO_ABORTP (trap_CST_Violation, entry_number);    /*   then trap for a violation */
3002 
3003 cst_entry = cst_pointer + entry_number * 4;             /* get the address of the target CST entry */
3004 
3005 cpu_read_memory  (absolute, cst_entry, entry_0);                /* get the first word of the entry */
3006 cpu_write_memory (absolute, cst_entry, *entry_0 | CST_R_BIT);   /*   and set the segment reference bit */
3007 
3008 cpu_read_memory (absolute, cst_entry + 2, &cst_bank);   /* read the bank address word */
3009 PBANK = cst_bank & CST_BANK_MASK;                       /*   and mask to just the bank number */
3010 
3011 cpu_read_memory (absolute, cst_entry + 3, &PB);         /* read the segment's base address */
3012 
3013 PL = (*entry_0 & CST_SEGLEN_MASK) * 4 - 1;              /* set PL to the segment length - 1 */
3014 
3015 *status = STA & ~LABEL_SEGMENT_MASK | segment_number;   /* set the segment number in the new status word */
3016 
3017 if (*entry_0 & CST_M_BIT)                               /* if the segment executes in privileged mode */
3018     *status |= STATUS_M;                                /*   then set up to enter privileged mode */
3019 
3020 if (! (*entry_0 & CST_A_BIT))                           /* if the segment is not absent */
3021     PL = PL + PB;                                       /*   then set the segment limit */
3022 
3023 return;
3024 }
3025 
3026 
3027 /* Set up a data segment.
3028 
3029    This routine is called to set up a data segment for access.  It is called by
3030    the MDS, MFDS, and MTDS instruction executors to obtain the bank and offset
3031    of specified segments from the Data Segment Table.  On entry,
3032    "segment_number" indicates the number of the desired data segment.  On exit,
3033    the memory bank number and offset of the data segment base are returned to
3034    the variables pointed to by "bank" and "address", respectively.
3035 
3036    The routine begins by reading the DST pointer.  Segment number 0,
3037    corresponding to the first entry of the table, is reserved and causes a DST
3038    Violation trap if specified.
3039 
3040    The DST entry corresponding to the segment number is examined to obtain the
3041    bank and base address.  If the segment is absent, a Data Segment Absent trap
3042    is taken.  Otherwise, the bank and address values are returned.
3043 
3044 
3045    Implementation notes:
3046 
3047     1. This routine implements the microcode DSEG subroutine.
3048 */
3049 
cpu_setup_data_segment(HP_WORD segment_number,HP_WORD * bank,HP_WORD * address)3050 void cpu_setup_data_segment (HP_WORD segment_number, HP_WORD *bank, HP_WORD *address)
3051 {
3052 HP_WORD dst_pointer, dst_size, dst_entry, entry_0;
3053 
3054 cpu_read_memory (absolute, DST_POINTER, &dst_pointer);  /* read the DST base pointer */
3055 
3056 if (segment_number == 0)                                /* segment number 0 does not exist */
3057     MICRO_ABORT (trap_DST_Violation);                   /*   so trap for a violation if it is specified */
3058 
3059 cpu_read_memory (absolute, dst_pointer, &dst_size);     /* read the table size */
3060 
3061 if (segment_number > dst_size)                          /* if the entry is outside of the table */
3062     MICRO_ABORT (trap_DST_Violation);                   /*   then trap for a violation */
3063 
3064 dst_entry = dst_pointer + segment_number * 4;           /* get the address of the target DST entry */
3065 
3066 cpu_read_memory (absolute, dst_entry, &entry_0);                /* get the first word of the entry */
3067 cpu_write_memory (absolute, dst_entry, entry_0 | DST_R_BIT);    /*   and set the segment reference bit */
3068 
3069 if (entry_0 & DST_A_BIT)                                /* if the segment is absent */
3070     MICRO_ABORTP (trap_DS_Absent, segment_number);      /*   then trap for an absentee violation */
3071 
3072 cpu_read_memory (absolute, dst_entry + 2, bank);        /* read the segment bank number */
3073 cpu_read_memory (absolute, dst_entry + 3, address);     /*   and base address */
3074 
3075 *bank = *bank & DST_BANK_MASK;                          /* mask off the reserved bits */
3076 
3077 return;                                                 /*   before returning to the caller */
3078 }
3079 
3080 
3081 /* Call a procedure.
3082 
3083    This routine sets up the PB, P, PL, and status registers to enter a
3084    procedure.  It is called by the PCAL instruction executor and by the
3085    interrupt and trap routines to set up the handler procedures.  On entry,
3086    "label" contains an external program label indicating the segment number and
3087    Segment Transfer Table entry number describing the procedure, or a local
3088    program label indicating the starting address of the procedure, and "offset"
3089    contains an offset to be added to the starting address.  On exit, the
3090    registers are set up for execution to resume with the first instruction of
3091    the procedure.
3092 
3093    If the label is a local label, the PB-relative address is obtained from the
3094    label and stored in the P register, and the Next Instruction Register is
3095    loaded with the first instruction of the procedure.
3096 
3097    If the label is external, the code segment referenced by the label is set up.
3098    If the "trace" or "absent" bits are set, the corresponding trap is taken.
3099    Otherwise, the Segment Transfer Table length is read, and the STT entry
3100    number is validated; if it references a location outside of the table, a STT
3101    violation trap is taken.
3102 
3103    Otherwise, the valid STT entry is examined.  If the target procedure is not
3104    in the designated code segment or is uncallable if not in privileged mode,
3105    the appropriate traps are taken.  If the STT entry contains a local label, it
3106    is used to set up the P register and NIR as above.
3107 
3108    The "offset" parameter is used only by the XBR instruction executor.  The
3109    PCAL executor and the interrupt handlers pass an offset of zero to begin
3110    execution at the first instruction of the designated procedure.
3111 
3112 
3113    Implementation notes:
3114 
3115     1. This routine implements the microcode PCL3 and PCL5 subroutines.
3116 */
3117 
cpu_call_procedure(HP_WORD label,HP_WORD offset)3118 void cpu_call_procedure (HP_WORD label, HP_WORD offset)
3119 {
3120 HP_WORD new_status, new_label, new_p, cst_entry, stt_size, stt_entry;
3121 
3122 new_status = STA;                                       /* save the status for a local label */
3123 
3124 if (label & LABEL_EXTERNAL) {                                   /* if the label is non-local */
3125     cpu_setup_code_segment (label, &new_status, &cst_entry);    /*   then set up the corresponding code segment */
3126 
3127     stt_entry = STT_NUMBER (label);                     /* get the STT entry number from the label */
3128 
3129     if (cst_entry & (CST_A_BIT | CST_T_BIT)) {          /* if the code segment is absent or being traced */
3130         STA = new_status;                               /*   then set the new status before trapping */
3131         cpu_mark_stack ();                              /*     and write a stack marker to memory */
3132 
3133         if (cst_entry & CST_A_BIT)                      /* if the code segment is absent */
3134             MICRO_ABORTP (trap_CS_Absent, label);       /*   then trap to load it */
3135         else                                            /* otherwise */
3136             MICRO_ABORTP (trap_Trace, label);           /*   trap to trace it */
3137         }
3138 
3139     cpu_read_memory (program_checked, PL, &stt_size);   /* read the table size */
3140 
3141     if (stt_entry > STT_LENGTH (stt_size))              /* if the entry is outside of the table */
3142         MICRO_ABORTP (trap_STT_Violation, new_status);  /*   then trap for a violation */
3143 
3144     cpu_read_memory (program_checked, PL - stt_entry, &new_label);  /* read the label from the STT */
3145 
3146     if (new_label & LABEL_EXTERNAL)                     /* if the procedure is not in the target segment */
3147         MICRO_ABORTP (trap_STT_Violation, new_status);  /*   then trap for a violation */
3148 
3149     if ((new_label & LABEL_UNCALLABLE) && NPRV)         /* if the procedure is uncallable in the current mode */
3150         MICRO_ABORTP (trap_Uncallable, label);          /*   then trap for a violation */
3151 
3152     if (stt_entry == 0)                                 /* if the STT number is zero in an external label */
3153         label = 0;                                      /*   then the starting address is PB */
3154     else                                                /* otherwise */
3155         label = new_label;                              /*   the PB offset is contained in the new label */
3156 
3157     cpu_base_changed = TRUE;                            /* the program base registers have changed for tracing */
3158     }
3159 
3160 new_p = PB + (label + offset & LABEL_ADDRESS_MASK);     /* get the procedure starting address */
3161 
3162 cpu_read_memory (fetch_checked, new_p, &NIR);           /* check the bounds and get the next instruction */
3163 P = new_p + 1 & R_MASK;                                 /* the bounds are valid, so set the new P value */
3164 
3165 STA = new_status;                                       /* set the new status value */
3166 
3167 return;
3168 }
3169 
3170 
3171 /* Return from a procedure.
3172 
3173    This routine sets up the P, Q, SM, and status registers to return from a
3174    procedure.  It is called by the EXIT and IXIT instruction executors and by
3175    the cpu_start_dispatcher routine to enter the dispatcher.  On entry, "new_q"
3176    and "new_sm" contain the new values for the Q and SM registers that unwind
3177    the stack.  The "parameter" value is used only if a Trace or Code Segment
3178    Absent trap is taken.  For EXIT, the parameter is the stack adjustment value
3179    (the N field).  For IXIT, the parameter is zero.  On exit, the registers are
3180    set up for execution to resume with the first instruction after the procedure
3181    call or interrupt.
3182 
3183    The routine begins by reloading register values from the stack marker.  The
3184    stack marker format is:
3185 
3186        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
3187      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
3188      |                       X register value                        |  [Q - 3]  X
3189      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
3190      | T | M |          PB-relative return address                   |  [Q - 2]  P + 1 - PB
3191      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
3192      |                     Status register value                     |  [Q - 1]  STA
3193      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
3194      |                         Delta Q value                         |  [Q - 0]  S - Q
3195      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
3196 
3197    Where:
3198 
3199      T = a trace or control-Y interrupt is pending
3200      M = the code segment is physically mapped
3201 
3202    The T and M bits are set by the operating system, if applicable, after the
3203    stack marker was originally written.
3204 
3205    Stack underflow and overflow are checked, and privilege changes are
3206    validated.  If the return will be to a different code segment, it is set up.
3207    Finally, the new P, Q, SM, and status register values are loaded, and NIR is
3208    loaded with the first instruction after the return.
3209 
3210 
3211    Implementation notes:
3212 
3213     1. This routine implements the microcode EXI1 subroutine.
3214 
3215     2. We pass a temporary status to cpu_setup_code_segment because it forms the
3216        returned new status from the current STA register value.  But for EXIT
3217        and IXIT, the new status comes from the stack marker, which already has
3218        the segment number to which we're returning, and which must not be
3219        altered.
3220 
3221     3. The NEXT action is modified when the R-bit is set in the status word
3222        being restored.  This occurs when an interrupt occurred between the two
3223        stackops of a stack instruction.  The main instruction loop does not
3224        alter CIR in this case, so we must set it up here.
3225 */
3226 
cpu_exit_procedure(HP_WORD new_q,HP_WORD new_sm,HP_WORD parameter)3227 void cpu_exit_procedure (HP_WORD new_q, HP_WORD new_sm, HP_WORD parameter)
3228 {
3229 HP_WORD temp_status, new_status, new_p, cst_entry;
3230 
3231 SM = Q;                                                 /* delete any local values from the stack */
3232 
3233 if (new_q > Z || new_sm > Z)                            /* if either the new Q or SM exceed the stack limit */
3234     MICRO_ABORT (trap_Stack_Overflow);                  /*   then trap with a stack overflow */
3235 
3236 cpu_read_memory (stack, Q - 1, &new_status);            /* read the new status value from the stack marker */
3237 
3238 if ((CIR & EXIT_MASK) == EXIT                           /* if an EXIT instruction is executing */
3239   && (new_q < DB || new_sm < DB)                        /*   and either new Q or new S are below the data base */
3240   && (new_status & STATUS_M) == 0)                      /*     and the new mode is non-privileged */
3241     MICRO_ABORT (trap_Stack_Underflow);                 /*       then trap with a stack underflow */
3242 
3243 cpu_read_memory (stack, Q - 2, &new_p);                 /* read the PB-relative return value from the stack marker */
3244 
3245 if (NPRV                                                /* if currently in user mode */
3246   && ((new_status & STATUS_M)                           /*   and returning to privileged mode */
3247   || (new_status & STATUS_I) != (STA & STATUS_I)))      /*   or attempting to change interrupt state */
3248     MICRO_ABORT (trap_Privilege_Violation);             /*     then trap with a privilege violation */
3249 
3250 STA &= ~STATUS_I;                                       /* turn off external interrupts */
3251 
3252 cpu_read_memory (stack, Q - 3, &X);                     /* read the new X value from the stack marker */
3253 
3254 if (STATUS_CS (new_status) != STATUS_CS (STA)) {                    /* if returning to a different segment */
3255     cpu_setup_code_segment (new_status, &temp_status, &cst_entry);  /*   then set up the new segment */
3256 
3257     if (NPRV && (temp_status & STATUS_M))               /* if in user mode now and returning to a privileged segment */
3258         MICRO_ABORT (trap_Privilege_Violation);         /*   then trap with a privilege violation */
3259 
3260     if (new_p & STMK_T)                                 /* if the new code segment is being traced */
3261         MICRO_ABORTP (trap_Trace, parameter);           /*   then trap to trace it */
3262 
3263     if (cst_entry & CST_A_BIT)                          /* if the code segment is absent */
3264         MICRO_ABORTP (trap_CS_Absent, parameter);       /*   then trap to load it */
3265     }
3266 
3267 new_p = PB + (new_p & STMK_RTN_ADDR);                   /* convert the relative address to absolute */
3268 
3269 cpu_read_memory (fetch_checked, new_p, &NIR);           /* check the bounds and get the next instruction */
3270 P = new_p + 1 & R_MASK;                                 /* the bounds are valid, so set the new P value */
3271 
3272 STA = new_status;                                       /* set the new status value */
3273 Q   = new_q;                                            /*   and the stack marker */
3274 SM  = new_sm;                                           /*     and the stack pointer */
3275 
3276 if (STA & STATUS_R) {                                   /* if a right-hand stack op is pending */
3277     CIR = NIR;                                          /*   then set the current instruction */
3278     cpu_read_memory (fetch, P, &NIR);                   /*     and load the next instruction */
3279     }
3280 
3281 cpu_base_changed = TRUE;                                /* one or more base registers have changed for tracing */
3282 
3283 return;
3284 }
3285 
3286 
3287 /* Start the dispatcher.
3288 
3289    This routine is called by the DISP and PSEB instruction executors to start
3290    the dispatcher and by the IXIT executor to restart the dispatcher if it was
3291    interrupted.
3292 
3293    On entry, the ICS has been set up.  The "dispatcher running" bit in the CPX1
3294    register is set, Q is set to point at the permanent dispatcher stack marker
3295    on the ICS, the dispatcher's DBANK and DB registers are loaded, and an "exit
3296    procedure" is performed to return to the dispatcher.
3297 */
3298 
cpu_start_dispatcher(void)3299 void cpu_start_dispatcher (void)
3300 {
3301 tprintf (cpu_dev, DEB_INSTR, BOV_FORMAT "%s interrupt\n",
3302          PBANK, P - 1 & R_MASK, 0, interrupt_name [irq_Dispatch]);
3303 
3304 CPX1 |= cpx1_DISPFLAG;                                  /* set the "dispatcher is running" flag */
3305 
3306 cpu_read_memory (absolute, ICS_Q, &Q);                  /* set Q to point to the dispatcher's stack marker */
3307 cpu_write_memory (absolute, Q, 0);                      /*   and clear the stack marker delta Q value */
3308 
3309 cpu_read_memory (stack, Q + 1 & LA_MASK, &DBANK);       /* load the dispatcher's data bank */
3310 cpu_read_memory (stack, Q + 2 & LA_MASK, &DB);          /*   and data base registers */
3311 
3312 cpu_exit_procedure (Q, Q + 2, 0);                       /* return to the dispatcher */
3313 
3314 return;
3315 }
3316 
3317 
3318 
3319 /* CPU local SCP support routines */
3320 
3321 
3322 /* Service the CPU process clock.
3323 
3324    The process clock is used by the operating system to time per-process CPU
3325    usage.  It is always enabled and running, although the PCLK register only
3326    increments if the CPU is not executing on the ICS.
3327 
3328    The process clock may be calibrated to wall-clock time or set to real time.
3329    In hardware, the process clock has a one-millisecond period.  Setting the
3330    mode to real time schedules clock events based on the number of event ticks
3331    equivalent to one millisecond.  Because the simulator is an order of
3332    magnitude faster than the hardware, this short period precludes idling.
3333 
3334    In the calibrated mode, the short period would still preclude idling.
3335    Therefore, in this mode, the clock is scheduled with a ten-millisecond
3336    service time, and the PCLK register is incremented by ten for each event
3337    service.  To present the correct value when PCLK is read, the
3338    "cpu_update_pclk" routine is called by the RCLK instruction executor to
3339    increment the count by an amount proportional to the fraction of the service
3340    interval that has elapsed.  In addition, that routine is called by the CPU
3341    instruction postlude, so that PCLK will have the correct value if it is
3342    examined from the SCP command prompt.
3343 
3344    The simulation console is normally hosted by, and therefore polled by, the
3345    ATC on channel 0.  If the console is not hosted by the ATC, due to a SET ATC
3346    DISABLED command, the process clock assumes polling control over the console.
3347 
3348 
3349    Implementation notes:
3350 
3351     1. If the process clock is calibrated, the system clock and ATC poll
3352        services are synchronized with the process clock service to improve
3353        idling.
3354 
3355     2. The current CPU speed, expressed as a multiple of the hardware speed, is
3356        calculated for each service entry.  It may be displayed at the SCP prompt
3357        with the SHOW CPU SPEED command.  The speed is only representative when
3358        the process clock is calibrated, and the CPU is not executing a PAUS
3359        instruction (which suspends the normal fetch/execute instruction cycle).
3360 */
3361 
cpu_service(UNIT * uptr)3362 static t_stat cpu_service (UNIT *uptr)
3363 {
3364 const t_bool ics_exec = (CPX1 & cpx1_ICSFLAG) != 0;     /* TRUE if the CPU is executing on the ICS */
3365 static uint32 last_cpu_speed = 0;                       /* last CPU execution rate multiple */
3366 t_stat status;
3367 
3368 tprintf (cpu_dev, DEB_PSERV, "Process clock delay %d service entered on the %s\n",
3369          uptr->wait, (ics_exec ? "ICS" : "user stack"));
3370 
3371 if (!ics_exec)                                          /* if the CPU is not executing on the ICS */
3372     PCLK = PCLK + pclk_increment & R_MASK;              /*   then increment the process clock */
3373 
3374 cpu_is_calibrated = (uptr->flags & UNIT_CALTIME) != 0;  /* TRUE if the process clock is calibrated */
3375 
3376 if (cpu_is_calibrated) {                                /* if the process clock is tracking wall-clock time */
3377     uptr->wait = sim_rtcn_calb (PCLK_RATE, TMR_PCLK);   /*   then calibrate it */
3378     pclk_increment = PCLK_MULTIPLIER;                   /*     and set the increment to the multiplier */
3379     }
3380 
3381 else {                                                  /* otherwise */
3382     uptr->wait = PCLK_PERIOD;                           /*   set the delay as an event tick count */
3383     pclk_increment = 1;                                 /*     and set the increment without multiplying */
3384     }
3385 
3386 sim_activate (uptr, uptr->wait);                        /* reschedule the timer */
3387 
3388 cpu_speed = uptr->wait / (PCLK_PERIOD * pclk_increment);    /* calculate the current CPU speed multiplier */
3389 
3390 if (TRACING (cpu_dev, DEB_PSERV))
3391     if (last_cpu_speed != cpu_speed) {
3392         hp_trace (&cpu_dev, DEB_PSERV, "Simulation rate %ux\n", cpu_speed);
3393         last_cpu_speed = cpu_speed;
3394         }
3395 
3396 if (atc_is_polling == FALSE) {                          /* if the ATC is not polling for the simulation console */
3397     status = sim_poll_kbd ();                           /*   then we must poll for a console interrupt */
3398 
3399     if (status < SCPE_KFLAG)                            /* if the result is not a character */
3400         return status;                                  /*   then return the resulting status */
3401     }
3402 
3403 return SCPE_OK;                                         /* return the success of the service */
3404 }
3405 
3406 
3407 /* Reset the CPU.
3408 
3409    This routine is called for a RESET, RESET CPU, or BOOT CPU command.  It is the
3410    simulation equivalent of the CPURESET signal, which is asserted by the front
3411    panel LOAD switch.  In hardware, this causes a microcode restart in addition
3412    to clearing certain registers.
3413 
3414    If this is the first call after simulator startup, the initial memory array
3415    is allocated, the default CPU and memory size configuration is set, and the
3416    SCP-required program counter pointer is set to point to the REG array element
3417    corresponding to the P register.
3418 
3419    If this is a power-on reset ("RESET -P"), the process clock calibrated timer
3420    is initialized, and any LOAD or DUMP request in progress is cleared.
3421 
3422    The micromachine is halted, the process clock is scheduled, and several
3423    registers are cleared.
3424 
3425 
3426    Implementation notes:
3427 
3428     1. Setting the sim_PC value at run time accommodates changes in the register
3429        order automatically.  A fixed setting runs the risk of it not being
3430        updated if a change in the register order is made.
3431 */
3432 
cpu_reset(DEVICE * dptr)3433 static t_stat cpu_reset (DEVICE *dptr)
3434 {
3435 if (sim_PC == NULL) {                                   /* if this is the first call after simulator start */
3436     if (mem_initialize (PA_MAX)) {
3437         set_model (&cpu_unit [0], UNIT_SERIES_III,      /*   so establish the initial CPU model */
3438                    NULL, NULL);
3439 
3440         for (sim_PC = dptr->registers;                      /* find the P register entry */
3441              sim_PC->loc != &P && sim_PC->loc != NULL;      /*   in the register array */
3442              sim_PC++);                                     /*     for the SCP interface */
3443 
3444         if (sim_PC == NULL)                                 /* if the P register entry is not present */
3445             return SCPE_NXREG;                              /*   then there is a serious problem! */
3446         }
3447 
3448     else                                                /* otherwise memory initialization failed */
3449         return SCPE_MEM;                                /*   so report the error and abort the simulation */
3450     }
3451 
3452 if (sim_switches & SWMASK ('P')) {                      /* if this is a power-on reset */
3453     sim_rtcn_init (cpu_unit [0].wait, TMR_PCLK);        /*   then initialize the process clock timer */
3454     CPX2 &= ~(cpx2_LOADSWCH | cpx2_DUMPSWCH);           /*     and clear any cold load or dump request */
3455     }
3456 
3457 cpu_micro_state = halted;                               /* halt the micromachine */
3458 sim_activate_abs (&cpu_unit [0], cpu_unit [0].wait);    /*   and schedule the process clock */
3459 
3460 PCLK = 0;                                               /* clear the process clock counter */
3461 CPX1 = 0;                                               /*   and all run-mode signals */
3462 CPX2 &= ~(cpx2_RUN | cpx2_SYSHALT);                     /*     and the run and system halt flip-flops */
3463 
3464 if (cpu_unit [0].flags & UNIT_PFARS)                    /* if the PF/ARS switch position is ENBL */
3465     CPX2 &= ~cpx2_INHPFARS;                             /*   then clear the auto-restart inhibit flag */
3466 else                                                    /* otherwise the position is DSBL */
3467     CPX2 |= cpx2_INHPFARS;                              /*   so set the auto-restart inhibit flag */
3468 
3469 CNTR = SR;                                              /* copy the stack register to the counter */
3470 cpu_flush ();                                           /*   and flush the TOS registers to memory */
3471 
3472 return SCPE_OK;                                         /* indicate that the reset succeeded */
3473 }
3474 
3475 
3476 /* Set the CPU simulation stop conditions.
3477 
3478    This validation routine is called to configure the set of CPU stop
3479    conditions.  The "option" parameter is 0 to clear the stops and 1 to set
3480    them, and "cptr" points to the first character of the name of the stop to be
3481    cleared or set.  The unit and description pointers are not used.
3482 
3483    The routine processes commands of the form:
3484 
3485      SET CPU STOP
3486      SET CPU STOP=<stopname>[;<stopname>...]
3487      SET CPU NOSTOP
3488      SET CPU NOSTOP=<stopname>[;<stopname>...]
3489 
3490    The valid <stopname>s are contained in the debug table "cpu_stop".  If names
3491    are not specified, all stop conditions are enabled or disabled.
3492 
3493 
3494    Implementation notes:
3495 
3496     1. The CPU simulator maintains a private and a public set of simulator
3497        stops.  This routine sets the private set.  The private set is copied to
3498        the public set as part of the instruction execution prelude, unless the
3499        "-B" ("bypass") command-line switch is used with the run command.  This
3500        allows the stops to be bypassed conveniently for the first instruction
3501        execution only.
3502 */
3503 
set_stops(UNIT * uptr,int32 option,char * cptr,void * desc)3504 static t_stat set_stops (UNIT *uptr, int32 option, char *cptr, void *desc)
3505 {
3506 char gbuf [CBUFSIZE];
3507 uint32 stop;
3508 
3509 if (cptr == NULL) {                                     /* if there are no arguments */
3510     sim_stops = 0;                                      /*   then clear all of the stop flags */
3511 
3512     if (option == 1)                                            /* if we're setting the stops */
3513         for (stop = 0; cpu_stop [stop].name != NULL; stop++)    /*   then loop through the flags */
3514             sim_stops |= cpu_stop [stop].mask;                  /*     and add each one to the set */
3515     }
3516 
3517 else if (*cptr == '\0')                                 /* otherwise if the argument is empty */
3518     return SCPE_MISVAL;                                 /*   then report the missing value */
3519 
3520 else                                                    /* otherwise at least one argument is present */
3521     while (*cptr) {                                     /* loop through the arguments */
3522         cptr = get_glyph (cptr, gbuf, ';');             /* get the next argument */
3523 
3524         for (stop = 0; cpu_stop [stop].name != NULL; stop++)    /* loop through the flags */
3525             if (strcmp (cpu_stop [stop].name, gbuf) == 0) {     /*   and if the argument matches */
3526                 if (option == 1)                                /*     then if it's a STOP argument */
3527                     sim_stops |= cpu_stop [stop].mask;          /*       then add the stop flag */
3528                 else                                            /*     otherwise it's a NOSTOP argument */
3529                     sim_stops &= ~cpu_stop [stop].mask;         /*       so remove the flag */
3530 
3531                 break;                                          /* this argument has been processed */
3532                 }
3533 
3534         if (cpu_stop [stop].name == NULL)               /* if the argument was not found */
3535             return SCPE_ARG;                            /*   then report it */
3536         }
3537 
3538 return SCPE_OK;                                         /* the stops were successfully processed */
3539 }
3540 
3541 
3542 /* Change the instruction execution trace criteria.
3543 
3544    This validation routine is called to configure the criteria that select
3545    instruction execution tracing.  The "option" parameter is 0 to clear and 1 to
3546    set the criteria, and "cptr" points to the first character of the match value
3547    to be set.  The unit and description pointers are not used.
3548 
3549    The routine processes commands of the form:
3550 
3551      SET CPU EXEC=<match>[;<mask>]
3552      SET CPU NOEXEC
3553 
3554    If the <mask> value is not supplied, a mask of 177777 octal is used.  The
3555    values are entered in the current CPU data radix, which defaults to octal,
3556    unless an override switch is present on the command line.
3557 */
3558 
set_exec(UNIT * uptr,int32 option,char * cptr,void * desc)3559 static t_stat set_exec (UNIT *uptr, int32 option, char *cptr, void *desc)
3560 {
3561 char   gbuf [CBUFSIZE];
3562 uint32 match, mask, radix;
3563 t_stat status;
3564 
3565 if (option == 0)                                        /* if this is a NOEXEC request */
3566     if (cptr == NULL) {                                 /*   then if there are no arguments */
3567         exec_match = D16_UMAX;                          /*     then set the match and mask values */
3568         exec_mask  = 0;                                 /*       to prevent matching */
3569         return SCPE_OK;                                 /*         and return success */
3570         }
3571 
3572     else                                                /*   otherwise there are extraneous characters */
3573         return SCPE_2MARG;                              /*     so report that there are too many arguments */
3574 
3575 else if (cptr == NULL || *cptr == '\0')                 /* otherwise if the EXEC request supplies no arguments */
3576     return SCPE_MISVAL;                                 /*   then report a missing value */
3577 
3578 else {                                                  /* otherwise at least one argument is present */
3579     cptr = get_glyph (cptr, gbuf, ';');                 /*   so get the match argument */
3580 
3581     if (sim_switches & SWMASK ('O'))                    /* if an octal override is present */
3582         radix = 8;                                      /*   then parse the value in base 8 */
3583     else if (sim_switches & SWMASK ('D'))               /* otherwise if a decimal override is present */
3584         radix = 10;                                     /*   then parse the value in base 10 */
3585     else if (sim_switches & SWMASK ('H'))               /* otherwise if a hex override is present */
3586         radix = 16;                                     /*   then parse the value in base 16 */
3587     else                                                /* otherwise */
3588         radix = cpu_dev.dradix;                         /*   use the current CPU data radix */
3589 
3590     match = (uint32) get_uint (gbuf, radix, D16_UMAX, &status); /* parse the match value */
3591 
3592     if (status != SCPE_OK)                              /* if a parsing error occurred */
3593         return status;                                  /*   then return the error status */
3594 
3595     else if (*cptr == '\0') {                           /* otherwise if no more characters are present */
3596         exec_match = match;                             /*   then set the match value */
3597         exec_mask  = D16_MASK;                          /*     and default the mask value */
3598         return SCPE_OK;                                 /*       and return success */
3599         }
3600 
3601     else {                                              /* otherwise another argument is present */
3602         cptr = get_glyph (cptr, gbuf, ';');             /*   so get the mask argument */
3603 
3604         mask = (uint32) get_uint (gbuf, radix, D16_UMAX, &status);  /* parse the mask value */
3605 
3606         if (status != SCPE_OK)                          /* if a parsing error occurred */
3607             return status;                              /*   then return the error status */
3608 
3609         else if (*cptr == '\0')                         /* if no more characters are present */
3610             if (mask == 0)                              /*   then if the mask value is zero */
3611                 return SCPE_ARG;                        /*     then the match will never succeed */
3612 
3613             else {                                      /*   otherwise */
3614                 exec_match = match;                     /*     set the match value */
3615                 exec_mask  = mask;                      /*       and the mask value */
3616                 return SCPE_OK;                         /*         and return success */
3617                 }
3618 
3619         else                                            /* otherwise extraneous characters are present */
3620             return SCPE_2MARG;                          /*   so report that there are too many arguments */
3621         }
3622     }
3623 }
3624 
3625 
3626 /* Set the CPU cold dump configuration jumpers.
3627 
3628    This validation routine is called to configure the set of jumpers on the
3629    system control panel that preset the device number and control value for the
3630    cold dump process.  The "option" parameter is 0 to set the device number
3631    and 1 to set the control value.  The "cptr" parameter points to the first
3632    character of the value to be set.  The unit and description pointers are not
3633    used.
3634 
3635    The routine processes commands of the form:
3636 
3637      SET CPU DUMPDEV=<devno>
3638      SET CPU DUMPCTL=<cntlval>
3639 
3640    The device number is a decimal value between 3 and 127, and the control value
3641    is an octal number between 0 and 377.  Values outside of these ranges are
3642    rejected.
3643 */
3644 
set_dump(UNIT * uptr,int32 option,char * cptr,void * desc)3645 static t_stat set_dump (UNIT *uptr, int32 option, char *cptr, void *desc)
3646 {
3647 t_value value;
3648 t_stat  status = SCPE_OK;
3649 
3650 if (cptr == NULL || *cptr == '\0')                      /* if the expected value is missing */
3651     status = SCPE_MISVAL;                               /*   then report the error */
3652 
3653 else if (option == 0) {                                 /* otherwise if a device number is present */
3654     value = get_uint (cptr, DEVNO_BASE,                 /*   then parse the supplied value */
3655                       DEVNO_MAX, &status);
3656 
3657     if (status == SCPE_OK)                                  /* if it is valid */
3658         if (value >= 3)                                     /*   and in the proper range */
3659             dump_control = REPLACE_LOWER (dump_control,     /*     then set the new device number */
3660                                           (uint32) value);  /*       into the dump control word */
3661         else                                                /*   otherwise the device number */
3662             status = SCPE_ARG;                              /*     is invalid */
3663     }
3664 
3665 else {                                                  /* otherwise a control byte is present */
3666     value = get_uint (cptr, CNTL_BASE,                  /*   so parse the supplied value */
3667                       CNTL_MAX, &status);
3668 
3669     if (status == SCPE_OK)                              /* if it is valid */
3670         dump_control = REPLACE_UPPER (dump_control,     /*   then set the new control value */
3671                                       (uint32) value);  /*     into the dump control word */
3672     }
3673 
3674 return status;                                          /* return the operation status */
3675 }
3676 
3677 
3678 /* Change the CPU memory size.
3679 
3680    This validation routine is called to configure the CPU memory size.  The
3681    "new_size" parameter is set to the size desired and will be one of the
3682    discrete sizes supported by the machine.  The "uptr" parameter points to the
3683    CPU unit and is used to obtain the CPU model.  The other parameters are not
3684    used.
3685 
3686    The routine processes commands of the form:
3687 
3688      SET [-F] CPU <memsize>
3689 
3690    If the new memory size is larger than the supported size for the CPU model
3691    currently selected, the routine returns an error.  If the new size is smaller
3692    than the previous size, and if the area that would be lost contains non-zero
3693    data, the user is prompted to confirm that memory should be truncated.  If
3694    the user denies the request, the change is rejected.  Otherwise, the new size
3695    is set.  The user may omit the confirmation request and force truncation by
3696    specifying the "-F" switch on the command line.
3697 
3698 
3699    Implementation notes:
3700 
3701     1. The memory access routines return a zero value for locations beyond the
3702        currently defined memory size.  Therefore, the unused area need not be
3703        explicitly zeroed.
3704 */
3705 
set_size(UNIT * uptr,int32 new_size,char * cptr,void * desc)3706 static t_stat set_size (UNIT *uptr, int32 new_size, char *cptr, void *desc)
3707 {
3708 static char confirm [] = "Really truncate memory [N]?";
3709 
3710 const uint32 model = CPU_MODEL (uptr->flags);           /* the current CPU model index */
3711 
3712 if ((uint32) new_size > cpu_features [model].maxmem)    /* if the new memory size is not supported on current model */
3713     return SCPE_NOFNC;                                  /*   then report the error */
3714 
3715 if (!(sim_switches & SWMASK ('F'))                      /* if truncation is not explicitly forced */
3716   && ! mem_is_empty (new_size)                          /*   and the truncated part is not empty */
3717   && get_yn (confirm, FALSE) == FALSE)                  /*     and the user denies confirmation */
3718     return SCPE_INCOMP;                                 /*       then abort the command */
3719 
3720 MEMSIZE = new_size;                                     /* set the new memory size */
3721 
3722 return SCPE_OK;                                         /* confirm that the change is OK */
3723 }
3724 
3725 
3726 /* Change the CPU model.
3727 
3728    This validation routine is called to configure the CPU model.  The
3729    "new_model" parameter is set to the model desired and will be one of the unit
3730    model flags.  The other parameters are not used.
3731 
3732    The routine processes commands of the form:
3733 
3734      SET [-F] CPU <model>
3735 
3736    Setting the model establishes a set of typical hardware features.  It also
3737    verifies that the current memory size is supported by the new model.  If it
3738    is not, the size is reduced to the maximum supported memory configuration.
3739    If the area that would be lost contains non-zero data, the user is prompted
3740    to confirm that memory should be truncated.  If the user denies the request,
3741    the change is rejected.  Otherwise, the new size is set.  The user may omit
3742    the confirmation request and force truncation by specifying the "-F" switch
3743    on the command line.
3744 
3745    This routine is also called once from the CPU reset routine to establish the
3746    initial CPU model.  The current memory size will be 0 when this call is made.
3747 */
3748 
set_model(UNIT * uptr,int32 new_model,char * cptr,void * desc)3749 static t_stat set_model (UNIT *uptr, int32 new_model, char *cptr, void *desc)
3750 {
3751 const uint32 new_index = CPU_MODEL (new_model);         /* the new index into the CPU features table */
3752 uint32 new_memsize;
3753 t_stat status;
3754 
3755 if (MEMSIZE == 0                                        /* if this is the initial establishing call */
3756   || MEMSIZE > cpu_features [new_index].maxmem)         /*   or if the current memory size is unsupported */
3757     new_memsize = cpu_features [new_index].maxmem;      /*     then set the new size to the maximum supported size */
3758 else                                                    /* otherwise the current size is valid for the new model */
3759     new_memsize = (uint32) MEMSIZE;                     /*   so leave it unchanged */
3760 
3761 status = set_size (uptr, new_memsize, NULL, NULL);      /* set the new memory size */
3762 
3763 if (status == SCPE_OK)                                  /* if the change succeeded */
3764     uptr->flags = uptr->flags & ~UNIT_OPTS              /*   then set the typical features */
3765                     | cpu_features [new_index].typ;     /*     for the new model */
3766 
3767 return status;                                          /* return the validation result */
3768 }
3769 
3770 
3771 /* Change a CPU option.
3772 
3773    This validation routine is called to configure the option set for the current
3774    CPU model.  The "new_option" parameter is set to the option desired and will
3775    be one of the unit option flags.  The "uptr" parameter points to the CPU unit
3776    and is used to obtain the CPU model.  The other parameters are not used.
3777 
3778    The routine processes commands of the form:
3779 
3780      SET CPU <option>[,<option>...]
3781 
3782    The option must be valid for the current CPU model, or the command is
3783    rejected.
3784 */
3785 
set_option(UNIT * uptr,int32 new_option,char * cptr,void * desc)3786 static t_stat set_option (UNIT *uptr, int32 new_option, char *cptr, void *desc)
3787 {
3788 const uint32 model = CPU_MODEL (uptr->flags);           /* the current CPU model index */
3789 
3790 if ((cpu_features [model].opt & new_option) != 0)       /* if the option is supported on the current model */
3791     return SCPE_OK;                                     /*   then confirm the change */
3792 else                                                    /* otherwise */
3793     return SCPE_NOFNC;                                  /*   reject the change */
3794 }
3795 
3796 
3797 /* Change the power-fail auto-restart switch setting.
3798 
3799    This validation routine is called to configure the PF/ARS switch that is
3800    located behind the system control panel.  If set to the ENBL (enable)
3801    position, the CPU will perform an auto-restart when power is restored after a
3802    failure.  In the DSBL (disable) position, the CPU will remain halted after
3803    power restoration; execution may be continued by pressing the RUN button.
3804 
3805    In simulation, a SET CPU ARS command enables auto-restart, and SET CPU NOARS
3806    disables auto-restart.  The "setting" parameter is set to the UNIT_ARS flag
3807    in the former cast and to zero in the latter case.  The other parameters are
3808    not used.  The routine reflects the ARS setting in "inhibit auto-restart" bit
3809    of the CPX2 register.
3810 */
3811 
set_pfars(UNIT * uptr,int32 setting,char * cptr,void * desc)3812 static t_stat set_pfars (UNIT *uptr, int32 setting, char *cptr, void *desc)
3813 {
3814 if (setting == UNIT_PFARS)                              /* if the option is ARS */
3815     CPX2 &= ~cpx2_INHPFARS;                             /*   then clear the auto-restart inhibit flag */
3816 else                                                    /* otherwise the option is NOARS */
3817     CPX2 |= cpx2_INHPFARS;                              /*   so set the auto-restart inhibit flag */
3818 
3819 return SCPE_OK;                                         /* confirm the change */
3820 }
3821 
3822 
3823 /* Show the CPU simulation stop conditions.
3824 
3825    This display routine is called to show the set of CPU stop conditions.  The
3826    "st" parameter is the open output stream.  The other parameters are not used.
3827 
3828    If at least one stop condition is enabled, the routine searches through the
3829    stop table for flag bits that are set in the stop set.  For each one it
3830    finds, the routine prints the corresponding stop name.
3831 
3832    This routine services an extended modifier entry, so it must add the trailing
3833    newline to the output before returning.
3834 */
3835 
show_stops(FILE * st,UNIT * uptr,int32 val,void * desc)3836 static t_stat show_stops (FILE *st, UNIT *uptr, int32 val, void *desc)
3837 {
3838 uint32 stop;
3839 t_bool need_spacer = FALSE;
3840 
3841 if (sim_stops == 0)                                     /* if no simulation stops are set */
3842     fputs ("Stops disabled", st);                       /*   then report that all are disabled */
3843 
3844 else {                                                  /* otherwise at least one stop is valid */
3845     fputs ("Stop=", st);                                /*   so prepare to report the list of conditions */
3846 
3847     for (stop = 0; cpu_stop [stop].name != NULL; stop++)    /* loop through the set of stops in the table */
3848         if (cpu_stop [stop].mask & sim_stops) {             /* if the current stop is enabled */
3849             if (need_spacer)                                /*   then if a spacer is needed */
3850                 fputc (';', st);                            /*     then add it first */
3851 
3852             fputs (cpu_stop [stop].name, st);               /* report the stop name */
3853 
3854             need_spacer = TRUE;                             /* a spacer will be needed next time */
3855             }
3856         }
3857 
3858 fputc ('\n', st);                                       /* add the trailing newline */
3859 
3860 return SCPE_OK;                                         /* report the success of the display */
3861 }
3862 
3863 
3864 /* Show the instruction execution trace criteria.
3865 
3866    This display routine is called to show the criteria that select instruction
3867    execution tracing.  The "st" parameter is the open output stream.  The other
3868    parameters are not used.
3869 
3870    This routine services an extended modifier entry, so it must add the trailing
3871    newline to the output before returning.
3872 */
3873 
show_exec(FILE * st,UNIT * uptr,int32 val,void * desc)3874 static t_stat show_exec (FILE *st, UNIT *uptr, int32 val, void *desc)
3875 {
3876 uint32 radix;
3877 
3878 if (exec_mask == 0)                                     /* if the instruction is entirely masked */
3879     fputs ("Execution trace disabled\n", st);           /*   then report that matching is disabled */
3880 
3881 else {                                                  /* otherwise */
3882     if (sim_switches & SWMASK ('O'))                    /*   if an octal override is present */
3883         radix = 8;                                      /*     then print the value in base 8 */
3884     else if (sim_switches & SWMASK ('D'))               /*   otherwise if a decimal override is present */
3885         radix = 10;                                     /*     then print the value in base 10 */
3886     else if (sim_switches & SWMASK ('H'))               /*   otherwise if a hex override is present */
3887         radix = 16;                                     /*     then print the value in base 16 */
3888     else                                                /*   otherwise */
3889         radix = cpu_dev.dradix;                         /*     use the current CPU data radix */
3890 
3891     fputs ("Execution trace match = ", st);                         /* print the label */
3892     fprint_val (st, exec_match, radix, cpu_dev.dwidth, PV_RZRO);    /*   and the match value */
3893 
3894     fputs (", mask = ", st);                                        /* print a separator */
3895     fprint_val (st, exec_mask, radix, cpu_dev.dwidth, PV_RZRO);     /*   and the mask value */
3896 
3897     fputc ('\n', st);                                               /* tie off the line */
3898     }
3899 
3900 return SCPE_OK;                                         /* report the success of the display */
3901 }
3902 
3903 
3904 /* Show the CPU cold dump configuration jumpers.
3905 
3906    This display routine is called to show the device number and control byte
3907    that are preset on the rear of the system control panel for the cold dump
3908    process.  The "st" parameter is the open output stream.  The other parameters
3909    are not used.
3910 */
3911 
show_dump(FILE * st,UNIT * uptr,int32 val,void * desc)3912 static t_stat show_dump (FILE *st, UNIT *uptr, int32 val, void *desc)
3913 {
3914 fprintf (st, "Dump device = %u, dump control = %03o\n",
3915          LOWER_BYTE (dump_control), UPPER_BYTE (dump_control));
3916 
3917 return SCPE_OK;
3918 }
3919 
3920 
3921 /* Show the current CPU simulation speed.
3922 
3923    This display routine is called to show the current simulation speed.  The
3924    "st" parameter is the open output stream.  The other parameters are not used.
3925 
3926    The CPU speed, expressed as a multiple of the hardware speed, is calculated
3927    by the process clock service routine.  It is only representative when the
3928    process clock is calibrated, and the CPU is not executing a PAUS instruction
3929    (which suspends the normal fetch/execute instruction cycle).
3930 */
3931 
show_speed(FILE * st,UNIT * uptr,int32 val,void * desc)3932 static t_stat show_speed (FILE *st, UNIT *uptr, int32 val, void *desc)
3933 {
3934 fprintf (st, "Simulation speed = %ux\n", cpu_speed);    /* display the current CPU speed */
3935 return SCPE_OK;                                         /*   and report success */
3936 }
3937 
3938 
3939 
3940 /* CPU local utility routines */
3941 
3942 
3943 /* Process a halt-mode interrupt.
3944 
3945    This routine is called when one or more of the interrupt request bits are set
3946    in the CPX2 register.  These bits represent switch closures on the CPU front
3947    panel or on the optional maintenance display panel.  The specific switch
3948    closure is identified, and the corresponding microcode routine is executed.
3949    If multiple bits are set in CPX2, the microcode recognizes them in order from
3950    MSB to LSB.
3951 
3952    If the RUN switch is set, a test is made for a System Halt, which inhibits
3953    recognition of the switch.  If the System Halt flag is set, the CPU must be
3954    reset before execution may be resumed.  Otherwise, the NIR is reloaded in
3955    case P was changed during the simulation stop.  If the R-bit (right stack op
3956    pending) flag in the status register is set, but the NIR no longer contains a
3957    stack instruction, R is cleared.  If a stack instruction is present, and the
3958    R-bit is set, then the CIR is set, and the following instruction is fetched.
3959    The micromachine state is set to "running", and one event tick is added back
3960    to the accumulator to ensure that a single step won't complete without
3961    executing an instruction.
3962 
3963    If the DUMP switch is pressed, an I/O Reset is performed on all devices
3964    except the CPU, which is skipped to preserve the register state.  The dump
3965    device number is obtained from the SWCH register and tested to ensure that a
3966    tape is mounted with a write ring and the unit is online.  Then the contents
3967    of the CPU registers are written to the reserved memory area starting at
3968    address 1400 octal in bank 0.  This is followed by two SIO programs.  The
3969    main program at addresses 1430-1437 write 4K-word blocks of memory to the
3970    dump device.  The error recovery program at addresses 1422-1427 is invoked
3971    when a write fails.  It does a Backspace Record followed by a Write Gap to
3972    skip the bad spot on the tape, and then the write is retried.
3973 
3974    The DUMP switch remains set, so after each pass through the main execution
3975    loop to run a channel cycle, this routine is reentered.  The "waiting" state
3976    causes the second part of the process to check for device completion.  When
3977    it occurs, the expected external interrupt is cleared, and if the dump is
3978    complete, the DUMP switch is reset, the original SIO pointer in the DRT is
3979    restored, and the micromachine is halted.  Otherwise, the SIO pointer is
3980    read.  If it points at the end of the program, then the operation completed
3981    normally.  In this case, the dump address is advanced, and, if all of memory
3982    has been dumped, the SIO pointer is reset to the recovery program, and that
3983    program is changed to finish up with Write File Mark and Rewind/Offline
3984    commands.  Otherwise, the pointer is reset to the main program in preparation
3985    for the next 4K write.  The SIO program is then restarted.
3986 
3987    If SIO pointer failed to complete, the pointer is reset to point at the error
3988    recovery program, and the memory address is unchanged; the same 4K write will
3989    be performed once the recovery program runs.  If the recovery program fails,
3990    the dump is terminated at that point with a failure indication.
3991 
3992    During the dump operation, the CIR register is continually updated with the
3993    current memory bank number.  If the dump runs to completion, CIR will contain
3994    the number of 64K memory banks installed in the machine.  A value less than
3995    the installed memory value indicates a dump failure.  Except for the CIR, the
3996    machine state is restored, so that another dump may be attempted.
3997 
3998    If the LOAD switch is pressed, the cold load process begins by filling memory
3999    with HALT 10 instructions if SWCH register bit 8 is clear.  The cold load
4000    device number is obtained from the lower byte of the SWCH register.
4001 
4002    The first part of the cold load process clears the TOS and STA registers,
4003    stores the initial channel program in memory, and executes an SIO instruction
4004    to start the channel.  Once the device starts, interrupts are enabled, and
4005    the micromachine state is set to "waiting" in preparation for executing the
4006    second part of the cold load process once the channel program ends.  The
4007    routine then exits to begin channel execution.
4008 
4009    The LOAD switch remains set, so after each pass through the main execution
4010    loop to run a channel cycle, this routine is reentered.  The "waiting" state
4011    causes the second part of the process to check for device completion.  The
4012    expected external interrupt is cleared, the LOAD switch is cleared, the
4013    micromachine state is set to "running", and the Cold Load trap is taken to
4014    complete the process.
4015 
4016 
4017    Implementation notes:
4018 
4019     1. After processing the RUN switch and returning to the instruction loop, if
4020        no interrupt is present, and the R-bit in the status register is clear,
4021        then CIR will be set from NIR, and NIR will be reloaded.  If the R-bit is
4022        set, then CIR and NIR will not be changed, i.e., the NEXT action will be
4023        skipped, so we perform it here.  If an interrupt is pending, then the
4024        interrupt will be processed using the old value of the CIR, and the
4025        instruction in the NIR will become the first instruction executed after
4026        the interrupt handler completes.
4027 
4028     2. The cold load microcode is shared with the cold dump process.  The Series
4029        II dump process saves memory locations DRT + 0 through DRT + 3 in the TOS
4030        registers.  The load process uses the same microcode but does not perform
4031        the memory read, so the TOS registers are loaded with the previous
4032        contents of the OPND register, which is effectively a random value.  In
4033        simulation, the TOS registers are cleared.
4034 
4035     3. The cold load and dump microcode waits forever for an interrupt from the
4036        cold load device.  If it doesn't occur, the microcode hangs until a
4037        system reset is performed (it tests CPX1 bit 8 and does a JMP *-1 if the
4038        bit is not set).  The simulation follows the microcode behavior.
4039 
4040     4. Front panel diagnostics and direct I/O cold loading is not implemented.
4041 */
4042 
halt_mode_interrupt(HP_WORD device_number)4043 static t_stat halt_mode_interrupt (HP_WORD device_number)
4044 {
4045 static HP_WORD cold_device, sio_pointer, status, offset, pointer;
4046 static uint32 address;
4047 static t_bool error_recovery;
4048 
4049 if (CPX2 & cpx2_RUNSWCH) {                              /* if the RUN switch is pressed */
4050     if (CPX2 & cpx2_SYSHALT) {                          /*   then if the System Halt flip-flop is set */
4051         CPX2 &= ~CPX2_IRQ_SET;                          /*     then clear all switches */
4052         return STOP_SYSHALT;                            /*       as the CPU cannot run until it is reset */
4053         }
4054 
4055     else                                                /*   otherwise */
4056         CPX2 = CPX2 & ~cpx2_RUNSWCH | cpx2_RUN;         /*     clear the switch and set the Run flip-flop */
4057 
4058     cpu_read_memory (fetch, P, &NIR);                   /* load the next instruction to execute */
4059     P = P + 1 & R_MASK;                                 /*   and point to the following instruction */
4060 
4061     if ((NIR & PAUS_MASK) == PAUS)                      /* if resuming into a PAUS instruction */
4062         cpu_stop_flags |= SS_PAUSE_RESUMED;             /*   then defer any interrupt until after PAUS is executed */
4063 
4064     if ((NIR & SUBOP_MASK) != 0)                        /* if the instruction is not a stack instruction */
4065         STA &= ~STATUS_R;                               /*   then clear the R-bit in case it had been set */
4066 
4067     else if (STA & STATUS_R) {                          /* otherwise if a right-hand stack op is pending */
4068         CIR = NIR;                                      /*   then set the current instruction */
4069         cpu_read_memory (fetch, P, &NIR);               /*     and load the next instruction */
4070         }
4071 
4072     cpu_micro_state = running;                          /* start the micromachine */
4073     sim_interval = sim_interval + 1;                    /* don't count this cycle against a STEP count */
4074 
4075     if (cpu_power_state == power_returning) {           /* if power is returning after a failure */
4076         if (CPX2 & cpx2_INHPFARS)                       /*   then if auto-restart is inhibited */
4077             CPX2 &= ~cpx2_RUN;                          /*     then clear the Run flip-flop */
4078 
4079         MICRO_ABORT (trap_Power_On);                    /* set up the trap to the power-on routine */
4080         }
4081     }
4082 
4083 
4084 else if (CPX2 & cpx2_DUMPSWCH) {                        /* otherwise if the DUMP switch is pressed */
4085     if (cpu_micro_state != waiting) {                   /*   then if the dump is not in progress */
4086         reset_all (IO_RESET);                           /*     then reset all I/O devices */
4087 
4088         cold_device = LOWER_BYTE (SWCH) & DEVNO_MASK;   /* get the device number from the lower SWCH byte */
4089 
4090         status = iop_direct_io (cold_device, ioTIO, 0); /* get the device status */
4091 
4092         if ((status & MS_ST_MASK) != MS_ST_READY) {     /* if the tape is not ready and unprotected */
4093             CPX2 &= ~cpx2_DUMPSWCH;                     /*   then clear the dump switch */
4094 
4095             CIR = 0;                                    /* clear CIR to indicate a failure */
4096             return STOP_CDUMP;                          /*   and terminate the dump */
4097             }
4098 
4099         cpu_read_memory (absolute, cold_device * 4,     /* get the original DRT pointer */
4100                          &sio_pointer);
4101 
4102         cpu_write_memory (absolute, 01400, 1);              /* set the machine ID to 1 for the Series III */
4103         cpu_write_memory (absolute, 01401, sio_pointer);    /* store the original DRT pointer */
4104         cpu_write_memory (absolute, 01402, SM);             /* store the stack pointer */
4105         cpu_write_memory (absolute, 01403, 0);              /* store zeros for the scratch pad 1 */
4106         cpu_write_memory (absolute, 01404, 0);              /*   and scratch pad 2 register values */
4107         cpu_write_memory (absolute, 01405, DB);             /* store the data base */
4108         cpu_write_memory (absolute, 01406, DBANK << 12      /* store DBANK in 0:4 */
4109                                              | PBANK << 8   /*   and PBANK in 4:4 */
4110                                              | SBANK);      /*     and SBANK in 12:4 */
4111         cpu_write_memory (absolute, 01407, Z);              /* store the stack limit */
4112         cpu_write_memory (absolute, 01410, DL);             /*   and the data limit */
4113         cpu_write_memory (absolute, 01411, X);              /*   and the index register */
4114         cpu_write_memory (absolute, 01412, Q);              /*   and the frame pointer */
4115         cpu_write_memory (absolute, 01413, CIR);            /*   and the current instruction */
4116         cpu_write_memory (absolute, 01414, PB);             /*   and the program base */
4117         cpu_write_memory (absolute, 01415, PL);             /*   and the program limit */
4118         cpu_write_memory (absolute, 01416, P);              /*   and the program counter */
4119         cpu_write_memory (absolute, 01417, CPX1);           /* store the CPX1 register */
4120         cpu_write_memory (absolute, 01420, STA);            /*   and the status register */
4121         cpu_write_memory (absolute, 01421,                  /* store the lower byte of the CPX2 register */
4122                           LOWER_WORD (CPX2 << 8             /*   in the upper byte of memory */
4123                             | MEMSIZE / 65536));            /*     and the memory bank count in the lower byte */
4124 
4125         cpu_write_memory (absolute, 01422, SIO_CNTL);           /* CONTRL 0,BSR */
4126         cpu_write_memory (absolute, 01423, MS_CN_BSR);
4127         cpu_write_memory (absolute, 01424, SIO_CNTL);           /* CONTRL 0,GAP */
4128         cpu_write_memory (absolute, 01425, MS_CN_GAP);
4129         cpu_write_memory (absolute, 01426, SIO_JUMP);           /* JUMP   001436 */
4130         cpu_write_memory (absolute, 01427, 001436);
4131 
4132         cpu_write_memory (absolute, 01430, SIO_SBANK);          /* SETBNK 0 */
4133         cpu_write_memory (absolute, 01431, 000000);
4134         cpu_write_memory (absolute, 01432, SIO_CNTL);           /* CONTRL 0,<SWCH-upper> */
4135         cpu_write_memory (absolute, 01433, UPPER_BYTE (SWCH));
4136         cpu_write_memory (absolute, 01434, SIO_WRITE);          /* WRITE  #4096,000000 */
4137         cpu_write_memory (absolute, 01435, 000000);
4138         cpu_write_memory (absolute, 01436, SIO_ENDIN);          /* ENDINT */
4139         cpu_write_memory (absolute, 01437, 000000);
4140 
4141         address = 0;                                    /* clear the address */
4142         offset = 0;                                     /*   and memory offset counters */
4143 
4144         CIR = 0;                                        /* clear the memory bank counter */
4145 
4146         cpu_write_memory (absolute, cold_device * 4, 01430);    /* point the DRT at the cold dump program */
4147         error_recovery = FALSE;
4148 
4149         iop_direct_io (cold_device, ioSIO, 0);          /* start the device */
4150 
4151         if (CPX1 & cpx1_IOTIMER)                        /* if the device did not respond */
4152             MICRO_ABORT (trap_SysHalt_IO_Timeout);      /*   then a System Halt occurs */
4153 
4154         else {                                          /* otherwise the device has started */
4155             status = STA;                               /*   so save the original status register value */
4156 
4157             STA = STATUS_I | STATUS_O;                  /* enable interrupts and set overflow */
4158             cpu_micro_state = waiting;                  /*   and set the load-in-progress state */
4159             }
4160         }
4161 
4162     else if (CPX1 & cpx1_EXTINTR) {                     /* otherwise if an external interrupt is pending */
4163         CPX1 &= ~cpx1_EXTINTR;                          /*   then clear it */
4164 
4165         iop_direct_io (device_number, ioRIN, 0);        /* reset the device interrupt */
4166 
4167         if (device_number == cold_device)               /* if the expected device interrupted */
4168             if (address >= MEMSIZE) {                   /*   then if all of memory has been dumped */
4169                 CPX2 &= ~cpx2_DUMPSWCH;                 /*   then reset the DUMP switch */
4170 
4171                 STA = status;                           /* restore the original status register value */
4172 
4173                 cpu_write_memory (absolute,             /* restore the */
4174                                   cold_device * 4,      /*   original SIO pointer */
4175                                   sio_pointer);         /*     to the DRT */
4176 
4177                 cpu_micro_state = halted;               /* clear the dump-in-progress state */
4178                 return STOP_CDUMP;                      /*   and report dump completion */
4179                 }
4180 
4181             else {                                      /* otherwise the dump continues */
4182                 cpu_read_memory (absolute,              /* read the */
4183                                  cold_device * 4,       /*   current SIO pointer address */
4184                                  &pointer);             /*     from the DRT */
4185 
4186                 if (pointer == 01440) {                 /* if the SIO program completed normally */
4187                     cpu_write_memory (absolute,         /*   then reset the pointer */
4188                                       cold_device * 4,  /*     to the start */
4189                                       001430);          /*       of the program */
4190 
4191                     if (error_recovery)                 /* if this was a successful error recovery */
4192                         error_recovery = FALSE;         /*   then clear the flag and keep the current address */
4193 
4194                     else {                                  /* otherwise this was a successful write */
4195                         address = address + 4096;           /*   so bump the memory address */
4196                         offset = offset + 4096 & LA_MASK;   /*     and offset to the next 4K block */
4197 
4198                         cpu_write_memory (absolute,         /* store the new write buffer address */
4199                                           001435, offset);
4200 
4201                         if (offset == 0) {                  /* if the offset wrapped around */
4202                             CIR = CIR + 1;                  /*   then increment the bank number */
4203                             cpu_write_memory (absolute,     /*     and store it as the SET BANK target */
4204                                               001431, CIR);
4205 
4206                             if (address >= MEMSIZE) {               /* if all of memory has been dumped */
4207                                 cpu_write_memory (absolute, 001423, /*   then change the error recovery program */
4208                                                   MS_CN_WFM);       /*     to write a file mark */
4209                                 cpu_write_memory (absolute, 001425, /*       followed by */
4210                                                   MS_CN_RST);       /*         a rewind/offline request */
4211 
4212                                 cpu_write_memory (absolute,         /* point at the recovery program */
4213                                                   cold_device * 4,
4214                                                   001422);
4215                                 }
4216                             }
4217                         }
4218                     }
4219 
4220                 else if (error_recovery) {              /* otherwise if the recover program failed */
4221                     CPX2 &= ~cpx2_DUMPSWCH;             /*   then reset the DUMP switch */
4222 
4223                     STA = status;                       /* restore the original status register value */
4224 
4225                     cpu_write_memory (absolute,         /* restore the */
4226                                       cold_device * 4,  /*   original SIO pointer */
4227                                       sio_pointer);     /*     to the DRT */
4228 
4229                     cpu_micro_state = halted;           /* clear the dump-in-progress state */
4230                     return STOP_CDUMP;                  /*   and report dump failure */
4231                     }
4232 
4233                 else {                                  /* otherwise attempt error recovery */
4234                     cpu_write_memory (absolute,         /*   by setting the SIO pointer */
4235                                       cold_device * 4,  /*     to the backspace/write gap */
4236                                       001422);          /*       program */
4237 
4238                     error_recovery = TRUE;              /* indicate that recovery is in progress */
4239                     }
4240 
4241                 iop_direct_io (cold_device, ioSIO, 0);  /* start the device */
4242                 }
4243         }                                               /* otherwise wait for the cold dump device to interrupt */
4244     }
4245 
4246 else if (CPX2 & cpx2_LOADSWCH)                          /* otherwise if the LOAD switch is pressed */
4247     if (cpu_micro_state != waiting) {                   /*   then if the load is not in progress */
4248         reset_all (CPU_IO_RESET);                       /*     then reset the CPU and all I/O devices */
4249 
4250         if ((SWCH & 000200) == 0)                       /* if switch register bit 8 is clear */
4251             mem_fill (0, HALT_10);                      /*   then fill all of memory with HALT 10 instructions */
4252 
4253         SBANK = 0;                                      /* set the stack bank to bank 0 */
4254 
4255         cold_device = LOWER_BYTE (SWCH) & DEVNO_MASK;   /* get the device number from the lower SWCH byte */
4256 
4257         if (cold_device < 3) {                          /* if the device number is between 0 and 2 */
4258             CPX2 &= ~cpx2_LOADSWCH;                     /*   then reset the LOAD switch */
4259             return SCPE_INCOMP;                         /*     and execute a front panel diagnostic */
4260             }
4261 
4262         else if (cold_device > 63) {                    /* otherwise if the device number is > 63 */
4263             CPX2 &= ~cpx2_LOADSWCH;                     /*   then reset the LOAD switch */
4264             return SCPE_INCOMP;                         /*     and execute a direct I/O cold load */
4265             }
4266 
4267         else {                                          /* otherwise the device number is in the channel I/O range */
4268             RA = 0;                                     /* set the */
4269             RB = 0;                                     /*   TOS registers */
4270             RC = 0;                                     /*     to the same */
4271             RD = 0;                                     /*       (random) value */
4272 
4273             SR = 4;                                     /* mark the TOS registers as valid */
4274             STA = 0;                                    /*   and clear the status register */
4275 
4276             cpu_write_memory (absolute, 01430, SIO_SBANK);          /* SETBNK 0 */
4277             cpu_write_memory (absolute, 01431, 000000);
4278             cpu_write_memory (absolute, 01432, SIO_CNTL);           /* CONTRL 0,<SWCH-upper> */
4279             cpu_write_memory (absolute, 01433, UPPER_BYTE (SWCH));
4280             cpu_write_memory (absolute, 01434, SIO_READ);           /* READ   #16,001400 */
4281             cpu_write_memory (absolute, 01435, 001400);
4282             cpu_write_memory (absolute, 01436, SIO_JUMP);           /* JUMP   001400 */
4283             cpu_write_memory (absolute, 01437, 001400);
4284 
4285             cpu_write_memory (absolute, cold_device * 4, 01430);    /* point the DRT to the cold load program */
4286 
4287             iop_direct_io (cold_device, ioSIO, 0);      /* start the device */
4288 
4289             if (CPX1 & cpx1_IOTIMER)                    /* if the device did not respond */
4290                 MICRO_ABORT (trap_SysHalt_IO_Timeout);  /*   then a System Halt occurs */
4291 
4292             else {                                      /* otherwise the device has started */
4293                 STA = STATUS_I | STATUS_O;              /*   so enable interrupts and set overflow */
4294                 cpu_micro_state = waiting;              /*     and set the load-in-progress state */
4295                 }
4296             }
4297         }
4298 
4299     else                                                /* otherwise the load is in progress */
4300         if (CPX1 & cpx1_EXTINTR) {                      /* if an external interrupt is pending */
4301             CPX1 &= ~cpx1_EXTINTR;                      /*   then clear it */
4302 
4303             iop_direct_io (device_number, ioRIN, 0);    /* reset the device interrupt */
4304 
4305             if (device_number == cold_device) {         /* if the expected device interrupted */
4306                 CPX2 &= ~cpx2_LOADSWCH;                 /*   then reset the LOAD switch */
4307 
4308                 cpu_micro_state = running;              /* clear the load-in-progress state */
4309                 MICRO_ABORT (trap_Cold_Load);           /*   and execute the cold load trap handler */
4310                 }
4311             }                                           /* otherwise wait for the cold load device to interrupt */
4312 
4313 return SCPE_OK;
4314 }
4315 
4316 
4317 /* Execute one machine instruction.
4318 
4319    This routine executes the CPU instruction present in the CIR.  The CPU state
4320    (registers, memory, interrupt status) is modified as necessary, and the
4321    routine return SCPE_OK if the instruction executed successfully.  Any other
4322    status indicates that execution should cease, and control should return to
4323    the simulator console.  For example, a programmed HALT instruction returns
4324    STOP_HALT status.
4325 
4326    Unimplemented instructions are detected by those decoding branches that
4327    result from bit patterns not corresponding to legal instructions or
4328    corresponding to optional instructions not currently enabled.  Normally,
4329    execution of an unimplemented instruction would result in an Unimplemented
4330    Instruction trap.  However, for debugging purposes, a simulator stop may be
4331    requested instead by returning STOP_UNIMPL status if the SS_UNIMPL simulation
4332    stop flag is set.
4333 
4334    This routine implements the main instruction dispatcher, as well as memory
4335    address instructions (subopcodes 04-17).  Instructions corresponding to
4336    subopcodes 00-03 are executed by routines in the base instruction set module.
4337 
4338 
4339    Implementation notes:
4340 
4341     1. Each instruction executor begins with a comment listing the instruction
4342        mnemonic and, following in parentheses, the condition code setting, or
4343        "none" if the condition code is not altered, and a list of any traps that
4344        might be generated.
4345 
4346     2. Stack preadjusts are simpler if performed explicitly due to overlapping
4347        requirements that reduce the number of static preadjusts to 4 of the 16
4348        entries.
4349 
4350     3. The order of operations for each instruction follows the microcode.  For
4351        example, the LOAD instruction performs the bounds check on the effective
4352        address and reads the operand before pushing the stack down and storing
4353        it in the RA registrer.  Pushing the stack down first and then reading
4354        the value directly into the RA register would leave the stack in a
4355        different state if the memory access caused a Bounds Violation trap.
4356 
4357     4. The TBA, MTBA, TBX, and MTBX instructions take longer to execute than the
4358        nominal 2.5 microseconds assumed for the average instruction execution
4359        time.  Consequently, the 7905 disc diagnostic fails Step 66 (the retry
4360        counter test) if the DS device is set for REALTIME operation.  The
4361        diagnostic uses the MTBA P+0 instruction in a timing loop, which expires
4362        before the disc operations complete.
4363 
4364        A workaround for this diagnostic is to decrement sim_interval twice for
4365        these instructions.  However, doing so causes the 7970 tape diagnostic to
4366        fail Step 532 (the timing error test) for the opposite reason: a wait
4367        loop of MTBA P+0 instructions causes the tape data transfer service event
4368        time to count down twice as fast, while the multiplexer channel data
4369        transfer polls occur at the usual one per instruction.  This could be
4370        remedied by having the channel polls execute twice as many I/O cycles for
4371        these instructions, although the general solution would be to recast
4372        sim_intervals as microseconds and to decrement sim_interval by differing
4373        amounts appropriate for each instruction.
4374 */
4375 
machine_instruction(void)4376 static t_stat machine_instruction (void)
4377 {
4378 HP_WORD       displacement, opcode, offset, operand, operand_1, operand_2, result;
4379 int32         control, limit;
4380 ACCESS_CLASS  class;
4381 BYTE_SELECTOR selector;
4382 t_bool        branch;
4383 t_stat        status = SCPE_OK;
4384 
4385 switch (SUBOP (CIR)) {                                  /* dispatch on bits 0-3 of the instruction */
4386 
4387     case 000:                                           /* stack operations */
4388         status = cpu_stack_op ();                       /* set the status from the instruction executor */
4389         break;
4390 
4391 
4392     case 001:                                           /* shift, branch, and bit test operations */
4393         status = cpu_shift_branch_bit_op ();            /* set the status from the instruction executor */
4394         break;
4395 
4396 
4397     case 002:                                           /* move, special, firmware, immediate, field, and register operations */
4398         status = cpu_move_spec_fw_imm_field_reg_op ();  /* set the status from the instruction executor */
4399         break;
4400 
4401 
4402     case 003:                                           /* I/O, control, program, immediate, and memory operations */
4403         status = cpu_io_cntl_prog_imm_mem_op ();        /* set the status from the instruction executor */
4404         break;
4405 
4406 
4407     case 004:                                           /* LOAD (CCA; STOV, BNDV) */
4408         cpu_ea (CIR, &class, &offset, NULL);            /* get the effective address */
4409         cpu_read_memory (class, offset, &operand);      /*   and read the operand */
4410 
4411         cpu_push ();                                    /* push the operand */
4412         RA = operand;                                   /*   onto the stack */
4413 
4414         SET_CCA (RA, 0);                                /* set the condition code */
4415         break;
4416 
4417 
4418     case 005:                                           /* TBA, MTBA, TBX, MTBX, and STOR */
4419         if (CIR & M_FLAG) {                             /* STOR (none; STUN, BNDV) */
4420             cpu_ea (CIR, &class, &offset, NULL);        /* get the effective address */
4421 
4422             PREADJUST_SR (1);                           /* ensure that at least one TOS register is loaded */
4423 
4424             cpu_write_memory (class, offset, RA);       /* write the TOS to memory */
4425             cpu_pop ();                                 /*   and pop the stack */
4426             }
4427 
4428         else {                                          /* TBA, MTBA, TBX, or MTBX */
4429             opcode = CIR & TBR_MASK;                    /* get the test and branch operation */
4430 
4431             if (opcode == TBA || opcode == MTBA) {      /* TBA or MTBA (none; STUN, STOV, BNDV) */
4432                 PREADJUST_SR (3);                       /* ensure that at least three TOS registers are loaded */
4433 
4434                 while (SR > 3)                          /* if more than three TOS register are loaded */
4435                     cpu_queue_down ();                  /*   queue them down until exactly three are left */
4436 
4437                 offset = DB + RC & LA_MASK;             /* get the address of the control value */
4438 
4439                 if (DL <= offset && offset <= SM || PRIV)       /* if the address is within the segment */
4440                     cpu_read_memory (data, offset, &operand);   /*   then read the value */
4441 
4442                 else                                            /* otherwise */
4443                     MICRO_ABORT (trap_Bounds_Violation);        /*   trap with a bounds violation if not privileged */
4444 
4445                 if (opcode == MTBA) {                           /* if the instruction is MTBA */
4446                     operand = operand + RB & DV_MASK;           /*   then add the step size */
4447                     cpu_write_memory (data, offset, operand);   /*     to the control variable */
4448                     }
4449 
4450                 control = SEXT16 (operand);             /* sign-extend the control value */
4451                 }
4452 
4453             else {                                      /* TBX or MTBX (none; STUN, BNDV) */
4454                 PREADJUST_SR (2);                       /* ensure that at least two TOS registers are loaded */
4455 
4456                 if (opcode == MTBX)                     /* if the instruction is MTBX */
4457                     X = X + RB & R_MASK;                /*   then add the step size to the control variable */
4458 
4459                 control = SEXT16 (X);                   /* sign-extend the control value */
4460                 }
4461 
4462             limit = SEXT16 (RA);                        /* sign-extend the limit value */
4463 
4464             if (RB & D16_SIGN)                          /* if the step size is negative */
4465                 branch = control >= limit;              /*   then branch if the value is not below the limit */
4466             else                                        /* otherwise */
4467                 branch = control <= limit;              /*   branch if the value is not above the limit */
4468 
4469             if (branch) {                                       /* if the test succeeded */
4470                 displacement = CIR & DISPL_255_MASK;            /*   then get the branch displacement */
4471 
4472                 if (CIR & DISPL_255_SIGN)                       /* if the displacement is negative */
4473                     offset = P - 2 - displacement & LA_MASK;    /*   then subtract the displacement from the base */
4474                 else                                            /* otherwise */
4475                     offset = P - 2 + displacement & LA_MASK;    /*   add the displacement to the base */
4476 
4477                 if (cpu_stop_flags & SS_LOOP                    /* if the infinite loop stop is active */
4478                   && displacement == 0                          /*   and the target is the current instruction */
4479                   && (opcode == TBA || opcode == TBX))          /*     and the instruction must be checked */
4480                     status = STOP_INFLOOP;                      /*       then stop the simulator */
4481                 else                                            /* otherwise */
4482                     status = SCPE_OK;                           /*   continue */
4483 
4484                 cpu_read_memory (fetch_checked, offset, &NIR);  /* load the next instruction register */
4485                 P = offset + 1 & R_MASK;                        /*   and increment the program counter */
4486                 }
4487 
4488             else {                                      /* otherwise the test failed */
4489                 cpu_pop ();                             /*   so pop the limit */
4490                 cpu_pop ();                             /*     and the step size from the stack */
4491 
4492                 if (opcode == TBA || opcode == MTBA)    /* if the instruction is TBA or MTBA */
4493                     cpu_pop ();                         /*   then pop the variable address too */
4494                 }                                       /*     and continue execution at P + 1 */
4495             }
4496         break;
4497 
4498 
4499     case 006:                                           /* CMPM (CCC; STUN) */
4500         cpu_ea (CIR, &class, &offset, NULL);            /* get the effective address */
4501         cpu_read_memory (class, offset, &operand);      /*   and read the operand */
4502 
4503         PREADJUST_SR (1);                               /* ensure that at least one TOS register is loaded */
4504 
4505         SET_CCC (RA, 0, operand, 0);                    /* set the condition code from the TOS value */
4506         cpu_pop ();                                     /*   and then pop the value from the stack */
4507         break;
4508 
4509 
4510     case 007:                                           /* ADDM (CCA, C, O; STUN, BNDV, ARITH) */
4511         cpu_ea (CIR, &class, &offset, NULL);            /* get the effective address */
4512         cpu_read_memory (class, offset, &operand);      /*   and read the operand */
4513 
4514         PREADJUST_SR (1);                               /* ensure that at least one TOS register is loaded */
4515 
4516         RA = cpu_add_16 (RA, operand);                  /* add the operands */
4517         SET_CCA (RA, 0);                                /*   and set the condition code */
4518         break;
4519 
4520 
4521     case 010:                                           /* SUBM (CCA, C, O; STUN, BNDV, ARITH) */
4522         cpu_ea (CIR, &class, &offset, NULL);            /* get the effective address */
4523         cpu_read_memory (class, offset, &operand);      /*   and read the operand */
4524 
4525         PREADJUST_SR (1);                               /* ensure that at least one TOS register is loaded */
4526 
4527         RA = cpu_sub_16 (RA, operand);                  /* subtract the operands */
4528         SET_CCA (RA, 0);                                /*   and set the condition code */
4529         break;
4530 
4531 
4532     case 011:                                           /* MPYM (CCA, O; STUN, STOV, BNDV, ARITH) */
4533         cpu_ea (CIR, &class, &offset, NULL);            /* get the effective address */
4534         cpu_read_memory (class, offset, &operand);      /*   and read the operand */
4535 
4536         PREADJUST_SR (1);                               /* ensure that at least one TOS register is loaded */
4537 
4538         RA = cpu_mpy_16 (RA, operand);                  /* multiply the operands */
4539         SET_CCA (RA, 0);                                /*   and set the condition code */
4540         break;
4541 
4542 
4543     case 012:                                           /* INCM, DECM */
4544         cpu_ea (CIR | M_FLAG, &class, &offset, NULL);   /* get the effective address (forced to data-relative) */
4545         cpu_read_memory (class, offset, &operand);      /*   and read the operand */
4546 
4547         if (CIR & M_FLAG)                               /* DECM (CCA, C, O; BNDV, ARITH) */
4548             result = cpu_sub_16 (operand, 1);           /* decrement the operand and set C and O as necessary */
4549         else                                            /* INCM (CCA, C, O; BNDV, ARITH) */
4550             result = cpu_add_16 (operand, 1);           /* increment the operand and set C and O as necessary */
4551 
4552         cpu_write_memory (class, offset, result);       /* write the operand back to memory */
4553         SET_CCA (result, 0);                            /*   and set the condition code */
4554         break;
4555 
4556 
4557     case 013:                                           /* LDX (CCA; BNDV) */
4558         cpu_ea (CIR, &class, &offset, NULL);            /* get the effective address */
4559         cpu_read_memory (class, offset, &X);            /*   and read the operand into the X register */
4560 
4561         SET_CCA (X, 0);                                 /* set the condition code */
4562         break;
4563 
4564 
4565     case 014:                                           /* BR (none; BNDV), BCC (none; BNDV) */
4566         if ((CIR & BR_MASK) != BCC) {                   /* if the instruction is BR */
4567             cpu_ea (CIR, &class, &offset, NULL);        /*   then get the effective address of the branch */
4568 
4569             if (cpu_stop_flags & SS_LOOP                /* if the infinite loop stop is active */
4570               && offset == (P - 2 & LA_MASK))           /*   and the target is the current instruction */
4571                 status = STOP_INFLOOP;                  /*     then stop the simulator */
4572             else                                        /* otherwise */
4573                 status = SCPE_OK;                       /*   continue */
4574 
4575             cpu_read_memory (fetch_checked, offset, &NIR);  /* load the next instruction register */
4576             P = offset + 1 & R_MASK;                        /*   and increment the program counter */
4577             }
4578 
4579         else if (TO_CCF (STA) & CIR << BCC_CCF_SHIFT)   /* otherwise if the BCC test succeeds */
4580             status = cpu_branch_short (TRUE);           /*   then branch to the target address */
4581         break;                                          /* otherwise continue execution at P + 1 */
4582 
4583 
4584     case 015:                                           /* LDD (CCA; STOV, BNDV), LDB (CCB; STOV, BNDV) */
4585         if (CIR & M_FLAG) {                             /* if the instruction is LDD */
4586             cpu_ea (CIR, &class, &offset, NULL);        /*   then get the effective address of the double-word */
4587 
4588             cpu_read_memory (class, offset, &operand_1);                /* read the MSW */
4589             cpu_read_memory (class, offset + 1 & LA_MASK, &operand_2);  /*   and the LSW of the operand */
4590 
4591             cpu_push ();                                /* push the MSW  */
4592             cpu_push ();                                /*   and the LSW  */
4593             RB = operand_1;                             /*     of the operand */
4594             RA = operand_2;                             /*       onto the stack */
4595 
4596             SET_CCA (RB, RA);                           /* set the condition code */
4597             }
4598 
4599         else {                                                  /* otherwise the instruction is LDB */
4600             cpu_ea (CIR | M_FLAG, &class,  &offset, &selector); /*   so get the effective word address of the byte */
4601             cpu_read_memory (class, offset, &operand);          /*     and read the operand */
4602 
4603             cpu_push ();                                /* push the stack down */
4604 
4605             if (selector == upper)                      /* if the upper byte is selected */
4606                 RA = UPPER_BYTE (operand);              /*   then store it in the TOS */
4607             else                                        /* otherwise */
4608                 RA = LOWER_BYTE (operand);              /*   store the lower byte in the TOS */
4609 
4610             SET_CCB (RA);                               /* set the condition code */
4611             }
4612         break;
4613 
4614 
4615     case 016:                                           /* STD (none; STUN, BNDV), STB (none; STUN, BNDV) */
4616         if (CIR & M_FLAG) {                             /* if the instruction is STD */
4617             cpu_ea (CIR, &class, &offset, NULL);        /*   then get the effective address of the double-word */
4618 
4619             PREADJUST_SR (2);                           /* ensure that at least two TOS registers are loaded */
4620 
4621             cpu_write_memory (class, offset + 1 & LA_MASK, RA); /* write the LSW first to follow the microcode */
4622             cpu_write_memory (class, offset, RB);               /*   and then write the MSW */
4623 
4624             cpu_pop ();                                 /* pop the TOS */
4625             cpu_pop ();                                 /*   and the NOS */
4626             }
4627 
4628         else {                                                  /* otherwise the instruction is STB */
4629             cpu_ea (CIR | M_FLAG, &class, &offset, &selector);  /*   so get the effective word address of the byte */
4630 
4631             PREADJUST_SR (1);                           /* ensure that at least one TOS register is loaded */
4632 
4633             cpu_read_memory (class, offset, &operand);  /* read the word containing the target byte */
4634 
4635             if (selector == upper)                      /* if the upper byte is targeted */
4636                 operand = REPLACE_UPPER (operand, RA);  /*   then store the TOS into it */
4637             else                                        /* otherwise */
4638                 operand = REPLACE_LOWER (operand, RA);  /*   store the TOS into the lower byte */
4639 
4640             cpu_write_memory (class, offset, operand);  /* write the word back */
4641             cpu_pop ();                                 /*   and pop the TOS */
4642             }
4643         break;
4644 
4645 
4646     case 017:                                           /* LRA (none; STOV, BNDV) */
4647         cpu_ea (CIR, &class, &offset, NULL);            /* get the effective address */
4648 
4649         if (class == program_checked)                   /* if this a program reference */
4650             offset = offset - PB;                       /*   then subtract PB to get the relative address */
4651         else                                            /* otherwise it is a data or stack reference */
4652             offset = offset - DB;                       /*   so subtract DB to get the address */
4653 
4654         cpu_push ();                                    /* push the relative address */
4655         RA = offset & R_MASK;                           /*   onto the stack */
4656         break;
4657 
4658     }                                                   /* all cases are handled */
4659 
4660 if (status == STOP_UNIMPL                               /* if the instruction is unimplemented */
4661   && (cpu_stop_flags & SS_UNIMPL) == 0)                 /*   and the unimplemented instruction stop is inactive */
4662     MICRO_ABORT (trap_Unimplemented);                   /*     then trap to handle it */
4663 
4664 return status;
4665 }
4666