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