First Commit of my working state
[simh.git] / VAX / vax_cpu.c
1 /* vax_cpu.c: VAX CPU
2
3 Copyright (c) 1998-2008, Robert M Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 cpu VAX central processor
27
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
67 (from Mark Pizzolato)
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
72
73 The register state for the VAX is:
74
75 R[0:15] general registers
76 PSL<31:0> processor status longword
77 TP<30> trace pending
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
99
100 The VAX has a variable length instruction format with up to six operands:
101
102 opcode byte
103 operand 1 specifier
104 :
105 operand n specifier
106
107 Each operand specifier is a byte consisting of an addressing mode, a
108 register, and possibly 1-8 bytes of extension:
109
110 number name extension mnemonic operation
111
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
117 op <- M[Rn]
118 8 autoincrement - (Rn)+ op <- M[Rn]
119 Rn <- Rn + length
120 9 auto deferred - @(Rn)+ op <- M[M[Rn]]
121 Rn <- Rn + 4
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]]
128
129 When the general register is the PC, certain modes are forbidden, and
130 others have special interpretations:
131
132 4F index fault
133 5F register fault
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]]
144
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.
149
150 General notes:
151
152 1. Traps and interrupts. Variable trpirq microencodes the outstanding
153 trap request (if any) and the level of the highest outstanding
154 interrupt (if any).
155
156 2. Interrupt requests are maintained in the int_req array, one word per
157 interrupt level, one bit per device.
158
159 3. Adding I/O devices. These modules must be modified:
160
161 vax_defs.h add device address and interrupt definitions
162 vax_sys.c add sim_devices table entry
163 */
164
165 /* Definitions */
166
167 #include "vax_defs.h"
168
169 #define OP_MEM -1
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))
175
176 #define OPND_SIZE 16
177 #define INST_SIZE 52
178 #define op0 opnd[0]
179 #define op1 opnd[1]
180 #define op2 opnd[2]
181 #define op3 opnd[3]
182 #define op4 opnd[4]
183 #define op5 opnd[5]
184 #define op6 opnd[6]
185 #define op7 opnd[7]
186 #define op8 opnd[8]
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); \
195 else R[rn] = (r)
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); \
201 } \
202 else { \
203 if (rn >= nSP) RSVD_ADDR_FAULT; \
204 R[rn] = rl; \
205 R[rn + 1] = rh; \
206 }
207
208 #define HIST_MIN 64
209 #define HIST_MAX 65536
210
211 typedef struct {
212 int32 iPC;
213 int32 PSL;
214 int32 opc;
215 uint8 inst[INST_SIZE];
216 int32 opnd[OPND_SIZE];
217 } InstHistory;
218
219 uint32 *M = NULL; /* memory */
220 int32 R[16]; /* registers */
221 int32 STK[5]; /* stack pointers */
222 int32 PSL; /* PSL */
223 int32 SCBB = 0; /* SCB base */
224 int32 PCBB = 0; /* PCB base */
225 int32 P0BR = 0; /* P0 mem mgt */
226 int32 P0LR = 0;
227 int32 P1BR = 0; /* P1 mem mgt */
228 int32 P1LR = 0;
229 int32 SBR = 0; /* S0 mem mgt */
230 int32 SLR = 0;
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 */
240 int32 mem_err = 0;
241 int32 crd_err = 0;
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 */
247 int32 badabo = 0;
248 int32 cpu_astop = 0;
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 */
255 jmp_buf save_env;
256 REG *pcq_r = NULL; /* PC queue reg ptr */
257 int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
258 InstHistory *hst = NULL; /* instruction history */
259
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
269 };
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
279 };
280 const uint32 align[4] = {
281 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF
282 };
283
284 /* External and forward references */
285
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;
291
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);
364
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);
380
381 /* CPU data structures
382
383 cpu_dev CPU device descriptor
384 cpu_unit CPU unit
385 cpu_reg CPU register list
386 cpu_mod CPU modifier list
387 */
388
389 UNIT cpu_unit = {
390 UDATA (&cpu_idle_svc, UNIT_FIX|UNIT_BINK, INITMEMSIZE)
391 };
392
393 REG cpu_reg[] = {
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) },
443 { NULL }
444 };
445
446 MTAB cpu_mod[] = {
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 },
460 #endif
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 },
465 { 0 }
466 };
467
468 DEBTAB cpu_deb[] = {
469 { "INTEXC", LOG_CPU_I },
470 { "REI", LOG_CPU_R },
471 { "CONTEXT", LOG_CPU_P },
472 { NULL, 0 }
473 };
474
475 DEVICE cpu_dev = {
476 "CPU", &cpu_unit, cpu_reg, cpu_mod,
477 1, 16, 32, 1, 16, 8,
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
482 };
483
484 t_stat sim_instr (void)
485 {
486 volatile int32 opc, cc; /* used by setjmp */
487 int32 acc; /* set by setjmp */
488 int abortval;
489 t_stat r;
490
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 */
497 return SCPE_STOP;
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 */
505
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 */
511 }
512 else if (abortval < 0) { /* mm or rsrv or int */
513 int32 i, delta;
514 if ((PSL & PSL_FPD) == 0) { /* FPD? no recovery */
515 for (i = 0; i < recqptr; i++) { /* unwind inst */
516 int32 rrn, rlnt;
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;
521 }
522 }
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 */
528
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 */
535 break;
536
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 */
541 GET_CUR;
542 in_ie = 1;
543 Write (SP - 4, p1, L_LONG, WA); /* write arith param */
544 SP = SP - 4;
545 in_ie = 0;
546 break;
547
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 */
553 GET_CUR;
554 }
555 else {
556 cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */
557 GET_CUR;
558 in_ie = 1;
559 Write (SP - 8, p1, L_LONG, WA); /* write mm params */
560 Write (SP - 4, p2, L_LONG, WA);
561 SP = SP - 8;
562 in_ie = 0;
563 }
564 break;
565
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 */
569 in_ie = 0;
570 GET_CUR; /* PSL<cur> changed */
571 break;
572
573 case 1: /* interrupt */
574 break; /* just proceed */
575 default: /* other */
576 badabo = abortval; /* save code */
577 ABORT (STOP_UNKABO); /* panic */
578 } /* end case */
579 } /* end else */
580
581 /* Main instruction loop */
582
583 for ( ;; ) {
584
585 int32 spec, disp, rn, index, numspec;
586 int32 vfldrp1, brdisp, flg, mstat;
587 int32 i, j, r, rh, temp;
588 uint32 va, iad;
589 int32 opnd[OPND_SIZE]; /* operand queue */
590
591 if (cpu_astop) {
592 cpu_astop = 0;
593 ABORT (SCPE_STOP);
594 }
595 fault_PC = PC;
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 */
601 }
602
603 /* Test for non-instruction dispatches, in SRM order
604
605 - trap or interrupt (trpirq != 0)
606 - PSL<tp> set
607
608 If any of these conditions are met, re-dispatch; otherwise,
609 set PSL<tp> from PSL<t>.
610 */
611
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 */
616 in_ie = 1;
617 Write (SP - 4, temp, L_LONG, WA); /* write parameter */
618 SP = SP - 4;
619 in_ie = 0;
620 }
621 else if (temp = GET_IRQL (trpirq)) { /* interrupt? */
622 int32 vec;
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 */
628 }
629 else if (temp >= IPL_HMIN) /* hardware req? */
630 vec = get_vector (temp); /* get vector */
631 else if (temp > IPL_SMAX) ABORT (STOP_UIPL);
632 else {
633 vec = SCB_IPLSOFT + (temp << 2);
634 SISR = SISR & ~(1u << temp);
635 }
636 if (vec) cc = intexc (vec, cc, temp, IE_INT);/* take intr */
637 GET_CUR; /* set cur mode */
638 }
639 else trpirq = 0; /* clear everything */
640 SET_IRQL; /* eval interrupts */
641 continue;
642 }
643
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 */
649 continue;
650 }
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 */
655 }
656 } /* end PSL event */
657
658 if (sim_brk_summ &&
659 sim_brk_test ((uint32) PC, SWMASK ('E'))) { /* breakpoint? */
660 ABORT (STOP_IBKPT); /* stop simulation */
661 }
662
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 */
668 }
669 numspec = drom[opc][0]; /* get # specs */
670 if (PSL & PSL_FPD) {
671 if ((numspec & DR_F) == 0) RSVD_INST_FAULT;
672 }
673 else {
674 numspec = numspec & DR_NSPMASK; /* get # specifiers */
675
676 /* Specifier flows. Operands are parsed and placed into queue opnd.
677
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
687
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.
692 */
693
694 for (i = 1, j = 0; i <= numspec; i++) { /* loop thru specs */
695 disp = drom[opc][i]; /* get dispatch */
696 if (disp >= BB) {
697 GET_ISTR (brdisp, DR_LNT (disp & 1));
698 break;
699 }
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 */
704
705 /* Short literal - only read access permitted */
706
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:
711 opnd[j++] = spec;
712 break;
713
714 case SH0|RQ: case SH1|RQ: case SH2|RQ: case SH3|RQ:
715 opnd[j++] = spec;
716 opnd[j++] = 0;
717 break;
718
719 case SH0|RO: case SH1|RO: case SH2|RO: case SH3|RO:
720 opnd[j++] = spec;
721 opnd[j++] = 0;
722 opnd[j++] = 0;
723 opnd[j++] = 0;
724 break;
725
726 case SH0|RF: case SH1|RF: case SH2|RF: case SH3|RF:
727 opnd[j++] = (spec << 4) | 0x4000;
728 break;
729
730 case SH0|RD: case SH1|RD: case SH2|RD: case SH3|RD:
731 opnd[j++] = (spec << 4) | 0x4000;
732 opnd[j++] = 0;
733 break;
734
735 case SH0|RG: case SH1|RG: case SH2|RG: case SH3|RG:
736 opnd[j++] = (spec << 1) | 0x4000;
737 opnd[j++] = 0;
738 break;
739
740 case SH0|RH: case SH1|RH: case SH2|RH: case SH3|RH:
741 opnd[j++] = ((spec & 0x7) << 29) | (0x4000 | ((spec >> 3) & 0x7));
742 opnd[j++] = 0;
743 opnd[j++] = 0;
744 opnd[j++] = 0;
745 break;
746
747 /* Register */
748
749 case GRN|RB: case GRN|MB:
750 CHECK_FOR_PC;
751 opnd[j++] = R[rn] & BMASK;
752 break;
753
754 case GRN|RW: case GRN|MW:
755 CHECK_FOR_PC;
756 opnd[j++] = R[rn] & WMASK;
757 break;
758
759 case GRN|VB:
760 vfldrp1 = R[(rn + 1) & RGMASK];
761 case GRN|WB: case GRN|WW: case GRN|WL: case GRN|WQ: case GRN|WO:
762 opnd[j++] = rn;
763 case GRN|RL: case GRN|RF: case GRN|ML:
764 CHECK_FOR_PC;
765 opnd[j++] = R[rn];
766 break;
767
768 case GRN|RQ: case GRN|RD: case GRN|RG: case GRN|MQ:
769 CHECK_FOR_SP;
770 opnd[j++] = R[rn];
771 opnd[j++] = R[rn + 1];
772 break;
773
774 case GRN|RO: case GRN|RH: case GRN|MO:
775 CHECK_FOR_AP;
776 opnd[j++] = R[rn];
777 opnd[j++] = R[rn + 1];
778 opnd[j++] = R[rn + 2];
779 opnd[j++] = R[rn + 3];
780 break;
781
782 /* Register deferred, autodecrement */
783
784 case RGD|VB:
785 case RGD|WB: case RGD|WW: case RGD|WL: case RGD|WQ: case RGD|WO:
786 opnd[j++] = OP_MEM;
787 case RGD|AB: case RGD|AW: case RGD|AL: case RGD|AQ: case RGD|AO:
788 CHECK_FOR_PC;
789 va = opnd[j++] = R[rn];
790 break;
791
792 case ADC|VB:
793 case ADC|WB: case ADC|WW: case ADC|WL: case ADC|WQ: case ADC|WO:
794 opnd[j++] = OP_MEM;
795 case ADC|AB: case ADC|AW: case ADC|AL: case ADC|AQ: case ADC|AO:
796 CHECK_FOR_PC;
797 va = opnd[j++] = R[rn] = R[rn] - DR_LNT (disp);
798 recq[recqptr++] = RQ_REC (disp, rn);
799 break;
800
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:
805 CHECK_FOR_PC;
806 opnd[j++] = Read (va = R[rn], DR_LNT (disp), RA);
807 break;
808
809 case ADC|RQ: case ADC|RD: case ADC|RG:
810 R[rn] = R[rn] - 8;
811 recq[recqptr++] = RQ_REC (disp, rn);
812 case RGD|RQ: case RGD|RD: case RGD|RG:
813 CHECK_FOR_PC;
814 opnd[j++] = Read (va = R[rn], L_LONG, RA);
815 opnd[j++] = Read (R[rn] + 4, L_LONG, RA);
816 break;
817
818 case ADC|RO: case ADC|RH:
819 R[rn] = R[rn] - 16;
820 recq[recqptr++] = RQ_REC (disp, rn);
821 case RGD|RO: case RGD|RH:
822 CHECK_FOR_PC;
823 j = ReadOcta (va = R[rn], opnd, j, RA);
824 break;
825
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:
830 CHECK_FOR_PC;
831 opnd[j++] = Read (va = R[rn], DR_LNT (disp), WA);
832 break;
833
834 case ADC|MQ:
835 R[rn] = R[rn] - 8;
836 recq[recqptr++] = RQ_REC (disp, rn);
837 case RGD|MQ:
838 CHECK_FOR_PC;
839 opnd[j++] = Read (va = R[rn], L_LONG, WA);
840 opnd[j++] = Read (R[rn] + 4, L_LONG, WA);
841 break;
842
843 case ADC|MO:
844 R[rn] = R[rn] - 16;
845 recq[recqptr++] = RQ_REC (disp, rn);
846 case RGD|MO:
847 CHECK_FOR_PC;
848 j = ReadOcta (va = R[rn], opnd, j, WA);
849 break;
850
851 /* Autoincrement */
852
853 case AIN|VB:
854 case AIN|WB: case AIN|WW: case AIN|WL: case AIN|WQ: case AIN|WO:
855 /* CHECK_FOR_PC; */
856 opnd[j++] = OP_MEM;
857 case AIN|AB: case AIN|AW: case AIN|AL: case AIN|AQ: case AIN|AO:
858 va = opnd[j++] = R[rn];
859 if (rn == nPC) {
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);
866 }
867 }
868 else GET_ISTR (temp, DR_LNT (disp));
869 }
870 else {
871 R[rn] = R[rn] + DR_LNT (disp);
872 recq[recqptr++] = RQ_REC (disp, rn);
873 }
874 break;
875
876 case AIN|RB: case AIN|RW: case AIN|RL: case AIN|RF:
877 va = R[rn];
878 if (rn == nPC) {
879 GET_ISTR (opnd[j++], DR_LNT (disp));
880 }
881 else {
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);
885 }
886 break;
887
888 case AIN|RQ: case AIN|RD: case AIN|RG:
889 va = R[rn];
890 if (rn == nPC) {
891 GET_ISTR (opnd[j++], L_LONG);
892 GET_ISTR (opnd[j++], L_LONG);
893 }
894 else {
895 opnd[j++] = Read (va, L_LONG, RA);
896 opnd[j++] = Read (va + 4, L_LONG, RA);
897 R[rn] = R[rn] + 8;
898 recq[recqptr++] = RQ_REC (disp, rn);
899 }
900 break;
901
902 case AIN|RO: case AIN|RH:
903 va = R[rn];
904 if (rn == nPC) {
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);
909 }
910 else {
911 j = ReadOcta (va, opnd, j, RA);
912 R[rn] = R[rn] + 16;
913 recq[recqptr++] = RQ_REC (disp, rn);
914 }
915 break;
916
917 case AIN|MB: case AIN|MW: case AIN|ML:
918 va = R[rn];
919 if (rn == nPC) {
920 GET_ISTR (opnd[j++], DR_LNT (disp));
921 }
922 else {
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);
926 }
927 break;
928
929 case AIN|MQ:
930 va = R[rn];
931 if (rn == nPC) {
932 GET_ISTR (opnd[j++], L_LONG);
933 GET_ISTR (opnd[j++], L_LONG);
934 }
935 else {
936 opnd[j++] = Read (va, L_LONG, WA);
937 opnd[j++] = Read (va + 4, L_LONG, WA);
938 R[rn] = R[rn] + 8;
939 recq[recqptr++] = RQ_REC (disp, rn);
940 }
941 break;
942
943 case AIN|MO:
944 va = R[rn];
945 if (rn == nPC) {
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);
950 }
951 else {
952 j = ReadOcta (va, opnd, j, WA);
953 R[rn] = R[rn] + 16;
954 recq[recqptr++] = RQ_REC (disp, rn);
955 }
956 break;
957
958 /* Autoincrement deferred */
959
960 case AID|VB:
961 case AID|WB: case AID|WW: case AID|WL: case AID|WQ: case AID|WO:
962 opnd[j++] = OP_MEM;
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); }
965 else {
966 va = opnd[j++] = Read (R[rn], L_LONG, RA);
967 R[rn] = R[rn] + 4;
968 recq[recqptr++] = RQ_REC (AID|RL, rn);
969 }
970 break;
971
972 case AID|RB: case AID|RW: case AID|RL: case AID|RF:
973 if (rn == nPC) {
974 GET_ISTR (va, L_LONG);
975 }
976 else {
977 va = Read (R[rn], L_LONG, RA);
978 R[rn] = R[rn] + 4;
979 recq[recqptr++] = RQ_REC (AID|RL, rn);
980 }
981 opnd[j++] = Read (va, DR_LNT (disp), RA);
982 break;
983
984 case AID|RQ: case AID|RD: case AID|RG:
985 if (rn == nPC) {
986 GET_ISTR (va, L_LONG);
987 }
988 else {
989 va = Read (R[rn], L_LONG, RA);
990 R[rn] = R[rn] + 4;
991 recq[recqptr++] = RQ_REC (AID|RL, rn);
992 }
993 opnd[j++] = Read (va, L_LONG, RA);
994 opnd[j++] = Read (va + 4, L_LONG, RA);
995 break;
996
997 case AID|RO: case AID|RH:
998 if (rn == nPC) {
999 GET_ISTR (va, L_LONG);
1000 }
1001 else {
1002 va = Read (R[rn], L_LONG, RA);
1003 R[rn] = R[rn] + 4;
1004 recq[recqptr++] = RQ_REC (AID|RL, rn);
1005 }
1006 j = ReadOcta (va, opnd, j, RA);
1007 break;
1008
1009 case AID|MB: case AID|MW: case AID|ML:
1010 if (rn == nPC) {
1011 GET_ISTR (va, L_LONG);
1012 }
1013 else {
1014 va = Read (R[rn], L_LONG, RA);
1015 R[rn] = R[rn] + 4;
1016 recq[recqptr++] = RQ_REC (AID|RL, rn);
1017 }
1018 opnd[j++] = Read (va, DR_LNT (disp), WA);
1019 break;
1020
1021 case AID|MQ:
1022 if (rn == nPC) {
1023 GET_ISTR (va, L_LONG);
1024 }
1025 else {
1026 va = Read (R[rn], L_LONG, RA);
1027 R[rn] = R[rn] + 4;
1028 recq[recqptr++] = RQ_REC (AID|RL, rn);
1029 }
1030 opnd[j++] = Read (va, L_LONG, WA);
1031 opnd[j++] = Read (va + 4, L_LONG, WA);
1032 break;
1033
1034 case AID|MO:
1035 if (rn == nPC) {
1036 GET_ISTR (va, L_LONG);
1037 }
1038 else {
1039 va = Read (R[rn], L_LONG, RA);
1040 R[rn] = R[rn] + 4;
1041 recq[recqptr++] = RQ_REC (AID|RL, rn);
1042 }
1043 j = ReadOcta (va, opnd, j, WA);
1044 break;
1045
1046 /* Byte displacement */
1047
1048 case BDP|VB:
1049 case BDP|WB: case BDP|WW: case BDP|WL: case BDP|WQ: case BDP|WO:
1050 opnd[j++] = OP_MEM;
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);
1054 break;
1055
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);
1060 break;
1061
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);
1067 break;
1068
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);
1073 break;
1074
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);
1079 break;
1080
1081 case BDP|MQ:
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);
1086 break;
1087
1088 case BDP|MO:
1089 GET_ISTR (temp, L_BYTE);
1090 va = R[rn] + SXTB (temp);
1091 j = ReadOcta (va, opnd, j, WA);
1092 break;
1093
1094 /* Byte displacement deferred */
1095
1096 case BDD|VB:
1097 case BDD|WB: case BDD|WW: case BDD|WL: case BDD|WQ: case BDD|WO:
1098 opnd[j++] = OP_MEM;
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);
1103 break;
1104
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);
1110 break;
1111
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);
1118 break;
1119
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);
1125 break;
1126
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);
1132 break;
1133
1134 case BDD|MQ:
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);
1140 break;
1141
1142 case BDD|MO:
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);
1147 break;
1148
1149 /* Word displacement */
1150
1151 case WDP|VB:
1152 case WDP|WB: case WDP|WW: case WDP|WL: case WDP|WQ: case WDP|WO:
1153 opnd[j++] = OP_MEM;
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);
1157 break;
1158
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);
1163 break;
1164
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);
1170 break;
1171
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);
1176 break;
1177
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);
1182 break;
1183
1184 case WDP|MQ:
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);
1189 break;
1190
1191 case WDP|MO:
1192 GET_ISTR (temp, L_WORD);
1193 va = R[rn] + SXTW (temp);
1194 j = ReadOcta (va, opnd, j, WA);
1195 break;
1196
1197 /* Word displacement deferred */
1198
1199 case WDD|VB:
1200 case WDD|WB: case WDD|WW: case WDD|WL: case WDD|WQ: case WDD|WO:
1201 opnd[j++] = OP_MEM;
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);
1206 break;
1207
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);
1213 break;
1214
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);
1221 break;
1222
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);
1228 break;
1229
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);
1235 break;
1236
1237 case WDD|MQ:
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);
1243 break;
1244
1245 case WDD|MO:
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);
1250 break;
1251
1252 /* Longword displacement */
1253
1254 case LDP|VB:
1255 case LDP|WB: case LDP|WW: case LDP|WL: case LDP|WQ: case LDP|WO:
1256 opnd[j++] = OP_MEM;
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;
1260 break;
1261
1262 case LDP|RB: case LDP|RW: case LDP|RL: case LDP|RF:
1263 GET_ISTR (temp, L_LONG);
1264 va = R[rn] + temp;
1265 opnd[j++] = Read (va, DR_LNT (disp), RA);
1266 break;
1267
1268 case LDP|RQ: case LDP|RD: case LDP|RG:
1269 GET_ISTR (temp, L_LONG);
1270 va = R[rn] + temp;
1271 opnd[j++] = Read (va, L_LONG, RA);
1272 opnd[j++] = Read (va + 4, L_LONG, RA);
1273 break;
1274
1275 case LDP|RO: case LDP|RH:
1276 GET_ISTR (temp, L_LONG);
1277 va = R[rn] + temp;
1278 j = ReadOcta (va, opnd, j, RA);
1279 break;
1280
1281 case LDP|MB: case LDP|MW: case LDP|ML:
1282 GET_ISTR (temp, L_LONG);
1283 va = R[rn] + temp;
1284 opnd[j++] = Read (va, DR_LNT (disp), WA);
1285 break;
1286
1287 case LDP|MQ:
1288 GET_ISTR (temp, L_LONG);
1289 va = R[rn] + temp;
1290 opnd[j++] = Read (va, L_LONG, WA);
1291 opnd[j++] = Read (va + 4, L_LONG, WA);
1292 break;
1293
1294 case LDP|MO:
1295 GET_ISTR (temp, L_LONG);
1296 va = R[rn] + temp;
1297 j = ReadOcta (va, opnd, j, WA);
1298 break;
1299
1300 /* Longword displacement deferred */
1301
1302 case LDD|VB:
1303 case LDD|WB: case LDD|WW: case LDD|WL: case LDD|WQ: case LDD|WO:
1304 opnd[j++] = OP_MEM;
1305 case LDD|AB: case LDD|AW: case LDD|AL: case LDD|AQ: case LDD|AO:
1306 GET_ISTR (temp, L_LONG);
1307 iad = R[rn] + temp;
1308 va = opnd[j++] = Read (iad, L_LONG, RA);
1309 break;
1310
1311 case LDD|RB: case LDD|RW: case LDD|RL: case LDD|RF:
1312 GET_ISTR (temp, L_LONG);
1313 iad = R[rn] + temp;
1314 va = Read (iad, L_LONG, RA);
1315 opnd[j++] = Read (va, DR_LNT (disp), RA);
1316 break;
1317
1318 case LDD|RQ: case LDD|RD: case LDD|RG:
1319 GET_ISTR (temp, L_LONG);
1320 iad = R[rn] + temp;
1321 va = Read (iad, L_LONG, RA);
1322 opnd[j++] = Read (va, L_LONG, RA);
1323 opnd[j++] = Read (va + 4, L_LONG, RA);
1324 break;
1325
1326 case LDD|RO: case LDD|RH:
1327 GET_ISTR (temp, L_LONG);
1328 iad = R[rn] + temp;
1329 va = Read (iad, L_LONG, RA);
1330 j = ReadOcta (va, opnd, j, RA);
1331 break;
1332
1333 case LDD|MB: case LDD|MW: case LDD|ML:
1334 GET_ISTR (temp, L_LONG);
1335 iad = R[rn] + temp;
1336 va = Read (iad, L_LONG, RA);
1337 opnd[j++] = Read (va, DR_LNT (disp), WA);
1338 break;
1339
1340 case LDD|MQ:
1341 GET_ISTR (temp, L_LONG);
1342 iad = R[rn] + temp;
1343 va = Read (iad, L_LONG, RA);
1344 opnd[j++] = Read (va, L_LONG, WA);
1345 opnd[j++] = Read (va + 4, L_LONG, WA);
1346 break;
1347
1348 case LDD|MO:
1349 GET_ISTR (temp, L_LONG);
1350 iad = R[rn] + temp;
1351 va = Read (iad, L_LONG, RA);
1352 j = ReadOcta (va, opnd, j, WA);
1353 break;
1354
1355 /* Index */
1356
1357 case IDX|VB:
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:
1363 CHECK_FOR_PC;
1364 index = R[rn] << (disp & DR_LNMASK);
1365 GET_ISTR (spec, L_BYTE);
1366 rn = spec & RGMASK;
1367 switch (spec & ~RGMASK) {
1368 case ADC:
1369 R[rn] = R[rn] - DR_LNT (disp);
1370 recq[recqptr++] = RQ_REC (ADC | (disp & DR_LNMASK), rn);
1371 case RGD:
1372 CHECK_FOR_PC;
1373 index = index + R[rn];
1374 break;
1375
1376 case AIN:
1377 CHECK_FOR_PC;
1378 index = index + R[rn];
1379 R[rn] = R[rn] + DR_LNT (disp);
1380 recq[recqptr++] = RQ_REC (AIN | (disp & DR_LNMASK), rn);
1381 break;
1382
1383 case AID:
1384 if (rn == nPC) {
1385 GET_ISTR (temp, L_LONG);
1386 }
1387 else {
1388 temp = Read (R[rn], L_LONG, RA);
1389 R[rn] = R[rn] + 4;
1390 recq[recqptr++] = RQ_REC (AID|RL, rn);
1391 }
1392 index = temp + index;
1393 break;
1394
1395 case BDP:
1396 GET_ISTR (temp, L_BYTE);
1397 index = index + R[rn] + SXTB (temp);
1398 break;
1399
1400 case BDD:
1401 GET_ISTR (temp, L_BYTE);
1402 index = index + Read (R[rn] + SXTB (temp), L_LONG, RA);
1403 break;
1404
1405 case WDP:
1406 GET_ISTR (temp, L_WORD);
1407 index = index + R[rn] + SXTW (temp);
1408 break;
1409
1410 case WDD:
1411 GET_ISTR (temp, L_WORD);
1412 index = index + Read (R[rn] + SXTW (temp), L_LONG, RA);
1413 break;
1414
1415 case LDP:
1416 GET_ISTR (temp, L_LONG);
1417 index = index + R[rn] + temp;
1418 break;
1419
1420 case LDD:
1421 GET_ISTR (temp, L_LONG);
1422 index = index + Read (R[rn] + temp, L_LONG, RA);
1423 break;
1424
1425 default:
1426 RSVD_ADDR_FAULT; /* end case idxspec */
1427 }
1428
1429 switch (disp & (DR_ACMASK|DR_SPFLAG|DR_LNMASK)) { /* case acc+lnt */
1430 case VB:
1431 case WB: case WW: case WL: case WQ: case WO:
1432 opnd[j++] = OP_MEM;
1433 case AB: case AW: case AL: case AQ: case AO:
1434 va = opnd[j++] = index;
1435 break;
1436
1437 case RB: case RW: case RL: case RF:
1438 opnd[j++] = Read (va = index, DR_LNT (disp), RA);
1439 break;
1440
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);
1444 break;
1445
1446 case RO: case RH:
1447 j = ReadOcta (va = index, opnd, j, RA);
1448 break;
1449
1450 case MB: case MW: case ML:
1451 opnd[j++] = Read (va = index, DR_LNT (disp), WA);
1452 break;
1453
1454 case MQ:
1455 opnd[j++] = Read (va = index, L_LONG, WA);
1456 opnd[j++] = Read (index + 4, L_LONG, WA);
1457 break;
1458
1459 case MO:
1460 j = ReadOcta (va = index, opnd, j, WA);
1461 break;
1462
1463 default: /* all others */
1464 RSVD_ADDR_FAULT; /* fault */
1465 break;
1466 } /* end case access/lnt */
1467 break; /* end index */
1468
1469 default: /* all others */
1470 RSVD_ADDR_FAULT; /* fault */
1471 break;
1472 } /* end case spec */
1473 } /* end for */
1474 } /* end if not FPD */
1475
1476 /* Optionally record instruction history */
1477
1478 if (hst_lnt) {
1479 int32 lim;
1480 t_value wd;
1481
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;
1492 else {
1493 hst[hst_p].inst[0] = hst[hst_p].inst[1] = 0xFF;
1494 break;
1495 }
1496 }
1497 hst_p = hst_p + 1;
1498 if (hst_p >= hst_lnt) hst_p = 0;
1499 }
1500
1501 /* Dispatch to instructions */
1502
1503 switch (opc) {
1504
1505 /* Single operand instructions with dest, write only - CLRx dst.wx
1506
1507 spec = reg/memory flag
1508 rn = register number
1509 va = virtual address
1510 */
1511
1512 case CLRB:
1513 WRITE_B (0); /* store result */
1514 CC_ZZ1P; /* set cc's */
1515 break;
1516
1517 case CLRW:
1518 WRITE_W (0); /* store result */
1519 CC_ZZ1P; /* set cc's */
1520 break;
1521
1522 case CLRL:
1523 WRITE_L (0); /* store result */
1524 CC_ZZ1P; /* set cc's */
1525 break;
1526
1527 case CLRQ:
1528 WRITE_Q (0, 0); /* store result */
1529 CC_ZZ1P; /* set cc's */
1530 break;
1531
1532 /* Single operand instructions with source, read only - TSTx src.rx
1533
1534 opnd[0] = source
1535 */
1536
1537 case TSTB:
1538 CC_IIZZ_B (op0); /* set cc's */
1539 break;
1540
1541 case TSTW:
1542 CC_IIZZ_W (op0); /* set cc's */
1543 break;
1544
1545 case TSTL:
1546 CC_IIZZ_L (op0); /* set cc's */
1547 break;
1548
1549 /* Single operand instructions with source, read/write - op src.mx
1550
1551 opnd[0] = operand
1552 spec = reg/mem flag
1553 rn = register number
1554 va = operand address
1555 */
1556
1557 case INCB:
1558 r = (op0 + 1) & BMASK; /* calc result */
1559 WRITE_B (r); /* store result */
1560 CC_ADD_B (r, 1, op0); /* set cc's */
1561 break;
1562
1563 case INCW:
1564 r = (op0 + 1) & WMASK; /* calc result */
1565 WRITE_W (r); /* store result */
1566 CC_ADD_W (r, 1, op0); /* set cc's */
1567 break;
1568
1569 case INCL:
1570 r = (op0 + 1) & LMASK; /* calc result */
1571 WRITE_L (r); /* store result */
1572 CC_ADD_L (r, 1, op0); /* set cc's */
1573 break;
1574
1575 case DECB:
1576 r = (op0 - 1) & BMASK; /* calc result */
1577 WRITE_B (r); /* store result */
1578 CC_SUB_B (r, 1, op0); /* set cc's */
1579 break;
1580
1581 case DECW:
1582 r = (op0 - 1) & WMASK; /* calc result */
1583 WRITE_W (r); /* store result */
1584 CC_SUB_W (r, 1, op0); /* set cc's */
1585 break;
1586
1587 case DECL:
1588 r = (op0 - 1) & LMASK; /* calc result */
1589 WRITE_L (r); /* store result */
1590 CC_SUB_L (r, 1, op0); /* set cc's */
1591 break;
1592
1593 /* Push instructions - PUSHL src.rl or PUSHAx src.ax
1594
1595 opnd[0] = source
1596 */
1597
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 */
1602 break;
1603
1604 /* Moves, converts, and ADAWI - op src.rx, dst.wx
1605
1606 opnd[0] = source
1607 spec = reg/mem flag
1608 rn = register number
1609 va = operand address
1610 */
1611
1612 case MOVB:
1613 WRITE_B (op0); /* result */
1614 CC_IIZP_B (op0); /* set cc's */
1615 break;
1616
1617 case MOVW: case MOVZBW:
1618 WRITE_W (op0); /* result */
1619 CC_IIZP_W (op0); /* set cc's */
1620 break;
1621
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 */
1626 break;
1627
1628 case MCOMB:
1629 r = op0 ^ BMASK; /* compl opnd */
1630 WRITE_B (r); /* store result */
1631 CC_IIZP_B (r); /* set cc's */
1632 break;
1633
1634 case MCOMW:
1635 r = op0 ^ WMASK; /* compl opnd */
1636 WRITE_W (r); /* store result */
1637 CC_IIZP_W (r); /* set cc's */
1638 break;
1639
1640 case MCOML:
1641 r = op0 ^ LMASK; /* compl opnd */
1642 WRITE_L (r); /* store result */
1643 CC_IIZP_L (r); /* set cc's */
1644 break;
1645
1646 case MNEGB:
1647 r = (-op0) & BMASK; /* negate opnd */
1648 WRITE_B (r); /* store result */
1649 CC_SUB_B (r, op0, 0); /* set cc's */
1650 break;
1651
1652 case MNEGW:
1653 r = (-op0) & WMASK; /* negate opnd */
1654 WRITE_W (r); /* store result */
1655 CC_SUB_W (r, op0, 0); /* set cc's */
1656 break;
1657
1658 case MNEGL:
1659 r = (-op0) & LMASK; /* negate opnd */
1660 WRITE_L (r); /* store result */
1661 CC_SUB_L (r, op0, 0); /* set cc's */
1662 break;
1663
1664 case CVTBW:
1665 r = SXTBW (op0); /* ext sign */
1666 WRITE_W (r); /* store result */
1667 CC_IIZZ_W (r); /* set cc's */
1668 break;
1669
1670 case CVTBL:
1671 r = SXTB (op0); /* ext sign */
1672 WRITE_L (r); /* store result */
1673 CC_IIZZ_L (r); /* set cc's */
1674 break;
1675
1676 case CVTWL:
1677 r = SXTW (op0); /* ext sign */
1678 WRITE_L (r); /* store result */
1679 CC_IIZZ_L (r); /* set cc's */
1680 break;
1681
1682 case CVTLB:
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; }
1687 break;
1688
1689 case CVTLW:
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; }
1694 break;
1695
1696 case CVTWB:
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; }
1702 break;
1703
1704 case ADAWI:
1705 if (op1 >= 0) temp = R[op1] & WMASK; /* reg? ADDW2 */
1706 else {
1707 if (op2 & 1) RSVD_OPND_FAULT; /* mem? chk align */
1708 temp = Read (op2, L_WORD, WA); /* ok, ADDW2 */
1709 }
1710 r = (op0 + temp) & WMASK;
1711 WRITE_W (r);
1712 CC_ADD_W (r, op0, temp); /* set cc's */
1713 break;
1714
1715 /* Integer operates, 2 operand, read only - op src1.rx, src2.rx
1716
1717 opnd[0] = source1
1718 opnd[1] = source2
1719 */
1720
1721 case CMPB:
1722 CC_CMP_B (op0, op1); /* set cc's */
1723 break;
1724
1725 case CMPW:
1726 CC_CMP_W (op0, op1); /* set cc's */
1727 break;
1728
1729 case CMPL:
1730 CC_CMP_L (op0, op1); /* set cc's */
1731 break;
1732
1733 case BITB:
1734 r = op1 & op0; /* calc result */
1735 CC_IIZP_B (r); /* set cc's */
1736 break;
1737
1738 case BITW:
1739 r = op1 & op0; /* calc result */
1740 CC_IIZP_W (r); /* set cc's */
1741 break;
1742
1743 case BITL:
1744 r = op1 & op0; /* calc result */
1745 CC_IIZP_L (r); /* set cc's */
1746 break;
1747
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
1750
1751 opnd[0] = source1
1752 opnd[1] = source2
1753 spec = register/memory flag
1754 rn = register number
1755 va = memory address
1756 */
1757
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 */
1762 break;
1763
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 */
1768 break;
1769
1770 case ADWC:
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 */
1775 break;
1776
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 */
1781 break;
1782
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 */
1787 break;
1788
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 */
1793 break;
1794
1795 case SBWC:
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 */
1800 break;
1801
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 */
1806 break;
1807
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; }
1814 break;
1815
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; }
1822 break;
1823
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 */
1829 break;
1830
1831 case DIVB2: case DIVB3:
1832 if (op0 == 0) { /* div by zero? */
1833 r = op1;
1834 temp = CC_V;
1835 SET_TRAP (TRAP_DIVZRO);
1836 }
1837 else if ((op0 == BMASK) && (op1 == BSIGN)) { /* overflow? */
1838 r = op1;
1839 temp = CC_V;
1840 INTOV;
1841 }
1842 else {
1843 r = SXTB (op1) / SXTB (op0); /* ok, divide */
1844 temp = 0;
1845 }
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 */
1850 break;
1851
1852 case DIVW2: case DIVW3:
1853 if (op0 == 0) { /* div by zero? */
1854 r = op1;
1855 temp = CC_V;
1856 SET_TRAP (TRAP_DIVZRO);
1857 }
1858 else if ((op0 == WMASK) && (op1 == WSIGN)) { /* overflow? */
1859 r = op1;
1860 temp = CC_V;
1861 INTOV;
1862 }
1863 else {
1864 r = SXTW (op1) / SXTW (op0); /* ok, divide */
1865 temp = 0;
1866 }
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 */
1871 break;
1872
1873 case DIVL2: case DIVL3:
1874 if (op0 == 0) { /* div by zero? */
1875 r = op1;
1876 temp = CC_V;
1877 SET_TRAP (TRAP_DIVZRO);
1878 }
1879 else if ((op0 == LMASK) && (op1 == LSIGN)) { /* overflow? */
1880 r = op1;
1881 temp = CC_V;
1882 INTOV;
1883 }
1884 else {
1885 r = op1 / op0; /* ok, divide */
1886 temp = 0;
1887 }
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 */
1892 break;
1893
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 */
1898 break;
1899
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 */
1904 break;
1905
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 */
1910 break;
1911
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 */
1916 break;
1917
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 */
1922 break;
1923
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 */
1928 break;
1929
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 */
1934 break;
1935
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 */
1940 break;
1941
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 */
1946 break;
1947
1948 /* MOVQ - movq src.rq, dst.wq
1949
1950 opnd[0:1] = source
1951 spec = register/memory flag
1952 rn = register number
1953 va = memory address
1954
1955 */
1956
1957 case MOVQ:
1958 WRITE_Q (op0, op1); /* store result */
1959 CC_IIZP_Q (op0, op1);
1960 break;
1961
1962 /* Shifts - op shf.rb,src.rl,dst.wl
1963
1964 opnd[0] = shift count
1965 opnd[1] = source
1966 spec = register/memory flag
1967 rn = register number
1968 va = memory address
1969 */
1970
1971 case ROTL:
1972 j = op0 % 32; /* reduce sc, mod 32 */
1973 if (j) r = ((((uint32) op1) << j) |
1974 (((uint32) op1) >> (32 - j))) & LMASK;
1975 else r = op1;
1976 WRITE_L (r); /* store result */
1977 CC_IIZP_L (r); /* set cc's */
1978 break;
1979
1980 case ASHL:
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 */
1987 break;
1988 }
1989 else {
1990 if (op0 > 31) r = temp = 0; /* sc > 31? */
1991 else {
1992 r = (((uint32) op1) << op0) & LMASK; /* shift */
1993 temp = r >> op0; /* shift back */
1994 }
1995 WRITE_L (r); /* store result */
1996 CC_IIZZ_L (r); /* set cc's */
1997 if (op1 != temp) { V_INTOV; } /* bits lost? */
1998 }
1999 break;
2000
2001 case ASHQ:
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 */
2006 break;
2007
2008 /* EMUL - emul mplr.rl,mpcn.rl,add.rl,dst.wq
2009
2010 op0 = multiplier
2011 op1 = multiplicand
2012 op2 = adder
2013 op3:op4 = destination (.wq)
2014 */
2015
2016 case EMUL:
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 */
2023 break;
2024
2025 /* EDIV - ediv dvr.rl,dvd.rq,quo.wl,rem.wl
2026
2027 op0 = divisor (.rl)
2028 op1:op2 = dividend (.rq)
2029 op3:op4 = quotient address (.wl)
2030 op5:op6 = remainder address (.wl)
2031 */
2032
2033 case EDIV:
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 */
2040 }
2041 else {
2042 r = op_ediv (opnd, &rh, &flg); /* extended divide */
2043 if (flg) { INTOV; } /* if ovf+IV, set trap */
2044 }
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 */
2051 break;
2052
2053 /* Control instructions */
2054
2055 /* Simple branches and subroutine calls */
2056
2057 case BRB:
2058 BRANCHB (brdisp); /* branch */
2059 if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F))
2060 ABORT (STOP_LOOP);
2061 break;
2062
2063 case BRW:
2064 BRANCHW (brdisp); /* branch */
2065 if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F))
2066 ABORT (STOP_LOOP);
2067 break;
2068
2069 case BSBB:
2070 Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */
2071 SP = SP - 4; /* decr stk ptr */
2072 BRANCHB (brdisp); /* branch */
2073 break;
2074
2075 case BSBW:
2076 Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */
2077 SP = SP - 4; /* decr stk ptr */
2078 BRANCHW (brdisp); /* branch */
2079 break;
2080
2081 case BGEQ:
2082 if (!(cc & CC_N)) BRANCHB (brdisp); /* br if N = 0 */
2083 break;
2084
2085 case BLSS:
2086 if (cc & CC_N) BRANCHB (brdisp); /* br if N = 1 */
2087 break;
2088
2089 case BNEQ:
2090 if (!(cc & CC_Z)) BRANCHB (brdisp); /* br if Z = 0 */
2091 break;
2092
2093 case BEQL:
2094 if (cc & CC_Z) BRANCHB (brdisp); /* br if Z = 1 */
2095 break;
2096
2097 case BVC:
2098 if (!(cc & CC_V)) BRANCHB (brdisp); /* br if V = 0 */
2099 break;
2100
2101 case BVS:
2102 if (cc & CC_V) BRANCHB (brdisp); /* br if V = 1 */
2103 break;
2104
2105 case BGEQU:
2106 if (!(cc & CC_C)) BRANCHB (brdisp); /* br if C = 0 */
2107 break;
2108
2109 case BLSSU:
2110 if (cc & CC_C) BRANCHB (brdisp); /* br if C = 1 */
2111 break;
2112
2113 case BGTR:
2114 if (!(cc & (CC_N | CC_Z))) BRANCHB (brdisp); /* br if N | Z = 0 */
2115 break;
2116
2117 case BLEQ:
2118 if (cc & (CC_N | CC_Z)) BRANCHB (brdisp); /* br if N | Z = 1 */
2119 break;
2120
2121 case BGTRU:
2122 if (!(cc & (CC_C | CC_Z))) BRANCHB (brdisp); /* br if C | Z = 0 */
2123 break;
2124
2125 case BLEQU:
2126 if (cc & (CC_C | CC_Z)) BRANCHB (brdisp); /* br if C | Z = 1 */
2127 break;
2128
2129 /* Simple jumps and subroutine calls - op addr.ab
2130
2131 opnd[0] = address
2132 */
2133
2134 case JSB:
2135 Write (SP - 4, PC, L_LONG, WA); /* push PC on stk */
2136 SP = SP - 4; /* decr stk ptr */
2137
2138 case JMP:
2139 JUMP (op0); /* jump */
2140 break;
2141
2142 case RSB:
2143 temp = Read (SP, L_LONG, RA); /* get top of stk */
2144 SP = SP + 4; /* incr stk ptr */
2145 JUMP (temp);
2146 break;
2147
2148 /* SOB instructions - op idx.ml,disp.bb
2149
2150 opnd[0] = index
2151 spec = register/memory flag
2152 rn = register number
2153 va = memory address
2154 */
2155
2156 case SOBGEQ:
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 */
2162 break;
2163
2164 case SOBGTR:
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 */
2170 break;
2171
2172 /* AOB instructions - op limit.rl,idx.ml,disp.bb
2173
2174 opnd[0] = limit
2175 opnd[1] = index
2176 spec = register/memory flag
2177 rn = register number
2178 va = memory address
2179 */
2180
2181 case AOBLSS:
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 */
2187 break;
2188
2189 case AOBLEQ:
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 */
2195 break;
2196
2197 /* ACB instructions - op limit.rx,add.rx,index.mx,disp.bw
2198
2199 opnd[0] = limit
2200 opnd[1] = adder
2201 opnd[2] = index
2202 spec = register/memory flag
2203 rn = register number
2204 va = memory address
2205 */
2206
2207 case ACBB:
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);
2214 break;
2215
2216 case ACBW:
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);
2223 break;
2224
2225 case ACBL:
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))
2231 BRANCHW (brdisp);
2232 break;
2233
2234 /* CASE instructions - casex sel.rx,base.rx,lim.rx
2235
2236 opnd[0] = selector
2237 opnd[1] = base
2238 opnd[2] = limit
2239 */
2240
2241 case CASEB:
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)? */
2245 else {
2246 temp = Read (PC + (r * 2), L_WORD, RA);
2247 BRANCHW (temp);
2248 }
2249 break;
2250
2251 case CASEW:
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)? */
2255 else {
2256 temp = Read (PC + (r * 2), L_WORD, RA);
2257 BRANCHW (temp);
2258 }
2259 break;
2260
2261 case CASEL:
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));
2266 else {
2267 temp = Read (PC + (r * 2), L_WORD, RA);
2268 BRANCHW (temp);
2269 }
2270 break;
2271
2272 /* Branch on bit instructions - bbxy pos.rl,op.wb,disp.bb
2273
2274 opnd[0] = position
2275 opnd[1] = register number/memory flag
2276 opnd[2] = memory address, if memory
2277 */
2278
2279 case BBS:
2280 if (op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit set */
2281 break;
2282
2283 case BBC:
2284 if (!op_bb_n (opnd, acc)) BRANCHB (brdisp); /* br if bit clr */
2285 break;
2286
2287 case BBSS: case BBSSI:
2288 if (op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, set */
2289 break;
2290
2291 case BBCC: case BBCCI:
2292 if (!op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, clr*/
2293 break;
2294
2295 case BBSC:
2296 if (op_bb_x (opnd, 0, acc)) BRANCHB (brdisp); /* br if clr, set */
2297 break;
2298
2299 case BBCS:
2300 if (!op_bb_x (opnd, 1, acc)) BRANCHB (brdisp); /* br if set, clr */
2301 break;
2302
2303 case BLBS:
2304 if (op0 & 1) BRANCHB (brdisp); /* br if bit set */
2305 break;
2306
2307 case BLBC:
2308 if ((op0 & 1) == 0) BRANCHB (brdisp); /* br if bit clear */
2309 break;
2310
2311 /* Extract field instructions - ext?v pos.rl,size.rb,base.wb,dst.wl
2312
2313 opnd[0] = position
2314 opnd[1] = size
2315 opnd[2] = register number/memory flag
2316 opnd[3] = register content/memory address
2317 spec = register/memory flag
2318 rn = register number
2319 va = memory address
2320 */
2321
2322 case EXTV:
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 */
2327 break;
2328
2329 case EXTZV:
2330 r = op_extv (opnd, vfldrp1, acc); /* get field */
2331 WRITE_L (r); /* store field */
2332 CC_IIZP_L (r); /* set cc's */
2333 break;
2334
2335 /* Compare field instructions - cmp?v pos.rl,size.rb,base.wb,src2.rl
2336
2337 opnd[0] = position
2338 opnd[1] = size
2339 opnd[2] = register number/memory flag
2340 opnd[3] = register content/memory address
2341 opnd[4] = source2
2342 */
2343
2344 case CMPV:
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 */
2348 break;
2349
2350 case CMPZV:
2351 r = op_extv (opnd, vfldrp1, acc); /* get field */
2352 CC_CMP_L (r, op4); /* set cc's */
2353 break;
2354
2355 /* Find first field instructions - ff? pos.rl,size.rb,base.wb,dst.wl
2356
2357 opnd[0] = position
2358 opnd[1] = size
2359 opnd[2] = register number/memory flag
2360 opnd[3] = register content/memory address
2361 spec = register/memory flag
2362 rn = register number
2363 va = memory address
2364 */
2365
2366 case FFS:
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 */
2371 break;
2372
2373 case FFC:
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 */
2379 break;
2380
2381 /* Insert field instruction - insv src.rl,pos.rb,size.rl,base.wb
2382
2383 opnd[0] = source
2384 opnd[1] = position
2385 opnd[2] = size
2386 opnd[3] = register number/memory flag
2387 opnd[4] = register content/memory address
2388 */
2389
2390 case INSV:
2391 op_insv (opnd, vfldrp1, acc); /* insert field */
2392 break;
2393
2394 /* Call and return - call? arg.rx,proc.ab
2395
2396 opnd[0] = argument
2397 opnd[1] = procedure address
2398 */
2399
2400 case CALLS:
2401 cc = op_call (opnd, TRUE, acc);
2402 break;
2403
2404 case CALLG:
2405 cc = op_call (opnd, FALSE, acc);
2406 break;
2407
2408 case RET:
2409 cc = op_ret (acc);
2410 break;
2411
2412 /* Miscellaneous instructions */
2413
2414 case HALT:
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 */
2418 else {
2419 ABORT (STOP_HALT); /* halt to simulator */
2420 }
2421
2422 case NOP:
2423 break;
2424
2425 case BPT:
2426 SETPC (fault_PC);
2427 cc = intexc (SCB_BPT, cc, 0, IE_EXC);
2428 GET_CUR;
2429 break;
2430
2431 case XFC:
2432 SETPC (fault_PC);
2433 cc = intexc (SCB_XFC, cc, 0, IE_EXC);
2434 GET_CUR;
2435 break;
2436
2437 case BISPSW:
2438 if (opnd[0] & PSW_MBZ) RSVD_OPND_FAULT;
2439 PSL = PSL | (opnd[0] & ~CC_MASK);
2440 cc = cc | (opnd[0] & CC_MASK);
2441 break;
2442
2443 case BICPSW:
2444 if (opnd[0] & PSW_MBZ) RSVD_OPND_FAULT;
2445 PSL = PSL & ~opnd[0];
2446 cc = cc & ~opnd[0];
2447 break;
2448
2449 case MOVPSL:
2450 r = PSL | cc;
2451 WRITE_L (r);
2452 break;
2453
2454 case PUSHR:
2455 op_pushr (opnd, acc);
2456 break;
2457
2458 case POPR:
2459 op_popr (opnd, acc);
2460 break;
2461
2462 case INDEX:
2463 if ((op0 < op1) || (op0 > op2)) SET_TRAP (TRAP_SUBSCR);
2464 r = (op0 + op4) * op3;
2465 WRITE_L (r);
2466 CC_IIZZ_L (r);
2467 break;
2468
2469 /* Queue and interlocked queue */
2470
2471 case INSQUE:
2472 cc = op_insque (opnd, acc);
2473 break;
2474
2475 case REMQUE:
2476 cc = op_remque (opnd, acc);
2477 break;
2478
2479 case INSQHI:
2480 cc = op_insqhi (opnd, acc);
2481 break;
2482
2483 case INSQTI:
2484 cc = op_insqti (opnd, acc);
2485 break;
2486
2487 case REMQHI:
2488 cc = op_remqhi (opnd, acc);
2489 break;
2490
2491 case REMQTI:
2492 cc = op_remqti (opnd, acc);
2493 break;
2494
2495 /* String instructions */
2496
2497 case MOVC3: case MOVC5:
2498 cc = op_movc (opnd, opc & 4, acc);
2499 break;
2500
2501 case CMPC3: case CMPC5:
2502 cc = op_cmpc (opnd, opc & 4, acc);
2503 break;
2504
2505 case LOCC: case SKPC:
2506 cc = op_locskp (opnd, opc & 1, acc);
2507 break;
2508
2509 case SCANC: case SPANC:
2510 cc = op_scnspn (opnd, opc & 1, acc);
2511 break;
2512
2513 /* Floating point instructions */
2514
2515 case TSTF: case TSTD:
2516 r = op_movfd (op0);
2517 CC_IIZZ_FP (r);
2518 break;
2519
2520 case TSTG:
2521 r = op_movg (op0);
2522 CC_IIZZ_FP (r);
2523 break;
2524
2525 case MOVF:
2526 r = op_movfd (op0);
2527 WRITE_L (r);
2528 CC_IIZP_FP (r);
2529 break;
2530
2531 case MOVD:
2532 if ((r = op_movfd (op0)) == 0) op1 = 0;
2533 WRITE_Q (r, op1);
2534 CC_IIZP_FP (r);
2535 break;
2536
2537 case MOVG:
2538 if ((r = op_movg (op0)) == 0) op1 = 0;
2539 WRITE_Q (r, op1);
2540 CC_IIZP_FP (r);
2541 break;
2542
2543 case MNEGF:
2544 r = op_mnegfd (op0);
2545 WRITE_L (r);
2546 CC_IIZZ_FP (r);
2547 break;
2548
2549 case MNEGD:
2550 if ((r = op_mnegfd (op0)) == 0) op1 = 0;
2551 WRITE_Q (r, op1);
2552 CC_IIZZ_FP (r);
2553 break;
2554
2555 case MNEGG:
2556 if ((r = op_mnegg (op0)) == 0) op1 = 0;
2557 WRITE_Q (r, op1);
2558 CC_IIZZ_FP (r);
2559 break;
2560
2561 case CMPF:
2562 cc = op_cmpfd (op0, 0, op1, 0);
2563 break;
2564
2565 case CMPD:
2566 cc = op_cmpfd (op0, op1, op2, op3);
2567 break;
2568
2569 case CMPG:
2570 cc = op_cmpg (op0, op1, op2, op3);
2571 break;
2572
2573 case CVTBF:
2574 r = op_cvtifdg (SXTB (op0), NULL, opc);
2575 WRITE_L (r);
2576 CC_IIZZ_FP (r);
2577 break;
2578
2579 case CVTWF:
2580 r = op_cvtifdg (SXTW (op0), NULL, opc);
2581 WRITE_L (r);
2582 CC_IIZZ_FP (r);
2583 break;
2584
2585 case CVTLF:
2586 r = op_cvtifdg (op0, NULL, opc);
2587 WRITE_L (r);
2588 CC_IIZZ_FP (r);
2589 break;
2590
2591 case CVTBD: case CVTBG:
2592 r = op_cvtifdg (SXTB (op0), &rh, opc);
2593 WRITE_Q (r, rh);
2594 CC_IIZZ_FP (r);
2595 break;
2596
2597 case CVTWD: case CVTWG:
2598 r = op_cvtifdg (SXTW (op0), &rh, opc);
2599 WRITE_Q (r, rh);
2600 CC_IIZZ_FP (r);
2601 break;
2602
2603 case CVTLD: case CVTLG:
2604 r = op_cvtifdg (op0, &rh, opc);
2605 WRITE_Q (r, rh);
2606 CC_IIZZ_FP (r);
2607 break;
2608
2609 case CVTFB: case CVTDB: case CVTGB:
2610 r = op_cvtfdgi (opnd, &flg, opc) & BMASK;
2611 WRITE_B (r);
2612 CC_IIZZ_B (r);
2613 if (flg) { V_INTOV; }
2614 break;
2615
2616 case CVTFW: case CVTDW: case CVTGW:
2617 r = op_cvtfdgi (opnd, &flg, opc) & WMASK;
2618 WRITE_W (r);
2619 CC_IIZZ_W (r);
2620 if (flg) { V_INTOV; }
2621 break;
2622
2623 case CVTFL: case CVTDL: case CVTGL:
2624 case CVTRFL: case CVTRDL: case CVTRGL:
2625 r = op_cvtfdgi (opnd, &flg, opc) & LMASK;
2626 WRITE_L (r);
2627 CC_IIZZ_L (r);
2628 if (flg) { V_INTOV; }
2629 break;
2630
2631 case CVTFD:
2632 r = op_movfd (op0);
2633 WRITE_Q (r, 0);
2634 CC_IIZZ_FP (r);
2635 break;
2636
2637 case CVTDF:
2638 r = op_cvtdf (opnd);
2639 WRITE_L (r);
2640 CC_IIZZ_FP (r);
2641 break;
2642
2643 case CVTFG:
2644 r = op_cvtfg (opnd, &rh);
2645 WRITE_Q (r, rh);
2646 CC_IIZZ_FP (r);
2647 break;
2648
2649 case CVTGF:
2650 r = op_cvtgf (opnd);
2651 WRITE_L (r);
2652 CC_IIZZ_FP (r);
2653 break;
2654
2655 case ADDF2: case ADDF3:
2656 r = op_addf (opnd, FALSE);
2657 WRITE_L (r);
2658 CC_IIZZ_FP (r);
2659 break;
2660
2661 case ADDD2: case ADDD3:
2662 r = op_addd (opnd, &rh, FALSE);
2663 WRITE_Q (r, rh);
2664 CC_IIZZ_FP (r);
2665 break;
2666
2667 case ADDG2: case ADDG3:
2668 r = op_addg (opnd, &rh, FALSE);
2669 WRITE_Q (r, rh);
2670 CC_IIZZ_FP (r);
2671 break;
2672
2673 case SUBF2: case SUBF3:
2674 r = op_addf (opnd, TRUE);
2675 WRITE_L (r);
2676 CC_IIZZ_FP (r);
2677 break;
2678
2679 case SUBD2: case SUBD3:
2680 r = op_addd (opnd, &rh, TRUE);
2681 WRITE_Q (r, rh);
2682 CC_IIZZ_FP (r);
2683 break;
2684
2685 case SUBG2: case SUBG3:
2686 r = op_addg (opnd, &rh, TRUE);
2687 WRITE_Q (r, rh);
2688 CC_IIZZ_FP (r);
2689 break;
2690
2691 case MULF2: case MULF3:
2692 r = op_mulf (opnd);
2693 WRITE_L (r);
2694 CC_IIZZ_FP (r);
2695 break;
2696
2697 case MULD2: case MULD3:
2698 r = op_muld (opnd, &rh);
2699 WRITE_Q (r, rh);
2700 CC_IIZZ_FP (r);
2701 break;
2702
2703 case MULG2: case MULG3:
2704 r = op_mulg (opnd, &rh);
2705 WRITE_Q (r, rh);
2706 CC_IIZZ_FP (r);
2707 break;
2708
2709 case DIVF2: case DIVF3:
2710 r = op_divf (opnd);
2711 WRITE_L (r);
2712 CC_IIZZ_FP (r);
2713 break;
2714
2715 case DIVD2: case DIVD3:
2716 r = op_divd (opnd, &rh);
2717 WRITE_Q (r, rh);
2718 CC_IIZZ_FP (r);
2719 break;
2720
2721 case DIVG2: case DIVG3:
2722 r = op_divg (opnd, &rh);
2723 WRITE_Q (r, rh);
2724 CC_IIZZ_FP (r);
2725 break;
2726
2727 case ACBF:
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);
2734 break;
2735
2736 case ACBD:
2737 r = op_addd (opnd + 2, &rh, FALSE);
2738 temp = op_cmpfd (r, rh, op0, op1);
2739 WRITE_Q (r, rh);
2740 CC_IIZP_FP (r);
2741 if ((temp & CC_Z) || ((op2 & FPSIGN)? /* test br cond */
2742 !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp);
2743 break;
2744
2745 case ACBG:
2746 r = op_addg (opnd + 2, &rh, FALSE);
2747 temp = op_cmpg (r, rh, op0, op1);
2748 WRITE_Q (r, rh);
2749 CC_IIZP_FP (r);
2750 if ((temp & CC_Z) || ((op2 & FPSIGN)? /* test br cond */
2751 !(temp & CC_N): (temp & CC_N))) BRANCHW (brdisp);
2752 break;
2753
2754 /* EMODF
2755
2756 op0 = multiplier
2757 op1 = extension
2758 op2 = multiplicand
2759 op3:op4 = integer destination (int.wl)
2760 op5:op6 = floating destination (flt.wl)
2761 */
2762
2763 case EMODF:
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);
2768 WRITE_L (r);
2769 CC_IIZZ_FP (r);
2770 if (flg) { V_INTOV; }
2771 break;
2772
2773 /* EMODD, EMODG
2774
2775 op0:op1 = multiplier
2776 op2 = extension
2777 op3:op4 = multiplicand
2778 op5:op6 = integer destination (int.wl)
2779 op7:op8 = floating destination (flt.wq)
2780 */
2781
2782 case EMODD:
2783 r = op_emodd (opnd, &rh, &temp, &flg);
2784 if (op7 < 0) {
2785 Read (op8, L_BYTE, WA);
2786 Read ((op8 + 7) & LMASK, L_BYTE, WA);
2787 }
2788 if (op5 >= 0) R[op5] = temp;
2789 else Write (op6, temp, L_LONG, WA);
2790 WRITE_Q (r, rh);
2791 CC_IIZZ_FP (r);
2792 if (flg) { V_INTOV; }
2793 break;
2794
2795 case EMODG:
2796 r = op_emodg (opnd, &rh, &temp, &flg);
2797 if (op7 < 0) {
2798 Read (op8, L_BYTE, WA);
2799 Read ((op8 + 7) & LMASK, L_BYTE, WA);
2800 }
2801 if (op5 >= 0) R[op5] = temp;
2802 else Write (op6, temp, L_LONG, WA);
2803 WRITE_Q (r, rh);
2804 CC_IIZZ_FP (r);
2805 if (flg) { V_INTOV; }
2806 break;
2807
2808 /* POLY */
2809
2810 case POLYF:
2811 op_polyf (opnd, acc);
2812 CC_IIZZ_FP (R[0]);
2813 break;
2814
2815 case POLYD:
2816 op_polyd (opnd, acc);
2817 CC_IIZZ_FP (R[0]);
2818 break;
2819
2820 case POLYG:
2821 op_polyg (opnd, acc);
2822 CC_IIZZ_FP (R[0]);
2823 break;
2824
2825 /* Operating system instructions */
2826
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 */
2831 break;
2832
2833 case REI:
2834 cc = op_rei (acc); /* REI */
2835 GET_CUR; /* update cur mode */
2836 SET_IRQL; /* update intreq */
2837 break;
2838
2839 case LDPCTX:
2840 op_ldpctx (acc);
2841 break;
2842
2843 case SVPCTX:
2844 op_svpctx (acc);
2845 break;
2846
2847 case PROBER: case PROBEW:
2848 cc = (cc & CC_C) | op_probe (opnd, opc & 1);
2849 break;
2850
2851 case MTPR:
2852 cc = (cc & CC_C) | op_mtpr (opnd);
2853 SET_IRQL; /* update intreq */
2854 break;
2855
2856 case MFPR:
2857 r = op_mfpr (opnd);
2858 WRITE_L (r);
2859 CC_IIZP_L (r);
2860 break;
2861
2862 /* CIS or emulated instructions */
2863
2864 case CVTPL:
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);
2871 break;
2872
2873 /* Octaword or reserved instructions */
2874
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? */
2886 BRANCHW (brdisp);
2887 cc = cc & CC_MASK; /* mask off flag */
2888 }
2889 break;
2890
2891 default:
2892 RSVD_INST_FAULT;
2893 break;
2894 } /* end case op */
2895 } /* end for */
2896 ABORT (STOP_UNKNOWN);
2897 } /* end sim_instr */
2898
2899 /* Prefetch buffer routine
2900
2901 Prefetch buffer state
2902
2903 ibufl, ibufh = the prefetch buffer
2904 ibcnt = number of bytes available (0, 4, 8)
2905 ppc = physical PC
2906
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.
2910
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.
2916 */
2917
2918 SIM_INLINE_GCC int32 get_istr (int32 lnt, int32 acc)
2919 {
2920 int32 bo = PC & 3;
2921 int32 sc, val, t;
2922
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);
2927 }
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 */
2932 }
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;
2938 }
2939 else if (bo) { /* unaligned lw? */
2940 sc = bo << 3;
2941 val = (((ibufl >> sc) & align[bo]) | (((uint32) ibufh) << (32 - sc)));
2942 }
2943 else val = ibufl; /* aligned lw */
2944 if ((bo + lnt) >= 4) { /* retire ibufl? */
2945 ibufl = ibufh;
2946 ibcnt = ibcnt - 4;
2947 }
2948 return val;
2949 }
2950
2951 /* Read octaword specifier */
2952
2953 int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc)
2954 {
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);
2959 return j;
2960 }
2961
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 */
2965
2966 int32 cpu_psl_ipl_idle (int32 newpsl)
2967 {
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);
2974 }
2975 }
2976 return newpsl;
2977 }
2978
2979 /* Idle timer has expired with no PSL change */
2980
2981 t_stat cpu_idle_svc (UNIT *uptr)
2982 {
2983 if (sim_idle_enab)
2984 sim_idle (TMR_CLK, FALSE);
2985 return SCPE_OK;
2986 }
2987
2988 /* Reset */
2989
2990 t_stat cpu_reset (DEVICE *dptr)
2991 {
2992 hlt_pin = 0;
2993 mem_err = 0;
2994 crd_err = 0;
2995 PSL = PSL_IS | PSL_IPL1F;
2996 SISR = 0;
2997 ASTLVL = 4;
2998 mapen = 0;
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 ();
3006 }
3007
3008 /* Memory examine */
3009
3010 t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
3011 {
3012 int32 st;
3013 uint32 addr = (uint32) exta;
3014
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);
3019 }
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);
3024 return SCPE_OK;
3025 }
3026 return SCPE_NXM;
3027 }
3028
3029 /* Memory deposit */
3030
3031 t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
3032 {
3033 int32 st;
3034 uint32 addr = (uint32) exta;
3035
3036 if (sw & SWMASK ('V')) {
3037 int32 acc = cpu_get_vsw (sw);
3038 addr = Test (addr, acc, &st);
3039 }
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);
3044 return SCPE_OK;
3045 }
3046 if (ADDR_IS_ROM (addr)) {
3047 rom_wr_B (addr, (int32) val);
3048 return SCPE_OK;
3049 }
3050 return SCPE_NXM;
3051 }
3052
3053 /* Memory allocation */
3054
3055 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
3056 {
3057 int32 mc = 0;
3058 uint32 i, clim;
3059 uint32 *nM = NULL;
3060
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))
3064 return SCPE_OK;
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];
3069 free (M);
3070 M = nM;
3071 MEMSIZE = val;
3072 return SCPE_OK;
3073 }
3074
3075 /* Virtual address translation */
3076
3077 t_stat cpu_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc)
3078 {
3079 t_stat r;
3080 char *cptr = (char *) desc;
3081 uint32 va, pa;
3082 int32 st;
3083 static const char *mm_str[] = {
3084 "Access control violation",
3085 "Length violation",
3086 "Process PTE access control violation",
3087 "Process PTE length violation",
3088 "Translation not valid",
3089 "Internal error",
3090 "Process PTE translation not valid"
3091 };
3092
3093 if (cptr) {
3094 va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r);
3095 if (r == SCPE_OK) {
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]);
3100 return SCPE_OK;
3101 }
3102 }
3103 fprintf (of, "Invalid argument\n");
3104 return SCPE_OK;
3105 }
3106
3107 /* Get access mode for examine, deposit, show virtual */
3108
3109 int32 cpu_get_vsw (int32 sw)
3110 {
3111 int32 md;
3112
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);
3120 }
3121
3122 /* Set history */
3123
3124 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
3125 {
3126 int32 i, lnt;
3127 t_stat r;
3128
3129 if (cptr == NULL) {
3130 for (i = 0; i < hst_lnt; i++) hst[i].iPC = 0;
3131 hst_p = 0;
3132 return SCPE_OK;
3133 }
3134 lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
3135 if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
3136 hst_p = 0;
3137 if (hst_lnt) {
3138 free (hst);
3139 hst_lnt = 0;
3140 hst = NULL;
3141 }
3142 if (lnt) {
3143 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
3144 if (hst == NULL) return SCPE_MEM;
3145 hst_lnt = lnt;
3146 }
3147 return SCPE_OK;
3148 }
3149
3150 /* Show history */
3151
3152 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
3153 {
3154 int32 i, k, di, lnt, numspec;
3155 char *cptr = (char *) desc;
3156 t_stat r;
3157 InstHistory *h;
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);
3162
3163 if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
3164 if (cptr) {
3165 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
3166 if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;
3167 }
3168 else lnt = hst_lnt;
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]);
3181 else { /* normal */
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);
3191 }
3192 }
3193 }
3194 } /* end else */
3195 fputc ('\n', st); /* end line */
3196 } /* end for */
3197 return SCPE_OK;
3198 }
3199
3200 t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line)
3201 {
3202
3203 int32 numspec, i, j, disp;
3204 t_bool more;
3205
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)) {
3213
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);
3219 j = j + 1;
3220 break;
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;
3225 j = j + 2;
3226 break;
3227 case RO: case MO: /* read, modify octa */
3228 fprintf (st, " %08X", h->opnd[j + line]);
3229 more = TRUE;
3230 j = j + 4;
3231 break;
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);
3235 j = j + 2;
3236 break;
3237 } /* end case */
3238 } /* end for */
3239 return more;
3240 }
3241
3242 struct os_idle {
3243 char *name;
3244 uint32 mask;
3245 };
3246
3247 static struct os_idle os_tab[] = {
3248 { "VMS", 0x8 },
3249 { "NETBSD", 0x2 },
3250 { "ULTRIX", 0x2 },
3251 { "OPENBSD", 0x1 },
3252 { "32V", 0x1 },
3253 { NULL, 0 }
3254 };
3255
3256 /* Set and show idle */
3257
3258 t_stat cpu_set_idle (UNIT *uptr, int32 val, char *cptr, void *desc)
3259 {
3260 uint32 i;
3261
3262 if (cptr != NULL) {
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);
3268 }
3269 }
3270 return SCPE_ARG;
3271 }
3272 return sim_set_idle (uptr, val, cptr, desc);
3273 }
3274
3275 t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc)
3276 {
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");
3280 return SCPE_OK;
3281 }