First Commit of my working state
[simh.git] / PDP11 / pdp11_cpu.c
CommitLineData
196ba1fc
PH
1/* pdp11_cpu.c: PDP-11 CPU simulator\r
2\r
3 Copyright (c) 1993-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 PDP-11 CPU\r
27\r
28 22-Apr-08 RMS Fixed MMR0 treatment in RESET (found by Walter Mueller)\r
29 02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas)\r
30 28-Apr-07 RMS Removed clock initialization\r
31 27-Oct-06 RMS Added idle support\r
32 18-Oct-06 RMS Fixed bug in ASH -32 C value\r
33 24-May-06 RMS Added instruction history\r
34 03-May-06 RMS Fixed XOR operand fetch order for 11/70-style systems\r
35 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)\r
36 16-Aug-05 RMS Fixed C++ declaration and cast problems\r
37 19-May-05 RMS Replaced WAIT clock queue check with API call\r
38 19-Jan-05 RMS Fixed bug(s) in RESET for 11/70 (reported by Tim Chapman)\r
39 22-Dec-04 RMS Fixed WAIT to work in all modes (from John Dundas)\r
40 02-Oct-04 RMS Added model emulation\r
41 25-Jan-04 RMS Removed local debug logging support\r
42 29-Dec-03 RMS Formalized 18b Qbus support\r
43 21-Dec-03 RMS Added autoconfiguration controls\r
44 05-Jun-03 RMS Fixed bugs in memory size table\r
45 12-Mar-03 RMS Added logical name support\r
46 01-Feb-03 RMS Changed R display to follow PSW<rs>, added SP display\r
47 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict\r
48 05-Jan-03 RMS Added memory size restore support\r
49 17-Oct-02 RMS Fixed bug in examine/deposit (found by Hans Pufal)\r
50 08-Oct-02 RMS Revised to build dib_tab dynamically\r
51 Added SHOW IOSPACE\r
52 09-Sep-02 RMS Added KW11P support\r
53 14-Jul-02 RMS Fixed bug in MMR0 error status load\r
54 03-Jun-02 RMS Fixed relocation add overflow, added PS<15:12> = 1111\r
55 special case logic to MFPI and removed it from MTPI\r
56 (found by John Dundas)\r
57 29-Apr-02 RMS More fixes to DIV and ASH/ASHC (found by John Dundas)\r
58 28-Apr-02 RMS Fixed bugs in illegal instruction 000010 and in\r
59 write-only memory pages (found by Wolfgang Helbig)\r
60 21-Apr-02 RMS Fixed bugs in DIV by zero, DIV overflow, TSTSET, RTS,\r
61 ASHC -32, and red zone trap (found by John Dundas)\r
62 04-Mar-02 RMS Changed double operand evaluation order for M+\r
63 23-Feb-02 RMS Fixed bug in MAINT, CPUERR, MEMERR read\r
64 28-Jan-02 RMS Revised for multiple timers; fixed calc_MMR1 macros\r
65 06-Jan-02 RMS Revised enable/disable support\r
66 30-Dec-01 RMS Added old PC queue\r
67 25-Dec-01 RMS Cleaned up sim_inst declarations\r
68 11-Dec-01 RMS Moved interrupt debug code\r
69 07-Dec-01 RMS Revised to use new breakpoint package\r
70 08-Nov-01 RMS Moved I/O to external module\r
71 26-Oct-01 RMS Revised to use symbolic definitions for IO page\r
72 15-Oct-01 RMS Added debug logging\r
73 08-Oct-01 RMS Fixed bug in revised interrupt logic\r
74 07-Sep-01 RMS Revised device disable and interrupt mechanisms\r
75 26-Aug-01 RMS Added DZ11 support\r
76 10-Aug-01 RMS Removed register from declarations\r
77 17-Jul-01 RMS Fixed warning from VC++ 6.0\r
78 01-Jun-01 RMS Added DZ11 interrupts\r
79 23-Apr-01 RMS Added RK611 support\r
80 05-Apr-01 RMS Added TS11/TSV05 support\r
81 05-Mar-01 RMS Added clock calibration support\r
82 11-Feb-01 RMS Added DECtape support\r
83 25-Jan-01 RMS Fixed 4M memory definition (found by Eric Smith)\r
84 14-Apr-99 RMS Changed t_addr to unsigned\r
85 18-Aug-98 RMS Added CIS support\r
86 09-May-98 RMS Fixed bug in DIV overflow test\r
87 19-Jan-97 RMS Added RP/RM support\r
88 06-Apr-96 RMS Added dynamic memory sizing\r
89 29-Feb-96 RMS Added TM11 support\r
90 17-Jul-94 RMS Corrected updating of MMR1 if MMR0 locked\r
91\r
92 The register state for the PDP-11 is:\r
93\r
94 REGFILE[0:5][0] general register set\r
95 REGFILE[0:5][1] alternate general register set\r
96 STACKFILE[4] stack pointers for kernel, supervisor, unused, user\r
97 PC program counter\r
98 PSW processor status word\r
99 <15:14> = CM current processor mode\r
100 <13:12> = PM previous processor mode\r
101 <11> = RS register set select\r
102 <8> = FPD first part done (CIS)\r
103 <7:5> = IPL interrupt priority level\r
104 <4> = TBIT trace trap enable\r
105 <3:0> = NZVC condition codes\r
106 FR[0:5] floating point accumulators\r
107 FPS floating point status register\r
108 FEC floating exception code\r
109 FEA floating exception address\r
110 MMR0,1,2,3 memory management control registers\r
111 APRFILE[0:63] memory management relocation registers for\r
112 kernel, supervisor, unused, user\r
113 <31:16> = PAR processor address registers\r
114 <15:0> = PDR processor data registers\r
115 PIRQ processor interrupt request register\r
116 CPUERR CPU error register\r
117 MEMERR memory system error register\r
118 CCR cache control register\r
119 MAINT maintenance register\r
120 HITMISS cache status register\r
121 SR switch register\r
122 DR display register\r
123\r
124 The PDP-11 has many instruction formats:\r
125\r
126 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ double operand\r
127 | opcode | source spec | dest spec | 010000:067777\r
128 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 110000:167777\r
129\r
130 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand\r
131 | opcode | src reg| dest spec | 004000:004777\r
132 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 070000:077777\r
133\r
134 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single operand\r
135 | opcode | dest spec | 000100:000177\r
136 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000300:000377\r
137 005000:007777\r
138 105000:107777\r
139\r
140 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single register\r
141 | opcode |dest reg| 000200:000207\r
142 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000230:000237\r
143\r
144 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand\r
145 | opcode | 000000:000007\r
146 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
147\r
148 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ branch\r
149 | opcode | branch displacement | 000400:003477\r
150 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 100000:103477\r
151\r
152 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ EMT/TRAP\r
153 | opcode | trap code | 104000:104777\r
154 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
155\r
156 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ cond code operator\r
157 | opcode | immediate | 000240:000277\r
158 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\r
159\r
160 An operand specifier consists of an addressing mode and a register.\r
161 The addressing modes are:\r
162\r
163 0 register direct R op = R\r
164 1 register deferred (R) op = M[R]\r
165 2 autoincrement (R)+ op = M[R]; R = R + length\r
166 3 autoincrement deferred @(R)+ op = M[M[R]]; R = R + 2\r
167 4 autodecrement -(R) R = R - length; op = M[R]\r
168 5 autodecrement deferred @-(R) R = R - 2; op = M[M[R]]\r
169 6 displacement d(R) op = M[R + disp]\r
170 7 displacement deferred @d(R) op = M[M[R + disp]]\r
171\r
172 There are eight general registers, R0-R7. R6 is the stack pointer,\r
173 R7 the PC. The combination of addressing modes with R7 yields:\r
174\r
175 27 immediate #n op = M[PC]; PC = PC + 2\r
176 37 absolute @#n op = M[M[PC]]; PC = PC + 2\r
177 67 relative d(PC) op = M[PC + disp]\r
178 77 relative deferred @d(PC) op = M[M[PC + disp]]\r
179\r
180 This routine is the instruction decode routine for the PDP-11. It\r
181 is called from the simulator control program to execute instructions\r
182 in simulated memory, starting at the simulated PC. It runs until an\r
183 enabled exception is encountered.\r
184\r
185 General notes:\r
186\r
187 1. Virtual address format. PDP-11 memory management uses the 16b\r
188 virtual address, the type of reference (instruction or data), and\r
189 the current mode, to construct the 22b physical address. To\r
190 package this conveniently, the simulator uses a 19b pseudo virtual\r
191 address, consisting of the 16b virtual address prefixed with the\r
192 current mode and ispace/dspace indicator. These are precalculated\r
193 as isenable and dsenable for ispace and dspace, respectively, and\r
194 must be recalculated whenever MMR0, MMR3, or PSW<cm> changes.\r
195\r
196 2. Traps and interrupts. Variable trap_req bit-encodes all possible\r
197 traps. In addition, an interrupt pending bit is encoded as the\r
198 lowest priority trap. Traps are processed by trap_vec and trap_clear,\r
199 which provide the vector and subordinate traps to clear, respectively.\r
200\r
201 Array int_req[0:7] bit encodes all possible interrupts. It is masked\r
202 under the interrupt priority level, ipl. If any interrupt request\r
203 is not masked, the interrupt bit is set in trap_req. While most\r
204 interrupts are handled centrally, a device can supply an interrupt\r
205 acknowledge routine.\r
206\r
207 3. PSW handling. The PSW is kept as components, for easier access.\r
208 Because the PSW can be explicitly written as address 17777776,\r
209 all instructions must update PSW before executing their last write.\r
210\r
211 4. Adding I/O devices. These modules must be modified:\r
212\r
213 pdp11_defs.h add device address and interrupt definitions\r
214 pdp11_sys.c add to sim_devices table entry\r
215*/\r
216\r
217/* Definitions */\r
218\r
219#include "pdp11_defs.h"\r
220#include "pdp11_cpumod.h"\r
221\r
222#define PCQ_SIZE 64 /* must be 2**n */\r
223#define PCQ_MASK (PCQ_SIZE - 1)\r
224#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC\r
225#define calc_is(md) ((md) << VA_V_MODE)\r
226#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0))\r
227#define calc_MMR1(val) ((MMR1)? (((val) << 8) | MMR1): (val))\r
228#define GET_SIGN_W(v) (((v) >> 15) & 1)\r
229#define GET_SIGN_B(v) (((v) >> 7) & 1)\r
230#define GET_Z(v) ((v) == 0)\r
231#define JMP_PC(x) PCQ_ENTRY; PC = (x)\r
232#define BRANCH_F(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) & 0377)) & 0177777\r
233#define BRANCH_B(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) | 0177400)) & 0177777\r
234#define last_pa (cpu_unit.u4) /* auto save/rest */\r
235#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy */\r
236#define UNIT_MSIZE (1u << UNIT_V_MSIZE)\r
237\r
238#define HIST_MIN 64\r
239#define HIST_MAX (1u << 18)\r
240#define HIST_VLD 1 /* make PC odd */\r
241#define HIST_ILNT 4 /* max inst length */\r
242\r
243typedef struct {\r
244 uint16 pc;\r
245 uint16 psw;\r
246 uint16 src;\r
247 uint16 dst;\r
248 uint16 inst[HIST_ILNT];\r
249 } InstHistory;\r
250\r
251/* Global state */\r
252\r
253extern FILE *sim_log;\r
254\r
255uint16 *M = NULL; /* memory */\r
256int32 REGFILE[6][2] = { 0 }; /* R0-R5, two sets */\r
257int32 STACKFILE[4] = { 0 }; /* SP, four modes */\r
258int32 saved_PC = 0; /* program counter */\r
259int32 R[8] = { 0 }; /* working registers */\r
260int32 PSW = 0; /* PSW */\r
261 int32 cm = 0; /* current mode */\r
262 int32 pm = 0; /* previous mode */\r
263 int32 rs = 0; /* register set */\r
264 int32 fpd = 0; /* first part done */\r
265 int32 ipl = 0; /* int pri level */\r
266 int32 tbit = 0; /* trace flag */\r
267 int32 N = 0, Z = 0, V = 0, C = 0; /* condition codes */\r
268int32 wait_state = 0; /* wait state */\r
269int32 trap_req = 0; /* trap requests */\r
270int32 int_req[IPL_HLVL] = { 0 }; /* interrupt requests */\r
271int32 PIRQ = 0; /* programmed int req */\r
272int32 STKLIM = 0; /* stack limit */\r
273fpac_t FR[6] = { 0 }; /* fp accumulators */\r
274int32 FPS = 0; /* fp status */\r
275int32 FEC = 0; /* fp exception code */\r
276int32 FEA = 0; /* fp exception addr */\r
277int32 APRFILE[64] = { 0 }; /* PARs/PDRs */\r
278int32 MMR0 = 0; /* MMR0 - status */\r
279int32 MMR1 = 0; /* MMR1 - R+/-R */\r
280int32 MMR2 = 0; /* MMR2 - saved PC */\r
281int32 MMR3 = 0; /* MMR3 - 22b status */\r
282int32 cpu_bme = 0; /* bus map enable */\r
283int32 cpu_astop = 0; /* address stop */\r
284int32 isenable = 0, dsenable = 0; /* i, d space flags */\r
285int32 stop_trap = 1; /* stop on trap */\r
286int32 stop_vecabort = 1; /* stop on vec abort */\r
287int32 stop_spabort = 1; /* stop on SP abort */\r
288int32 wait_enable = 0; /* wait state enable */\r
289int32 autcon_enb = 1; /* autoconfig enable */\r
290uint32 cpu_model = MOD_1173; /* CPU model */\r
291uint32 cpu_type = 1u << MOD_1173; /* model as bit mask */\r
292uint32 cpu_opt = SOP_1173; /* CPU options */\r
293uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */\r
294int32 pcq_p = 0; /* PC queue ptr */\r
295REG *pcq_r = NULL; /* PC queue reg ptr */\r
296jmp_buf save_env; /* abort handler */\r
297int32 hst_p = 0; /* history pointer */\r
298int32 hst_lnt = 0; /* history length */\r
299InstHistory *hst = NULL; /* instruction history */\r
300int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */\r
301t_addr cpu_memsize = INIMEMSIZE; /* last mem addr */\r
302\r
303extern int32 CPUERR, MAINT;\r
304extern int32 sim_interval;\r
305extern int32 sim_int_char;\r
306extern uint32 sim_switches;\r
307extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */\r
308extern t_bool sim_idle_enab;\r
309extern DEVICE *sim_devices[];\r
310extern CPUTAB cpu_tab[];\r
311\r
312/* Function declarations */\r
313\r
314t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);\r
315t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);\r
316t_stat cpu_reset (DEVICE *dptr);\r
317t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);\r
318t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);\r
319t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc);\r
320int32 GeteaB (int32 spec);\r
321int32 GeteaW (int32 spec);\r
322int32 relocR (int32 addr);\r
323int32 relocW (int32 addr);\r
324void relocR_test (int32 va, int32 apridx);\r
325void relocW_test (int32 va, int32 apridx);\r
326t_bool PLF_test (int32 va, int32 apr);\r
327void reloc_abort (int32 err, int32 apridx);\r
328int32 ReadE (int32 addr);\r
329int32 ReadW (int32 addr);\r
330int32 ReadB (int32 addr);\r
331int32 ReadMW (int32 addr);\r
332int32 ReadMB (int32 addr);\r
333void WriteW (int32 data, int32 addr);\r
334void WriteB (int32 data, int32 addr);\r
335void PWriteW (int32 data, int32 addr);\r
336void PWriteB (int32 data, int32 addr);\r
337void set_r_display (int32 rs, int32 cm);\r
338t_stat CPU_wr (int32 data, int32 addr, int32 access);\r
339void set_stack_trap (int32 adr);\r
340int32 get_PSW (void);\r
341void put_PSW (int32 val, t_bool prot);\r
342void put_PIRQ (int32 val);\r
343\r
344extern void fp11 (int32 IR);\r
345extern t_stat cis11 (int32 IR);\r
346extern t_stat fis11 (int32 IR);\r
347extern t_stat build_dib_tab (void);\r
348extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);\r
349extern t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc);\r
350extern t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc);\r
351extern t_stat iopageR (int32 *data, uint32 addr, int32 access);\r
352extern t_stat iopageW (int32 data, uint32 addr, int32 access);\r
353extern int32 calc_ints (int32 nipl, int32 trq);\r
354extern int32 get_vector (int32 nipl);\r
355\r
356/* Trap data structures */\r
357\r
358int32 trap_vec[TRAP_V_MAX] = { /* trap req to vector */\r
359 VEC_RED, VEC_ODD, VEC_MME, VEC_NXM,\r
360 VEC_PAR, VEC_PRV, VEC_ILL, VEC_BPT,\r
361 VEC_IOT, VEC_EMT, VEC_TRAP, VEC_TRC,\r
362 VEC_YEL, VEC_PWRFL, VEC_FPE\r
363 };\r
364\r
365int32 trap_clear[TRAP_V_MAX] = { /* trap clears */\r
366 TRAP_RED+TRAP_PAR+TRAP_YEL+TRAP_TRC+TRAP_ODD+TRAP_NXM,\r
367 TRAP_ODD+TRAP_PAR+TRAP_YEL+TRAP_TRC,\r
368 TRAP_MME+TRAP_PAR+TRAP_YEL+TRAP_TRC,\r
369 TRAP_NXM+TRAP_PAR+TRAP_YEL+TRAP_TRC,\r
370 TRAP_PAR+TRAP_TRC, TRAP_PRV+TRAP_TRC,\r
371 TRAP_ILL+TRAP_TRC, TRAP_BPT+TRAP_TRC,\r
372 TRAP_IOT+TRAP_TRC, TRAP_EMT+TRAP_TRC,\r
373 TRAP_TRAP+TRAP_TRC, TRAP_TRC,\r
374 TRAP_YEL, TRAP_PWRFL, TRAP_FPE\r
375 };\r
376\r
377/* CPU data structures\r
378\r
379 cpu_dev CPU device descriptor\r
380 cpu_unit CPU unit descriptor\r
381 cpu_reg CPU register list\r
382 cpu_mod CPU modifier list\r
383*/\r
384\r
385UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK, INIMEMSIZE) };\r
386\r
387REG cpu_reg[] = {\r
388 { ORDATA (PC, saved_PC, 16) },\r
389 { ORDATA (R0, REGFILE[0][0], 16) },\r
390 { ORDATA (R1, REGFILE[1][0], 16) },\r
391 { ORDATA (R2, REGFILE[2][0], 16) },\r
392 { ORDATA (R3, REGFILE[3][0], 16) },\r
393 { ORDATA (R4, REGFILE[4][0], 16) },\r
394 { ORDATA (R5, REGFILE[5][0], 16) },\r
395 { ORDATA (SP, STACKFILE[MD_KER], 16) },\r
396 { ORDATA (R00, REGFILE[0][0], 16) },\r
397 { ORDATA (R01, REGFILE[1][0], 16) },\r
398 { ORDATA (R02, REGFILE[2][0], 16) },\r
399 { ORDATA (R03, REGFILE[3][0], 16) },\r
400 { ORDATA (R04, REGFILE[4][0], 16) },\r
401 { ORDATA (R05, REGFILE[5][0], 16) },\r
402 { ORDATA (R10, REGFILE[0][1], 16) },\r
403 { ORDATA (R11, REGFILE[1][1], 16) },\r
404 { ORDATA (R12, REGFILE[2][1], 16) },\r
405 { ORDATA (R13, REGFILE[3][1], 16) },\r
406 { ORDATA (R14, REGFILE[4][1], 16) },\r
407 { ORDATA (R15, REGFILE[5][1], 16) },\r
408 { ORDATA (KSP, STACKFILE[MD_KER], 16) },\r
409 { ORDATA (SSP, STACKFILE[MD_SUP], 16) },\r
410 { ORDATA (USP, STACKFILE[MD_USR], 16) },\r
411 { ORDATA (PSW, PSW, 16) },\r
412 { GRDATA (CM, PSW, 8, 2, PSW_V_CM) },\r
413 { GRDATA (PM, PSW, 8, 2, PSW_V_PM) },\r
414 { FLDATA (RS, PSW, PSW_V_RS) },\r
415 { FLDATA (FPD, PSW, PSW_V_FPD) },\r
416 { GRDATA (IPL, PSW, 8, 3, PSW_V_IPL) },\r
417 { FLDATA (T, PSW, PSW_V_TBIT) },\r
418 { FLDATA (N, PSW, PSW_V_N) },\r
419 { FLDATA (Z, PSW, PSW_V_Z) },\r
420 { FLDATA (V, PSW, PSW_V_V) },\r
421 { FLDATA (C, PSW, PSW_V_C) },\r
422 { ORDATA (PIRQ, PIRQ, 16) },\r
423 { ORDATA (STKLIM, STKLIM, 16) },\r
424 { ORDATA (FAC0H, FR[0].h, 32) },\r
425 { ORDATA (FAC0L, FR[0].l, 32) },\r
426 { ORDATA (FAC1H, FR[1].h, 32) },\r
427 { ORDATA (FAC1L, FR[1].l, 32) },\r
428 { ORDATA (FAC2H, FR[2].h, 32) },\r
429 { ORDATA (FAC2L, FR[2].l, 32) },\r
430 { ORDATA (FAC3H, FR[3].h, 32) },\r
431 { ORDATA (FAC3L, FR[3].l, 32) },\r
432 { ORDATA (FAC4H, FR[4].h, 32) },\r
433 { ORDATA (FAC4L, FR[4].l, 32) },\r
434 { ORDATA (FAC5H, FR[5].h, 32) },\r
435 { ORDATA (FAC5L, FR[5].l, 32) },\r
436 { ORDATA (FPS, FPS, 16) },\r
437 { ORDATA (FEA, FEA, 16) },\r
438 { ORDATA (FEC, FEC, 4) },\r
439 { ORDATA (MMR0, MMR0, 16) },\r
440 { ORDATA (MMR1, MMR1, 16) },\r
441 { ORDATA (MMR2, MMR2, 16) },\r
442 { ORDATA (MMR3, MMR3, 16) },\r
443 { GRDATA (KIPAR0, APRFILE[000], 8, 16, 16) },\r
444 { GRDATA (KIPDR0, APRFILE[000], 8, 16, 0) },\r
445 { GRDATA (KIPAR1, APRFILE[001], 8, 16, 16) },\r
446 { GRDATA (KIPDR1, APRFILE[001], 8, 16, 0) },\r
447 { GRDATA (KIPAR2, APRFILE[002], 8, 16, 16) },\r
448 { GRDATA (KIPDR2, APRFILE[002], 8, 16, 0) },\r
449 { GRDATA (KIPAR3, APRFILE[003], 8, 16, 16) },\r
450 { GRDATA (KIPDR3, APRFILE[003], 8, 16, 0) },\r
451 { GRDATA (KIPAR4, APRFILE[004], 8, 16, 16) },\r
452 { GRDATA (KIPDR4, APRFILE[004], 8, 16, 0) },\r
453 { GRDATA (KIPAR5, APRFILE[005], 8, 16, 16) },\r
454 { GRDATA (KIPDR5, APRFILE[005], 8, 16, 0) },\r
455 { GRDATA (KIPAR6, APRFILE[006], 8, 16, 16) },\r
456 { GRDATA (KIPDR6, APRFILE[006], 8, 16, 0) },\r
457 { GRDATA (KIPAR7, APRFILE[007], 8, 16, 16) },\r
458 { GRDATA (KIPDR7, APRFILE[007], 8, 16, 0) },\r
459 { GRDATA (KDPAR0, APRFILE[010], 8, 16, 16) },\r
460 { GRDATA (KDPDR0, APRFILE[010], 8, 16, 0) },\r
461 { GRDATA (KDPAR1, APRFILE[011], 8, 16, 16) },\r
462 { GRDATA (KDPDR1, APRFILE[011], 8, 16, 0) },\r
463 { GRDATA (KDPAR2, APRFILE[012], 8, 16, 16) },\r
464 { GRDATA (KDPDR2, APRFILE[012], 8, 16, 0) },\r
465 { GRDATA (KDPAR3, APRFILE[013], 8, 16, 16) },\r
466 { GRDATA (KDPDR3, APRFILE[013], 8, 16, 0) },\r
467 { GRDATA (KDPAR4, APRFILE[014], 8, 16, 16) },\r
468 { GRDATA (KDPDR4, APRFILE[014], 8, 16, 0) },\r
469 { GRDATA (KDPAR5, APRFILE[015], 8, 16, 16) },\r
470 { GRDATA (KDPDR5, APRFILE[015], 8, 16, 0) },\r
471 { GRDATA (KDPAR6, APRFILE[016], 8, 16, 16) },\r
472 { GRDATA (KDPDR6, APRFILE[016], 8, 16, 0) },\r
473 { GRDATA (KDPAR7, APRFILE[017], 8, 16, 16) },\r
474 { GRDATA (KDPDR7, APRFILE[017], 8, 16, 0) },\r
475 { GRDATA (SIPAR0, APRFILE[020], 8, 16, 16) },\r
476 { GRDATA (SIPDR0, APRFILE[020], 8, 16, 0) },\r
477 { GRDATA (SIPAR1, APRFILE[021], 8, 16, 16) },\r
478 { GRDATA (SIPDR1, APRFILE[021], 8, 16, 0) },\r
479 { GRDATA (SIPAR2, APRFILE[022], 8, 16, 16) },\r
480 { GRDATA (SIPDR2, APRFILE[022], 8, 16, 0) },\r
481 { GRDATA (SIPAR3, APRFILE[023], 8, 16, 16) },\r
482 { GRDATA (SIPDR3, APRFILE[023], 8, 16, 0) },\r
483 { GRDATA (SIPAR4, APRFILE[024], 8, 16, 16) },\r
484 { GRDATA (SIPDR4, APRFILE[024], 8, 16, 0) },\r
485 { GRDATA (SIPAR5, APRFILE[025], 8, 16, 16) },\r
486 { GRDATA (SIPDR5, APRFILE[025], 8, 16, 0) },\r
487 { GRDATA (SIPAR6, APRFILE[026], 8, 16, 16) },\r
488 { GRDATA (SIPDR6, APRFILE[026], 8, 16, 0) },\r
489 { GRDATA (SIPAR7, APRFILE[027], 8, 16, 16) },\r
490 { GRDATA (SIPDR7, APRFILE[027], 8, 16, 0) },\r
491 { GRDATA (SDPAR0, APRFILE[030], 8, 16, 16) },\r
492 { GRDATA (SDPDR0, APRFILE[030], 8, 16, 0) },\r
493 { GRDATA (SDPAR1, APRFILE[031], 8, 16, 16) },\r
494 { GRDATA (SDPDR1, APRFILE[031], 8, 16, 0) },\r
495 { GRDATA (SDPAR2, APRFILE[032], 8, 16, 16) },\r
496 { GRDATA (SDPDR2, APRFILE[032], 8, 16, 0) },\r
497 { GRDATA (SDPAR3, APRFILE[033], 8, 16, 16) },\r
498 { GRDATA (SDPDR3, APRFILE[033], 8, 16, 0) },\r
499 { GRDATA (SDPAR4, APRFILE[034], 8, 16, 16) },\r
500 { GRDATA (SDPDR4, APRFILE[034], 8, 16, 0) },\r
501 { GRDATA (SDPAR5, APRFILE[035], 8, 16, 16) },\r
502 { GRDATA (SDPDR5, APRFILE[035], 8, 16, 0) },\r
503 { GRDATA (SDPAR6, APRFILE[036], 8, 16, 16) },\r
504 { GRDATA (SDPDR6, APRFILE[036], 8, 16, 0) },\r
505 { GRDATA (SDPAR7, APRFILE[037], 8, 16, 16) },\r
506 { GRDATA (SDPDR7, APRFILE[037], 8, 16, 0) },\r
507 { GRDATA (UIPAR0, APRFILE[060], 8, 16, 16) },\r
508 { GRDATA (UIPDR0, APRFILE[060], 8, 16, 0) },\r
509 { GRDATA (UIPAR1, APRFILE[061], 8, 16, 16) },\r
510 { GRDATA (UIPDR1, APRFILE[061], 8, 16, 0) },\r
511 { GRDATA (UIPAR2, APRFILE[062], 8, 16, 16) },\r
512 { GRDATA (UIPDR2, APRFILE[062], 8, 16, 0) },\r
513 { GRDATA (UIPAR3, APRFILE[063], 8, 16, 16) },\r
514 { GRDATA (UIPDR3, APRFILE[063], 8, 16, 0) },\r
515 { GRDATA (UIPAR4, APRFILE[064], 8, 16, 16) },\r
516 { GRDATA (UIPDR4, APRFILE[064], 8, 16, 0) },\r
517 { GRDATA (UIPAR5, APRFILE[065], 8, 16, 16) },\r
518 { GRDATA (UIPDR5, APRFILE[065], 8, 16, 0) },\r
519 { GRDATA (UIPAR6, APRFILE[066], 8, 16, 16) },\r
520 { GRDATA (UIPDR6, APRFILE[066], 8, 16, 0) },\r
521 { GRDATA (UIPAR7, APRFILE[067], 8, 16, 16) },\r
522 { GRDATA (UIPDR7, APRFILE[067], 8, 16, 0) },\r
523 { GRDATA (UDPAR0, APRFILE[070], 8, 16, 16) },\r
524 { GRDATA (UDPDR0, APRFILE[070], 8, 16, 0) },\r
525 { GRDATA (UDPAR1, APRFILE[071], 8, 16, 16) },\r
526 { GRDATA (UDPDR1, APRFILE[071], 8, 16, 0) },\r
527 { GRDATA (UDPAR2, APRFILE[072], 8, 16, 16) },\r
528 { GRDATA (UDPDR2, APRFILE[072], 8, 16, 0) },\r
529 { GRDATA (UDPAR3, APRFILE[073], 8, 16, 16) },\r
530 { GRDATA (UDPDR3, APRFILE[073], 8, 16, 0) },\r
531 { GRDATA (UDPAR4, APRFILE[074], 8, 16, 16) },\r
532 { GRDATA (UDPDR4, APRFILE[074], 8, 16, 0) },\r
533 { GRDATA (UDPAR5, APRFILE[075], 8, 16, 16) },\r
534 { GRDATA (UDPDR5, APRFILE[075], 8, 16, 0) },\r
535 { GRDATA (UDPAR6, APRFILE[076], 8, 16, 16) },\r
536 { GRDATA (UDPDR6, APRFILE[076], 8, 16, 0) },\r
537 { GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) },\r
538 { GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) },\r
539 { BRDATA (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO },\r
540 { ORDATA (TRAPS, trap_req, TRAP_V_MAX) },\r
541 { FLDATA (WAIT, wait_state, 0) },\r
542 { FLDATA (WAIT_ENABLE, wait_enable, 0), REG_HIDDEN },\r
543 { ORDATA (STOP_TRAPS, stop_trap, TRAP_V_MAX) },\r
544 { FLDATA (STOP_VECA, stop_vecabort, 0) },\r
545 { FLDATA (STOP_SPA, stop_spabort, 0) },\r
546 { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO },\r
547 { BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC },\r
548 { ORDATA (PCQP, pcq_p, 6), REG_HRO },\r
549 { ORDATA (WRU, sim_int_char, 8) },\r
550 { ORDATA (MODEL, cpu_model, 16), REG_HRO },\r
551 { ORDATA (OPTIONS, cpu_opt, 32), REG_HRO },\r
552 { NULL}\r
553 };\r
554\r
555MTAB cpu_mod[] = {\r
556 { MTAB_XTD|MTAB_VDV, 0, "TYPE", NULL,\r
557 NULL, &cpu_show_model },\r
558 { MTAB_XTD|MTAB_VDV, MOD_1103, NULL, "11/03", &cpu_set_model },\r
559 { MTAB_XTD|MTAB_VDV, MOD_1104, NULL, "11/04", &cpu_set_model },\r
560 { MTAB_XTD|MTAB_VDV, MOD_1105, NULL, "11/05", &cpu_set_model },\r
561 { MTAB_XTD|MTAB_VDV, MOD_1120, NULL, "11/20", &cpu_set_model },\r
562 { MTAB_XTD|MTAB_VDV, MOD_1123, NULL, "11/23", &cpu_set_model },\r
563 { MTAB_XTD|MTAB_VDV, MOD_1123P, NULL, "11/23+", &cpu_set_model },\r
564 { MTAB_XTD|MTAB_VDV, MOD_1124, NULL, "11/24", &cpu_set_model },\r
565 { MTAB_XTD|MTAB_VDV, MOD_1134, NULL, "11/34", &cpu_set_model },\r
566 { MTAB_XTD|MTAB_VDV, MOD_1140, NULL, "11/40", &cpu_set_model },\r
567 { MTAB_XTD|MTAB_VDV, MOD_1144, NULL, "11/44", &cpu_set_model },\r
568 { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "11/45", &cpu_set_model },\r
569 { MTAB_XTD|MTAB_VDV, MOD_1153, NULL, "11/53", &cpu_set_model },\r
570 { MTAB_XTD|MTAB_VDV, MOD_1160, NULL, "11/60", &cpu_set_model },\r
571 { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "11/70", &cpu_set_model },\r
572 { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "11/73", &cpu_set_model },\r
573 { MTAB_XTD|MTAB_VDV, MOD_1173B, NULL, "11/73B", &cpu_set_model },\r
574 { MTAB_XTD|MTAB_VDV, MOD_1183, NULL, "11/83", &cpu_set_model },\r
575 { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "11/84", &cpu_set_model },\r
576 { MTAB_XTD|MTAB_VDV, MOD_1193, NULL, "11/93", &cpu_set_model },\r
577 { MTAB_XTD|MTAB_VDV, MOD_1194, NULL, "11/94", &cpu_set_model },\r
578 { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model },\r
579 { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model },\r
580 { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model },\r
581 { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "U18", &cpu_set_model },\r
582 { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "EIS", &cpu_set_opt },\r
583 { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "NOEIS", &cpu_clr_opt },\r
584 { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "FIS", &cpu_set_opt },\r
585 { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "NOFIS", &cpu_clr_opt },\r
586 { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "FPP", &cpu_set_opt },\r
587 { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "NOFPP", &cpu_clr_opt },\r
588 { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "CIS", &cpu_set_opt },\r
589 { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "NOCIS", &cpu_clr_opt },\r
590 { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "MMU", &cpu_set_opt },\r
591 { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "NOMMU", &cpu_clr_opt },\r
592 { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },\r
593 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },\r
594 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},\r
595 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size},\r
596 { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size},\r
597 { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size},\r
598 { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size},\r
599 { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size},\r
600 { UNIT_MSIZE, 196608, NULL, "192K", &cpu_set_size},\r
601 { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size},\r
602 { UNIT_MSIZE, 393216, NULL, "384K", &cpu_set_size},\r
603 { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size},\r
604 { UNIT_MSIZE, 786432, NULL, "768K", &cpu_set_size},\r
605 { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size},\r
606 { UNIT_MSIZE, 2097152, NULL, "2048K", &cpu_set_size},\r
607 { UNIT_MSIZE, 3145728, NULL, "3072K", &cpu_set_size},\r
608 { UNIT_MSIZE, 4186112, NULL, "4096K", &cpu_set_size},\r
609 { UNIT_MSIZE, 1048576, NULL, "1M", &cpu_set_size},\r
610 { UNIT_MSIZE, 2097152, NULL, "2M", &cpu_set_size},\r
611 { UNIT_MSIZE, 3145728, NULL, "3M", &cpu_set_size},\r
612 { UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size},\r
613 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,\r
614 NULL, &show_iospace },\r
615 { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG",\r
616 &set_autocon, &show_autocon },\r
617 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG",\r
618 &set_autocon, NULL },\r
619 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",\r
620 &cpu_set_hist, &cpu_show_hist },\r
621 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL,\r
622 NULL, &cpu_show_virt },\r
623 { 0 }\r
624 };\r
625\r
626DEVICE cpu_dev = {\r
627 "CPU", &cpu_unit, cpu_reg, cpu_mod,\r
628 1, 8, 22, 2, 8, 16,\r
629 &cpu_ex, &cpu_dep, &cpu_reset,\r
630 NULL, NULL, NULL,\r
631 NULL, DEV_DYNM, 0,\r
632 NULL, &cpu_set_size, NULL\r
633 };\r
634\r
635t_stat sim_instr (void)\r
636{\r
637int abortval, i;\r
638volatile int32 trapea; /* used by setjmp */\r
639t_stat reason;\r
640\r
641/* Restore register state\r
642\r
643 1. PSW components\r
644 2. Active register file based on PSW<rs>\r
645 3. Active stack pointer based on PSW<cm>\r
646 4. Memory management control flags\r
647 5. Interrupt system\r
648*/\r
649\r
650reason = build_dib_tab (); /* build, chk dib_tab */\r
651if (reason != SCPE_OK) return reason;\r
652if (MEMSIZE < cpu_tab[cpu_model].maxm) /* mem size < max? */\r
653 cpu_memsize = MEMSIZE; /* then okay */\r
654else cpu_memsize = cpu_tab[cpu_model].maxm - IOPAGESIZE;/* max - io page */\r
655cpu_type = 1u << cpu_model; /* reset type mask */\r
656cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM); /* map enabled? */\r
657PC = saved_PC;\r
658put_PSW (PSW, 0); /* set PSW, call calc_xs */\r
659for (i = 0; i < 6; i++) R[i] = REGFILE[i][rs];\r
660SP = STACKFILE[cm];\r
661isenable = calc_is (cm);\r
662dsenable = calc_ds (cm);\r
663put_PIRQ (PIRQ); /* rewrite PIRQ */\r
664STKLIM = STKLIM & STKLIM_RW; /* clean up STKLIM */\r
665MMR0 = MMR0 | MMR0_IC; /* usually on */\r
666\r
667trap_req = calc_ints (ipl, trap_req); /* upd int req */\r
668trapea = 0;\r
669reason = 0;\r
670\r
671/* Abort handling\r
672\r
673 If an abort occurs in memory management or memory access, the lower\r
674 level routine executes a longjmp to this area OUTSIDE the main\r
675 simulation loop. The longjmp specifies a trap mask which is OR'd\r
676 into the trap_req register. Simulation then resumes at the fetch\r
677 phase, and the trap is sprung.\r
678\r
679 Aborts which occur within a trap sequence (trapea != 0) require\r
680 special handling. If the abort occured on the stack pushes, and\r
681 the mode (encoded in trapea) is kernel, an "emergency" kernel\r
682 stack is created at 4, and a red zone stack trap taken.\r
683\r
684 All variables used in setjmp processing, or assumed to be valid\r
685 after setjmp, must be volatile or global.\r
686*/\r
687\r
688abortval = setjmp (save_env); /* set abort hdlr */\r
689if (abortval != 0) {\r
690 trap_req = trap_req | abortval; /* or in trap flag */\r
691 if ((trapea > 0) && stop_vecabort) reason = STOP_VECABORT;\r
692 if ((trapea < 0) && /* stack push abort? */\r
693 (CPUT (STOP_STKA) || stop_spabort)) reason = STOP_SPABORT;\r
694 if (trapea == ~MD_KER) { /* kernel stk abort? */\r
695 setTRAP (TRAP_RED);\r
696 setCPUERR (CPUE_RED);\r
697 STACKFILE[MD_KER] = 4;\r
698 if (cm == MD_KER) SP = 4;\r
699 }\r
700 }\r
701\r
702/* Main instruction fetch/decode loop\r
703\r
704 Check for traps or interrupts. If trap, locate the vector and check\r
705 for stop condition. If interrupt, locate the vector.\r
706*/ \r
707\r
708while (reason == 0) {\r
709\r
710 int32 IR, srcspec, srcreg, dstspec, dstreg;\r
711 int32 src, src2, dst, ea;\r
712 int32 i, t, sign, oldrs, trapnum;\r
713\r
714 if (cpu_astop) {\r
715 cpu_astop = 0;\r
716 reason = SCPE_STOP;\r
717 break;\r
718 }\r
719\r
720 if (sim_interval <= 0) { /* intv cnt expired? */\r
721 reason = sim_process_event (); /* process events */\r
722 trap_req = calc_ints (ipl, trap_req); /* recalc int req */\r
723 continue;\r
724 } /* end if sim_interval */\r
725\r
726 if (trap_req) { /* check traps, ints */\r
727 trapea = 0; /* assume srch fails */\r
728 if (t = trap_req & TRAP_ALL) { /* if a trap */\r
729 for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) {\r
730 if ((t >> trapnum) & 1) { /* trap set? */\r
731 trapea = trap_vec[trapnum]; /* get vec, clr */\r
732 trap_req = trap_req & ~trap_clear[trapnum];\r
733 if ((stop_trap >> trapnum) & 1) /* stop on trap? */\r
734 reason = trapnum + 1;\r
735 break;\r
736 } /* end if t & 1 */\r
737 } /* end for */\r
738 } /* end if t */\r
739 else {\r
740 trapea = get_vector (ipl); /* get int vector */\r
741 trapnum = TRAP_V_MAX; /* defang stk trap */\r
742 } /* end else t */\r
743 if (trapea == 0) { /* nothing to do? */\r
744 trap_req = calc_ints (ipl, 0); /* recalculate */\r
745 continue; /* back to fetch */\r
746 } /* end if trapea */\r
747\r
748/* Process a trap or interrupt\r
749\r
750 1. Exit wait state\r
751 2. Save the current SP and PSW\r
752 3. Read the new PC, new PSW from trapea, kernel data space\r
753 4. Get the mode and stack selected by the new PSW\r
754 5. Push the old PC and PSW on the new stack\r
755 6. Update SP, PSW, and PC\r
756 7. If not stack overflow, check for stack overflow\r
757*/\r
758\r
759 wait_state = 0; /* exit wait state */\r
760 STACKFILE[cm] = SP;\r
761 PSW = get_PSW (); /* assemble PSW */\r
762 oldrs = rs;\r
763 if (CPUT (HAS_MMTR)) { /* 45,70? */\r
764 if (update_MM) MMR2 = trapea; /* save vector */\r
765 MMR0 = MMR0 & ~MMR0_IC; /* clear IC */\r
766 }\r
767 src = ReadW (trapea | calc_ds (MD_KER)); /* new PC */\r
768 src2 = ReadW ((trapea + 2) | calc_ds (MD_KER)); /* new PSW */\r
769 t = (src2 >> PSW_V_CM) & 03; /* new cm */\r
770 trapea = ~t; /* flag pushes */\r
771 WriteW (PSW, ((STACKFILE[t] - 2) & 0177777) | calc_ds (t));\r
772 WriteW (PC, ((STACKFILE[t] - 4) & 0177777) | calc_ds (t));\r
773 trapea = 0; /* clear trap flag */\r
774 src2 = (src2 & ~PSW_PM) | (cm << PSW_V_PM); /* insert prv mode */\r
775 put_PSW (src2, 0); /* call calc_is,ds */\r
776 if (rs != oldrs) { /* if rs chg, swap */\r
777 for (i = 0; i < 6; i++) {\r
778 REGFILE[i][oldrs] = R[i];\r
779 R[i] = REGFILE[i][rs];\r
780 }\r
781 }\r
782 SP = (STACKFILE[cm] - 4) & 0177777; /* update SP, PC */\r
783 isenable = calc_is (cm);\r
784 dsenable = calc_ds (cm);\r
785 trap_req = calc_ints (ipl, trap_req);\r
786 JMP_PC (src);\r
787 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)) &&\r
788 (trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL))\r
789 set_stack_trap (SP);\r
790 MMR0 = MMR0 | MMR0_IC; /* back to instr */\r
791 continue; /* end if traps */\r
792 }\r
793\r
794/* Fetch and decode next instruction */\r
795\r
796 if (tbit) setTRAP (TRAP_TRC);\r
797 if (wait_state) { /* wait state? */\r
798 if (sim_idle_enab) /* idle enabled? */\r
799 sim_idle (TMR_CLK, TRUE);\r
800 else if (wait_enable) /* old style idle? */\r
801 sim_interval = 0; /* force check */\r
802 else sim_interval = sim_interval - 1; /* count cycle */\r
803 continue;\r
804 }\r
805\r
806 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */\r
807 reason = STOP_IBKPT; /* stop simulation */\r
808 continue;\r
809 }\r
810\r
811 if (update_MM) { /* if mm not frozen */\r
812 MMR1 = 0;\r
813 MMR2 = PC;\r
814 }\r
815 IR = ReadE (PC | isenable); /* fetch instruction */\r
816 sim_interval = sim_interval - 1;\r
817 srcspec = (IR >> 6) & 077; /* src, dst specs */\r
818 dstspec = IR & 077;\r
819 srcreg = (srcspec <= 07); /* src, dst = rmode? */\r
820 dstreg = (dstspec <= 07);\r
821 if (hst_lnt) { /* record history? */\r
822 t_value val;\r
823 uint32 i;\r
824 hst[hst_p].pc = PC | HIST_VLD;\r
825 hst[hst_p].psw = get_PSW ();\r
826 hst[hst_p].src = R[srcspec & 07];\r
827 hst[hst_p].dst = R[dstspec & 07];\r
828 hst[hst_p].inst[0] = IR;\r
829 for (i = 1; i < HIST_ILNT; i++) {\r
830 if (cpu_ex (&val, (PC + (i << 1)) & 0177777, &cpu_unit, SWMASK ('V')))\r
831 hst[hst_p].inst[i] = 0;\r
832 else hst[hst_p].inst[i] = (uint16) val;\r
833 }\r
834 hst_p = (hst_p + 1);\r
835 if (hst_p >= hst_lnt) hst_p = 0;\r
836 }\r
837 PC = (PC + 2) & 0177777; /* incr PC, mod 65k */\r
838 switch ((IR >> 12) & 017) { /* decode IR<15:12> */\r
839\r
840/* Opcode 0: no operands, specials, branches, JSR, SOPs */\r
841\r
842 case 000:\r
843 switch ((IR >> 6) & 077) { /* decode IR<11:6> */\r
844 case 000: /* no operand */\r
845 if (IR >= 000010) { /* 000010 - 000077 */\r
846 setTRAP (TRAP_ILL); /* illegal */\r
847 break;\r
848 }\r
849 switch (IR) { /* decode IR<2:0> */\r
850 case 0: /* HALT */\r
851 if ((cm == MD_KER) &&\r
852 (!CPUT (CPUT_J) || ((MAINT & MAINT_HTRAP) == 0)))\r
853 reason = STOP_HALT;\r
854 else if (CPUT (HAS_HALT4)) { /* priv trap? */\r
855 setTRAP (TRAP_PRV);\r
856 setCPUERR (CPUE_HALT);\r
857 }\r
858 else setTRAP (TRAP_ILL); /* no, ill inst */\r
859 break;\r
860 case 1: /* WAIT */\r
861 wait_state = 1;\r
862 break;\r
863 case 3: /* BPT */\r
864 setTRAP (TRAP_BPT);\r
865 break;\r
866 case 4: /* IOT */\r
867 setTRAP (TRAP_IOT);\r
868 break;\r
869 case 5: /* RESET */\r
870 if (cm == MD_KER) {\r
871 reset_all (2); /* skip CPU, sys reg */\r
872 PIRQ = 0; /* clear PIRQ */\r
873 STKLIM = 0; /* clear STKLIM */\r
874 MMR0 = 0; /* clear MMR0 */\r
875 MMR3 = 0; /* clear MMR3 */\r
876 for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0;\r
877 trap_req = trap_req & ~TRAP_INT;\r
878 dsenable = calc_ds (cm);\r
879 }\r
880 break;\r
881 case 6: /* RTT */\r
882 if (!CPUT (HAS_RTT)) {\r
883 setTRAP (TRAP_ILL);\r
884 break;\r
885 }\r
886 case 2: /* RTI */\r
887 src = ReadW (SP | dsenable);\r
888 src2 = ReadW (((SP + 2) & 0177777) | dsenable);\r
889 STACKFILE[cm] = SP = (SP + 4) & 0177777;\r
890 oldrs = rs;\r
891 put_PSW (src2, (cm != MD_KER)); /* store PSW, prot */\r
892 if (rs != oldrs) {\r
893 for (i = 0; i < 6; i++) {\r
894 REGFILE[i][oldrs] = R[i];\r
895 R[i] = REGFILE[i][rs];\r
896 }\r
897 }\r
898 SP = STACKFILE[cm];\r
899 isenable = calc_is (cm);\r
900 dsenable = calc_ds (cm);\r
901 trap_req = calc_ints (ipl, trap_req);\r
902 JMP_PC (src);\r
903 if (CPUT (HAS_RTT) && tbit && /* RTT impl? */\r
904 (IR == 000002)) setTRAP (TRAP_TRC); /* RTI immed trap */\r
905 break;\r
906 case 7: /* MFPT */\r
907 if (CPUT (HAS_MFPT)) /* implemented? */\r
908 R[0] = cpu_tab[cpu_model].mfpt; /* get type */\r
909 else setTRAP (TRAP_ILL);\r
910 break;\r
911 } /* end switch no ops */\r
912 break; /* end case no ops */\r
913\r
914 case 001: /* JMP */\r
915 if (dstreg) setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL);\r
916 else {\r
917 dst = GeteaW (dstspec) & 0177777; /* get eff addr */\r
918 if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */\r
919 ((dstspec & 070) == 020)) /* JMP (R)+? */\r
920 dst = R[dstspec & 07]; /* use post incr */\r
921 JMP_PC (dst);\r
922 }\r
923 break; /* end JMP */\r
924\r
925 case 002: /* RTS et al*/\r
926 if (IR < 000210) { /* RTS */\r
927 dstspec = dstspec & 07;\r
928 JMP_PC (R[dstspec]);\r
929 R[dstspec] = ReadW (SP | dsenable);\r
930 if (dstspec != 6) SP = (SP + 2) & 0177777;\r
931 break;\r
932 } /* end if RTS */\r
933 if (IR < 000230) {\r
934 setTRAP (TRAP_ILL);\r
935 break;\r
936 }\r
937 if (IR < 000240) { /* SPL */\r
938 if (CPUT (HAS_SPL)) {\r
939 if (cm == MD_KER) ipl = IR & 07;\r
940 trap_req = calc_ints (ipl, trap_req);\r
941 }\r
942 else setTRAP (TRAP_ILL);\r
943 break;\r
944 } /* end if SPL */\r
945 if (IR < 000260) { /* clear CC */\r
946 if (IR & 010) N = 0;\r
947 if (IR & 004) Z = 0;\r
948 if (IR & 002) V = 0;\r
949 if (IR & 001) C = 0;\r
950 break;\r
951 } /* end if clear CCs */\r
952 if (IR & 010) N = 1; /* set CC */\r
953 if (IR & 004) Z = 1;\r
954 if (IR & 002) V = 1;\r
955 if (IR & 001) C = 1;\r
956 break; /* end case RTS et al */\r
957\r
958 case 003: /* SWAB */\r
959 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
960 dst = ((dst & 0377) << 8) | ((dst >> 8) & 0377);\r
961 N = GET_SIGN_B (dst & 0377);\r
962 Z = GET_Z (dst & 0377);\r
963 if (!CPUT (CPUT_20)) V = 0;\r
964 C = 0;\r
965 if (dstreg) R[dstspec] = dst;\r
966 else PWriteW (dst, last_pa);\r
967 break; /* end SWAB */\r
968\r
969 case 004: case 005: /* BR */\r
970 BRANCH_F (IR);\r
971 break;\r
972\r
973 case 006: case 007: /* BR */\r
974 BRANCH_B (IR);\r
975 break;\r
976\r
977 case 010: case 011: /* BNE */\r
978 if (Z == 0) { BRANCH_F (IR); } \r
979 break;\r
980\r
981 case 012: case 013: /* BNE */\r
982 if (Z == 0) { BRANCH_B (IR); }\r
983 break;\r
984\r
985 case 014: case 015: /* BEQ */\r
986 if (Z) { BRANCH_F (IR); } \r
987 break;\r
988\r
989 case 016: case 017: /* BEQ */\r
990 if (Z) { BRANCH_B (IR); }\r
991 break;\r
992\r
993 case 020: case 021: /* BGE */\r
994 if ((N ^ V) == 0) { BRANCH_F (IR); } \r
995 break;\r
996\r
997 case 022: case 023: /* BGE */\r
998 if ((N ^ V) == 0) { BRANCH_B (IR); }\r
999 break;\r
1000\r
1001 case 024: case 025: /* BLT */\r
1002 if (N ^ V) { BRANCH_F (IR); }\r
1003 break;\r
1004\r
1005 case 026: case 027: /* BLT */\r
1006 if (N ^ V) { BRANCH_B (IR); }\r
1007 break;\r
1008\r
1009 case 030: case 031: /* BGT */\r
1010 if ((Z | (N ^ V)) == 0) { BRANCH_F (IR); } \r
1011 break;\r
1012\r
1013 case 032: case 033: /* BGT */\r
1014 if ((Z | (N ^ V)) == 0) { BRANCH_B (IR); }\r
1015 break;\r
1016\r
1017 case 034: case 035: /* BLE */\r
1018 if (Z | (N ^ V)) { BRANCH_F (IR); } \r
1019 break;\r
1020\r
1021 case 036: case 037: /* BLE */\r
1022 if (Z | (N ^ V)) { BRANCH_B (IR); }\r
1023 break;\r
1024\r
1025 case 040: case 041: case 042: case 043: /* JSR */\r
1026 case 044: case 045: case 046: case 047:\r
1027 if (dstreg) setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL);\r
1028 else {\r
1029 srcspec = srcspec & 07;\r
1030 dst = GeteaW (dstspec);\r
1031 if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */\r
1032 ((dstspec & 070) == 020)) /* JSR (R)+? */\r
1033 dst = R[dstspec & 07]; /* use post incr */\r
1034 SP = (SP - 2) & 0177777;\r
1035 if (update_MM) MMR1 = calc_MMR1 (0366);\r
1036 WriteW (R[srcspec], SP | dsenable);\r
1037 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))\r
1038 set_stack_trap (SP);\r
1039 R[srcspec] = PC;\r
1040 JMP_PC (dst & 0177777);\r
1041 }\r
1042 break; /* end JSR */\r
1043\r
1044 case 050: /* CLR */\r
1045 N = V = C = 0;\r
1046 Z = 1;\r
1047 if (dstreg) R[dstspec] = 0;\r
1048 else WriteW (0, GeteaW (dstspec));\r
1049 break;\r
1050\r
1051 case 051: /* COM */\r
1052 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1053 dst = dst ^ 0177777;\r
1054 N = GET_SIGN_W (dst);\r
1055 Z = GET_Z (dst);\r
1056 V = 0;\r
1057 C = 1;\r
1058 if (dstreg) R[dstspec] = dst;\r
1059 else PWriteW (dst, last_pa);\r
1060 break;\r
1061\r
1062 case 052: /* INC */\r
1063 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1064 dst = (dst + 1) & 0177777;\r
1065 N = GET_SIGN_W (dst);\r
1066 Z = GET_Z (dst);\r
1067 V = (dst == 0100000);\r
1068 if (dstreg) R[dstspec] = dst;\r
1069 else PWriteW (dst, last_pa);\r
1070 break;\r
1071\r
1072 case 053: /* DEC */\r
1073 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1074 dst = (dst - 1) & 0177777;\r
1075 N = GET_SIGN_W (dst);\r
1076 Z = GET_Z (dst);\r
1077 V = (dst == 077777);\r
1078 if (dstreg) R[dstspec] = dst;\r
1079 else PWriteW (dst, last_pa);\r
1080 break;\r
1081\r
1082 case 054: /* NEG */\r
1083 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1084 dst = (-dst) & 0177777;\r
1085 N = GET_SIGN_W (dst);\r
1086 Z = GET_Z (dst);\r
1087 V = (dst == 0100000);\r
1088 C = Z ^ 1;\r
1089 if (dstreg) R[dstspec] = dst;\r
1090 else PWriteW (dst, last_pa);\r
1091 break;\r
1092\r
1093 case 055: /* ADC */\r
1094 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1095 dst = (dst + C) & 0177777;\r
1096 N = GET_SIGN_W (dst);\r
1097 Z = GET_Z (dst);\r
1098 V = (C && (dst == 0100000));\r
1099 C = C & Z;\r
1100 if (dstreg) R[dstspec] = dst;\r
1101 else PWriteW (dst, last_pa);\r
1102 break;\r
1103\r
1104 case 056: /* SBC */\r
1105 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1106 dst = (dst - C) & 0177777;\r
1107 N = GET_SIGN_W (dst);\r
1108 Z = GET_Z (dst);\r
1109 V = (C && (dst == 077777));\r
1110 C = (C && (dst == 0177777));\r
1111 if (dstreg) R[dstspec] = dst;\r
1112 else PWriteW (dst, last_pa);\r
1113 break;\r
1114\r
1115 case 057: /* TST */\r
1116 dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1117 N = GET_SIGN_W (dst);\r
1118 Z = GET_Z (dst);\r
1119 V = C = 0;\r
1120 break;\r
1121\r
1122 case 060: /* ROR */\r
1123 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1124 dst = (src >> 1) | (C << 15);\r
1125 N = GET_SIGN_W (dst);\r
1126 Z = GET_Z (dst);\r
1127 C = (src & 1);\r
1128 V = N ^ C;\r
1129 if (dstreg) R[dstspec] = dst;\r
1130 else PWriteW (dst, last_pa);\r
1131 break;\r
1132\r
1133 case 061: /* ROL */\r
1134 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1135 dst = ((src << 1) | C) & 0177777;\r
1136 N = GET_SIGN_W (dst);\r
1137 Z = GET_Z (dst);\r
1138 C = GET_SIGN_W (src);\r
1139 V = N ^ C;\r
1140 if (dstreg) R[dstspec] = dst;\r
1141 else PWriteW (dst, last_pa);\r
1142 break;\r
1143\r
1144 case 062: /* ASR */\r
1145 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1146 dst = (src >> 1) | (src & 0100000);\r
1147 N = GET_SIGN_W (dst);\r
1148 Z = GET_Z (dst);\r
1149 C = (src & 1);\r
1150 V = N ^ C;\r
1151 if (dstreg) R[dstspec] = dst;\r
1152 else PWriteW (dst, last_pa);\r
1153 break;\r
1154\r
1155 case 063: /* ASL */\r
1156 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1157 dst = (src << 1) & 0177777;\r
1158 N = GET_SIGN_W (dst);\r
1159 Z = GET_Z (dst);\r
1160 C = GET_SIGN_W (src);\r
1161 V = N ^ C;\r
1162 if (dstreg) R[dstspec] = dst;\r
1163 else PWriteW (dst, last_pa);\r
1164 break;\r
1165\r
1166/* Notes:\r
1167 - MxPI must mask GeteaW returned address to force ispace\r
1168 - MxPI must set MMR1 for SP recovery in case of fault\r
1169*/\r
1170\r
1171 case 064: /* MARK */\r
1172 if (CPUT (HAS_MARK)) {\r
1173 i = (PC + dstspec + dstspec) & 0177777;\r
1174 JMP_PC (R[5]);\r
1175 R[5] = ReadW (i | dsenable);\r
1176 SP = (i + 2) & 0177777;\r
1177 }\r
1178 else setTRAP (TRAP_ILL);\r
1179 break;\r
1180\r
1181 case 065: /* MFPI */\r
1182 if (CPUT (HAS_MXPY)) {\r
1183 if (dstreg) {\r
1184 if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm];\r
1185 else dst = R[dstspec];\r
1186 }\r
1187 else {\r
1188 i = ((cm == pm) && (cm == MD_USR))? calc_ds (pm): calc_is (pm);\r
1189 dst = ReadW ((GeteaW (dstspec) & 0177777) | i);\r
1190 }\r
1191 N = GET_SIGN_W (dst);\r
1192 Z = GET_Z (dst);\r
1193 V = 0;\r
1194 SP = (SP - 2) & 0177777;\r
1195 if (update_MM) MMR1 = calc_MMR1 (0366);\r
1196 WriteW (dst, SP | dsenable);\r
1197 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))\r
1198 set_stack_trap (SP);\r
1199 }\r
1200 else setTRAP (TRAP_ILL);\r
1201 break;\r
1202\r
1203 case 066: /* MTPI */\r
1204 if (CPUT (HAS_MXPY)) {\r
1205 dst = ReadW (SP | dsenable);\r
1206 N = GET_SIGN_W (dst);\r
1207 Z = GET_Z (dst);\r
1208 V = 0;\r
1209 SP = (SP + 2) & 0177777;\r
1210 if (update_MM) MMR1 = 026;\r
1211 if (dstreg) {\r
1212 if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst;\r
1213 else R[dstspec] = dst;\r
1214 }\r
1215 else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_is (pm));\r
1216 }\r
1217 else setTRAP (TRAP_ILL);\r
1218 break;\r
1219\r
1220 case 067: /* SXT */\r
1221 if (CPUT (HAS_SXS)) {\r
1222 dst = N? 0177777: 0;\r
1223 Z = N ^ 1;\r
1224 V = 0;\r
1225 if (dstreg) R[dstspec] = dst;\r
1226 else WriteW (dst, GeteaW (dstspec));\r
1227 }\r
1228 else setTRAP (TRAP_ILL);\r
1229 break;\r
1230\r
1231 case 070: /* CSM */\r
1232 if (CPUT (HAS_CSM) && (MMR3 & MMR3_CSM) || (cm != MD_KER)) {\r
1233 dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1234 PSW = get_PSW () & ~PSW_CC; /* PSW, cc = 0 */\r
1235 STACKFILE[cm] = SP;\r
1236 WriteW (PSW, ((SP - 2) & 0177777) | calc_ds (MD_SUP));\r
1237 WriteW (PC, ((SP - 4) & 0177777) | calc_ds (MD_SUP));\r
1238 WriteW (dst, ((SP - 6) & 0177777) | calc_ds (MD_SUP));\r
1239 SP = (SP - 6) & 0177777;\r
1240 pm = cm;\r
1241 cm = MD_SUP;\r
1242 tbit = 0;\r
1243 isenable = calc_is (cm);\r
1244 dsenable = calc_ds (cm);\r
1245 PC = ReadW (010 | isenable);\r
1246 }\r
1247 else setTRAP (TRAP_ILL);\r
1248 break;\r
1249\r
1250 case 072: /* TSTSET */\r
1251 if (CPUT (HAS_TSWLK) && !dstreg) {\r
1252 dst = ReadMW (GeteaW (dstspec));\r
1253 N = GET_SIGN_W (dst);\r
1254 Z = GET_Z (dst);\r
1255 V = 0;\r
1256 C = (dst & 1);\r
1257 R[0] = dst; /* R[0] <- dst */\r
1258 PWriteW (R[0] | 1, last_pa); /* dst <- R[0] | 1 */\r
1259 }\r
1260 else setTRAP (TRAP_ILL);\r
1261 break;\r
1262\r
1263 case 073: /* WRTLCK */\r
1264 if (CPUT (HAS_TSWLK) && !dstreg) {\r
1265 N = GET_SIGN_W (R[0]);\r
1266 Z = GET_Z (R[0]);\r
1267 V = 0;\r
1268 WriteW (R[0], GeteaW (dstspec));\r
1269 }\r
1270 else setTRAP (TRAP_ILL);\r
1271 break;\r
1272\r
1273 default:\r
1274 setTRAP (TRAP_ILL);\r
1275 break;\r
1276 } /* end switch SOPs */\r
1277 break; /* end case 000 */\r
1278\r
1279/* Opcodes 01 - 06: double operand word instructions\r
1280\r
1281 J-11 (and F-11) optimize away register source operand decoding.\r
1282 As a result, dop R,+/-(R) use the modified version of R as source.\r
1283 Most (but not all) other PDP-11's fetch the source operand before\r
1284 any destination operand decoding.\r
1285\r
1286 Add: v = [sign (src) = sign (src2)] and [sign (src) != sign (result)]\r
1287 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]\r
1288*/\r
1289\r
1290 case 001: /* MOV */\r
1291 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1292 ea = GeteaW (dstspec);\r
1293 dst = R[srcspec];\r
1294 }\r
1295 else {\r
1296 dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));\r
1297 if (!dstreg) ea = GeteaW (dstspec);\r
1298 }\r
1299 N = GET_SIGN_W (dst);\r
1300 Z = GET_Z (dst);\r
1301 V = 0;\r
1302 if (dstreg) R[dstspec] = dst;\r
1303 else WriteW (dst, ea);\r
1304 break;\r
1305\r
1306 case 002: /* CMP */\r
1307 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1308 src2 = ReadW (GeteaW (dstspec));\r
1309 src = R[srcspec];\r
1310 }\r
1311 else {\r
1312 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));\r
1313 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1314 }\r
1315 dst = (src - src2) & 0177777;\r
1316 N = GET_SIGN_W (dst);\r
1317 Z = GET_Z (dst);\r
1318 V = GET_SIGN_W ((src ^ src2) & (~src2 ^ dst));\r
1319 C = (src < src2);\r
1320 break;\r
1321\r
1322 case 003: /* BIT */\r
1323 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1324 src2 = ReadW (GeteaW (dstspec));\r
1325 src = R[srcspec];\r
1326 }\r
1327 else {\r
1328 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));\r
1329 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1330 }\r
1331 dst = src2 & src;\r
1332 N = GET_SIGN_W (dst);\r
1333 Z = GET_Z (dst);\r
1334 V = 0;\r
1335 break;\r
1336\r
1337 case 004: /* BIC */\r
1338 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1339 src2 = ReadMW (GeteaW (dstspec));\r
1340 src = R[srcspec];\r
1341 }\r
1342 else {\r
1343 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));\r
1344 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1345 }\r
1346 dst = src2 & ~src;\r
1347 N = GET_SIGN_W (dst);\r
1348 Z = GET_Z (dst);\r
1349 V = 0;\r
1350 if (dstreg) R[dstspec] = dst;\r
1351 else PWriteW (dst, last_pa);\r
1352 break;\r
1353\r
1354 case 005: /* BIS */\r
1355 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1356 src2 = ReadMW (GeteaW (dstspec));\r
1357 src = R[srcspec];\r
1358 }\r
1359 else {\r
1360 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));\r
1361 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1362 }\r
1363 dst = src2 | src;\r
1364 N = GET_SIGN_W (dst);\r
1365 Z = GET_Z (dst);\r
1366 V = 0;\r
1367 if (dstreg) R[dstspec] = dst;\r
1368 else PWriteW (dst, last_pa);\r
1369 break;\r
1370\r
1371 case 006: /* ADD */\r
1372 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1373 src2 = ReadMW (GeteaW (dstspec));\r
1374 src = R[srcspec];\r
1375 }\r
1376 else {\r
1377 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));\r
1378 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1379 }\r
1380 dst = (src2 + src) & 0177777;\r
1381 N = GET_SIGN_W (dst);\r
1382 Z = GET_Z (dst);\r
1383 V = GET_SIGN_W ((~src ^ src2) & (src ^ dst));\r
1384 C = (dst < src);\r
1385 if (dstreg) R[dstspec] = dst;\r
1386 else PWriteW (dst, last_pa);\r
1387 break;\r
1388\r
1389/* Opcode 07: EIS, FIS, CIS\r
1390\r
1391 Notes:\r
1392 - The code assumes that the host int length is at least 32 bits.\r
1393 - MUL carry: C is set if the (signed) result doesn't fit in 16 bits.\r
1394 - Divide has three error cases:\r
1395 1. Divide by zero.\r
1396 2. Divide largest negative number by -1.\r
1397 3. (Signed) quotient doesn't fit in 16 bits.\r
1398 Cases 1 and 2 must be tested in advance, to avoid C runtime errors.\r
1399 - ASHx left: overflow if the bits shifted out do not equal the sign\r
1400 of the result (convert shift out to 1/0, xor against sign).\r
1401 - ASHx right: if right shift sign extends, then the shift and\r
1402 conditional or of shifted -1 is redundant. If right shift zero\r
1403 extends, then the shift and conditional or does sign extension.\r
1404*/\r
1405\r
1406 case 007:\r
1407 srcspec = srcspec & 07;\r
1408 switch ((IR >> 9) & 07) { /* decode IR<11:9> */\r
1409\r
1410 case 0: /* MUL */\r
1411 if (!CPUO (OPT_EIS)) {\r
1412 setTRAP (TRAP_ILL);\r
1413 break;\r
1414 }\r
1415 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1416 src = R[srcspec];\r
1417 if (GET_SIGN_W (src2)) src2 = src2 | ~077777;\r
1418 if (GET_SIGN_W (src)) src = src | ~077777;\r
1419 dst = src * src2;\r
1420 R[srcspec] = (dst >> 16) & 0177777;\r
1421 R[srcspec | 1] = dst & 0177777;\r
1422 N = (dst < 0);\r
1423 Z = GET_Z (dst);\r
1424 V = 0;\r
1425 C = ((dst > 077777) || (dst < -0100000));\r
1426 break;\r
1427\r
1428 case 1: /* DIV */\r
1429 if (!CPUO (OPT_EIS)) {\r
1430 setTRAP (TRAP_ILL);\r
1431 break;\r
1432 }\r
1433 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1434 src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1];\r
1435 if (src2 == 0) {\r
1436 N = 0; /* J11,11/70 compat */\r
1437 Z = V = C = 1; /* N = 0, Z = 1 */\r
1438 break;\r
1439 }\r
1440 if ((src == 020000000000) && (src2 == 0177777)) {\r
1441 V = 1; /* J11,11/70 compat */\r
1442 N = Z = C = 0; /* N = Z = 0 */\r
1443 break;\r
1444 }\r
1445 if (GET_SIGN_W (src2)) src2 = src2 | ~077777;\r
1446 if (GET_SIGN_W (R[srcspec])) src = src | ~017777777777;\r
1447 dst = src / src2;\r
1448 N = (dst < 0); /* N set on 32b result */\r
1449 if ((dst > 077777) || (dst < -0100000)) {\r
1450 V = 1; /* J11,11/70 compat */\r
1451 Z = C = 0; /* Z = C = 0 */\r
1452 break;\r
1453 }\r
1454 R[srcspec] = dst & 0177777;\r
1455 R[srcspec | 1] = (src - (src2 * dst)) & 0177777;\r
1456 Z = GET_Z (dst);\r
1457 V = C = 0;\r
1458 break;\r
1459\r
1460 case 2: /* ASH */\r
1461 if (!CPUO (OPT_EIS)) {\r
1462 setTRAP (TRAP_ILL);\r
1463 break;\r
1464 }\r
1465 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1466 src2 = src2 & 077;\r
1467 sign = GET_SIGN_W (R[srcspec]);\r
1468 src = sign? R[srcspec] | ~077777: R[srcspec];\r
1469 if (src2 == 0) { /* [0] */\r
1470 dst = src;\r
1471 V = C = 0;\r
1472 }\r
1473 else if (src2 <= 15) { /* [1,15] */\r
1474 dst = src << src2;\r
1475 i = (src >> (16 - src2)) & 0177777;\r
1476 V = (i != ((dst & 0100000)? 0177777: 0));\r
1477 C = (i & 1);\r
1478 }\r
1479 else if (src2 <= 31) { /* [16,31] */\r
1480 dst = 0;\r
1481 V = (src != 0);\r
1482 C = (src << (src2 - 16)) & 1;\r
1483 }\r
1484 else if (src2 == 32) { /* [32] = -32 */\r
1485 dst = -sign;\r
1486 V = 0;\r
1487 C = sign;\r
1488 }\r
1489 else { /* [33,63] = -31,-1 */\r
1490 dst = (src >> (64 - src2)) | (-sign << (src2 - 32));\r
1491 V = 0;\r
1492 C = ((src >> (63 - src2)) & 1);\r
1493 }\r
1494 dst = R[srcspec] = dst & 0177777;\r
1495 N = GET_SIGN_W (dst);\r
1496 Z = GET_Z (dst);\r
1497 break;\r
1498\r
1499 case 3: /* ASHC */\r
1500 if (!CPUO (OPT_EIS)) {\r
1501 setTRAP (TRAP_ILL);\r
1502 break;\r
1503 }\r
1504 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));\r
1505 src2 = src2 & 077;\r
1506 sign = GET_SIGN_W (R[srcspec]);\r
1507 src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1];\r
1508 if (src2 == 0) { /* [0] */\r
1509 dst = src;\r
1510 V = C = 0;\r
1511 }\r
1512 else if (src2 <= 31) { /* [1,31] */\r
1513 dst = ((uint32) src) << src2;\r
1514 i = (src >> (32 - src2)) | (-sign << src2);\r
1515 V = (i != ((dst & 020000000000)? -1: 0));\r
1516 C = (i & 1);\r
1517 }\r
1518 else if (src2 == 32) { /* [32] = -32 */\r
1519 dst = -sign;\r
1520 V = 0;\r
1521 C = sign;\r
1522 }\r
1523 else { /* [33,63] = -31,-1 */\r
1524 dst = (src >> (64 - src2)) | (-sign << (src2 - 32));\r
1525 V = 0;\r
1526 C = ((src >> (63 - src2)) & 1);\r
1527 }\r
1528 i = R[srcspec] = (dst >> 16) & 0177777;\r
1529 dst = R[srcspec | 1] = dst & 0177777;\r
1530 N = GET_SIGN_W (i);\r
1531 Z = GET_Z (dst | i);\r
1532 break;\r
1533\r
1534 case 4: /* XOR */\r
1535 if (CPUT (HAS_SXS)) {\r
1536 if (CPUT (IS_SDSD) && !dstreg) { /* R,not R */\r
1537 src2 = ReadMW (GeteaW (dstspec));\r
1538 src = R[srcspec];\r
1539 }\r
1540 else {\r
1541 src = R[srcspec];\r
1542 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1543 }\r
1544 dst = src ^ src2;\r
1545 N = GET_SIGN_W (dst);\r
1546 Z = GET_Z (dst);\r
1547 V = 0;\r
1548 if (dstreg) R[dstspec] = dst;\r
1549 else PWriteW (dst, last_pa);\r
1550 }\r
1551 else setTRAP (TRAP_ILL);\r
1552 break;\r
1553\r
1554 case 5: /* FIS */\r
1555 if (CPUO (OPT_FIS)) fis11 (IR);\r
1556 else setTRAP (TRAP_ILL);\r
1557 break;\r
1558\r
1559 case 6: /* CIS */\r
1560 if (CPUT (CPUT_60) && (cm == MD_KER) && /* 11/60 MED? */\r
1561 (IR == 076600)) {\r
1562 ReadE (PC | isenable); /* read immediate */\r
1563 PC = (PC + 2) & 0177777;\r
1564 }\r
1565 else if (CPUO (OPT_CIS)) /* CIS option? */\r
1566 reason = cis11 (IR);\r
1567 else setTRAP (TRAP_ILL);\r
1568 break;\r
1569\r
1570 case 7: /* SOB */\r
1571 if (CPUT (HAS_SXS)) {\r
1572 R[srcspec] = (R[srcspec] - 1) & 0177777;\r
1573 if (R[srcspec]) {\r
1574 JMP_PC ((PC - dstspec - dstspec) & 0177777);\r
1575 }\r
1576 }\r
1577 else setTRAP (TRAP_ILL);\r
1578 break;\r
1579 } /* end switch EIS */\r
1580 break; /* end case 007 */\r
1581\r
1582/* Opcode 10: branches, traps, SOPs */\r
1583\r
1584 case 010:\r
1585 switch ((IR >> 6) & 077) { /* decode IR<11:6> */\r
1586\r
1587 case 000: case 001: /* BPL */\r
1588 if (N == 0) { BRANCH_F (IR); } \r
1589 break;\r
1590\r
1591 case 002: case 003: /* BPL */\r
1592 if (N == 0) { BRANCH_B (IR); }\r
1593 break;\r
1594\r
1595 case 004: case 005: /* BMI */\r
1596 if (N) { BRANCH_F (IR); } \r
1597 break;\r
1598\r
1599 case 006: case 007: /* BMI */\r
1600 if (N) { BRANCH_B (IR); }\r
1601 break;\r
1602\r
1603 case 010: case 011: /* BHI */\r
1604 if ((C | Z) == 0) { BRANCH_F (IR); } \r
1605 break;\r
1606\r
1607 case 012: case 013: /* BHI */\r
1608 if ((C | Z) == 0) { BRANCH_B (IR); }\r
1609 break;\r
1610\r
1611 case 014: case 015: /* BLOS */\r
1612 if (C | Z) { BRANCH_F (IR); } \r
1613 break;\r
1614\r
1615 case 016: case 017: /* BLOS */\r
1616 if (C | Z) { BRANCH_B (IR); }\r
1617 break;\r
1618\r
1619 case 020: case 021: /* BVC */\r
1620 if (V == 0) { BRANCH_F (IR); } \r
1621 break;\r
1622\r
1623 case 022: case 023: /* BVC */\r
1624 if (V == 0) { BRANCH_B (IR); }\r
1625 break;\r
1626\r
1627 case 024: case 025: /* BVS */\r
1628 if (V) { BRANCH_F (IR); } \r
1629 break;\r
1630\r
1631 case 026: case 027: /* BVS */\r
1632 if (V) { BRANCH_B (IR); }\r
1633 break;\r
1634\r
1635 case 030: case 031: /* BCC */\r
1636 if (C == 0) { BRANCH_F (IR); } \r
1637 break;\r
1638\r
1639 case 032: case 033: /* BCC */\r
1640 if (C == 0) { BRANCH_B (IR); }\r
1641 break;\r
1642\r
1643 case 034: case 035: /* BCS */\r
1644 if (C) { BRANCH_F (IR); } \r
1645 break;\r
1646\r
1647 case 036: case 037: /* BCS */\r
1648 if (C) { BRANCH_B (IR); }\r
1649 break;\r
1650\r
1651 case 040: case 041: case 042: case 043: /* EMT */\r
1652 setTRAP (TRAP_EMT);\r
1653 break;\r
1654\r
1655 case 044: case 045: case 046: case 047: /* TRAP */\r
1656 setTRAP (TRAP_TRAP);\r
1657 break;\r
1658\r
1659 case 050: /* CLRB */\r
1660 N = V = C = 0;\r
1661 Z = 1;\r
1662 if (dstreg) R[dstspec] = R[dstspec] & 0177400;\r
1663 else WriteB (0, GeteaB (dstspec));\r
1664 break;\r
1665\r
1666 case 051: /* COMB */\r
1667 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1668 dst = (dst ^ 0377) & 0377;\r
1669 N = GET_SIGN_B (dst);\r
1670 Z = GET_Z (dst);\r
1671 V = 0;\r
1672 C = 1;\r
1673 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1674 else PWriteB (dst, last_pa);\r
1675 break;\r
1676\r
1677 case 052: /* INCB */\r
1678 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1679 dst = (dst + 1) & 0377;\r
1680 N = GET_SIGN_B (dst);\r
1681 Z = GET_Z (dst);\r
1682 V = (dst == 0200);\r
1683 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1684 else PWriteB (dst, last_pa);\r
1685 break;\r
1686\r
1687 case 053: /* DECB */\r
1688 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1689 dst = (dst - 1) & 0377;\r
1690 N = GET_SIGN_B (dst);\r
1691 Z = GET_Z (dst);\r
1692 V = (dst == 0177);\r
1693 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1694 else PWriteB (dst, last_pa);\r
1695 break;\r
1696\r
1697 case 054: /* NEGB */\r
1698 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1699 dst = (-dst) & 0377;\r
1700 N = GET_SIGN_B (dst);\r
1701 Z = GET_Z (dst);\r
1702 V = (dst == 0200);\r
1703 C = (Z ^ 1);\r
1704 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1705 else PWriteB (dst, last_pa);\r
1706 break;\r
1707\r
1708 case 055: /* ADCB */\r
1709 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1710 dst = (dst + C) & 0377;\r
1711 N = GET_SIGN_B (dst);\r
1712 Z = GET_Z (dst);\r
1713 V = (C && (dst == 0200));\r
1714 C = C & Z;\r
1715 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1716 else PWriteB (dst, last_pa);\r
1717 break;\r
1718\r
1719 case 056: /* SBCB */\r
1720 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1721 dst = (dst - C) & 0377;\r
1722 N = GET_SIGN_B (dst);\r
1723 Z = GET_Z (dst);\r
1724 V = (C && (dst == 0177));\r
1725 C = (C && (dst == 0377));\r
1726 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1727 else PWriteB (dst, last_pa);\r
1728 break;\r
1729\r
1730 case 057: /* TSTB */\r
1731 dst = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec));\r
1732 N = GET_SIGN_B (dst);\r
1733 Z = GET_Z (dst);\r
1734 V = C = 0;\r
1735 break;\r
1736\r
1737 case 060: /* RORB */\r
1738 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1739 dst = ((src & 0377) >> 1) | (C << 7);\r
1740 N = GET_SIGN_B (dst);\r
1741 Z = GET_Z (dst);\r
1742 C = (src & 1);\r
1743 V = N ^ C;\r
1744 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1745 else PWriteB (dst, last_pa);\r
1746 break;\r
1747\r
1748 case 061: /* ROLB */\r
1749 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1750 dst = ((src << 1) | C) & 0377;\r
1751 N = GET_SIGN_B (dst);\r
1752 Z = GET_Z (dst);\r
1753 C = GET_SIGN_B (src & 0377);\r
1754 V = N ^ C;\r
1755 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1756 else PWriteB (dst, last_pa);\r
1757 break;\r
1758\r
1759 case 062: /* ASRB */\r
1760 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1761 dst = ((src & 0377) >> 1) | (src & 0200);\r
1762 N = GET_SIGN_B (dst);\r
1763 Z = GET_Z (dst);\r
1764 C = (src & 1);\r
1765 V = N ^ C;\r
1766 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1767 else PWriteB (dst, last_pa);\r
1768 break;\r
1769\r
1770 case 063: /* ASLB */\r
1771 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1772 dst = (src << 1) & 0377;\r
1773 N = GET_SIGN_B (dst);\r
1774 Z = GET_Z (dst);\r
1775 C = GET_SIGN_B (src & 0377);\r
1776 V = N ^ C;\r
1777 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1778 else PWriteB (dst, last_pa);\r
1779 break;\r
1780/* Notes:\r
1781 - MTPS cannot alter the T bit\r
1782 - MxPD must mask GeteaW returned address, dspace is from cm not pm\r
1783 - MxPD must set MMR1 for SP recovery in case of fault\r
1784*/\r
1785\r
1786 case 064: /* MTPS */\r
1787 if (CPUT (HAS_MXPS)) {\r
1788 dst = dstreg? R[dstspec]: ReadB (GeteaB (dstspec));\r
1789 if (cm == MD_KER) {\r
1790 ipl = (dst >> PSW_V_IPL) & 07;\r
1791 trap_req = calc_ints (ipl, trap_req);\r
1792 }\r
1793 N = (dst >> PSW_V_N) & 01;\r
1794 Z = (dst >> PSW_V_Z) & 01;\r
1795 V = (dst >> PSW_V_V) & 01;\r
1796 C = (dst >> PSW_V_C) & 01;\r
1797 }\r
1798 else setTRAP (TRAP_ILL);\r
1799 break;\r
1800\r
1801 case 065: /* MFPD */\r
1802 if (CPUT (HAS_MXPY)) {\r
1803 if (dstreg) {\r
1804 if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm];\r
1805 else dst = R[dstspec];\r
1806 }\r
1807 else dst = ReadW ((GeteaW (dstspec) & 0177777) | calc_ds (pm));\r
1808 N = GET_SIGN_W (dst);\r
1809 Z = GET_Z (dst);\r
1810 V = 0;\r
1811 SP = (SP - 2) & 0177777;\r
1812 if (update_MM) MMR1 = calc_MMR1 (0366);\r
1813 WriteW (dst, SP | dsenable);\r
1814 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))\r
1815 set_stack_trap (SP);\r
1816 }\r
1817 else setTRAP (TRAP_ILL);\r
1818 break;\r
1819\r
1820 case 066: /* MTPD */\r
1821 if (CPUT (HAS_MXPY)) {\r
1822 dst = ReadW (SP | dsenable);\r
1823 N = GET_SIGN_W (dst);\r
1824 Z = GET_Z (dst);\r
1825 V = 0;\r
1826 SP = (SP + 2) & 0177777;\r
1827 if (update_MM) MMR1 = 026;\r
1828 if (dstreg) {\r
1829 if ((dstspec == 6) && (cm != pm)) STACKFILE[pm] = dst;\r
1830 else R[dstspec] = dst;\r
1831 }\r
1832 else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_ds (pm));\r
1833 }\r
1834 else setTRAP (TRAP_ILL);\r
1835 break;\r
1836\r
1837 case 067: /* MFPS */\r
1838 if (CPUT (HAS_MXPS)) {\r
1839 dst = get_PSW () & 0377;\r
1840 N = GET_SIGN_B (dst);\r
1841 Z = GET_Z (dst);\r
1842 V = 0;\r
1843 if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst;\r
1844 else WriteB (dst, GeteaB (dstspec));\r
1845 }\r
1846 else setTRAP (TRAP_ILL);\r
1847 break;\r
1848\r
1849 default:\r
1850 setTRAP (TRAP_ILL);\r
1851 break;\r
1852 } /* end switch SOPs */\r
1853 break; /* end case 010 */\r
1854\r
1855/* Opcodes 11 - 16: double operand byte instructions\r
1856\r
1857 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]\r
1858 Sub: v = [sign (src) != sign (src2)] and [sign (src) = sign (result)]\r
1859*/\r
1860\r
1861 case 011: /* MOVB */\r
1862 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1863 ea = GeteaB (dstspec);\r
1864 dst = R[srcspec] & 0377;\r
1865 }\r
1866 else {\r
1867 dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));\r
1868 if (!dstreg) ea = GeteaB (dstspec);\r
1869 }\r
1870 N = GET_SIGN_B (dst);\r
1871 Z = GET_Z (dst);\r
1872 V = 0;\r
1873 if (dstreg) R[dstspec] = (dst & 0200)? 0177400 | dst: dst;\r
1874 else WriteB (dst, ea);\r
1875 break;\r
1876\r
1877 case 012: /* CMPB */\r
1878 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1879 src2 = ReadB (GeteaB (dstspec));\r
1880 src = R[srcspec] & 0377;\r
1881 }\r
1882 else {\r
1883 src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));\r
1884 src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec));\r
1885 }\r
1886 dst = (src - src2) & 0377;\r
1887 N = GET_SIGN_B (dst);\r
1888 Z = GET_Z (dst);\r
1889 V = GET_SIGN_B ((src ^ src2) & (~src2 ^ dst));\r
1890 C = (src < src2);\r
1891 break;\r
1892\r
1893 case 013: /* BITB */\r
1894 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1895 src2 = ReadB (GeteaB (dstspec));\r
1896 src = R[srcspec] & 0377;\r
1897 }\r
1898 else {\r
1899 src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));\r
1900 src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec));\r
1901 }\r
1902 dst = (src2 & src) & 0377;\r
1903 N = GET_SIGN_B (dst);\r
1904 Z = GET_Z (dst);\r
1905 V = 0;\r
1906 break;\r
1907\r
1908 case 014: /* BICB */\r
1909 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1910 src2 = ReadMB (GeteaB (dstspec));\r
1911 src = R[srcspec];\r
1912 }\r
1913 else {\r
1914 src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));\r
1915 src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1916 }\r
1917 dst = (src2 & ~src) & 0377;\r
1918 N = GET_SIGN_B (dst);\r
1919 Z = GET_Z (dst);\r
1920 V = 0;\r
1921 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1922 else PWriteB (dst, last_pa);\r
1923 break;\r
1924\r
1925 case 015: /* BISB */\r
1926 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1927 src2 = ReadMB (GeteaB (dstspec));\r
1928 src = R[srcspec];\r
1929 }\r
1930 else {\r
1931 src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));\r
1932 src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));\r
1933 }\r
1934 dst = (src2 | src) & 0377;\r
1935 N = GET_SIGN_B (dst);\r
1936 Z = GET_Z (dst);\r
1937 V = 0;\r
1938 if (dstreg) R[dstspec] = (R[dstspec] & 0177400) | dst;\r
1939 else PWriteB (dst, last_pa);\r
1940 break;\r
1941\r
1942 case 016: /* SUB */\r
1943 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */\r
1944 src2 = ReadMW (GeteaW (dstspec));\r
1945 src = R[srcspec];\r
1946 }\r
1947 else {\r
1948 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));\r
1949 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));\r
1950 }\r
1951 dst = (src2 - src) & 0177777;\r
1952 N = GET_SIGN_W (dst);\r
1953 Z = GET_Z (dst);\r
1954 V = GET_SIGN_W ((src ^ src2) & (~src ^ dst));\r
1955 C = (src2 < src);\r
1956 if (dstreg) R[dstspec] = dst;\r
1957 else PWriteW (dst, last_pa);\r
1958 break;\r
1959\r
1960/* Opcode 17: floating point */\r
1961\r
1962 case 017:\r
1963 if (CPUO (OPT_FPP)) fp11 (IR); /* call fpp */\r
1964 else setTRAP (TRAP_ILL);\r
1965 break; /* end case 017 */\r
1966 } /* end switch op */\r
1967 } /* end main loop */\r
1968\r
1969/* Simulation halted */\r
1970\r
1971PSW = get_PSW ();\r
1972for (i = 0; i < 6; i++) REGFILE[i][rs] = R[i];\r
1973STACKFILE[cm] = SP;\r
1974saved_PC = PC & 0177777;\r
1975pcq_r->qptr = pcq_p; /* update pc q ptr */\r
1976set_r_display (rs, cm);\r
1977return reason;\r
1978}\r
1979\r
1980/* Effective address calculations\r
1981\r
1982 Inputs:\r
1983 spec = specifier <5:0>\r
1984 Outputs:\r
1985 ea = effective address\r
1986 <15:0> = virtual address\r
1987 <16> = instruction/data data space\r
1988 <18:17> = mode\r
1989\r
1990 Data space calculation: the PDP-11 features both instruction and data\r
1991 spaces. Instruction space contains the instruction and any sequential\r
1992 add ons (eg, immediates, absolute addresses). Data space contains all\r
1993 data operands and indirect addresses. If data space is enabled, then\r
1994 memory references are directed according to these rules:\r
1995\r
1996 Mode Index ref Indirect ref Direct ref\r
1997 10..16 na na data\r
1998 17 na na instruction\r
1999 20..26 na na data\r
2000 27 na na instruction\r
2001 30..36 na data data\r
2002 37 na instruction (absolute) data\r
2003 40..46 na na data\r
2004 47 na na instruction\r
2005 50..56 na data data\r
2006 57 na instruction data\r
2007 60..67 instruction na data\r
2008 70..77 instruction data data\r
2009\r
2010 According to the PDP-11 Architecture Handbook, MMR1 records all\r
2011 autoincrement and autodecrement operations, including those which\r
2012 explicitly reference the PC. For the J-11, this is only true for\r
2013 autodecrement operands, autodecrement deferred operands, and\r
2014 autoincrement destination operands that involve a write to memory.\r
2015 The simulator follows the Handbook, for simplicity.\r
2016\r
2017 Notes:\r
2018\r
2019 - dsenable will direct a reference to data space if data space is enabled\r
2020 - ds will direct a reference to data space if data space is enabled AND if\r
2021 the specifier register is not PC; this is used for 17, 27, 37, 47, 57\r
2022 - Modes 2x, 3x, 4x, and 5x must update MMR1 if updating enabled\r
2023 - Modes 46 and 56 must check for stack overflow if kernel mode\r
2024*/\r
2025\r
2026/* Effective address calculation for words */\r
2027\r
2028int32 GeteaW (int32 spec)\r
2029{\r
2030int32 adr, reg, ds;\r
2031\r
2032reg = spec & 07; /* register number */\r
2033ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */\r
2034switch (spec >> 3) { /* decode spec<5:3> */\r
2035\r
2036 default: /* can't get here */\r
2037 case 1: /* (R) */\r
2038 return (R[reg] | ds);\r
2039\r
2040 case 2: /* (R)+ */\r
2041 R[reg] = ((adr = R[reg]) + 2) & 0177777;\r
2042 if (update_MM) MMR1 = calc_MMR1 (020 | reg);\r
2043 return (adr | ds);\r
2044\r
2045 case 3: /* @(R)+ */\r
2046 R[reg] = ((adr = R[reg]) + 2) & 0177777;\r
2047 if (update_MM) MMR1 = calc_MMR1 (020 | reg);\r
2048 adr = ReadW (adr | ds);\r
2049 return (adr | dsenable);\r
2050\r
2051 case 4: /* -(R) */\r
2052 adr = R[reg] = (R[reg] - 2) & 0177777;\r
2053 if (update_MM) MMR1 = calc_MMR1 (0360 | reg);\r
2054 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))\r
2055 set_stack_trap (adr);\r
2056 return (adr | ds);\r
2057\r
2058 case 5: /* @-(R) */\r
2059 adr = R[reg] = (R[reg] - 2) & 0177777;\r
2060 if (update_MM) MMR1 = calc_MMR1 (0360 | reg);\r
2061 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))\r
2062 set_stack_trap (adr);\r
2063 adr = ReadW (adr | ds);\r
2064 return (adr | dsenable);\r
2065\r
2066 case 6: /* d(r) */\r
2067 adr = ReadW (PC | isenable);\r
2068 PC = (PC + 2) & 0177777;\r
2069 return (((R[reg] + adr) & 0177777) | dsenable);\r
2070\r
2071 case 7: /* @d(R) */\r
2072 adr = ReadW (PC | isenable);\r
2073 PC = (PC + 2) & 0177777;\r
2074 adr = ReadW (((R[reg] + adr) & 0177777) | dsenable);\r
2075 return (adr | dsenable);\r
2076 } /* end switch */\r
2077}\r
2078\r
2079/* Effective address calculation for bytes */\r
2080\r
2081int32 GeteaB (int32 spec)\r
2082{\r
2083int32 adr, reg, ds, delta;\r
2084\r
2085reg = spec & 07; /* reg number */\r
2086ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */\r
2087switch (spec >> 3) { /* decode spec<5:3> */\r
2088\r
2089 default: /* can't get here */\r
2090 case 1: /* (R) */\r
2091 return (R[reg] | ds);\r
2092\r
2093 case 2: /* (R)+ */\r
2094 delta = 1 + (reg >= 6); /* 2 if R6, PC */\r
2095 R[reg] = ((adr = R[reg]) + delta) & 0177777;\r
2096 if (update_MM) MMR1 = calc_MMR1 ((delta << 3) | reg);\r
2097 return (adr | ds);\r
2098\r
2099 case 3: /* @(R)+ */\r
2100 R[reg] = ((adr = R[reg]) + 2) & 0177777;\r
2101 if (update_MM) MMR1 = calc_MMR1 (020 | reg);\r
2102 adr = ReadW (adr | ds);\r
2103 return (adr | dsenable);\r
2104\r
2105 case 4: /* -(R) */\r
2106 delta = 1 + (reg >= 6); /* 2 if R6, PC */\r
2107 adr = R[reg] = (R[reg] - delta) & 0177777;\r
2108 if (update_MM) MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg);\r
2109 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))\r
2110 set_stack_trap (adr);\r
2111 return (adr | ds);\r
2112\r
2113 case 5: /* @-(R) */\r
2114 adr = R[reg] = (R[reg] - 2) & 0177777;\r
2115 if (update_MM) MMR1 = calc_MMR1 (0360 | reg);\r
2116 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))\r
2117 set_stack_trap (adr);\r
2118 adr = ReadW (adr | ds);\r
2119 return (adr | dsenable);\r
2120\r
2121 case 6: /* d(r) */\r
2122 adr = ReadW (PC | isenable);\r
2123 PC = (PC + 2) & 0177777;\r
2124 return (((R[reg] + adr) & 0177777) | dsenable);\r
2125\r
2126 case 7: /* @d(R) */\r
2127 adr = ReadW (PC | isenable);\r
2128 PC = (PC + 2) & 0177777;\r
2129 adr = ReadW (((R[reg] + adr) & 0177777) | dsenable);\r
2130 return (adr | dsenable);\r
2131 } /* end switch */\r
2132}\r
2133\r
2134/* Read byte and word routines, read only and read-modify-write versions\r
2135\r
2136 Inputs:\r
2137 va = virtual address, <18:16> = mode, I/D space\r
2138 Outputs:\r
2139 data = data read from memory or I/O space\r
2140*/\r
2141\r
2142int32 ReadE (int32 va)\r
2143{\r
2144int32 pa, data;\r
2145\r
2146if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */\r
2147 setCPUERR (CPUE_ODD);\r
2148 ABORT (TRAP_ODD);\r
2149 }\r
2150pa = relocR (va); /* relocate */\r
2151if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */\r
2152if ((pa < IOPAGEBASE) || /* not I/O address */\r
2153 (CPUT (CPUT_J) && (pa >= IOBA_CPU))) { /* or J11 int reg? */\r
2154 setCPUERR (CPUE_NXM);\r
2155 ABORT (TRAP_NXM);\r
2156 }\r
2157if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */\r
2158 setCPUERR (CPUE_TMO);\r
2159 ABORT (TRAP_NXM);\r
2160 }\r
2161return data;\r
2162}\r
2163\r
2164int32 ReadW (int32 va)\r
2165{\r
2166int32 pa, data;\r
2167\r
2168if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */\r
2169 setCPUERR (CPUE_ODD);\r
2170 ABORT (TRAP_ODD);\r
2171 }\r
2172pa = relocR (va); /* relocate */\r
2173if (ADDR_IS_MEM (pa)) return (M[pa >> 1]); /* memory address? */\r
2174if (pa < IOPAGEBASE) { /* not I/O address? */\r
2175 setCPUERR (CPUE_NXM);\r
2176 ABORT (TRAP_NXM);\r
2177 }\r
2178if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */\r
2179 setCPUERR (CPUE_TMO);\r
2180 ABORT (TRAP_NXM);\r
2181 }\r
2182return data;\r
2183}\r
2184\r
2185int32 ReadB (int32 va)\r
2186{\r
2187int32 pa, data;\r
2188\r
2189pa = relocR (va); /* relocate */\r
2190if (ADDR_IS_MEM (pa)) return (va & 1? M[pa >> 1] >> 8: M[pa >> 1]) & 0377;\r
2191if (pa < IOPAGEBASE) { /* not I/O address? */\r
2192 setCPUERR (CPUE_NXM);\r
2193 ABORT (TRAP_NXM);\r
2194 }\r
2195if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */\r
2196 setCPUERR (CPUE_TMO);\r
2197 ABORT (TRAP_NXM);\r
2198 }\r
2199return ((va & 1)? data >> 8: data) & 0377;\r
2200}\r
2201\r
2202int32 ReadMW (int32 va)\r
2203{\r
2204int32 data;\r
2205\r
2206if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */\r
2207 setCPUERR (CPUE_ODD);\r
2208 ABORT (TRAP_ODD);\r
2209 }\r
2210last_pa = relocW (va); /* reloc, wrt chk */\r
2211if (ADDR_IS_MEM (last_pa)) return (M[last_pa >> 1]); /* memory address? */\r
2212if (last_pa < IOPAGEBASE) { /* not I/O address? */\r
2213 setCPUERR (CPUE_NXM);\r
2214 ABORT (TRAP_NXM);\r
2215 }\r
2216if (iopageR (&data, last_pa, READ) != SCPE_OK) { /* invalid I/O addr? */\r
2217 setCPUERR (CPUE_TMO);\r
2218 ABORT (TRAP_NXM);\r
2219 }\r
2220return data;\r
2221}\r
2222\r
2223int32 ReadMB (int32 va)\r
2224{\r
2225int32 data;\r
2226\r
2227last_pa = relocW (va); /* reloc, wrt chk */\r
2228if (ADDR_IS_MEM (last_pa))\r
2229 return (va & 1? M[last_pa >> 1] >> 8: M[last_pa >> 1]) & 0377;\r
2230if (last_pa < IOPAGEBASE) { /* not I/O address? */\r
2231 setCPUERR (CPUE_NXM);\r
2232 ABORT (TRAP_NXM);\r
2233 }\r
2234if (iopageR (&data, last_pa, READ) != SCPE_OK) { /* invalid I/O addr? */\r
2235 setCPUERR (CPUE_TMO);\r
2236 ABORT (TRAP_NXM);\r
2237 }\r
2238return ((va & 1)? data >> 8: data) & 0377;\r
2239}\r
2240\r
2241/* Write byte and word routines\r
2242\r
2243 Inputs:\r
2244 data = data to be written\r
2245 va = virtual address, <18:16> = mode, I/D space, or\r
2246 pa = physical address\r
2247 Outputs: none\r
2248*/\r
2249\r
2250void WriteW (int32 data, int32 va)\r
2251{\r
2252int32 pa;\r
2253\r
2254if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */\r
2255 setCPUERR (CPUE_ODD);\r
2256 ABORT (TRAP_ODD);\r
2257 }\r
2258pa = relocW (va); /* relocate */\r
2259if (ADDR_IS_MEM (pa)) { /* memory address? */\r
2260 M[pa >> 1] = data;\r
2261 return;\r
2262 }\r
2263if (pa < IOPAGEBASE) { /* not I/O address? */\r
2264 setCPUERR (CPUE_NXM);\r
2265 ABORT (TRAP_NXM);\r
2266 }\r
2267if (iopageW (data, pa, WRITE) != SCPE_OK) { /* invalid I/O addr? */\r
2268 setCPUERR (CPUE_TMO);\r
2269 ABORT (TRAP_NXM);\r
2270 }\r
2271return;\r
2272}\r
2273\r
2274void WriteB (int32 data, int32 va)\r
2275{\r
2276int32 pa;\r
2277\r
2278pa = relocW (va); /* relocate */\r
2279if (ADDR_IS_MEM (pa)) { /* memory address? */\r
2280 if (va & 1) M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8);\r
2281 else M[pa >> 1] = (M[pa >> 1] & ~0377) | data;\r
2282 return;\r
2283 } \r
2284if (pa < IOPAGEBASE) { /* not I/O address? */\r
2285 setCPUERR (CPUE_NXM);\r
2286 ABORT (TRAP_NXM);\r
2287 }\r
2288if (iopageW (data, pa, WRITEB) != SCPE_OK) { /* invalid I/O addr? */\r
2289 setCPUERR (CPUE_TMO);\r
2290 ABORT (TRAP_NXM);\r
2291 }\r
2292return;\r
2293}\r
2294\r
2295void PWriteW (int32 data, int32 pa)\r
2296{\r
2297if (ADDR_IS_MEM (pa)) { /* memory address? */\r
2298 M[pa >> 1] = data;\r
2299 return;\r
2300 }\r
2301if (pa < IOPAGEBASE) { /* not I/O address? */\r
2302 setCPUERR (CPUE_NXM);\r
2303 ABORT (TRAP_NXM);\r
2304 }\r
2305if (iopageW (data, pa, WRITE) != SCPE_OK) { /* invalid I/O addr? */\r
2306 setCPUERR (CPUE_TMO);\r
2307 ABORT (TRAP_NXM);\r
2308 }\r
2309return;\r
2310}\r
2311\r
2312void PWriteB (int32 data, int32 pa)\r
2313{\r
2314if (ADDR_IS_MEM (pa)) { /* memory address? */\r
2315 if (pa & 1) M[pa >> 1] = (M[pa >> 1] & 0377) | (data << 8);\r
2316 else M[pa >> 1] = (M[pa >> 1] & ~0377) | data;\r
2317 return;\r
2318 } \r
2319if (pa < IOPAGEBASE) { /* not I/O address? */\r
2320 setCPUERR (CPUE_NXM);\r
2321 ABORT (TRAP_NXM);\r
2322 }\r
2323if (iopageW (data, pa, WRITEB) != SCPE_OK) { /* invalid I/O addr? */\r
2324 setCPUERR (CPUE_TMO);\r
2325 ABORT (TRAP_NXM);\r
2326 }\r
2327return;\r
2328}\r
2329\r
2330/* Relocate virtual address, read access\r
2331\r
2332 Inputs:\r
2333 va = virtual address, <18:16> = mode, I/D space\r
2334 Outputs:\r
2335 pa = physical address\r
2336 On aborts, this routine aborts back to the top level simulator\r
2337 with an appropriate trap code.\r
2338\r
2339 Notes:\r
2340 - The 'normal' read codes (010, 110) are done in-line; all\r
2341 others in a subroutine\r
2342 - APRFILE[UNUSED] is all zeroes, forcing non-resident abort\r
2343 - Aborts must update MMR0<15:13,6:1> if updating is enabled\r
2344*/\r
2345\r
2346int32 relocR (int32 va)\r
2347{\r
2348int32 apridx, apr, pa;\r
2349\r
2350if (MMR0 & MMR0_MME) { /* if mmgt */\r
2351 apridx = (va >> VA_V_APF) & 077; /* index into APR */\r
2352 apr = APRFILE[apridx]; /* with va<18:13> */\r
2353 if ((apr & PDR_PRD) != 2) /* not 2, 6? */\r
2354 relocR_test (va, apridx); /* long test */\r
2355 if (PLF_test (va, apr)) /* pg lnt error? */\r
2356 reloc_abort (MMR0_PL, apridx);\r
2357 pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK;\r
2358 if ((MMR3 & MMR3_M22E) == 0) {\r
2359 pa = pa & 0777777;\r
2360 if (pa >= 0760000) pa = 017000000 | pa;\r
2361 }\r
2362 }\r
2363else {\r
2364 pa = va & 0177777; /* mmgt off */\r
2365 if (pa >= 0160000) pa = 017600000 | pa;\r
2366 }\r
2367return pa;\r
2368}\r
2369\r
2370/* Read relocation, access control field != read only or read/write\r
2371\r
2372 ACF value 11/45,11/70 all others\r
2373\r
2374 0 abort NR abort NR\r
2375 1 trap -\r
2376 2 ok ok\r
2377 3 abort NR -\r
2378 4 trap abort NR\r
2379 5 ok -\r
2380 6 ok ok\r
2381 7 abort NR -\r
2382*/\r
2383\r
2384void relocR_test (int32 va, int32 apridx)\r
2385{\r
2386int32 apr, err;\r
2387\r
2388err = 0; /* init status */\r
2389apr = APRFILE[apridx]; /* get APR */\r
2390switch (apr & PDR_ACF) { /* case on ACF */\r
2391\r
2392 case 1: case 4: /* trap read */\r
2393 if (CPUT (HAS_MMTR)) { /* traps implemented? */\r
2394 APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */\r
2395 if (MMR0 & MMR0_TENB) { /* traps enabled? */\r
2396 if (update_MM) MMR0 = /* update MMR0 */\r
2397 (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE);\r
2398 MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */\r
2399 setTRAP (TRAP_MME); /* set trap */\r
2400 }\r
2401 return; /* continue op */\r
2402 } /* not impl, abort NR */\r
2403 case 0: case 3: case 7: /* non-resident */\r
2404 err = MMR0_NR; /* set MMR0 */\r
2405 break; /* go test PLF, abort */\r
2406\r
2407 case 2: case 5: case 6: /* readable */\r
2408 return; /* continue */\r
2409 } /* end switch */\r
2410\r
2411if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */\r
2412reloc_abort (err, apridx);\r
2413return;\r
2414}\r
2415\r
2416t_bool PLF_test (int32 va, int32 apr)\r
2417{\r
2418int32 dbn = va & VA_BN; /* extr block num */\r
2419int32 plf = (apr & PDR_PLF) >> 2; /* extr page length */\r
2420\r
2421return ((apr & PDR_ED)? (dbn < plf): (dbn > plf)); /* pg lnt error? */\r
2422}\r
2423\r
2424void reloc_abort (int32 err, int32 apridx)\r
2425{\r
2426if (update_MM) MMR0 = /* update MMR0 */\r
2427 (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE);\r
2428APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */\r
2429MMR0 = MMR0 | err; /* set aborts */\r
2430ABORT (TRAP_MME); /* abort ref */\r
2431return;\r
2432}\r
2433\r
2434/* Relocate virtual address, write access\r
2435\r
2436 Inputs:\r
2437 va = virtual address, <18:16> = mode, I/D space\r
2438 Outputs:\r
2439 pa = physical address\r
2440 On aborts, this routine aborts back to the top level simulator\r
2441 with an appropriate trap code.\r
2442\r
2443 Notes:\r
2444 - The 'normal' write code (110) is done in-line; all others\r
2445 in a subroutine\r
2446 - APRFILE[UNUSED] is all zeroes, forcing non-resident abort\r
2447 - Aborts must update MMR0<15:13,6:1> if updating is enabled\r
2448*/\r
2449\r
2450int32 relocW (int32 va)\r
2451{\r
2452int32 apridx, apr, pa;\r
2453\r
2454if (MMR0 & MMR0_MME) { /* if mmgt */\r
2455 apridx = (va >> VA_V_APF) & 077; /* index into APR */\r
2456 apr = APRFILE[apridx]; /* with va<18:13> */\r
2457 if ((apr & PDR_ACF) != 6) /* not writeable? */\r
2458 relocW_test (va, apridx); /* long test */\r
2459 if (PLF_test (va, apr)) /* pg lnt error? */\r
2460 reloc_abort (MMR0_PL, apridx);\r
2461 APRFILE[apridx] = apr | PDR_W; /* set W */\r
2462 pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK;\r
2463 if ((MMR3 & MMR3_M22E) == 0) {\r
2464 pa = pa & 0777777;\r
2465 if (pa >= 0760000) pa = 017000000 | pa;\r
2466 }\r
2467 }\r
2468else {\r
2469 pa = va & 0177777; /* mmgt off */\r
2470 if (pa >= 0160000) pa = 017600000 | pa;\r
2471 }\r
2472return pa;\r
2473}\r
2474\r
2475/* Write relocation, access control field != read/write\r
2476\r
2477 ACF value 11/45,11/70 all others\r
2478\r
2479 0 abort NR abort NR\r
2480 1 abort RO -\r
2481 2 abort RO abort RO\r
2482 3 abort NR -\r
2483 4 trap abort NR\r
2484 5 trap -\r
2485 6 ok ok\r
2486 7 abort NR -\r
2487*/\r
2488\r
2489void relocW_test (int32 va, int32 apridx)\r
2490{\r
2491int32 apr, err;\r
2492\r
2493err = 0; /* init status */\r
2494apr = APRFILE[apridx]; /* get APR */\r
2495switch (apr & PDR_ACF) { /* case on ACF */\r
2496\r
2497 case 4: case 5: /* trap write */\r
2498 if (CPUT (HAS_MMTR)) { /* traps implemented? */\r
2499 APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */\r
2500 if (MMR0 & MMR0_TENB) { /* traps enabled? */\r
2501 if (update_MM) MMR0 = /* update MMR0 */\r
2502 (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE);\r
2503 MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */\r
2504 setTRAP (TRAP_MME); /* set trap */\r
2505 }\r
2506 return; /* continue op */\r
2507 } /* not impl, abort NR */\r
2508 case 0: case 3: case 7: /* non-resident */\r
2509 err = MMR0_NR; /* MMR0 status */\r
2510 break; /* go test PLF, abort */\r
2511\r
2512 case 1: case 2: /* read only */\r
2513 err = MMR0_RO; /* MMR0 status */\r
2514 break;\r
2515\r
2516 case 6: /* read/write */\r
2517 return; /* continue */\r
2518 } /* end switch */\r
2519if (PLF_test (va, apr)) err = err | MMR0_PL; /* pg lnt error? */\r
2520reloc_abort (err, apridx);\r
2521return;\r
2522}\r
2523\r
2524/* Relocate virtual address, console access\r
2525\r
2526 Inputs:\r
2527 va = virtual address\r
2528 sw = switches\r
2529 Outputs:\r
2530 pa = physical address\r
2531 On aborts, this routine returns MAXMEMSIZE\r
2532*/\r
2533\r
2534int32 relocC (int32 va, int32 sw)\r
2535{\r
2536int32 mode, dbn, plf, apridx, apr, pa;\r
2537\r
2538if (MMR0 & MMR0_MME) { /* if mmgt */\r
2539 if (sw & SWMASK ('K')) mode = MD_KER;\r
2540 else if (sw & SWMASK ('S')) mode = MD_SUP;\r
2541 else if (sw & SWMASK ('U')) mode = MD_USR;\r
2542 else if (sw & SWMASK ('P')) mode = (PSW >> PSW_V_PM) & 03;\r
2543 else mode = (PSW >> PSW_V_CM) & 03;\r
2544 va = va | ((sw & SWMASK ('D'))? calc_ds (mode): calc_is (mode));\r
2545 apridx = (va >> VA_V_APF) & 077; /* index into APR */\r
2546 apr = APRFILE[apridx]; /* with va<18:13> */\r
2547 dbn = va & VA_BN; /* extr block num */\r
2548 plf = (apr & PDR_PLF) >> 2; /* extr page length */\r
2549 if ((apr & PDR_PRD) == 0) return MAXMEMSIZE; /* not readable? */\r
2550 if ((apr & PDR_ED)? dbn < plf: dbn > plf) return MAXMEMSIZE;\r
2551 pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK;\r
2552 if ((MMR3 & MMR3_M22E) == 0) {\r
2553 pa = pa & 0777777;\r
2554 if (pa >= 0760000) pa = 017000000 | pa;\r
2555 }\r
2556 }\r
2557else {\r
2558 pa = va & 0177777; /* mmgt off */\r
2559 if (pa >= 0160000) pa = 017600000 | pa;\r
2560 }\r
2561return pa;\r
2562}\r
2563\r
2564/* Memory management registers\r
2565\r
2566 MMR0 17777572 read/write, certain bits unimplemented or read only\r
2567 MMR1 17777574 read only\r
2568 MMR2 17777576 read only\r
2569 MMR3 17777516 read/write, certain bits unimplemented\r
2570*/\r
2571\r
2572t_stat MMR012_rd (int32 *data, int32 pa, int32 access)\r
2573{\r
2574switch ((pa >> 1) & 3) { /* decode pa<2:1> */\r
2575\r
2576 case 0: /* SR */\r
2577 return SCPE_NXM;\r
2578\r
2579 case 1: /* MMR0 */\r
2580 *data = MMR0 & cpu_tab[cpu_model].mm0;\r
2581 break;\r
2582\r
2583 case 2: /* MMR1 */\r
2584 *data = MMR1;\r
2585 break;\r
2586\r
2587 case 3: /* MMR2 */\r
2588 *data = MMR2;\r
2589 break;\r
2590 } /* end switch pa */\r
2591\r
2592return SCPE_OK;\r
2593}\r
2594\r
2595t_stat MMR012_wr (int32 data, int32 pa, int32 access)\r
2596{\r
2597switch ((pa >> 1) & 3) { /* decode pa<2:1> */\r
2598\r
2599 case 0: /* DR */\r
2600 return SCPE_NXM;\r
2601\r
2602 case 1: /* MMR0 */\r
2603 if (access == WRITEB) data = (pa & 1)?\r
2604 (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data;\r
2605 data = data & cpu_tab[cpu_model].mm0;\r
2606 MMR0 = (MMR0 & ~MMR0_WR) | (data & MMR0_WR);\r
2607 return SCPE_OK;\r
2608\r
2609 default: /* MMR1, MMR2 */\r
2610 return SCPE_OK;\r
2611 } /* end switch pa */\r
2612}\r
2613\r
2614t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */\r
2615{\r
2616*data = MMR3 & cpu_tab[cpu_model].mm3;\r
2617return SCPE_OK;\r
2618}\r
2619\r
2620t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */\r
2621{\r
2622if (pa & 1) return SCPE_OK;\r
2623MMR3 = data & cpu_tab[cpu_model].mm3;\r
2624cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM);\r
2625dsenable = calc_ds (cm);\r
2626return SCPE_OK;\r
2627}\r
2628\r
2629/* PARs and PDRs. These are grouped in I/O space as follows:\r
2630\r
2631 17772200 - 17772276 supervisor block\r
2632 17772300 - 17772376 kernel block\r
2633 17777600 - 17777676 user block\r
2634\r
2635 Within each block, the subblocks are I PDR's, D PDR's, I PAR's, D PAR's\r
2636\r
2637 Thus, the algorithm for converting between I/O space addresses and\r
2638 APRFILE indices is as follows:\r
2639\r
2640 idx<3:0> = dspace'page = pa<4:1>\r
2641 par = PDR vs PAR = pa<5>\r
2642 idx<5:4> = ker/sup/user = pa<8>'~pa<6>\r
2643\r
2644 Note: the A,W bits are read only; they are cleared by any write to an APR\r
2645*/\r
2646\r
2647t_stat APR_rd (int32 *data, int32 pa, int32 access)\r
2648{\r
2649t_stat left, idx;\r
2650\r
2651idx = (pa >> 1) & 017; /* dspace'page */\r
2652left = (pa >> 5) & 1; /* PDR vs PAR */\r
2653if ((pa & 0100) == 0) idx = idx | 020; /* 1 for super, user */\r
2654if (pa & 0400) idx = idx | 040; /* 1 for user only */\r
2655if (left) *data = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par;\r
2656else *data = APRFILE[idx] & cpu_tab[cpu_model].pdr;\r
2657return SCPE_OK;\r
2658}\r
2659\r
2660t_stat APR_wr (int32 data, int32 pa, int32 access)\r
2661{\r
2662int32 left, idx, curr;\r
2663\r
2664idx = (pa >> 1) & 017; /* dspace'page */\r
2665left = (pa >> 5) & 1; /* PDR vs PAR */\r
2666if ((pa & 0100) == 0) idx = idx | 020; /* 1 for super, user */\r
2667if (pa & 0400) idx = idx | 040; /* 1 for user only */\r
2668if (left) curr = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par;\r
2669else curr = APRFILE[idx] & cpu_tab[cpu_model].pdr;\r
2670if (access == WRITEB) data = (pa & 1)?\r
2671 (curr & 0377) | (data << 8): (curr & ~0377) | data;\r
2672if (left) APRFILE[idx] = ((APRFILE[idx] & 0177777) |\r
2673 (((uint32) (data & cpu_tab[cpu_model].par)) << 16)) & ~(PDR_A|PDR_W);\r
2674else APRFILE[idx] = ((APRFILE[idx] & ~0177777) |\r
2675 (data & cpu_tab[cpu_model].pdr)) & ~(PDR_A|PDR_W);\r
2676return SCPE_OK;\r
2677}\r
2678\r
2679/* Explicit PSW read */\r
2680\r
2681t_stat PSW_rd (int32 *data, int32 pa, int32 access)\r
2682{\r
2683if (access == READC) *data = PSW;\r
2684else *data = get_PSW ();\r
2685return SCPE_OK;\r
2686}\r
2687\r
2688/* Assemble PSW from pieces */\r
2689\r
2690int32 get_PSW (void)\r
2691{\r
2692return (cm << PSW_V_CM) | (pm << PSW_V_PM) |\r
2693 (rs << PSW_V_RS) | (fpd << PSW_V_FPD) |\r
2694 (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) |\r
2695 (N << PSW_V_N) | (Z << PSW_V_Z) |\r
2696 (V << PSW_V_V) | (C << PSW_V_C);\r
2697}\r
2698\r
2699/* Explicit PSW write - T-bit may be protected */\r
2700\r
2701t_stat PSW_wr (int32 data, int32 pa, int32 access)\r
2702{\r
2703int32 i, curr, oldrs;\r
2704\r
2705if (access == WRITEC) { /* console access? */\r
2706 PSW = data & cpu_tab[cpu_model].psw;\r
2707 return SCPE_OK;\r
2708 }\r
2709curr = get_PSW (); /* get current */\r
2710oldrs = rs; /* save reg set */\r
2711STACKFILE[cm] = SP; /* save curr SP */\r
2712if (access == WRITEB) data = (pa & 1)?\r
2713 (curr & 0377) | (data << 8): (curr & ~0377) | data;\r
2714if (!CPUT (HAS_EXPT)) /* expl T writes? */\r
2715 data = (data & ~PSW_TBIT) | (curr & PSW_TBIT); /* no, use old T */\r
2716put_PSW (data, 0); /* call calc_is,ds */\r
2717if (rs != oldrs) { /* switch reg set */\r
2718 for (i = 0; i < 6; i++) {\r
2719 REGFILE[i][oldrs] = R[i];\r
2720 R[i] = REGFILE[i][rs];\r
2721 }\r
2722 }\r
2723SP = STACKFILE[cm]; /* switch SP */\r
2724isenable = calc_is (cm);\r
2725dsenable = calc_ds (cm);\r
2726return SCPE_OK;\r
2727}\r
2728\r
2729/* Store pieces of new PSW - implements RTI/RTT protection */\r
2730\r
2731void put_PSW (int32 val, t_bool prot)\r
2732{\r
2733val = val & cpu_tab[cpu_model].psw; /* mask off invalid bits */\r
2734if (prot) { /* protected? */\r
2735 cm = cm | ((val >> PSW_V_CM) & 03); /* or to cm,pm,rs */\r
2736 pm = pm | ((val >> PSW_V_PM) & 03); /* can't change ipl */\r
2737 rs = rs | ((val >> PSW_V_RS) & 01);\r
2738 }\r
2739else {\r
2740 cm = (val >> PSW_V_CM) & 03; /* write cm,pm,rs,ipl */\r
2741 pm = (val >> PSW_V_PM) & 03;\r
2742 rs = (val >> PSW_V_RS) & 01;\r
2743 ipl = (val >> PSW_V_IPL) & 07;\r
2744 }\r
2745fpd = (val >> PSW_V_FPD) & 01; /* always writeable */\r
2746tbit = (val >> PSW_V_TBIT) & 01;\r
2747N = (val >> PSW_V_N) & 01;\r
2748Z = (val >> PSW_V_Z) & 01;\r
2749V = (val >> PSW_V_V) & 01;\r
2750C = (val >> PSW_V_C) & 01;\r
2751return;\r
2752}\r
2753\r
2754/* PIRQ write routine */\r
2755\r
2756void put_PIRQ (int32 val)\r
2757{\r
2758int32 pl;\r
2759\r
2760PIRQ = val & PIRQ_RW;\r
2761pl = 0;\r
2762if (PIRQ & PIRQ_PIR1) {\r
2763 SET_INT (PIR1);\r
2764 pl = 0042;\r
2765 }\r
2766else CLR_INT (PIR1);\r
2767if (PIRQ & PIRQ_PIR2) {\r
2768 SET_INT (PIR2);\r
2769 pl = 0104;\r
2770 }\r
2771else CLR_INT (PIR2);\r
2772if (PIRQ & PIRQ_PIR3) {\r
2773 SET_INT (PIR3);\r
2774 pl = 0146;\r
2775 }\r
2776else CLR_INT (PIR3);\r
2777if (PIRQ & PIRQ_PIR4) {\r
2778 SET_INT (PIR4);\r
2779 pl = 0210;\r
2780 }\r
2781else CLR_INT (PIR4);\r
2782if (PIRQ & PIRQ_PIR5) {\r
2783 SET_INT (PIR5);\r
2784 pl = 0252;\r
2785 }\r
2786else CLR_INT (PIR5);\r
2787if (PIRQ & PIRQ_PIR6) {\r
2788 SET_INT (PIR6);\r
2789 pl = 0314;\r
2790 }\r
2791else CLR_INT (PIR6);\r
2792if (PIRQ & PIRQ_PIR7) {\r
2793 SET_INT (PIR7);\r
2794 pl = 0356;\r
2795 }\r
2796else CLR_INT (PIR7);\r
2797PIRQ = PIRQ | pl;\r
2798return;\r
2799}\r
2800\r
2801/* Stack trap routine */\r
2802\r
2803void set_stack_trap (int32 adr)\r
2804{\r
2805if (CPUT (HAS_STKLF)) { /* fixed stack? */\r
2806 setTRAP (TRAP_YEL); /* always yellow trap */\r
2807 setCPUERR (CPUE_YEL);\r
2808 }\r
2809else if (CPUT (HAS_STKLR)) { /* register limit? */\r
2810 if (adr >= (STKLIM + STKL_R)) { /* yellow zone? */\r
2811 setTRAP (TRAP_YEL); /* still yellow trap */\r
2812 setCPUERR (CPUE_YEL);\r
2813 }\r
2814 else { /* red zone abort */\r
2815 setCPUERR (CPUE_RED);\r
2816 STACKFILE[MD_KER] = 4;\r
2817 SP = 4;\r
2818 ABORT (TRAP_RED);\r
2819 }\r
2820 }\r
2821return; /* no stack limit */\r
2822}\r
2823\r
2824/* Reset routine */\r
2825\r
2826t_stat cpu_reset (DEVICE *dptr)\r
2827{\r
2828PIRQ = 0;\r
2829STKLIM = 0;\r
2830PSW = 000340;\r
2831MMR0 = 0;\r
2832MMR1 = 0;\r
2833MMR2 = 0;\r
2834MMR3 = 0;\r
2835trap_req = 0;\r
2836wait_state = 0;\r
2837if (M == NULL) M = (uint16 *) calloc (MEMSIZE >> 1, sizeof (uint16));\r
2838if (M == NULL) return SCPE_MEM;\r
2839pcq_r = find_reg ("PCQ", NULL, dptr);\r
2840if (pcq_r) pcq_r->qptr = 0;\r
2841else return SCPE_IERR;\r
2842sim_brk_types = sim_brk_dflt = SWMASK ('E');\r
2843set_r_display (0, MD_KER);\r
2844return SCPE_OK;\r
2845}\r
2846\r
2847/* Memory examine */\r
2848\r
2849t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)\r
2850{\r
2851int32 iodata;\r
2852t_stat stat;\r
2853\r
2854if (vptr == NULL) return SCPE_ARG;\r
2855if (sw & SWMASK ('V')) { /* -v */\r
2856 if (addr >= VASIZE) return SCPE_NXM;\r
2857 addr = relocC (addr, sw); /* relocate */\r
2858 if (addr >= MAXMEMSIZE) return SCPE_REL;\r
2859 }\r
2860if (addr < MEMSIZE) {\r
2861 *vptr = M[addr >> 1] & 0177777;\r
2862 return SCPE_OK;\r
2863 }\r
2864if (addr < IOPAGEBASE) return SCPE_NXM;\r
2865stat = iopageR (&iodata, addr, READC);\r
2866*vptr = iodata;\r
2867return stat;\r
2868}\r
2869\r
2870/* Memory deposit */\r
2871\r
2872t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)\r
2873{\r
2874if (sw & SWMASK ('V')) { /* -v */\r
2875 if (addr >= VASIZE) return SCPE_NXM;\r
2876 addr = relocC (addr, sw); /* relocate */\r
2877 if (addr >= MAXMEMSIZE) return SCPE_REL;\r
2878 }\r
2879if (addr < MEMSIZE) {\r
2880 M[addr >> 1] = val & 0177777;\r
2881 return SCPE_OK;\r
2882 }\r
2883if (addr < IOPAGEBASE) return SCPE_NXM;\r
2884return iopageW ((int32) val, addr, WRITEC);\r
2885}\r
2886\r
2887/* Set R, SP register display addresses */\r
2888\r
2889void set_r_display (int32 rs, int32 cm)\r
2890{\r
2891extern REG *find_reg (char *cptr, char **optr, DEVICE *dptr);\r
2892REG *rptr;\r
2893int32 i;\r
2894\r
2895rptr = find_reg ("R0", NULL, &cpu_dev);\r
2896if (rptr == NULL) return;\r
2897for (i = 0; i < 6; i++, rptr++) rptr->loc = (void *) &REGFILE[i][rs];\r
2898rptr->loc = (void *) &STACKFILE[cm];\r
2899return;\r
2900}\r
2901\r
2902/* Set history */\r
2903\r
2904t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)\r
2905{\r
2906int32 i, lnt;\r
2907t_stat r;\r
2908\r
2909if (cptr == NULL) {\r
2910 for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;\r
2911 hst_p = 0;\r
2912 return SCPE_OK;\r
2913 }\r
2914lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);\r
2915if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;\r
2916hst_p = 0;\r
2917if (hst_lnt) {\r
2918 free (hst);\r
2919 hst_lnt = 0;\r
2920 hst = NULL;\r
2921 }\r
2922if (lnt) {\r
2923 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));\r
2924 if (hst == NULL) return SCPE_MEM;\r
2925 hst_lnt = lnt;\r
2926 }\r
2927return SCPE_OK;\r
2928}\r
2929\r
2930/* Show history */\r
2931\r
2932t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)\r
2933{\r
2934int32 j, k, di, lnt, ir;\r
2935char *cptr = (char *) desc;\r
2936t_value sim_eval[HIST_ILNT];\r
2937t_stat r;\r
2938InstHistory *h;\r
2939extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,\r
2940 UNIT *uptr, int32 sw);\r
2941\r
2942if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */\r
2943if (cptr) {\r
2944 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);\r
2945 if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;\r
2946 }\r
2947else lnt = hst_lnt;\r
2948di = hst_p - lnt; /* work forward */\r
2949if (di < 0) di = di + hst_lnt;\r
2950fprintf (st, "PC PSW src dst IR\n\n");\r
2951for (k = 0; k < lnt; k++) { /* print specified */\r
2952 h = &hst[(di++) % hst_lnt]; /* entry pointer */\r
2953 if (h->pc & HIST_VLD) { /* instruction? */\r
2954 ir = h->inst[0];\r
2955 fprintf (st, "%06o %06o|", h->pc & ~HIST_VLD, h->psw);\r
2956 if (((ir & 0070000) != 0) || /* dops, eis, fpp */\r
2957 ((ir & 0177000) == 0004000)) /* jsr */\r
2958 fprintf (st, "%06o %06o ", h->src, h->dst);\r
2959 else if ((ir >= 0000100) && /* not no opnd */\r
2960 (((ir & 0007700) < 0000300) || /* not branch */\r
2961 ((ir & 0007700) >= 0004000)))\r
2962 fprintf (st, " %06o ", h->dst);\r
2963 else fprintf (st, " ");\r
2964 for (j = 0; j < HIST_ILNT; j++) sim_eval[j] = h->inst[j];\r
2965 if ((fprint_sym (st, h->pc & ~HIST_VLD, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)\r
2966 fprintf (st, "(undefined) %06o", h->inst[0]);\r
2967 fputc ('\n', st); /* end line */\r
2968 } /* end else instruction */\r
2969 } /* end for */\r
2970return SCPE_OK;\r
2971}\r
2972\r
2973/* Virtual address translation */\r
2974\r
2975t_stat cpu_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc)\r
2976{\r
2977t_stat r;\r
2978char *cptr = (char *) desc;\r
2979uint32 va, pa;\r
2980\r
2981if (cptr) {\r
2982 va = (uint32) get_uint (cptr, 8, VAMASK, &r);\r
2983 if (r == SCPE_OK) {\r
2984 pa = relocC (va, sim_switches); /* relocate */\r
2985 if (pa < MAXMEMSIZE)\r
2986 fprintf (of, "Virtual %-o = physical %-o\n", va, pa);\r
2987 else fprintf (of, "Virtual %-o is not valid\n", va);\r
2988 return SCPE_OK;\r
2989 }\r
2990 }\r
2991fprintf (of, "Invalid argument\n");\r
2992return SCPE_OK;\r
2993}\r