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