1 /* id16_cpu.c: Interdata 16b CPU simulator
3 Copyright (c) 2000-2007, Robert M. Supnik
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
28 28-Apr-07 RMS Removed clock initialization
29 27-Oct-06 RMS Added idle support
30 Removed separate PASLA clock
31 06-Feb-06 RMS Fixed bug in DH (found by Mark Hittinger)
32 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
33 25-Aug-05 RMS Fixed DH integer overflow cases
34 16-Aug-05 RMS Fixed C++ declaration and cast problems
35 10-Mar-05 RMS Fixed bug in show history routine (from Mark Hittinger)
36 Revised examine/deposit to do words rather than bytes
37 07-Nov-04 RMS Added instruction history
38 22-Sep-03 RMS Added additional instruction decode types
39 07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato)
41 The register state for the Interdata 16b CPU is:
43 R[0:F]<0:15> general registers
44 F[0:7]<0:31> single precision floating point registers
45 D[0:7]<0:63> double precision floating point registers
46 PSW<0:31> processor status word, including
47 STAT<0:11> status flags
48 CC<0:3> condition codes
49 PC<0:15> program counter
50 int_req[8]<0:31> interrupt requests
51 int_enb[8]<0:31> interrupt enables
53 The Interdata 16b systems have four instruction formats: register to
54 register, short format, register to memory, and register to storage.
57 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
58 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
59 | op | R1 | R2 | register-register
60 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
62 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
63 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
64 | op | R1 | N | short format
65 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
67 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
68 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
69 | op | R1 | RX | register-memory
70 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
72 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
74 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
75 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
76 | op | R1 | RX | register-storage
77 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
79 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
81 For register-memory and register-storage instructions, an effective
82 address is calculated as follows:
84 effective addr = address + RX (if RX > 0)
86 Register-memory instructions can access an address space of 64K bytes.
88 The Interdata 16b product line had many different models, with varying
91 instruction group model = 3 4 5 70 80 716 816 816E
92 base group (61) y y y y y y y y
93 AL, LM, STM (3) - y y y y y y y
94 single prec fp (13) - y y y y y y y
95 model 5 group (36) - - y y y y y y
96 double prec fp (17) - - - - - - y y
97 memory extension (4) - - - - - - - y
99 This allows the most common CPU options to be covered by just five
100 model selections: I3, I4, I5/70/80/716, I816, and I816E. Variations
101 within a model (e.g., 816 with no floating point or just single
102 precision floating point) are not implemented.
104 The I3 kept its general registers in memory; this is not simulated.
105 Single precision (only) floating point was implemented in microcode,
106 did not have a guard digit, and kept the floating point registers in
107 memory. Double precision floating point was implemented in hardware,
108 provided a guard digit for single precision (but not double), and
109 kept the floating point registers in hardware.
111 This routine is the instruction decode routine for the Interdata CPU.
112 It is called from the simulator control program to execute
113 instructions in simulated memory, starting at the simulated PC.
114 It runs until 'reason' is set non-zero.
118 1. Reasons to stop. The simulator can be stopped by:
121 breakpoint encountered
122 wait state and no I/O outstanding
124 I/O error in I/O simulator
126 2. Interrupts. Each device has an interrupt armed flag, an interrupt
127 request flag, and an interrupt enabled flag. To facilitate evaluation,
128 all interrupt requests are kept in int_req, and all enables in int_enb.
129 Interrupt armed flags are local to devices. If external interrupts are
130 enabled in the PSW, and a request is pending, an interrupt occurs.
132 3. Non-existent memory. On the Interdata 16b, reads to non-existent
133 memory return zero, and writes are ignored. In the simulator, the
134 largest possible memory is instantiated and initialized to zero.
135 Thus, only writes need be checked against actual memory size.
137 4. Adding I/O devices. These modules must be modified:
139 id_defs.h add device interrupt definitions
140 id16_sys.c add sim_devices table entry
145 #define PCQ_SIZE 64 /* must be 2**n */
146 #define PCQ_MASK (PCQ_SIZE - 1)
147 #define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC
148 #define VAMASK VAMASK16
149 #define VA_S1 0x8000 /* S0/S1 flag */
151 #define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */
152 #define UNIT_V_ID4 (UNIT_V_UF + 1)
153 #define UNIT_V_716 (UNIT_V_UF + 2)
154 #define UNIT_V_816 (UNIT_V_UF + 3)
155 #define UNIT_V_816E (UNIT_V_UF + 4)
156 #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
157 #define UNIT_ID4 (1 << UNIT_V_ID4)
158 #define UNIT_716 (1 << UNIT_V_716)
159 #define UNIT_816 (1 << UNIT_V_816)
160 #define UNIT_816E (1 << UNIT_V_816E)
161 #define UNIT_TYPE (UNIT_ID4 | UNIT_716 | UNIT_816 | UNIT_816E)
164 #define HIST_MAX 65536
176 #define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP)
177 #define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | 0xFFFF8000)): \
178 ((int32) ((x) & 0x7FFF)))
179 #define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \
180 else if (x) cc = CC_G; \
182 #define CC_GL_32(x) if ((x) & SIGN32) cc = CC_L; \
183 else if (x) cc = CC_G; \
185 #define BUILD_PSW(x) (((PSW & ~CC_MASK) | (x)) & psw_mask)
186 #define CPU_x16 (cpu_unit.flags & (UNIT_716 | UNIT_816 | UNIT_816E))
188 uint32 GREG
[16] = { 0 }; /* general registers */
189 uint16
*M
= NULL
; /* memory */
190 uint32
*R
= &GREG
[0]; /* register set ptr */
191 uint32 F
[8] = { 0 }; /* sp fp registers */
192 dpr_t D
[8] = { 0 }; /* dp fp registers */
193 uint32 PSW
= 0; /* processor status word */
194 uint32 psw_mask
= PSW_x16
; /* PSW mask */
195 uint32 PC
= 0; /* program counter */
196 uint32 SR
= 0; /* switch register */
197 uint32 DR
= 0; /* display register */
198 uint32 DRX
= 0; /* display extension */
199 uint32 drmod
= 0; /* mode */
200 uint32 srpos
= 0; /* switch register pos */
201 uint32 drpos
= 0; /* display register pos */
202 uint32 s0_rel
= 0; /* S0 relocation */
203 uint32 s1_rel
= 0; /* S1 relocation */
204 uint32 int_req
[INTSZ
] = { 0 }; /* interrupt requests */
205 uint32 int_enb
[INTSZ
] = { 0 }; /* interrupt enables */
206 int32 blkiop
= -1; /* block I/O in prog */
207 uint32 qevent
= 0; /* events */
208 uint32 stop_inst
= 0; /* stop on ill inst */
209 uint32 stop_wait
= 0; /* stop on wait */
210 uint16 pcq
[PCQ_SIZE
] = { 0 }; /* PC queue */
211 int32 pcq_p
= 0; /* PC queue ptr */
212 REG
*pcq_r
= NULL
; /* PC queue reg ptr */
213 uint32 dec_flgs
= 0; /* decode flags */
214 uint32 fp_in_hwre
= 0; /* ucode/hwre fp */
215 uint32 pawidth
= PAWIDTH16
; /* phys addr mask */
216 uint32 hst_p
= 0; /* history pointer */
217 uint32 hst_lnt
= 0; /* history length */
218 InstHistory
*hst
= NULL
; /* instruction history */
219 struct BlockIO blk_io
; /* block I/O status */
220 uint32 (*dev_tab
[DEVNO
])(uint32 dev
, uint32 op
, uint32 datout
) = { NULL
};
222 extern int32 sim_interval
;
223 extern int32 sim_int_char
;
224 extern uint32 sim_brk_types
, sim_brk_dflt
, sim_brk_summ
; /* breakpoint info */
225 extern t_bool sim_idle_enab
;
227 uint32
ReadB (uint32 loc
);
228 uint32
ReadH (uint32 loc
);
229 void WriteB (uint32 loc
, uint32 val
);
230 void WriteH (uint32 loc
, uint32 val
);
231 uint32
int_auto (uint32 dev
, uint32 cc
);
232 uint32
addtoq (uint32 ea
, uint32 val
, uint32 flg
);
233 uint32
remfmq (uint32 ea
, uint32 r1
, uint32 flg
);
234 uint32
newPSW (uint32 val
);
235 uint32
swap_psw (uint32 loc
, uint32 cc
);
236 uint32
testsysq (uint32
);
237 uint32
display (uint32 dev
, uint32 op
, uint32 dat
);
238 t_stat
cpu_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
);
239 t_stat
cpu_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
);
240 t_stat
cpu_reset (DEVICE
*dptr
);
241 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
242 t_stat
cpu_set_model (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
243 t_stat
cpu_set_consint (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
244 t_stat
cpu_set_hist (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
245 t_stat
cpu_show_hist (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
247 extern t_bool
devtab_init (void);
248 extern void int_eval (void);
249 extern uint32
int_getdev (void);
250 extern t_bool
sch_blk (uint32 dev
);
251 extern uint32
f_l (uint32 op
, uint32 r1
, uint32 r2
, uint32 ea
);
252 extern uint32
f_c (uint32 op
, uint32 r1
, uint32 r2
, uint32 ea
);
253 extern uint32
f_as (uint32 op
, uint32 r1
, uint32 r2
, uint32 ea
);
254 extern uint32
f_m (uint32 op
, uint32 r1
, uint32 r2
, uint32 ea
);
255 extern uint32
f_d (uint32 op
, uint32 r1
, uint32 r2
, uint32 ea
);
256 extern uint32
f_fix (uint32 op
, uint32 r1
, uint32 r2
);
257 extern uint32
f_flt (uint32 op
, uint32 r1
, uint32 r2
);
259 /* Instruction decoding table - flags are first implementation */
261 const uint16 decrom
[256] = {
271 OP_RR
| OP_716
, /* CHR */
279 OP_RR
| OP_816E
| OP_PRV
, /* SETMR */
280 0, 0, 0, 0, /* 14:1F */
281 0, 0, 0, 0, 0, 0, 0, 0,
282 OP_NO
| OP_716
, /* BTBS */
283 OP_NO
| OP_716
, /* BTFS */
284 OP_NO
| OP_716
, /* BFBS */
285 OP_NO
| OP_716
, /* BFFS */
286 OP_NO
| OP_716
, /* LIS */
287 OP_NO
| OP_716
, /* LCS */
288 OP_NO
| OP_716
, /* AIS */
289 OP_NO
| OP_716
, /* SIS */
290 OP_NO
| OP_ID4
, /* LER */
291 OP_NO
| OP_ID4
, /* CER */
292 OP_NO
| OP_ID4
, /* AER */
293 OP_NO
| OP_ID4
, /* SER */
294 OP_NO
| OP_ID4
, /* MER */
295 OP_NO
| OP_ID4
, /* DER */
296 OP_NO
| OP_816
, /* FXR */
297 OP_NO
| OP_816
, /* FLR */
299 OP_NO
| OP_816E
| OP_PRV
, /* LPSR */
300 0, 0, 0, 0, /* 34:37 */
301 OP_NO
| OP_816
| OP_DPF
, /* LDR */
302 OP_NO
| OP_816
| OP_DPF
, /* CDR */
303 OP_NO
| OP_816
| OP_DPF
, /* ADR */
304 OP_NO
| OP_816
| OP_DPF
, /* SDR */
305 OP_NO
| OP_816
| OP_DPF
, /* MDR */
306 OP_NO
| OP_816
| OP_DPF
, /* DDR */
307 OP_NO
| OP_816
| OP_DPF
, /* FXDR */
308 OP_NO
| OP_816
| OP_DPF
, /* FLDR */
318 OP_RXH
| OP_716
, /* CH */
326 OP_RXH
| OP_816E
| OP_PRV
, /* SETM */
327 0, 0, 0, 0, /* 54:5F */
328 0, 0, 0, 0, 0, 0, 0, 0,
329 OP_RX
| OP_ID4
, /* STE */
330 OP_RXH
| OP_716
, /* AHM */
332 OP_RX
| OP_716
, /* ATL */
333 OP_RX
| OP_716
, /* ABL */
334 OP_RX
| OP_716
, /* RTL */
335 OP_RX
| OP_716
, /* RBL */
336 OP_RX
| OP_ID4
, /* LE */
337 OP_RX
| OP_ID4
, /* CE */
338 OP_RX
| OP_ID4
, /* AE */
339 OP_RX
| OP_ID4
, /* SE */
340 OP_RX
| OP_ID4
, /* ME */
341 OP_RX
| OP_ID4
, /* DE */
343 OP_RX
| OP_816
| OP_DPF
, /* STD */
344 OP_RX
| OP_816
, /* SME */
345 OP_RX
| OP_816
, /* LME */
346 OP_RXH
| OP_816E
| OP_PRV
, /* LPS */
347 0, 0, 0, 0, /* 74:7F */
348 OP_RX
| OP_816
| OP_DPF
, /* LD */
349 OP_RX
| OP_816
| OP_DPF
, /* CD */
350 OP_RX
| OP_816
| OP_DPF
, /* AD */
351 OP_RX
| OP_816
| OP_DPF
, /* SD */
352 OP_RX
| OP_816
| OP_DPF
, /* MD */
353 OP_RX
| OP_816
| OP_DPF
, /* DD */
354 OP_RX
| OP_816
| OP_DPF
, /* STMD */
355 OP_RX
| OP_816
| OP_DPF
, /* LMD */
356 0, 0, 0, 0, 0, 0, 0, 0, /* 80:8F */
357 0, 0, 0, 0, 0, 0, 0, 0,
358 OP_NO
| OP_716
, /* SRLS */
359 OP_NO
| OP_716
, /* SLLS */
362 OP_RR
| OP_716
, /* EXBR */
363 OP_NO
| OP_716
| OP_PRV
, /* EPSR */
364 OP_RR
| OP_PRV
, /* WBR */
365 OP_RR
| OP_PRV
, /* RBR */
366 OP_RR
| OP_716
| OP_PRV
, /* WHR */
367 OP_RR
| OP_716
| OP_PRV
, /* RHR */
368 OP_RR
| OP_PRV
, /* WDR */
369 OP_RR
| OP_PRV
, /* RDR */
370 OP_RR
| OP_716
, /* MHUR */
371 OP_RR
| OP_PRV
, /* SSR */
372 OP_RR
| OP_PRV
, /* OCR */
373 OP_RR
| OP_PRV
, /* AIR */
374 0, 0, 0, 0, 0, 0, 0, 0, /* A0:AF */
375 0, 0, 0, 0, 0, 0, 0, 0,
376 0, 0, 0, 0, 0, 0, 0, 0, /* B0:BF */
377 0, 0, 0, 0, 0, 0, 0, 0,
380 OP_RX
| OP_PRV
, /* LPSW */
381 OP_RS
| OP_716
, /* THI */
387 OP_RS
| OP_716
, /* CHI */
394 OP_RX
| OP_ID4
, /* STM */
395 OP_RX
| OP_ID4
, /* LM */
398 OP_RXB
| OP_716
, /* CLB */
399 OP_RX
| OP_ID4
| OP_PRV
, /* AL */
400 OP_RXH
| OP_PRV
, /* WB */
401 OP_RXH
| OP_PRV
, /* RB */
402 OP_RX
| OP_716
| OP_PRV
, /* WH */
403 OP_RX
| OP_716
| OP_PRV
, /* RH */
404 OP_RX
| OP_PRV
, /* WD */
405 OP_RX
| OP_PRV
, /* RD */
406 OP_RXH
| OP_716
, /* MHU */
407 OP_RX
| OP_PRV
, /* SS */
408 OP_RX
| OP_PRV
, /* OC */
409 OP_RX
| OP_PRV
, /* AI */
411 OP_RX
| OP_716
, /* SVC */
412 OP_RS
| OP_716
| OP_PRV
, /* SINT */
413 0, 0, 0, 0, 0, 0, 0, /* E3:E9 */
414 OP_RS
| OP_716
, /* RRL */
415 OP_RS
| OP_716
, /* RLL */
416 OP_RS
| OP_716
, /* SRL */
417 OP_RS
| OP_716
, /* SLL */
418 OP_RS
| OP_716
, /* SRA */
419 OP_RS
| OP_716
, /* SLA */
420 0, 0, 0, 0, 0, 0, 0, 0, /* F0:FF */
421 0, 0, 0, 0, 0, 0, 0, 0
424 /* 8/16E relocation constants for S0 and S1, indexed by PSW<8:11> */
426 static uint32 s0_rel_const
[16] = { /* addr 0-7FFF */
427 0x00000, 0x00000, 0x00000, 0x00000, /* 0 = no reloc */
428 0x00000, 0x00000, 0x00000, 0x08000, /* 8000 = rel to S1 */
429 0x08000, 0x08000, 0x08000, 0x08000,
430 0x08000, 0x08000, 0x08000, 0x00000
433 static uint32 s1_rel_const
[16] = { /* addr 8000-FFFF */
434 0x00000, 0x08000, 0x10000, 0x18000, /* reloc const must */
435 0x20000, 0x28000, 0x30000, 0xFFF8000, /* "sub" base addr */
436 0x00000, 0x08000, 0x10000, 0x18000,
437 0x20000, 0x28000, 0x30000, 0x00000
440 /* CPU data structures
442 cpu_dev CPU device descriptor
443 cpu_unit CPU unit descriptor
444 cpu_reg CPU register list
445 cpu_mod CPU modifiers list
448 DIB cpu_dib
= { d_DS
, -1, v_DS
, NULL
, &display
, NULL
};
451 UDATA (NULL
, UNIT_FIX
| UNIT_BINK
| UNIT_716
, MAXMEMSIZE16
)
455 { HRDATA (PC
, PC
, 16) },
456 { HRDATA (R0
, GREG
[0], 16) },
457 { HRDATA (R1
, GREG
[1], 16) },
458 { HRDATA (R2
, GREG
[2], 16) },
459 { HRDATA (R3
, GREG
[3], 16) },
460 { HRDATA (R4
, GREG
[4], 16) },
461 { HRDATA (R5
, GREG
[5], 16) },
462 { HRDATA (R6
, GREG
[6], 16) },
463 { HRDATA (R7
, GREG
[7], 16) },
464 { HRDATA (R8
, GREG
[8], 16) },
465 { HRDATA (R9
, GREG
[9], 16) },
466 { HRDATA (R10
, GREG
[10], 16) },
467 { HRDATA (R11
, GREG
[11], 16) },
468 { HRDATA (R12
, GREG
[12], 16) },
469 { HRDATA (R13
, GREG
[13], 16) },
470 { HRDATA (R14
, GREG
[14], 16) },
471 { HRDATA (R15
, GREG
[15], 16) },
472 { HRDATA (FR0
, F
[0], 32) },
473 { HRDATA (FR2
, F
[1], 32) },
474 { HRDATA (FR4
, F
[2], 32) },
475 { HRDATA (FR6
, F
[3], 32) },
476 { HRDATA (FR8
, F
[4], 32) },
477 { HRDATA (FR10
, F
[5], 32) },
478 { HRDATA (FR12
, F
[6], 32) },
479 { HRDATA (FR14
, F
[7], 32) },
480 { HRDATA (D0H
, D
[0].h
, 32) },
481 { HRDATA (D0L
, D
[0].l
, 32) },
482 { HRDATA (D2H
, D
[1].h
, 32) },
483 { HRDATA (D2L
, D
[1].l
, 32) },
484 { HRDATA (D4H
, D
[2].h
, 32) },
485 { HRDATA (D4L
, D
[2].l
, 32) },
486 { HRDATA (D6H
, D
[3].h
, 32) },
487 { HRDATA (D6L
, D
[3].l
, 32) },
488 { HRDATA (D8H
, D
[4].h
, 32) },
489 { HRDATA (D8L
, D
[4].l
, 32) },
490 { HRDATA (D10H
, D
[5].h
, 32) },
491 { HRDATA (D10L
, D
[5].l
, 32) },
492 { HRDATA (D12L
, D
[6].l
, 32) },
493 { HRDATA (D12H
, D
[6].h
, 32) },
494 { HRDATA (D14H
, D
[7].h
, 32) },
495 { HRDATA (D14L
, D
[7].l
, 32) },
496 { HRDATA (PSW
, PSW
, 16) },
497 { HRDATA (CC
, PSW
, 4) },
498 { HRDATA (SR
, SR
, 16) },
499 { HRDATA (DR
, DR
, 32) },
500 { HRDATA (DRX
, DRX
, 8) },
501 { FLDATA (DRMOD
, drmod
, 0) },
502 { FLDATA (SRPOS
, srpos
, 0) },
503 { HRDATA (DRPOS
, drpos
, 3) },
504 { BRDATA (IRQ
, int_req
, 16, 32, 8) },
505 { BRDATA (IEN
, int_enb
, 16, 32, 8) },
506 { HRDATA (QEVENT
, qevent
, 4), REG_HRO
},
507 { FLDATA (STOP_INST
, stop_inst
, 0) },
508 { FLDATA (STOP_WAIT
, stop_inst
, 0) },
509 { BRDATA (PCQ
, pcq
, 16, 16, PCQ_SIZE
), REG_RO
+REG_CIRC
},
510 { HRDATA (PCQP
, pcq_p
, 6), REG_HRO
},
511 { HRDATA (WRU
, sim_int_char
, 8) },
512 { HRDATA (BLKIOD
, blk_io
.dfl
, 16), REG_HRO
},
513 { HRDATA (BLKIOC
, blk_io
.cur
, 16), REG_HRO
},
514 { HRDATA (BLKIOE
, blk_io
.end
, 16), REG_HRO
},
519 { UNIT_TYPE
, 0, "I3", "I3", &cpu_set_model
},
520 { UNIT_TYPE
, UNIT_ID4
, "I4", "I4", &cpu_set_model
},
521 { UNIT_TYPE
, UNIT_716
, "7/16", "716", &cpu_set_model
},
522 { UNIT_TYPE
, UNIT_816
, "8/16", "816", &cpu_set_model
},
523 { UNIT_TYPE
, UNIT_816E
, "8/16E", "816E", &cpu_set_model
},
524 { MTAB_XTD
|MTAB_VDV
, 0, "IDLE", "IDLE", &sim_set_idle
, &sim_show_idle
},
525 { MTAB_XTD
|MTAB_VDV
, 0, NULL
, "NOIDLE", &sim_clr_idle
, NULL
},
526 { UNIT_MSIZE
, 8192, NULL
, "8K", &cpu_set_size
},
527 { UNIT_MSIZE
, 16384, NULL
, "16K", &cpu_set_size
},
528 { UNIT_MSIZE
, 24576, NULL
, "24K", &cpu_set_size
},
529 { UNIT_MSIZE
, 32768, NULL
, "32K", &cpu_set_size
},
530 { UNIT_MSIZE
, 49152, NULL
, "48K", &cpu_set_size
},
531 { UNIT_MSIZE
, 65536, NULL
, "64K", &cpu_set_size
},
532 { UNIT_MSIZE
, 131072, NULL
, "128K", &cpu_set_size
},
533 { UNIT_MSIZE
, 262144, NULL
, "256K", &cpu_set_size
},
534 { MTAB_XTD
|MTAB_VDV
|MTAB_NMO
, 0, NULL
, "CONSINT",
535 &cpu_set_consint
, NULL
, NULL
},
536 { MTAB_XTD
|MTAB_VDV
|MTAB_NMO
|MTAB_SHP
, 0, "HISTORY", "HISTORY",
537 &cpu_set_hist
, &cpu_show_hist
},
542 "CPU", &cpu_unit
, cpu_reg
, cpu_mod
,
543 1, 16, 18, 2, 16, 16,
544 &cpu_ex
, &cpu_dep
, &cpu_reset
,
549 t_stat
sim_instr (void)
554 /* Restore register state */
556 if (devtab_init ()) return SCPE_STOP
; /* check conflicts */
557 pawidth
= PAWIDTH16
; /* default width */
558 if (cpu_unit
.flags
& UNIT_816E
) { /* 8/16E? */
559 dec_flgs
= 0; /* all instr ok */
560 fp_in_hwre
= 1; /* fp in hwre */
561 pawidth
= PAWIDTH16E
; /* 18b phys addr */
562 psw_mask
= PSW_816E
; /* mem ext bits */
564 else if (cpu_unit
.flags
& UNIT_816
) { /* 8/16? */
570 else if (cpu_unit
.flags
& UNIT_716
) { /* I5, 70, 80, 7/16? */
571 dec_flgs
= OP_816
| OP_816E
;
576 else if (cpu_unit
.flags
& UNIT_ID4
) { /* I4? */
577 dec_flgs
= OP_716
| OP_816
| OP_816E
;
583 dec_flgs
= OP_ID4
| OP_716
| OP_816
| OP_816E
; /* I3 */
588 int_eval (); /* eval interrupts */
589 cc
= newPSW (PSW
& psw_mask
); /* split PSW, eval wait */
594 while (reason
== 0) { /* loop until halted */
595 uint32 dev
, drom
, inc
, lim
, opnd
;
596 uint32 op
, r1
, r1p1
, r2
, ea
, oPC
;
598 uint32 ir1
, ir2
, ityp
;
601 if (sim_interval
<= 0) { /* check clock queue */
602 if (reason
= sim_process_event ()) break;
606 if (qevent
) { /* any events? */
607 if (qevent
& EV_BLK
) { /* block I/O in prog? */
608 dev
= blk_io
.dfl
& DEV_MAX
; /* get device */
609 cc
= dev_tab
[dev
] (dev
, IO_SS
, 0) & 0xF; /* sense status */
610 if (cc
== STA_BSY
) { /* just busy? */
611 sim_interval
= 0; /* force I/O event */
614 else if (cc
== 0) { /* ready? */
615 if (blk_io
.dfl
& BL_RD
) { /* read? */
616 t
= dev_tab
[dev
] (dev
, IO_RD
, 0); /* get byte */
617 if ((t
== 0) && (blk_io
.dfl
& BL_LZ
)) continue;
618 blk_io
.dfl
= blk_io
.dfl
& ~BL_LZ
; /* non-zero seen */
619 WriteB (blk_io
.cur
, t
); /* write mem */
622 t
= ReadB (blk_io
.cur
); /* read mem */
623 dev_tab
[dev
] (dev
, IO_WD
, t
); /* put byte */
625 if (blk_io
.cur
!= blk_io
.end
) { /* more to do? */
626 blk_io
.cur
= (blk_io
.cur
+ 1) & VAMASK
; /* incr addr */
630 qevent
= qevent
& ~EV_BLK
; /* clr block I/O flg */
631 int_eval (); /* re-eval intr */
635 if ((qevent
& EV_INT
) && (PSW
& PSW_EXI
)) { /* interrupt? */
636 if (PSW
& PSW_AIO
) { /* auto enabled? */
637 dev
= int_getdev (); /* get int dev */
638 cc
= int_auto (dev
, cc
); /* do auto intr */
639 int_eval (); /* re-eval intr */
641 else cc
= swap_psw (EXIPSW
, cc
); /* old type, swap */
645 if (PSW
& PSW_WAIT
) { /* wait state? */
646 if (sim_idle_enab
) /* idling enabled? */
647 sim_idle (TMR_LFC
, TRUE
);
648 else sim_interval
= sim_interval
- 1; /* no, count cycle */
652 qevent
= 0; /* no events */
655 /* Fetch and decode instruction */
657 if (sim_brk_summ
&& sim_brk_test (PC
, SWMASK ('E'))) { /* breakpoint? */
658 reason
= STOP_IBKPT
; /* stop simulation */
662 sim_interval
= sim_interval
- 1;
664 ir1
= ReadH (oPC
= PC
); /* fetch instr */
665 op
= (ir1
>> 8) & 0xFF; /* isolate op, R1, R2 */
666 r1
= (ir1
>> 4) & 0xF;
669 ityp
= drom
& OP_MASK
;
671 if ((drom
== 0) || (drom
& dec_flgs
)) { /* not in model? */
672 if (stop_inst
) reason
= STOP_RSRV
; /* stop or */
673 else cc
= swap_psw (ILOPSW
, cc
); /* swap PSW */
676 if ((drom
& OP_PRV
) && (PSW
& PSW_PRO
)) { /* priv & protected? */
677 cc
= swap_psw (ILOPSW
, cc
); /* swap PSW */
681 switch (ityp
) { /* decode instruction */
683 case OP_NO
: /* no operand */
684 opnd
= r2
; /* assume short */
687 case OP_RR
: /* reg-reg */
688 opnd
= R
[r2
]; /* operand is R2 */
691 case OP_RS
: /* reg-storage */
692 case OP_RX
: /* reg-mem */
693 PC
= (PC
+ 2) & VAMASK
; /* increment PC */
694 ir2
= ea
= ReadH (PC
); /* fetch address */
695 if (r2
) ea
= (ir2
+ R
[r2
]) & VAMASK
; /* index calculation */
696 opnd
= ea
; /* operand is ea */
699 case OP_RXB
: /* reg-mem byte */
700 PC
= (PC
+ 2) & VAMASK
; /* increment PC */
701 ir2
= ea
= ReadH (PC
); /* fetch address */
702 if (r2
) ea
= (ea
+ R
[r2
]) & VAMASK
; /* index calculation */
703 opnd
= ReadB (ea
); /* fetch operand */
706 case OP_RXH
: /* reg-mem halfword */
707 PC
= (PC
+ 2) & VAMASK
; /* increment PC */
708 ir2
= ea
= ReadH (PC
); /* fetch address */
709 if (r2
) ea
= (ea
+ R
[r2
]) & VAMASK
; /* index calculation */
710 opnd
= ReadH (ea
); /* fetch operand */
717 if (hst_lnt
) { /* instruction history? */
720 hst
[hst_p
].ir1
= ir1
;
721 hst
[hst_p
].ir2
= ir2
;
722 hst
[hst_p
].r1
= R
[r1
];
724 hst
[hst_p
].opnd
= opnd
;
726 if (hst_p
>= hst_lnt
) hst_p
= 0;
729 PC
= (PC
+ 2) & VAMASK
; /* increment PC */
730 switch (op
) { /* case on opcode */
732 /* Load/store instructions */
734 case 0x08: /* LHR - RR */
735 case 0x24: /* LIS - NO */
736 case 0x48: /* LH - RXH */
737 case 0xC8: /* LHI - RS */
738 R
[r1
] = opnd
; /* load operand */
739 CC_GL_16 (R
[r1
]); /* set G,L */
742 case 0x25: /* LCS - NO */
743 R
[r1
] = (~opnd
+ 1) & DMASK16
; /* load complement */
744 CC_GL_16 (R
[r1
]); /* set G,L */
747 case 0x40: /* STH - RX */
748 WriteH (ea
, R
[r1
]); /* store register */
751 case 0xD1: /* LM - RX */
752 for ( ; r1
<= 0xF; r1
++) { /* loop thru reg */
753 R
[r1
] = ReadH (ea
); /* load register */
754 ea
= (ea
+ 2) & VAMASK
; /* incr mem addr */
758 case 0xD0: /* STM - RX */
759 for ( ; r1
<= 0xF; r1
++) { /* loop thru reg */
760 WriteH (ea
, R
[r1
]); /* store register */
761 ea
= (ea
+ 2) & VAMASK
; /* incr mem addr */
765 case 0x93: /* LDBR - RR */
766 case 0xD3: /* LDB - RXB */
767 R
[r1
] = opnd
& DMASK8
; /* load byte */
770 case 0x92: /* STBR - NO */
771 R
[r2
] = (R
[r2
] & ~DMASK8
) | (R
[r1
] & DMASK8
); /* store byte */
773 case 0xD2: /* STB - RX */
774 WriteB (ea
, R
[r1
] & DMASK8
); /* store byte */
777 case 0x94: /* EXBR - RR */
778 R
[r1
] = (opnd
>> 8) | ((opnd
& DMASK8
) << 8);
781 /* Control instructions */
783 case 0x01: /* BALR - RR */
784 case 0x41: /* BAL - RX */
785 PCQ_ENTRY
; /* save old PC */
786 R
[r1
] = PC
; /* save cur PC */
787 PC
= opnd
; /* branch */
790 case 0x02: /* BTCR - RR */
791 case 0x42: /* BTC - RX */
792 if (cc
& r1
) { /* test CC's */
793 PCQ_ENTRY
; /* branch if true */
798 case 0x20: /* BTBS - NO */
799 if (cc
& r1
) { /* test CC's */
800 PCQ_ENTRY
; /* branch if true */
801 PC
= (oPC
- r2
- r2
) & VAMASK
;
805 case 0x21: /* BTFS - NO */
806 if (cc
& r1
) { /* test CC's */
807 PCQ_ENTRY
; /* branch if true */
808 PC
= (oPC
+ r2
+ r2
) & VAMASK
;
812 case 0x03: /* BFCR - RR */
813 case 0x43: /* BFC - RX */
814 if ((cc
& r1
) == 0) { /* test CC's */
815 PCQ_ENTRY
; /* branch if false */
820 case 0x22: /* BFBS - NO */
821 if ((cc
& r1
) == 0) { /* test CC's */
822 PCQ_ENTRY
; /* branch if false */
823 PC
= (oPC
- r2
- r2
) & VAMASK
;
827 case 0x23: /* BFFS - NO */
828 if ((cc
& r1
) == 0) { /* test CC's */
829 PCQ_ENTRY
; /* branch if false */
830 PC
= (oPC
+ r2
+ r2
) & VAMASK
;
834 case 0xC0: /* BXH - RX */
835 inc
= R
[(r1
+ 1) & 0xF]; /* inc = R1 + 1 */
836 lim
= R
[(r1
+ 2) & 0xF]; /* lim = R1 + 2 */
837 R
[r1
] = (R
[r1
] + inc
) & DMASK16
; /* R1 = R1 + inc */
838 if (R
[r1
] > lim
) { /* if R1 > lim */
839 PCQ_ENTRY
; /* branch */
844 case 0xC1: /* BXLE - RX */
845 inc
= R
[(r1
+ 1) & 0xF]; /* inc = R1 + 1 */
846 lim
= R
[(r1
+ 2) & 0xF]; /* lim = R1 + 2 */
847 R
[r1
] = (R
[r1
] + inc
) & DMASK16
; /* R1 = R1 + inc */
848 if (R
[r1
] <= lim
) { /* if R1 <= lim */
849 PCQ_ENTRY
; /* branch */
854 /* Logical instructions */
856 case 0x04: /* NHR - RR */
857 case 0x44: /* NH - RXH */
858 case 0xC4: /* NHI - RS */
859 R
[r1
] = R
[r1
] & opnd
; /* result */
860 CC_GL_16 (R
[r1
]); /* set G,L */
863 case 0x06: /* OHR - RR */
864 case 0x46: /* OH - RXH */
865 case 0xC6: /* OHI - RS */
866 R
[r1
] = R
[r1
] | opnd
; /* result */
867 CC_GL_16 (R
[r1
]); /* set G,L */
870 case 0x07: /* XHR - RR */
871 case 0x47: /* XH - RXH */
872 case 0xC7: /* XHI - RS */
873 R
[r1
] = R
[r1
] ^ opnd
; /* result */
874 CC_GL_16 (R
[r1
]); /* set G,L */
877 case 0xC3: /* THI - RS */
878 rslt
= R
[r1
] & opnd
; /* result */
879 CC_GL_16 (rslt
); /* set G, L */
882 case 0x05: /* CLHR - RR */
883 case 0x45: /* CLH - RXH */
884 case 0xC5: /* CLHI - RS */
885 rslt
= (R
[r1
] - opnd
) & DMASK16
; /* result */
886 CC_GL_16 (rslt
); /* set G,L */
887 if (R
[r1
] < opnd
) cc
= cc
| CC_C
; /* set C if borrow */
888 if (((R
[r1
] ^ opnd
) & (~opnd
^ rslt
)) & SIGN16
) cc
= cc
| CC_V
;
891 case 0xD4: /* CLB - RXB */
893 rslt
= (t
- opnd
) & DMASK16
; /* result */
894 CC_GL_16 (rslt
); /* set G,L */
895 if (t
< opnd
) cc
= cc
| CC_C
; /* set C if borrow */
898 /* Shift instructions */
900 case 0xCC: /* SRHL - RS */
901 opnd
= opnd
& 0xF; /* shift count */
902 case 0x90: /* SRLS - NO */
903 rslt
= R
[r1
] >> opnd
; /* result */
904 CC_GL_16 (rslt
); /* set G,L */
905 if (opnd
&& ((R
[r1
] >> (opnd
- 1)) & 1)) cc
= cc
| CC_C
;
906 R
[r1
] = rslt
; /* store result */
909 case 0xCD: /* SLHL - RS */
910 opnd
= opnd
& 0xF; /* shift count */
911 case 0x91: /* SLLS - NO */
912 rslt
= R
[r1
] << opnd
; /* raw result */
913 R
[r1
] = rslt
& DMASK16
; /* masked result */
914 CC_GL_16 (R
[r1
]); /* set G,L */
915 if (opnd
&& (rslt
& 0x10000)) cc
= cc
| CC_C
; /* set C if shft out */
918 case 0xCE: /* SRHA - RS */
919 opnd
= opnd
& 0xF; /* shift count */
920 rslt
= (SEXT16 (R
[r1
]) >> opnd
) & DMASK16
; /* result */
921 CC_GL_16 (rslt
); /* set G,L */
922 if (opnd
&& ((R
[r1
] >> (opnd
- 1)) & 1)) cc
= cc
| CC_C
;
923 R
[r1
] = rslt
; /* store result */
926 case 0xCF: /* SLHA - RS */
927 opnd
= opnd
& 0xF; /* shift count */
928 rslt
= R
[r1
] << opnd
; /* raw result */
929 R
[r1
] = (R
[r1
] & SIGN16
) | (rslt
& MMASK16
); /* arith result */
930 CC_GL_16 (R
[r1
]); /* set G,L */
931 if (opnd
&& (rslt
& SIGN16
)) cc
= cc
| CC_C
; /* set C if shft out */
934 case 0xEA: /* RRL - RS */
935 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
936 opnd
= opnd
& 0x1F; /* shift count */
937 t
= (R
[r1
] << 16) | R
[r1p1
]; /* form 32b op */
938 if (opnd
) rslt
= (t
>> opnd
) | (t
<< (32 - opnd
)); /* result */
939 else rslt
= t
; /* no shift */
940 CC_GL_32 (rslt
); /* set G,L 32b */
941 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
942 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
945 case 0xEB: /* RLL - RS */
946 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
947 opnd
= opnd
& 0x1F; /* shift count */
948 t
= (R
[r1
] << 16) | R
[r1p1
]; /* form 32b op */
949 if (opnd
) rslt
= (t
<< opnd
) | (t
>> (32 - opnd
)); /* result */
950 else rslt
= t
; /* no shift */
951 CC_GL_32 (rslt
); /* set G,L 32b */
952 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
953 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
956 case 0xEC: /* SRL - RS */
957 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
958 opnd
= opnd
& 0x1F; /* shift count */
959 t
= (R
[r1
] << 16) | R
[r1p1
]; /* form 32b op */
960 rslt
= t
>> opnd
; /* result */
961 CC_GL_32 (rslt
); /* set G,L 32b */
962 if (opnd
&& ((t
>> (opnd
- 1)) & 1)) cc
= cc
| CC_C
;
963 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
964 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
967 case 0xED: /* SLL - RS */
968 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
969 opnd
= opnd
& 0x1F; /* shift count */
970 t
= (R
[r1
] << 16) | R
[r1p1
]; /* form 32b op */
971 rslt
= t
<< opnd
; /* result */
972 CC_GL_32 (rslt
); /* set G,L 32b */
973 if (opnd
&& ((t
<< (opnd
- 1)) & SIGN32
)) cc
= cc
| CC_C
;
974 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
975 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
978 case 0xEE: /* SRA - RS */
979 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
980 opnd
= opnd
& 0x1F; /* shift count */
981 t
= (R
[r1
] << 16) | R
[r1p1
]; /* form 32b op */
982 rslt
= ((int32
) t
) >> opnd
; /* signed result */
983 CC_GL_32 (rslt
); /* set G,L 32b */
984 if (opnd
&& ((t
>> (opnd
- 1)) & 1)) cc
= cc
| CC_C
;
985 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
986 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
989 case 0xEF: /* SLA - RS */
990 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
991 opnd
= opnd
& 0x1F; /* shift count */
992 t
= (R
[r1
] << 16) | R
[r1p1
]; /* form 32b op */
993 rslt
= (t
& SIGN32
) | ((t
<< opnd
) & MMASK32
); /* signed result */
994 CC_GL_32 (rslt
); /* set G,L 32b */
995 if (opnd
&& ((t
<< opnd
) & SIGN32
)) cc
= cc
| CC_C
;
996 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
997 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
1000 /* Arithmetic instructions */
1002 case 0x0A: /* AHR - RR */
1003 case 0x26: /* AIS - NO */
1004 case 0x4A: /* AH - RXH */
1005 case 0xCA: /* AHI - RS */
1006 rslt
= (R
[r1
] + opnd
) & DMASK16
; /* result */
1007 CC_GL_16 (rslt
); /* set G,L */
1008 if (rslt
< opnd
) cc
= cc
| CC_C
; /* set C if carry */
1009 if (((~R
[r1
] ^ opnd
) & (R
[r1
] ^ rslt
)) & SIGN16
) cc
= cc
| CC_V
;
1013 case 0x61: /* AHM - RXH */
1014 rslt
= (R
[r1
] + opnd
) & DMASK16
; /* result */
1015 CC_GL_16 (rslt
); /* set G,L */
1016 if (rslt
< opnd
) cc
= cc
| CC_C
; /* set C if carry */
1017 if (((~R
[r1
] ^ opnd
) & (R
[r1
] ^ rslt
)) & SIGN16
) cc
= cc
| CC_V
;
1018 WriteH (ea
, rslt
); /* store in memory */
1021 case 0x0B: /* SHR - RR */
1022 case 0x27: /* SIS - NO */
1023 case 0x4B: /* SH - RXH */
1024 case 0xCB: /* SHI - RS */
1025 rslt
= (R
[r1
] - opnd
) & DMASK16
; /* result */
1026 CC_GL_16 (rslt
); /* set G,L */
1027 if (R
[r1
] < opnd
) cc
= cc
| CC_C
; /* set C if borrow */
1028 if (((R
[r1
] ^ opnd
) & (~opnd
^ rslt
)) & SIGN16
) cc
= cc
| CC_V
;
1032 case 0x09: /* CHR - RR */
1033 case 0x49: /* CH - RXH */
1034 case 0xC9: /* CHI - RS */
1035 sr
= SEXT16 (R
[r1
]); /* sign ext */
1037 if (sr
< st
) cc
= CC_C
| CC_L
; /* < sets C, L */
1038 else if (sr
> st
) cc
= CC_G
; /* > sets G */
1040 if (((R
[r1
] ^ opnd
) & (~opnd
^ (sr
- st
))) & SIGN16
)
1044 case 0x0C: /* MHR - RR */
1045 case 0x4C: /* MH - RXH */
1046 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
1047 rslt
= SEXT16 (R
[r1p1
]) * SEXT16 (opnd
); /* multiply */
1048 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
1049 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
1052 case 0x9C: /* MHUR - RR */
1053 case 0xDC: /* MHU - RXH */
1054 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
1055 rslt
= R
[r1p1
] * opnd
; /* multiply, unsigned */
1056 R
[r1
] = (rslt
>> 16) & DMASK16
; /* hi result */
1057 R
[r1p1
] = rslt
& DMASK16
; /* lo result */
1060 case 0x0D: /* DHR - RR */
1061 case 0x4D: /* DH - RXH */
1062 r1p1
= (r1
+ 1) & 0xF; /* R1 + 1 */
1064 ((R
[r1
] == 0x8000) && (R
[r1p1
] == 0) && (opnd
== 0xFFFF))) {
1065 if (PSW
& PSW_AFI
) /* div fault enabled? */
1066 cc
= swap_psw (AFIPSW
, cc
); /* swap PSW */
1069 sr
= (R
[r1
] << 16) | R
[r1p1
]; /* signed 32b divd */
1070 st
= sr
/ SEXT16 (opnd
); /* signed quotient */
1071 sr
= sr
% SEXT16 (opnd
); /* remainder */
1072 if ((st
< 0x8000) && (st
>= -0x8000)) { /* if quo fits */
1073 R
[r1
] = sr
& DMASK16
; /* store remainder */
1074 R
[r1p1
] = st
& DMASK16
; /* store quotient */
1076 else if (PSW
& PSW_AFI
) /* div fault enabled? */
1077 cc
= swap_psw (AFIPSW
, cc
); /* swap PSW */
1080 case 0x0E: /* ACHR - RR */
1081 case 0x4E: /* ACH - RXH */
1082 t
= R
[r1
] + opnd
+ ((cc
& CC_C
) != 0); /* raw result */
1083 rslt
= t
& DMASK16
; /* masked result */
1084 CC_GL_16 (rslt
); /* set G,L */
1085 if (t
> DMASK16
) cc
= cc
| CC_C
; /* set C if carry */
1086 if (((~R
[r1
] ^ opnd
) & (R
[r1
] ^ rslt
)) & SIGN16
) cc
= cc
| CC_V
;
1087 R
[r1
] = rslt
; /* store result */
1090 case 0x0F: /* SCHR - RR */
1091 case 0x4F: /* SCH - RXH */
1092 t
= R
[r1
] - opnd
- ((cc
& CC_C
) != 0); /* raw result */
1093 rslt
= t
& DMASK16
; /* masked result */
1094 CC_GL_16 (rslt
); /* set G,L */
1095 if (t
> DMASK16
) cc
= cc
| CC_C
; /* set C if borrow */
1096 if (((R
[r1
] ^ opnd
) & (~opnd
^ rslt
)) & SIGN16
) cc
= cc
| CC_V
;
1097 R
[r1
] = rslt
; /* store result */
1100 /* Floating point instructions */
1102 case 0x28: /* LER - NO */
1103 case 0x38: /* LDR - NO */
1104 case 0x68: /* LE - RX */
1105 case 0x78: /* LD - RX */
1106 cc
= f_l (op
, r1
, r2
, ea
); /* load */
1107 if ((cc
& CC_V
) && (PSW
& PSW_FPF
) && CPU_x16
) /* V set, x/16? */
1108 cc
= swap_psw (FPFPSW
, cc
);
1111 case 0x29: /* CER - NO */
1112 case 0x39: /* CDR - NO */
1113 case 0x69: /* CE - RX */
1114 case 0x79: /* CD - RX */
1115 cc
= f_c (op
, r1
, r2
, ea
); /* compare */
1118 case 0x2A: /* AER - NO */
1119 case 0x2B: /* SER - NO */
1120 case 0x3A: /* ADR - NO */
1121 case 0x3B: /* SDR - NO */
1122 case 0x6A: /* AE - RX */
1123 case 0x6B: /* SE - RX */
1124 case 0x7A: /* AD - RX */
1125 case 0x7B: /* SD - RX */
1126 cc
= f_as (op
, r1
, r2
, ea
); /* add/sub */
1127 if ((cc
& CC_V
) && (PSW
& PSW_FPF
) && CPU_x16
) /* V set, x/16? */
1128 cc
= swap_psw (FPFPSW
, cc
);
1131 case 0x2C: /* MER - NO */
1132 case 0x3C: /* MDR - NO */
1133 case 0x6C: /* ME - RX */
1134 case 0x7C: /* MD - RX */
1135 cc
= f_m (op
, r1
, r2
, ea
); /* multiply */
1136 if ((cc
& CC_V
) && (PSW
& PSW_FPF
) && CPU_x16
) /* V set, x/16? */
1137 cc
= swap_psw (FPFPSW
, cc
);
1140 case 0x2D: /* DER - NO */
1141 case 0x3D: /* DDR - NO */
1142 case 0x6D: /* DE - RX */
1143 case 0x7D: /* DD - RX */
1144 cc
= f_d (op
, r1
, r2
, ea
); /* perform divide */
1145 if ((cc
& CC_V
) && ((cc
& CC_C
) || /* V set, x/16 or */
1146 ((PSW
& PSW_FPF
) && CPU_x16
))) /* V & C set? */
1147 cc
= swap_psw (FPFPSW
, cc
);
1150 case 0x2E: /* FXR - NO */
1151 case 0x3E: /* FXDR - NO */
1152 cc
= f_fix (op
, r1
, r2
); /* cvt to integer */
1155 case 0x2F: /* FLR - NO */
1156 case 0x3F: /* FLDR - NO */
1157 cc
= f_flt (op
, r1
, r2
); /* cvt to floating */
1160 case 0x60: /* STE - RX */
1161 t
= ReadFReg (r1
); /* get fp reg */
1162 WriteF (ea
, t
, P
); /* write */
1165 case 0x70: /* STD - RX */
1166 WriteF (ea
, D
[r1
>> 1].h
, P
); /* write hi */
1167 WriteF ((ea
+ 4) & VAMASK
, D
[r1
>> 1].l
, P
); /* write lo */
1170 case 0x71: /* STME - RX */
1171 for ( ; r1
<= 0xE; r1
= r1
+ 2) { /* loop thru reg */
1172 t
= ReadFReg (r1
); /* get fp reg */
1173 WriteF (ea
, t
, P
); /* write */
1174 ea
= (ea
+ 4) & VAMASK
; /* incr mem addr */
1178 case 0x72: /* LME - RX */
1179 for ( ; r1
<= 0xE; r1
= r1
+ 2) { /* loop thru reg */
1180 t
= ReadF (ea
, P
); /* get value */
1181 WriteFReg (r1
, t
); /* write reg */
1182 ea
= (ea
+ 4) & VAMASK
; /* incr mem addr */
1186 case 0x7E: /* STMD - RX */
1187 for ( ; r1
<= 0xE; r1
= r1
+ 2) { /* loop thru reg */
1188 WriteF (ea
, D
[r1
>> 1].h
, P
); /* write register */
1189 WriteF ((ea
+ 4) & VAMASK
, D
[r1
>> 1].l
, P
);
1190 ea
= (ea
+ 8) & VAMASK
; /* incr mem addr */
1194 case 0x7F: /* LMD - RX */
1195 for ( ; r1
<= 0xE; r1
= r1
+ 2) { /* loop thru reg */
1196 D
[r1
>> 1].h
= ReadF (ea
, P
); /* load register */
1197 D
[r1
>> 1].l
= ReadF ((ea
+ 4) & VAMASK
, P
);
1198 ea
= (ea
+ 8) & VAMASK
; /* incr mem addr */
1204 case 0xE1: /* SVC - RX */
1205 PCQ_ENTRY
; /* save PC */
1206 WriteH (SVCAP
, ea
); /* save opnd */
1207 WriteH (SVOPS
, BUILD_PSW (cc
)); /* save PS */
1208 WriteH (SVOPC
, PC
); /* save PC */
1209 PC
= ReadH (SVNPC
+ r1
+ r1
); /* new PC */
1210 cc
= newPSW (ReadH (SVNPS
)); /* new PS */
1213 case 0xE2: /* SINT - RS */
1214 dev
= opnd
& DEV_MAX
; /* get dev */
1215 cc
= int_auto (dev
, cc
); /* auto intr */
1216 int_eval (); /* re-eval intr */
1219 case 0xC2: /* LPSW - RX */
1220 PCQ_ENTRY
; /* effective branch */
1221 PC
= ReadH ((ea
+ 2) & VAMASK
); /* read PC */
1222 cc
= newPSW (ReadH (ea
)); /* read PSW */
1223 if (PSW
& PSW_SQI
) cc
= testsysq (cc
); /* test for q */
1226 case 0x95: /* EPSR - NO */
1227 R
[r1
] = BUILD_PSW (cc
); /* save PSW */
1228 case 0x33: /* LPSR - NO */
1229 cc
= newPSW (R
[r2
]); /* load new PSW */
1230 if (PSW
& PSW_SQI
) cc
= testsysq (cc
); /* test for q */
1233 case 0x73: /* LPS - RXH */
1234 cc
= newPSW (opnd
); /* load new PSW */
1235 if (PSW
& PSW_SQI
) cc
= testsysq (cc
); /* test for q */
1238 case 0x64: /* ATL - RX */
1239 case 0x65: /* ABL - RX */
1240 cc
= addtoq (ea
, R
[r1
], op
& 1); /* add to q */
1243 case 0x66: /* RTL - RX */
1244 case 0x67: /* RBL - RX */
1245 cc
= remfmq (ea
, r1
, op
& 1); /* remove from q */
1248 case 0x13: /* SETMR - RR */
1249 case 0x53: /* SETM - RXH */
1250 t
= BUILD_PSW (cc
); /* old PSW */
1251 map
= PSW_GETMAP (opnd
); /* get new map */
1252 switch (map
) { /* case on map */
1255 map
= 0; /* use 1:1 map */
1256 R
[r1
] = R
[r1
] ^ SIGN16
; /* flip sign */
1259 case 0x8: case 0x9: case 0xA: case 0xB:
1260 case 0xC: case 0xD: case 0xE:
1261 if (R
[r1
] & SIGN16
) map
= map
& ~0x8; /* S1? clr map<0> */
1263 map
= 0; /* else 1:1 map */
1264 R
[r1
] = R
[r1
] | SIGN16
; /* set sign */
1271 t
= (t
& ~PSW_MAP
) | (map
<< PSW_V_MAP
); /* insert map */
1272 newPSW (t
); /* load new PSW */
1273 CC_GL_16 (R
[r1
]); /* set G,L */
1276 /* I/O instructions */
1278 case 0xDE: /* OC - RX */
1279 opnd
= ReadB (ea
); /* fetch operand */
1280 case 0x9E: /* OCR - RR */
1281 dev
= R
[r1
] & DEV_MAX
;
1282 if (DEV_ACC (dev
)) {
1283 dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select */
1284 dev_tab
[dev
] (dev
, IO_OC
, opnd
& DMASK8
); /* send command */
1285 int_eval (); /* re-eval intr */
1291 case 0xDA: /* WD - RX */
1292 opnd
= ReadB (ea
); /* fetch operand */
1293 case 0x9A: /* WDR - RR */
1294 dev
= R
[r1
] & DEV_MAX
;
1295 if (DEV_ACC (dev
)) {
1296 dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select */
1297 dev_tab
[dev
] (dev
, IO_WD
, opnd
& DMASK8
); /* send data */
1298 int_eval (); /* re-eval intr */
1304 case 0xD8: /* WH - RX */
1305 opnd
= ReadH (ea
); /* fetch operand */
1306 case 0x98: /* WHR - RR */
1307 dev
= R
[r1
] & DEV_MAX
;
1308 if (DEV_ACC (dev
)) {
1309 if (dev_tab
[dev
] (dev
, IO_ADR
, 0)) /* select; hw ok? */
1310 dev_tab
[dev
] (dev
, IO_WH
, opnd
); /* send data */
1311 else { /* byte only */
1312 dev_tab
[dev
] (dev
, IO_WD
, opnd
>> 8); /* send hi byte */
1313 dev_tab
[dev
] (dev
, IO_WD
, opnd
& DMASK8
); /* send lo byte */
1315 int_eval (); /* re-eval intr */
1321 case 0x9B: /* RDR - RR */
1322 case 0xDB: /* RD - RX */
1323 dev
= R
[r1
] & DEV_MAX
;
1324 if (DEV_ACC (dev
)) { /* dev exist? */
1325 dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select */
1326 t
= dev_tab
[dev
] (dev
, IO_RD
, 0); /* get data */
1330 t
= 0; /* read zero */
1331 cc
= CC_V
; /* set V */
1333 if (OP_TYPE (op
) != OP_RR
) WriteB (ea
, t
); /* RX or RR? */
1334 else R
[r2
] = t
& DMASK8
;
1335 int_eval (); /* re-eval intr */
1338 case 0x99: /* RHR - RR */
1339 case 0xD9: /* RH - RX */
1340 dev
= R
[r1
] & DEV_MAX
;
1341 if (DEV_ACC (dev
)) { /* dev exist? */
1342 if (dev_tab
[dev
] (dev
, IO_ADR
, 0)) /* select, hw ok? */
1343 t
= dev_tab
[dev
] (dev
, IO_RH
, 0); /* get data */
1344 else { /* byte only */
1345 rslt
= dev_tab
[dev
] (dev
, IO_RD
, 0); /* get byte */
1346 t
= dev_tab
[dev
] (dev
, IO_RD
, 0); /* get byte */
1347 t
= (rslt
<< 8) | t
; /* merge */
1352 t
= 0; /* read zero */
1353 cc
= CC_V
; /* set V */
1355 if (OP_TYPE (op
) != OP_RR
) WriteH (ea
, t
); /* RX or RR? */
1357 int_eval (); /* re-eval intr */
1360 case 0x9F: /* AIR - RR */
1361 case 0xDF: /* AI - RX */
1362 R
[r1
] = int_getdev (); /* get int dev */
1364 case 0x9D: /* SSR - RR */
1365 case 0xDD: /* SS - RX */
1366 dev
= R
[r1
] & DEV_MAX
;
1367 if (DEV_ACC (dev
)) { /* dev exist? */
1368 dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select */
1369 t
= dev_tab
[dev
] (dev
, IO_SS
, 0); /* get status */
1371 else t
= STA_EX
; /* no */
1372 if (OP_TYPE (op
) != OP_RR
) WriteB (ea
, t
); /* RR or RX? */
1373 else R
[r2
] = t
& DMASK8
;
1375 int_eval (); /* re-eval intr */
1378 /* Block I/O instructions
1380 On a real Interdata system, the block I/O instructions can't be
1381 interrupted or stopped. To model this behavior, while allowing
1382 the instructions to go back through fetch for I/O processing and
1383 WRU testing, the simulator implements a 'block I/O in progress'
1384 flag and status block. If a block I/O is in progress, normal
1385 interrupts and fetches are suppressed until the block I/O is done.
1388 case 0x96: /* WBR - RR */
1389 case 0xD6: /* WB - RXH */
1390 dev
= R
[r1
] & DEV_MAX
;
1391 if (DEV_ACC (dev
)) { /* dev exist? */
1392 if (OP_TYPE (op
) != OP_RR
)
1393 lim
= ReadH ((ea
+ 2) & VAMASK
);
1394 else lim
= R
[(r2
+ 1) & 0xF];
1395 if (opnd
> lim
) cc
= 0; /* start > end? */
1396 else { /* no, start I/O */
1397 dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select dev */
1398 blk_io
.dfl
= dev
; /* set status block */
1401 qevent
= qevent
| EV_BLK
; /* I/O in prog */
1404 else cc
= CC_V
; /* nx dev */
1407 case 0x97: /* RBR - RR */
1408 case 0xD7: /* RB - RXH */
1409 dev
= R
[r1
] & DEV_MAX
;
1410 if (DEV_ACC (dev
)) { /* dev exist? */
1411 if (OP_TYPE (op
) != OP_RR
)
1412 lim
= ReadH ((ea
+ 2) & VAMASK
);
1413 else lim
= R
[(r2
+ 1) & 0xF];
1414 if (opnd
> lim
) cc
= 0; /* start > end? */
1415 else { /* no, start I/O */
1416 dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select dev */
1417 blk_io
.dfl
= dev
| BL_RD
; /* set status block */
1420 qevent
= qevent
| EV_BLK
; /* I/O in prog */
1423 else cc
= CC_V
; /* nx dev */
1426 case 0xD5: /* AL - RX */
1427 dev
= ReadB (AL_DEV
); /* get device */
1428 t
= ReadB (AL_IOC
); /* get command */
1429 if (DEV_ACC (dev
)) { /* dev exist? */
1430 if (AL_BUF
> ea
) cc
= 0; /* start > end? */
1431 else { /* no, start I/O */
1432 dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select dev */
1433 dev_tab
[dev
] (dev
, IO_OC
, t
); /* start dev */
1434 blk_io
.dfl
= dev
| BL_RD
| BL_LZ
; /* set status block */
1435 blk_io
.cur
= AL_BUF
;
1437 qevent
= qevent
| EV_BLK
; /* I/O in prog */
1440 else cc
= CC_V
; /* nx dev */
1445 /* Simulation halted */
1447 PSW
= BUILD_PSW (cc
);
1449 pcq_r
->qptr
= pcq_p
; /* update pc q ptr */
1453 /* Load new PSW and memory map */
1455 uint32
newPSW (uint32 val
)
1457 PSW
= val
& psw_mask
; /* store PSW */
1458 int_eval (); /* update intreq */
1459 if (PSW
& PSW_WAIT
) qevent
= qevent
| EV_WAIT
; /* wait state? */
1460 else qevent
= qevent
& ~EV_WAIT
;
1461 if (cpu_unit
.flags
& UNIT_816E
) { /* mapping enabled? */
1462 uint32 map
= PSW_GETMAP (PSW
); /* get new map */
1463 s0_rel
= s0_rel_const
[map
]; /* set relocation */
1464 s1_rel
= s1_rel_const
[map
]; /* constants */
1466 else s0_rel
= s1_rel
= 0; /* no relocation */
1467 if (PSW
& PSW_AIO
) SET_ENB (v_DS
); /* PSW<4> controls */
1468 else CLR_ENB (v_DS
); /* DS interrupts */
1469 return PSW
& CC_MASK
;
1474 uint32
swap_psw (uint32 loc
, uint32 cc
)
1476 WriteH (loc
, BUILD_PSW (cc
)); /* write PSW, PC */
1477 WriteH (loc
+ 2, PC
);
1478 cc
= newPSW (ReadH (loc
+ 4)); /* read PSW, PC */
1479 PC
= ReadH (loc
+ 6);
1480 if (PSW
& PSW_SQI
) cc
= testsysq (cc
); /* sys q int enb? */
1481 return cc
; /* return CC */
1484 /* Test for queue interrupts */
1486 uint32
testsysq (uint32 cc
)
1488 int32 qb
= ReadH (SQP
); /* get sys q addr */
1489 int32 usd
= ReadB (qb
+ Q16_USD
); /* get use count */
1491 if (usd
) { /* any entries? */
1492 WriteH (SQIPSW
, BUILD_PSW (cc
)); /* swap PSW */
1493 WriteH (SQIPSW
+ 2, PC
);
1494 cc
= newPSW (ReadH (SQIPSW
+ 4));
1495 PC
= ReadH (SQIPSW
+ 6);
1500 /* Add to head of queue */
1502 uint32
addtoq (uint32 ea
, uint32 val
, uint32 flg
)
1504 uint32 slt
, usd
, wra
, t
;
1506 t
= ReadH (ea
); /* slots/used */
1507 slt
= (t
>> 8) & DMASK8
; /* # slots */
1508 usd
= t
& DMASK8
; /* # used */
1509 if (usd
>= slt
) return CC_V
; /* list full? */
1510 usd
= usd
+ 1; /* inc # used */
1511 WriteB (ea
+ Q16_USD
, usd
); /* rewrite */
1512 if (flg
) { /* ABL? */
1513 wra
= ReadB ((ea
+ Q16_BOT
) & VAMASK
); /* get bottom */
1514 t
= wra
+ 1; /* adv bottom */
1515 if (t
>= slt
) t
= 0; /* wrap if necc */
1516 WriteB ((ea
+ Q16_BOT
) & VAMASK
, t
); /* rewrite bottom */
1519 wra
= ReadB ((ea
+ Q16_TOP
) & VAMASK
); /* get top */
1520 if (wra
== 0) wra
= (slt
- 1) & DMASK8
; /* wrap if necc */
1521 else wra
= wra
- 1; /* dec top */
1522 WriteB ((ea
+ Q16_TOP
) & VAMASK
, wra
); /* rewrite top */
1524 WriteH ((ea
+ Q16_BASE
+ (wra
* Q16_SLNT
)) & VAMASK
, val
); /* write slot */
1528 uint32
remfmq (uint32 ea
, uint32 r1
, uint32 flg
)
1530 uint32 slt
, usd
, rda
, t
;
1532 t
= ReadH (ea
); /* get slots/used */
1533 slt
= (t
>> 8) & DMASK8
; /* # slots */
1534 usd
= t
& DMASK8
; /* # used */
1535 if (usd
== 0) return CC_V
; /* empty? */
1536 usd
= usd
- 1; /* dec used */
1537 WriteB (ea
+ Q16_USD
, usd
); /* rewrite */
1538 if (flg
) { /* RBL? */
1539 rda
= ReadB ((ea
+ Q16_BOT
) & VAMASK
); /* get bottom */
1540 if (rda
== 0) rda
= (slt
- 1) & DMASK8
; /* wrap if necc */
1541 else rda
= rda
- 1; /* dec bottom */
1542 WriteB ((ea
+ Q16_BOT
) & VAMASK
, rda
); /* rewrite bottom */
1545 rda
= ReadB ((ea
+ Q16_TOP
) & VAMASK
); /* RTL, get top */
1546 t
= rda
+ 1; /* adv top */
1547 if (t
>= slt
) t
= 0; /* wrap if necc */
1548 WriteB ((ea
+ Q16_TOP
) & VAMASK
, t
); /* rewrite top */
1550 R
[r1
] = ReadH ((ea
+ Q16_BASE
+ (rda
* Q16_SLNT
)) & VAMASK
); /* read slot */
1551 if (usd
) return CC_G
; /* set cc's */
1555 /* Automatic interrupt processing */
1557 #define CCW16_ERR(x) (((x)|CCW16_INIT|CCW16_NOP|CCW16_Q) & \
1558 ~(CCW16_CHN|CCW16_CON|CCW16_HI))
1560 uint32
int_auto (uint32 dev
, uint32 cc
)
1562 int32 ba
, ea
, by
, vec
, ccw
, bpi
, fnc
, trm
, st
, i
, t
;
1563 t_bool sysqe
= FALSE
;
1567 vec
= ReadH (INTSVT
+ dev
+ dev
); /* get vector */
1568 if ((vec
& 1) == 0) { /* immed int? */
1569 WriteH (vec
, BUILD_PSW (cc
)); /* write PSW, PC */
1570 WriteH ((vec
+ 2) & VAMASK
, PC
);
1571 cc
= newPSW (ReadH ((vec
+ 4) & VAMASK
)); /* read PSW */
1572 PC
= (vec
+ 6) & VAMASK
; /* set new PC */
1575 vec
= vec
& ~1; /* get CCW addr */
1576 ccw
= ReadH (vec
); /* read CCW */
1577 if (DEV_ACC (dev
)) dev_tab
[dev
] (dev
, IO_ADR
, 0); /* select dev */
1578 if (ccw
& CCW16_NOP
) break; /* NOP? exit */
1579 if (ccw
& CCW16_INIT
) { /* init set? */
1580 ccw
= ccw
& ~CCW16_INIT
; /* clr init */
1581 WriteH (vec
, ccw
); /* rewrite */
1582 if (ccw
& CCW16_OC
) { /* OC set? */
1583 if (DEV_ACC (dev
)) { /* dev exist? */
1584 by
= ReadB ((vec
+ CCB16_IOC
) & VAMASK
);/* read OC byte */
1585 dev_tab
[dev
] (dev
, IO_OC
, by
); /* send to dev */
1587 break; /* and exit */
1590 fnc
= CCW16_FNC (ccw
); /* get func */
1591 st
= 0; /* default status */
1592 if (fnc
== CCW16_DMT
) { /* DMT */
1593 ba
= ReadH ((vec
+ CCB16_STR
) & VAMASK
); /* get cnt wd */
1594 ba
= (ba
- 1) & DMASK16
; /* decr */
1595 WriteH ((vec
+ CCB16_STR
) & VAMASK
, ba
); /* rewrite */
1596 if (ba
) break; /* nz? exit */
1598 else if (fnc
!= CCW16_NUL
) { /* rd or wr? */
1599 if (DEV_ACC (dev
)) /* dev exist? */
1600 st
= dev_tab
[dev
] (dev
, IO_SS
, 0); /* sense status */
1601 else st
= CC_V
; /* else timeout */
1602 if (st
& 0xF) { /* error? */
1603 ccw
= CCW16_ERR (ccw
); /* neuter CCW */
1604 WriteH (vec
, ccw
); /* rewrite CCW */
1606 else { /* ok, do xfer */
1607 bpi
= CCW16_BPI (ccw
); /* get bytes/int */
1608 if (bpi
== 0) bpi
= 16; /* max 16B */
1609 ba
= ReadH ((vec
+ CCB16_STR
) & VAMASK
); /* get start */
1610 for (i
= 0; i
< bpi
; i
++) { /* do # bytes */
1611 if (fnc
== CCW16_RD
) { /* chan read? */
1612 by
= dev_tab
[dev
] (dev
, IO_RD
, 0); /* read byte */
1613 WriteB (ba
, by
); /* store */
1615 else { /* chan write */
1616 by
= ReadB (ba
); /* fetch */
1617 dev_tab
[dev
] (dev
, IO_WD
, by
); /* write byte */
1619 ba
= (ba
+ 1) & VAMASK
; /* incr addr */
1621 WriteH ((vec
+ CCB16_STR
) & VAMASK
, ba
); /* rewrite */
1622 ea
= ReadH ((vec
+ CCB16_END
) & VAMASK
); /* get end */
1623 trm
= ReadB ((vec
+ CCB16_TRM
) & VAMASK
); /* get term chr */
1624 if ((ba
<= ea
) && /* not at end? */
1625 (((ccw
& CCW16_TRM
) == 0) || /* not term chr? */
1626 (by
!= trm
))) break; /* exit */
1627 ccw
= ccw
| CCW16_NOP
; /* nop CCW */
1628 WriteH (vec
, ccw
); /* rewrite CCW */
1629 } /* end else sta */
1632 /* Termination phase */
1634 t
= (dev
<< 8) | (st
& DMASK8
); /* form dev/sta */
1635 WriteH ((vec
+ CCB16_DEV
) & VAMASK
, t
); /* write dev/sta */
1636 if (ccw
& CCW16_Q
) { /* q request? */
1637 t
= ReadH (SQP
); /* get sys q addr */
1638 if (addtoq (t
, vec
, ccw
& CCW16_HI
)) { /* add to sys q */
1639 WriteH (SQOP
, vec
); /* write to ovflo */
1640 return swap_psw (SQVPSW
, cc
); /* take exception */
1642 else sysqe
= TRUE
; /* made an entry */
1644 if (ccw
& CCW16_CHN
) { /* chain */
1645 t
= ReadH ((vec
+ CCB16_CHN
) & VAMASK
); /* get chain wd */
1646 WriteH (INTSVT
+ dev
+ dev
, t
); /* wr int svc tab */
1647 if (ccw
& CCW16_CON
) rpt
= TRUE
; /* cont? */
1653 if (sysqe
&& (PSW
& PSW_SQI
)) /* sys q ent & enb? */
1654 return swap_psw (SQIPSW
, cc
); /* take sys q int */
1658 /* Display register device */
1660 uint32
display (uint32 dev
, uint32 op
, uint32 dat
)
1666 case IO_ADR
: /* select */
1667 if (!drmod
) drpos
= srpos
= 0; /* norm mode? clr */
1668 return BY
; /* byte only */
1670 case IO_OC
: /* command */
1672 if (op
== 0x40) { /* x40 = inc */
1674 drpos
= srpos
= 0; /* init cntrs */
1676 else if (op
== 0x80) drmod
= 0; /* x80 = norm */
1679 case IO_WD
: /* write */
1681 DR
= (DR
& ~(DMASK8
<< (drpos
* 8))) | (dat
<< (drpos
* 8));
1682 else if (drpos
== 4) DRX
= dat
;
1683 drpos
= (drpos
+ 1) &
1684 ((cpu_unit
.flags
& (UNIT_716
| UNIT_816
))? 7: 3);
1687 case IO_RD
: /* read */
1688 t
= (SR
>> (srpos
* 8)) & DMASK8
;
1692 case IO_SS
: /* status */
1699 /* Memory interface routines
1701 ReadB read byte (processor)
1702 ReadH read halfword (processor)
1703 ReadF read fullword (processor)
1704 WriteB write byte (processor)
1705 WriteH write halfword (processor)
1706 WriteF write fullword (processor)
1707 IOReadB read byte (IO)
1708 IOWriteB write byte (IO)
1709 IOReadH read halfword (IO)
1710 IOWriteH write halfword (IO)
1713 uint32
ReadB (uint32 loc
)
1715 uint32 pa
= (loc
+ ((loc
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1717 return ((M
[pa
>> 1] >> ((pa
& 1)? 0: 8)) & DMASK8
);
1720 uint32
ReadH (uint32 loc
)
1722 uint32 pa
= (loc
+ ((loc
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1727 uint32
ReadF (uint32 loc
, uint32 rel
)
1730 uint32 loc1
= (loc
+ 2) & VAMASK
;
1732 loc
= loc
& VAMASK
; /* FP doesn't mask */
1734 pa
= (loc
+ ((loc
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1735 pa1
= (loc1
+ ((loc1
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1741 return (((uint32
) M
[pa
>> 1]) << 16) | ((uint32
) M
[pa1
>> 1]);
1744 void WriteB (uint32 loc
, uint32 val
)
1746 uint32 pa
= (loc
+ ((loc
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1749 if (MEM_ADDR_OK (pa
)) M
[pa
>> 1] = ((pa
& 1)?
1750 ((M
[pa
>> 1] & ~DMASK8
) | val
):
1751 ((M
[pa
>> 1] & DMASK8
) | (val
<< 8)));
1755 void WriteH (uint32 loc
, uint32 val
)
1757 uint32 pa
= (loc
+ ((loc
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1759 if (MEM_ADDR_OK (pa
)) M
[pa
>> 1] = val
& DMASK16
;
1763 void WriteF (uint32 loc
, uint32 val
, uint32 rel
)
1766 uint32 loc1
= (loc
+ 2) & VAMASK
;
1768 loc
= loc
& VAMASK
; /* FP doesn't mask */
1770 pa
= (loc
+ ((loc
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1771 pa1
= (loc1
+ ((loc1
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1777 if (MEM_ADDR_OK (pa
)) M
[pa
>> 1] = (val
>> 16) & DMASK16
;
1778 if (MEM_ADDR_OK (pa1
)) M
[pa1
>> 1] = val
& DMASK16
;
1782 uint32
IOReadB (uint32 loc
)
1784 return ((M
[loc
>> 1] >> ((loc
& 1)? 0: 8)) & DMASK8
);
1787 void IOWriteB (uint32 loc
, uint32 val
)
1790 M
[loc
>> 1] = ((loc
& 1)?
1791 ((M
[loc
>> 1] & ~DMASK8
) | val
):
1792 ((M
[loc
>> 1] & DMASK8
) | (val
<< 8)));
1796 uint32
IOReadH (uint32 loc
)
1798 return (M
[loc
>> 1] & DMASK16
);
1801 void IOWriteH (uint32 loc
, uint32 val
)
1803 M
[loc
>> 1] = val
& DMASK16
;
1809 t_stat
cpu_reset (DEVICE
*dptr
)
1811 qevent
= 0; /* no events */
1812 newPSW (0); /* PSW = 0 */
1813 DR
= 0; /* clr display */
1815 blk_io
.dfl
= blk_io
.cur
= blk_io
.end
= 0; /* no block IO */
1816 sim_brk_types
= sim_brk_dflt
= SWMASK ('E'); /* init bkpts */
1817 if (M
== NULL
) M
= (uint16
*) calloc (MAXMEMSIZE16E
>> 1, sizeof (uint16
));
1818 if (M
== NULL
) return SCPE_MEM
;
1819 pcq_r
= find_reg ("PCQ", NULL
, dptr
); /* init PCQ */
1820 if (pcq_r
) pcq_r
->qptr
= 0;
1821 else return SCPE_IERR
;
1825 /* Memory examine */
1827 t_stat
cpu_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
)
1829 if (sw
& SWMASK ('V')) {
1830 if (addr
> VAMASK
) return SCPE_NXM
;
1831 addr
= (addr
+ ((addr
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1833 if (addr
>= MEMSIZE
) return SCPE_NXM
;
1834 if (vptr
!= NULL
) *vptr
= IOReadH (addr
);
1838 /* Memory deposit */
1840 t_stat
cpu_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
)
1842 if (sw
& SWMASK ('V')) {
1843 if (addr
> VAMASK
) return SCPE_NXM
;
1844 addr
= (addr
+ ((addr
& VA_S1
)? s1_rel
: s0_rel
)) & PAMASK16E
;
1846 if (addr
>= MEMSIZE
) return SCPE_NXM
;
1847 IOWriteH (addr
, val
);
1851 /* Change memory size */
1853 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
1858 if ((val
<= 0) || ((val
& 0xFFF) != 0) ||
1859 (((uint32
) val
) > ((uptr
->flags
& UNIT_816E
)? MAXMEMSIZE16E
: MAXMEMSIZE16
)))
1861 for (i
= val
; i
< MEMSIZE
; i
= i
+ 2) mc
= mc
| M
[i
>> 1];
1862 if ((mc
!= 0) && (!get_yn ("Really truncate memory [N]?", FALSE
)))
1865 for (i
= MEMSIZE
; i
< MAXMEMSIZE16E
; i
= i
+ 2) M
[i
>> 1] = 0;
1869 /* Change CPU model */
1871 t_stat
cpu_set_model (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
1875 if (!(val
& UNIT_816E
) && (MEMSIZE
> MAXMEMSIZE16
)) {
1876 MEMSIZE
= MAXMEMSIZE16
;
1877 for (i
= MEMSIZE
; i
< MAXMEMSIZE16E
; i
= i
+ 2) M
[i
>> 1] = 0;
1878 printf ("Reducing memory to 64KB\n");
1883 /* Set console interrupt */
1885 t_stat
cpu_set_consint (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
1887 if ((uptr
->flags
& (UNIT_716
| UNIT_816
| UNIT_816E
)) == 0)
1889 if (PSW
& PSW_AIO
) SET_INT (v_DS
);
1895 t_stat
cpu_set_hist (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
1901 for (i
= 0; i
< hst_lnt
; i
++) hst
[i
].vld
= 0;
1905 lnt
= (uint32
) get_uint (cptr
, 10, HIST_MAX
, &r
);
1906 if ((r
!= SCPE_OK
) || (lnt
&& (lnt
< HIST_MIN
))) return SCPE_ARG
;
1914 hst
= (InstHistory
*) calloc (lnt
, sizeof (InstHistory
));
1915 if (hst
== NULL
) return SCPE_MEM
;
1923 t_stat
cpu_show_hist (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
1925 int32 op
, k
, di
, lnt
;
1926 char *cptr
= (char *) desc
;
1927 t_value sim_eval
[2];
1930 extern t_stat
fprint_sym (FILE *ofile
, t_addr addr
, t_value
*val
,
1931 UNIT
*uptr
, int32 sw
);
1933 if (hst_lnt
== 0) return SCPE_NOFNC
; /* enabled? */
1935 lnt
= (int32
) get_uint (cptr
, 10, hst_lnt
, &r
);
1936 if ((r
!= SCPE_OK
) || (lnt
== 0)) return SCPE_ARG
;
1939 di
= hst_p
- lnt
; /* work forward */
1940 if (di
< 0) di
= di
+ hst_lnt
;
1941 fprintf (st
, "PC r1 opnd ea IR\n\n");
1942 for (k
= 0; k
< lnt
; k
++) { /* print specified */
1943 h
= &hst
[(di
++) % hst_lnt
]; /* entry pointer */
1944 if (h
->vld
) { /* instruction? */
1945 fprintf (st
, "%04X %04X %04X ", h
->pc
, h
->r1
, h
->opnd
);
1946 op
= (h
->ir1
>> 8) & 0xFF;
1947 if (OP_TYPE (op
) >= OP_RX
) fprintf (st
, "%04X ", h
->ea
);
1948 else fprintf (st
, " ");
1949 sim_eval
[0] = h
->ir1
;
1950 sim_eval
[1] = h
->ir2
;
1951 if ((fprint_sym (st
, h
->pc
, sim_eval
, &cpu_unit
, SWMASK ('M'))) > 0)
1952 fprintf (st
, "(undefined) %04X", h
->ir1
);
1953 fputc ('\n', st
); /* end line */
1954 } /* end if instruction */