1 /* vax_cpu.c: VAX CPU
2 
3    Copyright (c) 1998-2012, 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          VAX central processor
27 
28    20-Sep-11    MP      Fixed idle conditions for various versions of Ultrix,
29                         Quasijarus-4.3BSD, NetBSD and OpenBSD.
30                         Note: Since NetBSD and OpenBSD are still actively
31                         developed operating systems, new versions of
32                         these OSes are moving targets with regard to
33                         providing idle detection.  At this time, recent versions
34                         of OpenBSD have veered from the traditional OS idle
35                         approach taken in the other BSD derived OSes.
36                         Determining a reasonable idle detection pattern does
37                         not seem possible for these versions.
38    13-Sep-11    RMS     Fixed XFC, BPT to clear PSL<tp> before exception
39                         (Camiel Vanderhoeven)
40    23-Mar-11    RMS     Revised for new idle design (Mark Pizzolato)
41    24-Apr-10    RMS     Added OLDVMS idle timer option
42                         Fixed bug in SET CPU IDLE
43    21-May-08    RMS     Removed inline support
44    28-May-08    RMS     Inlined instruction prefetch, physical memory routines
45    13-Aug-07    RMS     Fixed bug in read access g-format indexed specifiers
46    28-Apr-07    RMS     Removed clock initialization
47    29-Oct-06    RMS     Added idle support
48    22-May-06    RMS     Fixed format error in CPU history (Peter Schorn)
49    10-May-06    RMS     Added -kesu switches for virtual addressing modes
50                         Fixed bugs in examine virtual
51                         Rewrote history function for greater usability
52                         Fixed bug in reported VA on faulting cross-page write
53    02-May-06    RMS     Fixed fault cleanup to clear PSL<tp>
54                         Fixed ADAWI r-mode to preserve dst<31:16>
55                         Fixed ACBD/G to test correct operand
56                         Fixed access checking on modify-class specifiers
57                         Fixed branch displacements in history buffer
58                         (Tim Stark)
59    17-Nov-05    RMS     Fixed CVTfi with integer overflow to trap if PSW<iv> set
60    13-Nov-05    RMS     Fixed breakpoint test with 64b addresses
61    25-Oct-05    RMS     Removed cpu_extmem
62    22-Sep-05    RMS     Fixed declarations (Sterling Garwood)
63    16-Aug-05    RMS     Fixed C++ declaration and cast problems
64    13-Jan-05    RMS     Fixed initial state of cpu_extmem
65    06-Nov-04    RMS     Added =n to SHOW HISTORY
66    30-Sep-04    RMS     Added octaword specifier decodes and instructions
67                         Moved model-specific routines to system module
68    02-Sep-04    RMS     Fixed bug in EMODD/G, second word of quad dst not probed
69    28-Jun-04    RMS     Fixed bug in DIVBx, DIVWx (Peter Trimmel)
70    18-Apr-04    RMS     Added octaword macros
71    25-Jan-04    RMS     Removed local debug logging support
72                 RMS,MP  Added extended physical memory support
73    31-Dec-03    RMS     Fixed bug in set_cpu_hist
74    21-Dec-03    RMS     Added autoconfiguration controls
75    29-Oct-03    RMS     Fixed WriteB declaration (Mark Pizzolato)
76    23-Sep-03    RMS     Revised instruction history for dynamic sizing
77    17-May-03    RMS     Fixed operand order in EMODx
78    23-Apr-03    RMS     Revised for 32b/64b t_addr
79    05-Jan-02    RMS     Added memory size restore support
80    25-Dec-02    RMS     Added instruction history (Mark Pizzolato)
81    29-Sep-02    RMS     Revised to build dib_tab dynamically
82    14-Jul-02    RMS     Added halt to console, infinite loop detection (Mark Pizzolato)
83    02-May-02    RMS     Fixed bug in indexed autoincrement register logging
84    30-Apr-02    RMS     Added TODR powerup routine
85    18-Apr-02    RMS     Cleanup ambiguous signed left shifts
86    15-Apr-02    RMS     Fixed bug in CASEL condition codes
87 
88    The register state for the VAX is:
89 
90         R[0:15]         general registers
91         PSL<31:0>       processor status longword
92          TP<30>         trace pending
93          FPD<27>        first part done
94          IS<26>         interrupt stack
95          CM<25:24>      current mode
96          PM<23:22>      previous mode
97          IPL<20:16>     interrupt priority level
98          PSW<15:0>      non-privileged processor status word
99           DV<7>         decimal overflow trap enable
100           FU<6>         floating underflow fault enable
101           IV<5>         integer overflow trap enable
102           T<4>          trace trap enable
103           CC<3:0>       condition codes
104         SCBB            system control block base
105         PCBB            process control block base
106         SBR             system page table base
107         SLR             system page table length
108         P0BR            process region 0 page table base
109         P0LR            process region 0 page table length
110         P1BR            process region 1 page table base
111         P1LR            process region 1 page table length
112         SIRR/SISR       software interrupt request/summary register
113         ASTLVL          AST level register
114 
115    The VAX has a variable length instruction format with up to six operands:
116 
117         opcode byte
118         operand 1 specifier
119          :
120         operand n specifier
121 
122    Each operand specifier is a byte consisting of an addressing mode, a
123    register, and possibly 1-8 bytes of extension:
124 
125         number  name        extension   mnemonic        operation
126 
127         0-3     short literal   -       #n      op <- specifier
128         4       index           -       [Rn]    index by Rn
129         5       register        -       Rn      op <- Rn
130         6       register def    -       (Rn)    op <- M[Rn]
131         7       autodecrement   -       -(Rn)   Rn <- Rn - length
132                                                 op <- M[Rn]
133         8       autoincrement   -       (Rn)+   op <- M[Rn]
134                                                 Rn <- Rn + length
135         9       auto deferred   -       @(Rn)+  op <- M[M[Rn]]
136                                                 Rn <- Rn + 4
137         A       byte displ      byte d  d(Rn)   op <- M[Rn + sxt.d]
138         B       byte displ def  byte d  @d(Rn)  op <- M[M[Rn + sxt.d]]
139         C       word displ      word d  d(Rn)   op <- M[Rn + sxt.d]
140         D       word displ def  word d  @d(Rn)  op <- M[M[Rn + sxt.d]]
141         E       long displ      long d  d(Rn)   op <- M[Rn + d]
142         F       long displ def  long d  @d(Rn)  op <- M[M[Rn + d]]
143 
144    When the general register is the PC, certain modes are forbidden, and
145    others have special interpretations:
146 
147         4F      index           fault
148         5F      register        fault
149         6F      register def    fault
150         7F      autodecrement   fault
151         8F      immediate       1-8B    #imm    op <- imm
152         9       absolute        4B      @#imm   op <- M[imm]
153         A       byte relative   byte d  d(Rn)   op <- M[PC + sxt.d]
154         B       byte rel def    byte d  @d(Rn)  op <- M[M[PC + sxt.d]]
155         C       word relative   word d  d(Rn)   op <- M[PC + sxt.d]
156         D       word rel def    word d  @d(Rn)  op <- M[M[PC + sxt.d]]
157         E       long relative   long d  d(Rn)   op <- M[PC + d]
158         F       long rel def    long d  @d(Rn)  op <- M[M[PC + d]]
159 
160    This routine is the instruction decode routine for the VAX.  It
161    is called from the simulator control program to execute instructions
162    in simulated memory, starting at the simulated PC.  It runs until an
163    enabled exception is encountered.
164 
165    General notes:
166 
167    1. Traps and interrupts.  Variable trpirq microencodes the outstanding
168         trap request (if any) and the level of the highest outstanding
169         interrupt (if any).
170 
171    2. Interrupt requests are maintained in the int_req array, one word per
172       interrupt level, one bit per device.
173 
174    3. Adding I/O devices.  These modules must be modified:
175 
176         vax_defs.h      add device address and interrupt definitions
177         vax_sys.c       add sim_devices table entry
178 */
179 
180 /* Definitions */
181 
182 #include "vax_defs.h"
183 
184 #define OP_MEM          -1
185 #define UNIT_V_CONH     (UNIT_V_UF + 0)                 /* halt to console */
186 #define UNIT_V_MSIZE    (UNIT_V_UF + 1)                 /* dummy */
187 #define UNIT_CONH       (1u << UNIT_V_CONH)
188 #define UNIT_MSIZE      (1u << UNIT_V_MSIZE)
189 #define GET_CUR         acc = ACC_MASK (PSL_GETCUR (PSL))
190 #define VAX_IDLE_VMS        0x01
191 #define VAX_IDLE_ULT        0x02
192 #define VAX_IDLE_ULTOLD     0x04
193 #define VAX_IDLE_QUAD       0x08
194 
195 #define OPND_SIZE       16
196 #define INST_SIZE       52
197 #define op0             opnd[0]
198 #define op1             opnd[1]
199 #define op2             opnd[2]
200 #define op3             opnd[3]
201 #define op4             opnd[4]
202 #define op5             opnd[5]
203 #define op6             opnd[6]
204 #define op7             opnd[7]
205 #define op8             opnd[8]
206 #define CHECK_FOR_PC    if (rn == nPC) \
207                             RSVD_ADDR_FAULT
208 #define CHECK_FOR_SP    if (rn >= nSP) \
209                             RSVD_ADDR_FAULT
210 #define CHECK_FOR_AP    if (rn >= nAP) \
211                             RSVD_ADDR_FAULT
212 #define WRITE_B(r)      if (spec > (GRN | nPC)) \
213                             Write (va, r, L_BYTE, WA); \
214                         else R[rn] = (R[rn] & ~BMASK) | ((r) & BMASK)
215 #define WRITE_W(r)      if (spec > (GRN | nPC)) \
216                             Write (va, r, L_WORD, WA); \
217                         else R[rn] = (R[rn] & ~WMASK) | ((r) & WMASK)
218 #define WRITE_L(r)      if (spec > (GRN | nPC)) \
219                             Write (va, r, L_LONG, WA); \
220                         else R[rn] = (r)
221 #define WRITE_Q(rl,rh)  if (spec > (GRN | nPC)) { \
222                         if ((Test (va + 7, WA, &mstat) >= 0) || \
223                             (Test (va, WA, &mstat) < 0)) \
224                             Write (va, rl, L_LONG, WA); \
225                             Write (va + 4, rh, L_LONG, WA); \
226                             } \
227                         else { \
228                             if (rn >= nSP) \
229                                 RSVD_ADDR_FAULT; \
230                             R[rn] = rl; \
231                             R[rn + 1] = rh; \
232                             }
233 
234 #define HIST_MIN        64
235 #define HIST_MAX        65536
236 
237 typedef struct {
238     int32               iPC;
239     int32               PSL;
240     int32               opc;
241     uint8               inst[INST_SIZE];
242     int32               opnd[OPND_SIZE];
243     } InstHistory;
244 
245 uint32 *M = NULL;                                       /* memory */
246 int32 R[16];                                            /* registers */
247 int32 STK[5];                                           /* stack pointers */
248 int32 PSL;                                              /* PSL */
249 int32 SCBB = 0;                                         /* SCB base */
250 int32 PCBB = 0;                                         /* PCB base */
251 int32 P0BR = 0;                                         /* P0 mem mgt */
252 int32 P0LR = 0;
253 int32 P1BR = 0;                                         /* P1 mem mgt */
254 int32 P1LR = 0;
255 int32 SBR = 0;                                          /* S0 mem mgt */
256 int32 SLR = 0;
257 int32 SISR;                                             /* swre int req */
258 int32 ASTLVL;                                           /* AST level */
259 int32 mapen;                                            /* map enable */
260 int32 pme;                                              /* perf mon enable */
261 int32 trpirq;                                           /* trap/intr req */
262 int32 in_ie = 0;                                        /* in exc, int */
263 int32 recq[6];                                          /* recovery queue */
264 int32 recqptr;                                          /* recq pointer */
265 int32 hlt_pin = 0;                                      /* HLT pin intr */
266 int32 mem_err = 0;
267 int32 crd_err = 0;
268 int32 p1 = 0, p2 = 0;                                   /* fault parameters */
269 int32 fault_PC;                                         /* fault PC */
270 int32 pcq_p = 0;                                        /* PC queue ptr */
271 int32 hst_p = 0;                                        /* history pointer */
272 int32 hst_lnt = 0;                                      /* history length */
273 int32 badabo = 0;
274 int32 cpu_astop = 0;
275 int32 mchk_va, mchk_ref;                                /* mem ref param */
276 int32 ibufl, ibufh;                                     /* prefetch buf */
277 int32 ibcnt, ppc;                                       /* prefetch ctl */
278 uint32 cpu_idle_mask = VAX_IDLE_VMS;                    /* idle mask */
279 uint32 cpu_idle_type = 1;                               /* default VMS */
280 jmp_buf save_env;
281 REG *pcq_r = NULL;                                      /* PC queue reg ptr */
282 int32 pcq[PCQ_SIZE] = { 0 };                            /* PC queue */
283 InstHistory *hst = NULL;                                /* instruction history */
284 
285 const uint32 byte_mask[33] = { 0x00000000,
286  0x00000001, 0x00000003, 0x00000007, 0x0000000F,
287  0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
288  0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
289  0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
290  0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
291  0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
292  0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
293  0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
294  };
295 const uint32 byte_sign[33] = { 0x00000000,
296  0x00000001, 0x00000002, 0x00000004, 0x00000008,
297  0x00000010, 0x00000020, 0x00000040, 0x00000080,
298  0x00000100, 0x00000200, 0x00000400, 0x00000800,
299  0x00001000, 0x00002000, 0x00004000, 0x00008000,
300  0x00010000, 0x00020000, 0x00040000, 0x00080000,
301  0x00100000, 0x00200000, 0x00400000, 0x00800000,
302  0x01000000, 0x02000000, 0x04000000, 0x08000000,
303  0x10000000, 0x20000000, 0x40000000, 0x80000000
304  };
305 const uint32 align[4] = {
306  0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF
307  };
308 
309 /* External and forward references */
310 
311 extern int32 sim_interval;
312 extern int32 sim_int_char;
313 extern int32 sim_switches;
314 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
315 extern t_bool sim_idle_enab;
316 
317 extern t_stat build_dib_tab (void);
318 extern UNIT rom_unit, nvr_unit;
319 extern int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg);
320 extern int32 op_emul (int32 mpy, int32 mpc, int32 *rh);
321 extern int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg);
322 extern int32 op_bb_n (int32 *opnd, int32 acc);
323 extern int32 op_bb_x (int32 *opnd, int32 newb, int32 acc);
324 extern int32 op_extv (int32 *opnd, int32 vfldrp1, int32 acc);
325 extern int32 op_ffs (uint32 fld, int32 size);
326 extern void op_insv (int32 *opnd, int32 vfldrp1, int32 acc);
327 extern int32 op_call (int32 *opnd, t_bool gs, int32 acc);
328 extern int32 op_ret (int32 acc);
329 extern int32 op_insque (int32 *opnd, int32 acc);
330 extern int32 op_remque (int32 *opnd, int32 acc);
331 extern int32 op_insqhi (int32 *opnd, int32 acc);
332 extern int32 op_insqti (int32 *opnd, int32 acc);
333 extern int32 op_remqhi (int32 *opnd, int32 acc);
334 extern int32 op_remqti (int32 *opnd, int32 acc);
335 extern void op_pushr (int32 *opnd, int32 acc);
336 extern void op_popr (int32 *opnd, int32 acc);
337 extern int32 op_movc (int32 *opnd, int32 opc, int32 acc);
338 extern int32 op_cmpc (int32 *opnd, int32 opc, int32 acc);
339 extern int32 op_locskp (int32 *opnd, int32 opc, int32 acc);
340 extern int32 op_scnspn (int32 *opnd, int32 opc, int32 acc);
341 extern int32 op_chm (int32 *opnd, int32 cc, int32 opc);
342 extern int32 op_rei (int32 acc);
343 extern void op_ldpctx (int32 acc);
344 extern void op_svpctx (int32 acc);
345 extern int32 op_probe (int32 *opnd, int32 opc);
346 extern int32 op_mtpr (int32 *opnd);
347 extern int32 op_mfpr (int32 *opnd);
348 extern int32 op_movfd (int32 val);
349 extern int32 op_movg (int32 val);
350 extern int32 op_mnegfd (int32 val);
351 extern int32 op_mnegg (int32 val);
352 extern int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2);
353 extern int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2);
354 extern int32 op_cvtifdg (int32 val, int32 *rh, int32 opc);
355 extern int32 op_cvtfdgi (int32 *opnd, int32 *flg, int32 opc);
356 extern int32 op_cvtdf (int32 *opnd);
357 extern int32 op_cvtgf (int32 *opnd);
358 extern int32 op_cvtfg (int32 *opnd, int32 *rh);
359 extern int32 op_cvtgh (int32 *opnd, int32 *hflt);
360 extern int32 op_addf (int32 *opnd, t_bool sub);
361 extern int32 op_addd (int32 *opnd, int32 *rh, t_bool sub);
362 extern int32 op_addg (int32 *opnd, int32 *rh, t_bool sub);
363 extern int32 op_mulf (int32 *opnd);
364 extern int32 op_muld (int32 *opnd, int32 *rh);
365 extern int32 op_mulg (int32 *opnd, int32 *rh);
366 extern int32 op_divf (int32 *opnd);
367 extern int32 op_divd (int32 *opnd, int32 *rh);
368 extern int32 op_divg (int32 *opnd, int32 *rh);
369 extern int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg);
370 extern int32 op_emodd (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg);
371 extern int32 op_emodg (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg);
372 extern void op_polyf (int32 *opnd, int32 acc);
373 extern void op_polyd (int32 *opnd, int32 acc);
374 extern void op_polyg (int32 *opnd, int32 acc);
375 extern int32 op_cmode (int32 cc);
376 extern int32 op_cis (int32 *opnd, int32 cc, int32 opc, int32 acc);
377 extern int32 op_octa (int32 *opnd, int32 cc, int32 opc, int32 acc, int32 spec, int32 va);
378 extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);
379 extern int32 Test (uint32 va, int32 acc, int32 *status);
380 extern int32 BadCmPSL (int32 newpsl);
381 extern int32 eval_int (void);
382 extern int32 get_vector (int32 lvl);
383 extern void set_map_reg (void);
384 extern void rom_wr_B (int32 pa, int32 val);
385 extern int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta);
386 extern const uint16 drom[NUM_INST][MAX_SPEC + 1];
387 extern t_stat cpu_boot (int32 unitno, DEVICE *dptr);
388 extern int32 con_halt (int32 code, int32 cc);
389 
390 t_stat cpu_reset (DEVICE *dptr);
391 t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
392 t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
393 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
394 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
395 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
396 t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc);
397 t_stat cpu_set_idle (UNIT *uptr, int32 val, char *cptr, void *desc);
398 t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc);
399 int32 cpu_get_vsw (int32 sw);
400 SIM_INLINE int32 get_istr (int32 lnt, int32 acc);
401 int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc);
402 t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line);
403 t_stat cpu_idle_svc (UNIT *uptr);
404 void cpu_idle (void);
405 
406 /* CPU data structures
407 
408    cpu_dev      CPU device descriptor
409    cpu_unit     CPU unit
410    cpu_reg      CPU register list
411    cpu_mod      CPU modifier list
412 */
413 
414 UNIT cpu_unit = {
415     UDATA (&cpu_idle_svc, UNIT_FIX|UNIT_BINK, INITMEMSIZE)
416     };
417 
418 REG cpu_reg[] = {
419     { HRDATA (PC, R[nPC], 32) },
420     { HRDATA (R0, R[0], 32) },
421     { HRDATA (R1, R[1], 32) },
422     { HRDATA (R2, R[2], 32) },
423     { HRDATA (R3, R[3], 32) },
424     { HRDATA (R4, R[4], 32) },
425     { HRDATA (R5, R[5], 32) },
426     { HRDATA (R6, R[6], 32) },
427     { HRDATA (R7, R[7], 32) },
428     { HRDATA (R8, R[8], 32) },
429     { HRDATA (R9, R[9], 32) },
430     { HRDATA (R10, R[10], 32) },
431     { HRDATA (R11, R[11], 32) },
432     { HRDATA (R12, R[12], 32) },
433     { HRDATA (R13, R[13], 32) },
434     { HRDATA (R14, R[14], 32) },
435     { HRDATA (AP, R[nAP], 32) },
436     { HRDATA (FP, R[nFP], 32) },
437     { HRDATA (SP, R[nSP], 32) },
438     { HRDATA (PSL, PSL, 32) },
439     { HRDATA (CC, PSL, 4) },
440     { HRDATA (KSP, KSP, 32) },
441     { HRDATA (ESP, ESP, 32) },
442     { HRDATA (SSP, SSP, 32) },
443     { HRDATA (USP, USP, 32) },
444     { HRDATA (IS, IS, 32) },
445     { HRDATA (SCBB, SCBB, 32) },
446     { HRDATA (PCBB, PCBB, 32) },
447     { HRDATA (P0BR, P0BR, 32) },
448     { HRDATA (P0LR, P0LR, 22) },
449     { HRDATA (P1BR, P1BR, 32) },
450     { HRDATA (P1LR, P1LR, 22) },
451     { HRDATA (SBR, SBR, 32) },
452     { HRDATA (SLR, SLR, 22) },
453     { HRDATA (SISR, SISR, 16) },
454     { HRDATA (ASTLVL, ASTLVL, 4) },
455     { FLDATA (MAPEN, mapen, 0) },
456     { FLDATA (PME, pme, 0) },
457     { HRDATA (TRPIRQ, trpirq, 8) },
458     { FLDATA (CRDERR, crd_err, 0) },
459     { FLDATA (MEMERR, mem_err, 0) },
460     { FLDATA (HLTPIN, hlt_pin, 0) },
461     { HRDATA (IDLE_MASK, cpu_idle_mask, 16), REG_HIDDEN },
462     { DRDATA (IDLE_INDX, cpu_idle_type, 4), REG_HRO },
463     { DRDATA (IDLE_ENAB, sim_idle_enab, 4), REG_HRO },
464     { BRDATA (PCQ, pcq, 16, 32, PCQ_SIZE), REG_RO+REG_CIRC },
465     { HRDATA (PCQP, pcq_p, 6), REG_HRO },
466     { HRDATA (BADABO, badabo, 32), REG_HRO },
467     { HRDATA (WRU, sim_int_char, 8) },
468     { NULL }
469     };
470 
471 MTAB cpu_mod[] = {
472     { UNIT_CONH, 0, "HALT to SIMH", "SIMHALT", NULL },
473     { UNIT_CONH, UNIT_CONH, "HALT to console", "CONHALT", NULL },
474     { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &cpu_set_idle, &cpu_show_idle },
475     { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
476     { UNIT_MSIZE, (1u << 23), NULL, "8M", &cpu_set_size },
477     { UNIT_MSIZE, (1u << 24), NULL, "16M", &cpu_set_size },
478     { UNIT_MSIZE, (1u << 25), NULL, "32M", &cpu_set_size },
479     { UNIT_MSIZE, (1u << 25) + (1u << 24), NULL, "48M", &cpu_set_size },
480     { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size },
481     { UNIT_MSIZE, (1u << 27), NULL, "128M", &cpu_set_size },
482 #if !defined (VAX_780)
483     { UNIT_MSIZE, (1u << 28), NULL, "256M", &cpu_set_size },
484     { UNIT_MSIZE, (1u << 29), NULL, "512M", &cpu_set_size },
485 #endif
486     { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
487       &cpu_set_hist, &cpu_show_hist },
488     { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL,
489       NULL, &cpu_show_virt },
490     { 0 }
491     };
492 
493 DEBTAB cpu_deb[] = {
494     { "INTEXC", LOG_CPU_I },
495     { "REI", LOG_CPU_R },
496     { "CONTEXT", LOG_CPU_P },
497     { NULL, 0 }
498     };
499 
500 DEVICE cpu_dev = {
501     "CPU", &cpu_unit, cpu_reg, cpu_mod,
502     1, 16, 32, 1, 16, 8,
503     &cpu_ex, &cpu_dep, &cpu_reset,
504     &cpu_boot, NULL, NULL,
505     NULL, DEV_DYNM | DEV_DEBUG, 0,
506     cpu_deb, &cpu_set_size, NULL
507     };
508 
sim_instr(void)509 t_stat sim_instr (void)
510 {
511 volatile int32 opc, cc;                                 /* used by setjmp */
512 volatile int32 acc;                                     /* set by setjmp */
513 int abortval;
514 t_stat r;
515 
516 if ((r = build_dib_tab ()) != SCPE_OK)                  /* build, chk dib_tab */
517     return r;
518 if ((PSL & PSL_MBZ) ||                                  /* validate PSL<mbz> */
519     ((PSL & PSL_CM) && BadCmPSL (PSL)) ||               /* validate PSL<cm> */
520     ((PSL_GETCUR (PSL) != KERN) &&                      /* esu => is, ipl = 0 */
521         (PSL & (PSL_IS|PSL_IPL))) ||
522     ((PSL & PSL_IS) && ((PSL & PSL_IPL) == 0)))         /* is => ipl > 0 */
523     return SCPE_STOP;
524 cc = PSL & CC_MASK;                                     /* split PSL */
525 PSL = PSL & ~CC_MASK;
526 in_ie = 0;                                              /* not in exc */
527 set_map_reg ();                                         /* set map reg */
528 GET_CUR;                                                /* set access mask */
529 SET_IRQL;                                               /* eval interrupts */
530 FLUSH_ISTR;                                             /* clear prefetch */
531 
532 abortval = setjmp (save_env);                           /* set abort hdlr */
533 if (abortval > 0) {                                     /* sim stop? */
534     PSL = PSL | cc;                                     /* put PSL together */
535     pcq_r->qptr = pcq_p;                                /* update pc q ptr */
536     return abortval;                                    /* return to SCP */
537     }
538 else if (abortval < 0) {                                /* mm or rsrv or int */
539     int32 i, delta;
540     if ((PSL & PSL_FPD) == 0) {                         /* FPD? no recovery */
541         for (i = 0; i < recqptr; i++) {                 /* unwind inst */
542             int32 rrn, rlnt;
543             rrn = RQ_GETRN (recq[i]);                   /* recover reg # */
544             rlnt = DR_LNT (RQ_GETLNT (recq[i]));        /* recovery lnt */
545             if (recq[i] & RQ_DIR)
546                 R[rrn] = R[rrn] - rlnt;
547             else R[rrn] = R[rrn] + rlnt;
548             }
549         }
550     PSL = PSL & ~PSL_TP;                                /* clear <tp> */
551     recqptr = 0;                                        /* clear queue */
552     delta = PC - fault_PC;                              /* save delta PC */
553     SETPC (fault_PC);                                   /* restore PC */
554     switch (-abortval) {                                /* case on abort code */
555 
556     case SCB_RESIN:                                     /* rsrv inst fault */
557     case SCB_RESAD:                                     /* rsrv addr fault */
558     case SCB_RESOP:                                     /* rsrv opnd fault */
559         if (in_ie)                                      /* in exc? panic */
560             ABORT (STOP_INIE);
561         cc = intexc (-abortval, cc, 0, IE_EXC);         /* take exception */
562         GET_CUR;                                        /* PSL<cur> changed */
563         break;
564 
565     case SCB_CMODE:                                     /* comp mode fault */
566     case SCB_ARITH:                                     /* arithmetic fault */
567         if (in_ie)                                      /* in exc? panic */
568             ABORT (STOP_INIE);
569         cc = intexc (-abortval, cc, 0, IE_EXC);         /* take exception */
570         GET_CUR;
571         in_ie = 1;
572         Write (SP - 4, p1, L_LONG, WA);                 /* write arith param */
573         SP = SP - 4;
574         in_ie = 0;
575         break;
576 
577     case SCB_ACV:                                       /* ACV fault */
578     case SCB_TNV:                                       /* TNV fault */
579         if (in_ie) {                                    /* in exception? */
580             if (PSL & PSL_IS)                           /* on is? panic */
581                 ABORT (STOP_INIE);
582             cc = intexc (SCB_KSNV, cc, 0, IE_SVE);      /* ksnv */
583             GET_CUR;
584             }
585         else {
586             cc = intexc (-abortval, cc, 0, IE_EXC);     /* take exception */
587             GET_CUR;
588             in_ie = 1;
589             Write (SP - 8, p1, L_LONG, WA);             /* write mm params */
590             Write (SP - 4, p2, L_LONG, WA);
591             SP = SP - 8;
592             in_ie = 0;
593             }
594         break;
595 
596     case SCB_MCHK:                                      /* machine check */
597         if (in_ie)                                      /* in exc? panic */
598             ABORT (STOP_INIE);
599         cc = machine_check (p1, opc, cc, delta);        /* system specific */
600         in_ie = 0;
601         GET_CUR;                                        /* PSL<cur> changed */
602         break;
603 
604     case 1:                                             /* interrupt */
605         break;                                          /* just proceed */
606     default:                                            /* other */
607         badabo = abortval;                              /* save code */
608         ABORT (STOP_UNKABO);                            /* panic */
609         }                                               /* end case */
610     }                                                   /* end else */
611 
612 /* Main instruction loop */
613 
614 for ( ;; ) {
615 
616     int32 spec, disp, rn, index, numspec;
617     int32 vfldrp1, brdisp, flg, mstat;
618     int32 i, j, r, rh, temp;
619     uint32 va, iad;
620     int32 opnd[OPND_SIZE];                              /* operand queue */
621 
622     if (cpu_astop) {
623         cpu_astop = 0;
624         ABORT (SCPE_STOP);
625         }
626     fault_PC = PC;
627     recqptr = 0;                                        /* clr recovery q */
628     if (sim_interval <= 0) {                            /* chk clock queue */
629         temp = sim_process_event ();
630         if (temp)
631             ABORT (temp);
632         SET_IRQL;                                       /* update interrupts */
633         }
634 
635 /* Test for non-instruction dispatches, in SRM order
636 
637         - trap or interrupt (trpirq != 0)
638         - PSL<tp> set
639 
640    If any of these conditions are met, re-dispatch; otherwise,
641    set PSL<tp> from PSL<t>.
642 */
643 
644     if (trpirq) {                                       /* trap or interrupt? */
645         if ((temp = GET_TRAP (trpirq))) {               /* trap? */
646             cc = intexc (SCB_ARITH, cc, 0, IE_EXC);     /* take, clear trap */
647             GET_CUR;                                    /* set cur mode */
648             in_ie = 1;
649             Write (SP - 4, temp, L_LONG, WA);           /* write parameter */
650             SP = SP - 4;
651             in_ie = 0;
652             }
653         else if ((temp = GET_IRQL (trpirq))) {          /* interrupt? */
654             int32 vec;
655             if (temp == IPL_HLTPIN) {                   /* console halt? */
656                 hlt_pin = 0;                            /* clear intr */
657                 trpirq = 0;                             /* clear everything */
658                 cc = con_halt (CON_HLTPIN, cc);         /* invoke firmware */
659                 continue;                               /* continue */
660                 }
661             else if (temp >= IPL_HMIN)                  /* hardware req? */
662                 vec = get_vector (temp);                /* get vector */
663             else if (temp > IPL_SMAX)
664                 ABORT (STOP_UIPL);
665             else {
666                 vec = SCB_IPLSOFT + (temp << 2);
667                 SISR = SISR & ~(1u << temp);
668                 }
669             if (vec)                                    /* take intr */
670                 cc = intexc (vec, cc, temp, IE_INT);
671             GET_CUR;                                    /* set cur mode */
672             }
673         else trpirq = 0;                                /* clear everything */
674         SET_IRQL;                                       /* eval interrupts */
675         continue;
676         }
677 
678     if (PSL & (PSL_CM|PSL_TP|PSW_T)) {                  /* PSL event? */
679         if (PSL & PSL_TP) {                             /* trace trap? */
680             PSL = PSL & ~PSL_TP;                        /* clear <tp> */
681             cc = intexc (SCB_TP, cc, 0, IE_EXC);        /* take trap */
682             GET_CUR;                                    /* set cur mode */
683             continue;
684             }
685         if (PSL & PSW_T)                                /* if T, set TP */
686             PSL = PSL | PSL_TP;
687         if (PSL & PSL_CM) {                             /* compat mode? */
688             cc = op_cmode (cc);                         /* exec instr */
689             continue;                                   /* skip fetch */
690             }
691         }                                               /* end PSL event */
692 
693     if (sim_brk_summ &&
694         sim_brk_test ((uint32) PC, SWMASK ('E'))) {     /* breakpoint? */
695         ABORT (STOP_IBKPT);                             /* stop simulation */
696         }
697 
698     sim_interval = sim_interval - 1;                    /* count instr */
699     GET_ISTR (opc, L_BYTE);                             /* get opcode */
700     if (opc == 0xFD) {                                  /* 2 byte op? */
701         GET_ISTR (opc, L_BYTE);                         /* get second byte */
702         opc = opc | 0x100;                              /* flag */
703         }
704     numspec = drom[opc][0];                             /* get # specs */
705     if (PSL & PSL_FPD) {
706         if ((numspec & DR_F) == 0)
707             RSVD_INST_FAULT;
708         }
709     else {
710         numspec = numspec & DR_NSPMASK;                 /* get # specifiers */
711 
712 /* Specifier flows.  Operands are parsed and placed into queue opnd.
713 
714         r.bwl   opnd[j]         =       value of operand
715         r.q     opnd[j:j+1]     =       value of operand
716         r.o     opnd[j:j+3]     =       value of operand
717         a.bwlqo opnd[j]         =       address of operand
718         m.bwl   opnd[j]         =       value of operand
719         m.q     opnd[j:j+1]     =       value of operand
720         m.o     opnd[j:j+3]     =       value of operand
721         w.bwlqo opnd[j]         =       register/memory flag
722                 opnd[j+1]       =       memory address
723 
724    For the last memory specifier, the specifier is in spec, the register
725    number is in rn, and the effective address is in va.  Modify specifiers
726    (always last) can test spec > reg+PC, as short literal are illegal for
727    modifiers specifiers, and final index specifiers are always illegal.
728 */
729 
730         for (i = 1, j = 0; i <= numspec; i++) {         /* loop thru specs */
731             disp = drom[opc][i];                        /* get dispatch */
732             if (disp >= BB) {
733                 GET_ISTR (brdisp, DR_LNT (disp & 1));
734                 break;
735                 }
736             GET_ISTR (spec, L_BYTE);                    /* get spec byte */
737             rn = spec & RGMASK;                         /* get reg # */
738             disp = (spec & ~RGMASK) | disp;             /* merge w dispatch */
739             switch (disp) {                             /* dispatch spec */
740 
741 /* Short literal - only read access permitted */
742 
743             case SH0|RB: case SH0|RW: case SH0|RL:
744             case SH1|RB: case SH1|RW: case SH1|RL:
745             case SH2|RB: case SH2|RW: case SH2|RL:
746             case SH3|RB: case SH3|RW: case SH3|RL:
747                 opnd[j++] = spec;
748                 break;
749 
750             case SH0|RQ: case SH1|RQ: case SH2|RQ: case SH3|RQ:
751                 opnd[j++] = spec;
752                 opnd[j++] = 0;
753                 break;
754 
755             case SH0|RO: case SH1|RO: case SH2|RO: case SH3|RO:
756                 opnd[j++] = spec;
757                 opnd[j++] = 0;
758                 opnd[j++] = 0;
759                 opnd[j++] = 0;
760                 break;
761 
762             case SH0|RF: case SH1|RF: case SH2|RF: case SH3|RF:
763                 opnd[j++] = (spec << 4) | 0x4000;
764                 break;
765 
766             case SH0|RD: case SH1|RD: case SH2|RD: case SH3|RD:
767                 opnd[j++] = (spec << 4) | 0x4000;
768                 opnd[j++] = 0;
769                 break;
770 
771             case SH0|RG: case SH1|RG: case SH2|RG: case SH3|RG:
772                 opnd[j++] = (spec << 1) | 0x4000;
773                 opnd[j++] = 0;
774                 break;
775 
776             case SH0|RH: case SH1|RH: case SH2|RH: case SH3|RH:
777                 opnd[j++] = ((spec & 0x7) << 29) | (0x4000 | ((spec >> 3) & 0x7));
778                 opnd[j++] = 0;
779                 opnd[j++] = 0;
780                 opnd[j++] = 0;
781                 break;
782 
783 /* Register */
784 
785             case GRN|RB: case GRN|MB:
786                 CHECK_FOR_PC;
787                 opnd[j++] = R[rn] & BMASK;
788                 break;
789 
790             case GRN|RW: case GRN|MW:
791                 CHECK_FOR_PC;
792                 opnd[j++] = R[rn] & WMASK;
793                 break;
794 
795             case GRN|VB:
796                 vfldrp1 = R[(rn + 1) & RGMASK];
797             case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: case GRN|WO:
798                 opnd[j++] = rn;
799             case GRN|RL: case GRN|RF: case GRN|ML:
800                 CHECK_FOR_PC;
801                 opnd[j++] = R[rn];
802                 break;
803 
804             case GRN|RQ: case GRN|RD: case GRN|RG: case GRN|MQ:
805                 CHECK_FOR_SP;
806                 opnd[j++] = R[rn];
807                 opnd[j++] = R[rn + 1];
808                 break;
809 
810             case GRN|RO: case GRN|RH: case GRN|MO:
811                 CHECK_FOR_AP;
812                 opnd[j++] = R[rn];
813                 opnd[j++] = R[rn + 1];
814                 opnd[j++] = R[rn + 2];
815                 opnd[j++] = R[rn + 3];
816                 break;
817 
818 /*  Register deferred, autodecrement */
819 
820             case RGD|VB:
821             case RGD|WB: case RGD|WW: case RGD|WL: case RGD|WQ: case RGD|WO:
822                 opnd[j++] = OP_MEM;
823             case RGD|AB: case RGD|AW: case RGD|AL: case RGD|AQ: case RGD|AO:
824                 CHECK_FOR_PC;
825                 va = opnd[j++] = R[rn];
826                 break;
827 
828             case ADC|VB:
829             case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: case ADC|WO:
830                 opnd[j++] = OP_MEM;
831             case ADC|AB: case ADC|AW: case ADC|AL: case ADC|AQ: case ADC|AO:
832                 CHECK_FOR_PC;
833                 va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp);
834                 recq[recqptr++] = RQ_REC (disp, rn);
835                 break;
836 
837             case ADC|RB: case ADC|RW: case ADC|RL: case ADC|RF:
838                 R[rn] = R[rn] - (DR_LNT (disp));
839                 recq[recqptr++] = RQ_REC (disp, rn);
840             case RGD|RB: case RGD|RW: case RGD|RL: case RGD|RF:
841                 CHECK_FOR_PC;
842                 opnd[j++] = Read (va = R[rn], DR_LNT (disp), RA);
843                 break;
844 
845             case ADC|RQ: case ADC|RD: case ADC|RG:
846                 R[rn] = R[rn] - 8;
847                 recq[recqptr++] = RQ_REC (disp, rn);
848             case RGD|RQ: case RGD|RD: case RGD|RG:
849                 CHECK_FOR_PC;
850                 opnd[j++] = Read (va = R[rn], L_LONG, RA);
851                 opnd[j++] = Read (R[rn] + 4, L_LONG, RA);
852                 break;
853 
854             case ADC|RO: case ADC|RH:
855                 R[rn] = R[rn] - 16;
856                 recq[recqptr++] = RQ_REC (disp, rn);
857             case RGD|RO: case RGD|RH:
858                 CHECK_FOR_PC;
859                 j = ReadOcta (va = R[rn], opnd, j, RA);
860                 break;
861 
862             case ADC|MB: case ADC|MW: case ADC|ML:
863                 R[rn] = R[rn] - (DR_LNT (disp));
864                 recq[recqptr++] = RQ_REC (disp, rn);
865             case RGD|MB: case RGD|MW: case RGD|ML:
866                 CHECK_FOR_PC;
867                 opnd[j++] = Read (va = R[rn], DR_LNT (disp), WA);
868                 break;
869 
870             case ADC|MQ:
871                 R[rn] = R[rn] - 8;
872                 recq[recqptr++] = RQ_REC (disp, rn);
873             case RGD|MQ:
874                 CHECK_FOR_PC;
875                 opnd[j++] = Read (va = R[rn], L_LONG, WA);
876                 opnd[j++] = Read (R[rn] + 4, L_LONG, WA);
877                 break;
878 
879             case ADC|MO:
880                 R[rn] = R[rn] - 16;
881                 recq[recqptr++] = RQ_REC (disp, rn);
882             case RGD|MO:
883                 CHECK_FOR_PC;
884                 j = ReadOcta (va = R[rn], opnd, j, WA);
885                 break;
886 
887 /* Autoincrement */
888 
889             case AIN|VB:
890             case AIN|WB: case AIN|WW: case AIN|WL: case AIN|WQ: case AIN|WO:
891 /*              CHECK_FOR_PC; */
892                 opnd[j++] = OP_MEM;
893             case AIN|AB: case AIN|AW: case AIN|AL: case AIN|AQ: case AIN|AO:
894                 va = opnd[j++] = R[rn];
895                 if (rn == nPC) {
896                     if (DR_LNT (disp) >= L_QUAD) {
897                         GET_ISTR (temp, L_LONG);
898                         GET_ISTR (temp, L_LONG);
899                         if (DR_LNT (disp) == L_OCTA) {
900                             GET_ISTR (temp, L_LONG);
901                             GET_ISTR (temp, L_LONG);
902                             }
903                         }
904                     else GET_ISTR (temp, DR_LNT (disp));
905                     }
906                 else {
907                     R[rn] = R[rn] + DR_LNT (disp);
908                     recq[recqptr++] = RQ_REC (disp, rn);
909                     }
910                 break;
911 
912             case AIN|RB: case AIN|RW: case AIN|RL: case AIN|RF:
913                 va = R[rn];
914                 if (rn == nPC) {
915                     GET_ISTR (opnd[j++], DR_LNT (disp));
916                     }
917                 else {
918                     opnd[j++] = Read (R[rn], DR_LNT (disp), RA);
919                     R[rn] = R[rn] + DR_LNT (disp);
920                     recq[recqptr++] = RQ_REC (disp, rn);
921                     }
922                 break;
923 
924             case AIN|RQ: case AIN|RD: case AIN|RG:
925                 va = R[rn];
926                 if (rn == nPC) {
927                     GET_ISTR (opnd[j++], L_LONG);
928                     GET_ISTR (opnd[j++], L_LONG);
929                     }
930                 else {
931                     opnd[j++] = Read (va, L_LONG, RA);
932                     opnd[j++] = Read (va + 4, L_LONG, RA);
933                     R[rn] = R[rn] + 8;
934                     recq[recqptr++] = RQ_REC (disp, rn);
935                     }
936                 break;
937 
938             case AIN|RO: case AIN|RH:
939                 va = R[rn];
940                 if (rn == nPC) {
941                     GET_ISTR (opnd[j++], L_LONG);
942                     GET_ISTR (opnd[j++], L_LONG);
943                     GET_ISTR (opnd[j++], L_LONG);
944                     GET_ISTR (opnd[j++], L_LONG);
945                     }
946                 else {
947                     j = ReadOcta (va, opnd, j, RA);
948                     R[rn] = R[rn] + 16;
949                     recq[recqptr++] = RQ_REC (disp, rn);
950                     }
951                 break;
952 
953             case AIN|MB: case AIN|MW: case AIN|ML:
954                 va = R[rn];
955                 if (rn == nPC) {
956                     GET_ISTR (opnd[j++], DR_LNT (disp));
957                     }
958                 else {
959                     opnd[j++] = Read (R[rn], DR_LNT (disp), WA);
960                     R[rn] = R[rn] + DR_LNT (disp);
961                     recq[recqptr++] = RQ_REC (disp, rn);
962                     }
963                 break;
964 
965             case AIN|MQ:
966                 va = R[rn];
967                 if (rn == nPC) {
968                     GET_ISTR (opnd[j++], L_LONG);
969                     GET_ISTR (opnd[j++], L_LONG);
970                     }
971                 else {
972                     opnd[j++] = Read (va, L_LONG, WA);
973                     opnd[j++] = Read (va + 4, L_LONG, WA);
974                     R[rn] = R[rn] + 8;
975                     recq[recqptr++] = RQ_REC (disp, rn);
976                     }
977                 break;
978 
979             case AIN|MO:
980                 va = R[rn];
981                 if (rn == nPC) {
982                     GET_ISTR (opnd[j++], L_LONG);
983                     GET_ISTR (opnd[j++], L_LONG);
984                     GET_ISTR (opnd[j++], L_LONG);
985                     GET_ISTR (opnd[j++], L_LONG);
986                     }
987                 else {
988                     j = ReadOcta (va, opnd, j, WA);
989                     R[rn] = R[rn] + 16;
990                     recq[recqptr++] = RQ_REC (disp, rn);
991                     }
992                 break;
993 
994 /* Autoincrement deferred */
995 
996             case AID|VB:
997             case AID|WB: case AID|WW: case AID|WL: case AID|WQ: case AID|WO:
998                 opnd[j++] = OP_MEM;
999             case AID|AB: case AID|AW: case AID|AL: case AID|AQ: case AID|AO:
1000                 if (rn == nPC) {
1001                     GET_ISTR (va = opnd[j++], L_LONG);
1002                     }
1003                 else {
1004                     va = opnd[j++] = Read (R[rn], L_LONG, RA);
1005                     R[rn] = R[rn] + 4;
1006                     recq[recqptr++] = RQ_REC (AID|RL, rn);
1007                     }
1008                 break;
1009 
1010             case AID|RB: case AID|RW: case AID|RL: case AID|RF:
1011                 if (rn == nPC) {
1012                     GET_ISTR (va, L_LONG);
1013                     }
1014                 else {
1015                     va = Read (R[rn], L_LONG, RA);
1016                     R[rn] = R[rn] + 4;
1017                     recq[recqptr++] = RQ_REC (AID|RL, rn);
1018                     }
1019                 opnd[j++] = Read (va, DR_LNT (disp), RA);
1020                 break;
1021 
1022             case AID|RQ: case AID|RD: case AID|RG:
1023                 if (rn == nPC) {
1024                     GET_ISTR (va, L_LONG);
1025                     }
1026                 else {
1027                     va = Read (R[rn], L_LONG, RA);
1028                     R[rn] = R[rn] + 4;
1029                     recq[recqptr++] = RQ_REC (AID|RL, rn);
1030                     }
1031                 opnd[j++] = Read (va, L_LONG, RA);
1032                 opnd[j++] = Read (va + 4, L_LONG, RA);
1033                 break;
1034 
1035             case AID|RO: case AID|RH:
1036                 if (rn == nPC) {
1037                     GET_ISTR (va, L_LONG);
1038                     }
1039                 else {
1040                     va = Read (R[rn], L_LONG, RA);
1041                     R[rn] = R[rn] + 4;
1042                     recq[recqptr++] = RQ_REC (AID|RL, rn);
1043                     }
1044                 j = ReadOcta (va, opnd, j, RA);
1045                 break;
1046 
1047             case AID|MB: case AID|MW: case AID|ML:
1048                 if (rn == nPC) {
1049                     GET_ISTR (va, L_LONG);
1050                     }
1051                 else {
1052                     va = Read (R[rn], L_LONG, RA);
1053                     R[rn] = R[rn] + 4;
1054                     recq[recqptr++] = RQ_REC (AID|RL, rn);
1055                     }
1056                 opnd[j++] = Read (va, DR_LNT (disp), WA);
1057                 break;
1058 
1059             case AID|MQ:
1060                 if (rn == nPC) {
1061                     GET_ISTR (va, L_LONG);
1062                     }
1063                 else {
1064                     va = Read (R[rn], L_LONG, RA);
1065                     R[rn] = R[rn] + 4;
1066                     recq[recqptr++] = RQ_REC (AID|RL, rn);
1067                     }
1068                 opnd[j++] = Read (va, L_LONG, WA);
1069                 opnd[j++] = Read (va + 4, L_LONG, WA);
1070                 break;
1071 
1072             case AID|MO:
1073                 if (rn == nPC) {
1074                     GET_ISTR (va, L_LONG);
1075                     }
1076                 else {
1077                     va = Read (R[rn], L_LONG, RA);
1078                     R[rn] = R[rn] + 4;
1079                     recq[recqptr++] = RQ_REC (AID|RL, rn);
1080                     }
1081                 j = ReadOcta (va, opnd, j, WA);
1082                 break;
1083 
1084 /* Byte displacement */
1085 
1086             case BDP|VB:
1087             case BDP|WB: case BDP|WW: case BDP|WL: case BDP|WQ: case BDP|WO:
1088                 opnd[j++] = OP_MEM;
1089             case BDP|AB: case BDP|AW: case BDP|AL: case BDP|AQ: case BDP|AO:
1090                 GET_ISTR (temp, L_BYTE);
1091                 va = opnd[j++] = R[rn] + SXTB (temp);
1092                 break;
1093 
1094             case BDP|RB: case BDP|RW: case BDP|RL: case BDP|RF:
1095                 GET_ISTR (temp, L_BYTE);
1096                 va = R[rn] + SXTB (temp);
1097                 opnd[j++] = Read (va, DR_LNT (disp), RA);
1098                 break;
1099 
1100             case BDP|RQ: case BDP|RD: case BDP|RG:
1101                 GET_ISTR (temp, L_BYTE);
1102                 va = R[rn] + SXTB (temp);
1103                 opnd[j++] = Read (va, L_LONG, RA);
1104                 opnd[j++] = Read (va + 4, L_LONG, RA);
1105                 break;
1106 
1107             case BDP|RO: case BDP|RH:
1108                 GET_ISTR (temp, L_BYTE);
1109                 va = R[rn] + SXTB (temp);
1110                 j = ReadOcta (va, opnd, j, RA);
1111                 break;
1112 
1113             case BDP|MB: case BDP|MW: case BDP|ML:
1114                 GET_ISTR (temp, L_BYTE);
1115                 va = R[rn] + SXTB (temp);
1116                 opnd[j++] = Read (va, DR_LNT (disp), WA);
1117                 break;
1118 
1119             case BDP|MQ:
1120                 GET_ISTR (temp, L_BYTE);
1121                 va = R[rn] + SXTB (temp);
1122                 opnd[j++] = Read (va, L_LONG, WA);
1123                 opnd[j++] = Read (va + 4, L_LONG, WA);
1124                 break;
1125 
1126             case BDP|MO:
1127                 GET_ISTR (temp, L_BYTE);
1128                 va = R[rn] + SXTB (temp);
1129                 j = ReadOcta (va, opnd, j, WA);
1130                 break;
1131 
1132 /* Byte displacement deferred */
1133 
1134             case BDD|VB:
1135             case BDD|WB: case BDD|WW: case BDD|WL: case BDD|WQ: case BDD|WO:
1136                 opnd[j++] = OP_MEM;
1137             case BDD|AB: case BDD|AW: case BDD|AL: case BDD|AQ: case BDD|AO:
1138                 GET_ISTR (temp, L_BYTE);
1139                 iad = R[rn] + SXTB (temp);
1140                 va = opnd[j++] = Read (iad, L_LONG, RA);
1141                 break;
1142 
1143             case BDD|RB: case BDD|RW: case BDD|RL: case BDD|RF:
1144                 GET_ISTR (temp, L_BYTE);
1145                 iad = R[rn] + SXTB (temp);
1146                 va = Read (iad, L_LONG, RA);
1147                 opnd[j++] = Read (va, DR_LNT (disp), RA);
1148                 break;
1149 
1150             case BDD|RQ: case BDD|RD: case BDD|RG:
1151                 GET_ISTR (temp, L_BYTE);
1152                 iad = R[rn] + SXTB (temp);
1153                 va = Read (iad, L_LONG, RA);
1154                 opnd[j++] = Read (va, L_LONG, RA);
1155                 opnd[j++] = Read (va + 4, L_LONG, RA);
1156                 break;
1157 
1158             case BDD|RO: case BDD|RH:
1159                 GET_ISTR (temp, L_BYTE);
1160                 iad = R[rn] + SXTB (temp);
1161                 va = Read (iad, L_LONG, RA);
1162                 j = ReadOcta (va, opnd, j, RA);
1163                 break;
1164 
1165             case BDD|MB: case BDD|MW: case BDD|ML:
1166                 GET_ISTR (temp, L_BYTE);
1167                 iad = R[rn] + SXTB (temp);
1168                 va = Read (iad, L_LONG, RA);
1169                 opnd[j++] = Read (va, DR_LNT (disp), WA);
1170                 break;
1171 
1172             case BDD|MQ:
1173                 GET_ISTR (temp, L_BYTE);
1174                 iad = R[rn] + SXTB (temp);
1175                 va = Read (iad, L_LONG, RA);
1176                 opnd[j++] = Read (va, L_LONG, WA);
1177                 opnd[j++] = Read (va + 4, L_LONG, WA);
1178                 break;
1179 
1180             case BDD|MO:
1181                 GET_ISTR (temp, L_BYTE);
1182                 iad = R[rn] + SXTB (temp);
1183                 va = Read (iad, L_LONG, RA);
1184                 j = ReadOcta (va, opnd, j, WA);
1185                 break;
1186 
1187 /* Word displacement */
1188 
1189             case WDP|VB:
1190             case WDP|WB: case WDP|WW: case WDP|WL: case WDP|WQ: case WDP|WO:
1191                 opnd[j++] = OP_MEM;
1192             case WDP|AB: case WDP|AW: case WDP|AL: case WDP|AQ: case WDP|AO:
1193                 GET_ISTR (temp, L_WORD);
1194                 va = opnd[j++] = R[rn] + SXTW (temp);
1195                 break;
1196 
1197             case WDP|RB: case WDP|RW: case WDP|RL: case WDP|RF:
1198                 GET_ISTR (temp, L_WORD);
1199                 va = R[rn] + SXTW (temp);
1200                 opnd[j++] = Read (va, DR_LNT (disp), RA);
1201                 break;
1202 
1203             case WDP|RQ: case WDP|RD: case WDP|RG:
1204                 GET_ISTR (temp, L_WORD);
1205                 va = R[rn] + SXTW (temp);
1206                 opnd[j++] = Read (va, L_LONG, RA);
1207                 opnd[j++] = Read (va + 4, L_LONG, RA);
1208                 break;
1209 
1210             case WDP|RO: case WDP|RH:
1211                 GET_ISTR (temp, L_WORD);
1212                 va = R[rn] + SXTW (temp);
1213                 j = ReadOcta (va, opnd, j, RA);
1214                 break;
1215 
1216             case WDP|MB: case WDP|MW: case WDP|ML:
1217                 GET_ISTR (temp, L_WORD);
1218                 va = R[rn] + SXTW (temp);
1219                 opnd[j++] = Read (va, DR_LNT (disp), WA);
1220                 break;
1221 
1222             case WDP|MQ:
1223                 GET_ISTR (temp, L_WORD);
1224                 va = R[rn] + SXTW (temp);
1225                 opnd[j++] = Read (va, L_LONG, WA);
1226                 opnd[j++] = Read (va + 4, L_LONG, WA);
1227                 break;
1228 
1229             case WDP|MO:
1230                 GET_ISTR (temp, L_WORD);
1231                 va = R[rn] + SXTW (temp);
1232                 j = ReadOcta (va, opnd, j, WA);
1233                 break;
1234 
1235 /* Word displacement deferred */
1236 
1237             case WDD|VB:
1238             case WDD|WB: case WDD|WW: case WDD|WL: case WDD|WQ: case WDD|WO:
1239                 opnd[j++] = OP_MEM;
1240             case WDD|AB: case WDD|AW: case WDD|AL: case WDD|AQ: case WDD|AO:
1241                 GET_ISTR (temp, L_WORD);
1242                 iad = R[rn] + SXTW (temp);
1243                 va = opnd[j++] = Read (iad, L_LONG, RA);
1244                 break;
1245 
1246             case WDD|RB: case WDD|RW: case WDD|RL: case WDD|RF:
1247                 GET_ISTR (temp, L_WORD);
1248                 iad = R[rn] + SXTW (temp);
1249                 va = Read (iad, L_LONG, RA);
1250                 opnd[j++] = Read (va, DR_LNT (disp), RA);
1251                 break;
1252 
1253             case WDD|RQ: case WDD|RD: case WDD|RG:
1254                 GET_ISTR (temp, L_WORD);
1255                 iad = R[rn] + SXTW (temp);
1256                 va = Read (iad, L_LONG, RA);
1257                 opnd[j++] = Read (va, L_LONG, RA);
1258                 opnd[j++] = Read (va + 4, L_LONG, RA);
1259                 break;
1260 
1261             case WDD|RO: case WDD|RH:
1262                 GET_ISTR (temp, L_WORD);
1263                 iad = R[rn] + SXTW (temp);
1264                 va = Read (iad, L_LONG, RA);
1265                 j = ReadOcta (va, opnd, j, RA);
1266                 break;
1267 
1268             case WDD|MB: case WDD|MW: case WDD|ML:
1269                 GET_ISTR (temp, L_WORD);
1270                 iad = R[rn] + SXTW (temp);
1271                 va = Read (iad, L_LONG, RA);
1272                 opnd[j++] = Read (va, DR_LNT (disp), WA);
1273                 break;
1274 
1275             case WDD|MQ:
1276                 GET_ISTR (temp, L_WORD);
1277                 iad = R[rn] + SXTW (temp);
1278                 va = Read (iad, L_LONG, RA);
1279                 opnd[j++] = Read (va, L_LONG, WA);
1280                 opnd[j++] = Read (va + 4, L_LONG, WA);
1281                 break;
1282 
1283             case WDD|MO:
1284                 GET_ISTR (temp, L_WORD);
1285                 iad = R[rn] + SXTW (temp);
1286                 va = Read (iad, L_LONG, RA);
1287                 j = ReadOcta (va, opnd, j, WA);
1288                 break;
1289 
1290 /* Longword displacement */
1291 
1292             case LDP|VB:
1293             case LDP|WB: case LDP|WW: case LDP|WL: case LDP|WQ: case LDP|WO:
1294                 opnd[j++] = OP_MEM;
1295             case LDP|AB: case LDP|AW: case LDP|AL: case LDP|AQ: case LDP|AO:
1296                 GET_ISTR (temp, L_LONG);
1297                 va = opnd[j++] = R[rn] + temp;
1298                 break;
1299 
1300             case LDP|RB: case LDP|RW: case LDP|RL: case LDP|RF:
1301                 GET_ISTR (temp, L_LONG);
1302                 va = R[rn] + temp;
1303                 opnd[j++] = Read (va, DR_LNT (disp), RA);
1304                 break;
1305 
1306             case LDP|RQ: case LDP|RD: case LDP|RG:
1307                 GET_ISTR (temp, L_LONG);
1308                 va = R[rn] + temp;
1309                 opnd[j++] = Read (va, L_LONG, RA);
1310                 opnd[j++] = Read (va + 4, L_LONG, RA);
1311                 break;
1312 
1313             case LDP|RO: case LDP|RH:
1314                 GET_ISTR (temp, L_LONG);
1315                 va = R[rn] + temp;
1316                 j = ReadOcta (va, opnd, j, RA);
1317                 break;
1318 
1319             case LDP|MB: case LDP|MW: case LDP|ML:
1320                 GET_ISTR (temp, L_LONG);
1321                 va = R[rn] + temp;
1322                 opnd[j++] = Read (va, DR_LNT (disp), WA);
1323                 break;
1324 
1325             case LDP|MQ:
1326                 GET_ISTR (temp, L_LONG);
1327                 va = R[rn] + temp;
1328                 opnd[j++] = Read (va, L_LONG, WA);
1329                 opnd[j++] = Read (va + 4, L_LONG, WA);
1330                 break;
1331 
1332             case LDP|MO:
1333                 GET_ISTR (temp, L_LONG);
1334                 va = R[rn] + temp;
1335                 j = ReadOcta (va, opnd, j, WA);
1336                 break;
1337 
1338 /* Longword displacement deferred */
1339 
1340             case LDD|VB:
1341             case LDD|WB: case LDD|WW: case LDD|WL: case LDD|WQ: case LDD|WO:
1342                 opnd[j++] = OP_MEM;
1343             case LDD|AB: case LDD|AW: case LDD|AL: case LDD|AQ: case LDD|AO:
1344                 GET_ISTR (temp, L_LONG);
1345                 iad = R[rn] + temp;
1346                 va = opnd[j++] = Read (iad, L_LONG, RA);
1347                 break;
1348 
1349             case LDD|RB: case LDD|RW: case LDD|RL: case LDD|RF:
1350                 GET_ISTR (temp, L_LONG);
1351                 iad = R[rn] + temp;
1352                 va = Read (iad, L_LONG, RA);
1353                 opnd[j++] = Read (va, DR_LNT (disp), RA);
1354                 break;
1355 
1356             case LDD|RQ: case LDD|RD: case LDD|RG:
1357                 GET_ISTR (temp, L_LONG);
1358                 iad = R[rn] + temp;
1359                 va = Read (iad, L_LONG, RA);
1360                 opnd[j++] = Read (va, L_LONG, RA);
1361                 opnd[j++] = Read (va + 4, L_LONG, RA);
1362                 break;
1363 
1364             case LDD|RO: case LDD|RH:
1365                 GET_ISTR (temp, L_LONG);
1366                 iad = R[rn] + temp;
1367                 va = Read (iad, L_LONG, RA);
1368                 j = ReadOcta (va, opnd, j, RA);
1369                 break;
1370 
1371             case LDD|MB: case LDD|MW: case LDD|ML:
1372                 GET_ISTR (temp, L_LONG);
1373                 iad = R[rn] + temp;
1374                 va = Read (iad, L_LONG, RA);
1375                 opnd[j++] = Read (va, DR_LNT (disp), WA);
1376                 break;
1377 
1378             case LDD|MQ:
1379                 GET_ISTR (temp, L_LONG);
1380                 iad = R[rn] + temp;
1381                 va = Read (iad, L_LONG, RA);
1382                 opnd[j++] = Read (va, L_LONG, WA);
1383                 opnd[j++] = Read (va + 4, L_LONG, WA);
1384                 break;
1385 
1386             case LDD|MO:
1387                 GET_ISTR (temp, L_LONG);
1388                 iad = R[rn] + temp;
1389                 va = Read (iad, L_LONG, RA);
1390                 j = ReadOcta (va, opnd, j, WA);
1391                 break;
1392 
1393 /* Index */
1394 
1395             case IDX|VB:
1396             case IDX|WB: case IDX|WW: case IDX|WL: case IDX|WQ: case IDX|WO:
1397             case IDX|AB: case IDX|AW: case IDX|AL: case IDX|AQ: case IDX|AO:
1398             case IDX|MB: case IDX|MW: case IDX|ML: case IDX|MQ: case IDX|MO:
1399             case IDX|RB: case IDX|RW: case IDX|RL: case IDX|RQ: case IDX|RO:
1400             case IDX|RF: case IDX|RD: case IDX|RG: case IDX|RH:
1401                 CHECK_FOR_PC;
1402                 index = R[rn] << (disp & DR_LNMASK);
1403                 GET_ISTR (spec, L_BYTE);
1404                 rn = spec & RGMASK;
1405                 switch (spec & ~RGMASK) {
1406                 case ADC:
1407                     R[rn] = R[rn] - DR_LNT (disp);
1408                     recq[recqptr++] = RQ_REC (ADC | (disp & DR_LNMASK), rn);
1409                 case RGD:
1410                     CHECK_FOR_PC;
1411                     index = index + R[rn];
1412                     break;
1413 
1414                 case AIN:
1415                     CHECK_FOR_PC;
1416                     index = index + R[rn];
1417                     R[rn] = R[rn] + DR_LNT (disp);
1418                     recq[recqptr++] = RQ_REC (AIN | (disp & DR_LNMASK), rn);
1419                     break;
1420 
1421                 case AID:
1422                     if (rn == nPC) {
1423                         GET_ISTR (temp, L_LONG);
1424                         }
1425                     else {
1426                         temp = Read (R[rn], L_LONG, RA);
1427                         R[rn] = R[rn] + 4;
1428                         recq[recqptr++] = RQ_REC (AID|RL, rn);
1429                         }
1430                     index = temp + index;
1431                     break;
1432 
1433                 case BDP:
1434                     GET_ISTR (temp, L_BYTE);
1435                     index = index + R[rn] + SXTB (temp);
1436                     break;
1437 
1438                 case BDD:
1439                     GET_ISTR (temp, L_BYTE);
1440                     index = index + Read (R[rn] + SXTB (temp), L_LONG, RA);
1441                     break;
1442 
1443                 case WDP:
1444                     GET_ISTR (temp, L_WORD);
1445                     index = index + R[rn] + SXTW (temp);
1446                     break;
1447 
1448                 case WDD:
1449                     GET_ISTR (temp, L_WORD);
1450                     index = index + Read (R[rn] + SXTW (temp), L_LONG, RA);
1451                     break;
1452 
1453                 case LDP:
1454                     GET_ISTR (temp, L_LONG);
1455                     index = index + R[rn] + temp;
1456                     break;
1457 
1458                 case LDD:
1459                     GET_ISTR (temp, L_LONG);
1460                     index = index + Read (R[rn] + temp, L_LONG, RA);
1461                     break;
1462 
1463                 default:
1464                     RSVD_ADDR_FAULT;                    /* end case idxspec */
1465 					}
1466 
1467                 switch (disp & (DR_ACMASK|DR_SPFLAG|DR_LNMASK)) { /* case acc+lnt */
1468                 case VB:
1469                 case WB: case WW: case WL: case WQ: case WO:
1470                     opnd[j++] = OP_MEM;
1471                 case AB: case AW: case AL: case AQ: case AO:
1472                     va = opnd[j++] = index;
1473                     break;
1474 
1475                 case RB: case RW: case RL: case RF:
1476                     opnd[j++] = Read (va = index, DR_LNT (disp), RA);
1477                     break;
1478 
1479                 case RQ: case RD: case RG:
1480                     opnd[j++] = Read (va = index, L_LONG, RA);
1481                     opnd[j++] = Read (index + 4, L_LONG, RA);
1482                     break;
1483 
1484                 case RO: case RH:
1485                     j = ReadOcta (va = index, opnd, j, RA);
1486                     break;
1487 
1488                 case MB: case MW: case ML:
1489                     opnd[j++] = Read (va = index, DR_LNT (disp), WA);
1490                     break;
1491 
1492                 case MQ:
1493                     opnd[j++] = Read (va = index, L_LONG, WA);
1494                     opnd[j++] = Read (index + 4, L_LONG, WA);
1495                     break;
1496 
1497                 case MO:
1498                     j = ReadOcta (va = index, opnd, j, WA);
1499                     break;
1500 
1501                 default:                                /* all others */
1502                     RSVD_ADDR_FAULT;                    /* fault */
1503                     break;
1504                     }                                   /* end case access/lnt */
1505                 break;                                  /* end index */
1506 
1507             default:                                    /* all others */
1508                 RSVD_ADDR_FAULT;                        /* fault */
1509                 break;
1510                 }                                       /* end case spec */
1511             }                                           /* end for */
1512         }                                               /* end if not FPD */
1513 
1514 /* Optionally record instruction history */
1515 
1516     if (hst_lnt) {
1517         int32 lim;
1518         t_value wd;
1519 
1520         hst[hst_p].iPC = fault_PC;
1521         hst[hst_p].PSL = PSL | cc;
1522         hst[hst_p].opc = opc;
1523         for (i = 0; i < j; i++)
1524             hst[hst_p].opnd[i] = opnd[i];
1525         lim = PC - fault_PC;
1526         if ((uint32) lim > INST_SIZE)
1527             lim = INST_SIZE;
1528         for (i = 0; i < lim; i++) {
1529             if ((cpu_ex (&wd, fault_PC + i, &cpu_unit, SWMASK ('V'))) == SCPE_OK)
1530                 hst[hst_p].inst[i] = (uint8) wd;
1531             else {
1532                 hst[hst_p].inst[0] = hst[hst_p].inst[1] = 0xFF;
1533                 break;
1534                 }
1535             }
1536         hst_p = hst_p + 1;
1537         if (hst_p >= hst_lnt)
1538             hst_p = 0;
1539         }
1540 
1541 /* Dispatch to instructions */
1542 
1543     switch (opc) {
1544 
1545 /* Single operand instructions with dest, write only - CLRx dst.wx
1546 
1547         spec    =       reg/memory flag
1548         rn      =       register number
1549         va      =       virtual address
1550 */
1551 
1552     case CLRB:
1553         WRITE_B (0);                                    /* store result */
1554         CC_ZZ1P;                                        /* set cc's */
1555         break;
1556 
1557     case CLRW:
1558         WRITE_W (0);                                    /* store result */
1559         CC_ZZ1P;                                        /* set cc's */
1560         break;
1561 
1562     case CLRL:
1563         WRITE_L (0);                                    /* store result */
1564         CC_ZZ1P;                                        /* set cc's */
1565         break;
1566 
1567     case CLRQ:
1568         WRITE_Q (0, 0);                                 /* store result */
1569         CC_ZZ1P;                                        /* set cc's */
1570         break;
1571 
1572 /* Single operand instructions with source, read only - TSTx src.rx
1573 
1574         opnd[0] =       source
1575 */
1576 
1577     case TSTB:
1578         CC_IIZZ_B (op0);                                /* set cc's */
1579         break;
1580 
1581     case TSTW:
1582         CC_IIZZ_W (op0);                                /* set cc's */
1583         break;
1584 
1585     case TSTL:
1586         CC_IIZZ_L (op0);                                /* set cc's */
1587         if ((cc == CC_Z) &&                             /* zero result and */
1588             ((((cpu_idle_mask & VAX_IDLE_ULTOLD) &&     /* running Old Ultrix or friends? */
1589                (PSL_GETIPL (PSL) == 0x1)) ||            /*  at IPL 1? */
1590               ((cpu_idle_mask & VAX_IDLE_QUAD) &&       /* running Quasijarus or friends? */
1591                (PSL_GETIPL (PSL) == 0x0))) &&           /*  at IPL 0? */
1592              (fault_PC & 0x80000000) &&                 /* in system space? */
1593              ((PC - fault_PC) == 6) &&                  /* 6 byte instruction? */
1594              ((fault_PC & 0x7fffffff) < 0x4000)))       /* in low system space? */
1595             cpu_idle();                                 /* idle loop */
1596         break;
1597 
1598 /* Single operand instructions with source, read/write - op src.mx
1599 
1600         opnd[0] =       operand
1601         spec    =       reg/mem flag
1602         rn      =       register number
1603         va      =       operand address
1604 */
1605 
1606     case INCB:
1607         r = (op0 + 1) & BMASK;                          /* calc result */
1608         WRITE_B (r);                                    /* store result */
1609         CC_ADD_B (r, 1, op0);                           /* set cc's */
1610         break;
1611 
1612     case INCW:
1613         r = (op0 + 1) & WMASK;                          /* calc result */
1614         WRITE_W (r);                                    /* store result */
1615         CC_ADD_W (r, 1, op0);                           /* set cc's */
1616         break;
1617 
1618     case INCL:
1619         r = (op0 + 1) & LMASK;                          /* calc result */
1620         WRITE_L (r);                                    /* store result */
1621         CC_ADD_L (r, 1, op0);                           /* set cc's */
1622         break;
1623 
1624     case DECB:
1625         r = (op0 - 1) & BMASK;                          /* calc result */
1626         WRITE_B (r);                                    /* store result */
1627         CC_SUB_B (r, 1, op0);                           /* set cc's */
1628         break;
1629 
1630     case DECW:
1631         r = (op0 - 1) & WMASK;                          /* calc result */
1632         WRITE_W (r);                                    /* store result */
1633         CC_SUB_W (r, 1, op0);                           /* set cc's */
1634         break;
1635 
1636     case DECL:
1637         r = (op0 - 1) & LMASK;                          /* calc result */
1638         WRITE_L (r);                                    /* store result */
1639         CC_SUB_L (r, 1, op0);                           /* set cc's */
1640         break;
1641 
1642 /* Push instructions - PUSHL src.rl or PUSHAx src.ax
1643 
1644         opnd[0] =       source
1645 */
1646 
1647     case PUSHL: case PUSHAB: case PUSHAW: case PUSHAL: case PUSHAQ:
1648         Write (SP - 4, op0, L_LONG, WA);                /* push operand */
1649         SP = SP - 4;                                    /* decr stack ptr */
1650         CC_IIZP_L (op0);                                /* set cc's */
1651         break;
1652 
1653 /* Moves, converts, and ADAWI - op src.rx, dst.wx
1654 
1655         opnd[0] =       source
1656         spec    =       reg/mem flag
1657         rn      =       register number
1658         va      =       operand address
1659 */
1660 
1661     case MOVB:
1662         WRITE_B (op0);                                  /* result */
1663         CC_IIZP_B (op0);                                /* set cc's */
1664         break;
1665 
1666     case MOVW: case MOVZBW:
1667         WRITE_W (op0);                                  /* result */
1668         CC_IIZP_W (op0);                                /* set cc's */
1669         break;
1670 
1671     case MOVL: case MOVZBL: case MOVZWL:
1672     case MOVAB: case MOVAW: case MOVAL: case MOVAQ:
1673         WRITE_L (op0);                                  /* result */
1674         CC_IIZP_L (op0);                                /* set cc's */
1675         break;
1676 
1677     case MCOMB:
1678         r = op0 ^ BMASK;                                /* compl opnd */
1679         WRITE_B (r);                                    /* store result */
1680         CC_IIZP_B (r);                                  /* set cc's */
1681         break;
1682 
1683     case MCOMW:
1684         r = op0 ^ WMASK;                                /* compl opnd */
1685         WRITE_W (r);                                    /* store result */
1686         CC_IIZP_W (r);                                  /* set cc's */
1687         break;
1688 
1689     case MCOML:
1690         r = op0 ^ LMASK;                                /* compl opnd */
1691         WRITE_L (r);                                    /* store result */
1692         CC_IIZP_L (r);                                  /* set cc's */
1693         break;
1694 
1695     case MNEGB:
1696         r = (-op0) & BMASK;                             /* negate opnd */
1697         WRITE_B (r);                                    /* store result */
1698         CC_SUB_B (r, op0, 0);                           /* set cc's */
1699         break;
1700 
1701     case MNEGW:
1702         r = (-op0) & WMASK;                             /* negate opnd */
1703         WRITE_W (r);                                    /* store result */
1704         CC_SUB_W (r, op0, 0);                           /* set cc's */
1705         break;
1706 
1707     case MNEGL:
1708         r = (-op0) & LMASK;                             /* negate opnd */
1709         WRITE_L (r);                                    /* store result */
1710         CC_SUB_L (r, op0, 0);                           /* set cc's */
1711         break;
1712 
1713     case CVTBW:
1714         r = SXTBW (op0);                                /* ext sign */
1715         WRITE_W (r);                                    /* store result */
1716         CC_IIZZ_W (r);                                  /* set cc's */
1717         break;
1718 
1719     case CVTBL:
1720         r = SXTB (op0);                                 /* ext sign */
1721         WRITE_L (r);                                    /* store result */
1722         CC_IIZZ_L (r);                                  /* set cc's */
1723         break;
1724 
1725     case CVTWL:
1726         r = SXTW (op0);                                 /* ext sign */
1727         WRITE_L (r);                                    /* store result */
1728         CC_IIZZ_L (r);                                  /* set cc's */
1729         break;
1730 
1731     case CVTLB:
1732         r = op0 & BMASK;                                /* set result */
1733         WRITE_B (r);                                    /* store result */
1734         CC_IIZZ_B (r);                                  /* initial cc's */
1735         if ((op0 > 127) || (op0 < -128)) {
1736             V_INTOV;
1737             }
1738         break;
1739 
1740     case CVTLW:
1741         r = op0 & WMASK;                                /* set result */
1742         WRITE_W (r);                                    /* store result */
1743         CC_IIZZ_W (r);                                  /* initial cc's */
1744         if ((op0 > 32767) || (op0 < -32768)) {
1745             V_INTOV;
1746             }
1747         break;
1748 
1749     case CVTWB:
1750         r = op0 & BMASK;                                /* set result */
1751         WRITE_B (r);                                    /* store result */
1752         CC_IIZZ_B (r);                                  /* initial cc's */
1753         temp = SXTW (op0);                              /* cvt op to long */
1754         if ((temp > 127) || (temp < -128)) {
1755             V_INTOV;
1756             }
1757         break;
1758 
1759     case ADAWI:
1760         if (op1 >= 0) temp = R[op1] & WMASK;            /* reg? ADDW2 */
1761         else {
1762             if (op2 & 1)                                /* mem? chk align */
1763                 RSVD_OPND_FAULT;
1764             temp = Read (op2, L_WORD, WA);              /* ok, ADDW2 */
1765             }
1766         r = (op0 + temp) & WMASK;
1767         WRITE_W (r);
1768         CC_ADD_W (r, op0, temp);                        /* set cc's */
1769         break;
1770 
1771 /* Integer operates, 2 operand, read only - op src1.rx, src2.rx
1772 
1773         opnd[0] =       source1
1774         opnd[1] =       source2
1775 */
1776 
1777     case CMPB:
1778         CC_CMP_B (op0, op1);                            /* set cc's */
1779         break;
1780 
1781     case CMPW:
1782         CC_CMP_W (op0, op1);                            /* set cc's */
1783         break;
1784 
1785     case CMPL:
1786         CC_CMP_L (op0, op1);                            /* set cc's */
1787         break;
1788 
1789     case BITB:
1790         r = op1 & op0;                                  /* calc result */
1791         CC_IIZP_B (r);                                  /* set cc's */
1792         break;
1793 
1794     case BITW:
1795         r = op1 & op0;                                  /* calc result */
1796         CC_IIZP_W (r);                                  /* set cc's */
1797         break;
1798 
1799     case BITL:
1800         r = op1 & op0;                                  /* calc result */
1801         CC_IIZP_L (r);                                  /* set cc's */
1802         if ((cc == CC_Z) &&
1803             (cpu_idle_mask & VAX_IDLE_ULT) &&           /* running Ultrix or friends? */
1804             ((PSL & PSL_IS) != 0) &&                    /* on IS? */
1805             (PSL_GETIPL (PSL) == 0x18) &&               /* at IPL 18? */
1806             (fault_PC & 0x80000000) &&                  /* in system space? */
1807             ((PC - fault_PC) == 8) &&                   /* 8 byte instruction? */
1808             ((fault_PC & 0x7fffffff) < 0x6000))         /* in low system space? */
1809             cpu_idle();                                 /* idle loop */
1810         break;
1811 
1812 /* Integer operates, 2 operand read/write, and 3 operand, also MOVQ
1813         op2 src.rx, dst.mx      op3 src.rx, src.rx, dst.wx
1814 
1815         opnd[0] =       source1
1816         opnd[1] =       source2
1817         spec    =       register/memory flag
1818         rn      =       register number
1819         va      =       memory address
1820 */
1821 
1822     case ADDB2: case ADDB3:
1823         r = (op1 + op0) & BMASK;                        /* calc result */
1824         WRITE_B (r);                                    /* store result */
1825         CC_ADD_B (r, op0, op1);                         /* set cc's */
1826         break;
1827 
1828     case ADDW2: case ADDW3:
1829         r = (op1 + op0) & WMASK;                        /* calc result */
1830         WRITE_W (r);                                    /* store result */
1831         CC_ADD_W (r, op0, op1);                         /* set cc's */
1832         break;
1833 
1834     case ADWC:
1835         r = (op1 + op0 + (cc & CC_C)) & LMASK;          /* calc result */
1836         WRITE_L (r);                                    /* store result */
1837         CC_ADD_L (r, op0, op1);                         /* set cc's */
1838         if ((r == op1) && op0)                          /* special case */
1839             cc = cc | CC_C;
1840         break;
1841 
1842     case ADDL2: case ADDL3:
1843         r = (op1 + op0) & LMASK;                        /* calc result */
1844         WRITE_L (r);                                    /* store result */
1845         CC_ADD_L (r, op0, op1);                         /* set cc's */
1846         break;
1847 
1848     case SUBB2: case SUBB3:
1849         r = (op1 - op0) & BMASK;                        /* calc result */
1850         WRITE_B (r);                                    /* store result */
1851         CC_SUB_B (r, op0, op1);                         /* set cc's */
1852         break;
1853 
1854     case SUBW2: case SUBW3:
1855         r = (op1 - op0) & WMASK;                        /* calc result */
1856         WRITE_W (r);                                    /* store result */
1857         CC_SUB_W (r, op0, op1);                         /* set cc's */
1858         break;
1859 
1860     case SBWC:
1861         r = (op1 - op0 - (cc & CC_C)) & LMASK;          /* calc result */
1862         WRITE_L (r);                                    /* store result */
1863         CC_SUB_L (r, op0, op1);                         /* set cc's */
1864         if ((op0 == op1) && r)                          /* special case */
1865             cc = cc | CC_C;
1866         break;
1867 
1868     case SUBL2: case SUBL3:
1869         r = (op1 - op0) & LMASK;                        /* calc result */
1870         WRITE_L (r);                                    /* store result */
1871         CC_SUB_L (r, op0, op1);                         /* set cc's */
1872         break;
1873 
1874     case MULB2: case MULB3:
1875         temp = SXTB (op0) * SXTB (op1);                 /* multiply */
1876         r = temp & BMASK;                               /* mask to result */
1877         WRITE_B (r);                                    /* store result */
1878         CC_IIZZ_B (r);                                  /* set cc's */
1879         if ((temp > 127) || (temp < -128)) {
1880             V_INTOV;
1881             }
1882         break;
1883 
1884     case MULW2: case MULW3:
1885         temp = SXTW (op0) * SXTW (op1);                 /* multiply */
1886         r = temp & WMASK;                               /* mask to result */
1887         WRITE_W (r);                                    /* store result */
1888         CC_IIZZ_W (r);                                  /* set cc's */
1889         if ((temp > 32767) || (temp < -32768)) {
1890             V_INTOV;
1891             }
1892         break;
1893 
1894     case MULL2: case MULL3:
1895         r = op_emul (op0, op1, &rh);                    /* get 64b result */
1896         WRITE_L (r);                                    /* store result */
1897         CC_IIZZ_L (r);                                  /* set cc's */
1898         if (rh != ((r & LSIGN)? -1: 0)) {               /* chk overflow */
1899             V_INTOV;
1900             }
1901         break;
1902 
1903     case DIVB2: case DIVB3:
1904         if (op0 == 0) {                                 /* div by zero? */
1905             r = op1;
1906             temp = CC_V;
1907             SET_TRAP (TRAP_DIVZRO);
1908             }
1909         else if ((op0 == BMASK) && (op1 == BSIGN)) {    /* overflow? */
1910             r = op1;
1911             temp = CC_V;
1912             INTOV;
1913             }
1914         else {
1915             r = SXTB (op1) / SXTB (op0);                /* ok, divide */
1916             temp = 0;
1917             }
1918         r = r & BMASK;                                  /* mask to result */
1919         WRITE_B (r);                                    /* write result */
1920         CC_IIZZ_B (r);                                  /* set cc's */
1921         cc = cc | temp;                                 /* error? set V */
1922         break;
1923 
1924     case DIVW2: case DIVW3:
1925         if (op0 == 0) {                                 /* div by zero? */
1926             r = op1;
1927             temp = CC_V;
1928             SET_TRAP (TRAP_DIVZRO);
1929             }
1930         else if ((op0 == WMASK) && (op1 == WSIGN)) {    /* overflow? */
1931             r = op1;
1932             temp = CC_V;
1933             INTOV;
1934             }
1935         else {
1936             r = SXTW (op1) / SXTW (op0);                /* ok, divide */
1937             temp = 0;
1938             }
1939         r = r & WMASK;                                  /* mask to result */
1940         WRITE_W (r);                                    /* write result */
1941         CC_IIZZ_W (r);                                  /* set cc's */
1942         cc = cc | temp;                                 /* error? set V */
1943         break;
1944 
1945     case DIVL2: case DIVL3:
1946         if (op0 == 0) {                                 /* div by zero? */
1947             r = op1;
1948             temp = CC_V;
1949             SET_TRAP (TRAP_DIVZRO);
1950             }
1951         else if ((op0 == LMASK) && (op1 == LSIGN)) {    /* overflow? */
1952             r = op1;
1953             temp = CC_V;
1954             INTOV;
1955             }
1956         else {
1957             r = op1 / op0;                              /* ok, divide */
1958             temp = 0;
1959             }
1960         r = r & LMASK;                                  /* mask to result */
1961         WRITE_L (r);                                    /* write result */
1962         CC_IIZZ_L (r);                                  /* set cc's */
1963         cc = cc | temp;                                 /* error? set V */
1964         break;
1965 
1966     case BISB2: case BISB3:
1967         r = op1 | op0;                                  /* calc result */
1968         WRITE_B (r);                                    /* store result */
1969         CC_IIZP_B (r);                                  /* set cc's */
1970         break;
1971 
1972     case BISW2: case BISW3:
1973         r = op1 | op0;                                  /* calc result */
1974         WRITE_W (r);                                    /* store result */
1975         CC_IIZP_W (r);                                  /* set cc's */
1976         break;
1977 
1978     case BISL2: case BISL3:
1979         r = op1 | op0;                                  /* calc result */
1980         WRITE_L (r);                                    /* store result */
1981         CC_IIZP_L (r);                                  /* set cc's */
1982         break;
1983 
1984     case BICB2: case BICB3:
1985         r = op1 & ~op0;                                 /* calc result */
1986         WRITE_B (r);                                    /* store result */
1987         CC_IIZP_B (r);                                  /* set cc's */
1988         break;
1989 
1990     case BICW2: case BICW3:
1991         r = op1 & ~op0;                                 /* calc result */
1992         WRITE_W (r);                                    /* store result */
1993         CC_IIZP_W (r);                                  /* set cc's */
1994         break;
1995 
1996     case BICL2: case BICL3:
1997         r = op1 & ~op0;                                 /* calc result */
1998         WRITE_L (r);                                    /* store result */
1999         CC_IIZP_L (r);                                  /* set cc's */
2000         break;
2001 
2002     case XORB2: case XORB3:
2003         r = op1 ^ op0;                                  /* calc result */
2004         WRITE_B (r);                                    /* store result */
2005         CC_IIZP_B (r);                                  /* set cc's */
2006         break;
2007 
2008     case XORW2: case XORW3:
2009         r = op1 ^ op0;                                  /* calc result */
2010         WRITE_W (r);                                    /* store result */
2011         CC_IIZP_W (r);                                  /* set cc's */
2012         break;
2013 
2014     case XORL2: case XORL3:
2015         r = op1 ^ op0;                                  /* calc result */
2016         WRITE_L (r);                                    /* store result */
2017         CC_IIZP_L (r);                                  /* set cc's */
2018         break;
2019 
2020 /* MOVQ - movq src.rq, dst.wq
2021 
2022         opnd[0:1] =     source
2023         spec    =       register/memory flag
2024         rn      =       register number
2025         va      =       memory address
2026 
2027 */
2028 
2029     case MOVQ:
2030         WRITE_Q (op0, op1);                             /* store result */
2031         CC_IIZP_Q (op0, op1);
2032         break;
2033 
2034 /* Shifts - op shf.rb,src.rl,dst.wl
2035 
2036         opnd[0] =       shift count
2037         opnd[1] =       source
2038         spec    =       register/memory flag
2039         rn      =       register number
2040         va      =       memory address
2041 */
2042 
2043     case ROTL:
2044         j = op0 % 32;                                   /* reduce sc, mod 32 */
2045         if (j)
2046             r = ((((uint32) op1) << j) | (((uint32) op1) >> (32 - j))) & LMASK;
2047         else r = op1;
2048         WRITE_L (r);                                    /* store result */
2049         CC_IIZP_L (r);                                  /* set cc's */
2050         break;
2051 
2052     case ASHL:
2053         if (op0 & BSIGN) {                              /* right shift? */
2054             temp = 0x100 - op0;                         /* get |shift| */
2055             if (temp > 31)                              /* sc > 31? */
2056                 r = (op1 & LSIGN)? LMASK: 0;
2057             else r = op1 >> temp;                       /* shift */
2058             WRITE_L (r);                                /* store result */
2059             CC_IIZZ_L (r);                              /* set cc's */
2060             break;
2061             }
2062         else {
2063             if (op0 > 31)                               /* sc > 31? */
2064                 r = temp = 0;
2065             else {
2066                 r = (((uint32) op1) << op0) & LMASK;    /* shift */
2067                 temp = r >> op0;                        /* shift back */
2068                 }
2069             WRITE_L (r);                                /* store result */
2070             CC_IIZZ_L (r);                              /* set cc's */
2071             if (op1 != temp) {                          /* bits lost? */
2072                 V_INTOV;
2073                 }
2074             }
2075         break;
2076 
2077     case ASHQ:
2078         r = op_ashq (opnd, &rh, &flg);                  /* do qw shift */
2079         WRITE_Q (r, rh);                                /* store results */
2080         CC_IIZZ_Q (r, rh);                              /* set cc's */
2081         if (flg) {                                      /* if ovflo, set */
2082             V_INTOV;
2083             }
2084         break;
2085 
2086 /* EMUL - emul mplr.rl,mpcn.rl,add.rl,dst.wq
2087 
2088         op0     =       multiplier
2089         op1     =       multiplicand
2090         op2     =       adder
2091         op3:op4 =       destination (.wq)
2092 */
2093 
2094     case EMUL:
2095         r = op_emul (op0, op1, &rh);                    /* calc 64b result */
2096         r = r + op2;                                    /* add 32b value */
2097         rh = rh + (((uint32) r) < ((uint32) op2)) -     /* into 64b result */
2098             ((op2 & LSIGN)? 1: 0);
2099         WRITE_Q (r, rh);                                /* write result */
2100         CC_IIZZ_Q (r, rh);                              /* set cc's */
2101         break;
2102 
2103 /* EDIV - ediv dvr.rl,dvd.rq,quo.wl,rem.wl
2104 
2105         op0     =       divisor (.rl)
2106         op1:op2 =       dividend (.rq)
2107         op3:op4 =       quotient address (.wl)
2108         op5:op6 =       remainder address (.wl)
2109 */
2110 
2111     case EDIV:
2112         if (op5 < 0)                                    /* wtest remainder */
2113             Read (op6, L_LONG, WA);
2114         if (op0 == 0) {                                 /* divide by zero? */
2115             flg = CC_V;                                 /* set V */
2116             r = opnd[1];                                /* quo = low divd */
2117             rh = 0;                                     /* rem = 0 */
2118             SET_TRAP (TRAP_DIVZRO);                     /* set trap */
2119             }
2120         else {
2121             r = op_ediv (opnd, &rh, &flg);              /* extended divide */
2122             if (flg) {                                  /* if ovf+IV, set trap */
2123                 INTOV;
2124                 }
2125             }
2126         if (op3 >= 0)                                   /* store quotient */
2127             R[op3] = r;
2128         else Write (op4, r, L_LONG, WA);
2129         if (op5 >= 0)                                   /* store remainder */
2130             R[op5] = rh;
2131         else Write (op6, rh, L_LONG, WA);
2132         CC_IIZZ_L (r);                                  /* set cc's */
2133         cc = cc | flg;                                  /* set V if required */
2134         break;
2135 
2136 /* Control instructions */
2137 
2138 /* Simple branches and subroutine calls */
2139 
2140     case BRB:
2141         BRANCHB (brdisp);                               /* branch  */
2142         if (PC == fault_PC) {                           /* to self? */
2143             if (PSL_GETIPL (PSL) == 0x1F)               /* int locked out? */
2144                 ABORT (STOP_LOOP);                      /* infinite loop */
2145             cpu_idle ();                                /* idle loop */
2146             }
2147         break;
2148 
2149     case BRW:
2150         BRANCHW (brdisp);                               /* branch */
2151         if (PC == fault_PC) {                           /* to self? */
2152             if (PSL_GETIPL (PSL) == 0x1F)               /* int locked out? */
2153                 ABORT (STOP_LOOP);                      /* infinite loop */
2154             cpu_idle ();                                /* idle loop */
2155             }
2156         break;
2157 
2158     case BSBB:
2159         Write (SP - 4, PC, L_LONG, WA);                 /* push PC on stk */
2160         SP = SP - 4;                                    /* decr stk ptr */
2161         BRANCHB (brdisp);                               /* branch  */
2162         break;
2163 
2164     case BSBW:
2165         Write (SP - 4, PC, L_LONG, WA);                 /* push PC on stk */
2166         SP = SP - 4;                                    /* decr stk ptr */
2167         BRANCHW (brdisp);                               /* branch */
2168         break;
2169 
2170     case BGEQ:
2171         if (!(cc & CC_N))                               /* br if N = 0 */
2172             BRANCHB (brdisp);
2173         break;
2174 
2175     case BLSS:
2176         if (cc & CC_N)                                  /* br if N = 1 */
2177             BRANCHB (brdisp);
2178         break;
2179 
2180     case BNEQ:
2181         if (!(cc & CC_Z))                               /* br if Z = 0 */
2182             BRANCHB (brdisp);
2183         break;
2184 
2185     case BEQL:
2186         if (cc & CC_Z) {                                /* br if Z = 1 */
2187             BRANCHB (brdisp);
2188             if (((PSL & PSL_IS) != 0) &&                /* on IS? */
2189                 (PSL_GETIPL (PSL) == 0x1F) &&           /* at IPL 31 */
2190                 (fault_PC == 0x2004361B))               /* Boot ROM Character Prompt */
2191                 cpu_idle();
2192             }
2193         break;
2194 
2195     case BVC:
2196         if (!(cc & CC_V))                               /* br if V = 0 */
2197             BRANCHB (brdisp);
2198         break;
2199 
2200     case BVS:
2201         if (cc & CC_V)                                  /* br if V = 1 */
2202             BRANCHB (brdisp);
2203         break;
2204 
2205     case BGEQU:
2206         if (!(cc & CC_C))                               /* br if C = 0 */
2207             BRANCHB (brdisp);
2208         break;
2209 
2210     case BLSSU:
2211         if (cc & CC_C)                                  /* br if C = 1 */
2212             BRANCHB (brdisp);
2213         break;
2214 
2215     case BGTR:
2216         if (!(cc & (CC_N | CC_Z)))                      /* br if N | Z = 0 */
2217             BRANCHB (brdisp);
2218         break;
2219 
2220     case BLEQ:
2221         if (cc & (CC_N | CC_Z))                         /* br if N | Z = 1 */
2222             BRANCHB (brdisp);
2223         break;
2224 
2225     case BGTRU:
2226         if (!(cc & (CC_C | CC_Z)))                      /* br if C | Z = 0 */
2227             BRANCHB (brdisp);
2228         break;
2229 
2230     case BLEQU:
2231         if (cc & (CC_C | CC_Z))                         /* br if C | Z = 1 */
2232             BRANCHB (brdisp);
2233         break;
2234 
2235 /* Simple jumps and subroutine calls - op addr.ab
2236 
2237         opnd[0] =       address
2238 */
2239 
2240     case JSB:
2241         Write (SP - 4, PC, L_LONG, WA);                 /* push PC on stk */
2242         SP = SP - 4;                                    /* decr stk ptr */
2243 
2244     case JMP:
2245         JUMP (op0);                                     /* jump */
2246         break;
2247 
2248     case RSB:
2249         temp = Read (SP, L_LONG, RA);                   /* get top of stk */
2250         SP = SP + 4;                                    /* incr stk ptr */
2251         JUMP (temp);
2252         break;
2253 
2254 /* SOB instructions - op idx.ml,disp.bb
2255 
2256         opnd[0] =       index
2257         spec    =       register/memory flag
2258         rn      =       register number
2259         va      =       memory address
2260 */
2261 
2262     case SOBGEQ:
2263         r = op0 - 1;                                    /* decr index */
2264         WRITE_L (r);                                    /* store result */
2265         CC_IIZP_L (r);                                  /* set cc's */
2266         V_SUB_L (r, 1, op0);                            /* test for ovflo */
2267         if (r >= 0)                                     /* if >= 0, branch */
2268             BRANCHB (brdisp);
2269         break;
2270 
2271     case SOBGTR:
2272         r = op0 - 1;                                    /* decr index */
2273         WRITE_L (r);                                    /* store result */
2274         CC_IIZP_L (r);                                  /* set cc's */
2275         V_SUB_L (r, 1, op0);                            /* test for ovflo */
2276         if (r > 0)                                      /* if >= 0, branch */
2277             BRANCHB (brdisp);
2278         break;
2279 
2280 /* AOB instructions - op limit.rl,idx.ml,disp.bb
2281 
2282         opnd[0] =       limit
2283         opnd[1] =       index
2284         spec    =       register/memory flag
2285         rn      =       register number
2286         va      =       memory address
2287 */
2288 
2289     case AOBLSS:
2290         r = op1 + 1;                                    /* incr index */
2291         WRITE_L (r);                                    /* store result */
2292         CC_IIZP_L (r);                                  /* set cc's */
2293         V_ADD_L (r, 1, op1);                            /* test for ovflo */
2294         if (r < op0)                                    /* if < lim, branch */
2295             BRANCHB (brdisp);
2296         break;
2297 
2298     case AOBLEQ:
2299         r = op1 + 1;                                    /* incr index */
2300         WRITE_L (r);                                    /* store result */
2301         CC_IIZP_L (r);                                  /* set cc's */
2302         V_ADD_L (r, 1, op1);                            /* test for ovflo */
2303         if (r <= op0)                                   /* if < lim, branch */
2304             BRANCHB (brdisp);
2305         break;
2306 
2307 /* ACB instructions - op limit.rx,add.rx,index.mx,disp.bw
2308 
2309         opnd[0] =       limit
2310         opnd[1] =       adder
2311         opnd[2] =       index
2312         spec    =       register/memory flag
2313         rn      =       register number
2314         va      =       memory address
2315 */
2316 
2317     case ACBB:
2318         r = (op2 + op1) & BMASK;                        /* calc result */
2319         WRITE_B (r);                                    /* store result */
2320         CC_IIZP_B (r);                                  /* set cc's */
2321         V_ADD_B (r, op1, op2);                          /* test for ovflo */
2322         if ((op1 & BSIGN)? (SXTB (r) >= SXTB (op0)): (SXTB (r) <= SXTB (op0)))
2323             BRANCHW (brdisp);
2324         break;
2325 
2326     case ACBW:
2327         r = (op2 + op1) & WMASK;                        /* calc result */
2328         WRITE_W (r);                                    /* store result */
2329         CC_IIZP_W (r);                                  /* set cc's */
2330         V_ADD_W (r, op1, op2);                          /* test for ovflo */
2331         if ((op1 & WSIGN)? (SXTW (r) >= SXTW (op0)): (SXTW (r) <= SXTW (op0)))
2332             BRANCHW (brdisp);
2333         break;
2334 
2335     case ACBL:
2336         r = (op2 + op1) & LMASK;                        /* calc result */
2337         WRITE_L (r);                                    /* store result */
2338         CC_IIZP_L (r);                                  /* set cc's */
2339         V_ADD_L (r, op1, op2);                          /* test for ovflo */
2340         if ((op1 & LSIGN)? (r >= op0): (r <= op0))
2341             BRANCHW (brdisp);
2342         break;
2343 
2344 /* CASE instructions - casex sel.rx,base.rx,lim.rx
2345 
2346         opnd[0] =       selector
2347         opnd[1] =       base
2348         opnd[2] =       limit
2349 */
2350 
2351     case CASEB:
2352         r = (op0 - op1) & BMASK;                        /* sel - base */
2353         CC_CMP_B (r, op2);                              /* r:limit, set cc's */
2354         if (r > op2)                                    /* r > limit (unsgnd)? */
2355             JUMP (PC + ((op2 + 1) * 2));
2356         else {
2357             temp = Read (PC + (r * 2), L_WORD, RA);
2358             BRANCHW (temp);
2359             }
2360         break;
2361 
2362     case CASEW:
2363         r = (op0 - op1) & WMASK;                        /* sel - base */
2364         CC_CMP_W (r, op2);                              /* r:limit, set cc's */
2365         if (r > op2)                                    /* r > limit (unsgnd)? */
2366             JUMP (PC + ((op2 + 1) * 2));
2367         else {
2368             temp = Read (PC + (r * 2), L_WORD, RA);
2369             BRANCHW (temp);
2370             }
2371         break;
2372 
2373     case CASEL:
2374         r = (op0 - op1) & LMASK;                        /* sel - base */
2375         CC_CMP_L (r, op2);                              /* r:limit, set cc's */
2376         if (((uint32) r) > ((uint32) op2))              /* r > limit (unsgnd)? */
2377             JUMP (PC + ((op2 + 1) * 2));
2378         else {
2379             temp = Read (PC + (r * 2), L_WORD, RA);
2380             BRANCHW (temp);
2381             }
2382         break;
2383 
2384 /* Branch on bit instructions - bbxy pos.rl,op.wb,disp.bb
2385 
2386         opnd[0] =       position
2387         opnd[1] =       register number/memory flag
2388         opnd[2] =       memory address, if memory
2389 */
2390 
2391     case BBS:
2392         if (op_bb_n (opnd, acc)) {                      /* br if bit set */
2393             BRANCHB (brdisp);
2394             if (((PSL & PSL_IS) != 0) &&                /* on IS? */
2395                 (PSL_GETIPL (PSL) == 0x3) &&            /* at IPL 3? */
2396                 ((cpu_idle_mask & VAX_IDLE_VMS) != 0))  /* running VMS? */
2397                 cpu_idle ();                            /* idle loop */
2398             }
2399         break;
2400 
2401     case BBC:
2402         if (!op_bb_n (opnd, acc))                       /* br if bit clr */
2403             BRANCHB (brdisp);
2404         break;
2405 
2406     case BBSS: case BBSSI:
2407         if (op_bb_x (opnd, 1, acc))                     /* br if set, set */
2408             BRANCHB (brdisp);
2409         break;
2410 
2411     case BBCC: case BBCCI:
2412         if (!op_bb_x (opnd, 0, acc))                    /* br if clr, clr*/
2413             BRANCHB (brdisp);
2414         break;
2415 
2416     case BBSC:
2417         if (op_bb_x (opnd, 0, acc))                     /* br if clr, set */
2418             BRANCHB (brdisp);
2419         break;
2420 
2421     case BBCS:
2422         if (!op_bb_x (opnd, 1, acc))                    /* br if set, clr */
2423             BRANCHB (brdisp);
2424         break;
2425 
2426     case BLBS:
2427         if (op0 & 1)                                    /* br if bit set */
2428             BRANCHB (brdisp);
2429         break;
2430 
2431     case BLBC:
2432         if ((op0 & 1) == 0)                             /* br if bit clear */
2433             BRANCHB (brdisp);
2434         break;
2435 
2436 /* Extract field instructions - ext?v pos.rl,size.rb,base.wb,dst.wl
2437 
2438         opnd[0] =       position
2439         opnd[1] =       size
2440         opnd[2] =       register number/memory flag
2441         opnd[3] =       register content/memory address
2442         spec    =       register/memory flag
2443         rn      =       register number
2444         va      =       memory address
2445 */
2446 
2447     case EXTV:
2448         r = op_extv (opnd, vfldrp1, acc);               /* get field */
2449         if (r & byte_sign[op1])
2450             r = r | ~byte_mask[op1];
2451         WRITE_L (r);                                    /* store field */
2452         CC_IIZP_L (r);                                  /* set cc's */
2453         break;
2454 
2455     case EXTZV:
2456         r = op_extv (opnd, vfldrp1, acc);               /* get field */
2457         WRITE_L (r);                                    /* store field */
2458         CC_IIZP_L (r);                                  /* set cc's */
2459         break;
2460 
2461 /* Compare field instructions - cmp?v pos.rl,size.rb,base.wb,src2.rl
2462 
2463         opnd[0] =       position
2464         opnd[1] =       size
2465         opnd[2] =       register number/memory flag
2466         opnd[3] =       register content/memory address
2467         opnd[4] =       source2
2468 */
2469 
2470     case CMPV:
2471         r = op_extv (opnd, vfldrp1, acc);               /* get field */
2472         if (r & byte_sign[op1])
2473             r = r | ~byte_mask[op1];
2474         CC_CMP_L (r, op4);                              /* set cc's */
2475         break;
2476 
2477     case CMPZV:
2478         r = op_extv (opnd, vfldrp1, acc);               /* get field */
2479         CC_CMP_L (r, op4);                              /* set cc's */
2480         break;
2481 
2482 /* Find first field instructions - ff? pos.rl,size.rb,base.wb,dst.wl
2483 
2484         opnd[0] =       position
2485         opnd[1] =       size
2486         opnd[2] =       register number/memory flag
2487         opnd[3] =       register content/memory address
2488         spec    =       register/memory flag
2489         rn      =       register number
2490         va      =       memory address
2491 */
2492 
2493     case FFS:
2494         r = op_extv (opnd, vfldrp1, acc);               /* get field */
2495         temp = op_ffs (r, op1);                         /* find first 1 */
2496         WRITE_L (op0 + temp);                           /* store result */
2497         cc = r? 0: CC_Z;                                /* set cc's */
2498         break;
2499 
2500     case FFC:
2501         r = op_extv (opnd, vfldrp1, acc);               /* get field */
2502         r = r ^ byte_mask[op1];                         /* invert bits */
2503         temp = op_ffs (r, op1);                         /* find first 1 */
2504         WRITE_L (op0 + temp);                           /* store result */
2505         cc = r? 0: CC_Z;                                /* set cc's */
2506         break;
2507 
2508 /* Insert field instruction - insv src.rl,pos.rb,size.rl,base.wb
2509 
2510         opnd[0] =       source
2511         opnd[1] =       position
2512         opnd[2] =       size
2513         opnd[3] =       register number/memory flag
2514         opnd[4] =       register content/memory address
2515 */
2516 
2517     case INSV:
2518         op_insv (opnd, vfldrp1, acc);                   /* insert field */
2519         break;
2520 
2521 /* Call and return - call? arg.rx,proc.ab
2522 
2523         opnd[0] =       argument
2524         opnd[1] =       procedure address
2525 */
2526 
2527     case CALLS:
2528         cc = op_call (opnd, TRUE, acc);
2529         break;
2530 
2531     case CALLG:
2532         cc = op_call (opnd, FALSE, acc);
2533         break;
2534 
2535     case RET:
2536         cc = op_ret (acc);
2537         break;
2538 
2539 /* Miscellaneous instructions */
2540 
2541     case HALT:
2542         if (PSL & PSL_CUR)                              /* not kern? rsvd inst */
2543             RSVD_INST_FAULT;
2544         else if (cpu_unit.flags & UNIT_CONH)            /* halt to console? */
2545             cc = con_halt (CON_HLTINS, cc);             /* enter firmware */
2546         else {
2547             ABORT (STOP_HALT);                          /* halt to simulator */
2548             }
2549 
2550     case NOP:
2551         break;
2552 
2553     case BPT:
2554         SETPC (fault_PC);
2555         PSL = PSL & ~PSL_TP;                                /* clear <tp> */
2556         cc = intexc (SCB_BPT, cc, 0, IE_EXC);
2557         GET_CUR;
2558         break;
2559 
2560     case XFC:
2561         SETPC (fault_PC);
2562         PSL = PSL & ~PSL_TP;                                /* clear <tp> */
2563         cc = intexc (SCB_XFC, cc, 0, IE_EXC);
2564         GET_CUR;
2565         break;
2566 
2567     case BISPSW:
2568         if (opnd[0] & PSW_MBZ)
2569             RSVD_OPND_FAULT;
2570         PSL = PSL | (opnd[0] & ~CC_MASK);
2571         cc = cc | (opnd[0] & CC_MASK);
2572         break;
2573 
2574     case BICPSW:
2575         if (opnd[0] & PSW_MBZ)
2576             RSVD_OPND_FAULT;
2577         PSL = PSL & ~opnd[0];
2578         cc = cc & ~opnd[0];
2579         break;
2580 
2581     case MOVPSL:
2582         r = PSL | cc;
2583         WRITE_L (r);
2584         break;
2585 
2586     case PUSHR:
2587         op_pushr (opnd, acc);
2588         break;
2589 
2590     case POPR:
2591         op_popr (opnd, acc);
2592         break;
2593 
2594     case INDEX:
2595         if ((op0 < op1) || (op0 > op2))
2596             SET_TRAP (TRAP_SUBSCR);
2597         r = (op0 + op4) * op3;
2598         WRITE_L (r);
2599         CC_IIZZ_L (r);
2600         break;
2601 
2602 /* Queue and interlocked queue */
2603 
2604     case INSQUE:
2605         cc = op_insque (opnd, acc);
2606         break;
2607 
2608     case REMQUE:
2609         cc = op_remque (opnd, acc);
2610         break;
2611 
2612     case INSQHI:
2613         cc = op_insqhi (opnd, acc);
2614         break;
2615 
2616     case INSQTI:
2617         cc = op_insqti (opnd, acc);
2618         break;
2619 
2620     case REMQHI:
2621         cc = op_remqhi (opnd, acc);
2622         break;
2623 
2624     case REMQTI:
2625         cc = op_remqti (opnd, acc);
2626         break;
2627 
2628 /* String instructions */
2629 
2630     case MOVC3: case MOVC5:
2631         cc = op_movc (opnd, opc & 4, acc);
2632         break;
2633 
2634     case CMPC3: case CMPC5:
2635         cc = op_cmpc (opnd, opc & 4, acc);
2636         break;
2637 
2638     case LOCC: case SKPC:
2639         cc = op_locskp (opnd, opc & 1, acc);
2640         break;
2641 
2642     case SCANC: case SPANC:
2643         cc = op_scnspn (opnd, opc & 1, acc);
2644         break;
2645 
2646 /* Floating point instructions */
2647 
2648     case TSTF: case TSTD:
2649         r = op_movfd (op0);
2650         CC_IIZZ_FP (r);
2651         break;
2652 
2653     case TSTG:
2654         r = op_movg (op0);
2655         CC_IIZZ_FP (r);
2656         break;
2657 
2658     case MOVF:
2659         r = op_movfd (op0);
2660         WRITE_L (r);
2661         CC_IIZP_FP (r);
2662         break;
2663 
2664     case MOVD:
2665         if ((r = op_movfd (op0)) == 0)
2666             op1 = 0;
2667         WRITE_Q (r, op1);
2668         CC_IIZP_FP (r);
2669         break;
2670 
2671     case MOVG:
2672         if ((r = op_movg (op0)) == 0)
2673             op1 = 0;
2674         WRITE_Q (r, op1);
2675         CC_IIZP_FP (r);
2676         break;
2677 
2678     case MNEGF:
2679         r = op_mnegfd (op0);
2680         WRITE_L (r);
2681         CC_IIZZ_FP (r);
2682         break;
2683 
2684     case MNEGD:
2685         if ((r = op_mnegfd (op0)) == 0)
2686             op1 = 0;
2687         WRITE_Q (r, op1);
2688         CC_IIZZ_FP (r);
2689         break;
2690 
2691     case MNEGG:
2692         if ((r = op_mnegg (op0)) == 0)
2693             op1 = 0;
2694         WRITE_Q (r, op1);
2695         CC_IIZZ_FP (r);
2696         break;
2697 
2698     case CMPF:
2699         cc = op_cmpfd (op0, 0, op1, 0);
2700         break;
2701 
2702     case CMPD:
2703         cc = op_cmpfd (op0, op1, op2, op3);
2704         break;
2705 
2706     case CMPG:
2707         cc = op_cmpg (op0, op1, op2, op3);
2708         break;
2709 
2710     case CVTBF:
2711         r = op_cvtifdg (SXTB (op0), NULL, opc);
2712         WRITE_L (r);
2713         CC_IIZZ_FP (r);
2714         break;
2715 
2716     case CVTWF:
2717         r = op_cvtifdg (SXTW (op0), NULL, opc);
2718         WRITE_L (r);
2719         CC_IIZZ_FP (r);
2720         break;
2721 
2722     case CVTLF:
2723         r = op_cvtifdg (op0, NULL, opc);
2724         WRITE_L (r);
2725         CC_IIZZ_FP (r);
2726         break;
2727 
2728     case CVTBD: case CVTBG:
2729         r = op_cvtifdg (SXTB (op0), &rh, opc);
2730         WRITE_Q (r, rh);
2731         CC_IIZZ_FP (r);
2732         break;
2733 
2734     case CVTWD: case CVTWG:
2735         r = op_cvtifdg (SXTW (op0), &rh, opc);
2736         WRITE_Q (r, rh);
2737         CC_IIZZ_FP (r);
2738         break;
2739 
2740     case CVTLD: case CVTLG:
2741         r = op_cvtifdg (op0, &rh, opc);
2742         WRITE_Q (r, rh);
2743         CC_IIZZ_FP (r);
2744         break;
2745 
2746     case CVTFB: case CVTDB: case CVTGB:
2747         r = op_cvtfdgi (opnd, &flg, opc) & BMASK;
2748         WRITE_B (r);
2749         CC_IIZZ_B (r);
2750         if (flg) {
2751             V_INTOV;
2752             }
2753         break;
2754 
2755     case CVTFW: case CVTDW: case CVTGW:
2756         r = op_cvtfdgi (opnd, &flg, opc) & WMASK;
2757         WRITE_W (r);
2758         CC_IIZZ_W (r);
2759         if (flg) {
2760             V_INTOV;
2761             }
2762         break;
2763 
2764     case CVTFL: case CVTDL: case CVTGL:
2765     case CVTRFL: case CVTRDL: case CVTRGL:
2766         r = op_cvtfdgi (opnd, &flg, opc) & LMASK;
2767         WRITE_L (r);
2768         CC_IIZZ_L (r);
2769         if (flg) {
2770             V_INTOV;
2771             }
2772         break;
2773 
2774     case CVTFD:
2775         r = op_movfd (op0);
2776         WRITE_Q (r, 0);
2777         CC_IIZZ_FP (r);
2778         break;
2779 
2780     case CVTDF:
2781         r = op_cvtdf (opnd);
2782         WRITE_L (r);
2783         CC_IIZZ_FP (r);
2784         break;
2785 
2786     case CVTFG:
2787         r = op_cvtfg (opnd, &rh);
2788         WRITE_Q (r, rh);
2789         CC_IIZZ_FP (r);
2790         break;
2791 
2792     case CVTGF:
2793         r = op_cvtgf (opnd);
2794         WRITE_L (r);
2795         CC_IIZZ_FP (r);
2796         break;
2797 
2798     case ADDF2: case ADDF3:
2799         r = op_addf (opnd, FALSE);
2800         WRITE_L (r);
2801         CC_IIZZ_FP (r);
2802         break;
2803 
2804     case ADDD2: case ADDD3:
2805         r = op_addd (opnd, &rh, FALSE);
2806         WRITE_Q (r, rh);
2807         CC_IIZZ_FP (r);
2808         break;
2809 
2810     case ADDG2: case ADDG3:
2811         r = op_addg (opnd, &rh, FALSE);
2812         WRITE_Q (r, rh);
2813         CC_IIZZ_FP (r);
2814         break;
2815 
2816     case SUBF2: case SUBF3:
2817         r = op_addf (opnd, TRUE);
2818         WRITE_L (r);
2819         CC_IIZZ_FP (r);
2820         break;
2821 
2822     case SUBD2: case SUBD3:
2823         r = op_addd (opnd, &rh, TRUE);
2824         WRITE_Q (r, rh);
2825         CC_IIZZ_FP (r);
2826         break;
2827 
2828     case SUBG2: case SUBG3:
2829         r = op_addg (opnd, &rh, TRUE);
2830         WRITE_Q (r, rh);
2831         CC_IIZZ_FP (r);
2832         break;
2833 
2834     case MULF2: case MULF3:
2835         r = op_mulf (opnd);
2836         WRITE_L (r);
2837         CC_IIZZ_FP (r);
2838         break;
2839 
2840     case MULD2: case MULD3:
2841         r = op_muld (opnd, &rh);
2842         WRITE_Q (r, rh);
2843         CC_IIZZ_FP (r);
2844         break;
2845 
2846     case MULG2: case MULG3:
2847         r = op_mulg (opnd, &rh);
2848         WRITE_Q (r, rh);
2849         CC_IIZZ_FP (r);
2850         break;
2851 
2852     case DIVF2: case DIVF3:
2853         r = op_divf (opnd);
2854         WRITE_L (r);
2855         CC_IIZZ_FP (r);
2856         break;
2857 
2858     case DIVD2: case DIVD3:
2859         r = op_divd (opnd, &rh);
2860         WRITE_Q (r, rh);
2861         CC_IIZZ_FP (r);
2862         break;
2863 
2864     case DIVG2: case DIVG3:
2865         r = op_divg (opnd, &rh);
2866         WRITE_Q (r, rh);
2867         CC_IIZZ_FP (r);
2868         break;
2869 
2870     case ACBF:
2871         r = op_addf (opnd + 1, FALSE);                  /* add + index */
2872         temp = op_cmpfd (r, 0, op0, 0);                 /* result : limit */
2873         WRITE_L (r);                                    /* write result */
2874         CC_IIZP_FP (r);                                 /* set cc's */
2875         if ((temp & CC_Z) || ((op1 & FPSIGN)?           /* test br cond */
2876            !(temp & CC_N): (temp & CC_N)))
2877            BRANCHW (brdisp);
2878         break;
2879 
2880     case ACBD:
2881         r = op_addd (opnd + 2, &rh, FALSE);
2882         temp = op_cmpfd (r, rh, op0, op1);
2883         WRITE_Q (r, rh);
2884         CC_IIZP_FP (r);
2885         if ((temp & CC_Z) || ((op2 & FPSIGN)?           /* test br cond */
2886            !(temp & CC_N): (temp & CC_N)))
2887            BRANCHW (brdisp);
2888         break;
2889 
2890     case ACBG:
2891         r = op_addg (opnd + 2, &rh, FALSE);
2892         temp = op_cmpg (r, rh, op0, op1);
2893         WRITE_Q (r, rh);
2894         CC_IIZP_FP (r);
2895         if ((temp & CC_Z) || ((op2 & FPSIGN)?           /* test br cond */
2896            !(temp & CC_N): (temp & CC_N)))
2897            BRANCHW (brdisp);
2898         break;
2899 
2900 /* EMODF
2901 
2902         op0     =       multiplier
2903         op1     =       extension
2904         op2     =       multiplicand
2905         op3:op4 =       integer destination (int.wl)
2906         op5:op6 =       floating destination (flt.wl)
2907 */
2908 
2909     case EMODF:
2910         r = op_emodf (opnd, &temp, &flg);
2911         if (op5 < 0)
2912             Read (op6, L_LONG, WA);
2913         if (op3 >= 0)
2914             R[op3] = temp;
2915         else Write (op4, temp, L_LONG, WA);
2916         WRITE_L (r);
2917         CC_IIZZ_FP (r);
2918         if (flg) {
2919             V_INTOV;
2920             }
2921         break;
2922 
2923 /* EMODD, EMODG
2924 
2925         op0:op1 =       multiplier
2926         op2     =       extension
2927         op3:op4 =       multiplicand
2928         op5:op6 =       integer destination (int.wl)
2929         op7:op8 =       floating destination (flt.wq)
2930 */
2931 
2932     case EMODD:
2933         r = op_emodd (opnd, &rh, &temp, &flg);
2934         if (op7 < 0) {
2935             Read (op8, L_BYTE, WA);
2936             Read ((op8 + 7) & LMASK, L_BYTE, WA);
2937 			}
2938         if (op5 >= 0)
2939             R[op5] = temp;
2940         else Write (op6, temp, L_LONG, WA);
2941         WRITE_Q (r, rh);
2942         CC_IIZZ_FP (r);
2943         if (flg) {
2944             V_INTOV;
2945             }
2946         break;
2947 
2948     case EMODG:
2949         r = op_emodg (opnd, &rh, &temp, &flg);
2950         if (op7 < 0) {
2951             Read (op8, L_BYTE, WA);
2952             Read ((op8 + 7) & LMASK, L_BYTE, WA);
2953 			}
2954         if (op5 >= 0)
2955             R[op5] = temp;
2956         else Write (op6, temp, L_LONG, WA);
2957         WRITE_Q (r, rh);
2958         CC_IIZZ_FP (r);
2959         if (flg) {
2960             V_INTOV;
2961             }
2962         break;
2963 
2964 /* POLY */
2965 
2966     case POLYF:
2967         op_polyf (opnd, acc);
2968         CC_IIZZ_FP (R[0]);
2969         break;
2970 
2971     case POLYD:
2972         op_polyd (opnd, acc);
2973         CC_IIZZ_FP (R[0]);
2974         break;
2975 
2976     case POLYG:
2977         op_polyg (opnd, acc);
2978         CC_IIZZ_FP (R[0]);
2979         break;
2980 
2981 /* Operating system instructions */
2982 
2983     case CHMK: case CHME: case CHMS: case CHMU:
2984         cc = op_chm (opnd, cc, opc);                    /* CHMx */
2985         GET_CUR;                                        /* update cur mode */
2986         SET_IRQL;                                       /* update intreq */
2987         break;
2988 
2989     case REI:
2990         cc = op_rei (acc);                              /* REI */
2991         GET_CUR;                                        /* update cur mode */
2992         SET_IRQL;                                       /* update intreq */
2993         break;
2994 
2995     case LDPCTX:
2996         op_ldpctx (acc);
2997         break;
2998 
2999     case SVPCTX:
3000         op_svpctx (acc);
3001         break;
3002 
3003     case PROBER: case PROBEW:
3004         cc = (cc & CC_C) | op_probe (opnd, opc & 1);
3005         break;
3006 
3007     case MTPR:
3008         cc = (cc & CC_C) | op_mtpr (opnd);
3009         SET_IRQL;                                       /* update intreq */
3010         break;
3011 
3012     case MFPR:
3013         r = op_mfpr (opnd);
3014         WRITE_L (r);
3015         CC_IIZP_L (r);
3016         break;
3017 
3018 /* CIS or emulated instructions */
3019 
3020     case CVTPL:
3021     case MOVP: case CMPP3: case CMPP4: case CVTLP:
3022     case CVTPS: case CVTSP: case CVTTP: case CVTPT:
3023     case ADDP4: case ADDP6: case SUBP4: case SUBP6:
3024     case MULP: case DIVP: case ASHP: case CRC:
3025     case MOVTC: case MOVTUC: case MATCHC: case EDITPC:
3026         cc = op_cis (opnd, cc, opc, acc);
3027         break;
3028 
3029 /* Octaword or reserved instructions */
3030 
3031     case PUSHAO: case MOVAO: case CLRO: case MOVO:
3032     case TSTH: case MOVH: case MNEGH: case CMPH:
3033     case CVTBH: case CVTWH: case CVTLH:
3034     case CVTHB: case CVTHW: case CVTHL: case CVTRHL:
3035     case CVTFH: case CVTDH: case CVTGH:
3036     case CVTHF: case CVTHD: case CVTHG:
3037     case ADDH2: case ADDH3: case SUBH2: case SUBH3:
3038     case MULH2: case MULH3: case DIVH2: case DIVH3:
3039     case ACBH: case POLYH: case EMODH:
3040         cc = op_octa (opnd, cc, opc, acc, spec, va);
3041         if (cc & LSIGN) {                               /* ACBH branch? */
3042             BRANCHW (brdisp);
3043             cc = cc & CC_MASK;                          /* mask off flag */
3044             }
3045         break;
3046 
3047     default:
3048         RSVD_INST_FAULT;
3049         break;
3050         }                                               /* end case op */
3051     }                                                   /* end for */
3052 ABORT (STOP_UNKNOWN);
3053 }                                                       /* end sim_instr */
3054 
3055 /* Prefetch buffer routine
3056 
3057    Prefetch buffer state
3058 
3059         ibufl, ibufh    =       the prefetch buffer
3060         ibcnt           =       number of bytes available (0, 4, 8)
3061         ppc             =       physical PC
3062 
3063    The get_istr routines fetches the indicated number of bytes from
3064    the prefetch buffer.  Although it is complicated, it is faster
3065    than calling Read on every byte of the instruction stream.
3066 
3067    If the prefetch buffer has enough bytes, the required bytes are
3068    extracted from the prefetch buffer and returned. If it does not
3069    have enough bytes, enough prefetch words are fetched until there
3070    are.  A longword is only prefetched if data is needed from it,
3071    so any translation errors are real.
3072 */
3073 
get_istr(int32 lnt,int32 acc)3074 SIM_INLINE int32 get_istr (int32 lnt, int32 acc)
3075 {
3076 int32 bo = PC & 3;
3077 int32 sc, val, t;
3078 
3079 while ((bo + lnt) > ibcnt) {                            /* until enuf bytes */
3080     if ((ppc < 0) || (VA_GETOFF (ppc) == 0)) {          /* PPC inv, xpg? */
3081         ppc = Test ((PC + ibcnt) & ~03, RD, &t);        /* xlate PC */
3082         if (ppc < 0)
3083             Read ((PC + ibcnt) & ~03, L_LONG, RA);
3084         }
3085     if (ibcnt == 0)                                     /* fill low */
3086         ibufl = ReadLP (ppc);
3087     else ibufh = ReadLP (ppc);                          /* or high */
3088     ppc = ppc + 4;                                      /* incr phys PC */
3089     ibcnt = ibcnt + 4;                                  /* incr ibuf cnt */
3090     }
3091 PC = PC + lnt;                                          /* incr PC */
3092 if (lnt == L_BYTE)                                      /* byte? */
3093     val = (ibufl >> (bo << 3)) & BMASK;
3094 else if (lnt == L_WORD) {                               /* word? */
3095     if (bo == 3)
3096         val = ((ibufl >> 24) & 0xFF) | ((ibufh & 0xFF) << 8);
3097     else val = (ibufl >> (bo << 3)) & WMASK;
3098     }
3099 else if (bo) {                                          /* unaligned lw? */
3100     sc = bo << 3;
3101     val =  (((ibufl >> sc) & align[bo]) | (((uint32) ibufh) << (32 - sc)));
3102     }
3103 else val = ibufl;                                       /* aligned lw */
3104 if ((bo + lnt) >= 4) {                                  /* retire ibufl? */
3105     ibufl = ibufh;
3106     ibcnt = ibcnt - 4;
3107     }
3108 return val;
3109 }
3110 
3111 /* Read octaword specifier */
3112 
ReadOcta(int32 va,int32 * opnd,int32 j,int32 acc)3113 int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc)
3114 {
3115 opnd[j++] = Read (va, L_LONG, acc);
3116 opnd[j++] = Read (va + 4, L_LONG, acc);
3117 opnd[j++] = Read (va + 8, L_LONG, acc);
3118 opnd[j++] = Read (va + 12, L_LONG, acc);
3119 return j;
3120 }
3121 
3122 /* Schedule idle before the next instruction */
3123 
cpu_idle(void)3124 void cpu_idle (void)
3125 {
3126 sim_activate_abs (&cpu_unit, 0);
3127 return;
3128 }
3129 
3130 /* Idle service */
3131 
cpu_idle_svc(UNIT * uptr)3132 t_stat cpu_idle_svc (UNIT *uptr)
3133 {
3134 if (sim_idle_enab)
3135     sim_idle (TMR_CLK, FALSE);
3136 return SCPE_OK;
3137 }
3138 
3139 /* Reset */
3140 
cpu_reset(DEVICE * dptr)3141 t_stat cpu_reset (DEVICE *dptr)
3142 {
3143 hlt_pin = 0;
3144 mem_err = 0;
3145 crd_err = 0;
3146 PSL = PSL_IS | PSL_IPL1F;
3147 SISR = 0;
3148 ASTLVL = 4;
3149 mapen = 0;
3150 FLUSH_ISTR;                                             /* init I-stream */
3151 if (M == NULL) {                                        /* first time init? */
3152     sim_brk_types = sim_brk_dflt = SWMASK ('E');
3153     pcq_r = find_reg ("PCQ", NULL, dptr);
3154     if (pcq_r == NULL)
3155         return SCPE_IERR;
3156     pcq_r->qptr = 0;
3157     M = (uint32 *) calloc (((uint32) MEMSIZE) >> 2, sizeof (uint32));
3158     if (M == NULL)
3159         return SCPE_MEM;
3160     }
3161 return build_dib_tab ();
3162 }
3163 
3164 /* Memory examine */
3165 
cpu_ex(t_value * vptr,t_addr exta,UNIT * uptr,int32 sw)3166 t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
3167 {
3168 int32 st;
3169 uint32 addr = (uint32) exta;
3170 
3171 if (vptr == NULL)
3172     return SCPE_ARG;
3173 if (sw & SWMASK ('V')) {
3174     int32 acc = cpu_get_vsw (sw);
3175     addr = Test (addr, acc, &st);
3176     }
3177 else addr = addr & PAMASK;
3178 if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) ||
3179     ADDR_IS_ROM (addr) || ADDR_IS_NVR (addr)) {
3180     *vptr = (uint32) ReadB (addr);
3181     return SCPE_OK;
3182     }
3183 return SCPE_NXM;
3184 }
3185 
3186 /* Memory deposit */
3187 
cpu_dep(t_value val,t_addr exta,UNIT * uptr,int32 sw)3188 t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
3189 {
3190 int32 st;
3191 uint32 addr = (uint32) exta;
3192 
3193 if (sw & SWMASK ('V')) {
3194     int32 acc = cpu_get_vsw (sw);
3195     addr = Test (addr, acc, &st);
3196     }
3197 else addr = addr & PAMASK;
3198 if (ADDR_IS_MEM (addr) || ADDR_IS_CDG (addr) ||
3199     ADDR_IS_NVR (addr)) {
3200     WriteB (addr, (int32) val);
3201     return SCPE_OK;
3202     }
3203 if (ADDR_IS_ROM (addr)) {
3204     rom_wr_B (addr, (int32) val);
3205     return SCPE_OK;
3206     }
3207 return SCPE_NXM;
3208 }
3209 
3210 /* Memory allocation */
3211 
cpu_set_size(UNIT * uptr,int32 val,char * cptr,void * desc)3212 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
3213 {
3214 int32 mc = 0;
3215 uint32 i, clim;
3216 uint32 *nM = NULL;
3217 
3218 if ((val <= 0) || (val > MAXMEMSIZE_X))
3219     return SCPE_ARG;
3220 for (i = val; i < MEMSIZE; i = i + 4)
3221     mc = mc | M[i >> 2];
3222 if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE))
3223     return SCPE_OK;
3224 nM = (uint32 *) calloc (val >> 2, sizeof (uint32));
3225 if (nM == NULL)
3226     return SCPE_MEM;
3227 clim = (uint32) ((((uint32) val) < MEMSIZE)? val: MEMSIZE);
3228 for (i = 0; i < clim; i = i + 4)
3229     nM[i >> 2] = M[i >> 2];
3230 free (M);
3231 M = nM;
3232 MEMSIZE = val;
3233 return SCPE_OK;
3234 }
3235 
3236 /* Virtual address translation */
3237 
cpu_show_virt(FILE * of,UNIT * uptr,int32 val,void * desc)3238 t_stat cpu_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc)
3239 {
3240 t_stat r;
3241 char *cptr = (char *) desc;
3242 uint32 va, pa;
3243 int32 st;
3244 static const char *mm_str[] = {
3245     "Access control violation",
3246     "Length violation",
3247     "Process PTE access control violation",
3248     "Process PTE length violation",
3249     "Translation not valid",
3250     "Internal error",
3251     "Process PTE translation not valid"
3252     };
3253 
3254 if (cptr) {
3255     va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r);
3256     if (r == SCPE_OK) {
3257         int32 acc = cpu_get_vsw (sim_switches);
3258         pa = Test (va, acc, &st);
3259         if (st == PR_OK)
3260             fprintf (of, "Virtual %-X = physical %-X\n", va, pa);
3261         else fprintf (of, "Virtual %-X: %s\n", va, mm_str[st]);
3262         return SCPE_OK;
3263         }
3264     }
3265 fprintf (of, "Invalid argument\n");
3266 return SCPE_OK;
3267 }
3268 
3269 /* Get access mode for examine, deposit, show virtual */
3270 
cpu_get_vsw(int32 sw)3271 int32 cpu_get_vsw (int32 sw)
3272 {
3273 int32 md;
3274 
3275 set_map_reg ();                                         /* update dyn reg */
3276 if (sw & SWMASK ('K'))
3277     md = KERN;
3278 else if (sw & SWMASK ('E'))
3279     md = EXEC;
3280 else if (sw & SWMASK ('S'))
3281     md = SUPV;
3282 else if (sw & SWMASK ('U'))
3283     md = USER;
3284 else md = PSL_GETCUR (PSL);
3285 return ACC_MASK (md);
3286 }
3287 
3288 /* Set history */
3289 
cpu_set_hist(UNIT * uptr,int32 val,char * cptr,void * desc)3290 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
3291 {
3292 int32 i, lnt;
3293 t_stat r;
3294 
3295 if (cptr == NULL) {
3296     for (i = 0; i < hst_lnt; i++)
3297         hst[i].iPC = 0;
3298     hst_p = 0;
3299     return SCPE_OK;
3300     }
3301 lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
3302 if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN)))
3303     return SCPE_ARG;
3304 hst_p = 0;
3305 if (hst_lnt) {
3306     free (hst);
3307     hst_lnt = 0;
3308     hst = NULL;
3309     }
3310 if (lnt) {
3311     hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
3312     if (hst == NULL)
3313             return SCPE_MEM;
3314     hst_lnt = lnt;
3315     }
3316 return SCPE_OK;
3317 }
3318 
3319 /* Show history */
3320 
cpu_show_hist(FILE * st,UNIT * uptr,int32 val,void * desc)3321 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
3322 {
3323 int32 i, k, di, lnt, numspec;
3324 char *cptr = (char *) desc;
3325 t_stat r;
3326 InstHistory *h;
3327 extern const char *opcode[];
3328 extern t_value *sim_eval;
3329 extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
3330     UNIT *uptr, int32 sw);
3331 
3332 if (hst_lnt == 0)                                       /* enabled? */
3333     return SCPE_NOFNC;
3334 if (cptr) {
3335     lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
3336     if ((r != SCPE_OK) || (lnt == 0))
3337         return SCPE_ARG;
3338     }
3339 else lnt = hst_lnt;
3340 di = hst_p - lnt;                                       /* work forward */
3341 if (di < 0)
3342     di = di + hst_lnt;
3343 fprintf (st, "PC       PSL       IR\n\n");
3344 for (k = 0; k < lnt; k++) {                             /* print specified */
3345     h = &hst[(di++) % hst_lnt];                         /* entry pointer */
3346     if (h->iPC == 0)                                    /* filled in? */
3347         continue;
3348     fprintf(st, "%08X %08X| ", h->iPC, h->PSL);         /* PC, PSL */
3349     numspec = drom[h->opc][0] & DR_NSPMASK;             /* #specifiers */
3350     if (opcode[h->opc] == NULL)                         /* undefined? */
3351         fprintf (st, "%03X (undefined)", h->opc);
3352     else if (h->PSL & PSL_FPD)                          /* FPD set? */
3353         fprintf (st, "%s FPD set", opcode[h->opc]);
3354     else {                                              /* normal */
3355         for (i = 0; i < INST_SIZE; i++)
3356             sim_eval[i] = h->inst[i];
3357         if ((fprint_sym (st, h->iPC, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
3358             fprintf (st, "%03X (undefined)", h->opc);
3359         if ((numspec > 1) ||
3360             ((numspec == 1) && (drom[h->opc][1] < BB))) {
3361             if (cpu_show_opnd (st, h, 0)) {             /* operands; more? */
3362                 if (cpu_show_opnd (st, h, 1)) {         /* 2nd line; more? */
3363                     cpu_show_opnd (st, h, 2);           /* octa, 3rd/4th */
3364                     cpu_show_opnd (st, h, 3);
3365                     }
3366                 }
3367             }
3368         }                                               /* end else */
3369     fputc ('\n', st);                                   /* end line */
3370     }                                                   /* end for */
3371 return SCPE_OK;
3372 }
3373 
cpu_show_opnd(FILE * st,InstHistory * h,int32 line)3374 t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line)
3375 {
3376 
3377 int32 numspec, i, j, disp;
3378 t_bool more;
3379 
3380 numspec = drom[h->opc][0] & DR_NSPMASK;                 /* #specifiers */
3381 fputs ("\n                  ", st);                     /* space */
3382 for (i = 1, j = 0, more = FALSE; i <= numspec; i++) {   /* loop thru specs */
3383     disp = drom[h->opc][i];                             /* specifier type */
3384     if (disp == RG)                                     /* fix specials */
3385         disp = RQ;
3386     else if (disp >= BB)
3387         break;                         /* ignore branches */
3388     else switch (disp & (DR_LNMASK|DR_ACMASK)) {
3389 
3390     case RB: case RW: case RL:                          /* read */
3391     case AB: case AW: case AL: case AQ: case AO:        /* address */
3392     case MB: case MW: case ML:                          /* modify */
3393         if (line == 0)
3394             fprintf (st, " %08X", h->opnd[j]);
3395         else fputs ("         ", st);
3396         j = j + 1;
3397         break;
3398     case RQ: case MQ:                                   /* read, modify quad */
3399         if (line <= 1)
3400             fprintf (st, " %08X", h->opnd[j + line]);
3401         else fputs ("         ", st);
3402         if (line == 0)
3403             more = TRUE;
3404         j = j + 2;
3405         break;
3406     case RO: case MO:                                   /* read, modify octa */
3407         fprintf (st, " %08X", h->opnd[j + line]);
3408         more = TRUE;
3409         j = j + 4;
3410         break;
3411     case WB: case WW: case WL: case WQ: case WO:        /* write */
3412         if (line == 0)
3413             fprintf (st, " %08X", h->opnd[j + 1]);
3414         else fputs ("         ", st);
3415         j = j + 2;
3416         break;
3417         }                                       /* end case */
3418     }                                           /* end for */
3419 return more;
3420 }
3421 
3422 struct os_idle {
3423     char        *name;
3424     uint32      mask;
3425     };
3426 
3427 static struct os_idle os_tab[] = {
3428     { "VMS", VAX_IDLE_VMS },
3429     { "NETBSD", VAX_IDLE_ULTOLD },
3430     { "ULTRIX", VAX_IDLE_ULT },
3431     { "ULTRIXOLD", VAX_IDLE_ULTOLD },
3432     { "OPENBSD", VAX_IDLE_QUAD },
3433     { "QUASIJARUS", VAX_IDLE_QUAD },
3434     { "32V", VAX_IDLE_QUAD },
3435     { "ALL", VAX_IDLE_VMS|VAX_IDLE_ULTOLD|VAX_IDLE_ULT|VAX_IDLE_QUAD },
3436     { NULL, 0 }
3437     };
3438 
3439 /* Set and show idle */
3440 
cpu_set_idle(UNIT * uptr,int32 val,char * cptr,void * desc)3441 t_stat cpu_set_idle (UNIT *uptr, int32 val, char *cptr, void *desc)
3442 {
3443 uint32 i;
3444 
3445 if (cptr != NULL) {
3446     for (i = 0; os_tab[i].name != NULL; i++) {
3447         if (strcmp (os_tab[i].name, cptr) == 0) {
3448             cpu_idle_type = i + 1;
3449             cpu_idle_mask = os_tab[i].mask;
3450             return sim_set_idle (uptr, val, NULL, desc);
3451             }
3452         }
3453     return SCPE_ARG;
3454     }
3455 return sim_set_idle (uptr, val, cptr, desc);
3456 }
3457 
cpu_show_idle(FILE * st,UNIT * uptr,int32 val,void * desc)3458 t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc)
3459 {
3460 if (sim_idle_enab && (cpu_idle_type != 0)) {
3461     fprintf (st, "idle=%s, ", os_tab[cpu_idle_type - 1].name);
3462     sim_show_idle (st, uptr, val, desc);
3463     }
3464 else fprintf (st, "idle disabled");
3465 return SCPE_OK;
3466 }
3467