1 /* hp2100_cpu.c: HP 21xx/1000 CPU simulator
2 
3    Copyright (c) 1993-2012, Robert M. Supnik
4 
5    Permission is hereby granted, free of charge, to any person obtaining a
6    copy of this software and associated documentation files (the "Software"),
7    to deal in the Software without restriction, including without limitation
8    the rights to use, copy, modify, merge, publish, distribute, sublicense,
9    and/or sell copies of the Software, and to permit persons to whom the
10    Software is furnished to do so, subject to the following conditions:
11 
12    The above copyright notice and this permission notice shall be included in
13    all copies or substantial portions of the Software.
14 
15    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18    ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22    Except as contained in this notice, the name of Robert M Supnik shall not be
23    used in advertising or otherwise to promote the sale, use or other dealings
24    in this Software without prior written authorization from Robert M Supnik.
25 
26    CPU          2114C/2115A/2116C/2100A/1000-M/E/F central processing unit
27                 12731A memory expansion module
28    MP           12581A/12892B memory protect
29    DMA1,DMA2    12607B/12578A/12895A direct memory access controller
30    DCPC1,DCPC2  12897B dual channel port controller
31 
32    13-Jan-12    JDB     Minor speedup in "is_mapped"
33                         Added casts to cpu_mod, dmasio, dmapio, cpu_reset, dma_reset
34    07-Apr-11    JDB     Fixed I/O return status bug for DMA cycles
35                         Failed I/O cycles now stop on failing instruction
36    28-Mar-11    JDB     Tidied up signal handling
37    29-Oct-10    JDB     Revised DMA for new multi-card paradigm
38                         Consolidated DMA reset routines
39                         DMA channels renamed from 0,1 to 1,2 to match documentation
40    27-Oct-10    JDB     Changed I/O instructions, handlers, and DMA for revised signal model
41                         Changed I/O dispatch table to use DIB pointers
42    19-Oct-10    JDB     Removed DMA latency counter
43    13-Oct-10    JDB     Fixed DMA requests to enable stealing every cycle
44                         Fixed DMA priority for channel 1 over channel 2
45                         Corrected comments for "cpu_set_idle"
46    30-Sep-08    JDB     Breakpoints on interrupt trap cells now work
47    05-Sep-08    JDB     VIS and IOP are now mutually exclusive on 1000-F
48    11-Aug-08    JDB     Removed A/B shadow register variables
49    07-Aug-08    JDB     Moved hp_setdev, hp_showdev to hp2100_sys.c
50                         Moved non-existent memory checks to WritePW
51    05-Aug-08    JDB     Fixed mp_dms_jmp to accept lower bound, check write protection
52    30-Jul-08    JDB     Corrected DMS violation register set conditions
53                         Refefined ABORT to pass address, moved def to hp2100_cpu.h
54                         Combined dms and dms_io routines
55    29-Jul-08    JDB     JSB to 0/1 with W5 out and fence = 0 erroneously causes MP abort
56    11-Jul-08    JDB     Unified I/O slot dispatch by adding DIBs for CPU, MP, and DMA
57    26-Jun-08    JDB     Rewrote device I/O to model backplane signals
58                         EDT no longer passes DMA channel
59    30-Apr-08    JDB     Enabled SIGNAL instructions, SIG debug flag
60    28-Apr-08    JDB     Added SET CPU IDLE/NOIDLE, idle detection for DOS/RTE
61    24-Apr-08    JDB     Fixed single stepping through interrupts
62    20-Apr-08    JDB     Enabled EMA and VIS, added EMA, VIS, and SIGNAL debug flags
63    03-Dec-07    JDB     Memory ex/dep and bkpt type default to current map mode
64    26-Nov-07    JDB     Added SET CPU DEBUG and OS/VMA flags, enabled OS/VMA
65    15-Nov-07    JDB     Corrected MP W5 (JSB) jumper action, SET/SHOW reversal,
66                         mp_mevff clear on interrupt with I/O instruction in trap cell
67    04-Nov-07    JDB     Removed DBI support from 1000-M (was temporary for RTE-6/VM)
68    28-Apr-07    RMS     Removed clock initialization
69    02-Mar-07    JDB     EDT passes input flag and DMA channel in dat parameter
70    11-Jan-07    JDB     Added 12578A DMA byte packing
71    28-Dec-06    JDB     CLC 0 now sends CRS instead of CLC to devices
72    26-Dec-06    JDB     Fixed improper IRQ deferral for 21xx CPUs
73                         Fixed improper interrupt servicing in resolve
74    21-Dec-06    JDB     Added 21xx loader enable/disable support
75    16-Dec-06    JDB     Added 2114 and 2115 CPU options.
76                         Added support for 12607B (2114) and 12578A (2115/6) DMA
77    01-Dec-06    JDB     Added 1000-F CPU option (requires HAVE_INT64)
78                         SHOW CPU displays 1000-M/E instead of 21MX-M/E
79    16-Oct-06    JDB     Moved ReadF to hp2100_cpu1.c
80    12-Oct-06    JDB     Fixed INDMAX off-by-one error in resolve
81    26-Sep-06    JDB     Added iotrap parameter to UIG dispatchers for RTE microcode
82    12-Sep-06    JDB     iogrp returns NOTE_IOG to recalc interrupts
83                         resolve returns NOTE_INDINT to service held-off interrupt
84    16-Aug-06    JDB     Added support for future microcode options, future F-Series
85    09-Aug-06    JDB     Added double integer microcode, 1000-M/E synonyms
86                         Enhanced CPU option validity checking
87                         Added DCPC as a synonym for DMA for 21MX simulations
88    26-Dec-05    JDB     Improved reporting in dev_conflict
89    22-Sep-05    RMS     Fixed declarations (from Sterling Garwood)
90    21-Jan-05    JDB     Reorganized CPU option flags
91    15-Jan-05    RMS     Split out EAU and MAC instructions
92    26-Dec-04    RMS     DMA reset doesn't clear alternate CTL flop (from Dave Bryan)
93                         DMA reset shouldn't clear control words (from Dave Bryan)
94                         Alternate CTL flop not visible as register (from Dave Bryan)
95                         Fixed CBS, SBS, TBS to perform virtual reads
96                         Separated A/B from M[0/1] for DMA IO (from Dave Bryan)
97                         Fixed bug in JPY (from Dave Bryan)
98    25-Dec-04    JDB     Added SET CPU 21MX-M, 21MX-E (21MX defaults to MX-E)
99                         TIMER/EXECUTE/DIAG instructions disabled for 21MX-M
100                         T-register reflects changes in M-register when halted
101    25-Sep-04    JDB     Moved MP into its own device; added MP option jumpers
102                         Modified DMA to allow disabling
103                         Modified SET CPU 2100/2116 to truncate memory > 32K
104                         Added -F switch to SET CPU to force memory truncation
105                         Fixed S-register behavior on 2116
106                         Fixed LIx/MIx behavior for DMA on 2116 and 2100
107                         Fixed LIx/MIx behavior for empty I/O card slots
108                         Modified WRU to be REG_HRO
109                         Added BRK and DEL to save console settings
110                         Fixed use of "unsigned int16" in cpu_reset
111                         Modified memory size routine to return SCPE_INCOMP if
112                         memory size truncation declined
113    20-Jul-04    RMS     Fixed bug in breakpoint test (reported by Dave Bryan)
114                         Back up PC on instruction errors (from Dave Bryan)
115    14-May-04    RMS     Fixed bugs and added features from Dave Bryan
116                         - SBT increments B after store
117                         - DMS console map must check dms_enb
118                         - SFS x,C and SFC x,C work
119                         - MP violation clears automatically on interrupt
120                         - SFS/SFC 5 is not gated by protection enabled
121                         - DMS enable does not disable mem prot checks
122                         - DMS status inconsistent at simulator halt
123                         - Examine/deposit are checking wrong addresses
124                         - Physical addresses are 20b not 15b
125                         - Revised DMS to use memory rather than internal format
126                         - Added instruction printout to HALT message
127                         - Added M and T internal registers
128                         - Added N, S, and U breakpoints
129                         Revised IBL facility to conform to microcode
130                         Added DMA EDT I/O pseudo-opcode
131                         Separated DMA SRQ (service request) from FLG
132    12-Mar-03    RMS     Added logical name support
133    02-Feb-03    RMS     Fixed last cycle bug in DMA output (found by Mike Gemeny)
134    22-Nov-02    RMS     Added 21MX IOP support
135    24-Oct-02    RMS     Fixed bugs in IOP and extended instructions
136                         Fixed bugs in memory protection and DMS
137                         Added clock calibration
138    25-Sep-02    RMS     Fixed bug in DMS decode (found by Robert Alan Byer)
139    26-Jul-02    RMS     Restructured extended instructions, added IOP support
140    22-Mar-02    RMS     Changed to allocate memory array dynamically
141    11-Mar-02    RMS     Cleaned up setjmp/auto variable interaction
142    17-Feb-02    RMS     Added DMS support
143                         Fixed bugs in extended instructions
144    03-Feb-02    RMS     Added terminal multiplexor support
145                         Changed PCQ macro to use unmodified PC
146                         Fixed flop restore logic (found by Bill McDermith)
147                         Fixed SZx,SLx,RSS bug (found by Bill McDermith)
148                         Added floating point support
149    16-Jan-02    RMS     Added additional device support
150    07-Jan-02    RMS     Fixed DMA register tables (found by Bill McDermith)
151    07-Dec-01    RMS     Revised to use breakpoint package
152    03-Dec-01    RMS     Added extended SET/SHOW support
153    10-Aug-01    RMS     Removed register in declarations
154    26-Nov-00    RMS     Fixed bug in dual device number routine
155    21-Nov-00    RMS     Fixed bug in reset routine
156    15-Oct-00    RMS     Added dynamic device number support
157 
158    References:
159    - 2100A Computer Reference Manual (02100-90001, Dec-1971)
160    - Model 2100A Computer Installation and Maintenance Manual
161         (02100-90002, Aug-1972)
162    - HP 1000 M/E/F-Series Computers Technical Reference Handbook
163         (5955-0282, Mar-1980)
164    - HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
165         (92851-90001, Mar-1981)
166    - HP 1000 M/E/F-Series Computers I/O Interfacing Guide
167         (02109-90006, Sep-1980)
168    - 12607A Direct Memory Access Operating and Service Manual
169         (12607-90002, Jan-1970)
170    - 12578A/12578A-01 Direct Memory Access Operating and Service Manual
171         (12578-9001, Mar-1972)
172    - 12892B Memory Protect Installation Manual (12892-90007, Jun-1978)
173 
174 
175    The register state for the HP 2116 CPU is:
176 
177    AR<15:0>             A register - addressable as location 0
178    BR<15:0>             B register - addressable as location 1
179    PC<14:0>             P register - program counter
180    SR<15:0>             S register - switch register
181    MR<14:0>             M register - memory address
182    TR<15:0>             T register - memory data
183    E                    extend flag (carry out)
184    O                    overflow flag
185 
186    The 2100 adds memory protection logic:
187 
188    mp_fence<14:0>       memory fence register
189    mp_viol<15:0>        memory protection violation register (F register)
190 
191    The 21MX adds a pair of index registers and memory expansion logic:
192 
193    XR<15:0>             X register
194    YR<15:0>             Y register
195    dms_sr<15:0>         dynamic memory system status register
196    dms_vr<15:0>         dynamic memory system violation register
197 
198    The original HP 2116 has four instruction formats: memory reference,
199    shift, alter/skip, and I/O.  The HP 2100 added extended memory reference
200    and extended arithmetic.  The HP21MX added extended byte, bit, and word
201    instructions as well as extended memory.
202 
203    The memory reference format is:
204 
205     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
206    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
207    |in|     op    |cp|           offset            | memory reference
208    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
209 
210    <14:11>      mnemonic        action
211 
212    0010         AND             A = A & M[MA]
213    0011         JSB             M[MA] = P, P = MA + 1
214    0100         XOR             A = A ^ M[MA]
215    0101         JMP             P = MA
216    0110         IOR             A = A | M[MA]
217    0111         ISZ             M[MA] = M[MA] + 1, skip if M[MA] == 0
218    1000         ADA             A = A + M[MA]
219    1001         ADB             B = B + M[MA]
220    1010         CPA             skip if A != M[MA]
221    1011         CPB             skip if B != M[MA]
222    1100         LDA             A = M[MA]
223    1101         LDB             B = M[MA]
224    1110         STA             M[MA] = A
225    1111         STB             M[MA] = B
226 
227    <15,10>      mode            action
228 
229    0,0  page zero direct        MA = IR<9:0>
230    0,1  current page direct     MA = PC<14:0>'IR,9:0>
231    1,0  page zero indirect      MA = M[IR<9:0>]
232    1,1  current page indirect   MA = M[PC<14:10>'IR<9:0>]
233 
234    Memory reference instructions can access an address space of 32K words.
235    An instruction can directly reference the first 1024 words of memory
236    (called page zero), as well as 1024 words of the current page; it can
237    indirectly access all 32K.
238 
239    The shift format is:
240 
241     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
242    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
243    | 0  0  0  0|ab| 0|s1|   op1  |ce|s2|sl|   op2  | shift
244    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
245                  |     | \---+---/ |  |  | \---+---/
246                  |     |     |     |  |  |     |
247                  |     |     |     |  |  |     +---- shift 2 opcode
248                  |     |     |     |  |  +---------- skip if low bit == 0
249                  |     |     |     |  +------------- shift 2 enable
250                  |     |     |     +---------------- clear Extend
251                  |     |     +---------------------- shift 1 opcode
252                  |     +---------------------------- shift 1 enable
253                  +---------------------------------- A/B select
254 
255    The alter/skip format is:
256 
257     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
258    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
259    | 0  0  0  0|ab| 1|regop| e op|se|ss|sl|in|sz|rs| alter/skip
260    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
261                  |    \-+-/ \-+-/  |  |  |  |  |  |
262                  |      |     |    |  |  |  |  |  +- reverse skip sense
263                  |      |     |    |  |  |  |  +---- skip if register == 0
264                  |      |     |    |  |  |  +------- increment register
265                  |      |     |    |  |  +---------- skip if low bit == 0
266                  |      |     |    |  +------------- skip if sign bit == 0
267                  |      |     |    +---------------- skip if Extend == 0
268                  |      |     +--------------------- clr/com/set Extend
269                  |      +--------------------------- clr/com/set register
270                  +---------------------------------- A/B select
271 
272    The I/O transfer format is:
273 
274     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
275    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
276    | 1  0  0  0|ab| 1|hc| opcode |      device     | I/O transfer
277    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
278                  |     | \---+---/\-------+-------/
279                  |     |     |            |
280                  |     |     |            +--------- device select
281                  |     |     +---------------------- opcode
282                  |     +---------------------------- hold/clear flag
283                  +---------------------------------- A/B select
284 
285    The IO transfer instruction controls the specified device.
286    Depending on the opcode, the instruction may set or clear
287    the device flag, start or stop I/O, or read or write data.
288 
289    The 2100 added an extended memory reference instruction;
290    the 21MX added extended arithmetic, operate, byte, word,
291    and bit instructions.  Note that the HP 21xx is, despite
292    the right-to-left bit numbering, a big endian system.
293    Bits <15:8> are byte 0, and bits <7:0> are byte 1.
294 
295 
296    The extended memory reference format (HP 2100) is:
297 
298     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
299    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
300    | 1| 0  0  0|op| 0|            opcode           | extended mem ref
301    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
302    |in|              operand address               |
303    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
304 
305    The extended arithmetic format (HP 2100) is:
306 
307     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
308    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
309    | 1| 0  0  0  0  0|dr| 0  0| opcode |shift count| extended arithmetic
310    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
311 
312    The extended operate format (HP 21MX) is:
313 
314     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
315    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
316    | 1| 0  0  0|op| 0| 1  1  1  1  1|    opcode    | extended operate
317    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
318 
319    The extended byte and word format (HP 21MX) is:
320 
321     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
322    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
323    | 1| 0  0  0  1  0  1  1  1  1  1  1|   opcode  | extended byte/word
324    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
325    |in|              operand address               |
326    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
327    | 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0|
328    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
329 
330    The extended bit operate format (HP 21MX) is:
331 
332     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
333    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
334    | 1| 0  0  0  1  0  1  1  1  1  1  1  1| opcode | extended bit operate
335    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
336    |in|              operand address               |
337    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
338    |in|              operand address               |
339    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
340 
341    General notes:
342 
343    1. Reasons to stop.  The simulator can be stopped by:
344 
345         HALT instruction
346         breakpoint encountered
347         infinite indirection loop
348         unimplemented instruction and stop_inst flag set
349         unknown I/O device and stop_dev flag set
350         I/O error in I/O simulator
351 
352    2. Interrupts.  I/O devices are modelled by substituting software states for
353       I/O backplane signals.  Signals generated by I/O instructions and DMA
354       cycles are dispatched to the target device for action.  Backplane signals
355       are processed sequentially, except for the "clear flag" signal, which may
356       be generated in parallel with another signal.  For example, the "STC sc,C"
357       instruction generates the "set control" and the "clear flag" signals
358       concurrently.
359 
360       CPU interrupt signals are modelled as three parallel arrays:
361 
362         - device request priority as bit vector dev_prl [2] [31..0]
363         - device interrupt requests as bit vector dev_irq [2] [31..0]
364         - device service requests as bit vector dev_srq [2] [31..0]
365 
366       Each array forms a 64-bit vector, with bits 0-31 of the first element
367       corresponding to select codes 00-37 octal, and bits 0-31 of the second
368       element corresponding to select codes 40-77 octal.
369 
370       The HP 2100 interrupt structure is based on the PRH, PRL, IRQ, and IAK
371       signals.  PRH indicates that no higher-priority device is interrupting.
372       PRL indicates to lower-priority devices that a given device is not
373       interrupting.  IRQ indicates that a given device is requesting an
374       interrupt.  IAK indicates that the given device's interrupt request is
375       being acknowledged.
376 
377       PRH and PRL form a hardware priority chain that extends from interface to
378       interface on the backplane.  We model just PRL, as PRH is calculated from
379       the PRLs of higher-priority devices.
380 
381       Typical I/O devices have a flag, flag buffer, and control flip-flop.  If a
382       device's flag, flag buffer, and control bits are set, and the device is
383       the highest priority on the interrupt chain, it requests an interrupt by
384       asserting IRQ.  When the interrupt is acknowledged with IAK, the flag
385       buffer is cleared, preventing further interrupt requests from that device.
386       The combination of flag and control set blocks interrupts from lower
387       priority devices.
388 
389       Service requests are used to trigger the DMA service logic.  Setting the
390       device flag typically also sets SRQ, although SRQ may be calculated
391       independently.
392 
393    3. Non-existent memory.  On the HP 2100, reads to non-existent memory
394       return zero, and writes are ignored.  In the simulator, the
395       largest possible memory is instantiated and initialized to zero.
396       Thus, only writes need be checked against memory size.
397 
398       On the 21xx machines, doing SET CPU LOADERDISABLE decreases available
399       memory size by 64 words.
400 
401    4. Adding I/O devices.  These modules must be modified:
402 
403         hp2100_defs.h   add interrupt request definition
404         hp2100_sys.c    add sim_devices table entry
405 
406    5. Instruction interruptibility.  The simulator is fast enough, compared
407       to the run-time of the longest instructions, for interruptibility not
408       to matter.  But the HP diagnostics explicitly test interruptibility in
409       EIS and DMS instructions, and long indirect address chains.  Accordingly,
410       the simulator does "just enough" to pass these tests.  In particular, if
411       an interrupt is pending but deferred at the beginning of an interruptible
412       instruction, the interrupt is taken at the appropriate point; but there
413       is no testing for new interrupts during execution (that is, the event
414       timer is not called).
415 
416    6. Interrupt deferral.  At instruction fetch time, a pending interrupt
417       request will be deferred if the previous instruction was a JMP indirect,
418       JSB indirect, STC, CLC, STF, CLF, or was executing from an interrupt trap
419       cell.  In addition, the following instructions will cause deferral on the
420       1000 series: SFS, SFC, JRS, DJP, DJS, SJP, SJS, UJP, and UJS.
421 
422       On the HP 1000, the request is always deferred until after the current
423       instruction completes.  On the 21xx, the request is deferred unless the
424       current instruction is an MRG instruction other than JMP or JMP,I or
425       JSB,I.  Note that for the 21xx, SFS and SFC are not included in the
426       deferral criteria.
427 
428    7. Terminology.  The 1000 series of computers was originally called the 21MX
429       at introduction.  The 21MX (occasionally, 21MXM) corresponds to the 1000
430       M-Series, and the 21MXE (occasionally, 21XE) corresponds to the 1000
431       E-Series.  The model numbers were changed before the introduction of the
432       1000 F-Series, although some internal HP documentation refers to a 21MXF.
433 
434       The terms MEM (Memory Expansion Module), MEU (Memory Expansion Unit), DMI
435       (Dynamic Mapping Instructions), and DMS (Dynamic Mapping System) are used
436       somewhat interchangeably to refer to the logical-to-physical memory
437       address translation option provided on the 1000-Series.  DMS consists of
438       the MEM card (12731A) and the DMI firmware (13307A).  However, MEM and MEU
439       have been used interchangeably to refer to the mapping card, as have DMI
440       and DMS to refer to the firmware instructions.
441 */
442 
443 
444 #include "hp2100_defs.h"
445 #include "hp2100_cpu.h"
446 
447 
448 /* Memory protect constants */
449 
450 #define UNIT_V_MP_JSB   (UNIT_V_UF + 0)                 /* MP jumper W5 */
451 #define UNIT_V_MP_INT   (UNIT_V_UF + 1)                 /* MP jumper W6 */
452 #define UNIT_V_MP_SEL1  (UNIT_V_UF + 2)                 /* MP jumper W7 */
453 #define UNIT_MP_JSB     (1 << UNIT_V_MP_JSB)            /* 1 = W5 is out */
454 #define UNIT_MP_INT     (1 << UNIT_V_MP_INT)            /* 1 = W6 is out */
455 #define UNIT_MP_SEL1    (1 << UNIT_V_MP_SEL1)           /* 1 = W7 is out */
456 
457 /* DMA channels */
458 
459 typedef enum { ch1, ch2 } CHANNEL;                      /* channel number */
460 
461 #define DMA_CHAN_COUNT  2                               /* number of DMA channels */
462 
463 #define DMA_OE          020000000000                    /* byte packing odd/even flag */
464 #define DMA1_STC        0100000                         /* DMA - issue STC */
465 #define DMA1_PB         0040000                         /* DMA - pack bytes */
466 #define DMA1_CLC        0020000                         /* DMA - issue CLC */
467 #define DMA2_OI         0100000                         /* DMA - output/input */
468 
469 typedef struct {
470     FLIP_FLOP control;                                  /* control flip-flop */
471     FLIP_FLOP flag;                                     /* flag flip-flop */
472     FLIP_FLOP flagbuf;                                  /* flag buffer flip-flop */
473     FLIP_FLOP xferen;                                   /* transfer enable flip-flop */
474     FLIP_FLOP select;                                   /* register select flip-flop */
475 
476     uint32    cw1;                                      /* device select */
477     uint32    cw2;                                      /* direction, address */
478     uint32    cw3;                                      /* word count */
479     uint32    packer;                                   /* byte-packer holding reg */
480     } DMA_STATE;
481 
482 #define DMA_1_REQ       (1 << ch1)                      /* channel 1 request */
483 #define DMA_2_REQ       (1 << ch2)                      /* channel 2 request */
484 
485 
486 /* Command line switches */
487 
488 #define ALL_BKPTS       (SWMASK('E')|SWMASK('N')|SWMASK('S')|SWMASK('U'))
489 #define ALL_MAPMODES    (SWMASK('S')|SWMASK('U')|SWMASK('P')|SWMASK('Q'))
490 
491 
492 /* RTE base-page addresses. */
493 
494 static const uint32 xeqt = 0001717;                     /* XEQT address */
495 static const uint32 tbg  = 0001674;                     /* TBG address */
496 
497 /* DOS base-page addresses. */
498 
499 static const uint32 m64  = 0000040;                     /* constant -64 address */
500 static const uint32 p64  = 0000067;                     /* constant +64 address */
501 
502 /* CPU local data */
503 
504 static uint32 jsb_plb = 2;                              /* protected lower bound for JSB */
505 static uint32 saved_MR = 0;                             /* between executions */
506 static uint32 fwanxm = 0;                               /* first word addr of nx mem */
507 
508 /* CPU global data */
509 
510 uint16 *M = NULL;                                       /* memory */
511 uint16 ABREG[2];                                        /* A/B registers */
512 uint32 PC = 0;                                          /* P register */
513 uint32 SR = 0;                                          /* S register */
514 uint32 MR = 0;                                          /* M register */
515 uint32 TR = 0;                                          /* T register */
516 uint32 XR = 0;                                          /* X register */
517 uint32 YR = 0;                                          /* Y register */
518 uint32 E = 0;                                           /* E register */
519 uint32 O = 0;                                           /* O register */
520 FLIP_FLOP ion = CLEAR;                                  /* interrupt enable */
521 t_bool ion_defer = FALSE;                               /* interrupt defer */
522 uint32 intaddr = 0;                                     /* interrupt addr */
523 uint32 stop_inst = 1;                                   /* stop on ill inst */
524 uint32 stop_dev = 0;                                    /* stop on ill dev */
525 uint16 pcq[PCQ_SIZE] = { 0 };                           /* PC queue */
526 uint32 pcq_p = 0;                                       /* PC queue ptr */
527 REG *pcq_r = NULL;                                      /* PC queue reg ptr */
528 
529 uint32 dev_prl [2] = { ~(uint32) 0, ~(uint32) 0 };      /* device priority low bit vector */
530 uint32 dev_irq [2] = { 0, 0 };                          /* device interrupt request bit vector */
531 uint32 dev_srq [2] = { 0, 0 };                          /* device service request bit vector */
532 
533 /* Memory protect global data */
534 
535 FLIP_FLOP mp_control = CLEAR;                           /* MP control flip-flop */
536 FLIP_FLOP mp_flag = CLEAR;                              /* MP flag flip-flop */
537 FLIP_FLOP mp_flagbuf = CLEAR;                           /* MP flag buffer flip-flop */
538 FLIP_FLOP mp_mevff = CLEAR;                             /* memory expansion violation flip-flop */
539 FLIP_FLOP mp_evrff = SET;                               /* enable violation register flip-flop */
540 
541 uint32 mp_fence = 0;                                    /* MP fence register  */
542 uint32 mp_viol = 0;                                     /* MP violation register */
543 
544 uint32 iop_sp = 0;                                      /* iop stack reg */
545 uint32 ind_max = 16;                                    /* iadr nest limit */
546 uint32 err_PC = 0;                                      /* error PC */
547 jmp_buf save_env;                                       /* MP abort handler */
548 
549 /* DMA global data */
550 
551 DMA_STATE dma [DMA_CHAN_COUNT];                         /* per-channel state */
552 
553 /* Dynamic mapping system global data */
554 
555 uint32 dms_enb = 0;                                     /* dms enable */
556 uint32 dms_ump = 0;                                     /* dms user map */
557 uint32 dms_sr = 0;                                      /* dms status reg */
558 uint32 dms_vr = 0;                                      /* dms violation reg */
559 uint16 dms_map[MAP_NUM * MAP_LNT] = { 0 };              /* dms maps */
560 
561 /* External data */
562 
563 extern int32 sim_interval;
564 extern int32 sim_int_char;
565 extern int32 sim_brk_char;
566 extern int32 sim_del_char;
567 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
568 extern DEVICE *sim_devices[];
569 extern char halt_msg[];
570 extern t_bool sim_idle_enab;
571 extern DIB clk_dib;                                     /* CLK DIB for idle check */
572 
573 /* CPU local routines */
574 
575 static t_stat Ea (uint32 IR, uint32 *addr, uint32 irq);
576 static uint16 ReadTAB (uint32 va);
577 static uint32 dms (uint32 va, uint32 map, uint32 prot);
578 static uint32 shift (uint32 inval, uint32 flag, uint32 oper);
579 static t_stat dma_cycle (CHANNEL chan, uint32 map);
580 static uint32 calc_dma (void);
581 static t_bool dev_conflict (void);
582 static uint32 devdisp (uint32 select_code, IOCYCLE signal_set, uint16 data);
583 
584 /* CPU global routines */
585 
586 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
587 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
588 t_stat cpu_reset (DEVICE *dptr);
589 t_stat cpu_boot (int32 unitno, DEVICE *dptr);
590 t_stat mp_reset (DEVICE *dptr);
591 t_stat dma_reset (DEVICE *dptr);
592 t_stat cpu_set_size (UNIT *uptr, int32 new_size, char *cptr, void *desc);
593 t_stat cpu_set_model (UNIT *uptr, int32 new_model, char *cptr, void *desc);
594 t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc);
595 t_stat cpu_set_opt (UNIT *uptr, int32 option, char *cptr, void *desc);
596 t_stat cpu_clr_opt (UNIT *uptr, int32 option, char *cptr, void *desc);
597 t_stat cpu_set_ldr (UNIT *uptr, int32 enable, char *cptr, void *desc);
598 t_stat cpu_set_idle  (UNIT *uptr, int32 option, char *cptr, void *desc);
599 t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc);
600 void hp_post_cmd (t_bool from_scp);
601 
602 IOHANDLER cpuio;
603 IOHANDLER ovflio;
604 IOHANDLER pwrfio;
605 IOHANDLER protio;
606 IOHANDLER dmapio;
607 IOHANDLER dmasio;
608 IOHANDLER nullio;
609 
610 /* External routines */
611 
612 extern t_stat cpu_eau   (uint32 IR, uint32 intrq);
613 extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap);
614 extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap);
615 
616 extern void (*sim_vm_post) (t_bool from_scp);
617 
618 
619 /* Table of CPU features by model.
620 
621    Fields:
622     - typ:    standard features plus typically configured options.
623     - opt:    complete list of optional features.
624     - maxmem: maximum configurable memory in 16-bit words.
625 
626    Features in the "typical" list are enabled when the CPU model is selected.
627    If a feature appears in the "typical" list but NOT in the "optional" list,
628    then it is standard equipment and cannot be disabled.  If a feature appears
629    in the "optional" list, then it may be enabled or disabled as desired by the
630    user.
631 */
632 
633 struct FEATURE_TABLE {                                  /* CPU model feature table: */
634     uint32      typ;                                    /*  - typical features */
635     uint32      opt;                                    /*  - optional features */
636     uint32      maxmem;                                 /*  - maximum memory */
637     };
638 
639 static struct FEATURE_TABLE cpu_features[] = {          /* features in UNIT_xxxx order*/
640   { UNIT_DMA | UNIT_MP,                                 /* UNIT_2116 */
641     UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_EAU,
642     32768 },
643   { UNIT_DMA,                                           /* UNIT_2115 */
644     UNIT_PFAIL | UNIT_DMA | UNIT_EAU,
645     8192 },
646   { UNIT_DMA,                                           /* UNIT_2114 */
647     UNIT_PFAIL | UNIT_DMA,
648     16384 },
649   { 0, 0, 0 },
650   { UNIT_PFAIL | UNIT_MP | UNIT_DMA | UNIT_EAU,         /* UNIT_2100 */
651     UNIT_DMA   | UNIT_FP | UNIT_IOP | UNIT_FFP,
652     32768 },
653   { 0, 0, 0 },
654   { 0, 0, 0 },
655   { 0, 0, 0 },
656   { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_M */
657     UNIT_PFAIL | UNIT_DMA | UNIT_MP | UNIT_DMS |
658     UNIT_IOP   | UNIT_FFP | UNIT_DS,
659     1048576 },
660   { UNIT_MP | UNIT_DMA | UNIT_EAU | UNIT_FP | UNIT_DMS, /* UNIT_1000_E */
661     UNIT_PFAIL | UNIT_DMA | UNIT_MP  | UNIT_DMS |
662     UNIT_IOP   | UNIT_FFP | UNIT_DBI | UNIT_DS  | UNIT_EMA_VMA,
663     1048576 },
664   { UNIT_MP  | UNIT_DMA | UNIT_EAU | UNIT_FP |          /* UNIT_1000_F */
665     UNIT_FFP | UNIT_DBI | UNIT_DMS,
666     UNIT_PFAIL | UNIT_DMA | UNIT_MP     | UNIT_VIS |
667     UNIT_IOP   | UNIT_DS  | UNIT_SIGNAL | UNIT_EMA_VMA,
668     1048576 }
669   };
670 
671 
672 /* Null device information block */
673 
674 DIB null_dib = { &nullio, 0 };
675 
676 /* CPU data structures
677 
678    cpu_dib      CPU device information block
679    cpu_dev      CPU device descriptor
680    cpu_unit     CPU unit descriptor
681    cpu_reg      CPU register list
682    cpu_mod      CPU modifiers list
683    cpu_deb      CPU debug flags
684 */
685 
686 DIB cpu_dib = { &cpuio, CPU };
687 
688 UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, 0) };
689 
690 REG cpu_reg[] = {
691     { ORDATA (P, PC, 15) },
692     { ORDATA (A, AR, 16), REG_FIT },
693     { ORDATA (B, BR, 16), REG_FIT },
694     { ORDATA (M, MR, 15) },
695     { ORDATA (T, TR, 16), REG_RO },
696     { ORDATA (X, XR, 16) },
697     { ORDATA (Y, YR, 16) },
698     { ORDATA (S, SR, 16) },
699     { FLDATA (E, E, 0) },
700     { FLDATA (O, O, 0) },
701     { FLDATA (ION, ion, 0) },
702     { FLDATA (ION_DEFER, ion_defer, 0) },
703     { ORDATA (CIR, intaddr, 6) },
704     { FLDATA (DMSENB, dms_enb, 0) },
705     { FLDATA (DMSCUR, dms_ump, VA_N_PAG) },
706     { ORDATA (DMSSR, dms_sr, 16) },
707     { ORDATA (DMSVR, dms_vr, 16) },
708     { BRDATA (DMSMAP, dms_map, 8, 16, MAP_NUM * MAP_LNT) },
709     { ORDATA (IOPSP, iop_sp, 16) },
710     { FLDATA (STOP_INST, stop_inst, 0) },
711     { FLDATA (STOP_DEV, stop_dev, 1) },
712     { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
713     { BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC },
714     { ORDATA (PCQP, pcq_p, 6), REG_HRO },
715     { ORDATA (JSBPLB, jsb_plb, 32), REG_HRO },
716     { ORDATA (SAVEDMR, saved_MR, 32), REG_HRO },
717     { ORDATA (FWANXM, fwanxm, 32), REG_HRO },
718     { ORDATA (WRU, sim_int_char, 8), REG_HRO },
719     { ORDATA (BRK, sim_brk_char, 8), REG_HRO },
720     { ORDATA (DEL, sim_del_char, 8), REG_HRO },
721     { BRDATA (PRL, dev_prl, 8, 32, 2), REG_HRO },
722     { BRDATA (IRQ, dev_irq, 8, 32, 2), REG_HRO },
723     { BRDATA (SRQ, dev_srq, 8, 32, 2), REG_HRO },
724     { NULL }
725     };
726 
727 /* CPU modifier table.
728 
729    The 21MX monikers are deprecated in favor of the 1000 designations.  See the
730    "HP 1000 Series Naming History" on the back inside cover of the Technical
731    Reference Handbook. */
732 
733 MTAB cpu_mod[] = {
734     { UNIT_MODEL_MASK, UNIT_2116,   "",   "2116",   &cpu_set_model, &cpu_show_model, (void *) "2116"   },
735     { UNIT_MODEL_MASK, UNIT_2115,   "",   "2115",   &cpu_set_model, &cpu_show_model, (void *) "2115"   },
736     { UNIT_MODEL_MASK, UNIT_2114,   "",   "2114",   &cpu_set_model, &cpu_show_model, (void *) "2114"   },
737     { UNIT_MODEL_MASK, UNIT_2100,   "",   "2100",   &cpu_set_model, &cpu_show_model, (void *) "2100"   },
738     { UNIT_MODEL_MASK, UNIT_1000_E, "",   "1000-E", &cpu_set_model, &cpu_show_model, (void *) "1000-E" },
739     { UNIT_MODEL_MASK, UNIT_1000_E, NULL, "21MX-E", &cpu_set_model, &cpu_show_model, (void *) "1000-E" },
740     { UNIT_MODEL_MASK, UNIT_1000_M, "",   "1000-M", &cpu_set_model, &cpu_show_model, (void *) "1000-M" },
741     { UNIT_MODEL_MASK, UNIT_1000_M, NULL, "21MX-M", &cpu_set_model, &cpu_show_model, (void *) "1000-M" },
742 
743 #if defined (HAVE_INT64)
744     { UNIT_MODEL_MASK, UNIT_1000_F, "",   "1000-F", &cpu_set_model, &cpu_show_model, (void *) "1000-F" },
745 #endif
746 
747     { MTAB_XTD | MTAB_VDV, 1, "IDLE", "IDLE",   &cpu_set_idle, &cpu_show_idle, NULL },
748     { MTAB_XTD | MTAB_VDV, 0, NULL,   "NOIDLE", &cpu_set_idle, NULL,           NULL },
749 
750     { MTAB_XTD | MTAB_VDV, 1, NULL, "LOADERENABLE",  &cpu_set_ldr, NULL, NULL },
751     { MTAB_XTD | MTAB_VDV, 0, NULL, "LOADERDISABLE", &cpu_set_ldr, NULL, NULL },
752 
753     { UNIT_EAU,     UNIT_EAU,   "EAU",        "EAU",      &cpu_set_opt, NULL, NULL },
754     { UNIT_EAU,     0,          "no EAU",     NULL,       NULL,         NULL, NULL },
755     { MTAB_XTD | MTAB_VDV, UNIT_EAU,    NULL, "NOEAU",    &cpu_clr_opt, NULL, NULL },
756 
757     { UNIT_FP,      UNIT_FP,    "FP",         "FP",       &cpu_set_opt, NULL, NULL },
758     { UNIT_FP,      0,          "no FP",      NULL,       NULL,         NULL, NULL },
759     { MTAB_XTD | MTAB_VDV, UNIT_FP,     NULL, "NOFP",     &cpu_clr_opt, NULL, NULL },
760 
761     { UNIT_IOP,     UNIT_IOP,   "IOP",        "IOP",      &cpu_set_opt, NULL, NULL },
762     { UNIT_IOP,     0,          "no IOP",     NULL,       NULL,         NULL, NULL },
763     { MTAB_XTD | MTAB_VDV, UNIT_IOP,    NULL, "NOIOP",    &cpu_clr_opt, NULL, NULL },
764 
765     { UNIT_DMS,     UNIT_DMS,   "DMS",        "DMS",      &cpu_set_opt, NULL, NULL },
766     { UNIT_DMS,     0,          "no DMS",     NULL,       NULL,         NULL, NULL },
767     { MTAB_XTD | MTAB_VDV, UNIT_DMS,    NULL, "NODMS",    &cpu_clr_opt, NULL, NULL },
768 
769     { UNIT_FFP,     UNIT_FFP,   "FFP",        "FFP",      &cpu_set_opt, NULL, NULL },
770     { UNIT_FFP,     0,          "no FFP",     NULL,       NULL,         NULL, NULL },
771     { MTAB_XTD | MTAB_VDV, UNIT_FFP,    NULL, "NOFFP",    &cpu_clr_opt, NULL, NULL },
772 
773     { UNIT_DBI,     UNIT_DBI,   "DBI",        "DBI",      &cpu_set_opt, NULL, NULL },
774     { UNIT_DBI,     0,          "no DBI",     NULL,       NULL,         NULL, NULL },
775     { MTAB_XTD | MTAB_VDV, UNIT_DBI,    NULL, "NODBI",    &cpu_clr_opt, NULL, NULL },
776 
777     { UNIT_EMA_VMA, UNIT_EMA,   "EMA",        "EMA",      &cpu_set_opt, NULL, NULL },
778     { MTAB_XTD | MTAB_VDV, UNIT_EMA,    NULL, "NOEMA",    &cpu_clr_opt, NULL, NULL },
779 
780     { UNIT_EMA_VMA, UNIT_VMAOS, "VMA",        "VMA",      &cpu_set_opt, NULL, NULL },
781     { MTAB_XTD | MTAB_VDV, UNIT_VMAOS,  NULL, "NOVMA",    &cpu_clr_opt, NULL, NULL },
782 
783     { UNIT_EMA_VMA, 0,          "no EMA/VMA", NULL,       &cpu_set_opt, NULL, NULL },
784 
785 #if defined (HAVE_INT64)
786     { UNIT_VIS,     UNIT_VIS,   "VIS",        "VIS",      &cpu_set_opt, NULL, NULL },
787     { UNIT_VIS,     0,          "no VIS",     NULL,       NULL,         NULL, NULL },
788     { MTAB_XTD | MTAB_VDV, UNIT_VIS,    NULL, "NOVIS",    &cpu_clr_opt, NULL, NULL },
789 
790     { UNIT_SIGNAL,  UNIT_SIGNAL,"SIGNAL",     "SIGNAL",   &cpu_set_opt, NULL, NULL },
791     { UNIT_SIGNAL,  0,          "no SIGNAL",  NULL,       NULL,         NULL, NULL },
792     { MTAB_XTD | MTAB_VDV, UNIT_SIGNAL, NULL, "NOSIGNAL", &cpu_clr_opt, NULL, NULL },
793 #endif
794 
795 /* Future microcode support.
796     { UNIT_DS,      UNIT_DS,    "DS",         "DS",       &cpu_set_opt, NULL, NULL },
797     { UNIT_DS,      0,          "no DS",      NULL,       NULL,         NULL, NULL },
798     { MTAB_XTD | MTAB_VDV, UNIT_DS,     NULL, "NODS",     &cpu_clr_opt, NULL, NULL },
799 */
800 
801     { MTAB_XTD | MTAB_VDV,    4096, NULL, "4K",    &cpu_set_size, NULL, NULL },
802     { MTAB_XTD | MTAB_VDV,    8192, NULL, "8K",    &cpu_set_size, NULL, NULL },
803     { MTAB_XTD | MTAB_VDV,   12288, NULL, "12K",   &cpu_set_size, NULL, NULL },
804     { MTAB_XTD | MTAB_VDV,   16384, NULL, "16K",   &cpu_set_size, NULL, NULL },
805     { MTAB_XTD | MTAB_VDV,   24576, NULL, "24K",   &cpu_set_size, NULL, NULL },
806     { MTAB_XTD | MTAB_VDV,   32768, NULL, "32K",   &cpu_set_size, NULL, NULL },
807     { MTAB_XTD | MTAB_VDV,   65536, NULL, "64K",   &cpu_set_size, NULL, NULL },
808     { MTAB_XTD | MTAB_VDV,  131072, NULL, "128K",  &cpu_set_size, NULL, NULL },
809     { MTAB_XTD | MTAB_VDV,  262144, NULL, "256K",  &cpu_set_size, NULL, NULL },
810     { MTAB_XTD | MTAB_VDV,  524288, NULL, "512K",  &cpu_set_size, NULL, NULL },
811     { MTAB_XTD | MTAB_VDV, 1048576, NULL, "1024K", &cpu_set_size, NULL, NULL },
812     { 0 }
813     };
814 
815 DEBTAB cpu_deb[] = {
816     { "OS",    DEB_OS },
817     { "OSTBG", DEB_OSTBG },
818     { "VMA",   DEB_VMA },
819     { "EMA",   DEB_EMA },
820     { "VIS",   DEB_VIS },
821     { "SIG",   DEB_SIG },
822     { NULL,    0 }
823     };
824 
825 DEVICE cpu_dev = {
826     "CPU",                                  /* device name */
827     &cpu_unit,                              /* unit array */
828     cpu_reg,                                /* register array */
829     cpu_mod,                                /* modifier array */
830     1,                                      /* number of units */
831     8,                                      /* address radix */
832     PA_N_SIZE,                              /* address width */
833     1,                                      /* address increment */
834     8,                                      /* data radix */
835     16,                                     /* data width */
836     &cpu_ex,                                /* examine routine */
837     &cpu_dep,                               /* deposit routine */
838     &cpu_reset,                             /* reset routine */
839     &cpu_boot,                              /* boot routine */
840     NULL,                                   /* attach routine */
841     NULL,                                   /* detach routine */
842     &cpu_dib,                               /* device information block */
843     DEV_DEBUG,                              /* device flags */
844     0,                                      /* debug control flags */
845     cpu_deb,                                /* debug flag name table */
846     NULL,                                   /* memory size change routine */
847     NULL };                                 /* logical device name */
848 
849 /* Overflow device information block */
850 
851 DIB ovfl_dib = { &ovflio, OVF };
852 
853 /* Powerfail device information block */
854 
855 DIB pwrf_dib = { &pwrfio, PWR };
856 
857 /* Memory protect data structures
858 
859    mp_dib       MP device information block
860    mp_dev       MP device descriptor
861    mp_unit      MP unit descriptor
862    mp_reg       MP register list
863    mp_mod       MP modifiers list
864 */
865 
866 DIB mp_dib = { &protio, PRO };
867 
868 UNIT mp_unit = { UDATA (NULL, UNIT_MP_SEL1, 0) };       /* default is JSB in, INT in, SEL1 out */
869 
870 REG mp_reg[] = {
871     { FLDATA (CTL, mp_control, 0) },
872     { FLDATA (FLG, mp_flag, 0) },
873     { FLDATA (FBF, mp_flagbuf, 0) },
874     { ORDATA (FR, mp_fence, 15) },
875     { ORDATA (VR, mp_viol, 16) },
876     { FLDATA (EVR, mp_evrff, 0) },
877     { FLDATA (MEV, mp_mevff, 0) },
878     { NULL }
879     };
880 
881 MTAB mp_mod[] = {
882     { UNIT_MP_JSB, UNIT_MP_JSB, "JSB (W5) out", "JSBOUT", NULL },
883     { UNIT_MP_JSB, 0, "JSB (W5) in", "JSBIN", NULL },
884     { UNIT_MP_INT, UNIT_MP_INT, "INT (W6) out", "INTOUT", NULL },
885     { UNIT_MP_INT, 0, "INT (W6) in", "INTIN", NULL },
886     { UNIT_MP_SEL1, UNIT_MP_SEL1, "SEL1 (W7) out", "SEL1OUT", NULL },
887     { UNIT_MP_SEL1, 0, "SEL1 (W7) in", "SEL1IN", NULL },
888     { 0 }
889     };
890 
891 DEVICE mp_dev = {
892     "MP",                                   /* device name */
893     &mp_unit,                               /* unit array */
894     mp_reg,                                 /* register array */
895     mp_mod,                                 /* modifier array */
896     1,                                      /* number of units */
897     8,                                      /* address radix */
898     1,                                      /* address width */
899     1,                                      /* address increment */
900     8,                                      /* data radix */
901     16,                                     /* data width */
902     NULL,                                   /* examine routine */
903     NULL,                                   /* deposit routine */
904     &mp_reset,                              /* reset routine */
905     NULL,                                   /* boot routine */
906     NULL,                                   /* attach routine */
907     NULL,                                   /* detach routine */
908     &mp_dib,                                /* device information block */
909     DEV_DISABLE | DEV_DIS,                  /* device flags */
910     0,                                      /* debug control flags */
911     NULL,                                   /* debug flag name table */
912     NULL,                                   /* memory size change routine */
913     NULL };                                 /* logical device name */
914 
915 /* DMA controller data structures
916 
917    dmax_dib     DMAx device information block
918    dmax_dev     DMAx device descriptor
919    dmax_reg     DMAx register list
920 */
921 
922 DIB dmap1_dib = { &dmapio, DMA1,   ch1 };
923 DIB dmas1_dib = { &dmasio, DMALT1, ch1 };
924 
925 UNIT dma1_unit = { UDATA (NULL, 0, 0) };
926 
927 REG dma1_reg[] = {
928     { FLDATA (XFR,    dma [ch1].xferen,   0) },
929     { FLDATA (CTL,    dma [ch1].control,  0) },
930     { FLDATA (FLG,    dma [ch1].flag,     0) },
931     { FLDATA (FBF,    dma [ch1].flagbuf,  0) },
932     { FLDATA (CTL2,   dma [ch1].select,   0) },
933     { ORDATA (CW1,    dma [ch1].cw1,     16) },
934     { ORDATA (CW2,    dma [ch1].cw2,     16) },
935     { ORDATA (CW3,    dma [ch1].cw3,     16) },
936     { FLDATA (BYTE,   dma [ch1].packer,  31) },
937     { ORDATA (PACKER, dma [ch1].packer,   8) },
938     { NULL }
939     };
940 
941 DEVICE dma1_dev = {
942     "DMA1",                                 /* device name */
943     &dma1_unit,                             /* unit array */
944     dma1_reg,                               /* register array */
945     NULL,                                   /* modifier array */
946     1,                                      /* number of units */
947     8,                                      /* address radix */
948     1,                                      /* address width */
949     1,                                      /* address increment */
950     8,                                      /* data radix */
951     16,                                     /* data width */
952     NULL,                                   /* examine routine */
953     NULL,                                   /* deposit routine */
954     &dma_reset,                             /* reset routine */
955     NULL,                                   /* boot routine */
956     NULL,                                   /* attach routine */
957     NULL,                                   /* detach routine */
958     &dmap1_dib,                             /* device information block */
959     DEV_DISABLE,                            /* device flags */
960     0,                                      /* debug control flags */
961     NULL,                                   /* debug flag name table */
962     NULL,                                   /* memory size change routine */
963     NULL };                                 /* logical device name */
964 
965 DIB dmap2_dib = { &dmapio, DMA2,   ch2 };
966 DIB dmas2_dib = { &dmasio, DMALT2, ch2 };
967 
968 UNIT dma2_unit = { UDATA (NULL, 0, 0) };
969 
970 REG dma2_reg[] = {
971     { FLDATA (XFR,    dma [ch2].xferen,   0) },
972     { FLDATA (CTL,    dma [ch2].control,  0) },
973     { FLDATA (FLG,    dma [ch2].flag,     0) },
974     { FLDATA (FBF,    dma [ch2].flagbuf,  0) },
975     { FLDATA (CTL2,   dma [ch2].select,   0) },
976     { ORDATA (CW1,    dma [ch2].cw1,     16) },
977     { ORDATA (CW2,    dma [ch2].cw2,     16) },
978     { ORDATA (CW3,    dma [ch2].cw3,     16) },
979     { FLDATA (BYTE,   dma [ch2].packer,  31) },
980     { ORDATA (PACKER, dma [ch2].packer,   8) },
981     { NULL }
982     };
983 
984 DEVICE dma2_dev = {
985     "DMA2",                                 /* device name */
986     &dma2_unit,                             /* unit array */
987     dma2_reg,                               /* register array */
988     NULL,                                   /* modifier array */
989     1,                                      /* number of units */
990     8,                                      /* address radix */
991     1,                                      /* address width */
992     1,                                      /* address increment */
993     8,                                      /* data radix */
994     16,                                     /* data width */
995     NULL,                                   /* examine routine */
996     NULL,                                   /* deposit routine */
997     &dma_reset,                             /* reset routine */
998     NULL,                                   /* boot routine */
999     NULL,                                   /* attach routine */
1000     NULL,                                   /* detach routine */
1001     &dmap2_dib,                             /* device information block */
1002     DEV_DISABLE,                            /* device flags */
1003     0,                                      /* debug control flags */
1004     NULL,                                   /* debug flag name table */
1005     NULL,                                   /* memory size change routine */
1006     NULL };                                 /* logical device name */
1007 
1008 static DEVICE *dma_dptrs [] = { &dma1_dev, &dma2_dev };
1009 
1010 
1011 /* Interrupt deferral table (1000 version) */
1012 /* Deferral for I/O subops:    soHLT, soFLG, soSFC, soSFS, soMIX, soLIX, soOTX, soCTL */
1013 static t_bool defer_tab [] = { FALSE,  TRUE,  TRUE,  TRUE, FALSE, FALSE, FALSE,  TRUE };
1014 
1015 /* Device I/O dispatch table */
1016 
1017 DIB *dtab [64] = { &cpu_dib, &ovfl_dib };               /* init with immutable devices */
1018 
1019 
1020 
1021 /* Execute CPU instructions.
1022 
1023    This routine is the instruction decode routine for the HP 2100.  It is called
1024    from the simulator control program to execute instructions in simulated
1025    memory, starting at the simulated PC.  It runs until 'reason' is set to a
1026    status other than SCPE_OK.
1027 */
1028 
sim_instr(void)1029 t_stat sim_instr (void)
1030 {
1031 uint32 intrq, dmarq;                                    /* set after setjmp */
1032 uint32 iotrap = 0;                                      /* set after setjmp */
1033 t_stat reason = SCPE_OK;                                /* set after setjmp */
1034 int32 i;                                                /* temp */
1035 DEVICE *dptr;                                           /* temp */
1036 DIB *dibptr;                                            /* temp */
1037 int abortval;
1038 
1039 /* Restore register state */
1040 
1041 if (dev_conflict ())                                    /* check device assignment consistency */
1042     return SCPE_STOP;                                   /* conflict; stop execution */
1043 
1044 err_PC = PC = PC & VAMASK;                              /* load local PC */
1045 
1046 /* Restore I/O state */
1047 
1048 dev_prl [0] = dev_prl [1] = ~(uint32) 0;                /* set all priority lows */
1049 dev_irq [0] = dev_irq [1] = 0;                          /* clear all interrupt requests */
1050 dev_srq [0] = dev_srq [1] = 0;                          /* clear all service requests */
1051 
1052 for (i = OPTDEV; i <= MAXDEV; i++)                      /* default optional devices */
1053     dtab [i] = &null_dib;
1054 
1055 dtab [PWR] = &pwrf_dib;                                 /* for now, powerfail is always present */
1056 
1057 for (i = 0; (dptr = sim_devices [i]); i++) {              /* loop thru dev */
1058     dibptr = (DIB *) dptr->ctxt;                        /* get DIB */
1059 
1060     if (dibptr && !(dptr->flags & DEV_DIS)) {           /* handler exists and device is enabled? */
1061         dtab [dibptr->select_code] = dibptr;            /* set DIB pointer into dispatch table */
1062         dibptr->io_handler (dibptr, ioSIR, 0);          /* set interrupt request state */
1063         }
1064     }
1065 
1066 if (dtab [DMA1] != &null_dib)                           /* first DMA channel enabled? */
1067     dtab [DMALT1] = &dmas1_dib;                         /* set up secondary device handler */
1068 
1069 if (dtab [DMA2] != &null_dib)                           /* second DMA channel enabled? */
1070     dtab [DMALT2] = &dmas2_dib;                         /* set up secondary device handler */
1071 
1072 /* Configure interrupt deferral table */
1073 
1074 if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX)                /* 21xx series? */
1075     defer_tab [soSFC] = defer_tab [soSFS] = FALSE;      /* SFC/S doesn't defer */
1076 else                                                    /* 1000 series */
1077     defer_tab [soSFC] = defer_tab [soSFS] = TRUE;       /* SFC/S does defer */
1078 
1079 
1080 /* Set MP abort handling.
1081 
1082    If an abort occurs in memory protection, the relocation routine executes a
1083    longjmp to this area OUTSIDE the main simulation loop.  Memory protection
1084    errors are the only sources of aborts in the HP 2100.  All referenced
1085    variables must be globals, and all sim_instr scoped automatics must be set
1086    after the setjmp.
1087 
1088    To initiate an MP abort, use the MP_ABORT macro and pass the violation
1089    address.  MP_ABORT should only be called if "mp_control" is SET, as aborts do
1090    not occur if MP is turned off.
1091 
1092    An MP interrupt (SC 05) is qualified by "ion" but not by "ion_defer".  If the
1093    interrupt system is off when an MP violation is detected, the violating
1094    instruction will be aborted, even though no interrupt occurs.  In this case,
1095    neither the flag nor flag buffer are set, and EVR is not cleared.
1096 
1097    Implementation notes:
1098 
1099     1. The protected lower bound address for the JSB instruction depends on the
1100        W5 jumper setting.  If W5 is in, then the lower bound is 2, allowing JSBs
1101        to the A and B registers.  If W5 is out, then the lower bound is 0, just
1102        as with JMP.
1103 
1104     2. The violation address is passed to enable the MEM violation register to
1105        be updated.  The "longjmp" routine will not pass a value of 0; it is
1106        converted internally to 1.  This is OK, because only the page number
1107        of the address value is used, and locations 0 and 1 are both on page 0.
1108 
1109     3. This routine is used both for MP and MEM violations.  The MEV flip-flop
1110        will be clear for the former and set for the latter.  The MEV violation
1111        register will be updated by "dms_upd_vr" only if the call is NOT for an
1112        MEM violation; if it is, then the VR has already been set and should not
1113        be disturbed.
1114 */
1115 
1116 jsb_plb = (mp_unit.flags & UNIT_MP_JSB) ? 0 : 2;        /* set protected lower bound for JSB */
1117 
1118 abortval = setjmp (save_env);                           /* set abort hdlr */
1119 
1120 if (abortval) {                                         /* memory protect abort? */
1121     dms_upd_vr (abortval);                              /* update violation register (if not MEV) */
1122 
1123     if (ion)                                            /* interrupt system on? */
1124         protio (dtab [PRO], ioENF, 0);                  /* set flag */
1125     }
1126 
1127 dmarq = calc_dma ();                                    /* initial recalc of DMA masks */
1128 intrq = calc_int ();                                    /* initial recalc of interrupts */
1129 
1130 
1131 /* Main instruction fetch/decode loop */
1132 
1133 while (reason == SCPE_OK) {                             /* loop until halted */
1134     uint32 IR, MA, absel, v1, t, skip;
1135 
1136     err_PC = PC;                                        /* save PC for error recovery */
1137 
1138     if (sim_interval <= 0) {                            /* event timeout? */
1139         reason = sim_process_event ();                  /* process event service */
1140 
1141         if (reason != SCPE_OK)                          /* service failed? */
1142             break;                                      /* stop execution */
1143 
1144         dmarq = calc_dma ();                            /* recalc DMA reqs */
1145         intrq = calc_int ();                            /* recalc interrupts */
1146         }
1147 
1148 /* DMA cycles are requested by an I/O card asserting its SRQ signal.  If a DMA
1149    channel is programmed to respond to that card's select code, a DMA cycle will
1150    be initiated.  A DMA cycle consists of a memory cycle and an I/O cycle.
1151    These cycles are synchronized with the control processor on the 21xx CPUs.
1152    On the 1000s, memory cycles are asynchronous, while I/O cycles are
1153    synchronous.  Memory cycle time is about 40% of the I/O cycle time.
1154 
1155    With properly designed interface cards, DMA is capable of taking consecutive
1156    I/O cycles.  On all machines except the 1000 M-Series, a DMA cycle freezes
1157    the CPU for the duration of the cycle.  On the M-Series, a DMA cycle freezes
1158    the CPU if it attempts an I/O cycle (including IAK) or a directly-interfering
1159    memory cycle.  An interleaved memory cycle is allowed.  Otherwise, the
1160    control processor is allowed to run.  Therefore, during consecutive DMA
1161    cycles, the M-Series CPU will run until an IOG instruction is attempted,
1162    whereas the other CPUs will freeze completely.
1163 
1164    All DMA cards except the 12607B provide two independent channels.  If both
1165    channels are active simultaneously, channel 1 has priority for I/O cycles
1166    over channel 2.
1167 
1168    Most I/O cards assert SRQ no more than 50% of the time.  A few buffered
1169    cards, such as the 12821A and 13175A Disc Interfaces, are capable of
1170    asserting SRQ continuously while filling or emptying the buffer.  If SRQ for
1171    channel 1 is asserted continuously when both channels are active, then no
1172    channel 2 cycles will occur until channel 1 completes.
1173 
1174    Implementation notes:
1175 
1176     1. CPU freeze is simulated by skipping instruction execution during the
1177        current loop cycle.
1178 
1179     2. If both channels have SRQ asserted, DMA priority is simulated by skipping
1180        the channel 2 cycle if channel 1's SRQ is still asserted at the end of
1181        its cycle.  If it is not, then channel 2 steals the next cycle from the
1182        CPU.
1183 
1184     3. The 1000 M-Series allows some CPU processing concurrently with
1185        continuous DMA cycles, whereas all other CPUs freeze.  The processor
1186        freezes if an I/O cycle is attempted, including an interrupt
1187        acknowledgement.  Because some microcode extensions (e.g., Access IOP,
1188        RTE-6/VM OS) perform I/O cycles, advance detection of I/O cycles is
1189        difficult.  Therefore, we freeze all processing for the M-Series as well.
1190 */
1191 
1192     if (dmarq) {
1193         if (dmarq & DMA_1_REQ) {                                /* DMA channel 1 request? */
1194             reason = dma_cycle (ch1, PAMAP);                    /* do one DMA cycle using port A map */
1195 
1196             if (reason == SCPE_OK)                              /* cycle OK? */
1197                 dmarq = calc_dma ();                            /* recalc DMA requests */
1198             else
1199                 break;                                          /* cycle failed, so stop */
1200             }
1201 
1202         if ((dmarq & (DMA_1_REQ | DMA_2_REQ)) == DMA_2_REQ) {   /* DMA channel 1 idle and channel 2 request? */
1203             reason = dma_cycle (ch2, PBMAP);                    /* do one DMA cycle using port B map */
1204 
1205             if (reason == SCPE_OK)                              /* cycle OK? */
1206                 dmarq = calc_dma ();                            /* recalc DMA requests */
1207             else
1208                 break;                                          /* cycle failed, so stop */
1209             }
1210 
1211         if (dmarq)                                              /* DMA request still pending? */
1212             continue;                                           /* service it before instruction execution */
1213 
1214         intrq = calc_int ();                                    /* recalc interrupts */
1215         }
1216 
1217     if (intrq && ion_defer)                                     /* interrupt pending but deferred? */
1218         ion_defer = calc_defer ();                              /* confirm deferral */
1219 
1220 /* Check for pending interrupt request.
1221 
1222    Interrupt recognition is controlled by three state variables: "ion",
1223    "ion_defer", and "intrq".  "ion" corresponds to the INTSYS flip-flop in the
1224    1000 CPU, "ion_defer" corresponds to the INTEN flip-flop, and "intrq"
1225    corresponds to the NRMINT flip-flop.  STF 00 and CLF 00 set and clear INTSYS,
1226    turning the interrupt system on and off.  Micro-orders ION and IOFF set and
1227    clear INTEN, deferring or allowing certain interrupts.  An IRQ signal from a
1228    device, qualified by the corresponding PRL signal, will set NRMINT to request
1229    a normal interrupt; an IOFF or IAK will clear it.
1230 
1231    Under simulation, "ion" is controlled by STF/CLF 00.  "ion_defer" is set or
1232    cleared as appropriate by the individual instruction simulators.  "intrq" is
1233    set to the successfully interrupting device's select code, or to zero if
1234    there is no qualifying interrupt request.
1235 
1236    Presuming PRL is set to allow priority to an interrupting device:
1237 
1238     1. Power fail (SC 04) may interrupt if "ion_defer" is clear; this is not
1239        conditional on "ion" being set.
1240 
1241     2. Memory protect (SC 05) may interrupt if "ion" is set; this is not
1242        conditional on "ion_defer" being clear.
1243 
1244     3. Parity error (SC 05) may interrupt always; this is not conditional on
1245        "ion" being set or "ion_defer" being clear.
1246 
1247     4. All other devices (SC 06 and up) may interrupt if "ion" is set and
1248        "ion_defer" is clear.
1249 
1250    Qualification with "ion" is performed by "calc_int", except for case 2, which
1251    is qualified by the MP abort handler above (because qualification occurs on
1252    the MP card, rather than in the CPU).  Therefore, we need only qualify by
1253    "ion_defer" here.
1254 */
1255 
1256     if (intrq && ((intrq == PRO) || !ion_defer)) {      /* interrupt request? */
1257         if (sim_brk_summ &&                             /* any breakpoints? */
1258             sim_brk_test (intrq, SWMASK ('E') |         /* unconditional or right type for DMS? */
1259               (dms_enb ? SWMASK ('S') : SWMASK ('N')))) {
1260             reason = STOP_IBKPT;                        /* stop simulation */
1261             break;
1262             }
1263 
1264         intaddr = intrq;                                /* save int addr in CIR */
1265         intrq = 0;                                      /* clear request */
1266         ion_defer = TRUE;                               /* defer interrupts */
1267         iotrap = 1;                                     /* mark as I/O trap cell instr */
1268 
1269         if (dms_enb)                                    /* dms enabled? */
1270             dms_sr = dms_sr | MST_ENBI;                 /* set in status */
1271         else                                            /* not enabled */
1272             dms_sr = dms_sr & ~MST_ENBI;                /* clear in status */
1273 
1274         if (dms_ump) {                                  /* user map enabled at interrupt? */
1275             dms_sr = dms_sr | MST_UMPI;                 /* set in status */
1276             dms_ump = SMAP;                             /* switch to system map */
1277             }
1278         else                                            /* system map enabled at interrupt */
1279             dms_sr = dms_sr & ~MST_UMPI;                /* clear in status */
1280 
1281         IR = ReadW (intaddr);                           /* get trap cell instruction */
1282 
1283         devdisp (intaddr, ioIAK, (uint16) IR);          /* acknowledge interrupt */
1284 
1285         if (intaddr != PRO)                             /* not MP interrupt? */
1286             protio (dtab [intaddr], ioIAK, IR);         /* send IAK for device to MP too */
1287         }
1288 
1289     else {                                              /* normal instruction */
1290         iotrap = 0;                                     /* not a trap cell instruction */
1291 
1292         if (sim_brk_summ &&                             /* any breakpoints? */
1293             sim_brk_test (PC, SWMASK ('E') |            /* unconditional or */
1294                               (dms_enb ?                /*   correct type for DMS state? */
1295                                 (dms_ump ?
1296                                   SWMASK ('U') : SWMASK ('S')) :
1297                                 SWMASK ('N')))) {
1298             reason = STOP_IBKPT;                        /* stop simulation */
1299             break;
1300             }
1301 
1302         if (mp_evrff)                                   /* violation register enabled */
1303             mp_viol = PC;                               /* update with current PC */
1304 
1305         IR = ReadW (PC);                                /* fetch instr */
1306         PC = (PC + 1) & VAMASK;
1307         ion_defer = FALSE;
1308         }
1309 
1310     sim_interval = sim_interval - 1;                    /* count instruction */
1311 
1312 /* Instruction decode.  The 21MX does a 256-way decode on IR<15:8>
1313 
1314    15 14 13 12 11 10 09 08      instruction
1315 
1316     x <-!= 0->  x  x  x  x      memory reference
1317     0  0  0  0  x  0  x  x      shift
1318     0  0  0  0  x  0  x  x      alter-skip
1319     1  0  0  0  x  1  x  x      IO
1320     1  0  0  0  0  0  x  0      extended arithmetic
1321     1  0  0  0  0  0  0  1      divide (decoded as 100400)
1322     1  0  0  0  1  0  0  0      double load (decoded as 104000)
1323     1  0  0  0  1  0  0  1      double store (decoded as 104400)
1324     1  0  0  0  1  0  1  0      extended instr group 0 (A/B must be set)
1325     1  0  0  0  x  0  1  1      extended instr group 1 (A/B ignored) */
1326 
1327     absel = (IR & I_AB) ? 1 : 0;                        /* get A/B select */
1328 
1329     switch ((IR >> 8) & 0377) {                         /* decode IR<15:8> */
1330 
1331 /* Memory reference instructions */
1332 
1333     case 0020:case 0021:case 0022:case 0023:
1334     case 0024:case 0025:case 0026:case 0027:
1335     case 0220:case 0221:case 0222:case 0223:
1336     case 0224:case 0225:case 0226:case 0227:
1337         reason = Ea (IR, &MA, intrq);                   /* AND */
1338 
1339         if (reason != SCPE_OK)                          /* address failed to resolve? */
1340             break;                                      /* stop execution */
1341 
1342         AR = AR & ReadW (MA);
1343         break;
1344 
1345 /* JSB is a little tricky.  It is possible to generate both an MP and a DM
1346    violation simultaneously, as the MP and MEM cards validate in parallel.
1347    Consider a JSB to a location under the MP fence and on a write-protected
1348    page.  This situation must be reported as a DM violation, because it has
1349    priority (SFS 5 and SFC 5 check only the MEVFF, which sets independently of
1350    the MP fence violation).  Under simulation, this means that DM violations
1351    must be checked, and the MEVFF must be set, before an MP abort is taken.
1352    This is done by the "mp_dms_jmp" routine.
1353 */
1354 
1355     case 0230:case 0231:case 0232:case 0233:
1356     case 0234:case 0235:case 0236:case 0237:
1357         ion_defer = TRUE;                               /* defer if JSB,I */
1358 
1359     case 0030:case 0031:case 0032:case 0033:
1360     case 0034:case 0035:case 0036:case 0037:
1361         reason = Ea (IR, &MA, intrq);                   /* JSB */
1362 
1363         if (reason != SCPE_OK)                          /* address failed to resolve? */
1364             break;                                      /* stop execution */
1365 
1366         mp_dms_jmp (MA, jsb_plb);                       /* validate jump address */
1367 
1368         WriteW (MA, PC);                                /* store PC */
1369         PCQ_ENTRY;
1370         PC = (MA + 1) & VAMASK;                         /* jump */
1371         break;
1372 
1373     case 0040:case 0041:case 0042:case 0043:
1374     case 0044:case 0045:case 0046:case 0047:
1375     case 0240:case 0241:case 0242:case 0243:
1376     case 0244:case 0245:case 0246:case 0247:
1377         reason = Ea (IR, &MA, intrq);                   /* XOR */
1378 
1379         if (reason != SCPE_OK)                          /* address failed to resolve? */
1380             break;                                      /* stop execution */
1381 
1382         AR = AR ^ ReadW (MA);
1383         break;
1384 
1385 /* CPU idle processing.
1386 
1387    The 21xx/1000 CPUs have no "wait for interrupt" instruction.  Idling in HP
1388    operating systems consists of sitting in "idle loops" that end with JMP
1389    instructions.  We test for certain known patterns when a JMP instruction is
1390    executed to decide if the simulator should idle.
1391 
1392    Idling must not occur if an interrupt is pending.  As mentioned in the
1393    "General Notes" above, HP CPUs will defer interrupts if certain instructions
1394    are executed.  OS interrupt handlers exit via such deferring instructions.
1395    If there is a pending interrupt when the OS is otherwise idle, the idle loop
1396    will execute one instruction before reentering the interrupt handler.  If we
1397    call sim_idle() in this case, we will lose interrupts.
1398 
1399    Consider the situation in RTE.  Under simulation, the TTY and CLK events are
1400    co-scheduled, with the CLK expiring one instruction after the TTY.  When the
1401    TTY interrupts, $CIC in RTE is entered.  One instruction later, the CLK
1402    expires and posts its interrupt, but it is not immediately handled, because
1403    the JSB $CIC,I / JMP $CIC0,I / SFS 0,C instruction entry sequence continually
1404    defers interrupts until the interrupt system is turned off.  When $CIC
1405    returns via $IRT, one instruction of the idle loop is executed, even though
1406    the CLK interrupt is still pending, because the UJP instruction used to
1407    return also defers interrupts.
1408 
1409    If sim_idle() is called at this point, the simulator will sleep when it
1410    should be handling the pending CLK interrupt.  When it awakes, TTY expiration
1411    will be moved forward to the next instruction.  The still-pending CLK
1412    interrupt will then be recognized, and $CIC will be entered.  But the TTY and
1413    then the CLK will then expire and attempt to interrupt again, although they
1414    are deferred by the $CIC entry sequence.  This causes the second CLK
1415    interrupt to be missed, as processing of the first one is just now being
1416    started.
1417 
1418    Similarly, at the end of the CLK handling, the TTY interrupt is still
1419    pending.  When $IRT returns to the idle loop, sim_idle() would be called
1420    again, so the TTY and then CLK interrupt a third time.  Because the second
1421    TTY interrupt is still pending, $CIC is entered, but the third TTY interrupt
1422    is lost.
1423 
1424    We solve this problem by testing for a pending interrupt before calling
1425    sim_idle().  The system isn't really quiescent if it is just about to handle
1426    an interrupt.
1427 */
1428 
1429     case 0250:case 0251:case 0252:case 0253:
1430     case 0254:case 0255:case 0256:case 0257:
1431         ion_defer = TRUE;                               /* defer if JMP,I */
1432 
1433     case 0050:case 0051:case 0052:case 0053:
1434     case 0054:case 0055:case 0056:case 0057:
1435         reason = Ea (IR, &MA, intrq);                   /* JMP */
1436 
1437         if (reason != SCPE_OK)                          /* address failed to resolve? */
1438             break;                                      /* stop execution */
1439 
1440         mp_dms_jmp (MA, 0);                             /* validate jump addr */
1441         PCQ_ENTRY;
1442         PC = MA;                                        /* jump */
1443 
1444 /* Idle conditions by operating system:
1445 
1446    RTE-6/VM:
1447     - ISZ <n> / JMP *-1
1448     - mp_fence = 0
1449     - XEQT (address 1717B) = 0
1450     - DMS on with system map enabled
1451     - RTE verification: TBG (address 1674B) = CLK select code
1452 
1453    RTE though RTE-IVB:
1454     - JMP *
1455     - mp_fence = 0
1456     - XEQT (address 1717B) = 0
1457     - DMS on with user map enabled (RTE-III through RTE-IVB only)
1458     - RTE verification: TBG (address 1674B) = CLK select code
1459 
1460    DOS through DOS-III:
1461     - STF 0 / CCA / CCB / JMP *-3
1462     - DOS verification: A = B = -1, address 40B = -64, address 67B = +64
1463     - Note that in DOS, the TBG is set to 100 milliseconds
1464 */
1465 
1466         if ((sim_idle_enab) && (intrq == 0))                /* idle enabled w/o pending irq? */
1467             if (((PC == err_PC) ||                          /* RTE through RTE-IVB */
1468                  ((PC == (err_PC - 1)) &&                   /* RTE-6/VM */
1469                   ((ReadW (PC) & I_MRG) == I_ISZ))) &&      /* RTE jump target */
1470                 (mp_fence == CLEAR) && (M [xeqt] == 0) &&   /* RTE idle indications */
1471                 (M [tbg] == clk_dib.select_code) ||         /* RTE verification */
1472 
1473                 (PC == (err_PC - 3)) &&                     /* DOS through DOS-III */
1474                 (ReadW (PC) == I_STF) &&                    /* DOS jump target */
1475                 (AR == 0177777) && (BR == 0177777) &&       /* DOS idle indication */
1476                 (M [m64] == 0177700) &&                     /* DOS verification */
1477                 (M [p64] == 0000100))                       /* DOS verification */
1478 
1479                 sim_idle (TMR_POLL, FALSE);                 /* idle the simulator */
1480         break;
1481 
1482     case 0060:case 0061:case 0062:case 0063:
1483     case 0064:case 0065:case 0066:case 0067:
1484     case 0260:case 0261:case 0262:case 0263:
1485     case 0264:case 0265:case 0266:case 0267:
1486         reason = Ea (IR, &MA, intrq);                   /* IOR */
1487 
1488         if (reason != SCPE_OK)                          /* address failed to resolve? */
1489             break;                                      /* stop execution */
1490 
1491         AR = AR | ReadW (MA);
1492         break;
1493 
1494     case 0070:case 0071:case 0072:case 0073:
1495     case 0074:case 0075:case 0076:case 0077:
1496     case 0270:case 0271:case 0272:case 0273:
1497     case 0274:case 0275:case 0276:case 0277:
1498         reason = Ea (IR, &MA, intrq);                   /* ISZ */
1499 
1500         if (reason != SCPE_OK)                          /* address failed to resolve? */
1501             break;                                      /* stop execution */
1502 
1503         t = (ReadW (MA) + 1) & DMASK;
1504         WriteW (MA, t);
1505 
1506         if (t == 0)
1507             PC = (PC + 1) & VAMASK;
1508         break;
1509 
1510     case 0100:case 0101:case 0102:case 0103:
1511     case 0104:case 0105:case 0106:case 0107:
1512     case 0300:case 0301:case 0302:case 0303:
1513     case 0304:case 0305:case 0306:case 0307:
1514         reason = Ea (IR, &MA, intrq);                   /* ADA */
1515 
1516         if (reason != SCPE_OK)                          /* address failed to resolve? */
1517             break;                                      /* stop execution */
1518 
1519         v1 = ReadW (MA);
1520         t = AR + v1;
1521 
1522         if (t > DMASK)
1523             E = 1;
1524 
1525         if (((~AR ^ v1) & (AR ^ t)) & SIGN)
1526             O = 1;
1527 
1528         AR = t & DMASK;
1529         break;
1530 
1531     case 0110:case 0111:case 0112:case 0113:
1532     case 0114:case 0115:case 0116:case 0117:
1533     case 0310:case 0311:case 0312:case 0313:
1534     case 0314:case 0315:case 0316:case 0317:
1535         reason = Ea (IR, &MA, intrq);                   /* ADB */
1536 
1537         if (reason != SCPE_OK)                          /* address failed to resolve? */
1538             break;                                      /* stop execution */
1539 
1540         v1 = ReadW (MA);
1541         t = BR + v1;
1542 
1543         if (t > DMASK)
1544             E = 1;
1545 
1546         if (((~BR ^ v1) & (BR ^ t)) & SIGN)
1547             O = 1;
1548 
1549         BR = t & DMASK;
1550         break;
1551 
1552     case 0120:case 0121:case 0122:case 0123:
1553     case 0124:case 0125:case 0126:case 0127:
1554     case 0320:case 0321:case 0322:case 0323:
1555     case 0324:case 0325:case 0326:case 0327:
1556         reason = Ea (IR, &MA, intrq);                   /* CPA */
1557 
1558         if (reason != SCPE_OK)                          /* address failed to resolve? */
1559             break;                                      /* stop execution */
1560 
1561         if (AR != ReadW (MA))
1562             PC = (PC + 1) & VAMASK;
1563         break;
1564 
1565     case 0130:case 0131:case 0132:case 0133:
1566     case 0134:case 0135:case 0136:case 0137:
1567     case 0330:case 0331:case 0332:case 0333:
1568     case 0334:case 0335:case 0336:case 0337:
1569         reason = Ea (IR, &MA, intrq);                   /* CPB */
1570 
1571         if (reason != SCPE_OK)                          /* address failed to resolve? */
1572             break;                                      /* stop execution */
1573 
1574         if (BR != ReadW (MA))
1575             PC = (PC + 1) & VAMASK;
1576         break;
1577 
1578     case 0140:case 0141:case 0142:case 0143:
1579     case 0144:case 0145:case 0146:case 0147:
1580     case 0340:case 0341:case 0342:case 0343:
1581     case 0344:case 0345:case 0346:case 0347:
1582         reason = Ea (IR, &MA, intrq);                   /* LDA */
1583 
1584         if (reason != SCPE_OK)                          /* address failed to resolve? */
1585             break;                                      /* stop execution */
1586 
1587         AR = ReadW (MA);
1588         break;
1589 
1590     case 0150:case 0151:case 0152:case 0153:
1591     case 0154:case 0155:case 0156:case 0157:
1592     case 0350:case 0351:case 0352:case 0353:
1593     case 0354:case 0355:case 0356:case 0357:
1594         reason = Ea (IR, &MA, intrq);                   /* LDB */
1595 
1596         if (reason != SCPE_OK)                          /* address failed to resolve? */
1597             break;                                      /* stop execution */
1598 
1599         BR = ReadW (MA);
1600         break;
1601 
1602     case 0160:case 0161:case 0162:case 0163:
1603     case 0164:case 0165:case 0166:case 0167:
1604     case 0360:case 0361:case 0362:case 0363:
1605     case 0364:case 0365:case 0366:case 0367:
1606         reason = Ea (IR, &MA, intrq);                   /* STA */
1607 
1608         if (reason != SCPE_OK)                          /* address failed to resolve? */
1609             break;                                      /* stop execution */
1610 
1611         WriteW (MA, AR);
1612         break;
1613 
1614     case 0170:case 0171:case 0172:case 0173:
1615     case 0174:case 0175:case 0176:case 0177:
1616     case 0370:case 0371:case 0372:case 0373:
1617     case 0374:case 0375:case 0376:case 0377:
1618         reason = Ea (IR, &MA, intrq);                   /* STB */
1619 
1620         if (reason != SCPE_OK)                          /* address failed to resolve? */
1621             break;                                      /* stop execution */
1622 
1623         WriteW (MA, BR);
1624         break;
1625 
1626 /* Alter/skip instructions */
1627 
1628     case 0004:case 0005:case 0006:case 0007:
1629     case 0014:case 0015:case 0016:case 0017:
1630         skip = 0;                                       /* no skip */
1631 
1632         if (IR & 000400)                                /* CLx */
1633             t = 0;
1634         else
1635             t = ABREG[absel];
1636 
1637         if (IR & 001000)                                /* CMx */
1638             t = t ^ DMASK;
1639 
1640         if (IR & 000001) {                              /* RSS? */
1641             if ((IR & 000040) && (E != 0))              /* SEZ,RSS */
1642                 skip = 1;
1643 
1644             if (IR & 000100)                            /* CLE */
1645                 E = 0;
1646 
1647             if (IR & 000200)                            /* CME */
1648                 E = E ^ 1;
1649 
1650             if (((IR & 000030) == 000030) &&            /* SSx,SLx,RSS */
1651                 ((t & 0100001) == 0100001))
1652                 skip = 1;
1653 
1654             if (((IR & 000030) == 000020) &&            /* SSx,RSS */
1655                 ((t & SIGN) != 0))
1656                 skip = 1;
1657 
1658             if (((IR & 000030) == 000010) &&            /* SLx,RSS */
1659                 ((t & 1) != 0))
1660                 skip = 1;
1661 
1662             if (IR & 000004) {                          /* INx */
1663                 t = (t + 1) & DMASK;
1664 
1665                 if (t == 0)
1666                     E = 1;
1667 
1668                 if (t == SIGN)
1669                     O = 1;
1670                 }
1671 
1672             if ((IR & 000002) && (t != 0))              /* SZx,RSS */
1673                 skip = 1;
1674 
1675             if ((IR & 000072) == 0)                     /* RSS */
1676                 skip = 1;
1677             }                                           /* end if RSS */
1678 
1679         else {
1680             if ((IR & 000040) && (E == 0))              /* SEZ */
1681                 skip = 1;
1682 
1683             if (IR & 000100)                            /* CLE */
1684                 E = 0;
1685 
1686             if (IR & 000200)                            /* CME */
1687                 E = E ^ 1;
1688 
1689             if ((IR & 000020) &&                        /* SSx */
1690                 ((t & SIGN) == 0))
1691                 skip = 1;
1692 
1693             if ((IR & 000010) &&                        /* SLx */
1694                  ((t & 1) == 0))
1695                  skip = 1;
1696 
1697             if (IR & 000004) {                          /* INx */
1698                 t = (t + 1) & DMASK;
1699 
1700                 if (t == 0)
1701                     E = 1;
1702 
1703                 if (t == SIGN)
1704                     O = 1;
1705                 }
1706             if ((IR & 000002) && (t == 0))              /* SZx */
1707                 skip = 1;
1708             }                                           /* end if ~RSS */
1709 
1710         ABREG[absel] = t;                               /* store result */
1711         PC = (PC + skip) & VAMASK;                      /* add in skip */
1712         break;                                          /* end if alter/skip */
1713 
1714 /* Shift instructions */
1715 
1716     case 0000:case 0001:case 0002:case 0003:
1717     case 0010:case 0011:case 0012:case 0013:
1718         t = shift (ABREG[absel], IR & 01000, IR >> 6);  /* do first shift */
1719 
1720         if (IR & 000040)                                /* CLE */
1721             E = 0;
1722 
1723         if ((IR & 000010) && ((t & 1) == 0))            /* SLx */
1724             PC = (PC + 1) & VAMASK;
1725 
1726         ABREG[absel] = shift (t, IR & 00020, IR);       /* do second shift */
1727         break;                                          /* end if shift */
1728 
1729 /* I/O instructions */
1730 
1731     case 0204:case 0205:case 0206:case 0207:
1732     case 0214:case 0215:case 0216:case 0217:
1733         reason = iogrp (IR, iotrap);                    /* execute instr */
1734         break;                                          /* end if I/O */
1735 
1736 /* Extended arithmetic */
1737 
1738     case 0200:                                          /* EAU group 0 */
1739     case 0201:                                          /* divide */
1740     case 0202:                                          /* EAU group 2 */
1741     case 0210:                                          /* DLD */
1742     case 0211:                                          /* DST */
1743         reason = cpu_eau (IR, intrq);                   /* extended arith */
1744         break;
1745 
1746 /* Extended instructions */
1747 
1748     case 0212:                                          /* UIG 0 extension */
1749         reason = cpu_uig_0 (IR, intrq, iotrap);         /* extended opcode */
1750         break;
1751 
1752     case 0203:                                          /* UIG 1 extension */
1753     case 0213:
1754         reason = cpu_uig_1 (IR, intrq, iotrap);         /* extended opcode */
1755         break;
1756         }                                               /* end case IR */
1757 
1758     if (reason == NOTE_IOG) {                           /* I/O instr exec? */
1759         dmarq = calc_dma ();                            /* recalc DMA masks */
1760         intrq = calc_int ();                            /* recalc interrupts */
1761         reason = SCPE_OK;                               /* continue */
1762         }
1763 
1764     else if (reason == NOTE_INDINT) {                   /* intr pend during indir? */
1765         PC = err_PC;                                    /* back out of inst */
1766         reason = SCPE_OK;                               /* continue */
1767         }
1768     }                                                   /* end while */
1769 
1770 /* Simulation halted */
1771 
1772 if (iotrap && (reason == STOP_HALT))                    /* HLT in trap cell? */
1773     MR = intaddr;                                       /* M = interrupt address */
1774 else                                                    /* normal HLT */
1775     MR = (PC - 1) & VAMASK;                             /* M = P - 1 */
1776 
1777 TR = ReadTAB (MR);                                      /* T = last word fetched */
1778 saved_MR = MR;                                          /* save for T cmd update */
1779 
1780 if (reason == STOP_HALT)                                /* programmed halt? */
1781     cpu_set_ldr (NULL, FALSE, NULL, NULL);              /* disable loader (after T is read) */
1782 else                                                    /* simulation stop */
1783     PC = err_PC;                                        /* back out instruction */
1784 
1785 dms_upd_sr ();                                          /* update dms_sr */
1786 dms_upd_vr (MR);                                        /* update dms_vr */
1787 pcq_r->qptr = pcq_p;                                    /* update pc q ptr */
1788 
1789 if (dms_enb)                                            /* DMS enabled? */
1790     if (dms_ump)                                        /* set default */
1791         sim_brk_dflt = SWMASK ('U');                    /*   breakpoint type */
1792     else                                                /*     to current */
1793         sim_brk_dflt = SWMASK ('S');                    /*       map mode */
1794 
1795 else                                                    /* DMS disabled */
1796     sim_brk_dflt = SWMASK ('N');                        /* set breakpoint type to non-DMS */
1797 
1798 return reason;                                          /* return status code */
1799 }
1800 
1801 
1802 /* Resolve indirect addresses.
1803 
1804    An indirect chain is followed until a direct address is obtained.  Under
1805    simulation, a maximum number of indirect levels are allowed (typically 16),
1806    after which the instruction will be aborted.
1807 
1808    If the memory protect feature is present, an indirect counter is used that
1809    allows a pending interrupt to be serviced if more than three levels of
1810    indirection are encountered.  If MP jumper W6 ("INT") is out and MP is
1811    enabled, then pending interrupts are serviced immediately.  When employing
1812    the indirect counter, the hardware clears a pending interrupt deferral after
1813    the third indirection and aborts the instruction after the fourth.
1814 */
1815 
resolve(uint32 MA,uint32 * addr,uint32 irq)1816 t_stat resolve (uint32 MA, uint32 *addr, uint32 irq)
1817 {
1818 uint32 i;
1819 t_bool pending = (irq && !(mp_unit.flags & DEV_DIS));
1820 t_bool int_enable = ((mp_unit.flags & UNIT_MP_INT) && mp_control);
1821 
1822 for (i = 0; (i < ind_max) && (MA & I_IA); i++) {        /* resolve multilevel */
1823     if (pending) {                                      /* interrupt pending and MP enabled? */
1824         if ((i == 2) || int_enable)                     /* 3rd level indirect or INT out? */
1825             ion_defer = FALSE;                          /* reenable interrrupts */
1826         if ((i > 2) || int_enable)                      /* 4th or higher or INT out? */
1827             return NOTE_INDINT;                         /* break out now */
1828         }
1829 
1830     MA = ReadW (MA & VAMASK);                           /* follow address chain */
1831     }
1832 
1833 if (MA & I_IA)                                          /* indirect loop? */
1834     return STOP_IND;                                    /* stop simulation */
1835 
1836 *addr = MA;
1837 return SCPE_OK;
1838 }
1839 
1840 
1841 /* Get effective address from IR */
1842 
Ea(uint32 IR,uint32 * addr,uint32 irq)1843 static t_stat Ea (uint32 IR, uint32 *addr, uint32 irq)
1844 {
1845 uint32 MA;
1846 
1847 MA = IR & (I_IA | I_DISP);                              /* ind + disp */
1848 
1849 if (IR & I_CP)                                          /* current page? */
1850     MA = ((PC - 1) & I_PAGENO) | MA;                    /* merge in page from PC */
1851 
1852 return resolve (MA, addr, irq);                         /* resolve indirects */
1853 }
1854 
1855 
1856 /* Shift micro operation */
1857 
shift(uint32 t,uint32 flag,uint32 op)1858 static uint32 shift (uint32 t, uint32 flag, uint32 op)
1859 {
1860 uint32 oldE;
1861 
1862 op = op & 07;                                           /* get shift op */
1863 if (flag) {                                             /* enabled? */
1864     switch (op) {                                       /* case on operation */
1865 
1866     case 00:                                            /* signed left shift */
1867         return ((t & SIGN) | ((t << 1) & 077777));
1868 
1869     case 01:                                            /* signed right shift */
1870         return ((t & SIGN) | (t >> 1));
1871 
1872     case 02:                                            /* rotate left */
1873         return (((t << 1) | (t >> 15)) & DMASK);
1874 
1875     case 03:                                            /* rotate right */
1876         return (((t >> 1) | (t << 15)) & DMASK);
1877 
1878     case 04:                                            /* left shift, 0 sign */
1879         return ((t << 1) & 077777);
1880 
1881     case 05:                                            /* ext right rotate */
1882         oldE = E;
1883         E = t & 1;
1884         return ((t >> 1) | (oldE << 15));
1885 
1886     case 06:                                            /* ext left rotate */
1887         oldE = E;
1888         E = (t >> 15) & 1;
1889         return (((t << 1) | oldE) & DMASK);
1890 
1891     case 07:                                            /* rotate left four */
1892         return (((t << 4) | (t >> 12)) & DMASK);
1893         }                                               /* end case */
1894     }                                                   /* end if */
1895 
1896 if (op == 05)                                           /* disabled ext rgt rot */
1897     E = t & 1;
1898 
1899 if (op == 06)                                           /* disabled ext lft rot */
1900     E = (t >> 15) & 1;
1901 
1902 return t;                                               /* input unchanged */
1903 }
1904 
1905 
1906 /* I/O instruction decode.
1907 
1908    If memory protect is enabled, and the instruction is not in a trap cell, then
1909    HLT instructions are illegal and will cause a memory protect violation.  If
1910    jumper W7 (SEL1) is in, then all other I/O instructions are legal; if W7 is
1911    out, then only I/O instructions to select code 1 are legal, and I/O to other
1912    select codes will cause a violation.
1913 
1914    If the instruction is allowed, then the I/O signal corresponding to the
1915    instruction is determined, the state of the interrupt deferral flag is set.
1916    Then the signal is dispatched to the device simulator indicated by the target
1917    select code.  The return value is split into status and data values, with the
1918    latter containing the SKF signal state or data to be returned in the A or B
1919    registers.
1920 
1921    Implementation notes:
1922 
1923     1. If the H/C (hold/clear flag) bit is set, then the ioCLF signal is added
1924        (not ORed) to the base signal derived from the I/O instruction.
1925 
1926     2. ioNONE is dispatched for HLT instructions because although HLT does not
1927        assert any backplane signals, the H/C bit may be set.  If it is, then the
1928        result will be to dispatch ioCLF.
1929 
1930     3. Device simulators return either ioSKF or ioNONE in response to an SFC or
1931        SFS signal.  ioSKF means that the instruction should skip.  Because
1932        device simulators return the "data" parameter value by default, we
1933        initialize that parameter to ioNONE to ensure that a simulator that does
1934        not implement SFC or SFS does not skip, which is the correct action for
1935        an interface that does not drive the SKF signal.
1936 
1937     4. STF/CLF and STC/CLC share sub-opcode values and must be further decoded
1938        by the state of instruction register bits 9 and 11, respectively.
1939 
1940     5. We return NOTE_IOG for normal status instead of SCPE_OK to request that
1941        interrupts be recalculated at the end of the instruction (execution of
1942        the I/O group instructions can change the interrupt priority chain).
1943 */
1944 
iogrp(uint32 ir,uint32 iotrap)1945 t_stat iogrp (uint32 ir, uint32 iotrap)
1946 {
1947 
1948 /* Translation for I/O subopcodes:            soHLT, soFLG, soSFC, soSFS, soMIX, soLIX, soOTX, soCTL */
1949 static const IOSIGNAL generate_signal [] = { ioNONE, ioSTF, ioSFC, ioSFS, ioIOI, ioIOI, ioIOO, ioSTC };
1950 
1951 const uint32 dev = ir & I_DEVMASK;                      /* device select code */
1952 const uint32 sop = I_GETIOOP (ir);                      /* I/O subopcode */
1953 const uint32 ab  = (ir & I_AB) != 0;                    /* A/B register select */
1954 const t_bool clf = (ir & I_HC) != 0;                    /* H/C flag select */
1955 uint16 iodata = (uint16) ioNONE;                        /* initialize for SKF test */
1956 uint32 ioreturn;
1957 t_stat iostat;
1958 IOCYCLE signal_set;
1959 
1960 if (!iotrap && mp_control &&                                /* instr not in trap cell and MP on? */
1961     ((sop == soHLT) ||                                      /*   and is HLT? */
1962     ((dev != OVF) && (mp_unit.flags & UNIT_MP_SEL1)))) {    /*   or is not SC 01 and SEL1 out? */
1963         if (sop == soLIX)                                   /* MP violation; is LIA/B instruction? */
1964             ABREG [ab] = 0;                                 /* A/B writes anyway */
1965 
1966         MP_ABORT (err_PC);                                  /* MP abort */
1967         }
1968 
1969 signal_set = generate_signal [sop];                     /* generate I/O signal from instruction */
1970 ion_defer = defer_tab [sop];                            /* defer depending on instruction */
1971 
1972 if (sop == soOTX)                                       /* OTA/B instruction? */
1973     iodata = ABREG [ab];                                /* pass A/B register value */
1974 
1975 else if ((sop == soCTL) && (ir & I_CTL))                /* CLC instruction? */
1976     signal_set = ioCLC;                                 /* change STC to CLC signal */
1977 
1978 if ((sop == soFLG) && clf)                              /* CLF instruction? */
1979     signal_set = ioCLF;                                 /* change STF to CLF signal */
1980 
1981 else if (clf)                                           /* CLF with another instruction? */
1982     signal_set = signal_set | ioCLF;                    /* add CLF signal */
1983 
1984 ioreturn = devdisp (dev, signal_set, IORETURN (SCPE_OK, iodata));   /* dispatch I/O signal */
1985 
1986 iostat = IOSTATUS (ioreturn);                           /* extract status */
1987 iodata = IODATA (ioreturn);                             /* extract return data value */
1988 
1989 if (((sop == soSFC) || (sop == soSFS)) &&               /* testing flag state? */
1990     ((IOSIGNAL) iodata == ioSKF))                       /*   and SKF asserted? */
1991     PC = (PC + 1) & VAMASK;                             /* bump P to skip next instruction */
1992 
1993 else if (sop == soLIX)                                  /* LIA/B instruction? */
1994     ABREG [ab] = iodata;                                /* load returned data */
1995 
1996 else if (sop == soMIX)                                  /* MIA/B instruction? */
1997     ABREG [ab] = ABREG [ab] | iodata;                   /* merge returned data */
1998 
1999 else if (sop == soHLT) {                                /* HLT instruction? */
2000     const int32 len = strlen (halt_msg);                /* find end msg */
2001     sprintf (&halt_msg[len - 6], "%06o", ir);           /* add the halt */
2002     return STOP_HALT;
2003     }
2004 
2005 if (iostat == SCPE_OK)                                  /* normal status? */
2006     return NOTE_IOG;                                    /* request interrupt recalc */
2007 else                                                    /* abnormal status */
2008     return iostat;                                      /* return it */
2009 }
2010 
2011 
2012 /* Device I/O signal dispatcher */
2013 
devdisp(uint32 select_code,IOCYCLE signal_set,uint16 data)2014 static uint32 devdisp (uint32 select_code, IOCYCLE signal_set, uint16 data)
2015 {
2016 return dtab [select_code]->io_handler (dtab [select_code],
2017                                        signal_set,
2018                                        IORETURN (SCPE_OK, data));
2019 }
2020 
2021 
2022 /* Calculate DMA requests */
2023 
calc_dma(void)2024 static uint32 calc_dma (void)
2025 {
2026 uint32 r = 0;
2027 
2028 if (dma [ch1].xferen && SRQ (dma [ch1].cw1 & I_DEVMASK))    /* check DMA1 cycle */
2029     r = r | DMA_1_REQ;
2030 if (dma [ch2].xferen && SRQ (dma [ch2].cw1 & I_DEVMASK))    /* check DMA2 cycle */
2031     r = r | DMA_2_REQ;
2032 return r;
2033 }
2034 
2035 
2036 /* Determine whether a pending interrupt deferral should be inhibited.
2037 
2038    Execution of certain instructions generally cause a pending interrupt to be
2039    deferred until the succeeding instruction completes.  However, the interrupt
2040    deferral rules differ on the 21xx vs. the 1000.
2041 
2042    The 1000 always defers until the completion of the instruction following a
2043    deferring instruction.  The 21xx defers unless the following instruction is
2044    an MRG instruction other than JMP or JMP,I or JSB,I.  If it is, then the
2045    deferral is inhibited, i.e., the pending interrupt will be serviced.
2046 
2047    See the "Set Phase Logic Flowchart," transition from phase 1A to phase 1B,
2048    and the "Theory of Operation," "Control Section Detailed Theory," "Phase
2049    Control Logic," "Phase 1B" paragraph in the Model 2100A Computer Installation
2050    and Maintenance Manual for details.
2051 */
2052 
calc_defer(void)2053 t_bool calc_defer (void)
2054 {
2055 uint16 IR;
2056 
2057 if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) {              /* 21xx series? */
2058     IR = ReadW (PC);                                    /* prefetch next instr */
2059 
2060     if (((IR & I_MRG & ~I_AB) != 0000000) &&            /* is MRG instruction? */
2061         ((IR & I_MRG_I)       != I_JSB_I) &&            /*   but not JSB,I? */
2062         ((IR & I_MRG)         != I_JMP))                /*   and not JMP or JMP,I? */
2063         return FALSE;                                   /* yes, so inhibit deferral */
2064     else
2065         return TRUE;                                    /* no, so allow deferral */
2066     }
2067 else
2068     return TRUE;                                        /* 1000 always allows deferral */
2069 }
2070 
2071 
2072 /* Calculate interrupt requests.
2073 
2074    The interrupt request (IRQ) of the highest-priority device for which all
2075    higher-priority PRL bits are set is granted.  That is, there must be an
2076    unbroken chain of priority to a device requesting an interrupt for that
2077    request to be granted.
2078 
2079    A device sets its IRQ bit to request an interrupt, and it clears its PRL bit
2080    to prevent lower-priority devices from interrupting.  IRQ is cleared by an
2081    interrupt acknowledge (IAK) signal.  PRL generally remains low while a
2082    device's interrupt service routine is executing to prevent preemption.
2083 
2084    IRQ and PRL indicate one of four possible states for a device:
2085 
2086      IRQ  PRL  Device state
2087      ---  ---  ----------------------
2088       0    1   Not interrupting
2089       1    0   Interrupt requested
2090       0    0   Interrupt acknowledged
2091       1    1   (not allowed)
2092 
2093    Note that PRL must be dropped when requesting an interrupt (IRQ set).  This
2094    is a hardware requirement of the 1000 series.  The IRQ lines from the
2095    backplane are not priority encoded.  Instead, the PRL chain expresses the
2096    priority by allowing only one IRQ line to be active at a time.  This allows a
2097    simple pull-down encoding of the CIR inputs.
2098 
2099    The end of priority chain is marked by the highest-priority (lowest-order)
2100    bit that is clear.  The device corresponding to that bit is the only device
2101    that may interrupt (a higher priority device that had IRQ set would also have
2102    had PRL set, which is a state violation).  We calculate a priority mask by
2103    ANDing the complement of the PRL bits with an increment of the PRL bits.
2104    Only the lowest-order bit will differ.  For example:
2105 
2106      dev_prl     :  ...1 1 0 1 1 0 1 1 1 1 1 1   (PRL denied for SC 06 and 11)
2107 
2108      dev_prl + 1 :  ...1 1 0 1 1 1 0 0 0 0 0 0
2109     ~dev_prl     :  ...0 0 1 0 0 1 0 0 0 0 0 0
2110      ANDed value :  ...0 0 0 0 0 1 0 0 0 0 0 0   (break is at SC 06)
2111 
2112    The interrupt requests are then ANDed with the priority mask to determine if
2113    a request is pending:
2114 
2115      pri mask    :  ...0 0 0 0 0 1 0 0 0 0 0 0   (allowed interrupt source)
2116      dev_irq     :  ...0 0 1 0 0 1 0 0 0 0 0 0   (devices requesting interrupts)
2117      ANDed value :  ...0 0 0 0 0 1 0 0 0 0 0 0   (request to grant)
2118 
2119    The select code corresponding to the granted request is then returned to the
2120    caller.
2121 
2122    If ION is clear, only power fail (SC 04) and parity error (SC 05) are
2123    eligible to interrupt (memory protect shares SC 05, but qualification occurs
2124    in the MP abort handler, so if SC 05 is interrupting when ION is clear, it
2125    must be a parity error interrupt).
2126 */
2127 
calc_int(void)2128 uint32 calc_int (void)
2129 {
2130 uint32 sc, pri_mask [2], req_grant [2];
2131 
2132 pri_mask  [0] = ~dev_prl [0] & (dev_prl [0] + 1);       /* calculate lower priority mask */
2133 req_grant [0] = pri_mask [0] & dev_irq [0];             /* calculate lower request to grant */
2134 
2135 if (ion)                                                    /* interrupt system on? */
2136     if ((req_grant [0] == 0) && (pri_mask [0] == 0)) {      /* no requests in lower set and PRL unbroken? */
2137         pri_mask  [1] = ~dev_prl [1] & (dev_prl [1] + 1);   /* calculate upper priority mask */
2138         req_grant [1] = pri_mask [1] & dev_irq [1];         /* calculate upper request to grant */
2139         }
2140     else                                                /* lower set has request */
2141         req_grant [1] = 0;                              /* no grants to upper set */
2142 
2143 else {                                                  /* interrupt system off */
2144     req_grant [0] = req_grant [0] &                     /* only PF and PE can interrupt */
2145                     (BIT_M (PWR) | BIT_M (PRO));
2146     req_grant [1] = 0;
2147     }
2148 
2149 if (req_grant [0])                                      /* device in lower half? */
2150     for (sc = 0; sc <= 31; sc++)                        /* determine interrupting select code */
2151         if (req_grant [0] & 1)                          /* grant this request? */
2152             return sc;                                  /* return this select code */
2153         else                                            /* not this one */
2154             req_grant [0] = req_grant [0] >> 1;         /* position next request */
2155 
2156 else if (req_grant [1]) {                                /* device in upper half */
2157     for (sc = 32; sc <= 63; sc++)                       /* determine interrupting select code */
2158         if (req_grant [1] & 1)                          /* grant this request? */
2159             return sc;                                  /* return this select code */
2160         else                                            /* not this one */
2161             req_grant [1] = req_grant [1] >> 1;         /* position next request */
2162   }
2163 return 0;                                               /* no interrupt granted */
2164 }
2165 
2166 
2167 /* Memory access routines.
2168 
2169    These routines access memory for reads and writes.  They validate the
2170    accesses for MP and MEM violations, if enabled.  The following routines are
2171    provided:
2172 
2173      - ReadPW  : Read a word using a physical address
2174      - ReadB   : Read a byte using the current map
2175      - ReadBA  : Read a byte using the alternate map
2176      - ReadW   : Read a word using the current map
2177      - ReadWA  : Read a word using the alternate map
2178      - ReadIO  : Read a word using the specified map without protection
2179      - ReadTAB : Read a word using the current map without protection
2180 
2181      - WritePW : Write a word using a physical address
2182      - WriteB  : Write a byte using the current map
2183      - WriteBA : Write a byte using the alternate map
2184      - WriteW  : Write a word using the current map
2185      - WriteWA : Write a word using the alternate map
2186      - WriteIO : Write a word using the specified map without protection
2187 
2188    The memory protect (MP) and memory expansion module (MEM) accessories provide
2189    a protected mode that guards against improper accesses by user programs.
2190    They may be enabled or disabled independently, although protection requires
2191    that both be enabled.  MP checks that memory writes do not fall below the
2192    Memory Protect Fence Register (MPFR) value, and MEM checks that read/write
2193    protection rules on the target page are compatible with the access desired.
2194    If either check fails, and MP is enabled, then the request is aborted.
2195 
2196    Each mapped routine calls "dms" if DMS is enabled to translate the logical
2197    address supplied to a physical address.  "dms" performs a protection check
2198    and aborts without returning if the check fails.  The write routines perform
2199    an additional memory-protect check and abort if a violation occurs (so, to
2200    pass, a page must be writable AND the target must be above the MP fence).
2201 
2202    Note that MP uses a lower bound of 2 for memory writes, allowing unrestricted
2203    access to the A and B registers (addressed as locations 0 and 1).
2204 */
2205 
2206 #define MP_TEST(va)     (mp_control && ((va) >= 2) && ((va) < mp_fence))
2207 
2208 
2209 /* Read a word using a physical address */
2210 
ReadPW(uint32 pa)2211 uint16 ReadPW (uint32 pa)
2212 {
2213 if (pa <= 1)                                            /* read locations 0 or 1? */
2214     return ABREG[pa];                                   /* return A/B register */
2215 else                                                    /* location >= 2 */
2216     return M[pa];                                       /* return physical memory value */
2217 }
2218 
2219 
2220 /* Read a byte using the current map */
2221 
ReadB(uint32 va)2222 uint8 ReadB (uint32 va)
2223 {
2224 int32 pa;
2225 
2226 if (dms_enb)                                            /* MEM enabled? */
2227     pa = dms (va >> 1, dms_ump, RDPROT);                /* translate address */
2228 else                                                    /* MEM disabled */
2229     pa = va >> 1;                                       /* use logical as physical address */
2230 
2231 if (va & 1)                                             /* low byte addressed? */
2232     return (ReadPW (pa) & 0377);                        /* mask to lower byte */
2233 else                                                    /* high byte addressed */
2234     return ((ReadPW (pa) >> 8) & 0377);                 /* position higher byte and mask */
2235 }
2236 
2237 
2238 /* Read a byte using the alternate map */
2239 
ReadBA(uint32 va)2240 uint8 ReadBA (uint32 va)
2241 {
2242 uint32 pa;
2243 
2244 if (dms_enb)                                            /* MEM enabled? */
2245     pa = dms (va >> 1, dms_ump ^ MAP_LNT, RDPROT);      /* translate address using alternate map */
2246 else                                                    /* MEM disabled */
2247     pa = va >> 1;                                       /* use logical as physical address */
2248 
2249 if (va & 1)                                             /* low byte addressed? */
2250     return (ReadPW (pa) & 0377);                        /* mask to lower byte */
2251 else                                                    /* high byte addressed */
2252     return ((ReadPW (pa) >> 8) & 0377);                 /* position higher byte and mask */
2253 }
2254 
2255 
2256 /* Read a word using the current map */
2257 
ReadW(uint32 va)2258 uint16 ReadW (uint32 va)
2259 {
2260 uint32 pa;
2261 
2262 if (dms_enb)                                            /* MEM enabled? */
2263     pa = dms (va, dms_ump, RDPROT);                     /* translate address */
2264 else                                                    /* MEM disabled */
2265     pa = va;                                            /* use logical as physical address */
2266 
2267 return ReadPW (pa);                                     /* return word */
2268 }
2269 
2270 
2271 /* Read a word using the alternate map */
2272 
ReadWA(uint32 va)2273 uint16 ReadWA (uint32 va)
2274 {
2275 uint32 pa;
2276 
2277 if (dms_enb)                                            /* MEM enabled? */
2278     pa = dms (va, dms_ump ^ MAP_LNT, RDPROT);           /* translate address using alternate map */
2279 else                                                    /* MEM disabled */
2280     pa = va;                                            /* use logical as physical address */
2281 
2282 return ReadPW (pa);                                     /* return word */
2283 }
2284 
2285 
2286 /* Read a word using the specified map without protection */
2287 
ReadIO(uint32 va,uint32 map)2288 uint16 ReadIO (uint32 va, uint32 map)
2289 {
2290 uint32 pa;
2291 
2292 if (dms_enb)                                            /* MEM enabled? */
2293     pa = dms (va, map, NOPROT);                         /* translate address with no protection */
2294 else                                                    /* MEM disabled */
2295     pa = va;                                            /* use logical as physical address */
2296 
2297 return M[pa];                                           /* return word without A/B interception */
2298 }
2299 
2300 
2301 /* Read a word using the current map without protection */
2302 
ReadTAB(uint32 va)2303 static uint16 ReadTAB (uint32 va)
2304 {
2305 uint32 pa;
2306 
2307 if (dms_enb)                                            /* MEM enabled? */
2308     pa = dms (va, dms_ump, NOPROT);                     /* translate address with no protection */
2309 else                                                    /* MEM disabled */
2310     pa = va;                                            /* use logical as physical address */
2311 
2312 return ReadPW (pa);                                     /* return word */
2313 }
2314 
2315 
2316 /* Write a word using a physical address */
2317 
WritePW(uint32 pa,uint32 dat)2318 void WritePW (uint32 pa, uint32 dat)
2319 {
2320 if (pa <= 1)                                            /* write locations 0 or 1? */
2321     ABREG[pa] = dat & DMASK;                            /* store A/B register */
2322 else if (pa < fwanxm)                                   /* 2 <= location <= LWA memory? */
2323     M[pa] = dat & DMASK;                                /* store physical memory value */
2324 
2325 return;
2326 }
2327 
2328 
2329 /* Write a byte using the current map */
2330 
WriteB(uint32 va,uint32 dat)2331 void WriteB (uint32 va, uint32 dat)
2332 {
2333 uint32 pa, t;
2334 
2335 if (dms_enb)                                            /* MEM enabled? */
2336     pa = dms (va >> 1, dms_ump, WRPROT);                /* translate address */
2337 else                                                    /* MEM disabled */
2338     pa = va >> 1;                                       /* use logical as physical address */
2339 
2340 if (MP_TEST (va >> 1))                                  /* MPCK? */
2341     MP_ABORT (va >> 1);                                 /* MP violation */
2342 
2343 t = ReadPW (pa);                                        /* get word */
2344 
2345 if (va & 1)                                             /* low byte addressed? */
2346     t = (t & 0177400) | (dat & 0377);                   /* merge in lower byte */
2347 else                                                    /* high byte addressed */
2348     t = (t & 0377) | ((dat & 0377) << 8);               /* position higher byte and merge */
2349 
2350 WritePW (pa, t);                                        /* store word */
2351 return;
2352 }
2353 
2354 
2355 /* Write a byte using the alternate map */
2356 
WriteBA(uint32 va,uint32 dat)2357 void WriteBA (uint32 va, uint32 dat)
2358 {
2359 uint32 pa, t;
2360 
2361 if (dms_enb) {                                          /* MEM enabled? */
2362     dms_viol (va >> 1, MVI_WPR);                        /* always a violation if protected */
2363     pa = dms (va >> 1, dms_ump ^ MAP_LNT, WRPROT);      /* translate address using alternate map */
2364     }
2365 else                                                    /* MEM disabled */
2366     pa = va >> 1;                                       /* use logical as physical address */
2367 
2368 if (MP_TEST (va >> 1))                                  /* MPCK? */
2369     MP_ABORT (va >> 1);                                 /* MP violation */
2370 
2371 t = ReadPW (pa);                                        /* get word */
2372 
2373 if (va & 1)                                             /* low byte addressed? */
2374     t = (t & 0177400) | (dat & 0377);                   /* merge in lower byte */
2375 else                                                    /* high byte addressed */
2376     t = (t & 0377) | ((dat & 0377) << 8);               /* position higher byte and merge */
2377 
2378 WritePW (pa, t);                                        /* store word */
2379 return;
2380 }
2381 
2382 
2383 /* Write a word using the current map */
2384 
WriteW(uint32 va,uint32 dat)2385 void WriteW (uint32 va, uint32 dat)
2386 {
2387 uint32 pa;
2388 
2389 if (dms_enb)                                            /* MEM enabled? */
2390     pa = dms (va, dms_ump, WRPROT);                     /* translate address */
2391 else                                                    /* MEM disabled */
2392     pa = va;                                            /* use logical as physical address */
2393 
2394 if (MP_TEST (va))                                       /* MPCK? */
2395     MP_ABORT (va);                                      /* MP violation */
2396 
2397 WritePW (pa, dat);                                      /* store word */
2398 return;
2399 }
2400 
2401 
2402 /* Write a word using the alternate map */
2403 
WriteWA(uint32 va,uint32 dat)2404 void WriteWA (uint32 va, uint32 dat)
2405 {
2406 int32 pa;
2407 
2408 if (dms_enb) {                                          /* MEM enabled? */
2409     dms_viol (va, MVI_WPR);                             /* always a violation if protected */
2410     pa = dms (va, dms_ump ^ MAP_LNT, WRPROT);           /* translate address using alternate map */
2411     }
2412 else                                                    /* MEM disabled */
2413     pa = va;                                            /* use logical as physical address */
2414 
2415 if (MP_TEST (va))                                       /* MPCK? */
2416     MP_ABORT (va);                                      /* MP violation */
2417 
2418 WritePW (pa, dat);                                      /* store word */
2419 return;
2420 }
2421 
2422 
2423 /* Write a word using the specified map without protection */
2424 
WriteIO(uint32 va,uint32 dat,uint32 map)2425 void WriteIO (uint32 va, uint32 dat, uint32 map)
2426 {
2427 uint32 pa;
2428 
2429 if (dms_enb)                                            /* MEM enabled? */
2430     pa = dms (va, map, NOPROT);                         /* translate address with no protection */
2431 else                                                    /* MEM disabled */
2432     pa = va;                                            /* use logical as physical address */
2433 
2434 if (pa < fwanxm)
2435     M[pa] = dat & DMASK;                                /* store word without A/B interception */
2436 return;
2437 }
2438 
2439 
2440 /* Mapped access check.
2441 
2442    Returns TRUE if the address will be mapped (presuming MEM is enabled).
2443 */
2444 
is_mapped(uint32 va)2445 static t_bool is_mapped (uint32 va)
2446 {
2447 uint32 dms_fence;
2448 
2449 if (va >= 02000)                                        /* above the base bage? */
2450     return TRUE;                                        /* always mapped */
2451 else {
2452     dms_fence = dms_sr & MST_FENCE;                     /* get BP fence value */
2453     return (dms_sr & MST_FLT) ? (va < dms_fence) :      /* below BP fence and lower portion mapped? */
2454                                 (va >= dms_fence);      /*   or above BP fence and upper portion mapped? */
2455     }
2456 }
2457 
2458 
2459 /* DMS relocation.
2460 
2461    This routine translates logical into physical addresses.  It must be called
2462    only when DMS is enabled, as that condition is not checked.  The logical
2463    address, desired map, and desired access type are supplied.  If the access is
2464    legal, the mapped physical address is returned; if it is not, then a MEM
2465    violation is indicated.
2466 
2467    The current map may be specified by passing "dms_ump" as the "map" parameter,
2468    or a specific map may be used.  Normally, read and write accesses pass RDPROT
2469    or WRPROT as the "prot" parameter to request access checking.  For DMA
2470    accesses, NOPROT must be passed to inhibit access checks.
2471 
2472    This routine checks for read, write, and base-page violations and will call
2473    "dms_viol" as appropriate.  The latter routine will abort if MP is enabled,
2474    or will return if protection is off.
2475 */
2476 
dms(uint32 va,uint32 map,uint32 prot)2477 static uint32 dms (uint32 va, uint32 map, uint32 prot)
2478 {
2479 uint32 pgn, mpr;
2480 
2481 if (va <= 1)                                            /* reference to A/B register? */
2482     return va;                                          /* use address */
2483 
2484 if (!is_mapped (va)) {                                  /* unmapped? */
2485     if ((va >= 2) && (prot == WRPROT))                  /* base page write access? */
2486         dms_viol (va, MVI_BPG);                         /* signal a base page violation */
2487     return va;                                          /* use unmapped address */
2488     }
2489 
2490 pgn = VA_GETPAG (va);                                   /* get page num */
2491 mpr = dms_map[map + pgn];                               /* get map reg */
2492 
2493 if (mpr & prot)                                         /* desired access disallowed? */
2494     dms_viol (va, prot);                                /* signal protection violation */
2495 
2496 return (MAP_GETPAG (mpr) | VA_GETOFF (va));             /* return mapped address */
2497 }
2498 
2499 
2500 /* DMS relocation for console access.
2501 
2502    Console access allows the desired map to be specified by switches on the
2503    command line.  All protection checks are off for console access.
2504 
2505    This routine is called to restore a saved configuration, and mapping is not
2506    used for restoration.
2507 */
2508 
dms_cons(uint32 va,int32 sw)2509 static uint32 dms_cons (uint32 va, int32 sw)
2510 {
2511 uint32 map_sel;
2512 
2513 if ((dms_enb == 0) ||                                   /* DMS off? */
2514     (sw & (SWMASK ('N') | SIM_SW_REST)))                /* no mapping rqst or save/rest? */
2515     return va;                                          /* use physical address */
2516 
2517 else if (sw & SWMASK ('S'))
2518     map_sel = SMAP;
2519 
2520 else if (sw & SWMASK ('U'))
2521     map_sel = UMAP;
2522 
2523 else if (sw & SWMASK ('P'))
2524     map_sel = PAMAP;
2525 
2526 else if (sw & SWMASK ('Q'))
2527     map_sel = PBMAP;
2528 
2529 else                                                    /* dflt to log addr, cur map */
2530     map_sel = dms_ump;
2531 
2532 if (va >= VASIZE)                                       /* virtual, must be 15b */
2533     return MEMSIZE;
2534 
2535 else if (dms_enb)                                       /* DMS on? go thru map */
2536     return dms (va, map_sel, NOPROT);
2537 
2538 else                                                    /* else return virtual */
2539     return va;
2540 }
2541 
2542 
2543 /* Memory protect and DMS validation for jumps.
2544 
2545    Jumps are a special case of write validation.  The target address is treated
2546    as a write, even when no physical write takes place, so jumping to a
2547    write-protected page causes a MEM violation.  In addition, a MEM violation is
2548    indicated if the jump is to the unmapped portion of the base page.  Finally,
2549    jumping to a location under the memory-protect fence causes an MP violation.
2550 
2551    Because the MP and MEM hardware works in parallel, all three violations may
2552    exist concurrently.  For example, a JMP to the unmapped portion of the base
2553    page that is write protected and under the MP fence will indicate a
2554    base-page, write, and MP violation, whereas a JMP to the mapped portion will
2555    indicate a write and MP violation (BPV is inhibited by the MEBEN signal).  If
2556    MEM and MP violations occur concurrently, the MEM violation takes precedence,
2557    as the SFS and SFC instructions test the MEV flip-flop.
2558 
2559    The lower bound of protected memory is passed in the "plb" argument.  This
2560    must be either 0 or 2.  All violations are qualified by the MPCND signal,
2561    which responds to the lower bound.  Therefore, if the lower bound is 2, and
2562    if the part below the base-page fence is unmapped, or if the base page is
2563    write-protected, then a MEM violation will occur only if the access is not to
2564    locations 0 or 1.  The instruction set firmware uses a lower bound of 0 for
2565    JMP, JLY, and JPY (and for JSB with W5 out), and of 2 for DJP, SJP, UJP, JRS,
2566    and .GOTO (and JSB with W5 in).
2567 
2568    Finally, all violations are inhibited if MP is off (mp_control is CLEAR), and
2569    MEM violations are inhibited if the MEM is disabled.
2570 */
2571 
mp_dms_jmp(uint32 va,uint32 plb)2572 void mp_dms_jmp (uint32 va, uint32 plb)
2573 {
2574 uint32 violation = 0;
2575 uint32 pgn = VA_GETPAG (va);                            /* get page number */
2576 
2577 if (mp_control) {                                       /* MP on? */
2578     if (dms_enb) {                                      /* MEM on? */
2579         if (dms_map [dms_ump + pgn] & WRPROT)           /* page write protected? */
2580             violation = MVI_WPR;                        /* write violation occured */
2581 
2582         if (!is_mapped (va) && (va >= plb))             /* base page target? */
2583             violation = violation | MVI_BPG;            /* base page violation occured */
2584 
2585         if (violation)                                  /* any violation? */
2586             dms_viol (va, violation);                   /* signal MEM violation */
2587         }
2588 
2589     if ((va >= plb) && (va < mp_fence))                 /* jump under fence? */
2590         MP_ABORT (va);                                  /* signal MP violation */
2591     }
2592 
2593 return;
2594 }
2595 
2596 
2597 /* DMS read and write map registers */
2598 
dms_rmap(uint32 mapi)2599 uint16 dms_rmap (uint32 mapi)
2600 {
2601 mapi = mapi & MAP_MASK;
2602 return (dms_map[mapi] & ~MAP_RSVD);
2603 }
2604 
dms_wmap(uint32 mapi,uint32 dat)2605 void dms_wmap (uint32 mapi, uint32 dat)
2606 {
2607 mapi = mapi & MAP_MASK;
2608 dms_map[mapi] = (uint16) (dat & ~MAP_RSVD);
2609 return;
2610 }
2611 
2612 
2613 /* Process a MEM violation.
2614 
2615    A MEM violation will report the cause in the violation register.  This occurs
2616    even if the MEM is not in the protected mode (i.e., MP is not enabled).  If
2617    MP is enabled, an MP abort is taken with the MEV flip-flop set.  Otherwise,
2618    we return to the caller.
2619 */
2620 
dms_viol(uint32 va,uint32 st)2621 void dms_viol (uint32 va, uint32 st)
2622 {
2623 dms_vr = st | dms_upd_vr (va);                          /* set violation cause in register */
2624 
2625 if (mp_control) {                                       /* memory protect on? */
2626     mp_mevff = SET;                                     /* record memory expansion violation */
2627     MP_ABORT (va);                                      /* abort */
2628     }
2629 return;
2630 }
2631 
2632 
2633 /* Update the MEM violation register.
2634 
2635    In hardware, the MEM violation register (VR) is clocked on every memory read,
2636    every memory write above the lower bound of protected memory, and every
2637    execution of a privileged DMS instruction.  The register is not clocked when
2638    MP is disabled by an MP or MEM error (i.e., when MEVFF sets or CTL5FF
2639    clears), in order to capture the state of the MEM.  In other words, the VR
2640    continually tracks the memory map register accessed plus the MEM state
2641    (MEBEN, MAPON, and USR) until a violation occurs, and then it's "frozen."
2642 
2643    Under simulation, we do not have to update the VR on every memory access,
2644    because the visible state is only available via a programmed RVA/B
2645    instruction or via the SCP interface.  Therefore, it is sufficient if the
2646    register is updated:
2647 
2648      - at a MEM violation (when freezing)
2649      - at an MP violation (when freezing)
2650      - during RVA/B execution (if not frozen)
2651      - before returning to SCP after a simulator stop (if not frozen)
2652 */
2653 
dms_upd_vr(uint32 va)2654 uint32 dms_upd_vr (uint32 va)
2655 {
2656 if (mp_control && (mp_mevff == CLEAR)) {                /* violation register unfrozen? */
2657     dms_vr = VA_GETPAG (va) |                           /* set map address */
2658              (dms_enb ? MVI_MEM : 0) |                  /*   and MEM enabled */
2659              (dms_ump ? MVI_UMP : 0);                   /*   and user map enabled */
2660 
2661     if (is_mapped (va))                                 /* is addressed mapped? */
2662         dms_vr = dms_vr | MVI_MEB;                      /* ME bus is enabled */
2663     }
2664 
2665 return dms_vr;
2666 }
2667 
2668 
2669 /* Update the MEM status register */
2670 
dms_upd_sr(void)2671 uint32 dms_upd_sr (void)
2672 {
2673 dms_sr = dms_sr & ~(MST_ENB | MST_UMP | MST_PRO);
2674 
2675 if (dms_enb)
2676     dms_sr = dms_sr | MST_ENB;
2677 
2678 if (dms_ump)
2679     dms_sr = dms_sr | MST_UMP;
2680 
2681 if (mp_control)
2682     dms_sr = dms_sr | MST_PRO;
2683 
2684 return dms_sr;
2685 }
2686 
2687 
2688 /* CPU (SC 0) I/O signal handler.
2689 
2690    I/O instructions for select code 0 manipulate the interrupt system.  STF and
2691    CLF turn the interrupt system on and off, and SFS and SFC test the state of
2692    the interrupt system.  When the interrupt system is off, only power fail and
2693    parity error interrupts are allowed.
2694 
2695    A PON reset initializes certain CPU registers.  The 1000 series does a
2696    microcoded memory clear and leaves the T and P registers set as a result.
2697 
2698    Front-panel PRESET performs additional initialization.  We also handle MEM
2699    preset here.
2700 
2701    Implementation notes:
2702 
2703     1. An IOI signal reads the floating I/O bus (0 on all machines).
2704 
2705     2. A CLC 0 issues CRS to all devices, not CLC.  While most cards react
2706        identically to CRS and CLC, some do not, e.g., the 12566B when used as an
2707        I/O diagnostic target.
2708 
2709     3. RTE uses the undocumented SFS 0,C instruction to both test and turn off
2710        the interrupt system.  This is confirmed in the "RTE-6/VM Technical
2711        Specifications" manual (HP 92084-90015), section 2.3.1 "Process the
2712        Interrupt", subsection "A.1 $CIC":
2713 
2714         "Test to see if the interrupt system is on or off.  This is done with
2715          the SFS 0,C instruction.  In either case, turn it off (the ,C does
2716          it)."
2717 
2718        ...and in section 5.8, "Parity Error Detection":
2719 
2720         "Because parity error interrupts can occur even when the interrupt
2721          system is off, the code at $CIC must be able to save the complete
2722          system status. The major hole in being able to save the complete state
2723          is in saving the interrupt system state. In order to do this in both
2724          the 21MX and the 21XE the instruction 103300 was used to both test the
2725          interrupt system and turn it off."
2726 
2727     4. Select code 0 cannot interrupt, so there is no SIR handler.
2728 */
2729 
cpuio(DIB * dibptr,IOCYCLE signal_set,uint32 stat_data)2730 uint32 cpuio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
2731 {
2732 uint32 sc;
2733 IOSIGNAL signal;
2734 IOCYCLE  working_set = signal_set;                      /* no SIR handler needed */
2735 
2736 while (working_set) {
2737     signal = IONEXT (working_set);                      /* isolate next signal */
2738 
2739     switch (signal) {                                   /* dispatch I/O signal */
2740 
2741         case ioCLF:                                     /* clear flag flip-flop */
2742             ion = CLEAR;                                /* turn interrupt system off */
2743             break;
2744 
2745         case ioSTF:                                     /* set flag flip-flop */
2746             ion = SET;                                  /* turn interrupt system on */
2747             break;
2748 
2749         case ioSFC:                                     /* skip if flag is clear */
2750             setSKF (!ion);                              /* skip if interrupt system is off */
2751             break;
2752 
2753         case ioSFS:                                     /* skip if flag is set */
2754             setSKF (ion);                               /* skip if interupt system is on */
2755             break;
2756 
2757         case ioIOI:                                     /* I/O input */
2758             stat_data = IORETURN (SCPE_OK, 0);          /* returns 0 */
2759             break;
2760 
2761         case ioPON:                                     /* power on normal */
2762             AR = 0;                                     /* clear A register */
2763             BR = 0;                                     /* clear B register */
2764             SR = 0;                                     /* clear S register */
2765             TR = 0;                                     /* clear T register */
2766             E = 1;                                      /* set E register */
2767 
2768             if (UNIT_CPU_FAMILY == UNIT_FAMILY_1000) {  /* 1000 series? */
2769                 memset (M, 0, MEMSIZE * 2);             /* zero allocated memory */
2770                 MR = 0077777;                           /* set M register */
2771                 PC = 0100000;                           /* set P register */
2772                 }
2773 
2774             else {                                      /* 21xx series */
2775                 MR = 0;                                 /* clear M register */
2776                 PC = 0;                                 /* clear P register */
2777                 }
2778             break;
2779 
2780         case ioPOPIO:                                   /* power-on preset to I/O */
2781             O = 0;                                      /* clear O register */
2782             ion = CLEAR;                                /* turn off interrupt system */
2783             ion_defer = FALSE;                          /* clear interrupt deferral */
2784 
2785             dms_enb = 0;                                /* turn DMS off */
2786             dms_ump = 0;                                /* init to system map */
2787             dms_sr = 0;                                 /* clear status register and BP fence */
2788             dms_vr = 0;                                 /* clear violation register */
2789             break;
2790 
2791         case ioCLC:                                     /* clear control flip-flop */
2792             for (sc = CRSDEV; sc <= MAXDEV; sc++)       /* send CRS to devices */
2793                 devdisp (sc, ioCRS, 0);                 /*   from select code 6 and up */
2794             break;
2795 
2796         default:                                        /* all other signals */
2797             break;                                      /*   are ignored */
2798         }
2799 
2800     working_set = working_set & ~signal;                /* remove current signal from set */
2801     }
2802 
2803 return stat_data;
2804 }
2805 
2806 
2807 /* Overflow/S-register (SC 1) I/O signal handler.
2808 
2809    Flag instructions directed to select code 1 manipulate the overflow (O)
2810    register.  Input and output instructions access the switch (S) register.  On
2811    the 2115 and 2116, there is no S-register indicator, so it is effectively
2812    read-only.  On the other machines, a front-panel display of the S-register is
2813    provided.  On all machines, front-panel switches are provided to set the
2814    contents of the S register.
2815 
2816    Implementation notes:
2817 
2818     1. Select code 1 cannot interrupt, so there is no SIR handler.
2819 */
2820 
ovflio(DIB * dibptr,IOCYCLE signal_set,uint32 stat_data)2821 uint32 ovflio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
2822 {
2823 IOSIGNAL signal;
2824 IOCYCLE  working_set = signal_set;                      /* no SIR handler needed */
2825 
2826 while (working_set) {
2827     signal = IONEXT (working_set);                      /* isolate next signal */
2828 
2829     switch (signal) {                                   /* dispatch I/O signal */
2830 
2831         case ioCLF:                                     /* clear flag flip-flop */
2832             O = 0;                                      /* clear overflow */
2833             break;
2834 
2835         case ioSTF:                                     /* set flag flip-flop */
2836             O = 1;                                      /* set overflow */
2837             break;
2838 
2839         case ioSFC:                                     /* skip if flag is clear */
2840             setSKF (!O);                                /* skip if overflow is clear */
2841             break;
2842 
2843         case ioSFS:                                     /* skip if flag is set */
2844             setSKF (O);                                 /* skip if overflow is set */
2845             break;
2846 
2847         case ioIOI:                                     /* I/O input */
2848             stat_data = IORETURN (SCPE_OK, SR);         /* read switch register value */
2849             break;
2850 
2851         case ioIOO:                                     /* I/O output */
2852             if ((UNIT_CPU_MODEL != UNIT_2116) &&        /* no S register display on */
2853                 (UNIT_CPU_MODEL != UNIT_2115))          /*   2116 and 2115 machines */
2854                 SR = IODATA (stat_data);                /* write S register value */
2855             break;
2856 
2857         default:                                        /* all other signals */
2858             break;                                      /*   are ignored */
2859         }
2860 
2861     working_set = working_set & ~signal;                /* remove current signal from set */
2862     }
2863 
2864 return stat_data;
2865 }
2866 
2867 
2868 /* Power fail (SC 4) I/O signal handler.
2869 
2870    Power fail detection is standard on 2100 and 1000 systems and is optional on
2871    21xx systems.  Power fail recovery is standard on the 2100 and optional on
2872    the others.  Power failure or restoration will cause an interrupt on select
2873    code 4.  The direction of power change (down or up) can be tested by SFC.
2874 
2875    We do not implement power fail under simulation.  However, the central
2876    interrupt register (CIR) is always read by an IOI directed to select code 4.
2877 */
2878 
pwrfio(DIB * dibptr,IOCYCLE signal_set,uint32 stat_data)2879 uint32 pwrfio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
2880 {
2881 IOSIGNAL signal;
2882 IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */
2883 
2884 while (working_set) {
2885     signal = IONEXT (working_set);                      /* isolate next signal */
2886 
2887     switch (signal) {                                   /* dispatch I/O signal */
2888 
2889         case ioSTC:                                     /* set control flip-flop */
2890             break;                                      /* reinitializes power fail */
2891 
2892         case ioCLC:                                     /* clear control flip-flop */
2893             break;                                      /* reinitializes power fail */
2894 
2895         case ioSFC:                                     /* skip if flag is clear */
2896             break;                                      /* skips if power fail occurred */
2897 
2898         case ioIOI:                                     /* I/O input */
2899             stat_data = IORETURN (SCPE_OK, intaddr);    /* input CIR value */
2900             break;
2901 
2902         default:                                        /* all other signals */
2903             break;                                      /*   are ignored */
2904         }
2905 
2906     working_set = working_set & ~signal;                /* remove current signal from set */
2907     }
2908 
2909 return stat_data;
2910 }
2911 
2912 
2913 /* Memory protect/parity error (SC 5) I/O signal handler.
2914 
2915    The memory protect card has a number of non-standard features:
2916 
2917     - CLF and STF affect the parity error enable flip-flop, not the flag
2918     - SFC and SFS test the memory expansion violation flip-flop, not the flag
2919     - POPIO clears control, flag, and flag buffer instead of setting the flags
2920     - CLC does not clear control (the only way to turn off MP is to cause a
2921       violation)
2922     - PRL and IRQ are a function of the flag only, not flag and control
2923     - IAK is used unqualified by IRQ
2924 
2925    The IAK backplane signal is asserted when any interrupt is acknowledged by
2926    the CPU.  Normally, an interface qualifies IAK with its own IRQ to ensure
2927    that it responds only to an acknowledgement of its own request.  The MP card
2928    does this to reset its flag buffer and flag flip-flops, and to reset the
2929    parity error indication.  However, it also responds to an unqualified IAK
2930    (i.e., for any interface) as follows:
2931 
2932     - clears the MPV flip-flop
2933     - clears the indirect counter
2934     - clears the control flip-flop
2935     - sets the INTPT flip-flop
2936 
2937    The INTPT flip-flop indicates an occurrence of an interrupt.  If the trap
2938    cell of the interrupting device contains an I/O instruction that is not a
2939    HLT, action equivalent to STC 05 is taken, i.e.:
2940 
2941     - sets the control flip-flop
2942     - set the EVR flip-flop
2943     - clears the MEV flip-flop
2944     - clears the PARERR flip-flop
2945 
2946    In other words, an interrupt for any device will disable MP unless the trap
2947    cell contains an I/O instruction other than a HLT.
2948 
2949    Implementation notes:
2950 
2951     1. Because the card uses IAK unqualified, this routine is called whenever
2952        any interrupt occurs.  If the MP card itself is not interrupting, the
2953        select code passed will not be SC 05.  In either case, the trap cell
2954        instruction is passed in the data portion of the "stat_data" parameter.
2955 
2956     2. The MEV flip-flop records memory expansion (a.k.a. dynamic mapping)
2957        violations.  It is set when an DM violation is encountered and can be
2958        tested via SFC/SFS.
2959 
2960     3. MP cannot be turned off in hardware, except by causing a violation.
2961        Microcode typically does this by executing an IOG micro-order with select
2962        code /= 1, followed by an IAK to clear the interrupt and a FTCH to clear
2963        the INTPT flip-flop.  Under simulation, mp_control may be set to CLEAR to
2964        produce the same effect.
2965 
2966     4. Parity error logic is not implemented.
2967 */
2968 
protio(DIB * dibptr,IOCYCLE signal_set,uint32 stat_data)2969 uint32 protio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
2970 {
2971 uint16 data;
2972 IOSIGNAL signal;
2973 IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */
2974 
2975 while (working_set) {
2976     signal = IONEXT (working_set);                      /* isolate next signal */
2977 
2978     switch (signal) {                                   /* dispatch I/O signal */
2979 
2980         case ioCLF:                                     /* clear flag flip-flop */
2981             break;                                      /* turns off PE interrupt */
2982 
2983         case ioSTF:                                     /* set flag flip-flop */
2984             break;                                      /* turns on PE interrupt */
2985 
2986         case ioENF:                                     /* enable flag */
2987             mp_flag = mp_flagbuf = SET;                 /* set flag buffer and flag flip-flops */
2988             mp_evrff = CLEAR;                           /* inhibit violation register updates */
2989             break;
2990 
2991         case ioSFC:                                     /* skip if flag is clear */
2992             setSKF (!mp_mevff);                         /* skip if MP interrupt */
2993             break;
2994 
2995         case ioSFS:                                     /* skip if flag is set */
2996             setSKF (mp_mevff);                          /* skip if DMS interrupt */
2997             break;
2998 
2999         case ioIOI:                                     /* I/O input */
3000             stat_data = IORETURN (SCPE_OK, mp_viol);    /* read MP violation register */
3001             break;
3002 
3003         case ioIOO:                                     /* I/O output */
3004             mp_fence = IODATA (stat_data) & VAMASK;     /* write to MP fence register */
3005 
3006             if (cpu_unit.flags & UNIT_2100)             /* 2100 IOP uses MP fence */
3007                 iop_sp = mp_fence;                      /*   as a stack pointer */
3008             break;
3009 
3010         case ioPOPIO:                                   /* power-on preset to I/O */
3011             mp_control = CLEAR;                         /* clear control flip-flop */
3012             mp_flag = mp_flagbuf = CLEAR;               /* clear flag and flag buffer flip-flops */
3013             mp_mevff = CLEAR;                           /* clear memory expansion violation flip-flop */
3014             mp_evrff = SET;                             /* set enable violation register flip-flop */
3015             break;
3016 
3017         case ioSTC:                                     /* set control flip-flop */
3018             mp_control = SET;                           /* turn on MP */
3019             mp_mevff = CLEAR;                           /* clear memory expansion violation flip-flop */
3020             mp_evrff = SET;                             /* set enable violation register flip-flop */
3021             break;
3022 
3023         case ioSIR:                                     /* set interrupt request */
3024             setPRL (PRO, !mp_flag);                     /* set PRL signal */
3025             setIRQ (PRO, mp_flag);                      /* set IRQ signal */
3026             break;
3027 
3028         case ioIAK:                                     /* interrupt acknowledge */
3029             if (dibptr->select_code == PRO)             /* MP interrupt acknowledgement? */
3030                 mp_flag = mp_flagbuf = CLEAR;           /* clear flag and flag buffer */
3031 
3032             data = IODATA (stat_data);                  /* get trap cell instruction */
3033 
3034             if (((data & I_NMRMASK) != I_IO) ||         /* trap cell instruction not I/O */
3035                 (I_GETIOOP (data) == soHLT))            /*   or is halt? */
3036                 mp_control = CLEAR;                     /* turn protection off */
3037             else {                                      /* non-HLT I/O instruction leaves MP on */
3038                 mp_mevff = CLEAR;                       /*   but clears MEV flip-flop */
3039                 mp_evrff = SET;                         /*   and reenables violation register flip-flop */
3040                 }
3041             break;
3042 
3043         default:                                        /* all other signals */
3044             break;                                      /*   are ignored */
3045         }
3046 
3047     working_set = working_set & ~signal;                /* remove current signal from set */
3048     }
3049 
3050 return stat_data;
3051 }
3052 
3053 
3054 /* DMA/DCPC secondary (SC 2/3) I/O signal handler.
3055 
3056    DMA consists of one (12607B) or two (12578A/12895A/12897B) channels.  Each
3057    channel uses two select codes: 2 and 6 for channel 1, and 3 and 7 for channel
3058    2.  The lower select codes are used to configure the memory address register
3059    (control word 2) and the word count register (control word 3).  The upper
3060    select codes are used to configure the service select register (control word
3061    1) and to activate and terminate the transfer.
3062 
3063    There are differences in the implementations of the memory address and word
3064    count registers among the various cards.  The 12607B (2114) supports 14-bit
3065    addresses and 13-bit word counts.  The 12578A (2115/6) supports 15-bit
3066    addresses and 14-bit word counts.  The 12895A (2100) and 12897B (1000)
3067    support 15-bit addresses and 16-bit word counts.
3068 
3069    Implementation notes:
3070 
3071     1. Because the I/O bus floats to zero on 211x computers, an IOI (read word
3072        count) returns zeros in the unused bit locations, even though the word
3073        count is a negative value.
3074 
3075     2. Select codes 2 and 3 cannot interrupt, so there is no SIR handler.
3076 */
3077 
dmasio(DIB * dibptr,IOCYCLE signal_set,uint32 stat_data)3078 uint32 dmasio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
3079 {
3080 const CHANNEL ch = (CHANNEL) dibptr->card_index;        /* DMA channel number */
3081 uint16 data;
3082 IOSIGNAL signal;
3083 IOCYCLE  working_set = signal_set;                      /* no SIR handler needed */
3084 
3085 while (working_set) {
3086     signal = IONEXT (working_set);                      /* isolate next signal */
3087 
3088     switch (signal) {                                   /* dispatch I/O signal */
3089 
3090         case ioIOI:                                     /* I/O data input */
3091             if (UNIT_CPU_MODEL == UNIT_2114)            /* 2114? */
3092                 data = dma [ch].cw3 & 0017777;          /* only 13-bit count */
3093             else if (UNIT_CPU_TYPE == UNIT_TYPE_211X)   /* 2115/2116? */
3094                 data = dma [ch].cw3 & 0037777;          /* only 14-bit count */
3095             else                                        /* other models */
3096                 data = dma [ch].cw3;                    /* rest use full value */
3097 
3098             stat_data = IORETURN (SCPE_OK, data);       /* merge status and remaining word count */
3099             break;
3100 
3101         case ioIOO:                                                 /* I/O data output */
3102             if (dma [ch].select)                                    /* word count selected? */
3103                 dma [ch].cw3 = IODATA (stat_data);                  /* save count */
3104             else                                                    /* memory address selected */
3105                 if (UNIT_CPU_MODEL == UNIT_2114)                    /* 2114? */
3106                     dma [ch].cw2 = IODATA (stat_data) & 0137777;    /* only 14-bit address */
3107                 else                                                /* other models */
3108                     dma [ch].cw2 = IODATA (stat_data);              /* full address stored */
3109             break;
3110 
3111         case ioCLC:                                     /* clear control flip-flop */
3112             dma [ch].select = CLEAR;                    /* set for word count access */
3113             break;
3114 
3115         case ioSTC:                                     /* set control flip-flop */
3116             dma [ch].select = SET;                      /* set for memory address access */
3117             break;
3118 
3119         default:                                        /* all other signals */
3120             break;                                      /*   are ignored */
3121         }
3122 
3123     working_set = working_set & ~signal;                /* remove current signal from set */
3124     }
3125 
3126 return stat_data;
3127 }
3128 
3129 
3130 /* DMA/DCPC primary (SC 6/7) I/O signal handler.
3131 
3132    The primary DMA control interface and the service select register are
3133    manipulated through select codes 6 and 7.  Each channel has transfer enable,
3134    control, flag, and flag buffer flip-flops.  Transfer enable must be set via
3135    STC to start DMA.  Control is used only to enable the DMA completion
3136    interrupt; it is set by STC and cleared by CLC.  Flag and flag buffer are set
3137    at transfer completion to signal an interrupt.  STF may be issued to abort a
3138    transfer in progress.
3139 
3140    Again, there are hardware differences between the various DMA cards.  The
3141    12607B (2114) stores only bits 2-0 of the select code and interprets them as
3142    select codes 10-16 (SRQ17 is not decoded).  The 12578A (2115/16), 12895A
3143    (2100), and 12897B (1000) support the full range of select codes (10-77
3144    octal).
3145 
3146    Implementation notes:
3147 
3148      1. An IOI reads the floating S-bus (high on the 1000, low on the 21xx).
3149 
3150      2. The CRS signal on the DMA card resets the secondary (SC 2/3) select
3151         flip-flops.  Under simulation, ioCRS is dispatched to select codes 6 and
3152         up, so we reset the flip-flop in our handler.
3153 
3154      3. The 12578A supports byte-sized transfers by setting bit 14.  Bit 14 is
3155         ignored by all other DMA cards, which support word transfers only.
3156         Under simulation, we use a byte-packing/unpacking register to hold one
3157         byte while the other is read or written during the DMA cycle.
3158 */
3159 
dmapio(DIB * dibptr,IOCYCLE signal_set,uint32 stat_data)3160 uint32 dmapio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
3161 {
3162 const CHANNEL ch = (CHANNEL) dibptr->card_index;        /* DMA channel number */
3163 uint16 data;
3164 IOSIGNAL signal;
3165 IOCYCLE  working_set = IOADDSIR (signal_set);           /* add ioSIR if needed */
3166 
3167 while (working_set) {
3168     signal = IONEXT (working_set);                      /* isolate next signal */
3169 
3170     switch (signal) {                                   /* dispatch I/O signal */
3171 
3172         case ioCLF:                                     /* clear flag flip-flop */
3173             dma [ch].flag = dma [ch].flagbuf = CLEAR;   /* clear flag and flag buffer */
3174             break;
3175 
3176         case ioSTF:                                     /* set flag flip-flop */
3177         case ioENF:                                     /* enable flag */
3178             dma [ch].flag = dma [ch].flagbuf = SET;     /* set flag and flag buffer */
3179             dma [ch].xferen = CLEAR;                    /* clear transfer enable to abort transfer */
3180             break;
3181 
3182         case ioSFC:                                     /* skip if flag is clear */
3183             setstdSKF (dma [ch]);                       /* skip if transfer in progress */
3184             break;
3185 
3186         case ioSFS:                                     /* skip if flag is set */
3187             setstdSKF (dma [ch]);                       /* skip if transfer is complete */
3188             break;
3189 
3190         case ioIOI:                                     /* I/O data input */
3191             if (UNIT_CPU_TYPE == UNIT_TYPE_1000)        /* 1000? */
3192                 stat_data = IORETURN (SCPE_OK, DMASK);  /* return all ones */
3193             else                                        /* other models */
3194                 stat_data = IORETURN (SCPE_OK, 0);      /* return all zeros */
3195             break;
3196 
3197         case ioIOO:                                     /* I/O data output */
3198             data = IODATA (stat_data);                  /* clear supplied status */
3199 
3200             if (UNIT_CPU_MODEL == UNIT_2114)            /* 12607? */
3201                 dma [ch].cw1 = (data & 0137707) | 010;  /* mask SC, convert to 10-17 */
3202             else if (UNIT_CPU_TYPE == UNIT_TYPE_211X)   /* 12578? */
3203                 dma [ch].cw1 = data;                    /* store full select code, flags */
3204             else                                        /* 12895, 12897 */
3205                 dma [ch].cw1 = data & ~DMA1_PB;         /* clip byte-packing flag */
3206             break;
3207 
3208        case ioPOPIO:                                    /* power-on preset to I/O */
3209             dma [ch].flag = dma [ch].flagbuf = SET;     /* set flag and flag buffer */
3210             break;
3211 
3212         case ioCRS:                                     /* control reset */
3213             dma [ch].xferen = CLEAR;                    /* clear transfer enable */
3214             dma [ch].select = CLEAR;                    /* set secondary for word count access */
3215                                                         /* fall into CLC handler */
3216 
3217         case ioCLC:                                     /* clear control flip-flop */
3218             dma [ch].control = CLEAR;                   /* clear control */
3219             break;
3220 
3221         case ioSTC:                                     /* set control flip-flop */
3222             dma [ch].packer = 0;                        /* clear packing register */
3223             dma [ch].xferen = dma [ch].control = SET;   /* set transfer enable and control */
3224             break;
3225 
3226         case ioSIR:                                     /* set interrupt request */
3227             setstdPRL (dma [ch]);
3228             setstdIRQ (dma [ch]);
3229             break;
3230 
3231         case ioIAK:                                     /* interrupt acknowledge */
3232             dma [ch].flagbuf = CLEAR;                   /* clear flag buffer */
3233             break;
3234 
3235         default:                                        /* all other signals */
3236             break;                                      /*   are ignored */
3237         }
3238 
3239     working_set = working_set & ~signal;                /* remove current signal from set */
3240     }
3241 
3242 return stat_data;
3243 }
3244 
3245 
3246 /* Unassigned select code I/O signal handler.
3247 
3248    The 21xx/1000 I/O structure requires that no empty slots exist between
3249    interface cards.  This is due to the hardware priority chaining (PRH/PRL).
3250    If it is necessary to leave unused I/O slots, HP 12777A Priority Jumper Cards
3251    must be installed in them to maintain priority continuity.
3252 
3253    Under simulation, every unassigned I/O slot behaves as though a 12777A were
3254    resident.
3255 
3256    Implementation notes:
3257 
3258      1. For select codes < 10 octal, an IOI reads the floating S-bus (high on
3259         the 1000, low on the 21xx).  For select codes >= 10 octal, an IOI reads
3260         the floating I/O bus (low on all machines).
3261 
3262      2. If "stop_dev" is TRUE, then the simulator will stop when an unassigned
3263         device is accessed.
3264 */
3265 
nullio(DIB * dibptr,IOCYCLE signal_set,uint32 stat_data)3266 uint32 nullio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
3267 {
3268 uint16 data = 0;
3269 IOSIGNAL signal;
3270 IOCYCLE  working_set = signal_set;                      /* no SIR handler needed */
3271 
3272 while (working_set) {
3273     signal = IONEXT (working_set);                      /* isolate next signal */
3274 
3275     switch (signal) {                                   /* dispatch I/O signal */
3276 
3277         case ioIOI:                                     /* I/O data input */
3278             if ((dibptr->select_code < VARDEV) &&       /* internal device */
3279                 (UNIT_CPU_TYPE == UNIT_TYPE_1000))      /*   and 1000? */
3280                 data = DMASK;                           /* return all ones */
3281             else                                        /* external or other model */
3282                 data = 0;                               /* return all zeros */
3283             break;
3284 
3285         default:                                        /* all other signals */
3286             break;                                      /*   are ignored */
3287         }
3288 
3289     working_set = working_set & ~signal;                /* remove current signal from set */
3290     }
3291 
3292 return IORETURN (stop_dev, data);                       /* flag missing device */
3293 }
3294 
3295 
3296 /* DMA cycle routine.
3297 
3298    This routine performs one DMA input or output cycle using the indicated DMA
3299    channel number and DMS map.  When the transfer word count reaches zero, the
3300    flag is set on the corresponding DMA channel to indicate completion.
3301 
3302    The 12578A card supports byte-packing.  If bit 14 in control word 1 is set,
3303    each transfer will involve one read/write from memory and two output/input
3304    operations in order to transfer sequential bytes to/from the device.
3305 
3306    DMA I/O cycles differ from programmed I/O cycles in that multiple I/O control
3307    backplane signals may be asserted simultaneously.  With programmed I/O, only
3308    CLF may be asserted with other signals, specifically with STC, CLC, SFS, SFC,
3309    IOI, or IOO.  With DMA, as many as five signals may be asserted concurrently.
3310 
3311    DMA I/O timing looks like this:
3312 
3313            ------------ Input ------------   ----------- Output ------------
3314      Sig    Normal Cycle      Last Cycle      Normal Cycle      Last Cycle
3315      ===   ==============   ==============   ==============   ==============
3316      IOI   T2-T3            T2-T3
3317      IOO                                        T3-T4            T3-T4
3318      STC *    T3                                T3               T3
3319      CLC *                     T3-T4                             T3-T4
3320      CLF      T3                                T3               T3
3321      EDT                          T4                                T4
3322 
3323       * if enabled by control word 1
3324 
3325    Under simulation, this routine dispatches one set of I/O signals per DMA
3326    cycle to the target device's I/O signal handler.  The signals correspond to
3327    the table above, except that all signals for a given cycle are concurrent
3328    (e.g., the last input cycle has IOI, EDT, and optionally CLC asserted, even
3329    though IOI and EDT are not coincident in hardware).  I/O signal handlers will
3330    process these signals sequentially, in the order listed above, before
3331    returning.
3332 
3333    Implementation notes:
3334 
3335     1. The address increment and word count decrement is done only after the I/O
3336        cycle has completed successfully.  This allows a failed transfer to be
3337        retried after correcting the I/O error.
3338 */
3339 
dma_cycle(CHANNEL ch,uint32 map)3340 static t_stat dma_cycle (CHANNEL ch, uint32 map)
3341 {
3342 const uint32 dev   = dma [ch].cw1 & I_DEVMASK;          /* device select code */
3343 const uint32 stc   = dma [ch].cw1 & DMA1_STC;           /* STC enable flag */
3344 const uint32 bytes = dma [ch].cw1 & DMA1_PB;            /* pack bytes flag */
3345 const uint32 clc   = dma [ch].cw1 & DMA1_CLC;           /* CLC enable flag */
3346 const uint32 MA    = dma [ch].cw2 & VAMASK;             /* memory address */
3347 const uint32 input = dma [ch].cw2 & DMA2_OI;            /* input flag */
3348 const uint32 even  = dma [ch].packer & DMA_OE;          /* odd/even packed byte flag */
3349 uint16 data;
3350 t_stat status;
3351 uint32 ioresult;
3352 IOCYCLE signals;
3353 
3354 if (bytes && !even || dma [ch].cw3 != DMASK) {          /* normal cycle? */
3355     if (input)                                          /* input cycle? */
3356         signals = ioIOI | ioCLF;                        /* assert IOI and CLF */
3357     else                                                /* output cycle */
3358         signals = ioIOO | ioCLF;                        /* assert IOO and CLF */
3359 
3360     if (stc)                                            /* STC wanted? */
3361         signals = signals | ioSTC;                      /* assert STC */
3362     }
3363 
3364 else {                                                  /* last cycle */
3365     if (input)                                          /* input cycle? */
3366         signals = ioIOI | ioEDT;                        /* assert IOI and EDT */
3367     else {                                              /* output cycle */
3368         signals = ioIOO | ioCLF | ioEDT;                /* assert IOO and CLF and EDT */
3369 
3370         if (stc)                                        /* STC wanted? */
3371             signals = signals | ioSTC;                  /* assert STC */
3372         }
3373 
3374     if (clc)                                            /* CLC wanted? */
3375         signals = signals | ioCLC;                      /* assert CLC */
3376     }
3377 
3378 if (input) {                                            /* input cycle? */
3379     ioresult = devdisp (dev, signals,                   /* do I/O input */
3380                         IORETURN (SCPE_OK, 0));
3381 
3382     status = IOSTATUS (ioresult);                       /* get cycle status */
3383 
3384     if (status == SCPE_OK) {                            /* good I/O cycle? */
3385         data = IODATA (ioresult);                       /* extract return data value */
3386 
3387         if (bytes) {                                    /* byte packing? */
3388             if (even) {                                 /* second byte? */
3389                 data = (dma [ch].packer << 8) |         /* merge stored byte */
3390                          (data & DMASK8);
3391                 WriteIO (MA, data, map);                /* store word data */
3392                 }
3393             else                                        /* first byte */
3394                 dma [ch].packer = (data & DMASK8);      /* save it */
3395 
3396             dma [ch].packer = dma [ch].packer ^ DMA_OE; /* flip odd/even bit */
3397             }
3398         else                                            /* no byte packing */
3399             WriteIO (MA, data, map);                    /* store word data */
3400         }
3401     }
3402 
3403 else {                                                  /* output cycle */
3404     if (bytes) {                                        /* byte packing? */
3405         if (even)                                       /* second byte? */
3406             data = dma [ch].packer & DMASK8;            /* retrieve it */
3407 
3408         else {                                          /* first byte */
3409             dma [ch].packer = ReadIO (MA, map);         /* read word data */
3410             data = (dma [ch].packer >> 8) & DMASK8;     /* get high byte */
3411             }
3412 
3413         dma [ch].packer = dma [ch].packer ^ DMA_OE;     /* flip odd/even bit */
3414         }
3415     else                                                /* no byte packing */
3416         data = ReadIO (MA, map);                        /* read word data */
3417 
3418     ioresult = devdisp (dev, signals,                   /* do I/O output */
3419                         IORETURN (SCPE_OK, data));
3420 
3421     status = IOSTATUS (ioresult);                       /* get cycle status */
3422     }
3423 
3424 if ((even || !bytes) && (status == SCPE_OK)) {          /* new byte or no packing and good xfer? */
3425     dma [ch].cw2 = input | (dma [ch].cw2 + 1) & VAMASK; /* increment address */
3426     dma [ch].cw3 = (dma [ch].cw3 + 1) & DMASK;          /* increment word count */
3427 
3428     if (dma [ch].cw3 == 0)                              /* end of transfer? */
3429         dmapio (dtab [DMA1 + ch], ioENF, 0);            /* set DMA channel flag */
3430     }
3431 
3432 return status;                                          /* return I/O status */
3433 }
3434 
3435 
3436 /* Reset routines.
3437 
3438    The reset routines are called to simulate either an initial power on
3439    condition or a front-panel PRESET button press.  For initial power on
3440    (corresponds to PON, POPIO, and CRS signal assertion in the CPU), the "P"
3441    command switch will be set.  For PRESET (corresponds to POPIO and CRS
3442    assertion), the switch will be clear.
3443 
3444    SCP delivers a power-on reset to all devices when the simulator is started.
3445    A RUN, BOOT, RESET, or RESET ALL command delivers a PRESET to all devices.  A
3446    RESET <dev> delivers a PRESET to a specific device.
3447 */
3448 
3449 
3450 /* CPU reset.
3451 
3452    If this is the first call after simulator startup, allocate the initial
3453    memory array, set the default CPU model, and install the default BBL.
3454 */
3455 
cpu_reset(DEVICE * dptr)3456 t_stat cpu_reset (DEVICE *dptr)
3457 {
3458 if (M == NULL) {                                        /* initial call after startup? */
3459     pcq_r = find_reg ("PCQ", NULL, dptr);               /* get PC queue pointer */
3460 
3461     if (pcq_r)                                          /* defined? */
3462         pcq_r->qptr = 0;                                /* initialize queue */
3463     else                                                /* not defined */
3464         return SCPE_IERR;                               /* internal error */
3465 
3466     M = (uint16 *) calloc (PASIZE, sizeof (uint16));    /* alloc mem */
3467 
3468     if (M == NULL)                                      /* alloc fail? */
3469         return SCPE_MEM;
3470     else {                                              /* do one-time init */
3471         MEMSIZE = 32768;                                /* set initial memory size */
3472         cpu_set_model (NULL, UNIT_2116, NULL, NULL);    /* set initial CPU model */
3473         SR = 001000;                                    /* select PTR boot ROM at SC 10 */
3474         cpu_boot (0, NULL);                             /* install loader for 2116 */
3475         cpu_set_ldr (NULL, FALSE, NULL, NULL);          /* disable loader (was enabled) */
3476         SR = 0;                                         /* clear S */
3477         sim_vm_post = &hp_post_cmd;                     /* set cmd post proc */
3478         sim_brk_types = ALL_BKPTS;                      /* register allowed breakpoint types */
3479         }
3480     }
3481 
3482 if (sim_switches & SWMASK ('P'))                        /* PON reset? */
3483     IOPOWERON (&cpu_dib);
3484 else                                                    /* PRESET */
3485     IOPRESET (&cpu_dib);
3486 
3487 sim_brk_dflt = SWMASK ('N');                            /* type is nomap as DMS is off */
3488 
3489 return SCPE_OK;
3490 }
3491 
3492 
3493 /* Memory protect reset */
3494 
mp_reset(DEVICE * dptr)3495 t_stat mp_reset (DEVICE *dptr)
3496 {
3497 IOPRESET (&mp_dib);                                     /* PRESET device (does not use PON) */
3498 
3499 mp_fence = 0;                                           /* clear fence register */
3500 mp_viol = 0;                                            /* clear violation register */
3501 
3502 return SCPE_OK;
3503 }
3504 
3505 
3506 /* DMA reset */
3507 
dma_reset(DEVICE * dptr)3508 t_stat dma_reset (DEVICE *dptr)
3509 {
3510 DIB *dibptr = (DIB *) dptr->ctxt;                       /* DIB pointer */
3511 const CHANNEL ch = (CHANNEL) dibptr->card_index;        /* DMA channel number */
3512 
3513 if (UNIT_CPU_MODEL != UNIT_2114)                        /* 2114 has only one channel */
3514     hp_enbdis_pair (dma_dptrs [ch],                     /* make specified channel */
3515                     dma_dptrs [ch ^ 1]);                /*   consistent with other channel */
3516 
3517 if (sim_switches & SWMASK ('P')) {                      /* power-on reset? */
3518     dma [ch].cw1 = 0;                                   /* clear control word registers */
3519     dma [ch].cw2 = 0;
3520     dma [ch].cw3 = 0;
3521     }
3522 
3523 IOPRESET (dibptr);                                      /* PRESET device (does not use PON) */
3524 
3525 dma [ch].packer = 0;                                    /* clear byte packer */
3526 
3527 return SCPE_OK;
3528 }
3529 
3530 
3531 /* Memory examine */
3532 
cpu_ex(t_value * vptr,t_addr addr,UNIT * uptr,int32 sw)3533 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
3534 {
3535 uint16 d;
3536 
3537 if ((sw & ALL_MAPMODES) && (dms_enb == 0))              /* req map with DMS off? */
3538     return SCPE_NOFNC;                                  /* command not allowed */
3539 
3540 addr = dms_cons (addr, sw);                             /* translate address as indicated */
3541 
3542 if (addr >= MEMSIZE)                                    /* beyond memory limits? */
3543     return SCPE_NXM;                                    /* non-existent memory */
3544 
3545 if ((sw & SIM_SW_REST) || (addr >= 2))                  /* restoring or memory access? */
3546     d = M[addr];                                        /* return memory value */
3547 else                                                    /* not restoring and A/B access */
3548     d = ABREG[addr];                                    /* return A/B register value */
3549 
3550 if (vptr != NULL)
3551     *vptr = d & DMASK;                                  /* store return value */
3552 return SCPE_OK;
3553 }
3554 
3555 /* Memory deposit */
3556 
cpu_dep(t_value val,t_addr addr,UNIT * uptr,int32 sw)3557 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
3558 {
3559 if ((sw & ALL_MAPMODES) && (dms_enb == 0))              /* req map with DMS off? */
3560     return SCPE_NOFNC;                                  /* command not allowed */
3561 
3562 addr = dms_cons (addr, sw);                             /* translate address as indicated */
3563 
3564 if (addr >= MEMSIZE)                                    /* beyond memory limits? */
3565     return SCPE_NXM;                                    /* non-existent memory */
3566 
3567 if ((sw & SIM_SW_REST) || (addr >= 2))                  /* restoring or memory access? */
3568     M[addr] = val & DMASK;                              /* store memory value */
3569 else                                                    /* not restoring and A/B access */
3570     ABREG[addr] = val & DMASK;                          /* store A/B register value */
3571 
3572 return SCPE_OK;
3573 }
3574 
3575 
3576 /* Make a pair of devices consistent */
3577 
hp_enbdis_pair(DEVICE * ccp,DEVICE * dcp)3578 void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp)
3579 {
3580 if (ccp->flags & DEV_DIS)
3581     dcp->flags = dcp->flags | DEV_DIS;
3582 else
3583     dcp->flags = dcp->flags & ~DEV_DIS;
3584 
3585 return;
3586 }
3587 
3588 
3589 /* VM command post-processor
3590 
3591    Update T register to contents of memory addressed by M register
3592    if M register has changed. */
3593 
hp_post_cmd(t_bool from_scp)3594 void hp_post_cmd (t_bool from_scp)
3595 {
3596 if (MR != saved_MR) {                                   /* M changed since last update? */
3597     saved_MR = MR;
3598     TR = ReadTAB (MR);                                  /* sync T with new M */
3599     }
3600 return;
3601 }
3602 
3603 
3604 /* Test for device conflict */
3605 
dev_conflict(void)3606 static t_bool dev_conflict (void)
3607 {
3608 DEVICE *dptr;
3609 DIB *dibptr;
3610 uint32 i, j, k;
3611 t_bool is_conflict = FALSE;
3612 uint32 conflicts[MAXDEV + 1] = { 0 };
3613 
3614 for (i = 0; (dptr = sim_devices[i]); i++) {
3615     dibptr = (DIB *) dptr->ctxt;
3616     if (dibptr && !(dptr->flags & DEV_DIS))
3617         if (++conflicts[dibptr->select_code] > 1)
3618             is_conflict = TRUE;
3619     }
3620 
3621 if (is_conflict) {
3622     sim_ttcmd();
3623     for (i = 0; i <= MAXDEV; i++) {
3624         if (conflicts[i] > 1) {
3625             k = conflicts[i];
3626 
3627             printf ("Select code %o conflict:", i);
3628 
3629             if (sim_log)
3630                 fprintf (sim_log, "Select code %o conflict:", i);
3631 
3632             for (j = 0; (dptr = sim_devices[j]); j++) {
3633                 dibptr = (DIB *) dptr->ctxt;
3634                 if (dibptr && !(dptr->flags & DEV_DIS) && (i == dibptr->select_code)) {
3635                     if (k < conflicts[i]) {
3636                         printf (" and");
3637 
3638                         if (sim_log)
3639                             fputs (" and", sim_log);
3640                         }
3641 
3642                     printf (" %s", sim_dname (dptr));
3643 
3644                     if (sim_log)
3645                         fprintf (sim_log, " %s", sim_dname (dptr));
3646 
3647                     k = k - 1;
3648 
3649                     if (k == 0) {
3650                         putchar ('\n');
3651 
3652                         if (sim_log)
3653                             fputc ('\n', sim_log);
3654                         break;
3655                         }
3656                     }
3657                 }
3658             }
3659         }
3660     }
3661 return is_conflict;
3662 }
3663 
3664 
3665 /* Change CPU memory size.
3666 
3667    On a 21xx, move the current loader to the top of the new memory size.  Then
3668    clear "non-existent memory" so that reads return zero, per spec.
3669 
3670    Validation:
3671    - New size <= maximum size for current CPU.
3672    - New size a positive multiple of 4K (progamming error if not).
3673    - If new size < old size, truncation accepted.
3674 */
3675 
cpu_set_size(UNIT * uptr,int32 new_size,char * cptr,void * desc)3676 t_stat cpu_set_size (UNIT *uptr, int32 new_size, char *cptr, void *desc)
3677 {
3678 int32 mc = 0;
3679 uint32 i;
3680 uint32 model = CPU_MODEL_INDEX;                         /* current CPU model index */
3681 uint32 old_size = MEMSIZE;                              /* current memory size */
3682 
3683 if ((uint32) new_size > cpu_features[model].maxmem)
3684     return SCPE_NOFNC;                                  /* mem size unsupported */
3685 
3686 if ((new_size <= 0) || (new_size > PASIZE) || ((new_size & 07777) != 0))
3687     return SCPE_NXM;                                    /* invalid size (prog err) */
3688 
3689 if (!(sim_switches & SWMASK ('F'))) {                   /* force truncation? */
3690     for (i = new_size; i < MEMSIZE; i++)                /* check truncated memory */
3691         mc = mc | M[i];                                 /*   for content */
3692 
3693     if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
3694         return SCPE_INCOMP;
3695     }
3696 
3697 if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) {              /* 21xx CPU? */
3698     cpu_set_ldr (uptr, FALSE, NULL, NULL);              /* save loader to shadow RAM */
3699     MEMSIZE = new_size;                                 /* set new memory size */
3700     fwanxm = MEMSIZE - IBL_LNT;                         /* reserve memory for loader */
3701     }
3702 else                                                    /* loader unsupported */
3703     fwanxm = MEMSIZE = new_size;                        /* set new memory size */
3704 
3705 for (i = fwanxm; i < old_size; i++)                     /* zero non-existent memory */
3706     M[i] = 0;
3707 
3708 return SCPE_OK;
3709 }
3710 
3711 
3712 /* Change CPU models.
3713 
3714    For convenience, MP and DMA are typically enabled if available; they may be
3715    disabled subsequently if desired.  Note that the 2114 supports only one DMA
3716    channel (channel 1).  All other models support two channels.
3717 
3718    Validation:
3719    - Sets standard equipment and convenience features.
3720    - Changes DMA device name to DCPC if 1000 is selected.
3721    - Enforces maximum memory allowed (doesn't change otherwise).
3722    - Disables loader on 21xx machines.
3723 */
3724 
cpu_set_model(UNIT * uptr,int32 new_model,char * cptr,void * desc)3725 t_stat cpu_set_model (UNIT *uptr, int32 new_model, char *cptr, void *desc)
3726 {
3727 uint32 old_family = UNIT_CPU_FAMILY;                    /* current CPU type */
3728 uint32 new_family = new_model & UNIT_FAMILY_MASK;       /* new CPU family */
3729 uint32 new_index  = new_model >> UNIT_V_CPU;            /* new CPU model index */
3730 uint32 new_memsize;
3731 t_stat result;
3732 
3733 cpu_unit.flags = cpu_unit.flags & ~UNIT_OPTS |          /* set typical features */
3734                  cpu_features[new_index].typ & UNIT_OPTS;   /* mask pseudo-opts */
3735 
3736 
3737 if (cpu_features[new_index].typ & UNIT_MP)              /* MP in typ config? */
3738     mp_dev.flags = mp_dev.flags & ~DEV_DIS;             /* enable it */
3739 else
3740     mp_dev.flags = mp_dev.flags |  DEV_DIS;             /* disable it */
3741 
3742 if (cpu_features[new_index].opt & UNIT_MP)              /* MP an option? */
3743     mp_dev.flags = mp_dev.flags |  DEV_DISABLE;         /* make it alterable */
3744 else
3745     mp_dev.flags = mp_dev.flags & ~DEV_DISABLE;         /* make it unalterable */
3746 
3747 
3748 if (cpu_features[new_index].typ & UNIT_DMA) {           /* DMA in typ config? */
3749     dma1_dev.flags = dma1_dev.flags & ~DEV_DIS;         /* enable DMA channel 1 */
3750 
3751     if (new_model == UNIT_2114)                         /* 2114 has only one channel */
3752         dma2_dev.flags = dma2_dev.flags |  DEV_DIS;     /* disable channel 2 */
3753     else                                                /* all others have two channels */
3754         dma2_dev.flags = dma2_dev.flags & ~DEV_DIS;     /* enable it */
3755     }
3756 else {
3757     dma1_dev.flags = dma1_dev.flags | DEV_DIS;          /* disable channel 1 */
3758     dma2_dev.flags = dma2_dev.flags | DEV_DIS;          /* disable channel 2 */
3759     }
3760 
3761 if (cpu_features[new_index].opt & UNIT_DMA) {           /* DMA an option? */
3762     dma1_dev.flags = dma1_dev.flags |  DEV_DISABLE;     /* make it alterable */
3763 
3764     if (new_model == UNIT_2114)                         /* 2114 has only one channel */
3765         dma2_dev.flags = dma2_dev.flags & ~DEV_DISABLE; /* make it unalterable */
3766     else                                                /* all others have two channels */
3767         dma2_dev.flags = dma2_dev.flags |  DEV_DISABLE; /* make it alterable */
3768     }
3769 else {
3770     dma1_dev.flags = dma1_dev.flags & ~DEV_DISABLE;     /* make it unalterable */
3771     dma2_dev.flags = dma2_dev.flags & ~DEV_DISABLE;     /* make it unalterable */
3772     }
3773 
3774 
3775 if ((old_family == UNIT_FAMILY_1000) &&                 /* if current family is 1000 */
3776     (new_family == UNIT_FAMILY_21XX)) {                 /* and new family is 21xx */
3777     deassign_device (&dma1_dev);                        /* delete DCPC names */
3778     deassign_device (&dma2_dev);
3779     }
3780 else if ((old_family == UNIT_FAMILY_21XX) &&            /* if current family is 21xx */
3781          (new_family == UNIT_FAMILY_1000)) {            /* and new family is 1000 */
3782     assign_device (&dma1_dev, "DCPC1");                 /* change DMA device name */
3783     assign_device (&dma2_dev, "DCPC2");                 /* to DCPC for familiarity */
3784     }
3785 
3786 if ((MEMSIZE == 0) ||                                   /* current mem size not set? */
3787     (MEMSIZE > cpu_features[new_index].maxmem))         /* current mem size too large? */
3788     new_memsize = cpu_features[new_index].maxmem;       /* set it to max supported */
3789 else
3790     new_memsize = MEMSIZE;                              /* or leave it unchanged */
3791 
3792 result = cpu_set_size (uptr, new_memsize, NULL, NULL);  /* set memory size */
3793 
3794 if (result == SCPE_OK) {                                /* memory change OK? */
3795     if (new_family == UNIT_FAMILY_21XX)                 /* 21xx CPU? */
3796         fwanxm = MEMSIZE - IBL_LNT;                     /* reserve memory for loader */
3797     else
3798         fwanxm = MEMSIZE;                               /* loader reserved only for 21xx */
3799   }
3800 return result;
3801 }
3802 
3803 
3804 /* Display the CPU model and optional loader status.
3805 
3806    Loader status is displayed for 21xx models and suppressed for 1000 models.
3807 */
3808 
cpu_show_model(FILE * st,UNIT * uptr,int32 val,void * desc)3809 t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc)
3810 {
3811 fputs ((char *) desc, st);                              /* write model name */
3812 
3813 if (UNIT_CPU_FAMILY == UNIT_FAMILY_21XX) {              /* valid only for 21xx */
3814     if (fwanxm < MEMSIZE)                               /* loader area non-existent? */
3815         fputs (", loader disabled", st);                /* yes, so access disabled */
3816     else
3817         fputs (", loader enabled", st);                 /* no, so access enabled */
3818   }
3819 return SCPE_OK;
3820 }
3821 
3822 
3823 /* Set a CPU option.
3824 
3825    Validation:
3826    - Checks that the current CPU model supports the option selected.
3827    - If CPU is 1000-F, ensures that VIS and IOP are mutually exclusive.
3828    - If CPU is 2100, ensures that FP/FFP and IOP are mutually exclusive.
3829    - If CPU is 2100, ensures that FP is enabled if FFP enabled
3830      (FP is required for FFP installation).
3831 */
3832 
cpu_set_opt(UNIT * uptr,int32 option,char * cptr,void * desc)3833 t_stat cpu_set_opt (UNIT *uptr, int32 option, char *cptr, void *desc)
3834 {
3835 uint32 model = CPU_MODEL_INDEX;                         /* current CPU model index */
3836 
3837 if ((cpu_features[model].opt & option) == 0)            /* option supported? */
3838     return SCPE_NOFNC;                                  /* no */
3839 
3840 if (UNIT_CPU_TYPE == UNIT_TYPE_2100) {
3841     if ((option == UNIT_FP) || (option == UNIT_FFP))    /* 2100 IOP and FP/FFP options */
3842         uptr->flags = uptr->flags & ~UNIT_IOP;          /* are mutually exclusive */
3843     else if (option == UNIT_IOP)
3844         uptr->flags = uptr->flags & ~(UNIT_FP | UNIT_FFP);
3845 
3846     if (option == UNIT_FFP)                             /* 2100 FFP option requires FP */
3847         uptr->flags = uptr->flags | UNIT_FP;
3848     }
3849 
3850 else if (UNIT_CPU_MODEL == UNIT_1000_F) {
3851     if (option == UNIT_VIS)                             /* 1000-F IOP and VIS options */
3852         uptr->flags = uptr->flags & ~UNIT_IOP;          /* are mutually exclusive */
3853     else if (option == UNIT_IOP)
3854         uptr->flags = uptr->flags & ~UNIT_VIS;
3855   }
3856 return SCPE_OK;
3857 }
3858 
3859 
3860 /* Clear a CPU option.
3861 
3862    Validation:
3863    - Checks that the current CPU model supports the option selected.
3864    - Clears flag from unit structure (we are processing MTAB_XTD entries).
3865    - If CPU is 2100, ensures that FFP is disabled if FP disabled
3866      (FP is required for FFP installation).
3867 */
3868 
cpu_clr_opt(UNIT * uptr,int32 option,char * cptr,void * desc)3869 t_bool cpu_clr_opt (UNIT *uptr, int32 option, char *cptr, void *desc)
3870 {
3871 uint32 model = CPU_MODEL_INDEX;                         /* current CPU model index */
3872 
3873 if ((cpu_features[model].opt & option) == 0)            /* option supported? */
3874     return SCPE_NOFNC;                                  /* no */
3875 
3876 uptr->flags = uptr->flags & ~option;                    /* disable option */
3877 
3878 if ((UNIT_CPU_TYPE == UNIT_TYPE_2100) &&                /* disabling 2100 FP? */
3879     (option == UNIT_FP))
3880     uptr->flags = uptr->flags & ~UNIT_FFP;              /* yes, so disable FFP too */
3881 
3882 return SCPE_OK;
3883 }
3884 
3885 
3886 /* 21xx loader enable/disable function.
3887 
3888    The 21xx CPUs store their initial binary loaders in the last 64 words of
3889    available memory.  This memory is protected by a LOADER ENABLE switch on the
3890    front panel.  When the switch is off (disabled), main memory effectively ends
3891    64 locations earlier, i.e., the loader area is treated as non-existent.
3892    Because these are core machines, the loader is retained when system power is
3893    off.
3894 
3895    1000 CPUs do not have a protected loader feature.  Instead, loaders are
3896    stored in PROMs and are copied into main memory for execution by the IBL
3897    switch.
3898 
3899    Under simulation, we keep both a total configured memory size (MEMSIZE) and a
3900    current configured memory size (fwanxm = "first word address of non-existent
3901    memory").  When the two are equal, the loader is enabled.  When the current
3902    size is less than the total size, the loader is disabled.
3903 
3904    Disabling the loader copies the last 64 words to a shadow array, zeros the
3905    corresponding memory, and decreases the last word of addressable memory by
3906    64.  Enabling the loader reverses this process.
3907 
3908    Disabling may be done manually by user command or automatically when a halt
3909    instruction is executed.  Enabling occurs only by user command.  This differs
3910    slightly from actual machine operation, which additionally disables the
3911    loader when a manual halt is performed.  We do not do this to allow
3912    breakpoints within and single-stepping through the loaders.
3913 */
3914 
cpu_set_ldr(UNIT * uptr,int32 enable,char * cptr,void * desc)3915 t_stat cpu_set_ldr (UNIT *uptr, int32 enable, char *cptr, void *desc)
3916 {
3917 static BOOT_ROM loader;
3918 int32 i;
3919 t_bool is_enabled = (fwanxm == MEMSIZE);
3920 
3921 if ((UNIT_CPU_FAMILY != UNIT_FAMILY_21XX) ||            /* valid only for 21xx */
3922     (MEMSIZE == 0))                                     /* and for initialized memory */
3923     return SCPE_NOFNC;
3924 
3925 if (is_enabled && (enable == 0)) {                      /* disable loader? */
3926     fwanxm = MEMSIZE - IBL_LNT;                         /* decrease available memory */
3927     for (i = 0; i < IBL_LNT; i++) {                     /* copy loader */
3928         loader[i] = M[fwanxm + i];                      /* from memory */
3929         M[fwanxm + i] = 0;                              /* and zero location */
3930         }
3931     }
3932 
3933 else if ((!is_enabled) && (enable == 1)) {              /* enable loader? */
3934     for (i = 0; i < IBL_LNT; i++)                       /* copy loader */
3935         M[fwanxm + i] = loader[i];                      /* to memory */
3936     fwanxm = MEMSIZE;                                   /* increase available memory */
3937     }
3938 
3939 return SCPE_OK;
3940 }
3941 
3942 
3943 /* Idle enable/disable */
3944 
cpu_set_idle(UNIT * uptr,int32 option,char * cptr,void * desc)3945 t_stat cpu_set_idle (UNIT *uptr, int32 option, char *cptr, void *desc)
3946 {
3947     if (option)
3948         return sim_set_idle (uptr, 10, NULL, NULL);
3949     else
3950         return sim_clr_idle (uptr, 0, NULL, NULL);
3951 }
3952 
3953 
3954 /* Idle display */
3955 
cpu_show_idle(FILE * st,UNIT * uptr,int32 val,void * desc)3956 t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc)
3957 {
3958     return sim_show_idle (st, uptr, val, desc);
3959 }
3960 
3961 
3962 /* IBL routine (CPU boot) */
3963 
cpu_boot(int32 unitno,DEVICE * dptr)3964 t_stat cpu_boot (int32 unitno, DEVICE *dptr)
3965 {
3966 extern const BOOT_ROM ptr_rom, dq_rom, ms_rom, ds_rom;
3967 int32 dev = (SR >> IBL_V_DEV) & I_DEVMASK;
3968 int32 sel = (SR >> IBL_V_SEL) & IBL_M_SEL;
3969 
3970 if (dev < 010)
3971     return SCPE_NOFNC;
3972 
3973 switch (sel) {
3974 
3975     case 0:                                             /* PTR boot */
3976         ibl_copy (ptr_rom, dev);
3977         break;
3978 
3979     case 1:                                             /* DP/DQ boot */
3980         ibl_copy (dq_rom, dev);
3981         break;
3982 
3983     case 2:                                             /* MS boot */
3984         ibl_copy (ms_rom, dev);
3985         break;
3986 
3987     case 3:                                             /* DS boot */
3988         ibl_copy (ds_rom, dev);
3989         break;
3990         }
3991 
3992 return SCPE_OK;
3993 }
3994 
3995 
3996 /* IBL boot ROM copy
3997 
3998    - Use memory size to set the initial PC and base of the boot area
3999    - Copy boot ROM to memory, updating I/O instructions
4000    - Place 2s complement of boot base in last location
4001 
4002    Notes:
4003    - SR settings are done by the caller
4004    - Boot ROMs must be assembled with a device code of 10 (10 and 11 for
4005      devices requiring two codes)
4006 */
4007 
ibl_copy(const BOOT_ROM rom,int32 dev)4008 t_stat ibl_copy (const BOOT_ROM rom, int32 dev)
4009 {
4010 int32 i;
4011 uint16 wd;
4012 
4013 cpu_set_ldr (NULL, TRUE, NULL, NULL);                   /* enable loader (ignore errors) */
4014 
4015 if (dev < 010)                                          /* valid device? */
4016     return SCPE_ARG;
4017 
4018 PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK;              /* start at mem top */
4019 
4020 for (i = 0; i < IBL_LNT; i++) {                         /* copy bootstrap */
4021     wd = rom[i];                                        /* get word */
4022 
4023     if (((wd & I_NMRMASK) == I_IO) &&                   /* IO instruction? */
4024         ((wd & I_DEVMASK) >= 010) &&                    /* dev >= 10? */
4025         (I_GETIOOP (wd) != soHLT))                      /* not a HALT? */
4026         M[PC + i] = (wd + (dev - 010)) & DMASK;         /* change dev code */
4027 
4028     else                                                /* leave unchanged */
4029         M[PC + i] = wd;
4030     }
4031 
4032 M[PC + IBL_DPC] = (M[PC + IBL_DPC] + (dev - 010)) & DMASK;  /* patch DMA ctrl */
4033 M[PC + IBL_END] = (~PC + 1) & DMASK;                        /* fill in start of boot */
4034 return SCPE_OK;
4035 }
4036