Commit | Line | Data |
---|---|---|
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 | |
211 | typedef 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 | |
219 | uint32 *M = NULL; /* memory */\r | |
220 | int32 R[16]; /* registers */\r | |
221 | int32 STK[5]; /* stack pointers */\r | |
222 | int32 PSL; /* PSL */\r | |
223 | int32 SCBB = 0; /* SCB base */\r | |
224 | int32 PCBB = 0; /* PCB base */\r | |
225 | int32 P0BR = 0; /* P0 mem mgt */\r | |
226 | int32 P0LR = 0;\r | |
227 | int32 P1BR = 0; /* P1 mem mgt */\r | |
228 | int32 P1LR = 0;\r | |
229 | int32 SBR = 0; /* S0 mem mgt */\r | |
230 | int32 SLR = 0;\r | |
231 | int32 SISR; /* swre int req */\r | |
232 | int32 ASTLVL; /* AST level */\r | |
233 | int32 mapen; /* map enable */\r | |
234 | int32 pme; /* perf mon enable */\r | |
235 | int32 trpirq; /* trap/intr req */\r | |
236 | int32 in_ie = 0; /* in exc, int */\r | |
237 | int32 recq[6]; /* recovery queue */\r | |
238 | int32 recqptr; /* recq pointer */\r | |
239 | int32 hlt_pin = 0; /* HLT pin intr */\r | |
240 | int32 mem_err = 0;\r | |
241 | int32 crd_err = 0;\r | |
242 | int32 p1 = 0, p2 = 0; /* fault parameters */\r | |
243 | int32 fault_PC; /* fault PC */\r | |
244 | int32 pcq_p = 0; /* PC queue ptr */\r | |
245 | int32 hst_p = 0; /* history pointer */\r | |
246 | int32 hst_lnt = 0; /* history length */\r | |
247 | int32 badabo = 0;\r | |
248 | int32 cpu_astop = 0;\r | |
249 | int32 mchk_va, mchk_ref; /* mem ref param */\r | |
250 | int32 ibufl, ibufh; /* prefetch buf */\r | |
251 | int32 ibcnt, ppc; /* prefetch ctl */\r | |
252 | uint32 cpu_idle_ipl_mask = 0x8; /* idle if on IPL 3 */\r | |
253 | uint32 cpu_idle_type = 1; /* default to VMS */\r | |
254 | int32 cpu_idle_wait = 1000; /* for these cycles */\r | |
255 | jmp_buf save_env;\r | |
256 | REG *pcq_r = NULL; /* PC queue reg ptr */\r | |
257 | int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */\r | |
258 | InstHistory *hst = NULL; /* instruction history */\r | |
259 | \r | |
260 | const 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 | |
270 | const 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 | |
280 | const uint32 align[4] = {\r | |
281 | 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF\r | |
282 | };\r | |
283 | \r | |
284 | /* External and forward references */\r | |
285 | \r | |
286 | extern int32 sim_interval;\r | |
287 | extern int32 sim_int_char;\r | |
288 | extern int32 sim_switches;\r | |
289 | extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */\r | |
290 | extern t_bool sim_idle_enab;\r | |
291 | \r | |
292 | extern t_stat build_dib_tab (void);\r | |
293 | extern UNIT rom_unit, nvr_unit;\r | |
294 | extern int32 op_ashq (int32 *opnd, int32 *rh, int32 *flg);\r | |
295 | extern int32 op_emul (int32 mpy, int32 mpc, int32 *rh);\r | |
296 | extern int32 op_ediv (int32 *opnd, int32 *rh, int32 *flg);\r | |
297 | extern int32 op_bb_n (int32 *opnd, int32 acc);\r | |
298 | extern int32 op_bb_x (int32 *opnd, int32 newb, int32 acc);\r | |
299 | extern int32 op_extv (int32 *opnd, int32 vfldrp1, int32 acc);\r | |
300 | extern int32 op_ffs (uint32 fld, int32 size);\r | |
301 | extern void op_insv (int32 *opnd, int32 vfldrp1, int32 acc);\r | |
302 | extern int32 op_call (int32 *opnd, t_bool gs, int32 acc);\r | |
303 | extern int32 op_ret (int32 acc);\r | |
304 | extern int32 op_insque (int32 *opnd, int32 acc);\r | |
305 | extern int32 op_remque (int32 *opnd, int32 acc);\r | |
306 | extern int32 op_insqhi (int32 *opnd, int32 acc);\r | |
307 | extern int32 op_insqti (int32 *opnd, int32 acc);\r | |
308 | extern int32 op_remqhi (int32 *opnd, int32 acc);\r | |
309 | extern int32 op_remqti (int32 *opnd, int32 acc);\r | |
310 | extern void op_pushr (int32 *opnd, int32 acc);\r | |
311 | extern void op_popr (int32 *opnd, int32 acc);\r | |
312 | extern int32 op_movc (int32 *opnd, int32 opc, int32 acc);\r | |
313 | extern int32 op_cmpc (int32 *opnd, int32 opc, int32 acc);\r | |
314 | extern int32 op_locskp (int32 *opnd, int32 opc, int32 acc);\r | |
315 | extern int32 op_scnspn (int32 *opnd, int32 opc, int32 acc);\r | |
316 | extern int32 op_chm (int32 *opnd, int32 cc, int32 opc);\r | |
317 | extern int32 op_rei (int32 acc);\r | |
318 | extern void op_ldpctx (int32 acc);\r | |
319 | extern void op_svpctx (int32 acc);\r | |
320 | extern int32 op_probe (int32 *opnd, int32 opc);\r | |
321 | extern int32 op_mtpr (int32 *opnd);\r | |
322 | extern int32 op_mfpr (int32 *opnd);\r | |
323 | extern int32 op_movfd (int32 val);\r | |
324 | extern int32 op_movg (int32 val);\r | |
325 | extern int32 op_mnegfd (int32 val);\r | |
326 | extern int32 op_mnegg (int32 val);\r | |
327 | extern int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2);\r | |
328 | extern int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2);\r | |
329 | extern int32 op_cvtifdg (int32 val, int32 *rh, int32 opc);\r | |
330 | extern int32 op_cvtfdgi (int32 *opnd, int32 *flg, int32 opc);\r | |
331 | extern int32 op_cvtdf (int32 *opnd);\r | |
332 | extern int32 op_cvtgf (int32 *opnd);\r | |
333 | extern int32 op_cvtfg (int32 *opnd, int32 *rh);\r | |
334 | extern int32 op_cvtgh (int32 *opnd, int32 *hflt);\r | |
335 | extern int32 op_addf (int32 *opnd, t_bool sub);\r | |
336 | extern int32 op_addd (int32 *opnd, int32 *rh, t_bool sub);\r | |
337 | extern int32 op_addg (int32 *opnd, int32 *rh, t_bool sub);\r | |
338 | extern int32 op_mulf (int32 *opnd);\r | |
339 | extern int32 op_muld (int32 *opnd, int32 *rh);\r | |
340 | extern int32 op_mulg (int32 *opnd, int32 *rh);\r | |
341 | extern int32 op_divf (int32 *opnd);\r | |
342 | extern int32 op_divd (int32 *opnd, int32 *rh);\r | |
343 | extern int32 op_divg (int32 *opnd, int32 *rh);\r | |
344 | extern int32 op_emodf (int32 *opnd, int32 *intgr, int32 *flg);\r | |
345 | extern int32 op_emodd (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg);\r | |
346 | extern int32 op_emodg (int32 *opnd, int32 *rh, int32 *intgr, int32 *flg);\r | |
347 | extern void op_polyf (int32 *opnd, int32 acc);\r | |
348 | extern void op_polyd (int32 *opnd, int32 acc);\r | |
349 | extern void op_polyg (int32 *opnd, int32 acc);\r | |
350 | extern int32 op_cmode (int32 cc);\r | |
351 | extern int32 op_cis (int32 *opnd, int32 cc, int32 opc, int32 acc);\r | |
352 | extern int32 op_octa (int32 *opnd, int32 cc, int32 opc, int32 acc, int32 spec, int32 va);\r | |
353 | extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);\r | |
354 | extern int32 Test (uint32 va, int32 acc, int32 *status);\r | |
355 | extern int32 BadCmPSL (int32 newpsl);\r | |
356 | extern int32 eval_int (void);\r | |
357 | extern int32 get_vector (int32 lvl);\r | |
358 | extern void set_map_reg (void);\r | |
359 | extern void rom_wr_B (int32 pa, int32 val);\r | |
360 | extern int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta);\r | |
361 | extern const uint16 drom[NUM_INST][MAX_SPEC + 1];\r | |
362 | extern t_stat cpu_boot (int32 unitno, DEVICE *dptr);\r | |
363 | extern int32 con_halt (int32 code, int32 cc);\r | |
364 | \r | |
365 | t_stat cpu_reset (DEVICE *dptr);\r | |
366 | t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);\r | |
367 | t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);\r | |
368 | t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);\r | |
369 | t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);\r | |
370 | t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);\r | |
371 | t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc);\r | |
372 | t_stat cpu_set_idle (UNIT *uptr, int32 val, char *cptr, void *desc);\r | |
373 | t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc);\r | |
374 | int32 cpu_get_vsw (int32 sw);\r | |
375 | SIM_INLINE int32 get_istr (int32 lnt, int32 acc);\r | |
376 | int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc);\r | |
377 | t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line);\r | |
378 | int32 cpu_psl_ipl_idle (int32 newpsl);\r | |
379 | t_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 | |
389 | UNIT cpu_unit = {\r | |
390 | UDATA (&cpu_idle_svc, UNIT_FIX|UNIT_BINK, INITMEMSIZE)\r | |
391 | };\r | |
392 | \r | |
393 | REG 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 | |
446 | MTAB 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 | |
468 | DEBTAB 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 | |
475 | DEVICE 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 | |
484 | t_stat sim_instr (void)\r | |
485 | {\r | |
486 | volatile int32 opc, cc; /* used by setjmp */\r | |
487 | int32 acc; /* set by setjmp */\r | |
488 | int abortval;\r | |
489 | t_stat r;\r | |
490 | \r | |
491 | if ((r = build_dib_tab ()) != SCPE_OK) return r; /* build, chk dib_tab */\r | |
492 | if ((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 | |
498 | cc = PSL & CC_MASK; /* split PSL */\r | |
499 | PSL = PSL & ~CC_MASK;\r | |
500 | in_ie = 0; /* not in exc */\r | |
501 | set_map_reg (); /* set map reg */\r | |
502 | GET_CUR; /* set access mask */\r | |
503 | SET_IRQL; /* eval interrupts */\r | |
504 | FLUSH_ISTR; /* clear prefetch */\r | |
505 | \r | |
506 | abortval = setjmp (save_env); /* set abort hdlr */\r | |
507 | if (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 | |
512 | else 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 | |
583 | for ( ;; ) {\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 | |
2896 | ABORT (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 | |
2918 | SIM_INLINE_GCC int32 get_istr (int32 lnt, int32 acc)\r | |
2919 | {\r | |
2920 | int32 bo = PC & 3;\r | |
2921 | int32 sc, val, t;\r | |
2922 | \r | |
2923 | while ((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 | |
2933 | PC = PC + lnt; /* incr PC */\r | |
2934 | if (lnt == L_BYTE) val = (ibufl >> (bo << 3)) & BMASK; /* byte? */\r | |
2935 | else 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 | |
2939 | else if (bo) { /* unaligned lw? */\r | |
2940 | sc = bo << 3;\r | |
2941 | val = (((ibufl >> sc) & align[bo]) | (((uint32) ibufh) << (32 - sc)));\r | |
2942 | }\r | |
2943 | else val = ibufl; /* aligned lw */\r | |
2944 | if ((bo + lnt) >= 4) { /* retire ibufl? */\r | |
2945 | ibufl = ibufh;\r | |
2946 | ibcnt = ibcnt - 4;\r | |
2947 | }\r | |
2948 | return val;\r | |
2949 | }\r | |
2950 | \r | |
2951 | /* Read octaword specifier */\r | |
2952 | \r | |
2953 | int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc)\r | |
2954 | {\r | |
2955 | opnd[j++] = Read (va, L_LONG, acc);\r | |
2956 | opnd[j++] = Read (va + 4, L_LONG, acc);\r | |
2957 | opnd[j++] = Read (va + 8, L_LONG, acc); \r | |
2958 | opnd[j++] = Read (va + 12, L_LONG, acc); \r | |
2959 | return 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 | |
2966 | int32 cpu_psl_ipl_idle (int32 newpsl)\r | |
2967 | {\r | |
2968 | if (((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 | |
2976 | return newpsl;\r | |
2977 | }\r | |
2978 | \r | |
2979 | /* Idle timer has expired with no PSL change */\r | |
2980 | \r | |
2981 | t_stat cpu_idle_svc (UNIT *uptr)\r | |
2982 | {\r | |
2983 | if (sim_idle_enab)\r | |
2984 | sim_idle (TMR_CLK, FALSE);\r | |
2985 | return SCPE_OK;\r | |
2986 | }\r | |
2987 | \r | |
2988 | /* Reset */\r | |
2989 | \r | |
2990 | t_stat cpu_reset (DEVICE *dptr)\r | |
2991 | {\r | |
2992 | hlt_pin = 0;\r | |
2993 | mem_err = 0;\r | |
2994 | crd_err = 0;\r | |
2995 | PSL = PSL_IS | PSL_IPL1F;\r | |
2996 | SISR = 0;\r | |
2997 | ASTLVL = 4;\r | |
2998 | mapen = 0;\r | |
2999 | if (M == NULL) M = (uint32 *) calloc (((uint32) MEMSIZE) >> 2, sizeof (uint32));\r | |
3000 | if (M == NULL) return SCPE_MEM;\r | |
3001 | pcq_r = find_reg ("PCQ", NULL, dptr);\r | |
3002 | if (pcq_r) pcq_r->qptr = 0;\r | |
3003 | else return SCPE_IERR;\r | |
3004 | sim_brk_types = sim_brk_dflt = SWMASK ('E');\r | |
3005 | return build_dib_tab ();\r | |
3006 | }\r | |
3007 | \r | |
3008 | /* Memory examine */\r | |
3009 | \r | |
3010 | t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)\r | |
3011 | {\r | |
3012 | int32 st;\r | |
3013 | uint32 addr = (uint32) exta;\r | |
3014 | \r | |
3015 | if (vptr == NULL) return SCPE_ARG;\r | |
3016 | if (sw & SWMASK ('V')) {\r | |
3017 | int32 acc = cpu_get_vsw (sw);\r | |
3018 | addr = Test (addr, acc, &st);\r | |
3019 | }\r | |
3020 | else addr = addr & PAMASK;\r | |
3021 | if (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 | |
3026 | return SCPE_NXM;\r | |
3027 | }\r | |
3028 | \r | |
3029 | /* Memory deposit */\r | |
3030 | \r | |
3031 | t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)\r | |
3032 | {\r | |
3033 | int32 st;\r | |
3034 | uint32 addr = (uint32) exta;\r | |
3035 | \r | |
3036 | if (sw & SWMASK ('V')) {\r | |
3037 | int32 acc = cpu_get_vsw (sw);\r | |
3038 | addr = Test (addr, acc, &st);\r | |
3039 | }\r | |
3040 | else addr = addr & PAMASK;\r | |
3041 | if (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 | |
3046 | if (ADDR_IS_ROM (addr)) {\r | |
3047 | rom_wr_B (addr, (int32) val);\r | |
3048 | return SCPE_OK;\r | |
3049 | }\r | |
3050 | return SCPE_NXM;\r | |
3051 | }\r | |
3052 | \r | |
3053 | /* Memory allocation */\r | |
3054 | \r | |
3055 | t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)\r | |
3056 | {\r | |
3057 | int32 mc = 0;\r | |
3058 | uint32 i, clim;\r | |
3059 | uint32 *nM = NULL;\r | |
3060 | \r | |
3061 | if ((val <= 0) || (val > MAXMEMSIZE_X)) return SCPE_ARG;\r | |
3062 | for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2];\r | |
3063 | if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE))\r | |
3064 | return SCPE_OK;\r | |
3065 | nM = (uint32 *) calloc (val >> 2, sizeof (uint32));\r | |
3066 | if (nM == NULL) return SCPE_MEM;\r | |
3067 | clim = (uint32) ((((uint32) val) < MEMSIZE)? val: MEMSIZE);\r | |
3068 | for (i = 0; i < clim; i = i + 4) nM[i >> 2] = M[i >> 2];\r | |
3069 | free (M);\r | |
3070 | M = nM;\r | |
3071 | MEMSIZE = val; \r | |
3072 | return SCPE_OK;\r | |
3073 | }\r | |
3074 | \r | |
3075 | /* Virtual address translation */\r | |
3076 | \r | |
3077 | t_stat cpu_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc)\r | |
3078 | {\r | |
3079 | t_stat r;\r | |
3080 | char *cptr = (char *) desc;\r | |
3081 | uint32 va, pa;\r | |
3082 | int32 st;\r | |
3083 | static 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 | |
3093 | if (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 | |
3103 | fprintf (of, "Invalid argument\n");\r | |
3104 | return SCPE_OK;\r | |
3105 | }\r | |
3106 | \r | |
3107 | /* Get access mode for examine, deposit, show virtual */\r | |
3108 | \r | |
3109 | int32 cpu_get_vsw (int32 sw)\r | |
3110 | {\r | |
3111 | int32 md;\r | |
3112 | \r | |
3113 | set_map_reg (); /* update dyn reg */\r | |
3114 | if (sw & SWMASK ('K')) md = KERN;\r | |
3115 | else if (sw & SWMASK ('E')) md = EXEC;\r | |
3116 | else if (sw & SWMASK ('S')) md = SUPV;\r | |
3117 | else if (sw & SWMASK ('U')) md = USER;\r | |
3118 | else md = PSL_GETCUR (PSL);\r | |
3119 | return ACC_MASK (md);\r | |
3120 | }\r | |
3121 | \r | |
3122 | /* Set history */\r | |
3123 | \r | |
3124 | t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)\r | |
3125 | {\r | |
3126 | int32 i, lnt;\r | |
3127 | t_stat r;\r | |
3128 | \r | |
3129 | if (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 | |
3134 | lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);\r | |
3135 | if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;\r | |
3136 | hst_p = 0;\r | |
3137 | if (hst_lnt) {\r | |
3138 | free (hst);\r | |
3139 | hst_lnt = 0;\r | |
3140 | hst = NULL;\r | |
3141 | }\r | |
3142 | if (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 | |
3147 | return SCPE_OK;\r | |
3148 | }\r | |
3149 | \r | |
3150 | /* Show history */\r | |
3151 | \r | |
3152 | t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)\r | |
3153 | {\r | |
3154 | int32 i, k, di, lnt, numspec;\r | |
3155 | char *cptr = (char *) desc;\r | |
3156 | t_stat r;\r | |
3157 | InstHistory *h;\r | |
3158 | extern const char *opcode[];\r | |
3159 | extern t_value *sim_eval;\r | |
3160 | extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,\r | |
3161 | UNIT *uptr, int32 sw);\r | |
3162 | \r | |
3163 | if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */\r | |
3164 | if (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 | |
3168 | else lnt = hst_lnt;\r | |
3169 | di = hst_p - lnt; /* work forward */\r | |
3170 | if (di < 0) di = di + hst_lnt;\r | |
3171 | fprintf (st, "PC PSL IR\n\n");\r | |
3172 | for (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 | |
3197 | return SCPE_OK;\r | |
3198 | }\r | |
3199 | \r | |
3200 | t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line)\r | |
3201 | {\r | |
3202 | \r | |
3203 | int32 numspec, i, j, disp;\r | |
3204 | t_bool more;\r | |
3205 | \r | |
3206 | numspec = drom[h->opc][0] & DR_NSPMASK; /* #specifiers */\r | |
3207 | fputs ("\n ", st); /* space */\r | |
3208 | for (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 | |
3239 | return more;\r | |
3240 | }\r | |
3241 | \r | |
3242 | struct os_idle {\r | |
3243 | char *name;\r | |
3244 | uint32 mask;\r | |
3245 | };\r | |
3246 | \r | |
3247 | static 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 | |
3258 | t_stat cpu_set_idle (UNIT *uptr, int32 val, char *cptr, void *desc)\r | |
3259 | {\r | |
3260 | uint32 i;\r | |
3261 | \r | |
3262 | if (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 | |
3272 | return sim_set_idle (uptr, val, cptr, desc);\r | |
3273 | }\r | |
3274 | \r | |
3275 | t_stat cpu_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc)\r | |
3276 | {\r | |
3277 | if (sim_idle_enab && (cpu_idle_type != 0))\r | |
3278 | fprintf (st, "idle enabled=%s", os_tab[cpu_idle_type - 1].name);\r | |
3279 | else fprintf (st, "idle disabled");\r | |
3280 | return SCPE_OK;\r | |
3281 | }\r |