3 Copyright (c) 1998-2008, Robert M Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
26 cpu VAX central processor
28 28-May-08 RMS Inlined instruction prefetch, physical memory routines
29 13-Aug-07 RMS Fixed bug in read access g-format indexed specifiers
30 28-Apr-07 RMS Removed clock initialization
31 29-Oct-06 RMS Added idle support
32 22-May-06 RMS Fixed format error in CPU history (found by Peter Schorn)
33 10-May-06 RMS Added -kesu switches for virtual addressing modes
34 Fixed bugs in examine virtual
35 Rewrote history function for greater usability
36 Fixed bug in reported VA on faulting cross-page write
37 02-May-06 RMS Fixed fault cleanup to clear PSL<tp>
38 Fixed ADAWI r-mode to preserve dst<31:16>
39 Fixed ACBD/G to test correct operand
40 Fixed access checking on modify-class specifiers
41 Fixed branch displacements in history buffer
42 (all reported by Tim Stark)
43 17-Nov-05 RMS Fixed CVTfi with integer overflow to trap if PSW<iv> set
44 13-Nov-05 RMS Fixed breakpoint test with 64b addresses
45 25-Oct-05 RMS Removed cpu_extmem
46 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
47 16-Aug-05 RMS Fixed C++ declaration and cast problems
48 13-Jan-05 RMS Fixed initial state of cpu_extmem
49 06-Nov-04 RMS Added =n to SHOW HISTORY
50 30-Sep-04 RMS Added octaword specifier decodes and instructions
51 Moved model-specific routines to system module
52 02-Sep-04 RMS Fixed bug in EMODD/G, second word of quad dst not probed
53 28-Jun-04 RMS Fixed bug in DIVBx, DIVWx (reported by Peter Trimmel)
54 18-Apr-04 RMS Added octaword macros
55 25-Jan-04 RMS Removed local debug logging support
56 RMS,MP Added extended physical memory support
57 31-Dec-03 RMS Fixed bug in set_cpu_hist
58 21-Dec-03 RMS Added autoconfiguration controls
59 29-Oct-03 RMS Fixed WriteB declaration (found by Mark Pizzolato)
60 23-Sep-03 RMS Revised instruction history for dynamic sizing
61 17-May-03 RMS Fixed operand order in EMODx
62 23-Apr-03 RMS Revised for 32b/64b t_addr
63 05-Jan-02 RMS Added memory size restore support
64 25-Dec-02 RMS Added instruction history (from Mark Pizzolato)
65 29-Sep-02 RMS Revised to build dib_tab dynamically
66 14-Jul-02 RMS Added halt to console, infinite loop detection
68 02-May-02 RMS Fixed bug in indexed autoincrement register logging
69 30-Apr-02 RMS Added TODR powerup routine
70 18-Apr-02 RMS Cleanup ambiguous signed left shifts
71 15-Apr-02 RMS Fixed bug in CASEL condition codes
73 The register state for the VAX is:
75 R[0:15] general registers
76 PSL<31:0> processor status longword
78 FPD<27> first part done
79 IS<26> interrupt stack
80 CM<25:24> current mode
81 PM<23:22> previous mode
82 IPL<20:16> interrupt priority level
83 PSW<15:0> non-privileged processor status word
84 DV<7> decimal overflow trap enable
85 FU<6> floating underflow fault enable
86 IV<5> integer overflow trap enable
87 T<4> trace trap enable
88 CC<3:0> condition codes
89 SCBB system control block base
90 PCBB process control block base
91 SBR system page table base
92 SLR system page table length
93 P0BR process region 0 page table base
94 P0LR process region 0 page table length
95 P1BR process region 1 page table base
96 P1LR process region 1 page table length
97 SIRR/SISR software interrupt request/summary register
98 ASTLVL AST level register
100 The VAX has a variable length instruction format with up to six operands:
107 Each operand specifier is a byte consisting of an addressing mode, a
108 register, and possibly 1-8 bytes of extension:
110 number name extension mnemonic operation
112 0-3 short literal - #n op <- specifier
113 4 index - [Rn] index by Rn
114 5 register - Rn op <- Rn
115 6 register def - (Rn) op <- M[Rn]
116 7 autodecrement - -(Rn) Rn <- Rn - length
118 8 autoincrement - (Rn)+ op <- M[Rn]
120 9 auto deferred - @(Rn)+ op <- M[M[Rn]]
122 A byte displ byte d d(Rn) op <- M[Rn + sxt.d]
123 B byte displ def byte d @d(Rn) op <- M[M[Rn + sxt.d]]
124 C word displ word d d(Rn) op <- M[Rn + sxt.d]
125 D word displ def word d @d(Rn) op <- M[M[Rn + sxt.d]]
126 E long displ long d d(Rn) op <- M[Rn + d]
127 F long displ def long d @d(Rn) op <- M[M[Rn + d]]
129 When the general register is the PC, certain modes are forbidden, and
130 others have special interpretations:
134 6F register def fault
135 7F autodecrement fault
136 8F immediate 1-8B #imm op <- imm
137 9 absolute 4B @#imm op <- M[imm]
138 A byte relative byte d d(Rn) op <- M[PC + sxt.d]
139 B byte rel def byte d @d(Rn) op <- M[M[PC + sxt.d]]
140 C word relative word d d(Rn) op <- M[PC + sxt.d]
141 D word rel def word d @d(Rn) op <- M[M[PC + sxt.d]]
142 E long relative long d d(Rn) op <- M[PC + d]
143 F long rel def long d @d(Rn) op <- M[M[PC + d]]
145 This routine is the instruction decode routine for the VAX. It
146 is called from the simulator control program to execute instructions
147 in simulated memory, starting at the simulated PC. It runs until an
148 enabled exception is encountered.
152 1. Traps and interrupts. Variable trpirq microencodes the outstanding
153 trap request (if any) and the level of the highest outstanding
156 2. Interrupt requests are maintained in the int_req array, one word per
157 interrupt level, one bit per device.
159 3. Adding I/O devices. These modules must be modified:
161 vax_defs.h add device address and interrupt definitions
162 vax_sys.c add sim_devices table entry
167 #include "vax_defs.h"
170 #define UNIT_V_CONH (UNIT_V_UF + 0) /* halt to console */
171 #define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy */
172 #define UNIT_CONH (1u << UNIT_V_CONH)
173 #define UNIT_MSIZE (1u << UNIT_V_MSIZE)
174 #define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL))
187 #define CHECK_FOR_PC if (rn == nPC) RSVD_ADDR_FAULT
188 #define CHECK_FOR_SP if (rn >= nSP) RSVD_ADDR_FAULT
189 #define CHECK_FOR_AP if (rn >= nAP) RSVD_ADDR_FAULT
190 #define WRITE_B(r) if (spec > (GRN | nPC)) Write (va, r, L_BYTE, WA); \
191 else R[rn] = (R[rn] & ~BMASK) | ((r) & BMASK)
192 #define WRITE_W(r) if (spec > (GRN | nPC)) Write (va, r, L_WORD, WA); \
193 else R[rn] = (R[rn] & ~WMASK) | ((r) & WMASK)
194 #define WRITE_L(r) if (spec > (GRN | nPC)) Write (va, r, L_LONG, WA); \
196 #define WRITE_Q(rl,rh) if (spec > (GRN | nPC)) { \
197 if ((Test (va + 7, WA, &mstat) >= 0) || \
198 (Test (va, WA, &mstat) < 0)) \
199 Write (va, rl, L_LONG, WA); \
200 Write (va + 4, rh, L_LONG, WA); \
203 if (rn >= nSP) RSVD_ADDR_FAULT; \
209 #define HIST_MAX 65536
215 uint8 inst
[INST_SIZE
];
216 int32 opnd
[OPND_SIZE
];
219 uint32
*M
= NULL
; /* memory */
220 int32 R
[16]; /* registers */
221 int32 STK
[5]; /* stack pointers */
223 int32 SCBB
= 0; /* SCB base */
224 int32 PCBB
= 0; /* PCB base */
225 int32 P0BR
= 0; /* P0 mem mgt */
227 int32 P1BR
= 0; /* P1 mem mgt */
229 int32 SBR
= 0; /* S0 mem mgt */
231 int32 SISR
; /* swre int req */
232 int32 ASTLVL
; /* AST level */
233 int32 mapen
; /* map enable */
234 int32 pme
; /* perf mon enable */
235 int32 trpirq
; /* trap/intr req */
236 int32 in_ie
= 0; /* in exc, int */
237 int32 recq
[6]; /* recovery queue */
238 int32 recqptr
; /* recq pointer */
239 int32 hlt_pin
= 0; /* HLT pin intr */
242 int32 p1
= 0, p2
= 0; /* fault parameters */
243 int32 fault_PC
; /* fault PC */
244 int32 pcq_p
= 0; /* PC queue ptr */
245 int32 hst_p
= 0; /* history pointer */
246 int32 hst_lnt
= 0; /* history length */
249 int32 mchk_va
, mchk_ref
; /* mem ref param */
250 int32 ibufl
, ibufh
; /* prefetch buf */
251 int32 ibcnt
, ppc
; /* prefetch ctl */
252 uint32 cpu_idle_ipl_mask
= 0x8; /* idle if on IPL 3 */
253 uint32 cpu_idle_type
= 1; /* default to VMS */
254 int32 cpu_idle_wait
= 1000; /* for these cycles */
256 REG
*pcq_r
= NULL
; /* PC queue reg ptr */
257 int32 pcq
[PCQ_SIZE
] = { 0 }; /* PC queue */
258 InstHistory
*hst
= NULL
; /* instruction history */
260 const uint32 byte_mask
[33] = { 0x00000000,
261 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
262 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
263 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
264 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
265 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
266 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
267 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
268 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
270 const uint32 byte_sign
[33] = { 0x00000000,
271 0x00000001, 0x00000002, 0x00000004, 0x00000008,
272 0x00000010, 0x00000020, 0x00000040, 0x00000080,
273 0x00000100, 0x00000200, 0x00000400, 0x00000800,
274 0x00001000, 0x00002000, 0x00004000, 0x00008000,
275 0x00010000, 0x00020000, 0x00040000, 0x00080000,
276 0x00100000, 0x00200000, 0x00400000, 0x00800000,
277 0x01000000, 0x02000000, 0x04000000, 0x08000000,
278 0x10000000, 0x20000000, 0x40000000, 0x80000000
280 const uint32 align
[4] = {
281 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF
284 /* External and forward references */
286 extern int32 sim_interval
;
287 extern int32 sim_int_char
;
288 extern int32 sim_switches
;
289 extern uint32 sim_brk_types
, sim_brk_dflt
, sim_brk_summ
; /* breakpoint info */
290 extern t_bool sim_idle_enab
;
292 extern t_stat
build_dib_tab (void);
293 extern UNIT rom_unit
, nvr_unit
;
294 extern int32
op_ashq (int32
*opnd
, int32
*rh
, int32
*flg
);
295 extern int32
op_emul (int32 mpy
, int32 mpc
, int32
*rh
);
296 extern int32
op_ediv (int32
*opnd
, int32
*rh
, int32
*flg
);
297 extern int32
op_bb_n (int32
*opnd
, int32 acc
);
298 extern int32
op_bb_x (int32
*opnd
, int32 newb
, int32 acc
);
299 extern int32
op_extv (int32
*opnd
, int32 vfldrp1
, int32 acc
);
300 extern int32
op_ffs (uint32 fld
, int32 size
);
301 extern void op_insv (int32
*opnd
, int32 vfldrp1
, int32 acc
);
302 extern int32
op_call (int32
*opnd
, t_bool gs
, int32 acc
);
303 extern int32
op_ret (int32 acc
);
304 extern int32
op_insque (int32
*opnd
, int32 acc
);
305 extern int32
op_remque (int32
*opnd
, int32 acc
);
306 extern int32
op_insqhi (int32
*opnd
, int32 acc
);
307 extern int32
op_insqti (int32
*opnd
, int32 acc
);
308 extern int32
op_remqhi (int32
*opnd
, int32 acc
);
309 extern int32
op_remqti (int32
*opnd
, int32 acc
);
310 extern void op_pushr (int32
*opnd
, int32 acc
);
311 extern void op_popr (int32
*opnd
, int32 acc
);
312 extern int32
op_movc (int32
*opnd
, int32 opc
, int32 acc
);
313 extern int32
op_cmpc (int32
*opnd
, int32 opc
, int32 acc
);
314 extern int32
op_locskp (int32
*opnd
, int32 opc
, int32 acc
);
315 extern int32
op_scnspn (int32
*opnd
, int32 opc
, int32 acc
);
316 extern int32
op_chm (int32
*opnd
, int32 cc
, int32 opc
);
317 extern int32
op_rei (int32 acc
);
318 extern void op_ldpctx (int32 acc
);
319 extern void op_svpctx (int32 acc
);
320 extern int32
op_probe (int32
*opnd
, int32 opc
);
321 extern int32
op_mtpr (int32
*opnd
);
322 extern int32
op_mfpr (int32
*opnd
);
323 extern int32
op_movfd (int32 val
);
324 extern int32
op_movg (int32 val
);
325 extern int32
op_mnegfd (int32 val
);
326 extern int32
op_mnegg (int32 val
);
327 extern int32
op_cmpfd (int32 h1
, int32 l1
, int32 h2
, int32 l2
);
328 extern int32
op_cmpg (int32 h1
, int32 l1
, int32 h2
, int32 l2
);
329 extern int32
op_cvtifdg (int32 val
, int32
*rh
, int32 opc
);
330 extern int32
op_cvtfdgi (int32
*opnd
, int32
*flg
, int32 opc
);
331 extern int32
op_cvtdf (int32
*opnd
);
332 extern int32
op_cvtgf (int32
*opnd
);
333 extern int32
op_cvtfg (int32
*opnd
, int32
*rh
);
334 extern int32
op_cvtgh (int32
*opnd
, int32
*hflt
);
335 extern int32
op_addf (int32
*opnd
, t_bool sub
);
336 extern int32
op_addd (int32
*opnd
, int32
*rh
, t_bool sub
);
337 extern int32
op_addg (int32
*opnd
, int32
*rh
, t_bool sub
);
338 extern int32
op_mulf (int32
*opnd
);
339 extern int32
op_muld (int32
*opnd
, int32
*rh
);
340 extern int32
op_mulg (int32
*opnd
, int32
*rh
);
341 extern int32
op_divf (int32
*opnd
);
342 extern int32
op_divd (int32
*opnd
, int32
*rh
);
343 extern int32
op_divg (int32
*opnd
, int32
*rh
);
344 extern int32
op_emodf (int32
*opnd
, int32
*intgr
, int32
*flg
);
345 extern int32
op_emodd (int32
*opnd
, int32
*rh
, int32
*intgr
, int32
*flg
);
346 extern int32
op_emodg (int32
*opnd
, int32
*rh
, int32
*intgr
, int32
*flg
);
347 extern void op_polyf (int32
*opnd
, int32 acc
);
348 extern void op_polyd (int32
*opnd
, int32 acc
);
349 extern void op_polyg (int32
*opnd
, int32 acc
);
350 extern int32
op_cmode (int32 cc
);
351 extern int32
op_cis (int32
*opnd
, int32 cc
, int32 opc
, int32 acc
);
352 extern int32
op_octa (int32
*opnd
, int32 cc
, int32 opc
, int32 acc
, int32 spec
, int32 va
);
353 extern int32
intexc (int32 vec
, int32 cc
, int32 ipl
, int ei
);
354 extern int32
Test (uint32 va
, int32 acc
, int32
*status
);
355 extern int32
BadCmPSL (int32 newpsl
);
356 extern int32
eval_int (void);
357 extern int32
get_vector (int32 lvl
);
358 extern void set_map_reg (void);
359 extern void rom_wr_B (int32 pa
, int32 val
);
360 extern int32
machine_check (int32 p1
, int32 opc
, int32 cc
, int32 delta
);
361 extern const uint16 drom
[NUM_INST
][MAX_SPEC
+ 1];
362 extern t_stat
cpu_boot (int32 unitno
, DEVICE
*dptr
);
363 extern int32
con_halt (int32 code
, int32 cc
);
365 t_stat
cpu_reset (DEVICE
*dptr
);
366 t_stat
cpu_ex (t_value
*vptr
, t_addr exta
, UNIT
*uptr
, int32 sw
);
367 t_stat
cpu_dep (t_value val
, t_addr exta
, UNIT
*uptr
, int32 sw
);
368 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
369 t_stat
cpu_set_hist (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
370 t_stat
cpu_show_hist (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
371 t_stat
cpu_show_virt (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
372 t_stat
cpu_set_idle (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
373 t_stat
cpu_show_idle (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
374 int32
cpu_get_vsw (int32 sw
);
375 SIM_INLINE int32
get_istr (int32 lnt
, int32 acc
);
376 int32
ReadOcta (int32 va
, int32
*opnd
, int32 j
, int32 acc
);
377 t_bool
cpu_show_opnd (FILE *st
, InstHistory
*h
, int32 line
);
378 int32
cpu_psl_ipl_idle (int32 newpsl
);
379 t_stat
cpu_idle_svc (UNIT
*uptr
);
381 /* CPU data structures
383 cpu_dev CPU device descriptor
385 cpu_reg CPU register list
386 cpu_mod CPU modifier list
390 UDATA (&cpu_idle_svc
, UNIT_FIX
|UNIT_BINK
, INITMEMSIZE
)
394 { HRDATA (PC
, R
[nPC
], 32) },
395 { HRDATA (R0
, R
[0], 32) },
396 { HRDATA (R1
, R
[1], 32) },
397 { HRDATA (R2
, R
[2], 32) },
398 { HRDATA (R3
, R
[3], 32) },
399 { HRDATA (R4
, R
[4], 32) },
400 { HRDATA (R5
, R
[5], 32) },
401 { HRDATA (R6
, R
[6], 32) },
402 { HRDATA (R7
, R
[7], 32) },
403 { HRDATA (R8
, R
[8], 32) },
404 { HRDATA (R9
, R
[9], 32) },
405 { HRDATA (R10
, R
[10], 32) },
406 { HRDATA (R11
, R
[11], 32) },
407 { HRDATA (R12
, R
[12], 32) },
408 { HRDATA (R13
, R
[13], 32) },
409 { HRDATA (R14
, R
[14], 32) },
410 { HRDATA (AP
, R
[nAP
], 32) },
411 { HRDATA (FP
, R
[nFP
], 32) },
412 { HRDATA (SP
, R
[nSP
], 32) },
413 { HRDATA (PSL
, PSL
, 32) },
414 { HRDATA (CC
, PSL
, 4) },
415 { HRDATA (KSP
, KSP
, 32) },
416 { HRDATA (ESP
, ESP
, 32) },
417 { HRDATA (SSP
, SSP
, 32) },
418 { HRDATA (USP
, USP
, 32) },
419 { HRDATA (IS
, IS
, 32) },
420 { HRDATA (SCBB
, SCBB
, 32) },
421 { HRDATA (PCBB
, PCBB
, 32) },
422 { HRDATA (P0BR
, P0BR
, 32) },
423 { HRDATA (P0LR
, P0LR
, 22) },
424 { HRDATA (P1BR
, P1BR
, 32) },
425 { HRDATA (P1LR
, P1LR
, 22) },
426 { HRDATA (SBR
, SBR
, 32) },
427 { HRDATA (SLR
, SLR
, 22) },
428 { HRDATA (SISR
, SISR
, 16) },
429 { HRDATA (ASTLVL
, ASTLVL
, 4) },
430 { FLDATA (MAPEN
, mapen
, 0) },
431 { FLDATA (PME
, pme
, 0) },
432 { HRDATA (TRPIRQ
, trpirq
, 8) },
433 { FLDATA (CRDERR
, crd_err
, 0) },
434 { FLDATA (MEMERR
, mem_err
, 0) },
435 { FLDATA (HLTPIN
, hlt_pin
, 0) },
436 { HRDATA (IDLE_IPL
, cpu_idle_ipl_mask
, 16), REG_HIDDEN
},
437 { DRDATA (IDLE_TYPE
, cpu_idle_type
, 4), REG_HRO
},
438 { DRDATA (IDLE_WAIT
, cpu_idle_wait
, 16), REG_HIDDEN
},
439 { BRDATA (PCQ
, pcq
, 16, 32, PCQ_SIZE
), REG_RO
+REG_CIRC
},
440 { HRDATA (PCQP
, pcq_p
, 6), REG_HRO
},
441 { HRDATA (BADABO
, badabo
, 32), REG_HRO
},
442 { HRDATA (WRU
, sim_int_char
, 8) },
447 { UNIT_CONH
, 0, "HALT to SIMH", "SIMHALT", NULL
},
448 { UNIT_CONH
, UNIT_CONH
, "HALT to console", "CONHALT", NULL
},
449 { MTAB_XTD
|MTAB_VDV
, 0, "IDLE", "IDLE", &cpu_set_idle
, &cpu_show_idle
},
450 { MTAB_XTD
|MTAB_VDV
, 0, NULL
, "NOIDLE", &sim_clr_idle
, NULL
},
451 { UNIT_MSIZE
, (1u << 23), NULL
, "8M", &cpu_set_size
},
452 { UNIT_MSIZE
, (1u << 24), NULL
, "16M", &cpu_set_size
},
453 { UNIT_MSIZE
, (1u << 25), NULL
, "32M", &cpu_set_size
},
454 { UNIT_MSIZE
, (1u << 25) + (1u << 24), NULL
, "48M", &cpu_set_size
},
455 { UNIT_MSIZE
, (1u << 26), NULL
, "64M", &cpu_set_size
},
456 { UNIT_MSIZE
, (1u << 27), NULL
, "128M", &cpu_set_size
},
457 #if !defined (VAX_780)
458 { UNIT_MSIZE
, (1u << 28), NULL
, "256M", &cpu_set_size
},
459 { UNIT_MSIZE
, (1u << 29), NULL
, "512M", &cpu_set_size
},
461 { MTAB_XTD
|MTAB_VDV
|MTAB_NMO
|MTAB_SHP
, 0, "HISTORY", "HISTORY",
462 &cpu_set_hist
, &cpu_show_hist
},
463 { MTAB_XTD
|MTAB_VDV
|MTAB_NMO
|MTAB_SHP
, 0, "VIRTUAL", NULL
,
464 NULL
, &cpu_show_virt
},
469 { "INTEXC", LOG_CPU_I
},
470 { "REI", LOG_CPU_R
},
471 { "CONTEXT", LOG_CPU_P
},
476 "CPU", &cpu_unit
, cpu_reg
, cpu_mod
,
478 &cpu_ex
, &cpu_dep
, &cpu_reset
,
479 &cpu_boot
, NULL
, NULL
,
480 NULL
, DEV_DYNM
| DEV_DEBUG
, 0,
481 cpu_deb
, &cpu_set_size
, NULL
484 t_stat
sim_instr (void)
486 volatile int32 opc
, cc
; /* used by setjmp */
487 int32 acc
; /* set by setjmp */
491 if ((r
= build_dib_tab ()) != SCPE_OK
) return r
; /* build, chk dib_tab */
492 if ((PSL
& PSL_MBZ
) || /* validate PSL<mbz> */
493 ((PSL
& PSL_CM
) && BadCmPSL (PSL
)) || /* validate PSL<cm> */
494 ((PSL_GETCUR (PSL
) != KERN
) && /* esu => is, ipl = 0 */
495 (PSL
& (PSL_IS
|PSL_IPL
))) ||
496 ((PSL
& PSL_IS
) && ((PSL
& PSL_IPL
) == 0))) /* is => ipl > 0 */
498 cc
= PSL
& CC_MASK
; /* split PSL */
499 PSL
= PSL
& ~CC_MASK
;
500 in_ie
= 0; /* not in exc */
501 set_map_reg (); /* set map reg */
502 GET_CUR
; /* set access mask */
503 SET_IRQL
; /* eval interrupts */
504 FLUSH_ISTR
; /* clear prefetch */
506 abortval
= setjmp (save_env
); /* set abort hdlr */
507 if (abortval
> 0) { /* sim stop? */
508 PSL
= PSL
| cc
; /* put PSL together */
509 pcq_r
->qptr
= pcq_p
; /* update pc q ptr */
510 return abortval
; /* return to SCP */
512 else if (abortval
< 0) { /* mm or rsrv or int */
514 if ((PSL
& PSL_FPD
) == 0) { /* FPD? no recovery */
515 for (i
= 0; i
< recqptr
; i
++) { /* unwind inst */
517 rrn
= RQ_GETRN (recq
[i
]); /* recover reg # */
518 rlnt
= DR_LNT (RQ_GETLNT (recq
[i
])); /* recovery lnt */
519 if (recq
[i
] & RQ_DIR
) R
[rrn
] = R
[rrn
] - rlnt
;
520 else R
[rrn
] = R
[rrn
] + rlnt
;
523 PSL
= PSL
& ~PSL_TP
; /* clear <tp> */
524 recqptr
= 0; /* clear queue */
525 delta
= PC
- fault_PC
; /* save delta PC */
526 SETPC (fault_PC
); /* restore PC */
527 switch (-abortval
) { /* case on abort code */
529 case SCB_RESIN
: /* rsrv inst fault */
530 case SCB_RESAD
: /* rsrv addr fault */
531 case SCB_RESOP
: /* rsrv opnd fault */
532 if (in_ie
) ABORT (STOP_INIE
); /* in exc? panic */
533 cc
= intexc (-abortval
, cc
, 0, IE_EXC
); /* take exception */
534 GET_CUR
; /* PSL<cur> changed */
537 case SCB_CMODE
: /* comp mode fault */
538 case SCB_ARITH
: /* arithmetic fault */
539 if (in_ie
) ABORT (STOP_INIE
); /* in exc? panic */
540 cc
= intexc (-abortval
, cc
, 0, IE_EXC
); /* take exception */
543 Write (SP
- 4, p1
, L_LONG
, WA
); /* write arith param */
548 case SCB_ACV
: /* ACV fault */
549 case SCB_TNV
: /* TNV fault */
550 if (in_ie
) { /* in exception? */
551 if (PSL
& PSL_IS
) ABORT (STOP_INIE
); /* on is? panic */
552 cc
= intexc (SCB_KSNV
, cc
, 0, IE_SVE
); /* ksnv */
556 cc
= intexc (-abortval
, cc
, 0, IE_EXC
); /* take exception */
559 Write (SP
- 8, p1
, L_LONG
, WA
); /* write mm params */
560 Write (SP
- 4, p2
, L_LONG
, WA
);
566 case SCB_MCHK
: /* machine check */
567 if (in_ie
) ABORT (STOP_INIE
); /* in exception? */
568 cc
= machine_check (p1
, opc
, cc
, delta
); /* system specific */
570 GET_CUR
; /* PSL<cur> changed */
573 case 1: /* interrupt */
574 break; /* just proceed */
576 badabo
= abortval
; /* save code */
577 ABORT (STOP_UNKABO
); /* panic */
581 /* Main instruction loop */
585 int32 spec
, disp
, rn
, index
, numspec
;
586 int32 vfldrp1
, brdisp
, flg
, mstat
;
587 int32 i
, j
, r
, rh
, temp
;
589 int32 opnd
[OPND_SIZE
]; /* operand queue */
596 recqptr
= 0; /* clr recovery q */
597 if (sim_interval
<= 0) { /* chk clock queue */
598 temp
= sim_process_event ();
599 if (temp
) ABORT (temp
);
600 SET_IRQL
; /* update interrupts */
603 /* Test for non-instruction dispatches, in SRM order
605 - trap or interrupt (trpirq != 0)
608 If any of these conditions are met, re-dispatch; otherwise,
609 set PSL<tp> from PSL<t>.
612 if (trpirq
) { /* trap or interrupt? */
613 if (temp
= GET_TRAP (trpirq
)) { /* trap? */
614 cc
= intexc (SCB_ARITH
, cc
, 0, IE_EXC
); /* take, clear trap */
615 GET_CUR
; /* set cur mode */
617 Write (SP
- 4, temp
, L_LONG
, WA
); /* write parameter */
621 else if (temp
= GET_IRQL (trpirq
)) { /* interrupt? */
623 if (temp
== IPL_HLTPIN
) { /* console halt? */
624 hlt_pin
= 0; /* clear intr */
625 trpirq
= 0; /* clear everything */
626 cc
= con_halt (CON_HLTPIN
, cc
); /* invoke firmware */
627 continue; /* continue */
629 else if (temp
>= IPL_HMIN
) /* hardware req? */
630 vec
= get_vector (temp
); /* get vector */
631 else if (temp
> IPL_SMAX
) ABORT (STOP_UIPL
);
633 vec
= SCB_IPLSOFT
+ (temp
<< 2);
634 SISR
= SISR
& ~(1u << temp
);
636 if (vec
) cc
= intexc (vec
, cc
, temp
, IE_INT
);/* take intr */
637 GET_CUR
; /* set cur mode */
639 else trpirq
= 0; /* clear everything */
640 SET_IRQL
; /* eval interrupts */
644 if (PSL
& (PSL_CM
|PSL_TP
|PSW_T
)) { /* PSL event? */
645 if (PSL
& PSL_TP
) { /* trace trap? */
646 PSL
= PSL
& ~PSL_TP
; /* clear <tp> */
647 cc
= intexc (SCB_TP
, cc
, 0, IE_EXC
); /* take trap */
648 GET_CUR
; /* set cur mode */
651 if (PSL
& PSW_T
) PSL
= PSL
| PSL_TP
; /* if T, set TP */
652 if (PSL
& PSL_CM
) { /* compat mode? */
653 cc
= op_cmode (cc
); /* exec instr */
654 continue; /* skip fetch */
656 } /* end PSL event */
659 sim_brk_test ((uint32
) PC
, SWMASK ('E'))) { /* breakpoint? */
660 ABORT (STOP_IBKPT
); /* stop simulation */
663 sim_interval
= sim_interval
- 1; /* count instr */
664 GET_ISTR (opc
, L_BYTE
); /* get opcode */
665 if (opc
== 0xFD) { /* 2 byte op? */
666 GET_ISTR (opc
, L_BYTE
); /* get second byte */
667 opc
= opc
| 0x100; /* flag */
669 numspec
= drom
[opc
][0]; /* get # specs */
671 if ((numspec
& DR_F
) == 0) RSVD_INST_FAULT
;
674 numspec
= numspec
& DR_NSPMASK
; /* get # specifiers */
676 /* Specifier flows. Operands are parsed and placed into queue opnd.
678 r.bwl opnd[j] = value of operand
679 r.q opnd[j:j+1] = value of operand
680 r.o opnd[j:j+3] = value of operand
681 a.bwlqo opnd[j] = address of operand
682 m.bwl opnd[j] = value of operand
683 m.q opnd[j:j+1] = value of operand
684 m.o opnd[j:j+3] = value of operand
685 w.bwlqo opnd[j] = register/memory flag
686 opnd[j+1] = memory address
688 For the last memory specifier, the specifier is in spec, the register
689 number is in rn, and the effective address is in va. Modify specifiers
690 (always last) can test spec > reg+PC, as short literal are illegal for
691 modifiers specifiers, and final index specifiers are always illegal.
694 for (i
= 1, j
= 0; i
<= numspec
; i
++) { /* loop thru specs */
695 disp
= drom
[opc
][i
]; /* get dispatch */
697 GET_ISTR (brdisp
, DR_LNT (disp
& 1));
700 GET_ISTR (spec
, L_BYTE
); /* get spec byte */
701 rn
= spec
& RGMASK
; /* get reg # */
702 disp
= (spec
& ~RGMASK
) | disp
; /* merge w dispatch */
703 switch (disp
) { /* dispatch spec */
705 /* Short literal - only read access permitted */
707 case SH0
|RB
: case SH0
|RW
: case SH0
|RL
:
708 case SH1
|RB
: case SH1
|RW
: case SH1
|RL
:
709 case SH2
|RB
: case SH2
|RW
: case SH2
|RL
:
710 case SH3
|RB
: case SH3
|RW
: case SH3
|RL
:
714 case SH0
|RQ
: case SH1
|RQ
: case SH2
|RQ
: case SH3
|RQ
:
719 case SH0
|RO
: case SH1
|RO
: case SH2
|RO
: case SH3
|RO
:
726 case SH0
|RF
: case SH1
|RF
: case SH2
|RF
: case SH3
|RF
:
727 opnd
[j
++] = (spec
<< 4) | 0x4000;
730 case SH0
|RD
: case SH1
|RD
: case SH2
|RD
: case SH3
|RD
:
731 opnd
[j
++] = (spec
<< 4) | 0x4000;
735 case SH0
|RG
: case SH1
|RG
: case SH2
|RG
: case SH3
|RG
:
736 opnd
[j
++] = (spec
<< 1) | 0x4000;
740 case SH0
|RH
: case SH1
|RH
: case SH2
|RH
: case SH3
|RH
:
741 opnd
[j
++] = ((spec
& 0x7) << 29) | (0x4000 | ((spec
>> 3) & 0x7));
749 case GRN
|RB
: case GRN
|MB
:
751 opnd
[j
++] = R
[rn
] & BMASK
;
754 case GRN
|RW
: case GRN
|MW
:
756 opnd
[j
++] = R
[rn
] & WMASK
;
760 vfldrp1
= R
[(rn
+ 1) & RGMASK
];
761 case GRN
|WB
: case GRN
|WW
: case GRN
|WL
: case GRN
|WQ
: case GRN
|WO
:
763 case GRN
|RL
: case GRN
|RF
: case GRN
|ML
:
768 case GRN
|RQ
: case GRN
|RD
: case GRN
|RG
: case GRN
|MQ
:
771 opnd
[j
++] = R
[rn
+ 1];
774 case GRN
|RO
: case GRN
|RH
: case GRN
|MO
:
777 opnd
[j
++] = R
[rn
+ 1];
778 opnd
[j
++] = R
[rn
+ 2];
779 opnd
[j
++] = R
[rn
+ 3];
782 /* Register deferred, autodecrement */
785 case RGD
|WB
: case RGD
|WW
: case RGD
|WL
: case RGD
|WQ
: case RGD
|WO
:
787 case RGD
|AB
: case RGD
|AW
: case RGD
|AL
: case RGD
|AQ
: case RGD
|AO
:
789 va
= opnd
[j
++] = R
[rn
];
793 case ADC
|WB
: case ADC
|WW
: case ADC
|WL
: case ADC
|WQ
: case ADC
|WO
:
795 case ADC
|AB
: case ADC
|AW
: case ADC
|AL
: case ADC
|AQ
: case ADC
|AO
:
797 va
= opnd
[j
++] = R
[rn
] = R
[rn
] - DR_LNT (disp
);
798 recq
[recqptr
++] = RQ_REC (disp
, rn
);
801 case ADC
|RB
: case ADC
|RW
: case ADC
|RL
: case ADC
|RF
:
802 R
[rn
] = R
[rn
] - (DR_LNT (disp
));
803 recq
[recqptr
++] = RQ_REC (disp
, rn
);
804 case RGD
|RB
: case RGD
|RW
: case RGD
|RL
: case RGD
|RF
:
806 opnd
[j
++] = Read (va
= R
[rn
], DR_LNT (disp
), RA
);
809 case ADC
|RQ
: case ADC
|RD
: case ADC
|RG
:
811 recq
[recqptr
++] = RQ_REC (disp
, rn
);
812 case RGD
|RQ
: case RGD
|RD
: case RGD
|RG
:
814 opnd
[j
++] = Read (va
= R
[rn
], L_LONG
, RA
);
815 opnd
[j
++] = Read (R
[rn
] + 4, L_LONG
, RA
);
818 case ADC
|RO
: case ADC
|RH
:
820 recq
[recqptr
++] = RQ_REC (disp
, rn
);
821 case RGD
|RO
: case RGD
|RH
:
823 j
= ReadOcta (va
= R
[rn
], opnd
, j
, RA
);
826 case ADC
|MB
: case ADC
|MW
: case ADC
|ML
:
827 R
[rn
] = R
[rn
] - (DR_LNT (disp
));
828 recq
[recqptr
++] = RQ_REC (disp
, rn
);
829 case RGD
|MB
: case RGD
|MW
: case RGD
|ML
:
831 opnd
[j
++] = Read (va
= R
[rn
], DR_LNT (disp
), WA
);
836 recq
[recqptr
++] = RQ_REC (disp
, rn
);
839 opnd
[j
++] = Read (va
= R
[rn
], L_LONG
, WA
);
840 opnd
[j
++] = Read (R
[rn
] + 4, L_LONG
, WA
);
845 recq
[recqptr
++] = RQ_REC (disp
, rn
);
848 j
= ReadOcta (va
= R
[rn
], opnd
, j
, WA
);
854 case AIN
|WB
: case AIN
|WW
: case AIN
|WL
: case AIN
|WQ
: case AIN
|WO
:
857 case AIN
|AB
: case AIN
|AW
: case AIN
|AL
: case AIN
|AQ
: case AIN
|AO
:
858 va
= opnd
[j
++] = R
[rn
];
860 if (DR_LNT (disp
) >= L_QUAD
) {
861 GET_ISTR (temp
, L_LONG
);
862 GET_ISTR (temp
, L_LONG
);
863 if (DR_LNT (disp
) == L_OCTA
) {
864 GET_ISTR (temp
, L_LONG
);
865 GET_ISTR (temp
, L_LONG
);
868 else GET_ISTR (temp
, DR_LNT (disp
));
871 R
[rn
] = R
[rn
] + DR_LNT (disp
);
872 recq
[recqptr
++] = RQ_REC (disp
, rn
);
876 case AIN
|RB
: case AIN
|RW
: case AIN
|RL
: case AIN
|RF
:
879 GET_ISTR (opnd
[j
++], DR_LNT (disp
));
882 opnd
[j
++] = Read (R
[rn
], DR_LNT (disp
), RA
);
883 R
[rn
] = R
[rn
] + DR_LNT (disp
);
884 recq
[recqptr
++] = RQ_REC (disp
, rn
);
888 case AIN
|RQ
: case AIN
|RD
: case AIN
|RG
:
891 GET_ISTR (opnd
[j
++], L_LONG
);
892 GET_ISTR (opnd
[j
++], L_LONG
);
895 opnd
[j
++] = Read (va
, L_LONG
, RA
);
896 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
898 recq
[recqptr
++] = RQ_REC (disp
, rn
);
902 case AIN
|RO
: case AIN
|RH
:
905 GET_ISTR (opnd
[j
++], L_LONG
);
906 GET_ISTR (opnd
[j
++], L_LONG
);
907 GET_ISTR (opnd
[j
++], L_LONG
);
908 GET_ISTR (opnd
[j
++], L_LONG
);
911 j
= ReadOcta (va
, opnd
, j
, RA
);
913 recq
[recqptr
++] = RQ_REC (disp
, rn
);
917 case AIN
|MB
: case AIN
|MW
: case AIN
|ML
:
920 GET_ISTR (opnd
[j
++], DR_LNT (disp
));
923 opnd
[j
++] = Read (R
[rn
], DR_LNT (disp
), WA
);
924 R
[rn
] = R
[rn
] + DR_LNT (disp
);
925 recq
[recqptr
++] = RQ_REC (disp
, rn
);
932 GET_ISTR (opnd
[j
++], L_LONG
);
933 GET_ISTR (opnd
[j
++], L_LONG
);
936 opnd
[j
++] = Read (va
, L_LONG
, WA
);
937 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
939 recq
[recqptr
++] = RQ_REC (disp
, rn
);
946 GET_ISTR (opnd
[j
++], L_LONG
);
947 GET_ISTR (opnd
[j
++], L_LONG
);
948 GET_ISTR (opnd
[j
++], L_LONG
);
949 GET_ISTR (opnd
[j
++], L_LONG
);
952 j
= ReadOcta (va
, opnd
, j
, WA
);
954 recq
[recqptr
++] = RQ_REC (disp
, rn
);
958 /* Autoincrement deferred */
961 case AID
|WB
: case AID
|WW
: case AID
|WL
: case AID
|WQ
: case AID
|WO
:
963 case AID
|AB
: case AID
|AW
: case AID
|AL
: case AID
|AQ
: case AID
|AO
:
964 if (rn
== nPC
) { GET_ISTR (va
= opnd
[j
++], L_LONG
); }
966 va
= opnd
[j
++] = Read (R
[rn
], L_LONG
, RA
);
968 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
972 case AID
|RB
: case AID
|RW
: case AID
|RL
: case AID
|RF
:
974 GET_ISTR (va
, L_LONG
);
977 va
= Read (R
[rn
], L_LONG
, RA
);
979 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
981 opnd
[j
++] = Read (va
, DR_LNT (disp
), RA
);
984 case AID
|RQ
: case AID
|RD
: case AID
|RG
:
986 GET_ISTR (va
, L_LONG
);
989 va
= Read (R
[rn
], L_LONG
, RA
);
991 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
993 opnd
[j
++] = Read (va
, L_LONG
, RA
);
994 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
997 case AID
|RO
: case AID
|RH
:
999 GET_ISTR (va
, L_LONG
);
1002 va
= Read (R
[rn
], L_LONG
, RA
);
1004 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
1006 j
= ReadOcta (va
, opnd
, j
, RA
);
1009 case AID
|MB
: case AID
|MW
: case AID
|ML
:
1011 GET_ISTR (va
, L_LONG
);
1014 va
= Read (R
[rn
], L_LONG
, RA
);
1016 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
1018 opnd
[j
++] = Read (va
, DR_LNT (disp
), WA
);
1023 GET_ISTR (va
, L_LONG
);
1026 va
= Read (R
[rn
], L_LONG
, RA
);
1028 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
1030 opnd
[j
++] = Read (va
, L_LONG
, WA
);
1031 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
1036 GET_ISTR (va
, L_LONG
);
1039 va
= Read (R
[rn
], L_LONG
, RA
);
1041 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
1043 j
= ReadOcta (va
, opnd
, j
, WA
);
1046 /* Byte displacement */
1049 case BDP
|WB
: case BDP
|WW
: case BDP
|WL
: case BDP
|WQ
: case BDP
|WO
:
1051 case BDP
|AB
: case BDP
|AW
: case BDP
|AL
: case BDP
|AQ
: case BDP
|AO
:
1052 GET_ISTR (temp
, L_BYTE
);
1053 va
= opnd
[j
++] = R
[rn
] + SXTB (temp
);
1056 case BDP
|RB
: case BDP
|RW
: case BDP
|RL
: case BDP
|RF
:
1057 GET_ISTR (temp
, L_BYTE
);
1058 va
= R
[rn
] + SXTB (temp
);
1059 opnd
[j
++] = Read (va
, DR_LNT (disp
), RA
);
1062 case BDP
|RQ
: case BDP
|RD
: case BDP
|RG
:
1063 GET_ISTR (temp
, L_BYTE
);
1064 va
= R
[rn
] + SXTB (temp
);
1065 opnd
[j
++] = Read (va
, L_LONG
, RA
);
1066 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
1069 case BDP
|RO
: case BDP
|RH
:
1070 GET_ISTR (temp
, L_BYTE
);
1071 va
= R
[rn
] + SXTB (temp
);
1072 j
= ReadOcta (va
, opnd
, j
, RA
);
1075 case BDP
|MB
: case BDP
|MW
: case BDP
|ML
:
1076 GET_ISTR (temp
, L_BYTE
);
1077 va
= R
[rn
] + SXTB (temp
);
1078 opnd
[j
++] = Read (va
, DR_LNT (disp
), WA
);
1082 GET_ISTR (temp
, L_BYTE
);
1083 va
= R
[rn
] + SXTB (temp
);
1084 opnd
[j
++] = Read (va
, L_LONG
, WA
);
1085 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
1089 GET_ISTR (temp
, L_BYTE
);
1090 va
= R
[rn
] + SXTB (temp
);
1091 j
= ReadOcta (va
, opnd
, j
, WA
);
1094 /* Byte displacement deferred */
1097 case BDD
|WB
: case BDD
|WW
: case BDD
|WL
: case BDD
|WQ
: case BDD
|WO
:
1099 case BDD
|AB
: case BDD
|AW
: case BDD
|AL
: case BDD
|AQ
: case BDD
|AO
:
1100 GET_ISTR (temp
, L_BYTE
);
1101 iad
= R
[rn
] + SXTB (temp
);
1102 va
= opnd
[j
++] = Read (iad
, L_LONG
, RA
);
1105 case BDD
|RB
: case BDD
|RW
: case BDD
|RL
: case BDD
|RF
:
1106 GET_ISTR (temp
, L_BYTE
);
1107 iad
= R
[rn
] + SXTB (temp
);
1108 va
= Read (iad
, L_LONG
, RA
);
1109 opnd
[j
++] = Read (va
, DR_LNT (disp
), RA
);
1112 case BDD
|RQ
: case BDD
|RD
: case BDD
|RG
:
1113 GET_ISTR (temp
, L_BYTE
);
1114 iad
= R
[rn
] + SXTB (temp
);
1115 va
= Read (iad
, L_LONG
, RA
);
1116 opnd
[j
++] = Read (va
, L_LONG
, RA
);
1117 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
1120 case BDD
|RO
: case BDD
|RH
:
1121 GET_ISTR (temp
, L_BYTE
);
1122 iad
= R
[rn
] + SXTB (temp
);
1123 va
= Read (iad
, L_LONG
, RA
);
1124 j
= ReadOcta (va
, opnd
, j
, RA
);
1127 case BDD
|MB
: case BDD
|MW
: case BDD
|ML
:
1128 GET_ISTR (temp
, L_BYTE
);
1129 iad
= R
[rn
] + SXTB (temp
);
1130 va
= Read (iad
, L_LONG
, RA
);
1131 opnd
[j
++] = Read (va
, DR_LNT (disp
), WA
);
1135 GET_ISTR (temp
, L_BYTE
);
1136 iad
= R
[rn
] + SXTB (temp
);
1137 va
= Read (iad
, L_LONG
, RA
);
1138 opnd
[j
++] = Read (va
, L_LONG
, WA
);
1139 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
1143 GET_ISTR (temp
, L_BYTE
);
1144 iad
= R
[rn
] + SXTB (temp
);
1145 va
= Read (iad
, L_LONG
, RA
);
1146 j
= ReadOcta (va
, opnd
, j
, WA
);
1149 /* Word displacement */
1152 case WDP
|WB
: case WDP
|WW
: case WDP
|WL
: case WDP
|WQ
: case WDP
|WO
:
1154 case WDP
|AB
: case WDP
|AW
: case WDP
|AL
: case WDP
|AQ
: case WDP
|AO
:
1155 GET_ISTR (temp
, L_WORD
);
1156 va
= opnd
[j
++] = R
[rn
] + SXTW (temp
);
1159 case WDP
|RB
: case WDP
|RW
: case WDP
|RL
: case WDP
|RF
:
1160 GET_ISTR (temp
, L_WORD
);
1161 va
= R
[rn
] + SXTW (temp
);
1162 opnd
[j
++] = Read (va
, DR_LNT (disp
), RA
);
1165 case WDP
|RQ
: case WDP
|RD
: case WDP
|RG
:
1166 GET_ISTR (temp
, L_WORD
);
1167 va
= R
[rn
] + SXTW (temp
);
1168 opnd
[j
++] = Read (va
, L_LONG
, RA
);
1169 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
1172 case WDP
|RO
: case WDP
|RH
:
1173 GET_ISTR (temp
, L_WORD
);
1174 va
= R
[rn
] + SXTW (temp
);
1175 j
= ReadOcta (va
, opnd
, j
, RA
);
1178 case WDP
|MB
: case WDP
|MW
: case WDP
|ML
:
1179 GET_ISTR (temp
, L_WORD
);
1180 va
= R
[rn
] + SXTW (temp
);
1181 opnd
[j
++] = Read (va
, DR_LNT (disp
), WA
);
1185 GET_ISTR (temp
, L_WORD
);
1186 va
= R
[rn
] + SXTW (temp
);
1187 opnd
[j
++] = Read (va
, L_LONG
, WA
);
1188 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
1192 GET_ISTR (temp
, L_WORD
);
1193 va
= R
[rn
] + SXTW (temp
);
1194 j
= ReadOcta (va
, opnd
, j
, WA
);
1197 /* Word displacement deferred */
1200 case WDD
|WB
: case WDD
|WW
: case WDD
|WL
: case WDD
|WQ
: case WDD
|WO
:
1202 case WDD
|AB
: case WDD
|AW
: case WDD
|AL
: case WDD
|AQ
: case WDD
|AO
:
1203 GET_ISTR (temp
, L_WORD
);
1204 iad
= R
[rn
] + SXTW (temp
);
1205 va
= opnd
[j
++] = Read (iad
, L_LONG
, RA
);
1208 case WDD
|RB
: case WDD
|RW
: case WDD
|RL
: case WDD
|RF
:
1209 GET_ISTR (temp
, L_WORD
);
1210 iad
= R
[rn
] + SXTW (temp
);
1211 va
= Read (iad
, L_LONG
, RA
);
1212 opnd
[j
++] = Read (va
, DR_LNT (disp
), RA
);
1215 case WDD
|RQ
: case WDD
|RD
: case WDD
|RG
:
1216 GET_ISTR (temp
, L_WORD
);
1217 iad
= R
[rn
] + SXTW (temp
);
1218 va
= Read (iad
, L_LONG
, RA
);
1219 opnd
[j
++] = Read (va
, L_LONG
, RA
);
1220 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
1223 case WDD
|RO
: case WDD
|RH
:
1224 GET_ISTR (temp
, L_WORD
);
1225 iad
= R
[rn
] + SXTW (temp
);
1226 va
= Read (iad
, L_LONG
, RA
);
1227 j
= ReadOcta (va
, opnd
, j
, RA
);
1230 case WDD
|MB
: case WDD
|MW
: case WDD
|ML
:
1231 GET_ISTR (temp
, L_WORD
);
1232 iad
= R
[rn
] + SXTW (temp
);
1233 va
= Read (iad
, L_LONG
, RA
);
1234 opnd
[j
++] = Read (va
, DR_LNT (disp
), WA
);
1238 GET_ISTR (temp
, L_WORD
);
1239 iad
= R
[rn
] + SXTW (temp
);
1240 va
= Read (iad
, L_LONG
, RA
);
1241 opnd
[j
++] = Read (va
, L_LONG
, WA
);
1242 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
1246 GET_ISTR (temp
, L_WORD
);
1247 iad
= R
[rn
] + SXTW (temp
);
1248 va
= Read (iad
, L_LONG
, RA
);
1249 j
= ReadOcta (va
, opnd
, j
, WA
);
1252 /* Longword displacement */
1255 case LDP
|WB
: case LDP
|WW
: case LDP
|WL
: case LDP
|WQ
: case LDP
|WO
:
1257 case LDP
|AB
: case LDP
|AW
: case LDP
|AL
: case LDP
|AQ
: case LDP
|AO
:
1258 GET_ISTR (temp
, L_LONG
);
1259 va
= opnd
[j
++] = R
[rn
] + temp
;
1262 case LDP
|RB
: case LDP
|RW
: case LDP
|RL
: case LDP
|RF
:
1263 GET_ISTR (temp
, L_LONG
);
1265 opnd
[j
++] = Read (va
, DR_LNT (disp
), RA
);
1268 case LDP
|RQ
: case LDP
|RD
: case LDP
|RG
:
1269 GET_ISTR (temp
, L_LONG
);
1271 opnd
[j
++] = Read (va
, L_LONG
, RA
);
1272 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
1275 case LDP
|RO
: case LDP
|RH
:
1276 GET_ISTR (temp
, L_LONG
);
1278 j
= ReadOcta (va
, opnd
, j
, RA
);
1281 case LDP
|MB
: case LDP
|MW
: case LDP
|ML
:
1282 GET_ISTR (temp
, L_LONG
);
1284 opnd
[j
++] = Read (va
, DR_LNT (disp
), WA
);
1288 GET_ISTR (temp
, L_LONG
);
1290 opnd
[j
++] = Read (va
, L_LONG
, WA
);
1291 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
1295 GET_ISTR (temp
, L_LONG
);
1297 j
= ReadOcta (va
, opnd
, j
, WA
);
1300 /* Longword displacement deferred */
1303 case LDD
|WB
: case LDD
|WW
: case LDD
|WL
: case LDD
|WQ
: case LDD
|WO
:
1305 case LDD
|AB
: case LDD
|AW
: case LDD
|AL
: case LDD
|AQ
: case LDD
|AO
:
1306 GET_ISTR (temp
, L_LONG
);
1308 va
= opnd
[j
++] = Read (iad
, L_LONG
, RA
);
1311 case LDD
|RB
: case LDD
|RW
: case LDD
|RL
: case LDD
|RF
:
1312 GET_ISTR (temp
, L_LONG
);
1314 va
= Read (iad
, L_LONG
, RA
);
1315 opnd
[j
++] = Read (va
, DR_LNT (disp
), RA
);
1318 case LDD
|RQ
: case LDD
|RD
: case LDD
|RG
:
1319 GET_ISTR (temp
, L_LONG
);
1321 va
= Read (iad
, L_LONG
, RA
);
1322 opnd
[j
++] = Read (va
, L_LONG
, RA
);
1323 opnd
[j
++] = Read (va
+ 4, L_LONG
, RA
);
1326 case LDD
|RO
: case LDD
|RH
:
1327 GET_ISTR (temp
, L_LONG
);
1329 va
= Read (iad
, L_LONG
, RA
);
1330 j
= ReadOcta (va
, opnd
, j
, RA
);
1333 case LDD
|MB
: case LDD
|MW
: case LDD
|ML
:
1334 GET_ISTR (temp
, L_LONG
);
1336 va
= Read (iad
, L_LONG
, RA
);
1337 opnd
[j
++] = Read (va
, DR_LNT (disp
), WA
);
1341 GET_ISTR (temp
, L_LONG
);
1343 va
= Read (iad
, L_LONG
, RA
);
1344 opnd
[j
++] = Read (va
, L_LONG
, WA
);
1345 opnd
[j
++] = Read (va
+ 4, L_LONG
, WA
);
1349 GET_ISTR (temp
, L_LONG
);
1351 va
= Read (iad
, L_LONG
, RA
);
1352 j
= ReadOcta (va
, opnd
, j
, WA
);
1358 case IDX
|WB
: case IDX
|WW
: case IDX
|WL
: case IDX
|WQ
: case IDX
|WO
:
1359 case IDX
|AB
: case IDX
|AW
: case IDX
|AL
: case IDX
|AQ
: case IDX
|AO
:
1360 case IDX
|MB
: case IDX
|MW
: case IDX
|ML
: case IDX
|MQ
: case IDX
|MO
:
1361 case IDX
|RB
: case IDX
|RW
: case IDX
|RL
: case IDX
|RQ
: case IDX
|RO
:
1362 case IDX
|RF
: case IDX
|RD
: case IDX
|RG
: case IDX
|RH
:
1364 index
= R
[rn
] << (disp
& DR_LNMASK
);
1365 GET_ISTR (spec
, L_BYTE
);
1367 switch (spec
& ~RGMASK
) {
1369 R
[rn
] = R
[rn
] - DR_LNT (disp
);
1370 recq
[recqptr
++] = RQ_REC (ADC
| (disp
& DR_LNMASK
), rn
);
1373 index
= index
+ R
[rn
];
1378 index
= index
+ R
[rn
];
1379 R
[rn
] = R
[rn
] + DR_LNT (disp
);
1380 recq
[recqptr
++] = RQ_REC (AIN
| (disp
& DR_LNMASK
), rn
);
1385 GET_ISTR (temp
, L_LONG
);
1388 temp
= Read (R
[rn
], L_LONG
, RA
);
1390 recq
[recqptr
++] = RQ_REC (AID
|RL
, rn
);
1392 index
= temp
+ index
;
1396 GET_ISTR (temp
, L_BYTE
);
1397 index
= index
+ R
[rn
] + SXTB (temp
);
1401 GET_ISTR (temp
, L_BYTE
);
1402 index
= index
+ Read (R
[rn
] + SXTB (temp
), L_LONG
, RA
);
1406 GET_ISTR (temp
, L_WORD
);
1407 index
= index
+ R
[rn
] + SXTW (temp
);
1411 GET_ISTR (temp
, L_WORD
);
1412 index
= index
+ Read (R
[rn
] + SXTW (temp
), L_LONG
, RA
);
1416 GET_ISTR (temp
, L_LONG
);
1417 index
= index
+ R
[rn
] + temp
;
1421 GET_ISTR (temp
, L_LONG
);
1422 index
= index
+ Read (R
[rn
] + temp
, L_LONG
, RA
);
1426 RSVD_ADDR_FAULT
; /* end case idxspec */
1429 switch (disp
& (DR_ACMASK
|DR_SPFLAG
|DR_LNMASK
)) { /* case acc+lnt */
1431 case WB
: case WW
: case WL
: case WQ
: case WO
:
1433 case AB
: case AW
: case AL
: case AQ
: case AO
:
1434 va
= opnd
[j
++] = index
;
1437 case RB
: case RW
: case RL
: case RF
:
1438 opnd
[j
++] = Read (va
= index
, DR_LNT (disp
), RA
);
1441 case RQ
: case RD
: case RG
:
1442 opnd
[j
++] = Read (va
= index
, L_LONG
, RA
);
1443 opnd
[j
++] = Read (index
+ 4, L_LONG
, RA
);
1447 j
= ReadOcta (va
= index
, opnd
, j
, RA
);
1450 case MB
: case MW
: case ML
:
1451 opnd
[j
++] = Read (va
= index
, DR_LNT (disp
), WA
);
1455 opnd
[j
++] = Read (va
= index
, L_LONG
, WA
);
1456 opnd
[j
++] = Read (index
+ 4, L_LONG
, WA
);
1460 j
= ReadOcta (va
= index
, opnd
, j
, WA
);
1463 default: /* all others */
1464 RSVD_ADDR_FAULT
; /* fault */
1466 } /* end case access/lnt */
1467 break; /* end index */
1469 default: /* all others */
1470 RSVD_ADDR_FAULT
; /* fault */
1472 } /* end case spec */
1474 } /* end if not FPD */
1476 /* Optionally record instruction history */
1482 hst
[hst_p
].iPC
= fault_PC
;
1483 hst
[hst_p
].PSL
= PSL
| cc
;
1484 hst
[hst_p
].opc
= opc
;
1485 for (i
= 0; i
< j
; i
++)
1486 hst
[hst_p
].opnd
[i
] = opnd
[i
];
1487 lim
= PC
- fault_PC
;
1488 if ((uint32
) lim
> INST_SIZE
) lim
= INST_SIZE
;
1489 for (i
= 0; i
< lim
; i
++) {
1490 if ((cpu_ex (&wd
, fault_PC
+ i
, &cpu_unit
, SWMASK ('V'))) == SCPE_OK
)
1491 hst
[hst_p
].inst
[i
] = (uint8
) wd
;
1493 hst
[hst_p
].inst
[0] = hst
[hst_p
].inst
[1] = 0xFF;
1498 if (hst_p
>= hst_lnt
) hst_p
= 0;
1501 /* Dispatch to instructions */
1505 /* Single operand instructions with dest, write only - CLRx dst.wx
1507 spec = reg/memory flag
1508 rn = register number
1509 va = virtual address
1513 WRITE_B (0); /* store result */
1514 CC_ZZ1P
; /* set cc's */
1518 WRITE_W (0); /* store result */
1519 CC_ZZ1P
; /* set cc's */
1523 WRITE_L (0); /* store result */
1524 CC_ZZ1P
; /* set cc's */
1528 WRITE_Q (0, 0); /* store result */
1529 CC_ZZ1P
; /* set cc's */
1532 /* Single operand instructions with source, read only - TSTx src.rx
1538 CC_IIZZ_B (op0
); /* set cc's */
1542 CC_IIZZ_W (op0
); /* set cc's */
1546 CC_IIZZ_L (op0
); /* set cc's */
1549 /* Single operand instructions with source, read/write - op src.mx
1553 rn = register number
1554 va = operand address
1558 r
= (op0
+ 1) & BMASK
; /* calc result */
1559 WRITE_B (r
); /* store result */
1560 CC_ADD_B (r
, 1, op0
); /* set cc's */
1564 r
= (op0
+ 1) & WMASK
; /* calc result */
1565 WRITE_W (r
); /* store result */
1566 CC_ADD_W (r
, 1, op0
); /* set cc's */
1570 r
= (op0
+ 1) & LMASK
; /* calc result */
1571 WRITE_L (r
); /* store result */
1572 CC_ADD_L (r
, 1, op0
); /* set cc's */
1576 r
= (op0
- 1) & BMASK
; /* calc result */
1577 WRITE_B (r
); /* store result */
1578 CC_SUB_B (r
, 1, op0
); /* set cc's */
1582 r
= (op0
- 1) & WMASK
; /* calc result */
1583 WRITE_W (r
); /* store result */
1584 CC_SUB_W (r
, 1, op0
); /* set cc's */
1588 r
= (op0
- 1) & LMASK
; /* calc result */
1589 WRITE_L (r
); /* store result */
1590 CC_SUB_L (r
, 1, op0
); /* set cc's */
1593 /* Push instructions - PUSHL src.rl or PUSHAx src.ax
1598 case PUSHL
: case PUSHAB
: case PUSHAW
: case PUSHAL
: case PUSHAQ
:
1599 Write (SP
- 4, op0
, L_LONG
, WA
); /* push operand */
1600 SP
= SP
- 4; /* decr stack ptr */
1601 CC_IIZP_L (op0
); /* set cc's */
1604 /* Moves, converts, and ADAWI - op src.rx, dst.wx
1608 rn = register number
1609 va = operand address
1613 WRITE_B (op0
); /* result */
1614 CC_IIZP_B (op0
); /* set cc's */
1617 case MOVW
: case MOVZBW
:
1618 WRITE_W (op0
); /* result */
1619 CC_IIZP_W (op0
); /* set cc's */
1622 case MOVL
: case MOVZBL
: case MOVZWL
:
1623 case MOVAB
: case MOVAW
: case MOVAL
: case MOVAQ
:
1624 WRITE_L (op0
); /* result */
1625 CC_IIZP_L (op0
); /* set cc's */
1629 r
= op0
^ BMASK
; /* compl opnd */
1630 WRITE_B (r
); /* store result */
1631 CC_IIZP_B (r
); /* set cc's */
1635 r
= op0
^ WMASK
; /* compl opnd */
1636 WRITE_W (r
); /* store result */
1637 CC_IIZP_W (r
); /* set cc's */
1641 r
= op0
^ LMASK
; /* compl opnd */
1642 WRITE_L (r
); /* store result */
1643 CC_IIZP_L (r
); /* set cc's */
1647 r
= (-op0
) & BMASK
; /* negate opnd */
1648 WRITE_B (r
); /* store result */
1649 CC_SUB_B (r
, op0
, 0); /* set cc's */
1653 r
= (-op0
) & WMASK
; /* negate opnd */
1654 WRITE_W (r
); /* store result */
1655 CC_SUB_W (r
, op0
, 0); /* set cc's */
1659 r
= (-op0
) & LMASK
; /* negate opnd */
1660 WRITE_L (r
); /* store result */
1661 CC_SUB_L (r
, op0
, 0); /* set cc's */
1665 r
= SXTBW (op0
); /* ext sign */
1666 WRITE_W (r
); /* store result */
1667 CC_IIZZ_W (r
); /* set cc's */
1671 r
= SXTB (op0
); /* ext sign */
1672 WRITE_L (r
); /* store result */
1673 CC_IIZZ_L (r
); /* set cc's */
1677 r
= SXTW (op0
); /* ext sign */
1678 WRITE_L (r
); /* store result */
1679 CC_IIZZ_L (r
); /* set cc's */
1683 r
= op0
& BMASK
; /* set result */
1684 WRITE_B (r
); /* store result */
1685 CC_IIZZ_B (r
); /* initial cc's */
1686 if ((op0
> 127) || (op0
< -128)) { V_INTOV
; }
1690 r
= op0
& WMASK
; /* set result */
1691 WRITE_W (r
); /* store result */
1692 CC_IIZZ_W (r
); /* initial cc's */
1693 if ((op0
> 32767) || (op0
< -32768)) { V_INTOV
; }
1697 r
= op0
& BMASK
; /* set result */
1698 WRITE_B (r
); /* store result */
1699 CC_IIZZ_B (r
); /* initial cc's */
1700 temp
= SXTW (op0
); /* cvt op to long */
1701 if ((temp
> 127) || (temp
< -128)) { V_INTOV
; }
1705 if (op1
>= 0) temp
= R
[op1
] & WMASK
; /* reg? ADDW2 */
1707 if (op2
& 1) RSVD_OPND_FAULT
; /* mem? chk align */
1708 temp
= Read (op2
, L_WORD
, WA
); /* ok, ADDW2 */
1710 r
= (op0
+ temp
) & WMASK
;
1712 CC_ADD_W (r
, op0
, temp
); /* set cc's */
1715 /* Integer operates, 2 operand, read only - op src1.rx, src2.rx
1722 CC_CMP_B (op0
, op1
); /* set cc's */
1726 CC_CMP_W (op0
, op1
); /* set cc's */
1730 CC_CMP_L (op0
, op1
); /* set cc's */
1734 r
= op1
& op0
; /* calc result */
1735 CC_IIZP_B (r
); /* set cc's */
1739 r
= op1
& op0
; /* calc result */
1740 CC_IIZP_W (r
); /* set cc's */
1744 r
= op1
& op0
; /* calc result */
1745 CC_IIZP_L (r
); /* set cc's */
1748 /* Integer operates, 2 operand read/write, and 3 operand, also MOVQ
1749 op2 src.rx, dst.mx op3 src.rx, src.rx, dst.wx
1753 spec = register/memory flag
1754 rn = register number
1758 case ADDB2
: case ADDB3
:
1759 r
= (op1
+ op0
) & BMASK
; /* calc result */
1760 WRITE_B (r
); /* store result */
1761 CC_ADD_B (r
, op0
, op1
); /* set cc's */
1764 case ADDW2
: case ADDW3
:
1765 r
= (op1
+ op0
) & WMASK
; /* calc result */
1766 WRITE_W (r
); /* store result */
1767 CC_ADD_W (r
, op0
, op1
); /* set cc's */
1771 r
= (op1
+ op0
+ (cc
& CC_C
)) & LMASK
; /* calc result */
1772 WRITE_L (r
); /* store result */
1773 CC_ADD_L (r
, op0
, op1
); /* set cc's */
1774 if ((r
== op1
) && op0
) cc
= cc
| CC_C
; /* special case */
1777 case ADDL2
: case ADDL3
:
1778 r
= (op1
+ op0
) & LMASK
; /* calc result */
1779 WRITE_L (r
); /* store result */
1780 CC_ADD_L (r
, op0
, op1
); /* set cc's */
1783 case SUBB2
: case SUBB3
:
1784 r
= (op1
- op0
) & BMASK
; /* calc result */
1785 WRITE_B (r
); /* store result */
1786 CC_SUB_B (r
, op0
, op1
); /* set cc's */
1789 case SUBW2
: case SUBW3
:
1790 r
= (op1
- op0
) & WMASK
; /* calc result */
1791 WRITE_W (r
); /* store result */
1792 CC_SUB_W (r
, op0
, op1
); /* set cc's */
1796 r
= (op1
- op0
- (cc
& CC_C
)) & LMASK
; /* calc result */
1797 WRITE_L (r
); /* store result */
1798 CC_SUB_L (r
, op0
, op1
); /* set cc's */
1799 if ((op0
== op1
) && r
) cc
= cc
| CC_C
; /* special case */
1802 case SUBL2
: case SUBL3
:
1803 r
= (op1
- op0
) & LMASK
; /* calc result */
1804 WRITE_L (r
); /* store result */
1805 CC_SUB_L (r
, op0
, op1
); /* set cc's */
1808 case MULB2
: case MULB3
:
1809 temp
= SXTB (op0
) * SXTB (op1
); /* multiply */
1810 r
= temp
& BMASK
; /* mask to result */
1811 WRITE_B (r
); /* store result */
1812 CC_IIZZ_B (r
); /* set cc's */
1813 if ((temp
> 127) || (temp
< -128)) { V_INTOV
; }
1816 case MULW2
: case MULW3
:
1817 temp
= SXTW (op0
) * SXTW (op1
); /* multiply */
1818 r
= temp
& WMASK
; /* mask to result */
1819 WRITE_W (r
); /* store result */
1820 CC_IIZZ_W (r
); /* set cc's */
1821 if ((temp
> 32767) || (temp
< -32768)) { V_INTOV
; }
1824 case MULL2
: case MULL3
:
1825 r
= op_emul (op0
, op1
, &rh
); /* get 64b result */
1826 WRITE_L (r
); /* store result */
1827 CC_IIZZ_L (r
); /* set cc's */
1828 if (rh
!= ((r
& LSIGN
)? -1: 0)) { V_INTOV
; } /* chk overflow */
1831 case DIVB2
: case DIVB3
:
1832 if (op0
== 0) { /* div by zero? */
1835 SET_TRAP (TRAP_DIVZRO
);
1837 else if ((op0
== BMASK
) && (op1
== BSIGN
)) { /* overflow? */
1843 r
= SXTB (op1
) / SXTB (op0
); /* ok, divide */
1846 r
= r
& BMASK
; /* mask to result */
1847 WRITE_B (r
); /* write result */
1848 CC_IIZZ_B (r
); /* set cc's */
1849 cc
= cc
| temp
; /* error? set V */
1852 case DIVW2
: case DIVW3
:
1853 if (op0
== 0) { /* div by zero? */
1856 SET_TRAP (TRAP_DIVZRO
);
1858 else if ((op0
== WMASK
) && (op1
== WSIGN
)) { /* overflow? */
1864 r
= SXTW (op1
) / SXTW (op0
); /* ok, divide */
1867 r
= r
& WMASK
; /* mask to result */
1868 WRITE_W (r
); /* write result */
1869 CC_IIZZ_W (r
); /* set cc's */
1870 cc
= cc
| temp
; /* error? set V */
1873 case DIVL2
: case DIVL3
:
1874 if (op0
== 0) { /* div by zero? */
1877 SET_TRAP (TRAP_DIVZRO
);
1879 else if ((op0
== LMASK
) && (op1
== LSIGN
)) { /* overflow? */
1885 r
= op1
/ op0
; /* ok, divide */
1888 r
= r
& LMASK
; /* mask to result */
1889 WRITE_L (r
); /* write result */
1890 CC_IIZZ_L (r
); /* set cc's */
1891 cc
= cc
| temp
; /* error? set V */
1894 case BISB2
: case BISB3
:
1895 r
= op1
| op0
; /* calc result */
1896 WRITE_B (r
); /* store result */
1897 CC_IIZP_B (r
); /* set cc's */
1900 case BISW2
: case BISW3
:
1901 r
= op1
| op0
; /* calc result */
1902 WRITE_W (r
); /* store result */
1903 CC_IIZP_W (r
); /* set cc's */
1906 case BISL2
: case BISL3
:
1907 r
= op1
| op0
; /* calc result */
1908 WRITE_L (r
); /* store result */
1909 CC_IIZP_L (r
); /* set cc's */
1912 case BICB2
: case BICB3
:
1913 r
= op1
& ~op0
; /* calc result */
1914 WRITE_B (r
); /* store result */
1915 CC_IIZP_B (r
); /* set cc's */
1918 case BICW2
: case BICW3
:
1919 r
= op1
& ~op0
; /* calc result */
1920 WRITE_W (r
); /* store result */
1921 CC_IIZP_W (r
); /* set cc's */
1924 case BICL2
: case BICL3
:
1925 r
= op1
& ~op0
; /* calc result */
1926 WRITE_L (r
); /* store result */
1927 CC_IIZP_L (r
); /* set cc's */
1930 case XORB2
: case XORB3
:
1931 r
= op1
^ op0
; /* calc result */
1932 WRITE_B (r
); /* store result */
1933 CC_IIZP_B (r
); /* set cc's */
1936 case XORW2
: case XORW3
:
1937 r
= op1
^ op0
; /* calc result */
1938 WRITE_W (r
); /* store result */
1939 CC_IIZP_W (r
); /* set cc's */
1942 case XORL2
: case XORL3
:
1943 r
= op1
^ op0
; /* calc result */
1944 WRITE_L (r
); /* store result */
1945 CC_IIZP_L (r
); /* set cc's */
1948 /* MOVQ - movq src.rq, dst.wq
1951 spec = register/memory flag
1952 rn = register number
1958 WRITE_Q (op0
, op1
); /* store result */
1959 CC_IIZP_Q (op0
, op1
);
1962 /* Shifts - op shf.rb,src.rl,dst.wl
1964 opnd[0] = shift count
1966 spec = register/memory flag
1967 rn = register number
1972 j
= op0
% 32; /* reduce sc, mod 32 */
1973 if (j
) r
= ((((uint32
) op1
) << j
) |
1974 (((uint32
) op1
) >> (32 - j
))) & LMASK
;
1976 WRITE_L (r
); /* store result */
1977 CC_IIZP_L (r
); /* set cc's */
1981 if (op0
& BSIGN
) { /* right shift? */
1982 temp
= 0x100 - op0
; /* get |shift| */
1983 if (temp
> 31) r
= (op1
& LSIGN
)? LMASK
: 0; /* sc > 31? */
1984 else r
= op1
>> temp
; /* shift */
1985 WRITE_L (r
); /* store result */
1986 CC_IIZZ_L (r
); /* set cc's */
1990 if (op0
> 31) r
= temp
= 0; /* sc > 31? */
1992 r
= (((uint32
) op1
) << op0
) & LMASK
; /* shift */
1993 temp
= r
>> op0
; /* shift back */
1995 WRITE_L (r
); /* store result */
1996 CC_IIZZ_L (r
); /* set cc's */
1997 if (op1
!= temp
) { V_INTOV
; } /* bits lost? */
2002 r
= op_ashq (opnd
, &rh
, &flg
); /* do qw shift */
2003 WRITE_Q (r
, rh
); /* store results */
2004 CC_IIZZ_Q (r
, rh
); /* set cc's */
2005 if (flg
) { V_INTOV
; } /* if ovflo, set */
2008 /* EMUL - emul mplr.rl,mpcn.rl,add.rl,dst.wq
2013 op3:op4 = destination (.wq)
2017 r
= op_emul (op0
, op1
, &rh
); /* calc 64b result */
2018 r
= r
+ op2
; /* add 32b value */
2019 rh
= rh
+ (((uint32
) r
) < ((uint32
) op2
)) - /* into 64b result */
2020 ((op2
& LSIGN
)? 1: 0);
2021 WRITE_Q (r
, rh
); /* write result */
2022 CC_IIZZ_Q (r
, rh
); /* set cc's */
2025 /* EDIV - ediv dvr.rl,dvd.rq,quo.wl,rem.wl
2028 op1:op2 = dividend (.rq)
2029 op3:op4 = quotient address (.wl)
2030 op5:op6 = remainder address (.wl)
2034 if (op5
< 0) Read (op6
, L_LONG
, WA
); /* wtest remainder */
2035 if (op0
== 0) { /* divide by zero? */
2036 flg
= CC_V
; /* set V */
2037 r
= opnd
[1]; /* quo = low divd */
2038 rh
= 0; /* rem = 0 */
2039 SET_TRAP (TRAP_DIVZRO
); /* set trap */
2042 r
= op_ediv (opnd
, &rh
, &flg
); /* extended divide */
2043 if (flg
) { INTOV
; } /* if ovf+IV, set trap */
2045 if (op3
>= 0) R
[op3
] = r
; /* store quotient */
2046 else Write (op4
, r
, L_LONG
, WA
);
2047 if (op5
>= 0) R
[op5
] = rh
; /* store remainder */
2048 else Write (op6
, rh
, L_LONG
, WA
);
2049 CC_IIZZ_L (r
); /* set cc's */
2050 cc
= cc
| flg
; /* set V if required */
2053 /* Control instructions */
2055 /* Simple branches and subroutine calls */
2058 BRANCHB (brdisp
); /* branch */
2059 if ((PC
== fault_PC
) && (PSL_GETIPL (PSL
) == 0x1F))
2064 BRANCHW (brdisp
); /* branch */
2065 if ((PC
== fault_PC
) && (PSL_GETIPL (PSL
) == 0x1F))
2070 Write (SP
- 4, PC
, L_LONG
, WA
); /* push PC on stk */
2071 SP
= SP
- 4; /* decr stk ptr */
2072 BRANCHB (brdisp
); /* branch */
2076 Write (SP
- 4, PC
, L_LONG
, WA
); /* push PC on stk */
2077 SP
= SP
- 4; /* decr stk ptr */
2078 BRANCHW (brdisp
); /* branch */
2082 if (!(cc
& CC_N
)) BRANCHB (brdisp
); /* br if N = 0 */
2086 if (cc
& CC_N
) BRANCHB (brdisp
); /* br if N = 1 */
2090 if (!(cc
& CC_Z
)) BRANCHB (brdisp
); /* br if Z = 0 */
2094 if (cc
& CC_Z
) BRANCHB (brdisp
); /* br if Z = 1 */
2098 if (!(cc
& CC_V
)) BRANCHB (brdisp
); /* br if V = 0 */
2102 if (cc
& CC_V
) BRANCHB (brdisp
); /* br if V = 1 */
2106 if (!(cc
& CC_C
)) BRANCHB (brdisp
); /* br if C = 0 */
2110 if (cc
& CC_C
) BRANCHB (brdisp
); /* br if C = 1 */
2114 if (!(cc
& (CC_N
| CC_Z
))) BRANCHB (brdisp
); /* br if N | Z = 0 */
2118 if (cc
& (CC_N
| CC_Z
)) BRANCHB (brdisp
); /* br if N | Z = 1 */
2122 if (!(cc
& (CC_C
| CC_Z
))) BRANCHB (brdisp
); /* br if C | Z = 0 */
2126 if (cc
& (CC_C
| CC_Z
)) BRANCHB (brdisp
); /* br if C | Z = 1 */
2129 /* Simple jumps and subroutine calls - op addr.ab
2135 Write (SP
- 4, PC
, L_LONG
, WA
); /* push PC on stk */
2136 SP
= SP
- 4; /* decr stk ptr */
2139 JUMP (op0
); /* jump */
2143 temp
= Read (SP
, L_LONG
, RA
); /* get top of stk */
2144 SP
= SP
+ 4; /* incr stk ptr */
2148 /* SOB instructions - op idx.ml,disp.bb
2151 spec = register/memory flag
2152 rn = register number
2157 r
= op0
- 1; /* decr index */
2158 WRITE_L (r
); /* store result */
2159 CC_IIZP_L (r
); /* set cc's */
2160 V_SUB_L (r
, 1, op0
); /* test for ovflo */
2161 if (r
>= 0) BRANCHB (brdisp
); /* if >= 0, branch */
2165 r
= op0
- 1; /* decr index */
2166 WRITE_L (r
); /* store result */
2167 CC_IIZP_L (r
); /* set cc's */
2168 V_SUB_L (r
, 1, op0
); /* test for ovflo */
2169 if (r
> 0) BRANCHB (brdisp
); /* if >= 0, branch */
2172 /* AOB instructions - op limit.rl,idx.ml,disp.bb
2176 spec = register/memory flag
2177 rn = register number
2182 r
= op1
+ 1; /* incr index */
2183 WRITE_L (r
); /* store result */
2184 CC_IIZP_L (r
); /* set cc's */
2185 V_ADD_L (r
, 1, op1
); /* test for ovflo */
2186 if (r
< op0
) BRANCHB (brdisp
); /* if < lim, branch */
2190 r
= op1
+ 1; /* incr index */
2191 WRITE_L (r
); /* store result */
2192 CC_IIZP_L (r
); /* set cc's */
2193 V_ADD_L (r
, 1, op1
); /* test for ovflo */
2194 if (r
<= op0
) BRANCHB (brdisp
); /* if < lim, branch */
2197 /* ACB instructions - op limit.rx,add.rx,index.mx,disp.bw
2202 spec = register/memory flag
2203 rn = register number
2208 r
= (op2
+ op1
) & BMASK
; /* calc result */
2209 WRITE_B (r
); /* store result */
2210 CC_IIZP_B (r
); /* set cc's */
2211 V_ADD_B (r
, op1
, op2
); /* test for ovflo */
2212 if ((op1
& BSIGN
)? (SXTB (r
) >= SXTB (op0
)):
2213 (SXTB (r
) <= SXTB (op0
))) BRANCHW (brdisp
);
2217 r
= (op2
+ op1
) & WMASK
; /* calc result */
2218 WRITE_W (r
); /* store result */
2219 CC_IIZP_W (r
); /* set cc's */
2220 V_ADD_W (r
, op1
, op2
); /* test for ovflo */
2221 if ((op1
& WSIGN
)? (SXTW (r
) >= SXTW (op0
)):
2222 (SXTW (r
) <= SXTW (op0
))) BRANCHW (brdisp
);
2226 r
= (op2
+ op1
) & LMASK
; /* calc result */
2227 WRITE_L (r
); /* store result */
2228 CC_IIZP_L (r
); /* set cc's */
2229 V_ADD_L (r
, op1
, op2
); /* test for ovflo */
2230 if ((op1
& LSIGN
)? (r
>= op0
): (r
<= op0
))
2234 /* CASE instructions - casex sel.rx,base.rx,lim.rx
2242 r
= (op0
- op1
) & BMASK
; /* sel - base */
2243 CC_CMP_B (r
, op2
); /* r:limit, set cc's */
2244 if (r
> op2
) JUMP (PC
+ ((op2
+ 1) * 2)); /* r > limit (unsgnd)? */
2246 temp
= Read (PC
+ (r
* 2), L_WORD
, RA
);
2252 r
= (op0
- op1
) & WMASK
; /* sel - base */
2253 CC_CMP_W (r
, op2
); /* r:limit, set cc's */
2254 if (r
> op2
) JUMP (PC
+ ((op2
+ 1) * 2)); /* r > limit (unsgnd)? */
2256 temp
= Read (PC
+ (r
* 2), L_WORD
, RA
);
2262 r
= (op0
- op1
) & LMASK
; /* sel - base */
2263 CC_CMP_L (r
, op2
); /* r:limit, set cc's */
2264 if (((uint32
) r
) > ((uint32
) op2
)) /* r > limit (unsgnd)? */
2265 JUMP (PC
+ ((op2
+ 1) * 2));
2267 temp
= Read (PC
+ (r
* 2), L_WORD
, RA
);
2272 /* Branch on bit instructions - bbxy pos.rl,op.wb,disp.bb
2275 opnd[1] = register number/memory flag
2276 opnd[2] = memory address, if memory
2280 if (op_bb_n (opnd
, acc
)) BRANCHB (brdisp
); /* br if bit set */
2284 if (!op_bb_n (opnd
, acc
)) BRANCHB (brdisp
); /* br if bit clr */
2287 case BBSS
: case BBSSI
:
2288 if (op_bb_x (opnd
, 1, acc
)) BRANCHB (brdisp
); /* br if set, set */
2291 case BBCC
: case BBCCI
:
2292 if (!op_bb_x (opnd
, 0, acc
)) BRANCHB (brdisp
); /* br if clr, clr*/
2296 if (op_bb_x (opnd
, 0, acc
)) BRANCHB (brdisp
); /* br if clr, set */
2300 if (!op_bb_x (opnd
, 1, acc
)) BRANCHB (brdisp
); /* br if set, clr */
2304 if (op0
& 1) BRANCHB (brdisp
); /* br if bit set */
2308 if ((op0
& 1) == 0) BRANCHB (brdisp
); /* br if bit clear */
2311 /* Extract field instructions - ext?v pos.rl,size.rb,base.wb,dst.wl
2315 opnd[2] = register number/memory flag
2316 opnd[3] = register content/memory address
2317 spec = register/memory flag
2318 rn = register number
2323 r
= op_extv (opnd
, vfldrp1
, acc
); /* get field */
2324 if (r
& byte_sign
[op1
]) r
= r
| ~byte_mask
[op1
];
2325 WRITE_L (r
); /* store field */
2326 CC_IIZP_L (r
); /* set cc's */
2330 r
= op_extv (opnd
, vfldrp1
, acc
); /* get field */
2331 WRITE_L (r
); /* store field */
2332 CC_IIZP_L (r
); /* set cc's */
2335 /* Compare field instructions - cmp?v pos.rl,size.rb,base.wb,src2.rl
2339 opnd[2] = register number/memory flag
2340 opnd[3] = register content/memory address
2345 r
= op_extv (opnd
, vfldrp1
, acc
); /* get field */
2346 if (r
& byte_sign
[op1
]) r
= r
| ~byte_mask
[op1
];
2347 CC_CMP_L (r
, op4
); /* set cc's */
2351 r
= op_extv (opnd
, vfldrp1
, acc
); /* get field */
2352 CC_CMP_L (r
, op4
); /* set cc's */
2355 /* Find first field instructions - ff? pos.rl,size.rb,base.wb,dst.wl
2359 opnd[2] = register number/memory flag
2360 opnd[3] = register content/memory address
2361 spec = register/memory flag
2362 rn = register number
2367 r
= op_extv (opnd
, vfldrp1
, acc
); /* get field */
2368 temp
= op_ffs (r
, op1
); /* find first 1 */
2369 WRITE_L (op0
+ temp
); /* store result */
2370 cc
= r
? 0: CC_Z
; /* set cc's */
2374 r
= op_extv (opnd
, vfldrp1
, acc
); /* get field */
2375 r
= r
^ byte_mask
[op1
]; /* invert bits */
2376 temp
= op_ffs (r
, op1
); /* find first 1 */
2377 WRITE_L (op0
+ temp
); /* store result */
2378 cc
= r
? 0: CC_Z
; /* set cc's */
2381 /* Insert field instruction - insv src.rl,pos.rb,size.rl,base.wb
2386 opnd[3] = register number/memory flag
2387 opnd[4] = register content/memory address
2391 op_insv (opnd
, vfldrp1
, acc
); /* insert field */
2394 /* Call and return - call? arg.rx,proc.ab
2397 opnd[1] = procedure address
2401 cc
= op_call (opnd
, TRUE
, acc
);
2405 cc
= op_call (opnd
, FALSE
, acc
);
2412 /* Miscellaneous instructions */
2415 if (PSL
& PSL_CUR
) RSVD_INST_FAULT
; /* not kern? rsvd inst */
2416 else if (cpu_unit
.flags
& UNIT_CONH
) /* halt to console? */
2417 cc
= con_halt (CON_HLTINS
, cc
); /* enter firmware */
2419 ABORT (STOP_HALT
); /* halt to simulator */
2427 cc
= intexc (SCB_BPT
, cc
, 0, IE_EXC
);
2433 cc
= intexc (SCB_XFC
, cc
, 0, IE_EXC
);
2438 if (opnd
[0] & PSW_MBZ
) RSVD_OPND_FAULT
;
2439 PSL
= PSL
| (opnd
[0] & ~CC_MASK
);
2440 cc
= cc
| (opnd
[0] & CC_MASK
);
2444 if (opnd
[0] & PSW_MBZ
) RSVD_OPND_FAULT
;
2445 PSL
= PSL
& ~opnd
[0];
2455 op_pushr (opnd
, acc
);
2459 op_popr (opnd
, acc
);
2463 if ((op0
< op1
) || (op0
> op2
)) SET_TRAP (TRAP_SUBSCR
);
2464 r
= (op0
+ op4
) * op3
;
2469 /* Queue and interlocked queue */
2472 cc
= op_insque (opnd
, acc
);
2476 cc
= op_remque (opnd
, acc
);
2480 cc
= op_insqhi (opnd
, acc
);
2484 cc
= op_insqti (opnd
, acc
);
2488 cc
= op_remqhi (opnd
, acc
);
2492 cc
= op_remqti (opnd
, acc
);
2495 /* String instructions */
2497 case MOVC3
: case MOVC5
:
2498 cc
= op_movc (opnd
, opc
& 4, acc
);
2501 case CMPC3
: case CMPC5
:
2502 cc
= op_cmpc (opnd
, opc
& 4, acc
);
2505 case LOCC
: case SKPC
:
2506 cc
= op_locskp (opnd
, opc
& 1, acc
);
2509 case SCANC
: case SPANC
:
2510 cc
= op_scnspn (opnd
, opc
& 1, acc
);
2513 /* Floating point instructions */
2515 case TSTF
: case TSTD
:
2532 if ((r
= op_movfd (op0
)) == 0) op1
= 0;
2538 if ((r
= op_movg (op0
)) == 0) op1
= 0;
2544 r
= op_mnegfd (op0
);
2550 if ((r
= op_mnegfd (op0
)) == 0) op1
= 0;
2556 if ((r
= op_mnegg (op0
)) == 0) op1
= 0;
2562 cc
= op_cmpfd (op0
, 0, op1
, 0);
2566 cc
= op_cmpfd (op0
, op1
, op2
, op3
);
2570 cc
= op_cmpg (op0
, op1
, op2
, op3
);
2574 r
= op_cvtifdg (SXTB (op0
), NULL
, opc
);
2580 r
= op_cvtifdg (SXTW (op0
), NULL
, opc
);
2586 r
= op_cvtifdg (op0
, NULL
, opc
);
2591 case CVTBD
: case CVTBG
:
2592 r
= op_cvtifdg (SXTB (op0
), &rh
, opc
);
2597 case CVTWD
: case CVTWG
:
2598 r
= op_cvtifdg (SXTW (op0
), &rh
, opc
);
2603 case CVTLD
: case CVTLG
:
2604 r
= op_cvtifdg (op0
, &rh
, opc
);
2609 case CVTFB
: case CVTDB
: case CVTGB
:
2610 r
= op_cvtfdgi (opnd
, &flg
, opc
) & BMASK
;
2613 if (flg
) { V_INTOV
; }
2616 case CVTFW
: case CVTDW
: case CVTGW
:
2617 r
= op_cvtfdgi (opnd
, &flg
, opc
) & WMASK
;
2620 if (flg
) { V_INTOV
; }
2623 case CVTFL
: case CVTDL
: case CVTGL
:
2624 case CVTRFL
: case CVTRDL
: case CVTRGL
:
2625 r
= op_cvtfdgi (opnd
, &flg
, opc
) & LMASK
;
2628 if (flg
) { V_INTOV
; }
2638 r
= op_cvtdf (opnd
);
2644 r
= op_cvtfg (opnd
, &rh
);
2650 r
= op_cvtgf (opnd
);
2655 case ADDF2
: case ADDF3
:
2656 r
= op_addf (opnd
, FALSE
);
2661 case ADDD2
: case ADDD3
:
2662 r
= op_addd (opnd
, &rh
, FALSE
);
2667 case ADDG2
: case ADDG3
:
2668 r
= op_addg (opnd
, &rh
, FALSE
);
2673 case SUBF2
: case SUBF3
:
2674 r
= op_addf (opnd
, TRUE
);
2679 case SUBD2
: case SUBD3
:
2680 r
= op_addd (opnd
, &rh
, TRUE
);
2685 case SUBG2
: case SUBG3
:
2686 r
= op_addg (opnd
, &rh
, TRUE
);
2691 case MULF2
: case MULF3
:
2697 case MULD2
: case MULD3
:
2698 r
= op_muld (opnd
, &rh
);
2703 case MULG2
: case MULG3
:
2704 r
= op_mulg (opnd
, &rh
);
2709 case DIVF2
: case DIVF3
:
2715 case DIVD2
: case DIVD3
:
2716 r
= op_divd (opnd
, &rh
);
2721 case DIVG2
: case DIVG3
:
2722 r
= op_divg (opnd
, &rh
);
2728 r
= op_addf (opnd
+ 1, FALSE
); /* add + index */
2729 temp
= op_cmpfd (r
, 0, op0
, 0); /* result : limit */
2730 WRITE_L (r
); /* write result */
2731 CC_IIZP_FP (r
); /* set cc's */
2732 if ((temp
& CC_Z
) || ((op1
& FPSIGN
)? /* test br cond */
2733 !(temp
& CC_N
): (temp
& CC_N
))) BRANCHW (brdisp
);
2737 r
= op_addd (opnd
+ 2, &rh
, FALSE
);
2738 temp
= op_cmpfd (r
, rh
, op0
, op1
);
2741 if ((temp
& CC_Z
) || ((op2
& FPSIGN
)? /* test br cond */
2742 !(temp
& CC_N
): (temp
& CC_N
))) BRANCHW (brdisp
);
2746 r
= op_addg (opnd
+ 2, &rh
, FALSE
);
2747 temp
= op_cmpg (r
, rh
, op0
, op1
);
2750 if ((temp
& CC_Z
) || ((op2
& FPSIGN
)? /* test br cond */
2751 !(temp
& CC_N
): (temp
& CC_N
))) BRANCHW (brdisp
);
2759 op3:op4 = integer destination (int.wl)
2760 op5:op6 = floating destination (flt.wl)
2764 r
= op_emodf (opnd
, &temp
, &flg
);
2765 if (op5
< 0) Read (op6
, L_LONG
, WA
);
2766 if (op3
>= 0) R
[op3
] = temp
;
2767 else Write (op4
, temp
, L_LONG
, WA
);
2770 if (flg
) { V_INTOV
; }
2775 op0:op1 = multiplier
2777 op3:op4 = multiplicand
2778 op5:op6 = integer destination (int.wl)
2779 op7:op8 = floating destination (flt.wq)
2783 r
= op_emodd (opnd
, &rh
, &temp
, &flg
);
2785 Read (op8
, L_BYTE
, WA
);
2786 Read ((op8
+ 7) & LMASK
, L_BYTE
, WA
);
2788 if (op5
>= 0) R
[op5
] = temp
;
2789 else Write (op6
, temp
, L_LONG
, WA
);
2792 if (flg
) { V_INTOV
; }
2796 r
= op_emodg (opnd
, &rh
, &temp
, &flg
);
2798 Read (op8
, L_BYTE
, WA
);
2799 Read ((op8
+ 7) & LMASK
, L_BYTE
, WA
);
2801 if (op5
>= 0) R
[op5
] = temp
;
2802 else Write (op6
, temp
, L_LONG
, WA
);
2805 if (flg
) { V_INTOV
; }
2811 op_polyf (opnd
, acc
);
2816 op_polyd (opnd
, acc
);
2821 op_polyg (opnd
, acc
);
2825 /* Operating system instructions */
2827 case CHMK
: case CHME
: case CHMS
: case CHMU
:
2828 cc
= op_chm (opnd
, cc
, opc
); /* CHMx */
2829 GET_CUR
; /* update cur mode */
2830 SET_IRQL
; /* update intreq */
2834 cc
= op_rei (acc
); /* REI */
2835 GET_CUR
; /* update cur mode */
2836 SET_IRQL
; /* update intreq */
2847 case PROBER
: case PROBEW
:
2848 cc
= (cc
& CC_C
) | op_probe (opnd
, opc
& 1);
2852 cc
= (cc
& CC_C
) | op_mtpr (opnd
);
2853 SET_IRQL
; /* update intreq */
2862 /* CIS or emulated instructions */
2865 case MOVP
: case CMPP3
: case CMPP4
: case CVTLP
:
2866 case CVTPS
: case CVTSP
: case CVTTP
: case CVTPT
:
2867 case ADDP4
: case ADDP6
: case SUBP4
: case SUBP6
:
2868 case MULP
: case DIVP
: case ASHP
: case CRC
:
2869 case MOVTC
: case MOVTUC
: case MATCHC
: case EDITPC
:
2870 cc
= op_cis (opnd
, cc
, opc
, acc
);
2873 /* Octaword or reserved instructions */
2875 case PUSHAO
: case MOVAO
: case CLRO
: case MOVO
:
2876 case TSTH
: case MOVH
: case MNEGH
: case CMPH
:
2877 case CVTBH
: case CVTWH
: case CVTLH
:
2878 case CVTHB
: case CVTHW
: case CVTHL
: case CVTRHL
:
2879 case CVTFH
: case CVTDH
: case CVTGH
:
2880 case CVTHF
: case CVTHD
: case CVTHG
:
2881 case ADDH2
: case ADDH3
: case SUBH2
: case SUBH3
:
2882 case MULH2
: case MULH3
: case DIVH2
: case DIVH3
:
2883 case ACBH
: case POLYH
: case EMODH
:
2884 cc
= op_octa (opnd
, cc
, opc
, acc
, spec
, va
);
2885 if (cc
& LSIGN
) { /* ACBH branch? */
2887 cc
= cc
& CC_MASK
; /* mask off flag */
2896 ABORT (STOP_UNKNOWN
);
2897 } /* end sim_instr */
2899 /* Prefetch buffer routine
2901 Prefetch buffer state
2903 ibufl, ibufh = the prefetch buffer
2904 ibcnt = number of bytes available (0, 4, 8)
2907 The get_istr routines fetches the indicated number of bytes from
2908 the prefetch buffer. Although it is complicated, it is faster
2909 than calling Read on every byte of the instruction stream.
2911 If the prefetch buffer has enough bytes, the required bytes are
2912 extracted from the prefetch buffer and returned. If it does not
2913 have enough bytes, enough prefetch words are fetched until there
2914 are. A longword is only prefetched if data is needed from it,
2915 so any translation errors are real.
2918 SIM_INLINE_GCC int32
get_istr (int32 lnt
, int32 acc
)
2923 while ((bo
+ lnt
) > ibcnt
) { /* until enuf bytes */
2924 if ((ppc
< 0) || (VA_GETOFF (ppc
) == 0)) { /* PPC inv, xpg? */
2925 ppc
= Test ((PC
+ ibcnt
) & ~03, RD
, &t
); /* xlate PC */
2926 if (ppc
< 0) Read ((PC
+ ibcnt
) & ~03, L_LONG
, RA
);
2928 if (ibcnt
== 0) ibufl
= ReadLP (ppc
); /* fill low */
2929 else ibufh
= ReadLP (ppc
); /* or high */
2930 ppc
= ppc
+ 4; /* incr phys PC */
2931 ibcnt
= ibcnt
+ 4; /* incr ibuf cnt */
2933 PC
= PC
+ lnt
; /* incr PC */
2934 if (lnt
== L_BYTE
) val
= (ibufl
>> (bo
<< 3)) & BMASK
; /* byte? */
2935 else if (lnt
== L_WORD
) { /* word? */
2936 if (bo
== 3) val
= ((ibufl
>> 24) & 0xFF) | ((ibufh
& 0xFF) << 8);
2937 else val
= (ibufl
>> (bo
<< 3)) & WMASK
;
2939 else if (bo
) { /* unaligned lw? */
2941 val
= (((ibufl
>> sc
) & align
[bo
]) | (((uint32
) ibufh
) << (32 - sc
)));
2943 else val
= ibufl
; /* aligned lw */
2944 if ((bo
+ lnt
) >= 4) { /* retire ibufl? */
2951 /* Read octaword specifier */
2953 int32
ReadOcta (int32 va
, int32
*opnd
, int32 j
, int32 acc
)
2955 opnd
[j
++] = Read (va
, L_LONG
, acc
);
2956 opnd
[j
++] = Read (va
+ 4, L_LONG
, acc
);
2957 opnd
[j
++] = Read (va
+ 8, L_LONG
, acc
);
2958 opnd
[j
++] = Read (va
+ 12, L_LONG
, acc
);
2962 /* Check new PSL IPL for idle start
2963 Checked only on exception or REI, not on MTPR #IPL,
2964 to allow for local locking within the idle loop */
2966 int32
cpu_psl_ipl_idle (int32 newpsl
)
2968 if (((newpsl
^ PSL
) & PSL_IPL
) != 0) {
2969 sim_cancel (&cpu_unit
);
2970 if (sim_idle_enab
&& ((newpsl
& PSL_CUR
) == 0)) {
2971 uint32 newipl
= PSL_GETIPL (newpsl
);
2972 if (cpu_idle_ipl_mask
& (1u << newipl
))
2973 sim_activate (&cpu_unit
, cpu_idle_wait
);
2979 /* Idle timer has expired with no PSL change */
2981 t_stat
cpu_idle_svc (UNIT
*uptr
)
2984 sim_idle (TMR_CLK
, FALSE
);
2990 t_stat
cpu_reset (DEVICE
*dptr
)
2995 PSL
= PSL_IS
| PSL_IPL1F
;
2999 if (M
== NULL
) M
= (uint32
*) calloc (((uint32
) MEMSIZE
) >> 2, sizeof (uint32
));
3000 if (M
== NULL
) return SCPE_MEM
;
3001 pcq_r
= find_reg ("PCQ", NULL
, dptr
);
3002 if (pcq_r
) pcq_r
->qptr
= 0;
3003 else return SCPE_IERR
;
3004 sim_brk_types
= sim_brk_dflt
= SWMASK ('E');
3005 return build_dib_tab ();
3008 /* Memory examine */
3010 t_stat
cpu_ex (t_value
*vptr
, t_addr exta
, UNIT
*uptr
, int32 sw
)
3013 uint32 addr
= (uint32
) exta
;
3015 if (vptr
== NULL
) return SCPE_ARG
;
3016 if (sw
& SWMASK ('V')) {
3017 int32 acc
= cpu_get_vsw (sw
);
3018 addr
= Test (addr
, acc
, &st
);
3020 else addr
= addr
& PAMASK
;
3021 if (ADDR_IS_MEM (addr
) || ADDR_IS_CDG (addr
) ||
3022 ADDR_IS_ROM (addr
) || ADDR_IS_NVR (addr
)) {
3023 *vptr
= (uint32
) ReadB (addr
);
3029 /* Memory deposit */
3031 t_stat
cpu_dep (t_value val
, t_addr exta
, UNIT
*uptr
, int32 sw
)
3034 uint32 addr
= (uint32
) exta
;
3036 if (sw
& SWMASK ('V')) {
3037 int32 acc
= cpu_get_vsw (sw
);
3038 addr
= Test (addr
, acc
, &st
);
3040 else addr
= addr
& PAMASK
;
3041 if (ADDR_IS_MEM (addr
) || ADDR_IS_CDG (addr
) ||
3042 ADDR_IS_NVR (addr
)) {
3043 WriteB (addr
, (int32
) val
);
3046 if (ADDR_IS_ROM (addr
)) {
3047 rom_wr_B (addr
, (int32
) val
);
3053 /* Memory allocation */
3055 t_stat
cpu_set_size (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
3061 if ((val
<= 0) || (val
> MAXMEMSIZE_X
)) return SCPE_ARG
;
3062 for (i
= val
; i
< MEMSIZE
; i
= i
+ 4) mc
= mc
| M
[i
>> 2];
3063 if ((mc
!= 0) && !get_yn ("Really truncate memory [N]?", FALSE
))
3065 nM
= (uint32
*) calloc (val
>> 2, sizeof (uint32
));
3066 if (nM
== NULL
) return SCPE_MEM
;
3067 clim
= (uint32
) ((((uint32
) val
) < MEMSIZE
)? val
: MEMSIZE
);
3068 for (i
= 0; i
< clim
; i
= i
+ 4) nM
[i
>> 2] = M
[i
>> 2];
3075 /* Virtual address translation */
3077 t_stat
cpu_show_virt (FILE *of
, UNIT
*uptr
, int32 val
, void *desc
)
3080 char *cptr
= (char *) desc
;
3083 static const char *mm_str
[] = {
3084 "Access control violation",
3086 "Process PTE access control violation",
3087 "Process PTE length violation",
3088 "Translation not valid",
3090 "Process PTE translation not valid"
3094 va
= (uint32
) get_uint (cptr
, 16, 0xFFFFFFFF, &r
);
3096 int32 acc
= cpu_get_vsw (sim_switches
);
3097 pa
= Test (va
, acc
, &st
);
3098 if (st
== PR_OK
) fprintf (of
, "Virtual %-X = physical %-X\n", va
, pa
);
3099 else fprintf (of
, "Virtual %-X: %s\n", va
, mm_str
[st
]);
3103 fprintf (of
, "Invalid argument\n");
3107 /* Get access mode for examine, deposit, show virtual */
3109 int32
cpu_get_vsw (int32 sw
)
3113 set_map_reg (); /* update dyn reg */
3114 if (sw
& SWMASK ('K')) md
= KERN
;
3115 else if (sw
& SWMASK ('E')) md
= EXEC
;
3116 else if (sw
& SWMASK ('S')) md
= SUPV
;
3117 else if (sw
& SWMASK ('U')) md
= USER
;
3118 else md
= PSL_GETCUR (PSL
);
3119 return ACC_MASK (md
);
3124 t_stat
cpu_set_hist (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
3130 for (i
= 0; i
< hst_lnt
; i
++) hst
[i
].iPC
= 0;
3134 lnt
= (int32
) get_uint (cptr
, 10, HIST_MAX
, &r
);
3135 if ((r
!= SCPE_OK
) || (lnt
&& (lnt
< HIST_MIN
))) return SCPE_ARG
;
3143 hst
= (InstHistory
*) calloc (lnt
, sizeof (InstHistory
));
3144 if (hst
== NULL
) return SCPE_MEM
;
3152 t_stat
cpu_show_hist (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
3154 int32 i
, k
, di
, lnt
, numspec
;
3155 char *cptr
= (char *) desc
;
3158 extern const char *opcode
[];
3159 extern t_value
*sim_eval
;
3160 extern t_stat
fprint_sym (FILE *ofile
, t_addr addr
, t_value
*val
,
3161 UNIT
*uptr
, int32 sw
);
3163 if (hst_lnt
== 0) return SCPE_NOFNC
; /* enabled? */
3165 lnt
= (int32
) get_uint (cptr
, 10, hst_lnt
, &r
);
3166 if ((r
!= SCPE_OK
) || (lnt
== 0)) return SCPE_ARG
;
3169 di
= hst_p
- lnt
; /* work forward */
3170 if (di
< 0) di
= di
+ hst_lnt
;
3171 fprintf (st
, "PC PSL IR\n\n");
3172 for (k
= 0; k
< lnt
; k
++) { /* print specified */
3173 h
= &hst
[(di
++) % hst_lnt
]; /* entry pointer */
3174 if (h
->iPC
== 0) continue; /* filled in? */
3175 fprintf(st
, "%08X %08X| ", h
->iPC
, h
->PSL
); /* PC, PSL */
3176 numspec
= drom
[h
->opc
][0] & DR_NSPMASK
; /* #specifiers */
3177 if (opcode
[h
->opc
] == NULL
) /* undefined? */
3178 fprintf (st
, "%03X (undefined)", h
->opc
);
3179 else if (h
->PSL
& PSL_FPD
) /* FPD set? */
3180 fprintf (st
, "%s FPD set", opcode
[h
->opc
]);
3182 for (i
= 0; i
< INST_SIZE
; i
++) sim_eval
[i
] = h
->inst
[i
];
3183 if ((fprint_sym (st
, h
->iPC
, sim_eval
, &cpu_unit
, SWMASK ('M'))) > 0)
3184 fprintf (st
, "%03X (undefined)", h
->opc
);
3185 if ((numspec
> 1) ||
3186 ((numspec
== 1) && (drom
[h
->opc
][1] < BB
))) {
3187 if (cpu_show_opnd (st
, h
, 0)) { /* operands; more? */
3188 if (cpu_show_opnd (st
, h
, 1)) { /* 2nd line; more? */
3189 cpu_show_opnd (st
, h
, 2); /* octa, 3rd/4th */
3190 cpu_show_opnd (st
, h
, 3);
3195 fputc ('\n', st
); /* end line */
3200 t_bool
cpu_show_opnd (FILE *st
, InstHistory
*h
, int32 line
)
3203 int32 numspec
, i
, j
, disp
;
3206 numspec
= drom
[h
->opc
][0] & DR_NSPMASK
; /* #specifiers */
3207 fputs ("\n ", st
); /* space */
3208 for (i
= 1, j
= 0, more
= FALSE
; i
<= numspec
; i
++) { /* loop thru specs */
3209 disp
= drom
[h
->opc
][i
]; /* specifier type */
3210 if (disp
== RG
) disp
= RQ
; /* fix specials */
3211 else if (disp
>= BB
) break; /* ignore branches */
3212 else switch (disp
& (DR_LNMASK
|DR_ACMASK
)) {
3214 case RB
: case RW
: case RL
: /* read */
3215 case AB
: case AW
: case AL
: case AQ
: case AO
: /* address */
3216 case MB
: case MW
: case ML
: /* modify */
3217 if (line
== 0) fprintf (st
, " %08X", h
->opnd
[j
]);
3218 else fputs (" ", st
);
3221 case RQ
: case MQ
: /* read, modify quad */
3222 if (line
<= 1) fprintf (st
, " %08X", h
->opnd
[j
+ line
]);
3223 else fputs (" ", st
);
3224 if (line
== 0) more
= TRUE
;
3227 case RO
: case MO
: /* read, modify octa */
3228 fprintf (st
, " %08X", h
->opnd
[j
+ line
]);
3232 case WB
: case WW
: case WL
: case WQ
: case WO
: /* write */
3233 if (line
== 0) fprintf (st
, " %08X", h
->opnd
[j
+ 1]);
3234 else fputs (" ", st
);
3247 static struct os_idle os_tab
[] = {
3256 /* Set and show idle */
3258 t_stat
cpu_set_idle (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
3263 for (i
= 0; os_tab
[i
].name
!= NULL
; i
++) {
3264 if (strcmp (os_tab
[i
].name
, cptr
) == 0) {
3265 cpu_idle_type
= i
+ 1;
3266 cpu_idle_ipl_mask
= os_tab
[i
].mask
;
3267 return sim_set_idle (uptr
, val
, cptr
, desc
);
3272 return sim_set_idle (uptr
, val
, cptr
, desc
);
3275 t_stat
cpu_show_idle (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
3277 if (sim_idle_enab
&& (cpu_idle_type
!= 0))
3278 fprintf (st
, "idle enabled=%s", os_tab
[cpu_idle_type
- 1].name
);
3279 else fprintf (st
, "idle disabled");