1 /* id16_cpu.c: Interdata 16b CPU simulator
2
3 Copyright (c) 2000-2008, 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 Interdata 16b CPU
27
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 (Mark Hittinger)
32 22-Sep-05 RMS Fixed declarations (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 (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 (Mark Pizzolato)
40
41 The register state for the Interdata 16b CPU is:
42
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
52
53 The Interdata 16b systems have four instruction formats: register to
54 register, short format, register to memory, and register to storage.
55 The formats are:
56
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
61
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
66
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
71 | address |
72 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
73
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 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
78 | address |
79 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
80
81 For register-memory and register-storage instructions, an effective
82 address is calculated as follows:
83
84 effective addr = address + RX (if RX > 0)
85
86 Register-memory instructions can access an address space of 64K bytes.
87
88 The Interdata 16b product line had many different models, with varying
89 instruction sets:
90
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
98
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.
103
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.
110
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.
115
116 General notes:
117
118 1. Reasons to stop. The simulator can be stopped by:
119
120 HALT instruction
121 breakpoint encountered
122 wait state and no I/O outstanding
123 invalid instruction
124 I/O error in I/O simulator
125
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.
131
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.
136
137 4. Adding I/O devices. These modules must be modified:
138
139 id_defs.h add device interrupt definitions
140 id16_sys.c add sim_devices table entry
141 */
142
143 #include "id_defs.h"
144
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 */
150
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)
162
163 #define HIST_MIN 64
164 #define HIST_MAX 65536
165
166 typedef struct {
167 uint16 vld;
168 uint16 pc;
169 uint16 ir1;
170 uint16 ir2;
171 uint16 r1;
172 uint16 ea;
173 uint16 opnd;
174 } InstHistory;
175
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) \
180 cc = CC_L; \
181 else if (x) \
182 cc = CC_G; \
183 else cc = 0
184 #define CC_GL_32(x) if ((x) & SIGN32) \
185 cc = CC_L; \
186 else if (x) \
187 cc = CC_G; \
188 else cc = 0
189 #define BUILD_PSW(x) (((PSW & ~CC_MASK) | (x)) & psw_mask)
190 #define CPU_x16 (cpu_unit.flags & (UNIT_716 | UNIT_816 | UNIT_816E))
191
192 uint32 GREG[16] = { 0 }; /* general registers */
193 uint16 *M = NULL; /* memory */
194 uint32 *R = &GREG[0]; /* register set ptr */
195 uint32 F[8] = { 0 }; /* sp fp registers */
196 dpr_t D[8] = { 0 }; /* dp fp registers */
197 uint32 PSW = 0; /* processor status word */
198 uint32 psw_mask = PSW_x16; /* PSW mask */
199 uint32 PC = 0; /* program counter */
200 uint32 SR = 0; /* switch register */
201 uint32 DR = 0; /* display register */
202 uint32 DRX = 0; /* display extension */
203 uint32 drmod = 0; /* mode */
204 uint32 srpos = 0; /* switch register pos */
205 uint32 drpos = 0; /* display register pos */
206 uint32 s0_rel = 0; /* S0 relocation */
207 uint32 s1_rel = 0; /* S1 relocation */
208 uint32 int_req[INTSZ] = { 0 }; /* interrupt requests */
209 uint32 int_enb[INTSZ] = { 0 }; /* interrupt enables */
210 int32 blkiop = -1; /* block I/O in prog */
211 uint32 qevent = 0; /* events */
212 uint32 stop_inst = 0; /* stop on ill inst */
213 uint32 stop_wait = 0; /* stop on wait */
214 uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
215 int32 pcq_p = 0; /* PC queue ptr */
216 REG *pcq_r = NULL; /* PC queue reg ptr */
217 uint32 dec_flgs = 0; /* decode flags */
218 uint32 fp_in_hwre = 0; /* ucode/hwre fp */
219 uint32 pawidth = PAWIDTH16; /* phys addr mask */
220 uint32 hst_p = 0; /* history pointer */
221 uint32 hst_lnt = 0; /* history length */
222 InstHistory *hst = NULL; /* instruction history */
223 struct BlockIO blk_io; /* block I/O status */
224 uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
225
226 extern int32 sim_interval;
227 extern int32 sim_int_char;
228 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
229 extern t_bool sim_idle_enab;
230
231 uint32 ReadB (uint32 loc);
232 uint32 ReadH (uint32 loc);
233 void WriteB (uint32 loc, uint32 val);
234 void WriteH (uint32 loc, uint32 val);
235 uint32 int_auto (uint32 dev, uint32 cc);
236 uint32 addtoq (uint32 ea, uint32 val, uint32 flg);
237 uint32 remfmq (uint32 ea, uint32 r1, uint32 flg);
238 uint32 newPSW (uint32 val);
239 uint32 swap_psw (uint32 loc, uint32 cc);
240 uint32 testsysq (uint32);
241 uint32 display (uint32 dev, uint32 op, uint32 dat);
242 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
243 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
244 t_stat cpu_reset (DEVICE *dptr);
245 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
246 t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc);
247 t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc);
248 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
249 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
250
251 extern t_bool devtab_init (void);
252 extern void int_eval (void);
253 extern uint32 int_getdev (void);
254 extern t_bool sch_blk (uint32 dev);
255 extern uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea);
256 extern uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea);
257 extern uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea);
258 extern uint32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea);
259 extern uint32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea);
260 extern uint32 f_fix (uint32 op, uint32 r1, uint32 r2);
261 extern uint32 f_flt (uint32 op, uint32 r1, uint32 r2);
262
263 /* Instruction decoding table - flags are first implementation */
264
265 const uint16 decrom[256] = {
266 0, /* 00 */
267 OP_RR, /* BALR */
268 OP_RR, /* BTCR */
269 OP_RR, /* BFCR */
270 OP_RR, /* NHR */
271 OP_RR, /* CLHR */
272 OP_RR, /* OHR */
273 OP_RR, /* XHR */
274 OP_RR, /* LHR */
275 OP_RR | OP_716, /* CHR */
276 OP_RR, /* AHR */
277 OP_RR, /* SHR */
278 OP_RR, /* MHR */
279 OP_RR, /* DHR */
280 OP_RR, /* ACHR */
281 OP_RR, /* SCHR */
282 0, 0, 0, /* 10:12 */
283 OP_RR | OP_816E | OP_PRV, /* SETMR */
284 0, 0, 0, 0, /* 14:1F */
285 0, 0, 0, 0, 0, 0, 0, 0,
286 OP_NO | OP_716, /* BTBS */
287 OP_NO | OP_716, /* BTFS */
288 OP_NO | OP_716, /* BFBS */
289 OP_NO | OP_716, /* BFFS */
290 OP_NO | OP_716, /* LIS */
291 OP_NO | OP_716, /* LCS */
292 OP_NO | OP_716, /* AIS */
293 OP_NO | OP_716, /* SIS */
294 OP_NO | OP_ID4, /* LER */
295 OP_NO | OP_ID4, /* CER */
296 OP_NO | OP_ID4, /* AER */
297 OP_NO | OP_ID4, /* SER */
298 OP_NO | OP_ID4, /* MER */
299 OP_NO | OP_ID4, /* DER */
300 OP_NO | OP_816, /* FXR */
301 OP_NO | OP_816, /* FLR */
302 0, 0, 0, /* 30:32 */
303 OP_NO | OP_816E | OP_PRV, /* LPSR */
304 0, 0, 0, 0, /* 34:37 */
305 OP_NO | OP_816 | OP_DPF, /* LDR */
306 OP_NO | OP_816 | OP_DPF, /* CDR */
307 OP_NO | OP_816 | OP_DPF, /* ADR */
308 OP_NO | OP_816 | OP_DPF, /* SDR */
309 OP_NO | OP_816 | OP_DPF, /* MDR */
310 OP_NO | OP_816 | OP_DPF, /* DDR */
311 OP_NO | OP_816 | OP_DPF, /* FXDR */
312 OP_NO | OP_816 | OP_DPF, /* FLDR */
313 OP_RX, /* STH */
314 OP_RX, /* BAL */
315 OP_RX, /* BTC */
316 OP_RX, /* BFC */
317 OP_RXH, /* NH */
318 OP_RXH, /* CLH */
319 OP_RXH, /* OH */
320 OP_RXH, /* XH */
321 OP_RXH, /* LH */
322 OP_RXH | OP_716, /* CH */
323 OP_RXH, /* AH */
324 OP_RXH, /* SH */
325 OP_RXH, /* MH */
326 OP_RXH, /* DH */
327 OP_RXH, /* ACH */
328 OP_RXH, /* SCH */
329 0, 0, 0, /* 50:52 */
330 OP_RXH | OP_816E | OP_PRV, /* SETM */
331 0, 0, 0, 0, /* 54:5F */
332 0, 0, 0, 0, 0, 0, 0, 0,
333 OP_RX | OP_ID4, /* STE */
334 OP_RXH | OP_716, /* AHM */
335 0, 0, /* 62:63 */
336 OP_RX | OP_716, /* ATL */
337 OP_RX | OP_716, /* ABL */
338 OP_RX | OP_716, /* RTL */
339 OP_RX | OP_716, /* RBL */
340 OP_RX | OP_ID4, /* LE */
341 OP_RX | OP_ID4, /* CE */
342 OP_RX | OP_ID4, /* AE */
343 OP_RX | OP_ID4, /* SE */
344 OP_RX | OP_ID4, /* ME */
345 OP_RX | OP_ID4, /* DE */
346 0, 0, /* 6E:6F */
347 OP_RX | OP_816 | OP_DPF, /* STD */
348 OP_RX | OP_816, /* SME */
349 OP_RX | OP_816, /* LME */
350 OP_RXH | OP_816E | OP_PRV, /* LPS */
351 0, 0, 0, 0, /* 74:7F */
352 OP_RX | OP_816 | OP_DPF, /* LD */
353 OP_RX | OP_816 | OP_DPF, /* CD */
354 OP_RX | OP_816 | OP_DPF, /* AD */
355 OP_RX | OP_816 | OP_DPF, /* SD */
356 OP_RX | OP_816 | OP_DPF, /* MD */
357 OP_RX | OP_816 | OP_DPF, /* DD */
358 OP_RX | OP_816 | OP_DPF, /* STMD */
359 OP_RX | OP_816 | OP_DPF, /* LMD */
360 0, 0, 0, 0, 0, 0, 0, 0, /* 80:8F */
361 0, 0, 0, 0, 0, 0, 0, 0,
362 OP_NO | OP_716, /* SRLS */
363 OP_NO | OP_716, /* SLLS */
364 OP_NO, /* STBR */
365 OP_RR, /* LDBR */
366 OP_RR | OP_716, /* EXBR */
367 OP_NO | OP_716 | OP_PRV, /* EPSR */
368 OP_RR | OP_PRV, /* WBR */
369 OP_RR | OP_PRV, /* RBR */
370 OP_RR | OP_716 | OP_PRV, /* WHR */
371 OP_RR | OP_716 | OP_PRV, /* RHR */
372 OP_RR | OP_PRV, /* WDR */
373 OP_RR | OP_PRV, /* RDR */
374 OP_RR | OP_716, /* MHUR */
375 OP_RR | OP_PRV, /* SSR */
376 OP_RR | OP_PRV, /* OCR */
377 OP_RR | OP_PRV, /* AIR */
378 0, 0, 0, 0, 0, 0, 0, 0, /* A0:AF */
379 0, 0, 0, 0, 0, 0, 0, 0,
380 0, 0, 0, 0, 0, 0, 0, 0, /* B0:BF */
381 0, 0, 0, 0, 0, 0, 0, 0,
382 OP_RX, /* BXH */
383 OP_RX, /* BXLE */
384 OP_RX | OP_PRV, /* LPSW */
385 OP_RS | OP_716, /* THI */
386 OP_RS, /* NHI */
387 OP_RS, /* CLHI */
388 OP_RS, /* OHI */
389 OP_RS, /* XHI */
390 OP_RS, /* LHI */
391 OP_RS | OP_716, /* CHI */
392 OP_RS, /* AHI */
393 OP_RS, /* SHI */
394 OP_RS, /* SRHL */
395 OP_RS, /* SLHL */
396 OP_RS, /* SRHA */
397 OP_RS, /* SLHA */
398 OP_RX | OP_ID4, /* STM */
399 OP_RX | OP_ID4, /* LM */
400 OP_RX, /* STB */
401 OP_RXB, /* LDB */
402 OP_RXB | OP_716, /* CLB */
403 OP_RX | OP_ID4 | OP_PRV, /* AL */
404 OP_RXH | OP_PRV, /* WB */
405 OP_RXH | OP_PRV, /* RB */
406 OP_RX | OP_716 | OP_PRV, /* WH */
407 OP_RX | OP_716 | OP_PRV, /* RH */
408 OP_RX | OP_PRV, /* WD */
409 OP_RX | OP_PRV, /* RD */
410 OP_RXH | OP_716, /* MHU */
411 OP_RX | OP_PRV, /* SS */
412 OP_RX | OP_PRV, /* OC */
413 OP_RX | OP_PRV, /* AI */
414 0, /* E0 */
415 OP_RX | OP_716, /* SVC */
416 OP_RS | OP_716 | OP_PRV, /* SINT */
417 0, 0, 0, 0, 0, 0, 0, /* E3:E9 */
418 OP_RS | OP_716, /* RRL */
419 OP_RS | OP_716, /* RLL */
420 OP_RS | OP_716, /* SRL */
421 OP_RS | OP_716, /* SLL */
422 OP_RS | OP_716, /* SRA */
423 OP_RS | OP_716, /* SLA */
424 0, 0, 0, 0, 0, 0, 0, 0, /* F0:FF */
425 0, 0, 0, 0, 0, 0, 0, 0
426 };
427
428 /* 8/16E relocation constants for S0 and S1, indexed by PSW<8:11> */
429
430 static uint32 s0_rel_const[16] = { /* addr 0-7FFF */
431 0x00000, 0x00000, 0x00000, 0x00000, /* 0 = no reloc */
432 0x00000, 0x00000, 0x00000, 0x08000, /* 8000 = rel to S1 */
433 0x08000, 0x08000, 0x08000, 0x08000,
434 0x08000, 0x08000, 0x08000, 0x00000
435 };
436
437 static uint32 s1_rel_const[16] = { /* addr 8000-FFFF */
438 0x00000, 0x08000, 0x10000, 0x18000, /* reloc const must */
439 0x20000, 0x28000, 0x30000, 0xFFF8000, /* "sub" base addr */
440 0x00000, 0x08000, 0x10000, 0x18000,
441 0x20000, 0x28000, 0x30000, 0x00000
442 };
443
444 /* CPU data structures
445
446 cpu_dev CPU device descriptor
447 cpu_unit CPU unit descriptor
448 cpu_reg CPU register list
449 cpu_mod CPU modifiers list
450 */
451
452 DIB cpu_dib = { d_DS, -1, v_DS, NULL, &display, NULL };
453
454 UNIT cpu_unit = {
455 UDATA (NULL, UNIT_FIX | UNIT_BINK | UNIT_716, MAXMEMSIZE16)
456 };
457
458 REG cpu_reg[] = {
459 { HRDATA (PC, PC, 16) },
460 { HRDATA (R0, GREG[0], 16) },
461 { HRDATA (R1, GREG[1], 16) },
462 { HRDATA (R2, GREG[2], 16) },
463 { HRDATA (R3, GREG[3], 16) },
464 { HRDATA (R4, GREG[4], 16) },
465 { HRDATA (R5, GREG[5], 16) },
466 { HRDATA (R6, GREG[6], 16) },
467 { HRDATA (R7, GREG[7], 16) },
468 { HRDATA (R8, GREG[8], 16) },
469 { HRDATA (R9, GREG[9], 16) },
470 { HRDATA (R10, GREG[10], 16) },
471 { HRDATA (R11, GREG[11], 16) },
472 { HRDATA (R12, GREG[12], 16) },
473 { HRDATA (R13, GREG[13], 16) },
474 { HRDATA (R14, GREG[14], 16) },
475 { HRDATA (R15, GREG[15], 16) },
476 { HRDATA (FR0, F[0], 32) },
477 { HRDATA (FR2, F[1], 32) },
478 { HRDATA (FR4, F[2], 32) },
479 { HRDATA (FR6, F[3], 32) },
480 { HRDATA (FR8, F[4], 32) },
481 { HRDATA (FR10, F[5], 32) },
482 { HRDATA (FR12, F[6], 32) },
483 { HRDATA (FR14, F[7], 32) },
484 { HRDATA (D0H, D[0].h, 32) },
485 { HRDATA (D0L, D[0].l, 32) },
486 { HRDATA (D2H, D[1].h, 32) },
487 { HRDATA (D2L, D[1].l, 32) },
488 { HRDATA (D4H, D[2].h, 32) },
489 { HRDATA (D4L, D[2].l, 32) },
490 { HRDATA (D6H, D[3].h, 32) },
491 { HRDATA (D6L, D[3].l, 32) },
492 { HRDATA (D8H, D[4].h, 32) },
493 { HRDATA (D8L, D[4].l, 32) },
494 { HRDATA (D10H, D[5].h, 32) },
495 { HRDATA (D10L, D[5].l, 32) },
496 { HRDATA (D12L, D[6].l, 32) },
497 { HRDATA (D12H, D[6].h, 32) },
498 { HRDATA (D14H, D[7].h, 32) },
499 { HRDATA (D14L, D[7].l, 32) },
500 { HRDATA (PSW, PSW, 16) },
501 { HRDATA (CC, PSW, 4) },
502 { HRDATA (SR, SR, 16) },
503 { HRDATA (DR, DR, 32) },
504 { HRDATA (DRX, DRX, 8) },
505 { FLDATA (DRMOD, drmod, 0) },
506 { FLDATA (SRPOS, srpos, 0) },
507 { HRDATA (DRPOS, drpos, 3) },
508 { BRDATA (IRQ, int_req, 16, 32, 8) },
509 { BRDATA (IEN, int_enb, 16, 32, 8) },
510 { HRDATA (QEVENT, qevent, 4), REG_HRO },
511 { FLDATA (STOP_INST, stop_inst, 0) },
512 { FLDATA (STOP_WAIT, stop_inst, 0) },
513 { BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO+REG_CIRC },
514 { HRDATA (PCQP, pcq_p, 6), REG_HRO },
515 { HRDATA (WRU, sim_int_char, 8) },
516 { HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO },
517 { HRDATA (BLKIOC, blk_io.cur, 16), REG_HRO },
518 { HRDATA (BLKIOE, blk_io.end, 16), REG_HRO },
519 { NULL }
520 };
521
522 MTAB cpu_mod[] = {
523 { UNIT_TYPE, 0, "I3", "I3", &cpu_set_model },
524 { UNIT_TYPE, UNIT_ID4, "I4", "I4", &cpu_set_model },
525 { UNIT_TYPE, UNIT_716, "7/16", "716", &cpu_set_model },
526 { UNIT_TYPE, UNIT_816, "8/16", "816", &cpu_set_model },
527 { UNIT_TYPE, UNIT_816E, "8/16E", "816E", &cpu_set_model },
528 { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
529 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
530 { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
531 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
532 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
533 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
534 { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
535 { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
536 { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
537 { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },
538 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
539 &cpu_set_consint, NULL, NULL },
540 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
541 &cpu_set_hist, &cpu_show_hist },
542 { 0 }
543 };
544
545 DEVICE cpu_dev = {
546 "CPU", &cpu_unit, cpu_reg, cpu_mod,
547 1, 16, 18, 2, 16, 16,
548 &cpu_ex, &cpu_dep, &cpu_reset,
549 NULL, NULL, NULL,
550 &cpu_dib, 0
551 };
552
sim_instr(void)553 t_stat sim_instr (void)
554 {
555 uint32 cc;
556 t_stat reason;
557
558 /* Restore register state */
559
560 if (devtab_init ()) /* check conflicts */
561 return SCPE_STOP;
562 pawidth = PAWIDTH16; /* default width */
563 if (cpu_unit.flags & UNIT_816E) { /* 8/16E? */
564 dec_flgs = 0; /* all instr ok */
565 fp_in_hwre = 1; /* fp in hwre */
566 pawidth = PAWIDTH16E; /* 18b phys addr */
567 psw_mask = PSW_816E; /* mem ext bits */
568 }
569 else if (cpu_unit.flags & UNIT_816) { /* 8/16? */
570 dec_flgs = OP_816E;
571 fp_in_hwre = 1;
572 pawidth = PAWIDTH16;
573 psw_mask = PSW_x16;
574 }
575 else if (cpu_unit.flags & UNIT_716) { /* I5, 70, 80, 7/16? */
576 dec_flgs = OP_816 | OP_816E;
577 fp_in_hwre = 0;
578 pawidth = PAWIDTH16;
579 psw_mask = PSW_x16;
580 }
581 else if (cpu_unit.flags & UNIT_ID4) { /* I4? */
582 dec_flgs = OP_716 | OP_816 | OP_816E;
583 fp_in_hwre = 0;
584 pawidth = PAWIDTH16;
585 psw_mask = PSW_ID4;
586 }
587 else {
588 dec_flgs = OP_ID4 | OP_716 | OP_816 | OP_816E; /* I3 */
589 fp_in_hwre = 0;
590 pawidth = PAWIDTH16;
591 psw_mask = PSW_ID4;
592 }
593 int_eval (); /* eval interrupts */
594 cc = newPSW (PSW & psw_mask); /* split PSW, eval wait */
595 reason = 0;
596
597 /* Process events */
598
599 while (reason == 0) { /* loop until halted */
600 uint32 dev, drom, inc, lim, opnd;
601 uint32 op, r1, r1p1, r2, ea, oPC;
602 uint32 rslt, t, map;
603 uint32 ir1, ir2, ityp;
604 int32 sr, st;
605
606 if (sim_interval <= 0) { /* check clock queue */
607 if ((reason = sim_process_event ()))
608 break;
609 int_eval ();
610 }
611
612 if (qevent) { /* any events? */
613 if (qevent & EV_BLK) { /* block I/O in prog? */
614 dev = blk_io.dfl & DEV_MAX; /* get device */
615 cc = dev_tab[dev] (dev, IO_SS, 0) & 0xF; /* sense status */
616 if (cc == STA_BSY) { /* just busy? */
617 sim_interval = 0; /* force I/O event */
618 continue;
619 }
620 else if (cc == 0) { /* ready? */
621 if (blk_io.dfl & BL_RD) { /* read? */
622 t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */
623 if ((t == 0) && (blk_io.dfl & BL_LZ))
624 continue;
625 blk_io.dfl = blk_io.dfl & ~BL_LZ; /* non-zero seen */
626 WriteB (blk_io.cur, t); /* write mem */
627 }
628 else { /* write */
629 t = ReadB (blk_io.cur); /* read mem */
630 dev_tab[dev] (dev, IO_WD, t); /* put byte */
631 }
632 if (blk_io.cur != blk_io.end) { /* more to do? */
633 blk_io.cur = (blk_io.cur + 1) & VAMASK; /* incr addr */
634 continue;
635 }
636 }
637 qevent = qevent & ~EV_BLK; /* clr block I/O flg */
638 int_eval (); /* re-eval intr */
639 continue;
640 }
641
642 if ((qevent & EV_INT) && (PSW & PSW_EXI)) { /* interrupt? */
643 if (PSW & PSW_AIO) { /* auto enabled? */
644 dev = int_getdev (); /* get int dev */
645 cc = int_auto (dev, cc); /* do auto intr */
646 int_eval (); /* re-eval intr */
647 }
648 else cc = swap_psw (EXIPSW, cc); /* old type, swap */
649 continue;
650 }
651
652 if (PSW & PSW_WAIT) { /* wait state? */
653 if (sim_idle_enab) /* idling enabled? */
654 sim_idle (TMR_LFC, TRUE);
655 else sim_interval = sim_interval - 1; /* no, count cycle */
656 continue;
657 }
658
659 qevent = 0; /* no events */
660 } /* end if event */
661
662 /* Fetch and decode instruction */
663
664 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
665 reason = STOP_IBKPT; /* stop simulation */
666 break;
667 }
668
669 sim_interval = sim_interval - 1;
670
671 ir1 = ReadH (oPC = PC); /* fetch instr */
672 op = (ir1 >> 8) & 0xFF; /* isolate op, R1, R2 */
673 r1 = (ir1 >> 4) & 0xF;
674 r2 = ir1 & 0xF;
675 drom = decrom[op];
676 ityp = drom & OP_MASK;
677
678 if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
679 if (stop_inst) /* stop or */
680 reason = STOP_RSRV;
681 else cc = swap_psw (ILOPSW, cc); /* swap PSW */
682 continue;
683 }
684 if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */
685 cc = swap_psw (ILOPSW, cc); /* swap PSW */
686 continue;
687 }
688
689 switch (ityp) { /* decode instruction */
690
691 case OP_NO: /* no operand */
692 opnd = r2; /* assume short */
693 break;
694
695 case OP_RR: /* reg-reg */
696 opnd = R[r2]; /* operand is R2 */
697 break;
698
699 case OP_RS: /* reg-storage */
700 case OP_RX: /* reg-mem */
701 PC = (PC + 2) & VAMASK; /* increment PC */
702 ir2 = ea = ReadH (PC); /* fetch address */
703 if (r2) /* index calculation */
704 ea = (ir2 + R[r2]) & VAMASK;
705 opnd = ea; /* operand is ea */
706 break;
707
708 case OP_RXB: /* reg-mem byte */
709 PC = (PC + 2) & VAMASK; /* increment PC */
710 ir2 = ea = ReadH (PC); /* fetch address */
711 if (r2) /* index calculation */
712 ea = (ir2 + R[r2]) & VAMASK;
713 opnd = ReadB (ea); /* fetch operand */
714 break;
715
716 case OP_RXH: /* reg-mem halfword */
717 PC = (PC + 2) & VAMASK; /* increment PC */
718 ir2 = ea = ReadH (PC); /* fetch address */
719 if (r2) /* index calculation */
720 ea = (ir2 + R[r2]) & VAMASK;
721 opnd = ReadH (ea); /* fetch operand */
722 break;
723
724 default:
725 return SCPE_IERR;
726 }
727
728 if (hst_lnt) { /* instruction history? */
729 hst[hst_p].vld = 1;
730 hst[hst_p].pc = oPC;
731 hst[hst_p].ir1 = ir1;
732 hst[hst_p].ir2 = ir2;
733 hst[hst_p].r1 = R[r1];
734 hst[hst_p].ea = ea;
735 hst[hst_p].opnd = opnd;
736 hst_p = hst_p + 1;
737 if (hst_p >= hst_lnt)
738 hst_p = 0;
739 }
740
741 PC = (PC + 2) & VAMASK; /* increment PC */
742 switch (op) { /* case on opcode */
743
744 /* Load/store instructions */
745
746 case 0x08: /* LHR - RR */
747 case 0x24: /* LIS - NO */
748 case 0x48: /* LH - RXH */
749 case 0xC8: /* LHI - RS */
750 R[r1] = opnd; /* load operand */
751 CC_GL_16 (R[r1]); /* set G,L */
752 break;
753
754 case 0x25: /* LCS - NO */
755 R[r1] = (~opnd + 1) & DMASK16; /* load complement */
756 CC_GL_16 (R[r1]); /* set G,L */
757 break;
758
759 case 0x40: /* STH - RX */
760 WriteH (ea, R[r1]); /* store register */
761 break;
762
763 case 0xD1: /* LM - RX */
764 for ( ; r1 <= 0xF; r1++) { /* loop thru reg */
765 R[r1] = ReadH (ea); /* load register */
766 ea = (ea + 2) & VAMASK; /* incr mem addr */
767 }
768 break;
769
770 case 0xD0: /* STM - RX */
771 for ( ; r1 <= 0xF; r1++) { /* loop thru reg */
772 WriteH (ea, R[r1]); /* store register */
773 ea = (ea + 2) & VAMASK; /* incr mem addr */
774 }
775 break;
776
777 case 0x93: /* LDBR - RR */
778 case 0xD3: /* LDB - RXB */
779 R[r1] = opnd & DMASK8; /* load byte */
780 break;
781
782 case 0x92: /* STBR - NO */
783 R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */
784 break;
785 case 0xD2: /* STB - RX */
786 WriteB (ea, R[r1] & DMASK8); /* store byte */
787 break;
788
789 case 0x94: /* EXBR - RR */
790 R[r1] = (opnd >> 8) | ((opnd & DMASK8) << 8);
791 break;
792
793 /* Control instructions */
794
795 case 0x01: /* BALR - RR */
796 case 0x41: /* BAL - RX */
797 PCQ_ENTRY; /* save old PC */
798 R[r1] = PC; /* save cur PC */
799 PC = opnd; /* branch */
800 break;
801
802 case 0x02: /* BTCR - RR */
803 case 0x42: /* BTC - RX */
804 if (cc & r1) { /* test CC's */
805 PCQ_ENTRY; /* branch if true */
806 PC = opnd;
807 }
808 break;
809
810 case 0x20: /* BTBS - NO */
811 if (cc & r1) { /* test CC's */
812 PCQ_ENTRY; /* branch if true */
813 PC = (oPC - r2 - r2) & VAMASK;
814 }
815 break;
816
817 case 0x21: /* BTFS - NO */
818 if (cc & r1) { /* test CC's */
819 PCQ_ENTRY; /* branch if true */
820 PC = (oPC + r2 + r2) & VAMASK;
821 }
822 break;
823
824 case 0x03: /* BFCR - RR */
825 case 0x43: /* BFC - RX */
826 if ((cc & r1) == 0) { /* test CC's */
827 PCQ_ENTRY; /* branch if false */
828 PC = opnd;
829 }
830 break;
831
832 case 0x22: /* BFBS - NO */
833 if ((cc & r1) == 0) { /* test CC's */
834 PCQ_ENTRY; /* branch if false */
835 PC = (oPC - r2 - r2) & VAMASK;
836 }
837 break;
838
839 case 0x23: /* BFFS - NO */
840 if ((cc & r1) == 0) { /* test CC's */
841 PCQ_ENTRY; /* branch if false */
842 PC = (oPC + r2 + r2) & VAMASK;
843 }
844 break;
845
846 case 0xC0: /* BXH - RX */
847 inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */
848 lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */
849 R[r1] = (R[r1] + inc) & DMASK16; /* R1 = R1 + inc */
850 if (R[r1] > lim) { /* if R1 > lim */
851 PCQ_ENTRY; /* branch */
852 PC = opnd;
853 }
854 break;
855
856 case 0xC1: /* BXLE - RX */
857 inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */
858 lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */
859 R[r1] = (R[r1] + inc) & DMASK16; /* R1 = R1 + inc */
860 if (R[r1] <= lim) { /* if R1 <= lim */
861 PCQ_ENTRY; /* branch */
862 PC = opnd;
863 }
864 break;
865
866 /* Logical instructions */
867
868 case 0x04: /* NHR - RR */
869 case 0x44: /* NH - RXH */
870 case 0xC4: /* NHI - RS */
871 R[r1] = R[r1] & opnd; /* result */
872 CC_GL_16 (R[r1]); /* set G,L */
873 break;
874
875 case 0x06: /* OHR - RR */
876 case 0x46: /* OH - RXH */
877 case 0xC6: /* OHI - RS */
878 R[r1] = R[r1] | opnd; /* result */
879 CC_GL_16 (R[r1]); /* set G,L */
880 break;
881
882 case 0x07: /* XHR - RR */
883 case 0x47: /* XH - RXH */
884 case 0xC7: /* XHI - RS */
885 R[r1] = R[r1] ^ opnd; /* result */
886 CC_GL_16 (R[r1]); /* set G,L */
887 break;
888
889 case 0xC3: /* THI - RS */
890 rslt = R[r1] & opnd; /* result */
891 CC_GL_16 (rslt); /* set G, L */
892 break;
893
894 case 0x05: /* CLHR - RR */
895 case 0x45: /* CLH - RXH */
896 case 0xC5: /* CLHI - RS */
897 rslt = (R[r1] - opnd) & DMASK16; /* result */
898 CC_GL_16 (rslt); /* set G,L */
899 if (R[r1] < opnd) /* set C if borrow */
900 cc = cc | CC_C;
901 if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16)
902 cc = cc | CC_V;
903 break;
904
905 case 0xD4: /* CLB - RXB */
906 t = R[r1] & DMASK8;
907 rslt = (t - opnd) & DMASK16; /* result */
908 CC_GL_16 (rslt); /* set G,L */
909 if (t < opnd) /* set C if borrow */
910 cc = cc | CC_C;
911 break;
912
913 /* Shift instructions */
914
915 case 0xCC: /* SRHL - RS */
916 opnd = opnd & 0xF; /* shift count */
917 case 0x90: /* SRLS - NO */
918 rslt = R[r1] >> opnd; /* result */
919 CC_GL_16 (rslt); /* set G,L */
920 if (opnd && ((R[r1] >> (opnd - 1)) & 1))
921 cc = cc | CC_C;
922 R[r1] = rslt; /* store result */
923 break;
924
925 case 0xCD: /* SLHL - RS */
926 opnd = opnd & 0xF; /* shift count */
927 case 0x91: /* SLLS - NO */
928 rslt = R[r1] << opnd; /* raw result */
929 R[r1] = rslt & DMASK16; /* masked result */
930 CC_GL_16 (R[r1]); /* set G,L */
931 if (opnd && (rslt & 0x10000)) /* set C if shft out */
932 cc = cc | CC_C;
933 break;
934
935 case 0xCE: /* SRHA - RS */
936 opnd = opnd & 0xF; /* shift count */
937 rslt = (SEXT16 (R[r1]) >> opnd) & DMASK16; /* result */
938 CC_GL_16 (rslt); /* set G,L */
939 if (opnd && ((R[r1] >> (opnd - 1)) & 1))
940 cc = cc | CC_C;
941 R[r1] = rslt; /* store result */
942 break;
943
944 case 0xCF: /* SLHA - RS */
945 opnd = opnd & 0xF; /* shift count */
946 rslt = R[r1] << opnd; /* raw result */
947 R[r1] = (R[r1] & SIGN16) | (rslt & MMASK16); /* arith result */
948 CC_GL_16 (R[r1]); /* set G,L */
949 if (opnd && (rslt & SIGN16)) /* set C if shft out */
950 cc = cc | CC_C;
951 break;
952
953 case 0xEA: /* RRL - RS */
954 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
955 opnd = opnd & 0x1F; /* shift count */
956 t = (R[r1] << 16) | R[r1p1]; /* form 32b op */
957 if (opnd) /* result */
958 rslt = (t >> opnd) | (t << (32 - opnd));
959 else rslt = t; /* no shift */
960 CC_GL_32 (rslt); /* set G,L 32b */
961 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
962 R[r1p1] = rslt & DMASK16; /* lo result */
963 break;
964
965 case 0xEB: /* RLL - RS */
966 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
967 opnd = opnd & 0x1F; /* shift count */
968 t = (R[r1] << 16) | R[r1p1]; /* form 32b op */
969 if (opnd) /* result */
970 rslt = (t << opnd) | (t >> (32 - opnd));
971 else rslt = t; /* no shift */
972 CC_GL_32 (rslt); /* set G,L 32b */
973 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
974 R[r1p1] = rslt & DMASK16; /* lo result */
975 break;
976
977 case 0xEC: /* SRL - RS */
978 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
979 opnd = opnd & 0x1F; /* shift count */
980 t = (R[r1] << 16) | R[r1p1]; /* form 32b op */
981 rslt = t >> opnd; /* result */
982 CC_GL_32 (rslt); /* set G,L 32b */
983 if (opnd && ((t >> (opnd - 1)) & 1))
984 cc = cc | CC_C;
985 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
986 R[r1p1] = rslt & DMASK16; /* lo result */
987 break;
988
989 case 0xED: /* SLL - 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 << opnd; /* result */
994 CC_GL_32 (rslt); /* set G,L 32b */
995 if (opnd && ((t << (opnd - 1)) & SIGN32))
996 cc = cc | CC_C;
997 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
998 R[r1p1] = rslt & DMASK16; /* lo result */
999 break;
1000
1001 case 0xEE: /* SRA - RS */
1002 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
1003 opnd = opnd & 0x1F; /* shift count */
1004 t = (R[r1] << 16) | R[r1p1]; /* form 32b op */
1005 rslt = ((int32) t) >> opnd; /* signed result */
1006 CC_GL_32 (rslt); /* set G,L 32b */
1007 if (opnd && ((t >> (opnd - 1)) & 1))
1008 cc = cc | CC_C;
1009 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
1010 R[r1p1] = rslt & DMASK16; /* lo result */
1011 break;
1012
1013 case 0xEF: /* SLA - RS */
1014 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
1015 opnd = opnd & 0x1F; /* shift count */
1016 t = (R[r1] << 16) | R[r1p1]; /* form 32b op */
1017 rslt = (t & SIGN32) | ((t << opnd) & MMASK32); /* signed result */
1018 CC_GL_32 (rslt); /* set G,L 32b */
1019 if (opnd && ((t << opnd) & SIGN32))
1020 cc = cc | CC_C;
1021 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
1022 R[r1p1] = rslt & DMASK16; /* lo result */
1023 break;
1024
1025 /* Arithmetic instructions */
1026
1027 case 0x0A: /* AHR - RR */
1028 case 0x26: /* AIS - NO */
1029 case 0x4A: /* AH - RXH */
1030 case 0xCA: /* AHI - RS */
1031 rslt = (R[r1] + opnd) & DMASK16; /* result */
1032 CC_GL_16 (rslt); /* set G,L */
1033 if (rslt < opnd) /* set C if carry */
1034 cc = cc | CC_C;
1035 if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16)
1036 cc = cc | CC_V;
1037 R[r1] = rslt;
1038 break;
1039
1040 case 0x61: /* AHM - RXH */
1041 rslt = (R[r1] + opnd) & DMASK16; /* result */
1042 CC_GL_16 (rslt); /* set G,L */
1043 if (rslt < opnd) /* set C if carry */
1044 cc = cc | CC_C;
1045 if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16)
1046 cc = cc | CC_V;
1047 WriteH (ea, rslt); /* store in memory */
1048 break;
1049
1050 case 0x0B: /* SHR - RR */
1051 case 0x27: /* SIS - NO */
1052 case 0x4B: /* SH - RXH */
1053 case 0xCB: /* SHI - RS */
1054 rslt = (R[r1] - opnd) & DMASK16; /* result */
1055 CC_GL_16 (rslt); /* set G,L */
1056 if (R[r1] < opnd) /* set C if borrow */
1057 cc = cc | CC_C;
1058 if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16)
1059 cc = cc | CC_V;
1060 R[r1] = rslt;
1061 break;
1062
1063 case 0x09: /* CHR - RR */
1064 case 0x49: /* CH - RXH */
1065 case 0xC9: /* CHI - RS */
1066 sr = SEXT16 (R[r1]); /* sign ext */
1067 st = SEXT16 (opnd);
1068 if (sr < st) /* < sets C, L */
1069 cc = CC_C | CC_L;
1070 else if (sr > st) /* > sets G */
1071 cc = CC_G;
1072 else cc = 0;
1073 if (((R[r1] ^ opnd) & (~opnd ^ (sr - st))) & SIGN16)
1074 cc = cc | CC_V;
1075 break;
1076
1077 case 0x0C: /* MHR - RR */
1078 case 0x4C: /* MH - RXH */
1079 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
1080 rslt = SEXT16 (R[r1p1]) * SEXT16 (opnd); /* multiply */
1081 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
1082 R[r1p1] = rslt & DMASK16; /* lo result */
1083 break;
1084
1085 case 0x9C: /* MHUR - RR */
1086 case 0xDC: /* MHU - RXH */
1087 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
1088 rslt = R[r1p1] * opnd; /* multiply, unsigned */
1089 R[r1] = (rslt >> 16) & DMASK16; /* hi result */
1090 R[r1p1] = rslt & DMASK16; /* lo result */
1091 break;
1092
1093 case 0x0D: /* DHR - RR */
1094 case 0x4D: /* DH - RXH */
1095 r1p1 = (r1 + 1) & 0xF; /* R1 + 1 */
1096 if ((opnd == 0) ||
1097 ((R[r1] == 0x8000) && (R[r1p1] == 0) && (opnd == 0xFFFF))) {
1098 if (PSW & PSW_AFI) /* div fault enabled? */
1099 cc = swap_psw (AFIPSW, cc); /* swap PSW */
1100 break;
1101 }
1102 sr = (R[r1] << 16) | R[r1p1]; /* signed 32b divd */
1103 st = sr / SEXT16 (opnd); /* signed quotient */
1104 sr = sr % SEXT16 (opnd); /* remainder */
1105 if ((st < 0x8000) && (st >= -0x8000)) { /* if quo fits */
1106 R[r1] = sr & DMASK16; /* store remainder */
1107 R[r1p1] = st & DMASK16; /* store quotient */
1108 }
1109 else if (PSW & PSW_AFI) /* div fault enabled? */
1110 cc = swap_psw (AFIPSW, cc); /* swap PSW */
1111 break;
1112
1113 case 0x0E: /* ACHR - RR */
1114 case 0x4E: /* ACH - RXH */
1115 t = R[r1] + opnd + ((cc & CC_C) != 0); /* raw result */
1116 rslt = t & DMASK16; /* masked result */
1117 CC_GL_16 (rslt); /* set G,L */
1118 if (t > DMASK16) /* set C if carry */
1119 cc = cc | CC_C;
1120 if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16)
1121 cc = cc | CC_V;
1122 R[r1] = rslt; /* store result */
1123 break;
1124
1125 case 0x0F: /* SCHR - RR */
1126 case 0x4F: /* SCH - RXH */
1127 t = R[r1] - opnd - ((cc & CC_C) != 0); /* raw result */
1128 rslt = t & DMASK16; /* masked result */
1129 CC_GL_16 (rslt); /* set G,L */
1130 if (t > DMASK16) /* set C if borrow */
1131 cc = cc | CC_C;
1132 if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16)
1133 cc = cc | CC_V;
1134 R[r1] = rslt; /* store result */
1135 break;
1136
1137 /* Floating point instructions */
1138
1139 case 0x28: /* LER - NO */
1140 case 0x38: /* LDR - NO */
1141 case 0x68: /* LE - RX */
1142 case 0x78: /* LD - RX */
1143 cc = f_l (op, r1, r2, ea); /* load */
1144 if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */
1145 cc = swap_psw (FPFPSW, cc);
1146 break;
1147
1148 case 0x29: /* CER - NO */
1149 case 0x39: /* CDR - NO */
1150 case 0x69: /* CE - RX */
1151 case 0x79: /* CD - RX */
1152 cc = f_c (op, r1, r2, ea); /* compare */
1153 break;
1154
1155 case 0x2A: /* AER - NO */
1156 case 0x2B: /* SER - NO */
1157 case 0x3A: /* ADR - NO */
1158 case 0x3B: /* SDR - NO */
1159 case 0x6A: /* AE - RX */
1160 case 0x6B: /* SE - RX */
1161 case 0x7A: /* AD - RX */
1162 case 0x7B: /* SD - RX */
1163 cc = f_as (op, r1, r2, ea); /* add/sub */
1164 if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */
1165 cc = swap_psw (FPFPSW, cc);
1166 break;
1167
1168 case 0x2C: /* MER - NO */
1169 case 0x3C: /* MDR - NO */
1170 case 0x6C: /* ME - RX */
1171 case 0x7C: /* MD - RX */
1172 cc = f_m (op, r1, r2, ea); /* multiply */
1173 if ((cc & CC_V) && (PSW & PSW_FPF) && CPU_x16) /* V set, x/16? */
1174 cc = swap_psw (FPFPSW, cc);
1175 break;
1176
1177 case 0x2D: /* DER - NO */
1178 case 0x3D: /* DDR - NO */
1179 case 0x6D: /* DE - RX */
1180 case 0x7D: /* DD - RX */
1181 cc = f_d (op, r1, r2, ea); /* perform divide */
1182 if ((cc & CC_V) && ((cc & CC_C) || /* V set, x/16 or */
1183 ((PSW & PSW_FPF) && CPU_x16))) /* V & C set? */
1184 cc = swap_psw (FPFPSW, cc);
1185 break;
1186
1187 case 0x2E: /* FXR - NO */
1188 case 0x3E: /* FXDR - NO */
1189 cc = f_fix (op, r1, r2); /* cvt to integer */
1190 break;
1191
1192 case 0x2F: /* FLR - NO */
1193 case 0x3F: /* FLDR - NO */
1194 cc = f_flt (op, r1, r2); /* cvt to floating */
1195 break;
1196
1197 case 0x60: /* STE - RX */
1198 t = ReadFReg (r1); /* get fp reg */
1199 WriteF (ea, t, P); /* write */
1200 break;
1201
1202 case 0x70: /* STD - RX */
1203 WriteF (ea, D[r1 >> 1].h, P); /* write hi */
1204 WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, P); /* write lo */
1205 break;
1206
1207 case 0x71: /* STME - RX */
1208 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */
1209 t = ReadFReg (r1); /* get fp reg */
1210 WriteF (ea, t, P); /* write */
1211 ea = (ea + 4) & VAMASK; /* incr mem addr */
1212 }
1213 break;
1214
1215 case 0x72: /* LME - RX */
1216 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */
1217 t = ReadF (ea, P); /* get value */
1218 WriteFReg (r1, t); /* write reg */
1219 ea = (ea + 4) & VAMASK; /* incr mem addr */
1220 }
1221 break;
1222
1223 case 0x7E: /* STMD - RX */
1224 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */
1225 WriteF (ea, D[r1 >> 1].h, P); /* write register */
1226 WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, P);
1227 ea = (ea + 8) & VAMASK; /* incr mem addr */
1228 }
1229 break;
1230
1231 case 0x7F: /* LMD - RX */
1232 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */
1233 D[r1 >> 1].h = ReadF (ea, P); /* load register */
1234 D[r1 >> 1].l = ReadF ((ea + 4) & VAMASK, P);
1235 ea = (ea + 8) & VAMASK; /* incr mem addr */
1236 }
1237 break;
1238
1239 /* Miscellaneous */
1240
1241 case 0xE1: /* SVC - RX */
1242 PCQ_ENTRY; /* save PC */
1243 WriteH (SVCAP, ea); /* save opnd */
1244 WriteH (SVOPS, BUILD_PSW (cc)); /* save PS */
1245 WriteH (SVOPC, PC); /* save PC */
1246 PC = ReadH (SVNPC + r1 + r1); /* new PC */
1247 cc = newPSW (ReadH (SVNPS)); /* new PS */
1248 break;
1249
1250 case 0xE2: /* SINT - RS */
1251 dev = opnd & DEV_MAX; /* get dev */
1252 cc = int_auto (dev, cc); /* auto intr */
1253 int_eval (); /* re-eval intr */
1254 break;
1255
1256 case 0xC2: /* LPSW - RX */
1257 PCQ_ENTRY; /* effective branch */
1258 PC = ReadH ((ea + 2) & VAMASK); /* read PC */
1259 cc = newPSW (ReadH (ea)); /* read PSW */
1260 if (PSW & PSW_SQI) /* test for q */
1261 cc = testsysq (cc);
1262 break;
1263
1264 case 0x95: /* EPSR - NO */
1265 R[r1] = BUILD_PSW (cc); /* save PSW */
1266 case 0x33: /* LPSR - NO */
1267 cc = newPSW (R[r2]); /* load new PSW */
1268 if (PSW & PSW_SQI) /* test for q */
1269 cc = testsysq (cc);
1270 break;
1271
1272 case 0x73: /* LPS - RXH */
1273 cc = newPSW (opnd); /* load new PSW */
1274 if (PSW & PSW_SQI) /* test for q */
1275 cc = testsysq (cc);
1276 break;
1277
1278 case 0x64: /* ATL - RX */
1279 case 0x65: /* ABL - RX */
1280 cc = addtoq (ea, R[r1], op & 1); /* add to q */
1281 break;
1282
1283 case 0x66: /* RTL - RX */
1284 case 0x67: /* RBL - RX */
1285 cc = remfmq (ea, r1, op & 1); /* remove from q */
1286 break;
1287
1288 case 0x13: /* SETMR - RR */
1289 case 0x53: /* SETM - RXH */
1290 t = BUILD_PSW (cc); /* old PSW */
1291 map = PSW_GETMAP (opnd); /* get new map */
1292 switch (map) { /* case on map */
1293
1294 case 0x7:
1295 map = 0; /* use 1:1 map */
1296 R[r1] = R[r1] ^ SIGN16; /* flip sign */
1297 break;
1298
1299 case 0x8: case 0x9: case 0xA: case 0xB:
1300 case 0xC: case 0xD: case 0xE:
1301 if (R[r1] & SIGN16) /* S1? clr map<0> */
1302 map = map & ~0x8;
1303 else {
1304 map = 0; /* else 1:1 map */
1305 R[r1] = R[r1] | SIGN16; /* set sign */
1306 }
1307 break;
1308
1309 default:
1310 break;
1311 }
1312 t = (t & ~PSW_MAP) | (map << PSW_V_MAP); /* insert map */
1313 newPSW (t); /* load new PSW */
1314 CC_GL_16 (R[r1]); /* set G,L */
1315 break;
1316
1317 /* I/O instructions */
1318
1319 case 0xDE: /* OC - RX */
1320 opnd = ReadB (ea); /* fetch operand */
1321 case 0x9E: /* OCR - RR */
1322 dev = R[r1] & DEV_MAX;
1323 if (DEV_ACC (dev)) {
1324 dev_tab[dev] (dev, IO_ADR, 0); /* select */
1325 dev_tab[dev] (dev, IO_OC, opnd & DMASK8); /* send command */
1326 int_eval (); /* re-eval intr */
1327 cc = 0;
1328 }
1329 else cc = CC_V;
1330 break;
1331
1332 case 0xDA: /* WD - RX */
1333 opnd = ReadB (ea); /* fetch operand */
1334 case 0x9A: /* WDR - RR */
1335 dev = R[r1] & DEV_MAX;
1336 if (DEV_ACC (dev)) {
1337 dev_tab[dev] (dev, IO_ADR, 0); /* select */
1338 dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send data */
1339 int_eval (); /* re-eval intr */
1340 cc = 0;
1341 }
1342 else cc = CC_V;
1343 break;
1344
1345 case 0xD8: /* WH - RX */
1346 opnd = ReadH (ea); /* fetch operand */
1347 case 0x98: /* WHR - RR */
1348 dev = R[r1] & DEV_MAX;
1349 if (DEV_ACC (dev)) {
1350 if (dev_tab[dev] (dev, IO_ADR, 0)) /* select; hw ok? */
1351 dev_tab[dev] (dev, IO_WH, opnd); /* send data */
1352 else { /* byte only */
1353 dev_tab[dev] (dev, IO_WD, opnd >> 8); /* send hi byte */
1354 dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send lo byte */
1355 }
1356 int_eval (); /* re-eval intr */
1357 cc = 0;
1358 }
1359 else cc = CC_V;
1360 break;
1361
1362 case 0x9B: /* RDR - RR */
1363 case 0xDB: /* RD - RX */
1364 dev = R[r1] & DEV_MAX;
1365 if (DEV_ACC (dev)) { /* dev exist? */
1366 dev_tab[dev] (dev, IO_ADR, 0); /* select */
1367 t = dev_tab[dev] (dev, IO_RD, 0); /* get data */
1368 cc = 0;
1369 }
1370 else { /* no */
1371 t = 0; /* read zero */
1372 cc = CC_V; /* set V */
1373 }
1374 if (OP_TYPE (op) != OP_RR) /* RX or RR? */
1375 WriteB (ea, t);
1376 else R[r2] = t & DMASK8;
1377 int_eval (); /* re-eval intr */
1378 break;
1379
1380 case 0x99: /* RHR - RR */
1381 case 0xD9: /* RH - RX */
1382 dev = R[r1] & DEV_MAX;
1383 if (DEV_ACC (dev)) { /* dev exist? */
1384 if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */
1385 t = dev_tab[dev] (dev, IO_RH, 0); /* get data */
1386 else { /* byte only */
1387 rslt = dev_tab[dev] (dev, IO_RD, 0); /* get byte */
1388 t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */
1389 t = (rslt << 8) | t; /* merge */
1390 }
1391 cc = 0;
1392 }
1393 else { /* no */
1394 t = 0; /* read zero */
1395 cc = CC_V; /* set V */
1396 }
1397 if (OP_TYPE (op) != OP_RR) /* RX or RR? */
1398 WriteH (ea, t);
1399 else R[r2] = t;
1400 int_eval (); /* re-eval intr */
1401 break;
1402
1403 case 0x9F: /* AIR - RR */
1404 case 0xDF: /* AI - RX */
1405 R[r1] = int_getdev (); /* get int dev */
1406 /* fall through */
1407 case 0x9D: /* SSR - RR */
1408 case 0xDD: /* SS - RX */
1409 dev = R[r1] & DEV_MAX;
1410 if (DEV_ACC (dev)) { /* dev exist? */
1411 dev_tab[dev] (dev, IO_ADR, 0); /* select */
1412 t = dev_tab[dev] (dev, IO_SS, 0); /* get status */
1413 }
1414 else t = STA_EX; /* no */
1415 if (OP_TYPE (op) != OP_RR) /* RR or RX? */
1416 WriteB (ea, t);
1417 else R[r2] = t & DMASK8;
1418 cc = t & 0xF;
1419 int_eval (); /* re-eval intr */
1420 break;
1421
1422 /* Block I/O instructions
1423
1424 On a real Interdata system, the block I/O instructions can't be
1425 interrupted or stopped. To model this behavior, while allowing
1426 the instructions to go back through fetch for I/O processing and
1427 WRU testing, the simulator implements a 'block I/O in progress'
1428 flag and status block. If a block I/O is in progress, normal
1429 interrupts and fetches are suppressed until the block I/O is done.
1430 */
1431
1432 case 0x96: /* WBR - RR */
1433 case 0xD6: /* WB - RXH */
1434 dev = R[r1] & DEV_MAX;
1435 if (DEV_ACC (dev)) { /* dev exist? */
1436 if (OP_TYPE (op) != OP_RR)
1437 lim = ReadH ((ea + 2) & VAMASK);
1438 else lim = R[(r2 + 1) & 0xF];
1439 if (opnd > lim) /* start > end? */
1440 cc = 0;
1441 else { /* no, start I/O */
1442 dev_tab[dev] (dev, IO_ADR, 0); /* select dev */
1443 blk_io.dfl = dev; /* set status block */
1444 blk_io.cur = opnd;
1445 blk_io.end = lim;
1446 qevent = qevent | EV_BLK; /* I/O in prog */
1447 }
1448 }
1449 else cc = CC_V; /* nx dev */
1450 break;
1451
1452 case 0x97: /* RBR - RR */
1453 case 0xD7: /* RB - RXH */
1454 dev = R[r1] & DEV_MAX;
1455 if (DEV_ACC (dev)) { /* dev exist? */
1456 if (OP_TYPE (op) != OP_RR)
1457 lim = ReadH ((ea + 2) & VAMASK);
1458 else lim = R[(r2 + 1) & 0xF];
1459 if (opnd > lim) /* start > end? */
1460 cc = 0;
1461 else { /* no, start I/O */
1462 dev_tab[dev] (dev, IO_ADR, 0); /* select dev */
1463 blk_io.dfl = dev | BL_RD; /* set status block */
1464 blk_io.cur = opnd;
1465 blk_io.end = lim;
1466 qevent = qevent | EV_BLK; /* I/O in prog */
1467 }
1468 }
1469 else cc = CC_V; /* nx dev */
1470 break;
1471
1472 case 0xD5: /* AL - RX */
1473 dev = ReadB (AL_DEV); /* get device */
1474 t = ReadB (AL_IOC); /* get command */
1475 if (DEV_ACC (dev)) { /* dev exist? */
1476 if (AL_BUF > ea) /* start > end? */
1477 cc = 0;
1478 else { /* no, start I/O */
1479 dev_tab[dev] (dev, IO_ADR, 0); /* select dev */
1480 dev_tab[dev] (dev, IO_OC, t); /* start dev */
1481 blk_io.dfl = dev | BL_RD | BL_LZ; /* set status block */
1482 blk_io.cur = AL_BUF;
1483 blk_io.end = ea;
1484 qevent = qevent | EV_BLK; /* I/O in prog */
1485 }
1486 }
1487 else cc = CC_V; /* nx dev */
1488 break;
1489 } /* end switch */
1490 } /* end while */
1491
1492 /* Simulation halted */
1493
1494 PSW = BUILD_PSW (cc);
1495 PC = PC & VAMASK;
1496 pcq_r->qptr = pcq_p; /* update pc q ptr */
1497 return reason;
1498 }
1499
1500 /* Load new PSW and memory map */
1501
newPSW(uint32 val)1502 uint32 newPSW (uint32 val)
1503 {
1504 PSW = val & psw_mask; /* store PSW */
1505 int_eval (); /* update intreq */
1506 if (PSW & PSW_WAIT) /* wait state? */
1507 qevent = qevent | EV_WAIT;
1508 else qevent = qevent & ~EV_WAIT;
1509 if (cpu_unit.flags & UNIT_816E) { /* mapping enabled? */
1510 uint32 map = PSW_GETMAP (PSW); /* get new map */
1511 s0_rel = s0_rel_const[map]; /* set relocation */
1512 s1_rel = s1_rel_const[map]; /* constants */
1513 }
1514 else s0_rel = s1_rel = 0; /* no relocation */
1515 if (PSW & PSW_AIO) /* PSW<4> controls */
1516 SET_ENB (v_DS);
1517 else CLR_ENB (v_DS); /* DS interrupts */
1518 return PSW & CC_MASK;
1519 }
1520
1521 /* Swap PSW */
1522
swap_psw(uint32 loc,uint32 cc)1523 uint32 swap_psw (uint32 loc, uint32 cc)
1524 {
1525 WriteH (loc, BUILD_PSW (cc)); /* write PSW, PC */
1526 WriteH (loc + 2, PC);
1527 cc = newPSW (ReadH (loc + 4)); /* read PSW, PC */
1528 PC = ReadH (loc + 6);
1529 if (PSW & PSW_SQI) /* sys q int enb? */
1530 cc = testsysq (cc);
1531 return cc; /* return CC */
1532 }
1533
1534 /* Test for queue interrupts */
1535
testsysq(uint32 cc)1536 uint32 testsysq (uint32 cc)
1537 {
1538 int32 qb = ReadH (SQP); /* get sys q addr */
1539 int32 usd = ReadB (qb + Q16_USD); /* get use count */
1540
1541 if (usd) { /* any entries? */
1542 WriteH (SQIPSW, BUILD_PSW (cc)); /* swap PSW */
1543 WriteH (SQIPSW + 2, PC);
1544 cc = newPSW (ReadH (SQIPSW + 4));
1545 PC = ReadH (SQIPSW + 6);
1546 }
1547 return cc;
1548 }
1549
1550 /* Add to head of queue */
1551
addtoq(uint32 ea,uint32 val,uint32 flg)1552 uint32 addtoq (uint32 ea, uint32 val, uint32 flg)
1553 {
1554 uint32 slt, usd, wra, t;
1555
1556 t = ReadH (ea); /* slots/used */
1557 slt = (t >> 8) & DMASK8; /* # slots */
1558 usd = t & DMASK8; /* # used */
1559 if (usd >= slt) /* list full? */
1560 return CC_V;
1561 usd = usd + 1; /* inc # used */
1562 WriteB (ea + Q16_USD, usd); /* rewrite */
1563 if (flg) { /* ABL? */
1564 wra = ReadB ((ea + Q16_BOT) & VAMASK); /* get bottom */
1565 t = wra + 1; /* adv bottom */
1566 if (t >= slt) /* wrap if necc */
1567 t = 0;
1568 WriteB ((ea + Q16_BOT) & VAMASK, t); /* rewrite bottom */
1569 }
1570 else { /* ATL */
1571 wra = ReadB ((ea + Q16_TOP) & VAMASK); /* get top */
1572 if (wra == 0) /* wrap if necc */
1573 wra = (slt - 1) & DMASK8;
1574 else wra = wra - 1; /* dec top */
1575 WriteB ((ea + Q16_TOP) & VAMASK, wra); /* rewrite top */
1576 }
1577 WriteH ((ea + Q16_BASE + (wra * Q16_SLNT)) & VAMASK, val); /* write slot */
1578 return 0;
1579 }
1580
remfmq(uint32 ea,uint32 r1,uint32 flg)1581 uint32 remfmq (uint32 ea, uint32 r1, uint32 flg)
1582 {
1583 uint32 slt, usd, rda, t;
1584
1585 t = ReadH (ea); /* get slots/used */
1586 slt = (t >> 8) & DMASK8; /* # slots */
1587 usd = t & DMASK8; /* # used */
1588 if (usd == 0) /* empty? */
1589 return CC_V;
1590 usd = usd - 1; /* dec used */
1591 WriteB (ea + Q16_USD, usd); /* rewrite */
1592 if (flg) { /* RBL? */
1593 rda = ReadB ((ea + Q16_BOT) & VAMASK); /* get bottom */
1594 if (rda == 0) /* wrap if necc */
1595 rda = (slt - 1) & DMASK8;
1596 else rda = rda - 1; /* dec bottom */
1597 WriteB ((ea + Q16_BOT) & VAMASK, rda); /* rewrite bottom */
1598 }
1599 else {
1600 rda = ReadB ((ea + Q16_TOP) & VAMASK); /* RTL, get top */
1601 t = rda + 1; /* adv top */
1602 if (t >= slt) /* wrap if necc */
1603 t = 0;
1604 WriteB ((ea + Q16_TOP) & VAMASK, t); /* rewrite top */
1605 }
1606 R[r1] = ReadH ((ea + Q16_BASE + (rda * Q16_SLNT)) & VAMASK); /* read slot */
1607 if (usd) /* set cc's */
1608 return CC_G;
1609 else return 0;
1610 }
1611
1612 /* Automatic interrupt processing */
1613
1614 #define CCW16_ERR(x) (((x)|CCW16_INIT|CCW16_NOP|CCW16_Q) & \
1615 ~(CCW16_CHN|CCW16_CON|CCW16_HI))
1616
int_auto(uint32 dev,uint32 cc)1617 uint32 int_auto (uint32 dev, uint32 cc)
1618 {
1619 int32 ba, ea, by, vec, ccw, bpi, fnc, trm, st, i, t;
1620 t_bool sysqe = FALSE;
1621 t_bool rpt = FALSE;
1622
1623 do {
1624 vec = ReadH (INTSVT + dev + dev); /* get vector */
1625 if ((vec & 1) == 0) { /* immed int? */
1626 WriteH (vec, BUILD_PSW (cc)); /* write PSW, PC */
1627 WriteH ((vec + 2) & VAMASK, PC);
1628 cc = newPSW (ReadH ((vec + 4) & VAMASK)); /* read PSW */
1629 PC = (vec + 6) & VAMASK; /* set new PC */
1630 return cc;
1631 }
1632 vec = vec & ~1; /* get CCW addr */
1633 ccw = ReadH (vec); /* read CCW */
1634 if (DEV_ACC (dev)) /* select dev */
1635 dev_tab[dev] (dev, IO_ADR, 0);
1636 if (ccw & CCW16_NOP) /* NOP? exit */
1637 break;
1638 if (ccw & CCW16_INIT) { /* init set? */
1639 ccw = ccw & ~CCW16_INIT; /* clr init */
1640 WriteH (vec, ccw); /* rewrite */
1641 if (ccw & CCW16_OC) { /* OC set? */
1642 if (DEV_ACC (dev)) { /* dev exist? */
1643 by = ReadB ((vec + CCB16_IOC) & VAMASK);/* read OC byte */
1644 dev_tab[dev] (dev, IO_OC, by); /* send to dev */
1645 }
1646 break; /* and exit */
1647 }
1648 }
1649 fnc = CCW16_FNC (ccw); /* get func */
1650 st = 0; /* default status */
1651 if (fnc == CCW16_DMT) { /* DMT */
1652 ba = ReadH ((vec + CCB16_STR) & VAMASK); /* get cnt wd */
1653 ba = (ba - 1) & DMASK16; /* decr */
1654 WriteH ((vec + CCB16_STR) & VAMASK, ba); /* rewrite */
1655 if (ba) /* nz? exit */
1656 break;
1657 } /* end if dmt */
1658 else if (fnc != CCW16_NUL) { /* rd or wr? */
1659 if (DEV_ACC (dev)) /* dev exist? */
1660 st = dev_tab[dev] (dev, IO_SS, 0); /* sense status */
1661 else st = CC_V; /* else timeout */
1662 if (st & 0xF) { /* error? */
1663 ccw = CCW16_ERR (ccw); /* neuter CCW */
1664 WriteH (vec, ccw); /* rewrite CCW */
1665 }
1666 else { /* ok, do xfer */
1667 bpi = CCW16_BPI (ccw); /* get bytes/int */
1668 if (bpi == 0) /* max 16B */
1669 bpi = 16;
1670 ba = ReadH ((vec + CCB16_STR) & VAMASK); /* get start */
1671 for (i = 0; i < bpi; i++) { /* do # bytes */
1672 if (fnc == CCW16_RD) { /* chan read? */
1673 by = dev_tab[dev] (dev, IO_RD, 0); /* read byte */
1674 WriteB (ba, by); /* store */
1675 }
1676 else { /* chan write */
1677 by = ReadB (ba); /* fetch */
1678 dev_tab[dev] (dev, IO_WD, by); /* write byte */
1679 }
1680 ba = (ba + 1) & VAMASK; /* incr addr */
1681 }
1682 WriteH ((vec + CCB16_STR) & VAMASK, ba); /* rewrite */
1683 ea = ReadH ((vec + CCB16_END) & VAMASK); /* get end */
1684 trm = ReadB ((vec + CCB16_TRM) & VAMASK); /* get term chr */
1685 if ((ba <= ea) && /* not at end? */
1686 (((ccw & CCW16_TRM) == 0) || /* not term chr? */
1687 (by != trm))) /* exit */
1688 break;
1689 ccw = ccw | CCW16_NOP; /* nop CCW */
1690 WriteH (vec, ccw); /* rewrite CCW */
1691 } /* end else sta */
1692 } /* end if r/w */
1693
1694 /* Termination phase */
1695
1696 t = (dev << 8) | (st & DMASK8); /* form dev/sta */
1697 WriteH ((vec + CCB16_DEV) & VAMASK, t); /* write dev/sta */
1698 if (ccw & CCW16_Q) { /* q request? */
1699 t = ReadH (SQP); /* get sys q addr */
1700 if (addtoq (t, vec, ccw & CCW16_HI)) { /* add to sys q */
1701 WriteH (SQOP, vec); /* write to ovflo */
1702 return swap_psw (SQVPSW, cc); /* take exception */
1703 }
1704 else sysqe = TRUE; /* made an entry */
1705 }
1706 if (ccw & CCW16_CHN) { /* chain */
1707 t = ReadH ((vec + CCB16_CHN) & VAMASK); /* get chain wd */
1708 WriteH (INTSVT + dev + dev, t); /* wr int svc tab */
1709 if (ccw & CCW16_CON) /* cont? */
1710 rpt = TRUE;
1711 }
1712 } while (rpt);
1713
1714 /* Common exit */
1715
1716 if (sysqe && (PSW & PSW_SQI)) /* sys q ent & enb? */
1717 return swap_psw (SQIPSW, cc); /* take sys q int */
1718 return cc;
1719 }
1720
1721 /* Display register device */
1722
display(uint32 dev,uint32 op,uint32 dat)1723 uint32 display (uint32 dev, uint32 op, uint32 dat)
1724 {
1725 int t;
1726
1727 switch (op) {
1728
1729 case IO_ADR: /* select */
1730 if (!drmod) /* norm mode? clr */
1731 drpos = srpos = 0;
1732 return BY; /* byte only */
1733
1734 case IO_OC: /* command */
1735 op = op & 0xC0;
1736 if (op == 0x40) { /* x40 = inc */
1737 drmod = 1;
1738 drpos = srpos = 0; /* init cntrs */
1739 }
1740 else if (op == 0x80) /* x80 = norm */
1741 drmod = 0;
1742 break;
1743
1744 case IO_WD: /* write */
1745 if (drpos < 4)
1746 DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8));
1747 else if (drpos == 4)
1748 DRX = dat;
1749 drpos = (drpos + 1) &
1750 ((cpu_unit.flags & (UNIT_716 | UNIT_816))? 7: 3);
1751 break;
1752
1753 case IO_RD: /* read */
1754 t = (SR >> (srpos * 8)) & DMASK8;
1755 srpos = srpos ^ 1;
1756 return t;
1757
1758 case IO_SS: /* status */
1759 return 0x80;
1760 }
1761
1762 return 0;
1763 }
1764
1765 /* Memory interface routines
1766
1767 ReadB read byte (processor)
1768 ReadH read halfword (processor)
1769 ReadF read fullword (processor)
1770 WriteB write byte (processor)
1771 WriteH write halfword (processor)
1772 WriteF write fullword (processor)
1773 IOReadB read byte (IO)
1774 IOWriteB write byte (IO)
1775 IOReadH read halfword (IO)
1776 IOWriteH write halfword (IO)
1777 */
1778
ReadB(uint32 loc)1779 uint32 ReadB (uint32 loc)
1780 {
1781 uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1782
1783 return ((M[pa >> 1] >> ((pa & 1)? 0: 8)) & DMASK8);
1784 }
1785
ReadH(uint32 loc)1786 uint32 ReadH (uint32 loc)
1787 {
1788 uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1789
1790 return M[pa >> 1];
1791 }
1792
ReadF(uint32 loc,uint32 rel)1793 uint32 ReadF (uint32 loc, uint32 rel)
1794 {
1795 uint32 pa, pa1;
1796 uint32 loc1 = (loc + 2) & VAMASK;
1797
1798 loc = loc & VAMASK; /* FP doesn't mask */
1799 if (rel) {
1800 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1801 pa1 = (loc1 + ((loc1 & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1802 }
1803 else {
1804 pa = loc;
1805 pa1 = loc1;
1806 }
1807 return (((uint32) M[pa >> 1]) << 16) | ((uint32) M[pa1 >> 1]);
1808 }
1809
WriteB(uint32 loc,uint32 val)1810 void WriteB (uint32 loc, uint32 val)
1811 {
1812 uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1813
1814 val = val & DMASK8;
1815 if (MEM_ADDR_OK (pa))
1816 M[pa >> 1] = ((pa & 1)? ((M[pa >> 1] & ~DMASK8) | val):
1817 ((M[pa >> 1] & DMASK8) | (val << 8)));
1818 return;
1819 }
1820
WriteH(uint32 loc,uint32 val)1821 void WriteH (uint32 loc, uint32 val)
1822 {
1823 uint32 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1824
1825 if (MEM_ADDR_OK (pa))
1826 M[pa >> 1] = val & DMASK16;
1827 return;
1828 }
1829
WriteF(uint32 loc,uint32 val,uint32 rel)1830 void WriteF (uint32 loc, uint32 val, uint32 rel)
1831 {
1832 uint32 pa, pa1;
1833 uint32 loc1 = (loc + 2) & VAMASK;
1834
1835 loc = loc & VAMASK; /* FP doesn't mask */
1836 if (rel) {
1837 pa = (loc + ((loc & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1838 pa1 = (loc1 + ((loc1 & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1839 }
1840 else {
1841 pa = loc;
1842 pa1 = loc1;
1843 }
1844 if (MEM_ADDR_OK (pa))
1845 M[pa >> 1] = (val >> 16) & DMASK16;
1846 if (MEM_ADDR_OK (pa1))
1847 M[pa1 >> 1] = val & DMASK16;
1848 return;
1849 }
1850
IOReadB(uint32 loc)1851 uint32 IOReadB (uint32 loc)
1852 {
1853 return ((M[loc >> 1] >> ((loc & 1)? 0: 8)) & DMASK8);
1854 }
1855
IOWriteB(uint32 loc,uint32 val)1856 void IOWriteB (uint32 loc, uint32 val)
1857 {
1858 val = val & DMASK8;
1859 M[loc >> 1] = ((loc & 1)?
1860 ((M[loc >> 1] & ~DMASK8) | val):
1861 ((M[loc >> 1] & DMASK8) | (val << 8)));
1862 return;
1863 }
1864
IOReadH(uint32 loc)1865 uint32 IOReadH (uint32 loc)
1866 {
1867 return (M[loc >> 1] & DMASK16);
1868 }
1869
IOWriteH(uint32 loc,uint32 val)1870 void IOWriteH (uint32 loc, uint32 val)
1871 {
1872 M[loc >> 1] = val & DMASK16;
1873 return;
1874 }
1875
1876 /* Reset routine */
1877
cpu_reset(DEVICE * dptr)1878 t_stat cpu_reset (DEVICE *dptr)
1879 {
1880 qevent = 0; /* no events */
1881 newPSW (0); /* PSW = 0 */
1882 DR = 0; /* clr display */
1883 drmod = 0;
1884 blk_io.dfl = blk_io.cur = blk_io.end = 0; /* no block IO */
1885 sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init bkpts */
1886 if (M == NULL)
1887 M = (uint16 *) calloc (MAXMEMSIZE16E >> 1, sizeof (uint16));
1888 if (M == NULL)
1889 return SCPE_MEM;
1890 pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */
1891 if (pcq_r)
1892 pcq_r->qptr = 0;
1893 else return SCPE_IERR;
1894 return SCPE_OK;
1895 }
1896
1897 /* Memory examine */
1898
cpu_ex(t_value * vptr,t_addr addr,UNIT * uptr,int32 sw)1899 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
1900 {
1901 if (sw & SWMASK ('V')) {
1902 if (addr > VAMASK)
1903 return SCPE_NXM;
1904 addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1905 }
1906 if (addr >= MEMSIZE)
1907 return SCPE_NXM;
1908 if (vptr != NULL)
1909 *vptr = IOReadH (addr);
1910 return SCPE_OK;
1911 }
1912
1913 /* Memory deposit */
1914
cpu_dep(t_value val,t_addr addr,UNIT * uptr,int32 sw)1915 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
1916 {
1917 if (sw & SWMASK ('V')) {
1918 if (addr > VAMASK)
1919 return SCPE_NXM;
1920 addr = (addr + ((addr & VA_S1)? s1_rel: s0_rel)) & PAMASK16E;
1921 }
1922 if (addr >= MEMSIZE)
1923 return SCPE_NXM;
1924 IOWriteH (addr, val);
1925 return SCPE_OK;
1926 }
1927
1928 /* Change memory size */
1929
cpu_set_size(UNIT * uptr,int32 val,char * cptr,void * desc)1930 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
1931 {
1932 int32 mc = 0;
1933 uint32 i;
1934
1935 if ((val <= 0) || ((val & 0xFFF) != 0) ||
1936 (((uint32) val) > ((uptr->flags & UNIT_816E)? MAXMEMSIZE16E: MAXMEMSIZE16)))
1937 return SCPE_ARG;
1938 for (i = val; i < MEMSIZE; i = i + 2)
1939 mc = mc | M[i >> 1];
1940 if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
1941 return SCPE_OK;
1942 MEMSIZE = val;
1943 for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2)
1944 M[i >> 1] = 0;
1945 return SCPE_OK;
1946 }
1947
1948 /* Change CPU model */
1949
cpu_set_model(UNIT * uptr,int32 val,char * cptr,void * desc)1950 t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc)
1951 {
1952 uint32 i;
1953
1954 if (!(val & UNIT_816E) && (MEMSIZE > MAXMEMSIZE16)) {
1955 MEMSIZE = MAXMEMSIZE16;
1956 for (i = MEMSIZE; i < MAXMEMSIZE16E; i = i + 2)
1957 M[i >> 1] = 0;
1958 printf ("Reducing memory to 64KB\n");
1959 }
1960 return SCPE_OK;
1961 }
1962
1963 /* Set console interrupt */
1964
cpu_set_consint(UNIT * uptr,int32 val,char * cptr,void * desc)1965 t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc)
1966 {
1967 if ((uptr->flags & (UNIT_716 | UNIT_816 | UNIT_816E)) == 0)
1968 return SCPE_NOFNC;
1969 if (PSW & PSW_AIO)
1970 SET_INT (v_DS);
1971 return SCPE_OK;
1972 }
1973
1974 /* Set history */
1975
cpu_set_hist(UNIT * uptr,int32 val,char * cptr,void * desc)1976 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
1977 {
1978 uint32 i, lnt;
1979 t_stat r;
1980
1981 if (cptr == NULL) {
1982 for (i = 0; i < hst_lnt; i++)
1983 hst[i].vld = 0;
1984 hst_p = 0;
1985 return SCPE_OK;
1986 }
1987 lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r);
1988 if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN)))
1989 return SCPE_ARG;
1990 hst_p = 0;
1991 if (hst_lnt) {
1992 free (hst);
1993 hst_lnt = 0;
1994 hst = NULL;
1995 }
1996 if (lnt) {
1997 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
1998 if (hst == NULL)
1999 return SCPE_MEM;
2000 hst_lnt = lnt;
2001 }
2002 return SCPE_OK;
2003 }
2004
2005 /* Show history */
2006
cpu_show_hist(FILE * st,UNIT * uptr,int32 val,void * desc)2007 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
2008 {
2009 int32 op, k, di, lnt;
2010 char *cptr = (char *) desc;
2011 t_value sim_eval[2];
2012 t_stat r;
2013 InstHistory *h;
2014 extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
2015 UNIT *uptr, int32 sw);
2016
2017 if (hst_lnt == 0) /* enabled? */
2018 return SCPE_NOFNC;
2019 if (cptr) {
2020 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
2021 if ((r != SCPE_OK) || (lnt == 0))
2022 return SCPE_ARG;
2023 }
2024 else lnt = hst_lnt;
2025 di = hst_p - lnt; /* work forward */
2026 if (di < 0)
2027 di = di + hst_lnt;
2028 fprintf (st, "PC r1 opnd ea IR\n\n");
2029 for (k = 0; k < lnt; k++) { /* print specified */
2030 h = &hst[(di++) % hst_lnt]; /* entry pointer */
2031 if (h->vld) { /* instruction? */
2032 fprintf (st, "%04X %04X %04X ", h->pc, h->r1, h->opnd);
2033 op = (h->ir1 >> 8) & 0xFF;
2034 if (OP_TYPE (op) >= OP_RX)
2035 fprintf (st, "%04X ", h->ea);
2036 else fprintf (st, " ");
2037 sim_eval[0] = h->ir1;
2038 sim_eval[1] = h->ir2;
2039 if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
2040 fprintf (st, "(undefined) %04X", h->ir1);
2041 fputc ('\n', st); /* end line */
2042 } /* end if instruction */
2043 } /* end for */
2044 return SCPE_OK;
2045 }
2046