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