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