First Commit of my working state
[simh.git] / Interdata / id32_cpu.c
CommitLineData
196ba1fc
PH
1/* id32_cpu.c: Interdata 32b 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 32b 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 09-Mar-06 RMS Added 8 register bank support for 8/32\r
32 06-Feb-06 RMS Fixed bug in DH (found by Mark Hittinger)\r
33 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)\r
34 16-Aug-05 RMS Fixed C++ declaration and cast problems\r
35 10-Mar-05 RMS Fixed bug in initial memory allocation\r
36 RMS Fixed bug in show history routine (from Mark Hittinger)\r
37 RMS Revised examine/deposit to do words rather than bytes\r
38 18-Feb-05 RMS Fixed branches to mask new PC (from Greg Johnson)\r
39 06-Nov-04 RMS Added =n to SHOW HISTORY\r
40 25-Jan-04 RMS Revised for device debug support\r
41 31-Dec-03 RMS Fixed bug in cpu_set_hist\r
42 22-Sep-03 RMS Added additional instruction decode types\r
43 Added instruction history\r
44\r
45 The register state for an Interdata 32b CPU is:\r
46\r
47 REG[0:F][2]<0:31> general register sets\r
48 F[0:7]<0:31> single precision floating point registers\r
49 D[0:7]<0:63> double precision floating point registers\r
50 PSW<0:63> processor status word, including\r
51 STAT<0:11> status flags\r
52 CC<0:3> condition codes\r
53 PC<0:31> program counter\r
54 int_req[n]<0:31> interrupt requests\r
55 int_enb[n]<0:31> interrupt enables\r
56 \r
57 The Interdata 32b systems have seven instruction formats: register to\r
58 register, short format, register and memory (three formats), and register\r
59 and immediate (two formats). The formats are:\r
60\r
61 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r
62 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
63 | op | R1 | R2 | register-register\r
64 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
65\r
66 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r
67 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
68 | op | R1 | N | short format\r
69 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
70\r
71 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r
72 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
73 | op | R1 | RX | register-memory 1\r
74 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (absolute 14b)\r
75 | 0| 0| address |\r
76 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
77\r
78 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r
79 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
80 | op | R1 | RX | register-memory 2\r
81 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (relative)\r
82 | 1| address |\r
83 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
84\r
85 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r
86 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
87 | op | R1 | RX | register-memory 3\r
88 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ (double index)\r
89 | 0| 1| 0| 0| RX2 | address hi |\r
90 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
91 | address lo |\r
92 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
93\r
94 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r
95 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
96 | op | R1 | RX | register-immediate 1\r
97 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
98 | immediate |\r
99 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
100\r
101 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\r
102 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
103 | op | R1 | RX | register-immediate 2\r
104 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
105 | immediate hi |\r
106 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
107 | immediate lo |\r
108 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
109\r
110 For register-memory 1 and register-immediate 1 and 2 an instructions, an\r
111 effective address is calculated as follows:\r
112\r
113 effective addr = address + RX (if RX > 0)\r
114\r
115 For register-memory 2, an effective address is calculated as follows:\r
116\r
117 effective addr = address + PC + RX (if RX > 0)\r
118\r
119 For register-memory 3, an effective address is calculated as follows:\r
120\r
121 effective addr = address + RX (if RX > 0) + RX2 (if RX2 > 0)\r
122\r
123 Register-memory instructions can access an address space of 16M bytes.\r
124\r
125 This routine is the instruction decode routine for the Interdata CPU.\r
126 It is called from the simulator control program to execute\r
127 instructions in simulated memory, starting at the simulated PC.\r
128 It runs until 'reason' is set non-zero.\r
129\r
130 General notes:\r
131\r
132 1. Reasons to stop. The simulator can be stopped by:\r
133\r
134 HALT instruction\r
135 breakpoint encountered\r
136 wait state and no I/O outstanding\r
137 invalid instruction\r
138 I/O error in I/O simulator\r
139\r
140 2. Interrupts. Each device has an interrupt armed flag, an interrupt\r
141 request flag, and an interrupt enabled flag. To facilitate evaluation,\r
142 all interrupt requests are kept in int_req, and all enables in int_enb.\r
143 Interrupt armed flags are local to devices. If external interrupts are\r
144 enabled in the PSW, and a request is pending, an interrupt occurs.\r
145\r
146 3. Non-existent memory. On the Interdata 32b, reads to non-existent\r
147 memory return zero, and writes are ignored. In the simulator, the\r
148 largest possible memory is instantiated and initialized to zero.\r
149 Thus, only writes need be checked against actual memory size.\r
150\r
151 4. Adding I/O devices. These modules must be modified:\r
152\r
153 id_defs.h add device interrupt definitions\r
154 id32_sys.c add sim_devices table entry\r
155*/\r
156\r
157#include "id_defs.h"\r
158#include <setjmp.h>\r
159\r
160#define PCQ_SIZE 64 /* must be 2**n */\r
161#define PCQ_MASK (PCQ_SIZE - 1)\r
162#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = oPC\r
163#define VAMASK VAMASK32\r
164#define NRSETS 8 /* up to 8 reg sets */\r
165#define PSW_MASK PSW_x32\r
166#define ABORT(val) longjmp (save_env, (val))\r
167#define MPRO (-1)\r
168\r
169#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */\r
170#define UNIT_V_DPFP (UNIT_V_UF + 1)\r
171#define UNIT_V_832 (UNIT_V_UF + 2)\r
172#define UNIT_V_8RS (UNIT_V_UF + 3)\r
173#define UNIT_MSIZE (1 << UNIT_V_MSIZE)\r
174#define UNIT_DPFP (1 << UNIT_V_DPFP)\r
175#define UNIT_832 (1 << UNIT_V_832)\r
176#define UNIT_8RS (1 << UNIT_V_8RS)\r
177#define UNIT_TYPE (UNIT_DPFP | UNIT_832)\r
178\r
179#define HIST_PC 0x40000000\r
180#define HIST_MIN 64\r
181#define HIST_MAX 65536\r
182\r
183typedef struct {\r
184 uint32 pc;\r
185 uint32 ir1;\r
186 uint32 ir2;\r
187 uint32 ir3;\r
188 uint32 r1;\r
189 uint32 ea;\r
190 uint32 opnd;\r
191 } InstHistory;\r
192\r
193#define PSW_GETREG(x) (((x) >> PSW_V_REG) & psw_reg_mask)\r
194#define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \\r
195 ((int32) ((x) & 0x7FFFFFFF)))\r
196#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \\r
197 ((int32) ((x) & 0x7FFF)))\r
198#define SEXT15(x) (((x) & 0x4000)? ((int32) ((x) | ~0x3FFF)): \\r
199 ((int32) ((x) & 0x3FFF)))\r
200#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \\r
201 else if (x) cc = CC_G; \\r
202 else cc = 0\r
203#define CC_GL_32(x) if ((x) & SIGN32) cc = CC_L; \\r
204 else if (x) cc = CC_G; \\r
205 else cc = 0\r
206#define BUILD_PSW(x) (((PSW & ~CC_MASK) | (x)) & PSW_MASK)\r
207#define NEG(x) ((~(x) + 1) & DMASK32)\r
208#define ABS(x) (((x) & SIGN32)? NEG (x): (x))\r
209#define DNEG(x,y) y = NEG (y); \\r
210 x = (~(x) + (y == 0)) & DMASK32\r
211\r
212/* Logging */\r
213\r
214#define LOG_CPU_I 0x0001 /* intr/exception */\r
215#define LOG_CPU_C 0x0002 /* context change */\r
216\r
217uint32 GREG[16 * NRSETS] = { 0 }; /* general registers */\r
218uint32 *M = NULL; /* memory */\r
219uint32 *R = &GREG[0]; /* working reg set */\r
220uint32 F[8] = { 0 }; /* sp fp registers */\r
221dpr_t D[8] = { 0 }; /* dp fp registers */\r
222uint32 PSW = 0; /* processor status word */\r
223uint32 PC = 0; /* program counter */\r
224uint32 oPC = 0; /* PC at inst start */\r
225uint32 SR = 0; /* switch register */\r
226uint32 DR = 0; /* display register */\r
227uint32 DRX = 0; /* display extension */\r
228uint32 drmod = 0; /* mode */\r
229uint32 srpos = 0; /* switch register pos */\r
230uint32 drpos = 0; /* display register pos */\r
231uint32 mac_reg[MAC_LNT] = { 0 }; /* mac registers */\r
232uint32 mac_sta = 0; /* mac status */\r
233uint32 int_req[INTSZ] = { 0 }; /* interrupt requests */\r
234uint32 int_enb[INTSZ] = { 0 }; /* interrupt enables */\r
235uint32 qevent = 0; /* events */\r
236uint32 stop_inst = 0; /* stop on ill inst */\r
237uint32 stop_wait = 0; /* stop on wait */\r
238uint32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */\r
239int32 pcq_p = 0; /* PC queue ptr */\r
240REG *pcq_r = NULL; /* PC queue reg ptr */\r
241uint32 dec_flgs = 0; /* decode flags */\r
242uint32 fp_in_hwre = 0; /* ucode vs hwre fp */\r
243uint32 pawidth = PAWIDTH32; /* addr mask */\r
244uint32 hst_p = 0; /* history pointer */\r
245uint32 hst_lnt = 0; /* history length */\r
246uint32 psw_reg_mask = 1; /* PSW reg mask */\r
247InstHistory *hst = NULL; /* instruction history */\r
248jmp_buf save_env; /* abort handler */\r
249struct BlockIO blk_io; /* block I/O status */\r
250uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };\r
251\r
252extern int32 sim_interval;\r
253extern int32 sim_int_char;\r
254extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */\r
255extern t_bool sim_idle_enab;\r
256extern FILE *sim_deb;\r
257\r
258uint32 ReadB (uint32 loc, uint32 rel);\r
259uint32 ReadH (uint32 loc, uint32 rel);\r
260void WriteB (uint32 loc, uint32 val, uint32 rel);\r
261void WriteH (uint32 loc, uint32 val, uint32 rel);\r
262uint32 RelocT (uint32 va, uint32 base, uint32 rel, uint32 *pa);\r
263uint32 int_auto (uint32 dev, uint32 cc);\r
264uint32 addtoq (uint32 ea, uint32 val, uint32 flg);\r
265uint32 remfmq (uint32 ea, uint32 r1, uint32 flg);\r
266uint32 exception (uint32 loc, uint32 cc, uint32 flg);\r
267uint32 newPSW (uint32 val);\r
268uint32 testsysq (uint32 cc);\r
269uint32 display (uint32 dev, uint32 op, uint32 dat);\r
270t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);\r
271t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);\r
272t_stat cpu_reset (DEVICE *dptr);\r
273t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);\r
274t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc);\r
275t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);\r
276t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);\r
277void set_r_display (uint32 *rbase);\r
278\r
279extern t_bool devtab_init (void);\r
280extern void int_eval (void);\r
281extern uint32 int_getdev (void);\r
282extern void sch_cycle (uint32 ch);\r
283extern t_bool sch_blk (uint32 dev);\r
284extern uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea);\r
285extern uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea);\r
286extern uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea);\r
287extern uint32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea);\r
288extern uint32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea);\r
289extern uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2);\r
290extern uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2);\r
291\r
292/* Instruction decoding table */\r
293\r
294const uint16 decrom[256] = {\r
295 0, /* 00 */\r
296 OP_RR, /* BALR */\r
297 OP_RR, /* BTCR */\r
298 OP_RR, /* BFCR */\r
299 OP_RR, /* NR */\r
300 OP_RR, /* CLR */\r
301 OP_RR, /* OR */\r
302 OP_RR, /* XR */\r
303 OP_RR, /* LR */\r
304 OP_RR, /* CR */\r
305 OP_RR, /* AR */\r
306 OP_RR, /* SR */\r
307 OP_RR, /* MHR */\r
308 OP_RR, /* DHR */\r
309 0, 0, /* 0E:0F */\r
310 OP_NO, /* SRLS */\r
311 OP_NO, /* SLLS */\r
312 OP_RR, /* CHVR */\r
313 0, 0, 0, 0, 0, /* 13:17 */\r
314 OP_RR | OP_PRV, /* LPSWR */\r
315 0, 0, 0, /* 19:1B */\r
316 OP_RR, /* MR */\r
317 OP_RR, /* DR */\r
318 0, 0, /* 1E:1F */\r
319 OP_NO, /* BTBS */\r
320 OP_NO, /* BTFS */\r
321 OP_NO, /* BFBS */\r
322 OP_NO, /* BFFS */\r
323 OP_NO, /* LIS */\r
324 OP_NO, /* LCS */\r
325 OP_NO, /* AIS */\r
326 OP_NO, /* SIS */\r
327 OP_NO, /* LER */\r
328 OP_NO, /* CER */\r
329 OP_NO, /* AER */\r
330 OP_NO, /* SER */\r
331 OP_NO, /* MER */\r
332 OP_NO, /* DER */\r
333 OP_NO, /* FXR */\r
334 OP_NO, /* FLR */\r
335 0, /* MPBSR - 8/32C */\r
336 0, /* 31 */\r
337 0, /* PBR - 8/32C */\r
338 0, /* 33 */\r
339 OP_RR, /* EXHR */\r
340 0, 0, 0, /* 35:37 */\r
341 OP_NO | OP_DPF, /* LDR */\r
342 OP_NO | OP_DPF, /* CDR */\r
343 OP_NO | OP_DPF, /* ADR */\r
344 OP_NO | OP_DPF, /* SDR */\r
345 OP_NO | OP_DPF, /* MDR */\r
346 OP_NO | OP_DPF, /* DDR */\r
347 OP_NO | OP_DPF, /* FXDR */\r
348 OP_NO | OP_DPF, /* FLDR */\r
349 OP_RX, /* STH */\r
350 OP_RX, /* BAL */\r
351 OP_RX, /* BTC */\r
352 OP_RX, /* BFC */\r
353 OP_RXH, /* NH */\r
354 OP_RXH, /* CLH */\r
355 OP_RXH, /* OH */\r
356 OP_RXH, /* XH */\r
357 OP_RXH, /* LH */\r
358 OP_RXH, /* CH */\r
359 OP_RXH, /* AH */\r
360 OP_RXH, /* SH */\r
361 OP_RXH, /* MH */\r
362 OP_RXH, /* DH */\r
363 0, 0, /* 4E:4F */\r
364 OP_RX, /* ST */\r
365 OP_RXF, /* AM */\r
366 0, 0, /* 52:53 */\r
367 OP_RXF, /* N */\r
368 OP_RXF, /* CL */\r
369 OP_RXF, /* O */\r
370 OP_RXF, /* X */\r
371 OP_RXF, /* L */\r
372 OP_RXF, /* C */\r
373 OP_RXF, /* A */\r
374 OP_RXF, /* S */\r
375 OP_RXF, /* M */\r
376 OP_RXF, /* D */\r
377 OP_RXH, /* CRC12 */\r
378 OP_RXH, /* CRC16 */\r
379 OP_RX, /* STE */\r
380 OP_RXH, /* AHM */\r
381 0, /* PB - 8/32C */\r
382 OP_RX, /* LRA */\r
383 OP_RX, /* ATL */\r
384 OP_RX, /* ABL */\r
385 OP_RX, /* RTL */\r
386 OP_RX, /* RBL */\r
387 OP_RX, /* LE */\r
388 OP_RX, /* CE */\r
389 OP_RX, /* AE */\r
390 OP_RX, /* SE */\r
391 OP_RX, /* ME */\r
392 OP_RX, /* DE */\r
393 0, 0, /* 6E:6F */\r
394 OP_RX | OP_DPF, /* STD */\r
395 OP_RX, /* SME */\r
396 OP_RX, /* LME */\r
397 OP_RXH, /* LHL */\r
398 OP_RX, /* TBT */\r
399 OP_RX, /* SBT */\r
400 OP_RX, /* RBT */\r
401 OP_RX, /* CBT */\r
402 OP_RX | OP_DPF, /* LD */\r
403 OP_RX | OP_DPF, /* CD */\r
404 OP_RX | OP_DPF, /* AD */\r
405 OP_RX | OP_DPF, /* SD */\r
406 OP_RX | OP_DPF, /* MD */\r
407 OP_RX | OP_DPF, /* DD */\r
408 OP_RX | OP_DPF, /* STMD */\r
409 OP_RX | OP_DPF, /* LMD */\r
410 0, 0, 0, 0, 0, 0, 0, 0, /* 80:8F */\r
411 0, 0, 0, 0, 0, 0, 0, 0,\r
412 OP_NO, /* SRHLS */\r
413 OP_NO, /* SLHLS */\r
414 OP_NO, /* STBR */\r
415 OP_RR, /* LDBR */\r
416 OP_RR, /* EXBR */\r
417 OP_NO | OP_PRV, /* EPSR */\r
418 OP_RR | OP_PRV, /* WBR */\r
419 OP_RR | OP_PRV, /* RBR */\r
420 OP_RR | OP_PRV, /* WHR */\r
421 OP_RR | OP_PRV, /* RHR */\r
422 OP_RR | OP_PRV, /* WDR */\r
423 OP_RR | OP_PRV, /* RDR */\r
424 0, /* 9C */\r
425 OP_RR | OP_PRV, /* SSR */\r
426 OP_RR | OP_PRV, /* OCR */\r
427 0, /* 9F */\r
428 0, 0, 0, 0, 0, 0, 0, 0, /* A0:AF */\r
429 0, 0, 0, 0, 0, 0, 0, 0,\r
430 0, 0, 0, 0, 0, 0, 0, 0, /* B0:BF */\r
431 0, 0, 0, 0, 0, 0, 0, 0,\r
432 OP_RX, /* BXH */\r
433 OP_RX, /* BXLE */\r
434 OP_RXF | OP_PRV, /* LPSW */\r
435 OP_RI1, /* THI */\r
436 OP_RI1, /* NHI */\r
437 OP_RI1, /* CLHI */\r
438 OP_RI1, /* OHI */\r
439 OP_RI1, /* XHI */\r
440 OP_RI1, /* LHI */\r
441 OP_RI1, /* CHI */\r
442 OP_RI1, /* AHI */\r
443 OP_RI1, /* SHI */\r
444 OP_RI1, /* SRHL */\r
445 OP_RI1, /* SLHL */\r
446 OP_RI1, /* SRHA */\r
447 OP_RI1, /* SLHA */\r
448 OP_RX, /* STM */\r
449 OP_RX, /* LM */\r
450 OP_RX, /* STB */\r
451 OP_RXB, /* LDB */\r
452 OP_RXB, /* CLB */\r
453 OP_RX | OP_PRV, /* AL */\r
454 OP_RXF | OP_PRV, /* WB */\r
455 OP_RXF | OP_PRV, /* RB */\r
456 OP_RX | OP_PRV, /* WH */\r
457 OP_RX | OP_PRV, /* RH */\r
458 OP_RX | OP_PRV, /* WD */\r
459 OP_RX | OP_PRV, /* RD */\r
460 0, /* DC */\r
461 OP_RX | OP_PRV, /* SS */\r
462 OP_RX | OP_PRV, /* OC */\r
463 0, /* DF */\r
464 OP_RXH, /* TS */\r
465 OP_RX, /* SVC */\r
466 OP_RI1 | OP_PRV, /* SINT */\r
467 OP_RXH | OP_PRV, /* SCP */\r
468 0, 0, /* E4:E5 */\r
469 OP_RX, /* LA */\r
470 OP_RXF, /* TLATE */\r
471 0, 0, /* E8:E9 */\r
472 OP_RI1, /* RRL */\r
473 OP_RI1, /* RLL */\r
474 OP_RI1, /* SRL */\r
475 OP_RI1, /* SLL */\r
476 OP_RI1, /* SRA */\r
477 OP_RI1, /* SLA */\r
478 0, 0, 0, /* F0:F2 */\r
479 OP_RI2, /* TI */\r
480 OP_RI2, /* NI */\r
481 OP_RI2, /* CLI */\r
482 OP_RI2, /* OI */\r
483 OP_RI2, /* XI */\r
484 OP_RI2, /* LI */\r
485 OP_RI2, /* CI */\r
486 OP_RI2, /* AI */\r
487 OP_RI2, /* SI */\r
488 0, 0, 0, 0 /* FC:FF */\r
489 };\r
490\r
491/* CPU data structures\r
492\r
493 cpu_dev CPU device descriptor\r
494 cpu_unit CPU unit descriptor\r
495 cpu_reg CPU register list\r
496 cpu_mod CPU modifiers list\r
497*/\r
498\r
499DIB cpu_dib = { d_DS, -1, v_DS, NULL, &display };\r
500\r
501UNIT cpu_unit = { UDATA (NULL, UNIT_FIX | UNIT_BINK, MAXMEMSIZE32) };\r
502\r
503REG cpu_reg[] = {\r
504 { HRDATA (PC, PC, 20) },\r
505 { HRDATA (OPC, oPC, 20), REG_HRO },\r
506 { HRDATA (R0, GREG[0], 32) },\r
507 { HRDATA (R1, GREG[1], 32) },\r
508 { HRDATA (R2, GREG[2], 32) },\r
509 { HRDATA (R3, GREG[3], 32) },\r
510 { HRDATA (R4, GREG[4], 32) },\r
511 { HRDATA (R5, GREG[5], 32) },\r
512 { HRDATA (R6, GREG[6], 32) },\r
513 { HRDATA (R7, GREG[7], 32) },\r
514 { HRDATA (R8, GREG[8], 32) },\r
515 { HRDATA (R9, GREG[9], 32) },\r
516 { HRDATA (R10, GREG[10], 32) },\r
517 { HRDATA (R11, GREG[11], 32) },\r
518 { HRDATA (R12, GREG[12], 32) },\r
519 { HRDATA (R13, GREG[13], 32) },\r
520 { HRDATA (R14, GREG[14], 32) },\r
521 { HRDATA (R15, GREG[15], 32) },\r
522 { HRDATA (FR0, F[0], 32) },\r
523 { HRDATA (FR2, F[1], 32) },\r
524 { HRDATA (FR4, F[2], 32) },\r
525 { HRDATA (FR6, F[3], 32) },\r
526 { HRDATA (FR8, F[4], 32) },\r
527 { HRDATA (FR10, F[5], 32) },\r
528 { HRDATA (FR12, F[6], 32) },\r
529 { HRDATA (FR14, F[7], 32) },\r
530 { HRDATA (D0H, D[0].h, 32) },\r
531 { HRDATA (D0L, D[0].l, 32) },\r
532 { HRDATA (D2H, D[1].h, 32) },\r
533 { HRDATA (D2L, D[1].l, 32) },\r
534 { HRDATA (D4H, D[2].h, 32) },\r
535 { HRDATA (D4L, D[2].l, 32) },\r
536 { HRDATA (D6H, D[3].h, 32) },\r
537 { HRDATA (D6L, D[3].l, 32) },\r
538 { HRDATA (D8H, D[4].h, 32) },\r
539 { HRDATA (D8L, D[4].l, 32) },\r
540 { HRDATA (D10H, D[5].h, 32) },\r
541 { HRDATA (D10L, D[5].l, 32) },\r
542 { HRDATA (D12L, D[6].l, 32) },\r
543 { HRDATA (D12H, D[6].h, 32) },\r
544 { HRDATA (D14H, D[7].h, 32) },\r
545 { HRDATA (D14L, D[7].l, 32) },\r
546 { HRDATA (PSW, PSW, 16) },\r
547 { HRDATA (CC, PSW, 4) },\r
548 { HRDATA (SR, SR, 32) },\r
549 { HRDATA (DR, DR, 32) },\r
550 { HRDATA (DRX, DRX, 8) },\r
551 { FLDATA (DRMOD, drmod, 0) },\r
552 { FLDATA (SRPOS, srpos, 0) },\r
553 { HRDATA (DRPOS, drpos, 3) },\r
554 { BRDATA (IRQ, int_req, 16, 32, INTSZ) },\r
555 { BRDATA (IEN, int_enb, 16, 32, INTSZ) },\r
556 { BRDATA (MACREG, mac_reg, 16, 32, MAC_LNT) },\r
557 { HRDATA (MACSTA, mac_sta, 5) },\r
558 { HRDATA (QEVENT, qevent, 4), REG_HRO },\r
559 { FLDATA (STOP_INST, stop_inst, 0) },\r
560 { FLDATA (STOP_WAIT, stop_wait, 0) },\r
561 { BRDATA (PCQ, pcq, 16, 20, PCQ_SIZE), REG_RO+REG_CIRC },\r
562 { HRDATA (PCQP, pcq_p, 6), REG_HRO },\r
563 { HRDATA (WRU, sim_int_char, 8) },\r
564 { HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO },\r
565 { HRDATA (BLKIOC, blk_io.cur, 20), REG_HRO },\r
566 { HRDATA (BLKIOE, blk_io.end, 20), REG_HRO },\r
567 { BRDATA (GREG, GREG, 16, 32, 16 * NRSETS) },\r
568 { NULL }\r
569 };\r
570\r
571MTAB cpu_mod[] = {\r
572 { UNIT_8RS|UNIT_TYPE, 0, NULL, "732", NULL },\r
573 { UNIT_DPFP, UNIT_DPFP, NULL, "DPFP", NULL },\r
574 { UNIT_TYPE, 0, "7/32, single precision fp", "732", NULL },\r
575 { UNIT_TYPE, UNIT_DPFP, "7/32, double precision fp", NULL, NULL },\r
576 { UNIT_8RS|UNIT_TYPE, UNIT_8RS|UNIT_DPFP|UNIT_832, NULL, "832", NULL },\r
577 { UNIT_8RS, 0, NULL, "2RS", NULL },\r
578 { UNIT_8RS|UNIT_TYPE, UNIT_8RS|UNIT_DPFP|UNIT_832, "832, 8 register sets", NULL, NULL },\r
579 { UNIT_8RS|UNIT_TYPE, UNIT_DPFP|UNIT_832, "832, 2 register sets", NULL, NULL },\r
580 { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },\r
581 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },\r
582 { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },\r
583 { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },\r
584 { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size },\r
585 { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size },\r
586 { UNIT_MSIZE, 1048756, NULL, "1M", &cpu_set_size },\r
587 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",\r
588 &cpu_set_consint, NULL, NULL },\r
589 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",\r
590 &cpu_set_hist, &cpu_show_hist },\r
591 { 0 }\r
592 };\r
593\r
594DEBTAB cpu_deb[] = {\r
595 { "INTEXC", LOG_CPU_I },\r
596 { "CONTEXT", LOG_CPU_C },\r
597 { NULL, 0 }\r
598 };\r
599\r
600DEVICE cpu_dev = {\r
601 "CPU", &cpu_unit, cpu_reg, cpu_mod,\r
602 1, 16, 20, 2, 16, 16,\r
603 &cpu_ex, &cpu_dep, &cpu_reset,\r
604 NULL, NULL, NULL,\r
605 &cpu_dib, DEV_DEBUG, 0,\r
606 cpu_deb, NULL, NULL\r
607 };\r
608\r
609t_stat sim_instr (void)\r
610{\r
611volatile uint32 cc; /* set before setjmp */\r
612t_stat reason; /* set after setjmp */\r
613int abortval;\r
614\r
615/* Restore register state */\r
616\r
617if (devtab_init ()) return SCPE_STOP; /* check conflicts */\r
618if (cpu_unit.flags & (UNIT_DPFP | UNIT_832)) {\r
619 fp_in_hwre = 1; /* fp in hwre */\r
620 dec_flgs = 0; /* all instr ok */\r
621 }\r
622else {\r
623 fp_in_hwre = 0; /* fp in ucode */\r
624 dec_flgs = OP_DPF; /* sp only */\r
625 }\r
626if (cpu_unit.flags & UNIT_8RS) psw_reg_mask = 7; /* 8 register sets */\r
627else psw_reg_mask = 1; /* 2 register sets */\r
628int_eval (); /* eval interrupts */\r
629cc = newPSW (PSW & PSW_MASK); /* split PSW, eval wait */\r
630reason = 0;\r
631\r
632/* Abort handling\r
633\r
634 If an abort occurs in memory protection, the relocation routine\r
635 executes a longjmp to this area OUTSIDE the main simulation loop.\r
636 Memory protection errors are the only sources of aborts in the\r
637 Interdata 32b systems. All referenced variables must be globals,\r
638 and all sim_instr scoped automatic variables must be volatile or\r
639 set after the call on setjmp.\r
640*/\r
641\r
642abortval = setjmp (save_env); /* set abort hdlr */\r
643if (abortval != 0) { /* mem mgt abort? */\r
644 qevent = qevent | EV_MAC; /* set MAC intr */\r
645 if (cpu_unit.flags & UNIT_832) PC = oPC; /* 832? restore PC */\r
646 }\r
647\r
648/* Event handling */\r
649\r
650while (reason == 0) { /* loop until halted */\r
651\r
652 uint32 dev, drom, opnd, inc, lim, bufa;\r
653 uint32 op, r1, r1p1, r2, rx2, ea;\r
654 uint32 mpy, mpc, dvr;\r
655 uint32 i, rslt, rlo, t;\r
656 uint32 ir1, ir2, ir3, ityp;\r
657 int32 sr, st;\r
658\r
659 if (sim_interval <= 0) { /* check clock queue */\r
660 if (reason = sim_process_event ()) break;\r
661 int_eval ();\r
662 }\r
663\r
664 if (qevent) { /* any events? */\r
665 if (qevent & EV_MAC) { /* MAC interrupt? */\r
666 qevent = 0; /* clr all events */\r
667 cc = exception (MPRPSW, cc, 0); /* take exception */\r
668 int_eval (); /* re-eval intr */\r
669 continue;\r
670 }\r
671\r
672 if (qevent & EV_BLK) { /* block I/O in prog? */\r
673 dev = blk_io.dfl & DEV_MAX; /* get device */\r
674 cc = dev_tab[dev] (dev, IO_SS, 0) & 0xF; /* sense status */\r
675 if (cc == STA_BSY) { /* just busy? */\r
676 sim_interval = 0; /* force I/O event */\r
677 continue;\r
678 }\r
679 else if (cc == 0) { /* ready, no err? */\r
680 if (blk_io.dfl & BL_RD) { /* read? */\r
681 t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */\r
682 if ((t == 0) && (blk_io.dfl & BL_LZ)) continue;\r
683 blk_io.dfl = blk_io.dfl & ~BL_LZ; /* non-zero seen */\r
684 WriteB (blk_io.cur, t, VW); /* write mem */\r
685 }\r
686 else { /* write */\r
687 t = ReadB (blk_io.cur, VR); /* read mem */\r
688 dev_tab[dev] (dev, IO_WD, t); /* put byte */\r
689 }\r
690 if (blk_io.cur != blk_io.end) { /* more to do? */\r
691 blk_io.cur = (blk_io.cur + 1) & VAMASK; /* incr addr */\r
692 continue;\r
693 }\r
694 }\r
695 qevent = qevent & ~EV_BLK; /* clr blk I/O flag */\r
696 int_eval (); /* re-eval intr */\r
697 continue;\r
698 }\r
699\r
700 if ((qevent & EV_INT) && (PSW & PSW_EXI)) { /* interrupt? */\r
701 dev = int_getdev (); /* get int dev */\r
702 cc = int_auto (dev, cc); /* do auto intr */\r
703 int_eval (); /* re-eval intr */\r
704 continue;\r
705 }\r
706\r
707 if (PSW & PSW_WAIT) { /* wait state? */\r
708 if (sim_idle_enab) /* idling enabled? */\r
709 sim_idle (TMR_LFC, TRUE);\r
710 else sim_interval = sim_interval - 1; /* no, count cycle */\r
711 continue;\r
712 }\r
713\r
714 qevent = 0; /* no events */\r
715 }\r
716\r
717/* Instruction fetch and decode */\r
718\r
719 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */\r
720 reason = STOP_IBKPT; /* stop simulation */\r
721 break;\r
722 }\r
723\r
724 sim_interval = sim_interval - 1;\r
725\r
726 ir1 = ReadH (oPC = PC, VE); /* fetch instr */\r
727 op = (ir1 >> 8) & 0xFF; /* extract op,R1,R2 */\r
728 r1 = (ir1 >> 4) & 0xF;\r
729 r2 = ir1 & 0xF;\r
730 drom = decrom[op]; /* get decode flags */\r
731 ityp = drom & OP_MASK; /* instruction type */\r
732\r
733 if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */\r
734 if (stop_inst) reason = STOP_RSRV; /* stop or */\r
735 else cc = exception (ILOPSW, cc, 0); /* exception */\r
736 continue;\r
737 }\r
738 if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */\r
739 cc = exception (ILOPSW, cc, 0); /* exception */\r
740 continue;\r
741 }\r
742\r
743 switch (ityp) { /* decode instruction */\r
744\r
745 case OP_NO: /* no operand */\r
746 opnd = r2; /* assume short */\r
747 PC = (PC + 2) & VAMASK; /* increment PC */\r
748 break;\r
749\r
750 case OP_RR: /* reg-reg */\r
751 opnd = R[r2]; /* ea/operand is R2 */\r
752 PC = (PC + 2) & VAMASK; /* increment PC */\r
753 break;\r
754\r
755 case OP_RI1: /* reg-imm 1 */\r
756 ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */\r
757 opnd = SEXT16 (ir2); /* sign extend */\r
758 if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */\r
759 PC = (PC + 4) & VAMASK; /* increment PC */\r
760 break;\r
761\r
762 case OP_RI2: /* reg-imm 2 */\r
763 ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */\r
764 ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */\r
765 opnd = (ir2 << 16) | ir3; /* 32b immediate */\r
766 if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */\r
767 PC = (PC + 6) & VAMASK; /* increment PC */\r
768 break;\r
769\r
770 case OP_RX: case OP_RXB: case OP_RXH: case OP_RXF: /* reg-mem */\r
771 ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */\r
772 if ((ir2 & 0xC000) == 0) { /* displacement? */\r
773 PC = (PC + 4) & VAMASK; /* increment PC */\r
774 ea = ir2; /* abs 14b displ */\r
775 }\r
776 else if (ir2 & 0x8000) { /* relative? */\r
777 PC = (PC + 4) & VAMASK; /* increment PC */\r
778 ea = PC + SEXT15 (ir2); /* add to incr PC */\r
779 }\r
780 else { /* absolute */\r
781 rx2 = (ir2 >> 8) & 0xF; /* get second index */\r
782 ea = (ir2 & 0xFF) << 16; /* shift to place */\r
783 ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */\r
784 ea = ea | ir3; /* finish addr */\r
785 if (rx2) ea = ea + R[rx2]; /* index calc 2 */\r
786 PC = (PC + 6) & VAMASK; /* increment PC */\r
787 }\r
788 if (r2) ea = ea + R[r2]; /* index calculation */\r
789 ea = ea & VAMASK;\r
790 if (ityp == OP_RXF) opnd = ReadF (ea, VR); /* get fw operand? */\r
791 else if (ityp == OP_RXH) { /* get hw operand? */\r
792 t = ReadH (ea, VR); /* read halfword */\r
793 opnd = SEXT16 (t); /* sign extend */\r
794 }\r
795 else if (ityp == OP_RXB) opnd = ReadB (ea, VR); /* get byte opnd? */\r
796 else opnd = ea; /* just address */\r
797 break;\r
798\r
799 default:\r
800 return SCPE_IERR;\r
801 }\r
802\r
803 if (hst_lnt) { /* instruction history? */\r
804 hst[hst_p].pc = oPC | HIST_PC; /* save decode state */\r
805 hst[hst_p].ir1 = ir1;\r
806 hst[hst_p].ir2 = ir2;\r
807 hst[hst_p].ir3 = ir3;\r
808 hst[hst_p].r1 = R[r1];\r
809 hst[hst_p].ea = ea;\r
810 hst[hst_p].opnd = opnd;\r
811 hst_p = hst_p + 1;\r
812 if (hst_p >= hst_lnt) hst_p = 0;\r
813 }\r
814 if (qevent & EV_MAC) continue; /* MAC abort on fetch? */\r
815 switch (op) { /* case on opcode */\r
816\r
817/* Load/store instructions */\r
818\r
819 case 0x08: /* LR - RR */\r
820 case 0x24: /* LIS - NO */\r
821 case 0x48: /* LH - RXH */\r
822 case 0x58: /* L - RXF */\r
823 case 0xC8: /* LHI - RI1 */\r
824 case 0xF8: /* LI - RI2 */\r
825 R[r1] = opnd; /* load operand */\r
826 CC_GL_32 (R[r1]); /* set G,L */\r
827 break;\r
828\r
829 case 0x73: /* LHL - RXH */\r
830 R[r1] = opnd & DMASK16; /* get op, zero ext */\r
831 CC_GL_32 (R[r1]); /* set G, L */\r
832 break;\r
833\r
834 case 0x25: /* LCS - NO */\r
835 R[r1] = NEG (opnd); /* load complement */\r
836 CC_GL_32 (R[r1]); /* set G,L */\r
837 break;\r
838\r
839 case 0xE6: /* LA - RX */\r
840 R[r1] = ea; /* load addr */\r
841 break;\r
842\r
843 case 0x63: /* LRA - RX */\r
844 cc = RelocT (R[r1] & VAMASK, ea, VR, &R[r1]); /* test reloc */\r
845 break;\r
846\r
847 case 0x40: /* STH - RX */\r
848 WriteH (ea, R[r1], VW); /* store register */\r
849 break;\r
850\r
851 case 0x50: /* ST - RX */\r
852 WriteF (ea, R[r1], VW); /* store register */\r
853 break;\r
854\r
855 case 0xD1: /* LM - RX */\r
856 for ( ; r1 <= 0xF; r1++) { /* loop thru reg */\r
857 R[r1] = ReadF (ea, VR); /* load register */\r
858 ea = (ea + 4) & VAMASK; /* incr mem addr */\r
859 }\r
860 break;\r
861\r
862 case 0xD0: /* STM - RX */\r
863 for ( ; r1 <= 0xF; r1++) { /* loop thru reg */\r
864 WriteF (ea, R[r1], VW); /* store register */\r
865 ea = (ea + 4) & VAMASK; /* incr mem addr */\r
866 }\r
867 break;\r
868\r
869 case 0xE0: /* TS - RXH */\r
870 CC_GL_16 (opnd); /* set cc's */\r
871 WriteH (ea, opnd | SIGN16, VW); /* set MSB */\r
872 break;\r
873\r
874 case 0x93: /* LDBR - RR */\r
875 case 0xD3: /* LDB - RXB */\r
876 R[r1] = opnd & DMASK8; /* load byte */\r
877 break;\r
878\r
879 case 0x92: /* STBR - NO */\r
880 R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */\r
881 break;\r
882 case 0xD2: /* STB - RX */\r
883 WriteB (ea, R[r1], VW); /* store byte */\r
884 break;\r
885\r
886 case 0x34: /* EXHR - RR */\r
887 R[r1] = ((opnd >> 16) & DMASK16) | ((opnd & DMASK16) << 16);\r
888 break;\r
889\r
890 case 0x94: /* EXBR - RR */\r
891 R[r1] = (R[r1] & ~DMASK16) |\r
892 ((opnd >> 8) & DMASK8) | ((opnd & DMASK8) << 8);\r
893 break;\r
894\r
895/* Control instructions */\r
896\r
897 case 0x01: /* BALR - RR */\r
898 case 0x41: /* BAL - RX */\r
899 PCQ_ENTRY; /* save old PC */\r
900 R[r1] = PC; /* save cur PC */\r
901 PC = opnd & VAMASK; /* branch */\r
902 break;\r
903\r
904 case 0x02: /* BTCR - RR */\r
905 case 0x42: /* BTC - RX */\r
906 if (cc & r1) { /* test CC's */\r
907 PCQ_ENTRY; /* branch if true */\r
908 PC = opnd & VAMASK;\r
909 }\r
910 break;\r
911\r
912 case 0x20: /* BTBS - NO */\r
913 if (cc & r1) { /* test CC's */\r
914 PCQ_ENTRY; /* branch if true */\r
915 PC = (oPC - r2 - r2) & VAMASK;\r
916 }\r
917 break;\r
918\r
919 case 0x21: /* BTFS - NO */\r
920 if (cc & r1) { /* test CC's */\r
921 PCQ_ENTRY; /* branch if true */\r
922 PC = (oPC + r2 + r2) & VAMASK;\r
923 }\r
924 break;\r
925\r
926 case 0x03: /* BFCR - RR */\r
927 case 0x43: /* BFC - RX */\r
928 if ((cc & r1) == 0) { /* test CC's */\r
929 PCQ_ENTRY; /* branch if false */\r
930 PC = opnd & VAMASK;\r
931 }\r
932 break;\r
933\r
934 case 0x22: /* BFBS - NO */\r
935 if ((cc & r1) == 0) { /* test CC's */\r
936 PCQ_ENTRY; /* branch if false */\r
937 PC = (oPC - r2 - r2) & VAMASK;\r
938 }\r
939 break;\r
940\r
941 case 0x23: /* BFFS - NO */\r
942 if ((cc & r1) == 0) { /* test CC's */\r
943 PCQ_ENTRY; /* branch if false */\r
944 PC = (oPC + r2 + r2) & VAMASK;\r
945 }\r
946 break;\r
947\r
948 case 0xC0: /* BXH - RX */\r
949 inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */\r
950 lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */\r
951 R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */\r
952 if (R[r1] > lim) { /* if R1 > lim */\r
953 PCQ_ENTRY; /* branch */\r
954 PC = opnd & VAMASK;\r
955 }\r
956 break;\r
957\r
958 case 0xC1: /* BXLE - RX */\r
959 inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */\r
960 lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */\r
961 R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */\r
962 if (R[r1] <= lim) { /* if R1 <= lim */\r
963 PCQ_ENTRY; /* branch */\r
964 PC = opnd & VAMASK;\r
965 }\r
966 break;\r
967\r
968/* Logical instructions */\r
969\r
970 case 0x04: /* NR - RR */\r
971 case 0x44: /* NH - RXH */\r
972 case 0x54: /* N - RXF */\r
973 case 0xC4: /* NHI - RI1 */\r
974 case 0xF4: /* NI - RI2 */\r
975 R[r1] = R[r1] & opnd; /* result */\r
976 CC_GL_32 (R[r1]); /* set G,L */\r
977 break;\r
978\r
979 case 0x06: /* OR - RR */\r
980 case 0x46: /* OH - RXH */\r
981 case 0x56: /* O - RXF */\r
982 case 0xC6: /* OHI - RI1 */\r
983 case 0xF6: /* OI - RI2 */\r
984 R[r1] = R[r1] | opnd; /* result */\r
985 CC_GL_32 (R[r1]); /* set G,L */\r
986 break;\r
987\r
988 case 0x07: /* XR - RR */\r
989 case 0x47: /* XH - RXH */\r
990 case 0x57: /* X - RXF */\r
991 case 0xC7: /* XHI - RI1 */\r
992 case 0xF7: /* XI - RI2 */\r
993 R[r1] = R[r1] ^ opnd; /* result */\r
994 CC_GL_32 (R[r1]); /* set G,L */\r
995 break;\r
996\r
997 case 0xC3: /* THI - RI1 */\r
998 case 0xF3: /* TI - RI2 */\r
999 rslt = R[r1] & opnd; /* result */\r
1000 CC_GL_32 (rslt); /* set G, L */\r
1001 break;\r
1002\r
1003 case 0x05: /* CLR - RR */\r
1004 case 0x45: /* CLH - RXH */\r
1005 case 0x55: /* CL - RXF */\r
1006 case 0xC5: /* CLHI - RI1 */\r
1007 case 0xF5: /* CI - RI2 */\r
1008 rslt = (R[r1] - opnd) & DMASK32; /* result */\r
1009 CC_GL_32 (rslt); /* set G,L */\r
1010 if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */\r
1011 if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V;\r
1012 break;\r
1013\r
1014 case 0xD4: /* CLB - RXB */\r
1015 t = R[r1] & DMASK8;\r
1016 rslt = (t - opnd) & DMASK16; /* result */\r
1017 CC_GL_16 (rslt); /* set G,L 16b */\r
1018 if (t < opnd) cc = cc | CC_C; /* set C if borrow */\r
1019 break;\r
1020\r
1021 case 0x12: /* CHVR - RR */\r
1022 t = cc & CC_C; /* save C */\r
1023 R[r1] = (SEXT16 (opnd & DMASK16)) & DMASK32; /* result */\r
1024 CC_GL_32 (R[r1]); /* set G, L */\r
1025 if (R[r1] != opnd) cc = cc | CC_V; /* wont fit? set V */\r
1026 cc = cc | t; /* restore C */\r
1027 break;\r
1028\r
1029/* Shift instructions */\r
1030\r
1031 case 0xCC: /* SRHL - RI1 */\r
1032 opnd = opnd & 0xF; /* shift count */\r
1033 case 0x90: /* SRHLS - NO */\r
1034 rslt = (R[r1] & DMASK16) >> opnd; /* result */\r
1035 CC_GL_16 (rslt); /* set G,L 16b */\r
1036 if (opnd && (((R[r1] & DMASK16) >> (opnd - 1)) & 1)) cc = cc | CC_C;\r
1037 R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */\r
1038 break;\r
1039\r
1040 case 0xCD: /* SLHL - RI1 */\r
1041 opnd = opnd & 0xF; /* shift count */\r
1042 case 0x91: /* SLHLS - NO */\r
1043 rslt = R[r1] << opnd; /* result */\r
1044 CC_GL_16 (rslt & DMASK16); /* set G,L 16b */\r
1045 if (opnd && (rslt & 0x10000)) cc = cc | CC_C; /* set C if shft out */\r
1046 R[r1] = (R[r1] & ~DMASK16) | (rslt & DMASK16); /* store result */\r
1047 break;\r
1048\r
1049 case 0xCE: /* SRHA - RI1 */\r
1050 opnd = opnd & 0xF; /* shift count */\r
1051 rslt = (SEXT16 (R[r1]) >> opnd) & DMASK16; /* result */\r
1052 CC_GL_16 (rslt); /* set G,L 16b */\r
1053 if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C;\r
1054 R[r1] = (R[r1] & ~DMASK16) | rslt; /* store result */\r
1055 break;\r
1056\r
1057 case 0xCF: /* SLHA - RI1 */\r
1058 opnd = opnd & 0xF; /* shift count */\r
1059 rslt = R[r1] << opnd; /* raw result */\r
1060 R[r1] = (R[r1] & ~MMASK16) | (rslt & MMASK16);\r
1061 CC_GL_16 (R[r1] & DMASK16); /* set G,L 16b */\r
1062 if (opnd && (rslt & SIGN16)) cc = cc | CC_C; /* set C if shft out */\r
1063 break;\r
1064\r
1065 case 0xEC: /* SRL - RI1 */\r
1066 opnd = opnd & 0x1F; /* shift count */\r
1067 case 0x10: /* SRLS - NO */\r
1068 rslt = R[r1] >> opnd; /* result */\r
1069 CC_GL_32 (rslt); /* set G,L */\r
1070 if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C;\r
1071 R[r1] = rslt; /* store result */\r
1072 break;\r
1073\r
1074 case 0xED: /* SLL - RI1 */\r
1075 opnd = opnd & 0x1F; /* shift count */\r
1076 case 0x11: /* SLLS - NO */\r
1077 rslt = (R[r1] << opnd) & DMASK32; /* result */\r
1078 CC_GL_32 (rslt); /* set G,L */\r
1079 if (opnd && ((R[r1] << (opnd - 1)) & SIGN32)) cc = cc | CC_C;\r
1080 R[r1] = rslt; /* store result */\r
1081 break;\r
1082\r
1083 case 0xEE: /* SRA - RI1 */\r
1084 opnd = opnd & 0x1F; /* shift count */\r
1085 rslt = (SEXT32 (R[r1]) >> opnd) & DMASK32; /* result */\r
1086 CC_GL_32 (rslt); /* set G,L */\r
1087 if (opnd && ((R[r1] >> (opnd - 1)) & 1)) cc = cc | CC_C;\r
1088 R[r1] = rslt; /* store result */\r
1089 break;\r
1090\r
1091 case 0xEF: /* SLA - RI1 */\r
1092 opnd = opnd & 0x1F; /* shift count */\r
1093 rslt = (R[r1] << opnd) & DMASK32; /* raw result */\r
1094 R[r1] = (R[r1] & SIGN32) | (rslt & MMASK32); /* arith result */\r
1095 CC_GL_32 (R[r1]); /* set G,L */\r
1096 if (opnd && (rslt & SIGN32)) cc = cc | CC_C; /* set C if shft out */\r
1097 break;\r
1098\r
1099 case 0xEA: /* RRL - RI1 */\r
1100 opnd = opnd & 0x1F; /* shift count */\r
1101 if (opnd) R[r1] = (R[r1] >> opnd) | /* if cnt > 0 */\r
1102 ((R[r1] << (32 - opnd)) & DMASK32); /* rotate */\r
1103 CC_GL_32 (R[r1]); /* set G,L */\r
1104 break;\r
1105\r
1106 case 0xEB: /* RLL - RI1 */\r
1107 opnd = opnd & 0x1F; /* shift count */\r
1108 if (opnd) R[r1] = ((R[r1] << opnd) & DMASK32) | /* if cnt > 0 */\r
1109 (R[r1] >> (32 - opnd)); /* rotate */\r
1110 CC_GL_32 (R[r1]); /* set G,L */\r
1111 break;\r
1112\r
1113/* Bit instructions */\r
1114\r
1115 case 0x74: /* TBT - RX */\r
1116 t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */\r
1117 ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */\r
1118 opnd = ReadH (ea, VR); /* read HW */\r
1119 if (opnd & t) cc = CC_G; /* test bit */\r
1120 else cc = 0;\r
1121 break;\r
1122\r
1123 case 0x75: /* SBT - RX */\r
1124 t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */\r
1125 ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */\r
1126 opnd = ReadH (ea, VR); /* read HW */\r
1127 WriteH (ea, opnd | t, VW); /* set bit, rewr */\r
1128 if (opnd & t) cc = CC_G; /* test bit */\r
1129 else cc = 0;\r
1130 break;\r
1131\r
1132 case 0x76: /* RBT - RX */\r
1133 t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */\r
1134 ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */\r
1135 opnd = ReadH (ea, VR); /* read HW */\r
1136 WriteH (ea, opnd & ~t, VW); /* clr bit, rewr */\r
1137 if (opnd & t) cc = CC_G; /* test bit */\r
1138 else cc = 0;\r
1139 break;\r
1140\r
1141 case 0x77: /* CBT - RX */\r
1142 t = 1u << (15 - (R[r1] & 0xF)); /* bit mask in HW */\r
1143 ea = (ea + ((R[r1] >> 3) & ~1)) & VAMASK; /* HW location */\r
1144 opnd = ReadH (ea, VR); /* read HW */\r
1145 WriteH (ea, opnd ^ t, VW); /* com bit, rewr */\r
1146 if (opnd & t) cc = CC_G; /* test bit */\r
1147 else cc = 0;\r
1148 break;\r
1149\r
1150/* Arithmetic instructions */\r
1151\r
1152 case 0x0A: /* AR - RR */\r
1153 case 0x26: /* AIS - NO */\r
1154 case 0x4A: /* AH - RXH */\r
1155 case 0x5A: /* A - RXF */\r
1156 case 0xCA: /* AHI - RI1 */\r
1157 case 0xFA: /* AI - RI2 */\r
1158 rslt = (R[r1] + opnd) & DMASK32; /* result */\r
1159 CC_GL_32 (rslt); /* set G,L */\r
1160 if (rslt < opnd) cc = cc | CC_C; /* set C if carry */\r
1161 if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN32) cc = cc | CC_V;\r
1162 R[r1] = rslt;\r
1163 break;\r
1164\r
1165 case 0x51: /* AM - RXF */\r
1166 rslt = (R[r1] + opnd) & DMASK32; /* result */\r
1167 WriteF (ea, rslt, VW); /* write result */\r
1168 CC_GL_32 (rslt); /* set G,L */\r
1169 if (rslt < opnd) cc = cc | CC_C; /* set C if carry */\r
1170 if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN32) cc = cc | CC_V;\r
1171 break;\r
1172\r
1173 case 0x61: /* AHM - RXH */\r
1174 rslt = (R[r1] + opnd) & DMASK16; /* result */\r
1175 WriteH (ea, rslt, VW); /* write result */\r
1176 CC_GL_16 (rslt); /* set G,L 16b */\r
1177 if (rslt < (opnd & DMASK16)) cc = cc | CC_C; /* set C if carry */\r
1178 if (((~R[r1] ^ opnd) & (R[r1] ^ rslt)) & SIGN16) cc = cc | CC_V;\r
1179 break;\r
1180\r
1181 case 0x0B: /* SR - RR */\r
1182 case 0x27: /* SIS - NO */\r
1183 case 0x4B: /* SH - RXH */\r
1184 case 0x5B: /* S - RXF */\r
1185 case 0xCB: /* SHI - RI1 */\r
1186 case 0xFB: /* SI - RI2 */\r
1187 rslt = (R[r1] - opnd) & DMASK32; /* result */\r
1188 CC_GL_32 (rslt); /* set G,L */\r
1189 if (R[r1] < opnd) cc = cc | CC_C; /* set C if borrow */\r
1190 if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V;\r
1191 R[r1] = rslt;\r
1192 break;\r
1193\r
1194 case 0x09: /* CR - RR */\r
1195 case 0x49: /* CH - RXH */\r
1196 case 0x59: /* C - RXF */\r
1197 case 0xC9: /* CHI - RI1 */\r
1198 case 0xF9: /* CI - RI2 */\r
1199 if (R[r1] == opnd) cc = 0; /* =? */\r
1200 else if ((R[r1] ^ opnd) & SIGN32) /* unlike signs? */\r
1201 cc = (R[r1] & SIGN32)? (CC_C | CC_L): CC_G;\r
1202 else cc = (R[r1] > opnd)? CC_G: (CC_C | CC_L); /* like signs */\r
1203 if (((R[r1] ^ opnd) & (~opnd ^ (R[r1] - opnd))) & SIGN32)\r
1204 cc = cc | CC_V;\r
1205 break;\r
1206\r
1207 case 0x0C: /* MHR - RR */\r
1208 case 0x4C: /* MH - RXH */\r
1209 R[r1] = (SEXT16 (R[r1]) * SEXT16 (opnd)) & DMASK32; /* multiply */\r
1210 break;\r
1211\r
1212 case 0x1C: /* MR - RR */\r
1213 case 0x5C: /* M - RXF */\r
1214 r1p1 = (r1 + 1) & 0xF;\r
1215 mpc = ABS (opnd); /* |mpcnd| */\r
1216 mpy = ABS (R[r1p1]); /* |mplyr| */\r
1217 rslt = rlo = 0; /* clr result */\r
1218 for (i = 0; i < 32; i++) { /* develop 32b */\r
1219 t = 0; /* no cout */\r
1220 if (mpy & 1) { /* cond add */\r
1221 rslt = (rslt + mpc) & DMASK32;\r
1222 if (rslt < mpc) t = SIGN32;\r
1223 }\r
1224 rlo = (rlo >> 1) | ((rslt & 1) << 31); /* shift result */\r
1225 rslt = (rslt >> 1) | t;\r
1226 mpy = mpy >> 1; /* shift mpylr */\r
1227 }\r
1228 if ((opnd ^ R[r1p1]) & SIGN32) {\r
1229 DNEG (rslt, rlo);\r
1230 }\r
1231 R[r1] = rslt; /* store result */\r
1232 R[r1p1] = rlo;\r
1233 break;\r
1234\r
1235 case 0x0D: /* DHR - RR */\r
1236 case 0x4D: /* DH - RXH */\r
1237 opnd = opnd & DMASK16; /* force HW opnd */\r
1238 if ((opnd == 0) || /* div by zero? */\r
1239 ((R[r1] == 0x80000000) && (opnd == 0xFFFF))) {\r
1240 if (PSW & PSW_AFI) /* div fault enabled? */\r
1241 cc = exception (AFIPSW, cc, 0); /* exception */\r
1242 break;\r
1243 }\r
1244 r1p1 = (r1 + 1) & 0xF;\r
1245 st = SEXT32 (R[r1]) / SEXT16 (opnd); /* quotient */\r
1246 sr = SEXT32 (R[r1]) % SEXT16 (opnd); /* remainder */\r
1247 if ((st < 0x8000) && (st >= -0x8000)) { /* if quo fits */\r
1248 R[r1] = sr & DMASK32; /* store remainder */\r
1249 R[r1p1] = st & DMASK32; /* store quotient */\r
1250 }\r
1251 else if (PSW & PSW_AFI) /* div fault enabled? */\r
1252 cc = exception (AFIPSW, cc, 0); /* exception */\r
1253 break;\r
1254\r
1255 case 0x1D: /* DR - RR */\r
1256 case 0x5D: /* D - RXF */\r
1257 r1p1 = (r1 + 1) & 0xF;\r
1258 rslt = R[r1]; /* get dividend */\r
1259 rlo = R[r1p1];\r
1260 if (R[r1] & SIGN32) { DNEG (rslt, rlo); } /* |divd| */\r
1261 dvr = ABS (opnd); /* |divr| */\r
1262 if (rslt < dvr) { /* will div work? */\r
1263 uint32 quos = R[r1] ^ opnd; /* expected sign */\r
1264 for (i = t = 0; i < 32; i++) { /* 32 iterations */\r
1265 rslt = ((rslt << 1) & DMASK32) | /* shift divd */\r
1266 ((rlo >> 31) & 1);\r
1267 rlo = (rlo << 1) & DMASK32;\r
1268 t = (t << 1) & DMASK32; /* shift quo */\r
1269 if (rslt >= dvr) { /* subtract work? */\r
1270 rslt = rslt - dvr; /* divd -= divr */\r
1271 t = t | 1; /* set quo bit */\r
1272 }\r
1273 }\r
1274 if (quos & SIGN32) t = NEG (t); /* res -? neg quo */\r
1275 if (R[r1] & SIGN32) rslt = NEG (rslt); /* adj rem sign */\r
1276 if (t && ((t ^ quos) & SIGN32)) { /* res sign wrong? */\r
1277 if (PSW & PSW_AFI) /* if enabled, */\r
1278 cc = exception (AFIPSW, cc, 0); /* exception */\r
1279 break;\r
1280 }\r
1281 R[r1] = rslt; /* store rem */\r
1282 R[r1p1] = t; /* store quo */\r
1283 }\r
1284 else if (PSW & PSW_AFI) /* div fault enabled? */\r
1285 cc = exception (AFIPSW, cc, 0); /* exception */\r
1286 break;\r
1287\r
1288/* Floating point instructions */\r
1289\r
1290 case 0x28: /* LER - NO */\r
1291 case 0x38: /* LDR - NO */\r
1292 case 0x68: /* LE - RX */\r
1293 case 0x78: /* LD - RX */\r
1294 cc = f_l (op, r1, r2, ea); /* load */\r
1295 if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */\r
1296 cc = exception (AFIPSW, cc, 1);\r
1297 break;\r
1298\r
1299 case 0x29: /* CER - NO */\r
1300 case 0x39: /* CDR - NO */\r
1301 case 0x69: /* CE - RX */\r
1302 case 0x79: /* CD - RX */\r
1303 cc = f_c (op, r1, r2, ea); /* compare */\r
1304 break;\r
1305\r
1306 case 0x2A: /* AER - NO */\r
1307 case 0x2B: /* SER - NO */\r
1308 case 0x3A: /* ADR - NO */\r
1309 case 0x3B: /* SDR - NO */\r
1310 case 0x6A: /* AE - RX */\r
1311 case 0x6B: /* SE - RX */\r
1312 case 0x7A: /* AD - RX */\r
1313 case 0x7B: /* SD - RX */\r
1314 cc = f_as (op, r1, r2, ea); /* add/sub */\r
1315 if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */\r
1316 cc = exception (AFIPSW, cc, 1);\r
1317 break;\r
1318\r
1319 case 0x2C: /* MER - NO */\r
1320 case 0x3C: /* MDR - NO */\r
1321 case 0x6C: /* ME - RX */\r
1322 case 0x7C: /* MD - RX */\r
1323 cc = f_m (op, r1, r2, ea); /* multiply */\r
1324 if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */\r
1325 cc = exception (AFIPSW, cc, 1);\r
1326 break;\r
1327\r
1328 case 0x2D: /* DER - NO */\r
1329 case 0x3D: /* DDR - NO */\r
1330 case 0x6D: /* DE - RX */\r
1331 case 0x7D: /* DD - RX */\r
1332 cc = f_d (op, r1, r2, ea); /* perform divide */\r
1333 if ((cc & CC_V) && (PSW & PSW_AFI)) /* V set? */\r
1334 cc = exception (AFIPSW, cc, 1);\r
1335 break;\r
1336\r
1337 case 0x2E: /* FXR - NO */\r
1338 case 0x3E: /* FXDR - NO */\r
1339 cc = f_fix32 (op, r1, r2); /* cvt to integer */\r
1340 break;\r
1341\r
1342 case 0x2F: /* FLR - NO */\r
1343 case 0x3F: /* FLDR - NO */\r
1344 cc = f_flt32 (op, r1, r2); /* cvt to floating */\r
1345 break;\r
1346\r
1347 case 0x60: /* STE - RX */\r
1348 t = ReadFReg (r1); /* get sp reg */\r
1349 WriteF (ea, t, VW); /* write */\r
1350 break;\r
1351\r
1352 case 0x70: /* STD - RX */\r
1353 WriteF (ea, D[r1 >> 1].h, VW); /* write hi */\r
1354 WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, VW); /* write lo */\r
1355 break;\r
1356\r
1357 case 0x71: /* STME - RX */\r
1358 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */\r
1359 t = ReadFReg (r1); /* get sp reg */\r
1360 WriteF (ea, t, VW); /* write */\r
1361 ea = (ea + 4) & VAMASK; /* incr mem addr */\r
1362 }\r
1363 break;\r
1364\r
1365 case 0x72: /* LME - RX */\r
1366 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */\r
1367 t = ReadF (ea, VR); /* get value */\r
1368 WriteFReg (r1, t); /* write reg */\r
1369 ea = (ea + 4) & VAMASK; /* incr mem addr */\r
1370 }\r
1371 break;\r
1372\r
1373 case 0x7E: /* STMD - RX */\r
1374 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */\r
1375 WriteF (ea, D[r1 >> 1].h, VW); /* write register */\r
1376 WriteF ((ea + 4) & VAMASK, D[r1 >> 1].l, VW);\r
1377 ea = (ea + 8) & VAMASK; /* incr mem addr */\r
1378 }\r
1379 break;\r
1380\r
1381 case 0x7F: /* LMD - RX */\r
1382 for ( ; r1 <= 0xE; r1 = r1 + 2) { /* loop thru reg */\r
1383 D[r1 >> 1].h = ReadF (ea, VR); /* load register */\r
1384 D[r1 >> 1].l = ReadF ((ea + 4) & VAMASK, VR);\r
1385 ea = (ea + 8) & VAMASK; /* incr mem addr */\r
1386 }\r
1387 break;\r
1388\r
1389/* Miscellaneous */\r
1390 \r
1391 case 0xE1: /* SVC - RX */\r
1392 PCQ_ENTRY; /* effective branch */\r
1393 t = BUILD_PSW (cc); /* save PSW */\r
1394 cc = newPSW (ReadF (SVNPS32, P)); /* get new PSW */\r
1395 R[13] = ea & 0xFFFFFF; /* parameter */\r
1396 R[14] = t; /* old PSW */\r
1397 R[15] = PC; /* old PC */\r
1398 PC = ReadH (SVNPC + r1 + r1, P); /* new PC */\r
1399 if (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb,\r
1400 ">>SVC: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n",\r
1401 pcq[pcq_p], t, PC, PSW);\r
1402 break;\r
1403\r
1404 case 0xE2: /* SINT - RI1 */\r
1405 dev = opnd & DEV_MAX; /* get dev */\r
1406 cc = int_auto (dev, cc); /* auto int */\r
1407 int_eval ();\r
1408 break;\r
1409\r
1410 case 0xE3: /* SCP - RXH */\r
1411 opnd = opnd & DMASK16; /* zero ext operand */\r
1412 if (opnd & CCW32_B1) t = ea + CCB32_B1C; /* point to buf */\r
1413 else t = ea + CCB32_B0C;\r
1414 sr = ReadH (t & VAMASK, VR); /* get count */\r
1415 sr = SEXT16 (sr); /* sign extend */\r
1416 if (sr <= 0) { /* <= 0? */\r
1417 bufa = ReadF ((t + 2) & VAMASK, VR); /* get buf end */\r
1418 if (opnd & CCW32_WR) /* write? */\r
1419 R[r1] = ReadB ((bufa + sr) & VAMASK, VR); /* R1 gets mem */\r
1420 else WriteB ((bufa + sr) & VAMASK, R[r1], VW); /* read, R1 to mem */\r
1421 sr = sr + 1; /* inc count */\r
1422 CC_GL_32 (sr & DMASK32); /* set cc's */\r
1423 WriteH (t & VAMASK, sr, VW); /* rewrite */\r
1424 if ((sr > 0) && !(opnd & CCW32_FST)) /* buf switch? */\r
1425 WriteH (ea, opnd ^ CCW32_B1, VW); /* flip CCW bit */\r
1426 } /* end if */\r
1427 else cc = CC_V;\r
1428 break;\r
1429\r
1430 case 0x18: /* LPSWR - RR */\r
1431 PCQ_ENTRY; /* effective branch */\r
1432 PC = R[(r2 + 1) & 0xF] & VAMASK; /* new PC (old reg set) */\r
1433 if (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb,\r
1434 ">>LPSWR: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n",\r
1435 pcq[pcq_p], BUILD_PSW (cc), PC, opnd);\r
1436 cc = newPSW (opnd); /* new PSW */\r
1437 if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */\r
1438 break;\r
1439\r
1440 case 0xC2: /* LPSW - RXF */\r
1441 PCQ_ENTRY; /* effective branch */\r
1442 PC = ReadF ((ea + 4) & VAMASK, VR) & VAMASK; /* new PC */\r
1443 if (DEBUG_PRI (cpu_dev, LOG_CPU_C)) fprintf (sim_deb,\r
1444 ">>LPSW: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n",\r
1445 pcq[pcq_p], BUILD_PSW (cc), PC, opnd);\r
1446 cc = newPSW (opnd); /* new PSW */\r
1447 if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */\r
1448 break;\r
1449\r
1450 case 0x95: /* EPSR - NO */\r
1451 R[r1] = BUILD_PSW (cc); /* save PSW */\r
1452 cc = newPSW (R[r2]); /* load new PSW */\r
1453 if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */\r
1454 break; \r
1455\r
1456 case 0x64: /* ATL - RX */\r
1457 case 0x65: /* ABL - RX */\r
1458 cc = addtoq (ea, R[r1], op & 1); /* add to q */\r
1459 break;\r
1460\r
1461 case 0x66: /* RTL - RX */\r
1462 case 0x67: /* RBL - RX */\r
1463 cc = remfmq (ea, r1, op & 1); /* rem from q */\r
1464 break;\r
1465\r
1466 case 0x5E: /* CRC12 - RXH */\r
1467 opnd = opnd & DMASK16; /* zero ext opnd */\r
1468 t = (R[r1] & 0x3F) ^ opnd;\r
1469 for (i = 0; i < 6; i++) {\r
1470 if (t & 1) t = (t >> 1) ^ 0x0F01;\r
1471 else t = t >> 1;\r
1472 }\r
1473 WriteH (ea, t, VW);\r
1474 break;\r
1475\r
1476 case 0x5F: /* CRC16 - RXH */\r
1477 opnd = opnd & DMASK16; /* zero ext opnd */\r
1478 t = (R[r1] & 0xFF) ^ opnd;\r
1479 for (i = 0; i < 8; i++) {\r
1480 if (t & 1) t = (t >> 1) ^ 0xA001;\r
1481 else t = t >> 1;\r
1482 }\r
1483 WriteH (ea, t, VW);\r
1484 break;\r
1485\r
1486 case 0xE7: /* TLATE - RXF */\r
1487 t = (opnd + ((R[r1] & DMASK8) << 1)) & VAMASK; /* table entry */\r
1488 rslt = ReadH (t, VR); /* get entry */\r
1489 if (rslt & SIGN16) R[r1] = rslt & DMASK8; /* direct xlate? */\r
1490 else {\r
1491 PCQ_ENTRY; /* branch */\r
1492 PC = rslt << 1;\r
1493 }\r
1494 break;\r
1495\r
1496/* I/O instructions */\r
1497\r
1498 case 0xDE: /* OC - RX */\r
1499 opnd = ReadB (ea, VR); /* fetch operand */\r
1500 case 0x9E: /* OCR - RR */\r
1501 dev = R[r1] & DEV_MAX;\r
1502 if (DEV_ACC (dev)) {\r
1503 dev_tab[dev] (dev, IO_ADR, 0); /* select */\r
1504 dev_tab[dev] (dev, IO_OC, opnd & DMASK8); /* send command */\r
1505 cc = 0;\r
1506 }\r
1507 else cc = CC_V;\r
1508 int_eval (); /* re-eval intr */\r
1509 break;\r
1510\r
1511 case 0xDA: /* WD - RX */\r
1512 opnd = ReadB (ea, VR); /* fetch operand */\r
1513 case 0x9A: /* WDR - RR */\r
1514 dev = R[r1] & DEV_MAX;\r
1515 if (DEV_ACC (dev)) {\r
1516 dev_tab[dev] (dev, IO_ADR, 0); /* select */\r
1517 dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send data */\r
1518 cc = 0;\r
1519 }\r
1520 else cc = CC_V;\r
1521 int_eval (); /* re-eval intr */\r
1522 break;\r
1523\r
1524 case 0xD8: /* WH - RX */\r
1525 opnd = ReadH (ea, VR); /* fetch operand */\r
1526 case 0x98: /* WHR - RR */\r
1527 dev = R[r1] & DEV_MAX;\r
1528 if (DEV_ACC (dev)) {\r
1529 if (dev_tab[dev] (dev, IO_ADR, 0)) /* select; hw ok? */\r
1530 dev_tab[dev] (dev, IO_WH, opnd & DMASK16); /* send data */\r
1531 else { /* byte only */\r
1532 dev_tab[dev] (dev, IO_WD, (opnd >> 8) & DMASK8); /* hi */\r
1533 dev_tab[dev] (dev, IO_WD, opnd & DMASK8); /* send lo byte */\r
1534 }\r
1535 cc = 0;\r
1536 }\r
1537 else cc = CC_V;\r
1538 int_eval (); /* re-eval intr */\r
1539 break;\r
1540\r
1541 case 0x9B: /* RDR - RR */\r
1542 case 0xDB: /* RD - RX */\r
1543 dev = R[r1] & DEV_MAX;\r
1544 if (DEV_ACC (dev)) { /* dev exist? */\r
1545 dev_tab[dev] (dev, IO_ADR, 0); /* select */\r
1546 t = dev_tab[dev] (dev, IO_RD, 0); /* get data */\r
1547 cc = 0;\r
1548 }\r
1549 else { /* no */\r
1550 t = 0;\r
1551 cc = CC_V;\r
1552 }\r
1553 if (OP_TYPE (op) != OP_RR) WriteB (ea, t, VW); /* RX or RR? */\r
1554 else R[r2] = t & DMASK8;\r
1555 int_eval (); /* re-eval intr */\r
1556 break;\r
1557\r
1558 case 0x99: /* RHR - RR */\r
1559 case 0xD9: /* RH - RX */\r
1560 dev = R[r1] & DEV_MAX;\r
1561 if (DEV_ACC (dev)) { /* dev exist? */\r
1562 if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */\r
1563 t = dev_tab[dev] (dev, IO_RH, 0); /* get data */\r
1564 else { /* byte only */\r
1565 rslt = dev_tab[dev] (dev, IO_RD, 0); /* get byte */\r
1566 t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */\r
1567 t = (rslt << 8) | t; /* merge */\r
1568 }\r
1569 cc = 0;\r
1570 }\r
1571 else { /* no */\r
1572 t = 0;\r
1573 cc = CC_V;\r
1574 }\r
1575 if (OP_TYPE (op) != OP_RR) WriteH (ea, t, VW); /* RX or RR? */\r
1576 else R[r2] = t & DMASK16;\r
1577 int_eval (); /* re-eval intr */\r
1578 break;\r
1579\r
1580 case 0x9D: /* SSR - RR */\r
1581 case 0xDD: /* SS - RX */\r
1582 dev = R[r1] & DEV_MAX;\r
1583 if (DEV_ACC (dev)) { /* dev exist? */\r
1584 dev_tab[dev] (dev, IO_ADR, 0); /* select */\r
1585 t = dev_tab[dev] (dev, IO_SS, 0); /* get status */\r
1586 }\r
1587 else t = STA_EX; /* no */\r
1588 if (OP_TYPE (op) != OP_RR) WriteB (ea, t, VW); /* RX or RR? */\r
1589 else R[r2] = t & DMASK8;\r
1590 cc = t & 0xF;\r
1591 int_eval (); /* re-eval intr */\r
1592 break;\r
1593\r
1594/* Block I/O instructions\r
1595 \r
1596 On a real Interdata system, the block I/O instructions can't be\r
1597 interrupted or stopped. To model this behavior, while allowing\r
1598 the instructions to go back through fetch for I/O processing and\r
1599 WRU testing, the simulator implements a 'block I/O in progress'\r
1600 flag and status block. If a block I/O is in progress, normal\r
1601 interrupts and fetches are suppressed until the block I/O is done.\r
1602*/\r
1603\r
1604 case 0x96: /* WBR - RR */\r
1605 case 0xD6: /* WB - RXF */\r
1606 dev = R[r1] & DEV_MAX;\r
1607 if (DEV_ACC (dev)) { /* dev exist? */\r
1608 if (OP_TYPE (op) != OP_RR)\r
1609 lim = ReadF ((ea + 4) & VAMASK, VR);\r
1610 else lim = R[(r2 + 1) & 0xF];\r
1611 if (opnd > lim) cc = 0; /* start > end? */\r
1612 else { /* no, start I/O */\r
1613 dev_tab[dev] (dev, IO_ADR, 0); /* select dev */\r
1614 blk_io.dfl = dev; /* set status block */\r
1615 blk_io.cur = opnd;\r
1616 blk_io.end = lim;\r
1617 qevent = qevent | EV_BLK; /* I/O in prog */\r
1618 }\r
1619 }\r
1620 else cc = CC_V; /* nx dev */\r
1621 break;\r
1622\r
1623 case 0x97: /* RBR - RR */\r
1624 case 0xD7: /* RB - RXF */\r
1625 dev = R[r1] & DEV_MAX;\r
1626 if (DEV_ACC (dev)) { /* dev exist? */\r
1627 if (OP_TYPE (op) != OP_RR)\r
1628 lim = ReadF ((ea + 4) & VAMASK, VR);\r
1629 else lim = R[(r2 + 1) & 0xF];\r
1630 if (opnd > lim) cc = 0; /* start > end? */\r
1631 else { /* no, start I/O */\r
1632 dev_tab[dev] (dev, IO_ADR, 0); /* select dev */\r
1633 blk_io.dfl = dev | BL_RD; /* set status block */\r
1634 blk_io.cur = opnd;\r
1635 blk_io.end = lim;\r
1636 qevent = qevent | EV_BLK; /* I/O in prog */\r
1637 }\r
1638 }\r
1639 else cc = CC_V; /* nx dev */\r
1640 break;\r
1641\r
1642 case 0xD5: /* AL - RX */\r
1643 dev = ReadB (AL_DEV, P); /* get device */\r
1644 t = ReadB (AL_IOC, P); /* get command */\r
1645 if (DEV_ACC (dev)) { /* dev exist? */\r
1646 if (AL_BUF > ea) cc = 0; /* start > end? */\r
1647 else { /* no, start I/O */\r
1648 dev_tab[dev] (dev, IO_ADR, 0); /* select dev */\r
1649 dev_tab[dev] (dev, IO_OC, t); /* start dev */\r
1650 blk_io.dfl = dev | BL_RD | BL_LZ; /* set status block */\r
1651 blk_io.cur = AL_BUF;\r
1652 blk_io.end = ea;\r
1653 qevent = qevent | EV_BLK; /* I/O in prog */\r
1654 }\r
1655 }\r
1656 else cc = CC_V; /* nx dev */\r
1657 break;\r
1658 } /* end switch */\r
1659 } /* end while */\r
1660\r
1661/* Simulation halted */\r
1662\r
1663PSW = BUILD_PSW (cc);\r
1664PC = PC & VAMASK;\r
1665set_r_display (R);\r
1666pcq_r->qptr = pcq_p; /* update pc q ptr */\r
1667return reason;\r
1668}\r
1669\r
1670/* Load new PSW */\r
1671\r
1672uint32 newPSW (uint32 val)\r
1673{\r
1674uint32 rs = PSW_GETREG (val); /* register set */\r
1675\r
1676R = &GREG[rs * 16]; /* set register set */\r
1677PSW = val & PSW_MASK; /* store PSW */\r
1678int_eval (); /* update intreq */\r
1679if (PSW & PSW_WAIT) qevent = qevent | EV_WAIT; /* wait state? */\r
1680else qevent = qevent & ~EV_WAIT;\r
1681if (PSW & PSW_EXI) SET_ENB (v_DS); /* enable/disable */\r
1682else CLR_ENB (v_DS); /* console intr */\r
1683return PSW & CC_MASK;\r
1684}\r
1685\r
1686/* Exception handler - 7/32 always uses register set 0 */\r
1687\r
1688uint32 exception (uint32 loc, uint32 cc, uint32 flg)\r
1689{\r
1690int32 oldPSW = BUILD_PSW (cc); /* save old PSW */\r
1691int32 oldPC = PC; /* save old PC */\r
1692\r
1693cc = newPSW (ReadF (loc, P)); /* new PSW */\r
1694PC = ReadF (loc + 4, P) & VAMASK; /* new PC */\r
1695if (cpu_unit.flags & UNIT_832) { /* 8/32? */\r
1696 R[14] = oldPSW; /* PSW to new 14 */\r
1697 R[15] = oldPC; /* PC to new 15 */\r
1698 }\r
1699else {\r
1700 GREG[14] = oldPSW; /* 7/32, PSW to set 0 14 */\r
1701 GREG[15] = oldPC; /* PC to set 0 15 */\r
1702 }\r
1703if (DEBUG_PRI (cpu_dev, LOG_CPU_I)) fprintf (sim_deb,\r
1704 ">>Exc %X: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n",\r
1705 loc, oldPC, oldPSW, PC, PSW | cc | flg);\r
1706return cc | flg; /* return CC */\r
1707}\r
1708\r
1709/* Test for queue interrupts - system queue addresses are physical */\r
1710\r
1711uint32 testsysq (uint32 cc)\r
1712{\r
1713int32 qb = ReadF (SQP, P); /* get sys q addr */\r
1714int32 usd = ReadH (qb + Q32_USD, P); /* get use count */\r
1715\r
1716if (usd) { /* entries? */\r
1717 cc = exception (SQTPSW, cc, 0); /* take sysq exc */\r
1718 if (cpu_unit.flags & UNIT_832) R[13] = qb; /* R13 = sys q addr */\r
1719 else GREG[13] = qb;\r
1720 }\r
1721return cc;\r
1722}\r
1723\r
1724/* Add to queue */\r
1725\r
1726uint32 addtoq (uint32 ea, uint32 val, uint32 flg)\r
1727{\r
1728uint32 slt, usd, wra, t;\r
1729\r
1730t = ReadF (ea, VR); /* slots/used */\r
1731slt = (t >> 16) & DMASK16; /* # slots */\r
1732usd = t & DMASK16; /* # used */\r
1733if (usd >= slt) return CC_V; /* list full? */\r
1734usd = (usd + 1) & DMASK16; /* inc # used */\r
1735WriteH (ea + Q32_USD, usd, VW); /* rewrite */\r
1736if (flg) { /* ABL? */\r
1737 wra = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */\r
1738 t = wra + 1; /* adv bottom */\r
1739 if (t >= slt) t = 0; /* wrap if necc */\r
1740 WriteH ((ea + Q32_BOT) & VAMASK, t, VW); /* rewrite bottom */\r
1741 }\r
1742else {\r
1743 wra = ReadH ((ea + Q32_TOP) & VAMASK, VR); /* ATL, get top */\r
1744 if (wra == 0) wra = (slt - 1) & DMASK16; /* wrap if necc */\r
1745 else wra = wra - 1; /* dec top */\r
1746 WriteH ((ea + Q32_TOP) & VAMASK, wra, VW); /* rewrite top */\r
1747 }\r
1748WriteF ((ea + Q32_BASE + (wra * Q32_SLNT)) & VAMASK, val, VW); /* write slot */\r
1749return 0;\r
1750}\r
1751\r
1752/* Remove from queue */\r
1753\r
1754uint32 remfmq (uint32 ea, uint32 r1, uint32 flg)\r
1755{\r
1756uint32 slt, usd, rda, t;\r
1757\r
1758t = ReadF (ea, VR); /* get slots/used */\r
1759slt = (t >> 16) & DMASK16; /* # slots */\r
1760usd = t & DMASK16; /* # used */\r
1761if (usd == 0) return CC_V; /* empty? */\r
1762usd = usd - 1; /* dec used */\r
1763WriteH (ea + Q32_USD, usd, VW); /* rewrite */\r
1764if (flg) { /* RBL? */\r
1765 rda = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */\r
1766 if (rda == 0) rda = (slt - 1) & DMASK16; /* wrap if necc */\r
1767 else rda = rda - 1; /* dec bottom */\r
1768 WriteH ((ea + Q32_BOT) & VAMASK, rda, VW); /* rewrite bottom */\r
1769 }\r
1770else {\r
1771 rda = ReadH ((ea + Q32_TOP) & VAMASK, VR); /* RTL, get top */\r
1772 t = rda + 1; /* adv top */\r
1773 if (t >= slt) t = 0; /* wrap if necc */\r
1774 WriteH ((ea + Q32_TOP) & VAMASK, t, VW); /* rewrite top */\r
1775 }\r
1776R[r1] = ReadF ((ea + Q32_BASE + (rda * Q32_SLNT)) & VAMASK, VR); /* read slot */\r
1777if (usd) return CC_G;\r
1778else return 0;\r
1779}\r
1780\r
1781/* Automatic interrupt processing */\r
1782\r
1783uint32 int_auto (uint32 dev, uint32 cc)\r
1784{\r
1785uint32 addr, vec, by, ccw, ccwa, ccwb;\r
1786uint32 i, hw, tblad, tblen, bufe, st, t;\r
1787int32 bufc;\r
1788uint32 oldPSW = BUILD_PSW (cc);\r
1789\r
1790vec = ReadH (INTSVT + dev + dev, P); /* get vector */\r
1791newPSW (0x2800); /* new PSW */\r
1792R[0] = oldPSW; /* save old PSW */\r
1793R[1] = PC; /* save PC */\r
1794R[2] = dev; /* set dev # */\r
1795if (DEBUG_PRI (cpu_dev, LOG_CPU_I)) fprintf (sim_deb,\r
1796 ">>Int %X: oPC = %X, oPSW = %X, nPC = %X, nPSW = %X\n",\r
1797 dev, PC, oldPSW, vec, 0x2800);\r
1798if (DEV_ACC (dev)) { /* dev exist? */\r
1799 hw = dev_tab[dev] (dev, IO_ADR, 0); /* select, get hw */\r
1800 R[3] = st = dev_tab[dev] (dev, IO_SS, 0); /* sense status */\r
1801 }\r
1802else {\r
1803 hw = 0;\r
1804 R[3] = CC_V;\r
1805 }\r
1806if ((vec & 1) == 0) { /* immed int? */\r
1807 PC = vec; /* new PC */\r
1808 return PSW & CC_MASK; /* exit */\r
1809 }\r
1810R[4] = ccwa = vec & ~1; /* save CCW addr */\r
1811ccw = ReadH (ccwa, VR); /* read CCW */\r
1812if ((ccw & CCW32_EXE) == 0) { /* exec clr? */\r
1813 PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */\r
1814 return 0; /* CC = 0 */\r
1815 }\r
1816if (!DEV_ACC (dev) || (st & CCW32_STA (ccw))) { /* bad status? */\r
1817 PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */\r
1818 return CC_L; /* CC = L */\r
1819 }\r
1820if (ccw & CCW32_FST) { /* fast mode? */\r
1821 t = ReadH (ccwa + CCB32_B0C, VR); /* get count */\r
1822 bufc = SEXT16 (t); /* sign ext */\r
1823 if (bufc <= 0) { /* still valid? */\r
1824 bufe = ReadF (ccwa + CCB32_B0E, VR); /* get end addr */\r
1825 addr = (bufe + bufc) & VAMASK;\r
1826 if (hw) { /* halfword? */\r
1827 if (ccw & CCW32_WR) { /* write? */\r
1828 t = ReadH (addr, VR); /* get hw */\r
1829 dev_tab[dev] (dev, IO_WH, t); /* send to dev */\r
1830 }\r
1831 else { /* read */\r
1832 t = dev_tab[dev] (dev, IO_RH, 0); /* get hw */\r
1833 WriteH (addr, t, VW); /* write to mem */\r
1834 }\r
1835 bufc = bufc + 2; /* adv buf cnt */\r
1836 }\r
1837 else { /* byte */\r
1838 if (ccw & CCW32_WR) { /* write? */\r
1839 t = ReadB (addr, VR); /* get byte */\r
1840 dev_tab[dev] (dev, IO_WD, t); /* send to dev */\r
1841 }\r
1842 else { /* read */\r
1843 t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */\r
1844 WriteB (addr, t, VW); /* write to mem */\r
1845 }\r
1846 bufc = bufc + 1; /* adv buf cnt */\r
1847 }\r
1848 WriteH (ccwa + CCB32_B0C, bufc, VW); /* rewrite cnt */\r
1849 if (bufc > 0) {\r
1850 PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */\r
1851 return CC_G; /* CC = G */\r
1852 }\r
1853 } /* end if bufc <= 0 */\r
1854 } /* end fast */\r
1855else { /* slow mode */\r
1856 if (ccw & CCW32_B1) ccwb = ccwa + CCB32_B1C; /* which buf? */\r
1857 else ccwb = ccwa + CCB32_B0C;\r
1858 t = ReadH (ccwb, VR); /* get count */\r
1859 bufc = SEXT16 (t); /* sign ext */\r
1860 if (bufc <= 0) { /* still valid? */\r
1861 bufe = ReadF (ccwb + 2, VR); /* get end addr */\r
1862 addr = (bufe + bufc) & VAMASK;\r
1863 if (ccw & CCW32_WR) { /* write? */\r
1864 by = ReadB (addr, VR); /* byte fm mem */\r
1865 if (ccw & CCW32_TL) { /* translate? */\r
1866 tblad = ReadF (ccwa + CCB32_TAB, VR); /* get tbl addr */\r
1867 tblen = (tblad + (by << 1)) & VAMASK; /* tbl entry addr */\r
1868 t = ReadH (tblen, VR); /* get tbl entry */\r
1869 if ((t & SIGN16) == 0) { /* special xlate? */\r
1870 PC = t << 1; /* change PC */\r
1871 R[3] = by; /* untrans char */\r
1872 return 0; /* CC = 0 */\r
1873 }\r
1874 by = t & DMASK8; /* replace */\r
1875 }\r
1876 dev_tab[dev] (dev, IO_WD, by); /* write to dev */\r
1877 }\r
1878 else { /* read */\r
1879 by = dev_tab[dev] (dev, IO_RD, 0); /* get from dev */\r
1880 if (ccw & CCW32_TL) { /* translate? */\r
1881 tblad = ReadF (ccwa + CCB32_TAB, VR); /* get tbl addr */\r
1882 tblen = (tblad + (by << 1)) & VAMASK; /* tbl entry addr */\r
1883 t = ReadH (tblen, VR); /* get tbl entry */\r
1884 if ((t & SIGN16) == 0) { /* special xlate? */\r
1885 PC = t << 1; /* change PC */\r
1886 R[3] = by; /* untrans char */\r
1887 return 0; /* CC = 0 */\r
1888 }\r
1889 WriteB (addr, t, VW); /* wr trans */\r
1890 }\r
1891 else WriteB (addr, by, VW); /* wr orig */\r
1892 }\r
1893 t = ReadH (ccwa + CCB32_CHK, VR); /* get check wd */\r
1894 t = t ^ by; /* start LRC */\r
1895 if (ccw & CCW32_CRC) { /* CRC? */\r
1896 for (i = 0; i < 8; i++) {\r
1897 if (t & 1) t = (t >> 1) ^ 0xA001;\r
1898 else t = t >> 1;\r
1899 }\r
1900 }\r
1901 WriteH (ccwa + CCB32_CHK, t, VW); /* rewrite chk wd */\r
1902 bufc = bufc + 1; /* adv buf cnt */\r
1903 WriteH (ccwb, bufc, VW); /* rewrite cnt */\r
1904 if (bufc > 0) { /* cnt pos? */\r
1905 ccw = ccw ^ CCW32_B1; /* flip buf */\r
1906 WriteH (ccwa, ccw, VW); /* rewrite */\r
1907 PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */\r
1908 return CC_G; /* CC = G */\r
1909 }\r
1910 } /* end if bufc */\r
1911 } /* end slow */\r
1912PC = R[1]; /* restore PC */\r
1913return newPSW (R[0]); /* restore PSW, CC */\r
1914}\r
1915\r
1916/* Display register device */\r
1917\r
1918uint32 display (uint32 dev, uint32 op, uint32 dat)\r
1919{\r
1920int t;\r
1921\r
1922switch (op) {\r
1923\r
1924 case IO_ADR: /* select */\r
1925 if (!drmod) drpos = srpos = 0; /* norm mode? clr */\r
1926 return BY; /* byte only */\r
1927\r
1928 case IO_OC: /* command */\r
1929 op = op & 0xC0;\r
1930 if (op == 0x40) { /* x40 = inc */\r
1931 drmod = 1;\r
1932 drpos = srpos = 0; /* init cntrs */\r
1933 }\r
1934 else if (op == 0x80) drmod = 0; /* x80 = norm */\r
1935 break;\r
1936\r
1937 case IO_WD: /* write */\r
1938 if (drpos < 4) \r
1939 DR = (DR & ~(DMASK8 << (drpos * 8))) | (dat << (drpos * 8));\r
1940 else if (drpos == 4) DRX = dat;\r
1941 drpos = (drpos + 1) & 0x7;\r
1942 break;\r
1943\r
1944 case IO_RD: /* read */\r
1945 t = (SR >> (srpos * 8)) & DMASK8;\r
1946 srpos = srpos ^ 1;\r
1947 return t;\r
1948\r
1949 case IO_SS: /* status */\r
1950 return 0x80;\r
1951 }\r
1952\r
1953return 0;\r
1954} \r
1955\r
1956/* Relocation and protection */\r
1957\r
1958uint32 Reloc (uint32 va, uint32 rel)\r
1959{\r
1960uint32 seg, off, mapr, lim;\r
1961\r
1962seg = VA_GETSEG (va); /* get seg num */\r
1963off = VA_GETOFF (va); /* get offset */\r
1964mapr = mac_reg[seg]; /* get seg reg */\r
1965lim = GET_SRL (mapr); /* get limit */\r
1966if (off >= lim) { /* limit viol? */\r
1967 mac_sta = MACS_L; /* set status */\r
1968 ABORT (MPRO); /* abort */\r
1969 }\r
1970if ((mapr & SR_PRS) == 0) { /* not present? */\r
1971 mac_sta = MACS_NP; /* set status */\r
1972 ABORT (MPRO); /* abort */\r
1973 }\r
1974if ((rel == VE) && (mapr & SR_EXP)) { /* exec, prot? */\r
1975 mac_sta = MACS_EX; /* set status */\r
1976 qevent = qevent | EV_MAC; /* req intr */\r
1977 }\r
1978if ((rel == VW) && (mapr & (SR_WPI | SR_WRP))) { /* write, prot? */\r
1979 if (mapr & SR_WRP) { /* write abort? */\r
1980 mac_sta = MACS_WP; /* set status */\r
1981 ABORT (MPRO); /* abort */\r
1982 }\r
1983 else { /* write intr */\r
1984 mac_sta = MACS_WI; /* set status */\r
1985 qevent = qevent | EV_MAC; /* req intr */\r
1986 }\r
1987 }\r
1988return (off + (mapr & SRF_MASK)) & PAMASK32; /* relocate */\r
1989}\r
1990\r
1991uint32 RelocT (uint32 va, uint32 base, uint32 rel, uint32 *pa)\r
1992{\r
1993uint32 seg, off, mapr, lim;\r
1994\r
1995seg = VA_GETSEG (va); /* get seg num */\r
1996off = VA_GETOFF (va); /* get offset */\r
1997mapr = ReadF ((base + (seg << 2)) & VAMASK, rel); /* get seg reg */\r
1998lim = GET_SRL (mapr); /* get limit */\r
1999if (off >= lim) return CC_C; /* limit viol? */\r
2000if ((mapr & SR_PRS) == 0) return CC_V; /* not present? */\r
2001*pa = off + (mapr & SRF_MASK); /* translate */\r
2002if (mapr & (SR_WRP | SR_WPI)) return CC_G; /* write prot? */\r
2003if (mapr & SR_EXP) return CC_L; /* exec prot? */\r
2004return 0; /* ok */\r
2005}\r
2006\r
2007/* Memory interface routines\r
2008\r
2009 ReadB read byte (processor)\r
2010 ReadH read halfword (processor)\r
2011 ReadF read fullword (processor)\r
2012 WriteB write byte (processor)\r
2013 WriteH write halfword (processor)\r
2014 WriteF write fullword (processor)\r
2015 IOReadB read byte (IO)\r
2016 IOWriteB write byte (IO)\r
2017 IOReadH read halfword (IO)\r
2018 IOWriteH write halfword (IO)\r
2019*/\r
2020\r
2021uint32 ReadB (uint32 loc, uint32 rel)\r
2022{\r
2023uint32 val;\r
2024uint32 sc = (3 - (loc & 3)) << 3;\r
2025\r
2026if ((PSW & PSW_REL) == 0) { /* reloc off? */\r
2027 if ((loc & ~03) == MAC_STA) { /* MAC status? */\r
2028 val = mac_sta; /* read it */\r
2029 qevent = qevent & ~EV_MAC; /* clr MAC intr */\r
2030 }\r
2031 else val = M[loc >> 2]; /* get mem word */\r
2032 }\r
2033else if (rel == 0) val = M[loc >> 2]; /* phys ref? */\r
2034else {\r
2035 uint32 pa = Reloc (loc, rel); /* relocate */\r
2036 val = M[pa >> 2];\r
2037 }\r
2038return (val >> sc) & DMASK8;\r
2039}\r
2040\r
2041uint32 ReadH (uint32 loc, uint32 rel)\r
2042{\r
2043uint32 val;\r
2044\r
2045if ((PSW & PSW_REL) == 0) { /* reloc off? */\r
2046 if ((loc & ~03) == MAC_STA) { /* MAC status? */\r
2047 val = mac_sta; /* read it */\r
2048 qevent = qevent & ~EV_MAC; /* clr MAC intr */\r
2049 }\r
2050 else val = M[loc >> 2]; /* get mem word */\r
2051 }\r
2052else if (rel == 0) val = M[loc >> 2]; /* phys ref? */\r
2053else {\r
2054 uint32 pa = Reloc (loc, rel); /* relocate */\r
2055 val = M[pa >> 2];\r
2056 }\r
2057return (val >> ((loc & 2)? 0: 16)) & DMASK16;\r
2058}\r
2059\r
2060uint32 ReadF (uint32 loc, uint32 rel)\r
2061{\r
2062uint32 val;\r
2063\r
2064if ((PSW & PSW_REL) == 0) { /* reloc off? */\r
2065 if ((loc & ~03) == MAC_STA) { /* MAC status? */\r
2066 val = mac_sta; /* read it */\r
2067 qevent = qevent & ~EV_MAC; /* clr MAC intr */\r
2068 }\r
2069 else val = M[loc >> 2]; /* get mem word */\r
2070 }\r
2071else if (rel == 0) val = M[loc >> 2]; /* phys ref? */\r
2072else {\r
2073 uint32 pa = Reloc (loc, rel); /* relocate */\r
2074 val = M[pa >> 2];\r
2075 }\r
2076return val;\r
2077}\r
2078\r
2079void WriteB (uint32 loc, uint32 val, uint32 rel)\r
2080{\r
2081uint32 pa = loc;\r
2082uint32 sc = (3 - (loc & 3)) << 3;\r
2083\r
2084val = val & DMASK8;\r
2085if ((PSW & PSW_REL) == 0) { /* reloc off? */\r
2086 uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */\r
2087 if (idx <= MAC_LNT) {\r
2088 if (idx < MAC_LNT) mac_reg[idx] =\r
2089 ((mac_reg[idx] & ~(DMASK8 << sc)) | (val << sc)) & SR_MASK;\r
2090 else {\r
2091 mac_sta = 0;\r
2092 qevent = qevent & ~EV_MAC;\r
2093 }\r
2094 }\r
2095 }\r
2096else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */\r
2097if (MEM_ADDR_OK (pa)) M[pa >> 2] = \r
2098 (M[pa >> 2] & ~(DMASK8 << sc)) | (val << sc);\r
2099return;\r
2100}\r
2101\r
2102void WriteH (uint32 loc, uint32 val, uint32 rel)\r
2103{\r
2104uint32 pa = loc;\r
2105\r
2106val = val & DMASK16;\r
2107if ((PSW & PSW_REL) == 0) { /* reloc off? */\r
2108 uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */\r
2109 if (idx <= MAC_LNT) {\r
2110 if (idx < MAC_LNT) mac_reg[idx] = ((loc & 2)?\r
2111 ((mac_reg[idx] & ~DMASK16) | val):\r
2112 ((mac_reg[idx] & DMASK16) | (val << 16))) & SR_MASK;\r
2113 else {\r
2114 mac_sta = 0;\r
2115 qevent = qevent & ~EV_MAC;\r
2116 }\r
2117 }\r
2118 }\r
2119else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */\r
2120if (MEM_ADDR_OK (pa)) M[pa >> 2] = (loc & 2)?\r
2121 ((M[pa >> 2] & ~DMASK16) | val):\r
2122 ((M[pa >> 2] & DMASK16) | (val << 16));\r
2123return;\r
2124}\r
2125\r
2126void WriteF (uint32 loc, uint32 val, uint32 rel)\r
2127{\r
2128uint32 pa = loc;\r
2129\r
2130val = val & DMASK32;\r
2131if (loc & 2) {\r
2132 WriteH (loc & VAMASK, (val >> 16) & DMASK16, rel);\r
2133 WriteH ((loc + 2) & VAMASK, val & DMASK16, rel);\r
2134 return;\r
2135 }\r
2136if ((PSW & PSW_REL) == 0) { /* reloc off? */\r
2137 uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */\r
2138 if (idx <= MAC_LNT) {\r
2139 if (idx < MAC_LNT) mac_reg[idx] = val & SR_MASK;\r
2140 else {\r
2141 mac_sta = 0;\r
2142 qevent = qevent & ~EV_MAC;\r
2143 }\r
2144 }\r
2145 }\r
2146else if (rel != 0) pa = Reloc (loc, rel); /* !phys? relocate */\r
2147if (MEM_ADDR_OK (pa)) M[pa >> 2] = val & DMASK32;\r
2148return;\r
2149}\r
2150\r
2151uint32 IOReadB (uint32 loc)\r
2152{\r
2153uint32 sc = (3 - (loc & 3)) << 3;\r
2154\r
2155return (M[loc >> 2] >> sc) & DMASK8;\r
2156}\r
2157\r
2158uint32 IOReadH (uint32 loc)\r
2159{\r
2160return (M[loc >> 2] >> ((loc & 2)? 0: 16)) & DMASK16;\r
2161}\r
2162\r
2163void IOWriteB (uint32 loc, uint32 val)\r
2164{\r
2165uint32 sc = (3 - (loc & 3)) << 3;\r
2166\r
2167val = val & DMASK8;\r
2168M[loc >> 2] = (M[loc >> 2] & ~(DMASK8 << sc)) | (val << sc);\r
2169return;\r
2170}\r
2171\r
2172void IOWriteH (uint32 loc, uint32 val)\r
2173{\r
2174uint32 sc = (loc & 2)? 0: 16;\r
2175\r
2176val = val & DMASK16;\r
2177M[loc >> 2] = (M[loc >> 2] & ~(DMASK16 << sc)) | (val << sc);\r
2178return;\r
2179}\r
2180\r
2181/* Reset routine */\r
2182\r
2183t_stat cpu_reset (DEVICE *dptr)\r
2184{\r
2185qevent = 0; /* no events */\r
2186mac_sta = 0; /* clear MAC */\r
2187newPSW (0); /* PSW = 0 */\r
2188set_r_display (R);\r
2189DR = 0; /* clear display */\r
2190drmod = 0;\r
2191blk_io.dfl = blk_io.cur = blk_io.end = 0; /* no block I/O */\r
2192sim_brk_types = sim_brk_dflt = SWMASK ('E'); /* init bkpts */\r
2193if (M == NULL) M = (uint32 *) calloc (MAXMEMSIZE32 >> 2, sizeof (uint32));\r
2194if (M == NULL) return SCPE_MEM;\r
2195pcq_r = find_reg ("PCQ", NULL, dptr); /* init PCQ */\r
2196if (pcq_r) pcq_r->qptr = 0;\r
2197else return SCPE_IERR;\r
2198return SCPE_OK;\r
2199}\r
2200\r
2201/* Memory examine */\r
2202\r
2203t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)\r
2204{\r
2205if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) {\r
2206 int32 cc = RelocT (addr, MAC_BASE, P, &addr);\r
2207 if (cc & (CC_C | CC_V)) return SCPE_NXM;\r
2208 }\r
2209if (addr >= MEMSIZE) return SCPE_NXM;\r
2210if (vptr != NULL) *vptr = IOReadH (addr);\r
2211return SCPE_OK;\r
2212}\r
2213\r
2214/* Memory deposit */\r
2215\r
2216t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)\r
2217{\r
2218if ((sw & SWMASK ('V')) && (PSW & PSW_REL)) {\r
2219 int32 cc = RelocT (addr, MAC_BASE, P, &addr);\r
2220 if (cc & (CC_C | CC_V)) return SCPE_NXM;\r
2221 }\r
2222if (addr >= MEMSIZE) return SCPE_NXM;\r
2223IOWriteH (addr, val);\r
2224return SCPE_OK;\r
2225}\r
2226\r
2227/* Change memory size */\r
2228\r
2229t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)\r
2230{\r
2231uint32 mc = 0;\r
2232uint32 i;\r
2233\r
2234if ((val <= 0) || (val > MAXMEMSIZE32) || ((val & 0xFFFF) != 0))\r
2235 return SCPE_ARG;\r
2236for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2];\r
2237if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))\r
2238 return SCPE_OK;\r
2239MEMSIZE = val;\r
2240for (i = MEMSIZE; i < MAXMEMSIZE32; i = i + 4) M[i >> 2] = 0;\r
2241return SCPE_OK;\r
2242}\r
2243\r
2244/* Set current R pointers for SCP */\r
2245\r
2246void set_r_display (uint32 *rbase)\r
2247{\r
2248extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr);\r
2249REG *rptr;\r
2250int32 i;\r
2251\r
2252rptr = find_reg ("R0", NULL, &cpu_dev);\r
2253if (rptr == NULL) return;\r
2254for (i = 0; i < 16; i++, rptr++) rptr->loc = (void *) (rbase + i);\r
2255return;\r
2256}\r
2257\r
2258/* Set console interrupt */\r
2259\r
2260t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc)\r
2261{\r
2262if (PSW & PSW_EXI) SET_INT (v_DS);\r
2263return SCPE_OK;\r
2264}\r
2265\r
2266/* Set history */\r
2267\r
2268t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)\r
2269{\r
2270uint32 i, lnt;\r
2271t_stat r;\r
2272\r
2273if (cptr == NULL) {\r
2274 for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;\r
2275 hst_p = 0;\r
2276 return SCPE_OK;\r
2277 }\r
2278lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r);\r
2279if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;\r
2280hst_p = 0;\r
2281if (hst_lnt) {\r
2282 free (hst);\r
2283 hst_lnt = 0;\r
2284 hst = NULL;\r
2285 }\r
2286if (lnt) {\r
2287 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));\r
2288 if (hst == NULL) return SCPE_MEM;\r
2289 hst_lnt = lnt;\r
2290 }\r
2291return SCPE_OK;\r
2292}\r
2293\r
2294/* Show history */\r
2295\r
2296t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)\r
2297{\r
2298int32 op, k, di, lnt;\r
2299char *cptr = (char *) desc;\r
2300t_value sim_eval[3];\r
2301t_stat r;\r
2302InstHistory *h;\r
2303extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,\r
2304 UNIT *uptr, int32 sw);\r
2305\r
2306if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */\r
2307if (cptr) {\r
2308 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);\r
2309 if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;\r
2310 }\r
2311else lnt = hst_lnt;\r
2312di = hst_p - lnt; /* work forward */\r
2313if (di < 0) di = di + hst_lnt;\r
2314fprintf (st, "PC r1 operand ea IR\n\n");\r
2315for (k = 0; k < lnt; k++) { /* print specified */\r
2316 h = &hst[(di++) % hst_lnt]; /* entry pointer */\r
2317 if (h->pc & HIST_PC) { /* instruction? */\r
2318 fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd);\r
2319 op = (h->ir1 >> 8) & 0xFF;\r
2320 if (OP_TYPE (op) >= OP_RX) fprintf (st, "%06X ", h->ea);\r
2321 else fprintf (st, " ");\r
2322 sim_eval[0] = h->ir1;\r
2323 sim_eval[1] = h->ir2;\r
2324 sim_eval[2] = h->ir3;\r
2325 if ((fprint_sym (st, h->pc & VAMASK32, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)\r
2326 fprintf (st, "(undefined) %04X", h->ir1);\r
2327 fputc ('\n', st); /* end line */\r
2328 } /* end if instruction */\r
2329 } /* end for */\r
2330return SCPE_OK;\r
2331}\r