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