blob: b434533d3f29e6f1c7f8605ced4daf2cdcd3120b [file] [log] [blame] [raw]
Bob Supnik9af6fd22001-11-06 20:44:00 -08001/* pdp11_cpu.c: PDP-11 CPU simulator
2
Mark Pizzolato71e745b2016-03-06 06:27:15 -08003 Copyright (c) 1993-2016, Robert M Supnik
Bob Supnik9af6fd22001-11-06 20:44:00 -08004
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
Bob Supnikb7c1eae2005-09-09 18:09:00 -070022 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
Bob Supnik9af6fd22001-11-06 20:44:00 -080024 in this Software without prior written authorization from Robert M Supnik.
25
Bob Supnikb7c1eae2005-09-09 18:09:00 -070026 cpu PDP-11 CPU
Bob Supnik4d6dfa42001-11-06 20:50:00 -080027
Paul Koning998cf5c2017-02-04 12:19:41 -080028 04-Dec-16 RMS Removed duplicate IDLE entries in MTAB
29 30-Aug-16 RMS Fixed overloading of -d in ex/mod
30 14-Mar-16 RMS Added UC15 support
Mark Pizzolato71e745b2016-03-06 06:27:15 -080031 06-Mar-16 RMS Fixed bug in history virtual addressing
Mark Pizzolato59947e82015-12-30 12:01:58 -080032 30-Dec-15 RMS Added NOBEVENT option for 11/03, 11/23
33 29-Dec-15 RMS Call build_dib_tab during reset (Mark Pizzolato)
Mark Pizzolato2daa41e2013-12-06 10:54:56 -080034 05-Dec-13 RMS Fixed bug in CSM (John Dundas)
Mark Pizzolatof0d41f12013-10-27 05:30:13 -070035 23-Oct-13 RMS Fixed PS behavior on initialization and boot
Mark Pizzolato4064cc02013-06-02 06:52:32 -070036 10-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist)
Mark Pizzolatoe35e6bc2012-05-02 07:06:11 -070037 29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato)
Mark Pizzolato6e813b82012-03-24 19:46:37 -070038 19-Mar-12 RMS Fixed declaration of sim_switches (Mark Pizzolato)
39 29-Dec-08 RMS Fixed failure to clear cpu_bme on RESET (Walter Mueller)
40 22-Apr-08 RMS Fixed MMR0 treatment in RESET (Walter Mueller)
41 02-Feb-08 RMS Fixed DMA memory address limit test (John Dundas)
Bob Supnik6149cc72007-05-12 17:39:00 -070042 28-Apr-07 RMS Removed clock initialization
Bob Supnik53d02f72007-02-03 14:59:00 -080043 27-Oct-06 RMS Added idle support
44 18-Oct-06 RMS Fixed bug in ASH -32 C value
Bob Supnikdc871fa2006-05-27 11:34:00 -070045 24-May-06 RMS Added instruction history
46 03-May-06 RMS Fixed XOR operand fetch order for 11/70-style systems
Mark Pizzolato6e813b82012-03-24 19:46:37 -070047 22-Sep-05 RMS Fixed declarations (Sterling Garwood)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070048 16-Aug-05 RMS Fixed C++ declaration and cast problems
49 19-May-05 RMS Replaced WAIT clock queue check with API call
Mark Pizzolato6e813b82012-03-24 19:46:37 -070050 19-Jan-05 RMS Fixed bug(s) in RESET for 11/70 (Tim Chapman)
51 22-Dec-04 RMS Fixed WAIT to work in all modes (John Dundas)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070052 02-Oct-04 RMS Added model emulation
53 25-Jan-04 RMS Removed local debug logging support
54 29-Dec-03 RMS Formalized 18b Qbus support
55 21-Dec-03 RMS Added autoconfiguration controls
56 05-Jun-03 RMS Fixed bugs in memory size table
57 12-Mar-03 RMS Added logical name support
58 01-Feb-03 RMS Changed R display to follow PSW<rs>, added SP display
59 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
60 05-Jan-03 RMS Added memory size restore support
Mark Pizzolato6e813b82012-03-24 19:46:37 -070061 17-Oct-02 RMS Fixed bug in examine/deposit (Hans Pufal)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070062 08-Oct-02 RMS Revised to build dib_tab dynamically
63 Added SHOW IOSPACE
64 09-Sep-02 RMS Added KW11P support
65 14-Jul-02 RMS Fixed bug in MMR0 error status load
66 03-Jun-02 RMS Fixed relocation add overflow, added PS<15:12> = 1111
67 special case logic to MFPI and removed it from MTPI
Mark Pizzolato6e813b82012-03-24 19:46:37 -070068 (John Dundas)
69 29-Apr-02 RMS More fixes to DIV and ASH/ASHC (John Dundas)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070070 28-Apr-02 RMS Fixed bugs in illegal instruction 000010 and in
Mark Pizzolato6e813b82012-03-24 19:46:37 -070071 write-only memory pages (Wolfgang Helbig)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070072 21-Apr-02 RMS Fixed bugs in DIV by zero, DIV overflow, TSTSET, RTS,
Mark Pizzolato6e813b82012-03-24 19:46:37 -070073 ASHC -32, and red zone trap (John Dundas)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070074 04-Mar-02 RMS Changed double operand evaluation order for M+
75 23-Feb-02 RMS Fixed bug in MAINT, CPUERR, MEMERR read
76 28-Jan-02 RMS Revised for multiple timers; fixed calc_MMR1 macros
77 06-Jan-02 RMS Revised enable/disable support
78 30-Dec-01 RMS Added old PC queue
79 25-Dec-01 RMS Cleaned up sim_inst declarations
80 11-Dec-01 RMS Moved interrupt debug code
81 07-Dec-01 RMS Revised to use new breakpoint package
82 08-Nov-01 RMS Moved I/O to external module
83 26-Oct-01 RMS Revised to use symbolic definitions for IO page
84 15-Oct-01 RMS Added debug logging
85 08-Oct-01 RMS Fixed bug in revised interrupt logic
86 07-Sep-01 RMS Revised device disable and interrupt mechanisms
87 26-Aug-01 RMS Added DZ11 support
88 10-Aug-01 RMS Removed register from declarations
89 17-Jul-01 RMS Fixed warning from VC++ 6.0
90 01-Jun-01 RMS Added DZ11 interrupts
91 23-Apr-01 RMS Added RK611 support
92 05-Apr-01 RMS Added TS11/TSV05 support
93 05-Mar-01 RMS Added clock calibration support
94 11-Feb-01 RMS Added DECtape support
Mark Pizzolato6e813b82012-03-24 19:46:37 -070095 25-Jan-01 RMS Fixed 4M memory definition (Eric Smith)
Bob Supnikb7c1eae2005-09-09 18:09:00 -070096 14-Apr-99 RMS Changed t_addr to unsigned
97 18-Aug-98 RMS Added CIS support
98 09-May-98 RMS Fixed bug in DIV overflow test
99 19-Jan-97 RMS Added RP/RM support
100 06-Apr-96 RMS Added dynamic memory sizing
101 29-Feb-96 RMS Added TM11 support
102 17-Jul-94 RMS Corrected updating of MMR1 if MMR0 locked
Bob Supnik9af6fd22001-11-06 20:44:00 -0800103
104 The register state for the PDP-11 is:
105
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700106 REGFILE[0:5][0] general register set
107 REGFILE[0:5][1] alternate general register set
108 STACKFILE[4] stack pointers for kernel, supervisor, unused, user
109 PC program counter
110 PSW processor status word
111 <15:14> = CM current processor mode
112 <13:12> = PM previous processor mode
113 <11> = RS register set select
114 <8> = FPD first part done (CIS)
115 <7:5> = IPL interrupt priority level
116 <4> = TBIT trace trap enable
117 <3:0> = NZVC condition codes
118 FR[0:5] floating point accumulators
119 FPS floating point status register
120 FEC floating exception code
121 FEA floating exception address
122 MMR0,1,2,3 memory management control registers
123 APRFILE[0:63] memory management relocation registers for
124 kernel, supervisor, unused, user
125 <31:16> = PAR processor address registers
126 <15:0> = PDR processor data registers
127 PIRQ processor interrupt request register
128 CPUERR CPU error register
129 MEMERR memory system error register
130 CCR cache control register
131 MAINT maintenance register
132 HITMISS cache status register
133 SR switch register
134 DR display register
Bob Supnik9af6fd22001-11-06 20:44:00 -0800135
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700136 The PDP-11 has many instruction formats:
Bob Supnik9af6fd22001-11-06 20:44:00 -0800137
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700138 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ double operand
139 | opcode | source spec | dest spec | 010000:067777
140 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 110000:167777
Bob Supnik9af6fd22001-11-06 20:44:00 -0800141
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700142 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ register + operand
143 | opcode | src reg| dest spec | 004000:004777
144 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 070000:077777
Bob Supnik9af6fd22001-11-06 20:44:00 -0800145
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700146 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single operand
147 | opcode | dest spec | 000100:000177
148 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000300:000377
149 005000:007777
150 105000:107777
Bob Supnik9af6fd22001-11-06 20:44:00 -0800151
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700152 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ single register
153 | opcode |dest reg| 000200:000207
154 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 000230:000237
155
156 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ no operand
157 | opcode | 000000:000007
Bob Supnik9af6fd22001-11-06 20:44:00 -0800158 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
159
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700160 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ branch
161 | opcode | branch displacement | 000400:003477
162 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 100000:103477
Bob Supnik9af6fd22001-11-06 20:44:00 -0800163
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700164 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ EMT/TRAP
165 | opcode | trap code | 104000:104777
Bob Supnik9af6fd22001-11-06 20:44:00 -0800166 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
167
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700168 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ cond code operator
169 | opcode | immediate | 000240:000277
Bob Supnik9af6fd22001-11-06 20:44:00 -0800170 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
171
172 An operand specifier consists of an addressing mode and a register.
173 The addressing modes are:
174
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700175 0 register direct R op = R
176 1 register deferred (R) op = M[R]
177 2 autoincrement (R)+ op = M[R]; R = R + length
178 3 autoincrement deferred @(R)+ op = M[M[R]]; R = R + 2
179 4 autodecrement -(R) R = R - length; op = M[R]
180 5 autodecrement deferred @-(R) R = R - 2; op = M[M[R]]
181 6 displacement d(R) op = M[R + disp]
182 7 displacement deferred @d(R) op = M[M[R + disp]]
Bob Supnik9af6fd22001-11-06 20:44:00 -0800183
184 There are eight general registers, R0-R7. R6 is the stack pointer,
185 R7 the PC. The combination of addressing modes with R7 yields:
186
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700187 27 immediate #n op = M[PC]; PC = PC + 2
188 37 absolute @#n op = M[M[PC]]; PC = PC + 2
189 67 relative d(PC) op = M[PC + disp]
190 77 relative deferred @d(PC) op = M[M[PC + disp]]
191
192 This routine is the instruction decode routine for the PDP-11. It
Bob Supnik9af6fd22001-11-06 20:44:00 -0800193 is called from the simulator control program to execute instructions
194 in simulated memory, starting at the simulated PC. It runs until an
195 enabled exception is encountered.
196
197 General notes:
198
199 1. Virtual address format. PDP-11 memory management uses the 16b
200 virtual address, the type of reference (instruction or data), and
201 the current mode, to construct the 22b physical address. To
202 package this conveniently, the simulator uses a 19b pseudo virtual
203 address, consisting of the 16b virtual address prefixed with the
204 current mode and ispace/dspace indicator. These are precalculated
205 as isenable and dsenable for ispace and dspace, respectively, and
206 must be recalculated whenever MMR0, MMR3, or PSW<cm> changes.
207
208 2. Traps and interrupts. Variable trap_req bit-encodes all possible
209 traps. In addition, an interrupt pending bit is encoded as the
210 lowest priority trap. Traps are processed by trap_vec and trap_clear,
211 which provide the vector and subordinate traps to clear, respectively.
212
Bob Supnik654937f2001-11-06 21:02:00 -0800213 Array int_req[0:7] bit encodes all possible interrupts. It is masked
214 under the interrupt priority level, ipl. If any interrupt request
Bob Supnik9af6fd22001-11-06 20:44:00 -0800215 is not masked, the interrupt bit is set in trap_req. While most
216 interrupts are handled centrally, a device can supply an interrupt
217 acknowledge routine.
218
219 3. PSW handling. The PSW is kept as components, for easier access.
220 Because the PSW can be explicitly written as address 17777776,
221 all instructions must update PSW before executing their last write.
222
Bob Supnik2c2dd5e2002-11-17 15:54:00 -0800223 4. Adding I/O devices. These modules must be modified:
Bob Supnik9af6fd22001-11-06 20:44:00 -0800224
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700225 pdp11_defs.h add device address and interrupt definitions
226 pdp11_sys.c add to sim_devices table entry
Bob Supnik9af6fd22001-11-06 20:44:00 -0800227*/
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700228
Bob Supnik9af6fd22001-11-06 20:44:00 -0800229/* Definitions */
230
231#include "pdp11_defs.h"
Bob Supnikb6393b32004-11-23 15:49:00 -0800232#include "pdp11_cpumod.h"
Bob Supnik9af6fd22001-11-06 20:44:00 -0800233
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700234#define PCQ_SIZE 64 /* must be 2**n */
235#define PCQ_MASK (PCQ_SIZE - 1)
236#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
237#define calc_is(md) ((md) << VA_V_MODE)
238#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0))
Paul Koning89ffed42016-09-13 15:22:35 -0400239/* Register change tracking actually goes into variable reg_mods; from there
240 it is copied into MMR1 if that register is not currently locked. */
241#define calc_MMR1(val) ((reg_mods)? (((val) << 8) | reg_mods): (val))
Bob Supnik53d02f72007-02-03 14:59:00 -0800242#define GET_SIGN_W(v) (((v) >> 15) & 1)
243#define GET_SIGN_B(v) (((v) >> 7) & 1)
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700244#define GET_Z(v) ((v) == 0)
245#define JMP_PC(x) PCQ_ENTRY; PC = (x)
246#define BRANCH_F(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) & 0377)) & 0177777
247#define BRANCH_B(x) PCQ_ENTRY; PC = (PC + (((x) + (x)) | 0177400)) & 0177777
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700248#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy */
249#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
Bob Supnikb6393b32004-11-23 15:49:00 -0800250
Bob Supnikdc871fa2006-05-27 11:34:00 -0700251#define HIST_MIN 64
252#define HIST_MAX (1u << 18)
253#define HIST_VLD 1 /* make PC odd */
254#define HIST_ILNT 4 /* max inst length */
255
256typedef struct {
257 uint16 pc;
258 uint16 psw;
259 uint16 src;
260 uint16 dst;
261 uint16 inst[HIST_ILNT];
262 } InstHistory;
263
Bob Supnik9af6fd22001-11-06 20:44:00 -0800264/* Global state */
265
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700266uint16 *M = NULL; /* memory */
Mark Pizzolatoc71e0c32012-12-13 15:21:07 -0800267int32 REGFILE[6][2] = { {0} }; /* R0-R5, two sets */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700268int32 STACKFILE[4] = { 0 }; /* SP, four modes */
269int32 saved_PC = 0; /* program counter */
270int32 R[8] = { 0 }; /* working registers */
271int32 PSW = 0; /* PSW */
272 int32 cm = 0; /* current mode */
273 int32 pm = 0; /* previous mode */
274 int32 rs = 0; /* register set */
275 int32 fpd = 0; /* first part done */
276 int32 ipl = 0; /* int pri level */
277 int32 tbit = 0; /* trace flag */
278 int32 N = 0, Z = 0, V = 0, C = 0; /* condition codes */
279int32 wait_state = 0; /* wait state */
280int32 trap_req = 0; /* trap requests */
281int32 int_req[IPL_HLVL] = { 0 }; /* interrupt requests */
282int32 PIRQ = 0; /* programmed int req */
283int32 STKLIM = 0; /* stack limit */
Mark Pizzolatoc71e0c32012-12-13 15:21:07 -0800284fpac_t FR[6] = { {0} }; /* fp accumulators */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700285int32 FPS = 0; /* fp status */
286int32 FEC = 0; /* fp exception code */
287int32 FEA = 0; /* fp exception addr */
288int32 APRFILE[64] = { 0 }; /* PARs/PDRs */
289int32 MMR0 = 0; /* MMR0 - status */
290int32 MMR1 = 0; /* MMR1 - R+/-R */
291int32 MMR2 = 0; /* MMR2 - saved PC */
292int32 MMR3 = 0; /* MMR3 - 22b status */
293int32 cpu_bme = 0; /* bus map enable */
294int32 cpu_astop = 0; /* address stop */
295int32 isenable = 0, dsenable = 0; /* i, d space flags */
296int32 stop_trap = 1; /* stop on trap */
297int32 stop_vecabort = 1; /* stop on vec abort */
298int32 stop_spabort = 1; /* stop on SP abort */
299int32 wait_enable = 0; /* wait state enable */
300int32 autcon_enb = 1; /* autoconfig enable */
Paul Koning998cf5c2017-02-04 12:19:41 -0800301uint32 cpu_model = INIMODEL; /* CPU model */
302uint32 cpu_type = 1u << INIMODEL; /* model as bit mask */
303uint32 cpu_opt = INIOPTNS; /* CPU options */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700304uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
305int32 pcq_p = 0; /* PC queue ptr */
306REG *pcq_r = NULL; /* PC queue reg ptr */
307jmp_buf save_env; /* abort handler */
Bob Supnikdc871fa2006-05-27 11:34:00 -0700308int32 hst_p = 0; /* history pointer */
309int32 hst_lnt = 0; /* history length */
310InstHistory *hst = NULL; /* instruction history */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700311int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */
Paul Koning89ffed42016-09-13 15:22:35 -0400312int16 inst_pc; /* PC of current instr */
313int32 inst_psw; /* PSW at instr. start */
314int16 reg_mods; /* reg deltas */
315int32 last_pa; /* pa from ReadMW/ReadMB */
316int32 saved_sim_interval; /* saved at inst start */
317t_stat reason; /* stop reason */
Bob Supnik654937f2001-11-06 21:02:00 -0800318
Bob Supnikb6393b32004-11-23 15:49:00 -0800319extern int32 CPUERR, MAINT;
Bob Supnikb6393b32004-11-23 15:49:00 -0800320extern CPUTAB cpu_tab[];
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700321
Bob Supnik9af6fd22001-11-06 20:44:00 -0800322/* Function declarations */
323
324t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
325t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
326t_stat cpu_reset (DEVICE *dptr);
Mark Pizzolatoe7a93492014-04-17 13:07:37 -0700327t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs);
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700328t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
329t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
330t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
Bob Supnik9af6fd22001-11-06 20:44:00 -0800331int32 GeteaB (int32 spec);
332int32 GeteaW (int32 spec);
333int32 relocR (int32 addr);
334int32 relocW (int32 addr);
Bob Supnikb6393b32004-11-23 15:49:00 -0800335void relocR_test (int32 va, int32 apridx);
336void relocW_test (int32 va, int32 apridx);
337t_bool PLF_test (int32 va, int32 apr);
338void reloc_abort (int32 err, int32 apridx);
339int32 ReadE (int32 addr);
Bob Supnik9af6fd22001-11-06 20:44:00 -0800340int32 ReadW (int32 addr);
341int32 ReadB (int32 addr);
Paul Koning89ffed42016-09-13 15:22:35 -0400342int32 ReadCW (int32 addr);
Bob Supnik9af6fd22001-11-06 20:44:00 -0800343int32 ReadMW (int32 addr);
344int32 ReadMB (int32 addr);
Paul Koning89ffed42016-09-13 15:22:35 -0400345int32 PReadW (int32 addr);
346int32 PReadB (int32 addr);
Bob Supnik9af6fd22001-11-06 20:44:00 -0800347void WriteW (int32 data, int32 addr);
348void WriteB (int32 data, int32 addr);
Paul Koning89ffed42016-09-13 15:22:35 -0400349void WriteCW (int32 data, int32 addr);
Bob Supnik9af6fd22001-11-06 20:44:00 -0800350void PWriteW (int32 data, int32 addr);
351void PWriteB (int32 data, int32 addr);
Bob Supnikf20f5c62003-02-07 21:28:00 -0800352void set_r_display (int32 rs, int32 cm);
Bob Supnikb6393b32004-11-23 15:49:00 -0800353t_stat CPU_wr (int32 data, int32 addr, int32 access);
354void set_stack_trap (int32 adr);
355int32 get_PSW (void);
356void put_PSW (int32 val, t_bool prot);
357void put_PIRQ (int32 val);
Bob Supnik9af6fd22001-11-06 20:44:00 -0800358
Bob Supnikb6393b32004-11-23 15:49:00 -0800359extern void fp11 (int32 IR);
Bob Supnik15919a22006-07-20 13:36:00 -0700360extern t_stat cis11 (int32 IR);
Bob Supnik1e704bf2005-10-15 15:38:00 -0700361extern t_stat fis11 (int32 IR);
Bob Supnikb6393b32004-11-23 15:49:00 -0800362extern t_stat build_dib_tab (void);
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700363extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
364extern t_stat set_autocon (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
365extern t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
Bob Supnikdf647512002-07-14 15:20:00 -0700366extern t_stat iopageR (int32 *data, uint32 addr, int32 access);
367extern t_stat iopageW (int32 data, uint32 addr, int32 access);
Bob Supnik701f0fe2001-12-26 09:38:00 -0800368extern int32 calc_ints (int32 nipl, int32 trq);
369extern int32 get_vector (int32 nipl);
Bob Supnik9af6fd22001-11-06 20:44:00 -0800370
Bob Supnik701f0fe2001-12-26 09:38:00 -0800371/* Trap data structures */
Bob Supnik9af6fd22001-11-06 20:44:00 -0800372
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700373int32 trap_vec[TRAP_V_MAX] = { /* trap req to vector */
374 VEC_RED, VEC_ODD, VEC_MME, VEC_NXM,
375 VEC_PAR, VEC_PRV, VEC_ILL, VEC_BPT,
376 VEC_IOT, VEC_EMT, VEC_TRAP, VEC_TRC,
377 VEC_YEL, VEC_PWRFL, VEC_FPE
378 };
Bob Supnik9af6fd22001-11-06 20:44:00 -0800379
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700380int32 trap_clear[TRAP_V_MAX] = { /* trap clears */
381 TRAP_RED+TRAP_PAR+TRAP_YEL+TRAP_TRC+TRAP_ODD+TRAP_NXM,
382 TRAP_ODD+TRAP_PAR+TRAP_YEL+TRAP_TRC,
383 TRAP_MME+TRAP_PAR+TRAP_YEL+TRAP_TRC,
384 TRAP_NXM+TRAP_PAR+TRAP_YEL+TRAP_TRC,
385 TRAP_PAR+TRAP_TRC, TRAP_PRV+TRAP_TRC,
386 TRAP_ILL+TRAP_TRC, TRAP_BPT+TRAP_TRC,
387 TRAP_IOT+TRAP_TRC, TRAP_EMT+TRAP_TRC,
388 TRAP_TRAP+TRAP_TRC, TRAP_TRC,
389 TRAP_YEL, TRAP_PWRFL, TRAP_FPE
390 };
391
Bob Supnik9af6fd22001-11-06 20:44:00 -0800392/* CPU data structures
393
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700394 cpu_dev CPU device descriptor
395 cpu_unit CPU unit descriptor
396 cpu_reg CPU register list
397 cpu_mod CPU modifier list
Bob Supnik9af6fd22001-11-06 20:44:00 -0800398*/
399
Bob Supnik53d02f72007-02-03 14:59:00 -0800400UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK, INIMEMSIZE) };
Bob Supnik9af6fd22001-11-06 20:44:00 -0800401
Mark Pizzolatoe054a782016-01-18 07:02:06 -0800402const char *psw_modes[] = {"K", "E", "S", "U"};
403
404
405BITFIELD psw_bits[] = {
406 BIT(C), /* Carry */
407 BIT(V), /* Overflow */
408 BIT(Z), /* Zero */
409 BIT(N), /* Negative */
410 BIT(TBIT), /* trace trap */
411 BITFFMT(IPL,3,%d), /* IPL */
412 BIT(FPD), /* First Part Done */
413 BITNCF(2), /* MBZ */
414 BIT(RS), /* Register Set */
415 BITFNAM(PM,2,psw_modes), /* Previous Access Mode */
416 BITFNAM(CM,2,psw_modes), /* Current Access Mode */
417 ENDBITS
418};
419
Bob Supnik9af6fd22001-11-06 20:44:00 -0800420REG cpu_reg[] = {
Mark Pizzolatoe054a782016-01-18 07:02:06 -0800421 { ORDATAD (PC, saved_PC, 16, "Program Counter") },
422 { ORDATAD (R0, REGFILE[0][0], 16, "General Purpose R0") },
423 { ORDATAD (R1, REGFILE[1][0], 16, "General Purpose R1") },
424 { ORDATAD (R2, REGFILE[2][0], 16, "General Purpose R2") },
425 { ORDATAD (R3, REGFILE[3][0], 16, "General Purpose R3") },
426 { ORDATAD (R4, REGFILE[4][0], 16, "General Purpose R4") },
427 { ORDATAD (R5, REGFILE[5][0], 16, "General Purpose R5") },
428 { ORDATAD (SP, STACKFILE[MD_KER], 16, "Stack Pointer"), },
429 { ORDATAD (R00, REGFILE[0][0], 16, "Register File R00") },
430 { ORDATAD (R01, REGFILE[1][0], 16, "Register File R01") },
431 { ORDATAD (R02, REGFILE[2][0], 16, "Register File R02") },
432 { ORDATAD (R03, REGFILE[3][0], 16, "Register File R03") },
433 { ORDATAD (R04, REGFILE[4][0], 16, "Register File R04") },
434 { ORDATAD (R05, REGFILE[5][0], 16, "Register File R05") },
435 { ORDATAD (R10, REGFILE[0][1], 16, "Register File R10") },
436 { ORDATAD (R11, REGFILE[1][1], 16, "Register File R11") },
437 { ORDATAD (R12, REGFILE[2][1], 16, "Register File R12") },
438 { ORDATAD (R13, REGFILE[3][1], 16, "Register File R13") },
439 { ORDATAD (R14, REGFILE[4][1], 16, "Register File R14") },
440 { ORDATAD (R15, REGFILE[5][1], 16, "Register File R15") },
441 { ORDATAD (KSP, STACKFILE[MD_KER], 16, "Kernel Stack Pointer" ) },
442 { ORDATAD (SSP, STACKFILE[MD_SUP], 16, "Supervisor Stack Pointer" ) },
443 { ORDATAD (USP, STACKFILE[MD_USR], 16, "User Stack Pointer" ) },
444 { ORDATADF(PSW, PSW, 16, "Processor Status Word", psw_bits) },
445 { GRDATAD (CM, PSW, 8, 2, PSW_V_CM, "Current Mode") },
446 { GRDATAD (PM, PSW, 8, 2, PSW_V_PM, "Previous Mode") },
447 { FLDATAD (RS, PSW, PSW_V_RS, "Register Set") },
448 { FLDATAD (FPD, PSW, PSW_V_FPD, "First Part Done") },
449 { GRDATAD (IPL, PSW, 8, 3, PSW_V_IPL, "Interrupt Priority Level") },
450 { FLDATAD (T, PSW, PSW_V_TBIT, "Trace Trap") },
451 { FLDATAD (N, PSW, PSW_V_N, "Condition Code: Negative") },
452 { FLDATAD (Z, PSW, PSW_V_Z, "Condition Code: Zero") },
453 { FLDATAD (V, PSW, PSW_V_V, "Condition Code: Overflow") },
454 { FLDATAD (C, PSW, PSW_V_C, "Condition Code: Carry") },
455 { ORDATAD (PIRQ, PIRQ, 16, "Programmed Interrupt Request") },
456 { ORDATAD (STKLIM, STKLIM, 16, "Stack Limit") },
457 { ORDATAD (FAC0H, FR[0].h, 32, "Floating Point: R0 High") },
458 { ORDATAD (FAC0L, FR[0].l, 32, "Floating Point: R0 Low") },
459 { ORDATAD (FAC1H, FR[1].h, 32, "Floating Point: R1 High") },
460 { ORDATAD (FAC1L, FR[1].l, 32, "Floating Point: R1 Low") },
461 { ORDATAD (FAC2H, FR[2].h, 32, "Floating Point: R2 High") },
462 { ORDATAD (FAC2L, FR[2].l, 32, "Floating Point: R2 Low") },
463 { ORDATAD (FAC3H, FR[3].h, 32, "Floating Point: R3 High") },
464 { ORDATAD (FAC3L, FR[3].l, 32, "Floating Point: R3 Low") },
465 { ORDATAD (FAC4H, FR[4].h, 32, "Floating Point: R4 High") },
466 { ORDATAD (FAC4L, FR[4].l, 32, "Floating Point: R4 Low") },
467 { ORDATAD (FAC5H, FR[5].h, 32, "Floating Point: R5 High") },
468 { ORDATAD (FAC5L, FR[5].l, 32, "Floating Point: R5 Low") },
469 { ORDATAD (FPS, FPS, 16, "FP Status") },
470 { ORDATAD (FEA, FEA, 16, "FP Exception Code") },
471 { ORDATAD (FEC, FEC, 4, "FP Exception Address") },
472 { ORDATAD (MMR0, MMR0, 16, "MMR0 - Status") },
473 { ORDATAD (MMR1, MMR1, 16, "MMR1 - R+/-R") },
474 { ORDATAD (MMR2, MMR2, 16, "MMR2 - saved PC") },
475 { ORDATAD (MMR3, MMR3, 16, "MMR3 - 22b status") },
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700476 { GRDATA (KIPAR0, APRFILE[000], 8, 16, 16) },
477 { GRDATA (KIPDR0, APRFILE[000], 8, 16, 0) },
478 { GRDATA (KIPAR1, APRFILE[001], 8, 16, 16) },
479 { GRDATA (KIPDR1, APRFILE[001], 8, 16, 0) },
480 { GRDATA (KIPAR2, APRFILE[002], 8, 16, 16) },
481 { GRDATA (KIPDR2, APRFILE[002], 8, 16, 0) },
482 { GRDATA (KIPAR3, APRFILE[003], 8, 16, 16) },
483 { GRDATA (KIPDR3, APRFILE[003], 8, 16, 0) },
484 { GRDATA (KIPAR4, APRFILE[004], 8, 16, 16) },
485 { GRDATA (KIPDR4, APRFILE[004], 8, 16, 0) },
486 { GRDATA (KIPAR5, APRFILE[005], 8, 16, 16) },
487 { GRDATA (KIPDR5, APRFILE[005], 8, 16, 0) },
488 { GRDATA (KIPAR6, APRFILE[006], 8, 16, 16) },
489 { GRDATA (KIPDR6, APRFILE[006], 8, 16, 0) },
490 { GRDATA (KIPAR7, APRFILE[007], 8, 16, 16) },
491 { GRDATA (KIPDR7, APRFILE[007], 8, 16, 0) },
492 { GRDATA (KDPAR0, APRFILE[010], 8, 16, 16) },
493 { GRDATA (KDPDR0, APRFILE[010], 8, 16, 0) },
494 { GRDATA (KDPAR1, APRFILE[011], 8, 16, 16) },
495 { GRDATA (KDPDR1, APRFILE[011], 8, 16, 0) },
496 { GRDATA (KDPAR2, APRFILE[012], 8, 16, 16) },
497 { GRDATA (KDPDR2, APRFILE[012], 8, 16, 0) },
498 { GRDATA (KDPAR3, APRFILE[013], 8, 16, 16) },
499 { GRDATA (KDPDR3, APRFILE[013], 8, 16, 0) },
500 { GRDATA (KDPAR4, APRFILE[014], 8, 16, 16) },
501 { GRDATA (KDPDR4, APRFILE[014], 8, 16, 0) },
502 { GRDATA (KDPAR5, APRFILE[015], 8, 16, 16) },
503 { GRDATA (KDPDR5, APRFILE[015], 8, 16, 0) },
504 { GRDATA (KDPAR6, APRFILE[016], 8, 16, 16) },
505 { GRDATA (KDPDR6, APRFILE[016], 8, 16, 0) },
506 { GRDATA (KDPAR7, APRFILE[017], 8, 16, 16) },
507 { GRDATA (KDPDR7, APRFILE[017], 8, 16, 0) },
508 { GRDATA (SIPAR0, APRFILE[020], 8, 16, 16) },
509 { GRDATA (SIPDR0, APRFILE[020], 8, 16, 0) },
510 { GRDATA (SIPAR1, APRFILE[021], 8, 16, 16) },
511 { GRDATA (SIPDR1, APRFILE[021], 8, 16, 0) },
512 { GRDATA (SIPAR2, APRFILE[022], 8, 16, 16) },
513 { GRDATA (SIPDR2, APRFILE[022], 8, 16, 0) },
514 { GRDATA (SIPAR3, APRFILE[023], 8, 16, 16) },
515 { GRDATA (SIPDR3, APRFILE[023], 8, 16, 0) },
516 { GRDATA (SIPAR4, APRFILE[024], 8, 16, 16) },
517 { GRDATA (SIPDR4, APRFILE[024], 8, 16, 0) },
518 { GRDATA (SIPAR5, APRFILE[025], 8, 16, 16) },
519 { GRDATA (SIPDR5, APRFILE[025], 8, 16, 0) },
520 { GRDATA (SIPAR6, APRFILE[026], 8, 16, 16) },
521 { GRDATA (SIPDR6, APRFILE[026], 8, 16, 0) },
522 { GRDATA (SIPAR7, APRFILE[027], 8, 16, 16) },
523 { GRDATA (SIPDR7, APRFILE[027], 8, 16, 0) },
524 { GRDATA (SDPAR0, APRFILE[030], 8, 16, 16) },
525 { GRDATA (SDPDR0, APRFILE[030], 8, 16, 0) },
526 { GRDATA (SDPAR1, APRFILE[031], 8, 16, 16) },
527 { GRDATA (SDPDR1, APRFILE[031], 8, 16, 0) },
528 { GRDATA (SDPAR2, APRFILE[032], 8, 16, 16) },
529 { GRDATA (SDPDR2, APRFILE[032], 8, 16, 0) },
530 { GRDATA (SDPAR3, APRFILE[033], 8, 16, 16) },
531 { GRDATA (SDPDR3, APRFILE[033], 8, 16, 0) },
532 { GRDATA (SDPAR4, APRFILE[034], 8, 16, 16) },
533 { GRDATA (SDPDR4, APRFILE[034], 8, 16, 0) },
534 { GRDATA (SDPAR5, APRFILE[035], 8, 16, 16) },
535 { GRDATA (SDPDR5, APRFILE[035], 8, 16, 0) },
536 { GRDATA (SDPAR6, APRFILE[036], 8, 16, 16) },
537 { GRDATA (SDPDR6, APRFILE[036], 8, 16, 0) },
538 { GRDATA (SDPAR7, APRFILE[037], 8, 16, 16) },
539 { GRDATA (SDPDR7, APRFILE[037], 8, 16, 0) },
540 { GRDATA (UIPAR0, APRFILE[060], 8, 16, 16) },
541 { GRDATA (UIPDR0, APRFILE[060], 8, 16, 0) },
542 { GRDATA (UIPAR1, APRFILE[061], 8, 16, 16) },
543 { GRDATA (UIPDR1, APRFILE[061], 8, 16, 0) },
544 { GRDATA (UIPAR2, APRFILE[062], 8, 16, 16) },
545 { GRDATA (UIPDR2, APRFILE[062], 8, 16, 0) },
546 { GRDATA (UIPAR3, APRFILE[063], 8, 16, 16) },
547 { GRDATA (UIPDR3, APRFILE[063], 8, 16, 0) },
548 { GRDATA (UIPAR4, APRFILE[064], 8, 16, 16) },
549 { GRDATA (UIPDR4, APRFILE[064], 8, 16, 0) },
550 { GRDATA (UIPAR5, APRFILE[065], 8, 16, 16) },
551 { GRDATA (UIPDR5, APRFILE[065], 8, 16, 0) },
552 { GRDATA (UIPAR6, APRFILE[066], 8, 16, 16) },
553 { GRDATA (UIPDR6, APRFILE[066], 8, 16, 0) },
554 { GRDATA (UIPAR7, APRFILE[067], 8, 16, 16) },
555 { GRDATA (UIPDR7, APRFILE[067], 8, 16, 0) },
556 { GRDATA (UDPAR0, APRFILE[070], 8, 16, 16) },
557 { GRDATA (UDPDR0, APRFILE[070], 8, 16, 0) },
558 { GRDATA (UDPAR1, APRFILE[071], 8, 16, 16) },
559 { GRDATA (UDPDR1, APRFILE[071], 8, 16, 0) },
560 { GRDATA (UDPAR2, APRFILE[072], 8, 16, 16) },
561 { GRDATA (UDPDR2, APRFILE[072], 8, 16, 0) },
562 { GRDATA (UDPAR3, APRFILE[073], 8, 16, 16) },
563 { GRDATA (UDPDR3, APRFILE[073], 8, 16, 0) },
564 { GRDATA (UDPAR4, APRFILE[074], 8, 16, 16) },
565 { GRDATA (UDPDR4, APRFILE[074], 8, 16, 0) },
566 { GRDATA (UDPAR5, APRFILE[075], 8, 16, 16) },
567 { GRDATA (UDPDR5, APRFILE[075], 8, 16, 0) },
568 { GRDATA (UDPAR6, APRFILE[076], 8, 16, 16) },
569 { GRDATA (UDPDR6, APRFILE[076], 8, 16, 0) },
570 { GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) },
571 { GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) },
Mark Pizzolatoe054a782016-01-18 07:02:06 -0800572 { BRDATAD (IREQ, int_req, 8, 32, IPL_HLVL, "Interrupt Requests"), REG_RO },
573 { ORDATAD (TRAPS, trap_req, TRAP_V_MAX, "Trap Requests") },
574 { FLDATAD (WAIT, wait_state, 0, "Wait State") },
Bob Supnik53d02f72007-02-03 14:59:00 -0800575 { FLDATA (WAIT_ENABLE, wait_enable, 0), REG_HIDDEN },
Mark Pizzolatoe054a782016-01-18 07:02:06 -0800576 { ORDATAD (STOP_TRAPS, stop_trap, TRAP_V_MAX, "Stop on Trap") },
577 { FLDATAD (STOP_VECA, stop_vecabort, 0, "Stop on Vec Abort") },
578 { FLDATAD (STOP_SPA, stop_spabort, 0, "Stop on SP Abort") },
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700579 { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO },
580 { BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC },
581 { ORDATA (PCQP, pcq_p, 6), REG_HRO },
582 { ORDATA (WRU, sim_int_char, 8) },
583 { ORDATA (MODEL, cpu_model, 16), REG_HRO },
584 { ORDATA (OPTIONS, cpu_opt, 32), REG_HRO },
585 { NULL}
586 };
Bob Supnik9af6fd22001-11-06 20:44:00 -0800587
588MTAB cpu_mod[] = {
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700589 { MTAB_XTD|MTAB_VDV, 0, "TYPE", NULL,
590 NULL, &cpu_show_model },
Paul Koning998cf5c2017-02-04 12:19:41 -0800591#if !defined (UC15)
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700592 { MTAB_XTD|MTAB_VDV, MOD_1103, NULL, "11/03", &cpu_set_model },
593 { MTAB_XTD|MTAB_VDV, MOD_1104, NULL, "11/04", &cpu_set_model },
594 { MTAB_XTD|MTAB_VDV, MOD_1105, NULL, "11/05", &cpu_set_model },
595 { MTAB_XTD|MTAB_VDV, MOD_1120, NULL, "11/20", &cpu_set_model },
596 { MTAB_XTD|MTAB_VDV, MOD_1123, NULL, "11/23", &cpu_set_model },
597 { MTAB_XTD|MTAB_VDV, MOD_1123P, NULL, "11/23+", &cpu_set_model },
598 { MTAB_XTD|MTAB_VDV, MOD_1124, NULL, "11/24", &cpu_set_model },
599 { MTAB_XTD|MTAB_VDV, MOD_1134, NULL, "11/34", &cpu_set_model },
600 { MTAB_XTD|MTAB_VDV, MOD_1140, NULL, "11/40", &cpu_set_model },
601 { MTAB_XTD|MTAB_VDV, MOD_1144, NULL, "11/44", &cpu_set_model },
602 { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "11/45", &cpu_set_model },
603 { MTAB_XTD|MTAB_VDV, MOD_1153, NULL, "11/53", &cpu_set_model },
604 { MTAB_XTD|MTAB_VDV, MOD_1160, NULL, "11/60", &cpu_set_model },
605 { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "11/70", &cpu_set_model },
606 { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "11/73", &cpu_set_model },
607 { MTAB_XTD|MTAB_VDV, MOD_1173B, NULL, "11/73B", &cpu_set_model },
608 { MTAB_XTD|MTAB_VDV, MOD_1183, NULL, "11/83", &cpu_set_model },
609 { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "11/84", &cpu_set_model },
610 { MTAB_XTD|MTAB_VDV, MOD_1193, NULL, "11/93", &cpu_set_model },
611 { MTAB_XTD|MTAB_VDV, MOD_1194, NULL, "11/94", &cpu_set_model },
612 { MTAB_XTD|MTAB_VDV, MOD_1173, NULL, "Q22", &cpu_set_model },
613 { MTAB_XTD|MTAB_VDV, MOD_1184, NULL, "URH11", &cpu_set_model },
614 { MTAB_XTD|MTAB_VDV, MOD_1170, NULL, "URH70", &cpu_set_model },
615 { MTAB_XTD|MTAB_VDV, MOD_1145, NULL, "U18", &cpu_set_model },
616 { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "EIS", &cpu_set_opt },
617 { MTAB_XTD|MTAB_VDV, OPT_EIS, NULL, "NOEIS", &cpu_clr_opt },
618 { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "FIS", &cpu_set_opt },
619 { MTAB_XTD|MTAB_VDV, OPT_FIS, NULL, "NOFIS", &cpu_clr_opt },
620 { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "FPP", &cpu_set_opt },
621 { MTAB_XTD|MTAB_VDV, OPT_FPP, NULL, "NOFPP", &cpu_clr_opt },
622 { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "CIS", &cpu_set_opt },
623 { MTAB_XTD|MTAB_VDV, OPT_CIS, NULL, "NOCIS", &cpu_clr_opt },
624 { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "MMU", &cpu_set_opt },
625 { MTAB_XTD|MTAB_VDV, OPT_MMU, NULL, "NOMMU", &cpu_clr_opt },
Mark Pizzolato59947e82015-12-30 12:01:58 -0800626 { MTAB_XTD|MTAB_VDV, OPT_BVT, NULL, "BEVENT", &cpu_set_opt, NULL, NULL, "Enable BEVENT line (11/03, 11/23 only)" },
627 { MTAB_XTD|MTAB_VDV, OPT_BVT, NULL, "NOBEVENT", &cpu_clr_opt, NULL, NULL, "Disable BEVENT line (11/03, 11/23 only)" },
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700628 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
629 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size},
630 { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size},
631 { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size},
632 { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size},
633 { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size},
634 { UNIT_MSIZE, 196608, NULL, "192K", &cpu_set_size},
635 { UNIT_MSIZE, 262144, NULL, "256K", &cpu_set_size},
636 { UNIT_MSIZE, 393216, NULL, "384K", &cpu_set_size},
637 { UNIT_MSIZE, 524288, NULL, "512K", &cpu_set_size},
638 { UNIT_MSIZE, 786432, NULL, "768K", &cpu_set_size},
639 { UNIT_MSIZE, 1048576, NULL, "1024K", &cpu_set_size},
Mark Pizzolato7c9cebf2013-01-01 10:29:36 -0800640 { UNIT_MSIZE, 1572864, NULL, "1536K", &cpu_set_size},
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700641 { UNIT_MSIZE, 2097152, NULL, "2048K", &cpu_set_size},
642 { UNIT_MSIZE, 3145728, NULL, "3072K", &cpu_set_size},
643 { UNIT_MSIZE, 4186112, NULL, "4096K", &cpu_set_size},
644 { UNIT_MSIZE, 1048576, NULL, "1M", &cpu_set_size},
645 { UNIT_MSIZE, 2097152, NULL, "2M", &cpu_set_size},
646 { UNIT_MSIZE, 3145728, NULL, "3M", &cpu_set_size},
647 { UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size},
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700648 { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG",
649 &set_autocon, &show_autocon },
650 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG",
651 &set_autocon, NULL },
Paul Koning998cf5c2017-02-04 12:19:41 -0800652#else
653 { MTAB_XTD|MTAB_VDV, MOD_1104, NULL, "11/04", &cpu_set_model },
654 { MTAB_XTD|MTAB_VDV, MOD_1105, NULL, "11/05", &cpu_set_model },
655 { MTAB_XTD|MTAB_VDV, MOD_1120, NULL, "11/20", &cpu_set_model },
656 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
657 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size},
658 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size},
659#endif
660 { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
661 NULL, &show_iospace },
662 { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
663 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
Bob Supnikdc871fa2006-05-27 11:34:00 -0700664 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
665 &cpu_set_hist, &cpu_show_hist },
666 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL,
667 NULL, &cpu_show_virt },
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700668 { 0 }
669 };
Bob Supnik9af6fd22001-11-06 20:44:00 -0800670
Paul Koning89ffed42016-09-13 15:22:35 -0400671BRKTYPTAB cpu_breakpoints [] = {
672 BRKTYPE('E',"Execute Instruction at Virtual Address"),
673 BRKTYPE('P',"Execute Instruction at Physical Address"),
674 BRKTYPE('R',"Read from Virtual Address"),
675 BRKTYPE('S',"Read from Physical Address"),
676 BRKTYPE('W',"Write to Virtual Address"),
677 BRKTYPE('X',"Write to Physical Address"),
678 { 0 }
679 };
680
Mark Pizzolatocf1e7b92016-10-06 13:25:54 -0700681DEVICE cpu_dev = {
682 "CPU", &cpu_unit, cpu_reg, cpu_mod,
683 1, 8, 22, 2, 8, 16,
684 &cpu_ex, &cpu_dep, &cpu_reset,
685 NULL, NULL, NULL,
686 NULL, DEV_DYNM, 0,
687 NULL, &cpu_set_size, NULL,
688 NULL, NULL, NULL, NULL,
689 cpu_breakpoints
690 };
691
Mark Pizzolato3519c6c2013-11-17 08:55:29 -0800692t_value pdp11_pc_value (void)
693{
694return (t_value)PC;
695}
696
Bob Supnik9af6fd22001-11-06 20:44:00 -0800697t_stat sim_instr (void)
698{
Bob Supnik701f0fe2001-12-26 09:38:00 -0800699int abortval, i;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700700volatile int32 trapea; /* used by setjmp */
Mark Pizzolato0352e0f2016-08-25 14:27:02 -0700701InstHistory *hst_ent = NULL;
Bob Supnik9af6fd22001-11-06 20:44:00 -0800702
Mark Pizzolato3519c6c2013-11-17 08:55:29 -0800703sim_vm_pc_value = &pdp11_pc_value;
704
Bob Supnik9af6fd22001-11-06 20:44:00 -0800705/* Restore register state
706
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700707 1. PSW components
708 2. Active register file based on PSW<rs>
709 3. Active stack pointer based on PSW<cm>
710 4. Memory management control flags
711 5. Interrupt system
Bob Supnik9af6fd22001-11-06 20:44:00 -0800712*/
713
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700714reason = build_dib_tab (); /* build, chk dib_tab */
Bob Supnik9c4779c2009-02-08 09:06:00 -0800715if (reason != SCPE_OK)
716 return reason;
Paul Koning998cf5c2017-02-04 12:19:41 -0800717if (MEMSIZE >= (cpu_tab[cpu_model].maxm - IOPAGESIZE)) /* mem size >= max - io page? */
718 MEMSIZE = cpu_tab[cpu_model].maxm - IOPAGESIZE; /* max - io page */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700719cpu_type = 1u << cpu_model; /* reset type mask */
720cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM); /* map enabled? */
Bob Supnikb6393b32004-11-23 15:49:00 -0800721PC = saved_PC;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700722put_PSW (PSW, 0); /* set PSW, call calc_xs */
Bob Supnik9c4779c2009-02-08 09:06:00 -0800723for (i = 0; i < 6; i++)
724 R[i] = REGFILE[i][rs];
Bob Supnik9af6fd22001-11-06 20:44:00 -0800725SP = STACKFILE[cm];
Bob Supnik9af6fd22001-11-06 20:44:00 -0800726isenable = calc_is (cm);
727dsenable = calc_ds (cm);
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700728put_PIRQ (PIRQ); /* rewrite PIRQ */
729STKLIM = STKLIM & STKLIM_RW; /* clean up STKLIM */
730MMR0 = MMR0 | MMR0_IC; /* usually on */
Bob Supnik9af6fd22001-11-06 20:44:00 -0800731
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700732trap_req = calc_ints (ipl, trap_req); /* upd int req */
Bob Supnik9af6fd22001-11-06 20:44:00 -0800733trapea = 0;
734reason = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700735
Bob Supnik9af6fd22001-11-06 20:44:00 -0800736/* Abort handling
737
738 If an abort occurs in memory management or memory access, the lower
739 level routine executes a longjmp to this area OUTSIDE the main
740 simulation loop. The longjmp specifies a trap mask which is OR'd
741 into the trap_req register. Simulation then resumes at the fetch
742 phase, and the trap is sprung.
743
744 Aborts which occur within a trap sequence (trapea != 0) require
745 special handling. If the abort occured on the stack pushes, and
746 the mode (encoded in trapea) is kernel, an "emergency" kernel
747 stack is created at 4, and a red zone stack trap taken.
Bob Supnikdf647512002-07-14 15:20:00 -0700748
749 All variables used in setjmp processing, or assumed to be valid
750 after setjmp, must be volatile or global.
Bob Supnik9af6fd22001-11-06 20:44:00 -0800751*/
752
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700753abortval = setjmp (save_env); /* set abort hdlr */
Paul Koning89ffed42016-09-13 15:22:35 -0400754if (abortval == ABRT_BKPT) {
755 /* Breakpoint encountered. */
756 reason = STOP_IBKPT;
757 /* Print a message reporting the type and address if it is not a
758 plain virtual PC (instruction execution) breakpoint. */
759 if (sim_brk_match_type != BPT_PCVIR)
760 sim_messagef (reason, "\r\n%s", sim_brk_message());
761 /* Restore the PC and sim_interval. */
762 PC = inst_pc;
763 sim_interval = saved_sim_interval;
764 /* Restore PSW and the broken-out condition code values, provided
765 FPD is not currently set. If it is, that means the instruction
766 is interruptible and breakpoints are treated as continuation
767 rather than replay. */
768 if (!fpd) {
769 PSW = inst_psw;
770 put_PSW (inst_psw, 0);
771 }
772 /* Undo register changes. */
773 while (reg_mods) {
774 int rnum = reg_mods & 7;
775 int delta = (reg_mods >> 3) & 037;
776 reg_mods >>= 8;
777 if (delta & 020) /* negative delta */
778 delta = -(-delta & 037); /* get signed value */
779 if (rnum != 7)
780 R[rnum] -= delta;
781 }
782 }
783else {
784 if (abortval != 0) {
785 trap_req = trap_req | abortval; /* or in trap flag */
786 if ((trapea > 0) && stop_vecabort)
787 reason = STOP_VECABORT;
788 if ((trapea < 0) && /* stack push abort? */
789 (CPUT (STOP_STKA) || stop_spabort))
790 reason = STOP_SPABORT;
791 if (trapea == ~MD_KER) { /* kernel stk abort? */
792 setTRAP (TRAP_RED);
793 setCPUERR (CPUE_RED);
794 STACKFILE[MD_KER] = 4;
795 if (cm == MD_KER)
796 SP = 4;
797 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700798 }
799 }
Bob Supnik9af6fd22001-11-06 20:44:00 -0800800
801/* Main instruction fetch/decode loop
802
803 Check for traps or interrupts. If trap, locate the vector and check
804 for stop condition. If interrupt, locate the vector.
805*/
806
807while (reason == 0) {
Bob Supnik701f0fe2001-12-26 09:38:00 -0800808
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700809 int32 IR, srcspec, srcreg, dstspec, dstreg;
810 int32 src, src2, dst, ea;
811 int32 i, t, sign, oldrs, trapnum;
Bob Supnikdf647512002-07-14 15:20:00 -0700812
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700813 if (cpu_astop) {
814 cpu_astop = 0;
815 reason = SCPE_STOP;
816 break;
Mark Pizzolato4064cc02013-06-02 06:52:32 -0700817 }
Bob Supnik701f0fe2001-12-26 09:38:00 -0800818
Mark Pizzolato97de4db2013-01-29 04:35:30 -0800819 AIO_CHECK_EVENT;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700820 if (sim_interval <= 0) { /* intv cnt expired? */
Mark Pizzolato611a7e92014-10-26 15:15:31 -0700821 /* Make sure all intermediate state is visible in simh registers */
822 PSW = get_PSW ();
823 for (i = 0; i < 6; i++)
824 REGFILE[i][rs] = R[i];
825 STACKFILE[cm] = SP;
826 saved_PC = PC & 0177777;
827 pcq_r->qptr = pcq_p; /* update pc q ptr */
828 set_r_display (rs, cm);
Mark Pizzolato235ce922014-10-28 10:19:39 -0700829
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700830 reason = sim_process_event (); /* process events */
Mark Pizzolato235ce922014-10-28 10:19:39 -0700831
832 /* restore simh register contents into running variables */
833 PC = saved_PC;
834 put_PSW (PSW, 0); /* set PSW, call calc_xs */
835 for (i = 0; i < 6; i++)
836 R[i] = REGFILE[i][rs];
837 SP = STACKFILE[cm];
838 isenable = calc_is (cm);
839 dsenable = calc_ds (cm);
840 put_PIRQ (PIRQ); /* rewrite PIRQ */
841 STKLIM = STKLIM & STKLIM_RW; /* clean up STKLIM */
842 MMR0 = MMR0 | MMR0_IC; /* usually on */
843
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700844 trap_req = calc_ints (ipl, trap_req); /* recalc int req */
845 continue;
846 } /* end if sim_interval */
Bob Supnik701f0fe2001-12-26 09:38:00 -0800847
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700848 if (trap_req) { /* check traps, ints */
849 trapea = 0; /* assume srch fails */
Mark Pizzolato0f8e6cf2012-04-29 11:59:44 -0700850 if ((t = trap_req & TRAP_ALL)) { /* if a trap */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700851 for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) {
852 if ((t >> trapnum) & 1) { /* trap set? */
853 trapea = trap_vec[trapnum]; /* get vec, clr */
854 trap_req = trap_req & ~trap_clear[trapnum];
855 if ((stop_trap >> trapnum) & 1) /* stop on trap? */
856 reason = trapnum + 1;
857 break;
858 } /* end if t & 1 */
859 } /* end for */
860 } /* end if t */
861 else {
862 trapea = get_vector (ipl); /* get int vector */
863 trapnum = TRAP_V_MAX; /* defang stk trap */
864 } /* end else t */
865 if (trapea == 0) { /* nothing to do? */
866 trap_req = calc_ints (ipl, 0); /* recalculate */
867 continue; /* back to fetch */
868 } /* end if trapea */
869
Bob Supnik9af6fd22001-11-06 20:44:00 -0800870/* Process a trap or interrupt
871
872 1. Exit wait state
873 2. Save the current SP and PSW
874 3. Read the new PC, new PSW from trapea, kernel data space
875 4. Get the mode and stack selected by the new PSW
876 5. Push the old PC and PSW on the new stack
877 6. Update SP, PSW, and PC
878 7. If not stack overflow, check for stack overflow
Paul Koning89ffed42016-09-13 15:22:35 -0400879
880 If the reads in step 3, or the writes in step 5, match a data breakpoint,
881 the breakpoint status will be set but the interrupt actions will continue.
882 The breakpoint stop will occur at the beginning of the next instruction
883 cycle.
Bob Supnik9af6fd22001-11-06 20:44:00 -0800884*/
885
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700886 wait_state = 0; /* exit wait state */
887 STACKFILE[cm] = SP;
888 PSW = get_PSW (); /* assemble PSW */
889 oldrs = rs;
890 if (CPUT (HAS_MMTR)) { /* 45,70? */
Bob Supnik9c4779c2009-02-08 09:06:00 -0800891 if (update_MM) /* save vector */
892 MMR2 = trapea;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700893 MMR0 = MMR0 & ~MMR0_IC; /* clear IC */
894 }
Paul Koning89ffed42016-09-13 15:22:35 -0400895 src = ReadCW (trapea | calc_ds (MD_KER)); /* new PC */
896 src2 = ReadCW ((trapea + 2) | calc_ds (MD_KER)); /* new PSW */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700897 t = (src2 >> PSW_V_CM) & 03; /* new cm */
898 trapea = ~t; /* flag pushes */
Paul Koning89ffed42016-09-13 15:22:35 -0400899 WriteCW (PSW, ((STACKFILE[t] - 2) & 0177777) | calc_ds (t));
900 WriteCW (PC, ((STACKFILE[t] - 4) & 0177777) | calc_ds (t));
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700901 trapea = 0; /* clear trap flag */
902 src2 = (src2 & ~PSW_PM) | (cm << PSW_V_PM); /* insert prv mode */
903 put_PSW (src2, 0); /* call calc_is,ds */
904 if (rs != oldrs) { /* if rs chg, swap */
905 for (i = 0; i < 6; i++) {
906 REGFILE[i][oldrs] = R[i];
907 R[i] = REGFILE[i][rs];
908 }
909 }
910 SP = (STACKFILE[cm] - 4) & 0177777; /* update SP, PC */
911 isenable = calc_is (cm);
912 dsenable = calc_ds (cm);
913 trap_req = calc_ints (ipl, trap_req);
914 JMP_PC (src);
915 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)) &&
916 (trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL))
917 set_stack_trap (SP);
918 MMR0 = MMR0 | MMR0_IC; /* back to instr */
919 continue; /* end if traps */
920 }
921
Bob Supnik9af6fd22001-11-06 20:44:00 -0800922/* Fetch and decode next instruction */
923
Bob Supnik9c4779c2009-02-08 09:06:00 -0800924 if (tbit)
925 setTRAP (TRAP_TRC);
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700926 if (wait_state) { /* wait state? */
Mark Pizzolato7256e092014-12-19 08:45:47 -0800927 sim_idle (TMR_CLK, TRUE);
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700928 continue;
929 }
Bob Supnik9af6fd22001-11-06 20:44:00 -0800930
Paul Koning89ffed42016-09-13 15:22:35 -0400931 reg_mods = 0;
932 inst_pc = PC;
933 /* Save PSW also because condition codes need to be preserved.
934 We just save the whole PSW because that is sufficient (that
935 representation is up to date at this point). If restoring is
936 needed, both the PSW and the components that need to be restored
937 are handled explicitly. */
938 inst_psw = PSW;
939 saved_sim_interval = sim_interval;
940 if (BPT_SUMM_PC) { /* possible breakpoint */
941 t_addr pa = relocR (PC | isenable); /* relocate PC */
942 if (sim_brk_test (PC, BPT_PCVIR) || /* Normal PC breakpoint? */
943 sim_brk_test (pa, BPT_PCPHY)) /* Physical Address breakpoint? */
944 ABORT (ABRT_BKPT); /* stop simulation */
Mark Pizzolato4064cc02013-06-02 06:52:32 -0700945 }
Bob Supnik9af6fd22001-11-06 20:44:00 -0800946
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700947 if (update_MM) { /* if mm not frozen */
948 MMR1 = 0;
949 MMR2 = PC;
950 }
951 IR = ReadE (PC | isenable); /* fetch instruction */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700952 sim_interval = sim_interval - 1;
953 srcspec = (IR >> 6) & 077; /* src, dst specs */
954 dstspec = IR & 077;
955 srcreg = (srcspec <= 07); /* src, dst = rmode? */
956 dstreg = (dstspec <= 07);
Bob Supnikdc871fa2006-05-27 11:34:00 -0700957 if (hst_lnt) { /* record history? */
958 t_value val;
959 uint32 i;
Mark Pizzolato71e745b2016-03-06 06:27:15 -0800960 static int32 swmap[4] = {
961 SWMASK ('K') | SWMASK ('V'), SWMASK ('S') | SWMASK ('V'),
962 SWMASK ('U') | SWMASK ('V'), SWMASK ('U') | SWMASK ('V')
963 };
Paul Koning66fb70b2016-04-07 15:21:59 -0400964 hst_ent = &hst[hst_p];
965 hst_ent->pc = PC | HIST_VLD;
966 hst_ent->psw = get_PSW ();
967 hst_ent->src = 0;
968 hst_ent->dst = 0;
969 hst_ent->inst[0] = IR;
Bob Supnikdc871fa2006-05-27 11:34:00 -0700970 for (i = 1; i < HIST_ILNT; i++) {
Mark Pizzolato71e745b2016-03-06 06:27:15 -0800971 if (cpu_ex (&val, (PC + (i << 1)) & 0177777, &cpu_unit, swmap[cm & 03]))
Paul Koning66fb70b2016-04-07 15:21:59 -0400972 hst_ent->inst[i] = 0;
973 else hst_ent->inst[i] = (uint16) val;
Bob Supnikdc871fa2006-05-27 11:34:00 -0700974 }
975 hst_p = (hst_p + 1);
Bob Supnik9c4779c2009-02-08 09:06:00 -0800976 if (hst_p >= hst_lnt)
977 hst_p = 0;
Bob Supnikdc871fa2006-05-27 11:34:00 -0700978 }
979 PC = (PC + 2) & 0177777; /* incr PC, mod 65k */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700980 switch ((IR >> 12) & 017) { /* decode IR<15:12> */
981
Bob Supnik9af6fd22001-11-06 20:44:00 -0800982/* Opcode 0: no operands, specials, branches, JSR, SOPs */
983
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700984 case 000:
985 switch ((IR >> 6) & 077) { /* decode IR<11:6> */
986 case 000: /* no operand */
987 if (IR >= 000010) { /* 000010 - 000077 */
988 setTRAP (TRAP_ILL); /* illegal */
989 break;
990 }
991 switch (IR) { /* decode IR<2:0> */
992 case 0: /* HALT */
993 if ((cm == MD_KER) &&
994 (!CPUT (CPUT_J) || ((MAINT & MAINT_HTRAP) == 0)))
995 reason = STOP_HALT;
996 else if (CPUT (HAS_HALT4)) { /* priv trap? */
997 setTRAP (TRAP_PRV);
998 setCPUERR (CPUE_HALT);
999 }
1000 else setTRAP (TRAP_ILL); /* no, ill inst */
1001 break;
1002 case 1: /* WAIT */
Bob Supnik53d02f72007-02-03 14:59:00 -08001003 wait_state = 1;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001004 break;
1005 case 3: /* BPT */
1006 setTRAP (TRAP_BPT);
1007 break;
1008 case 4: /* IOT */
1009 setTRAP (TRAP_IOT);
1010 break;
1011 case 5: /* RESET */
1012 if (cm == MD_KER) {
1013 reset_all (2); /* skip CPU, sys reg */
Bob Supnik59aa4a72008-06-24 14:21:00 -07001014 PIRQ = 0; /* clear PIRQ */
1015 STKLIM = 0; /* clear STKLIM */
1016 MMR0 = 0; /* clear MMR0 */
1017 MMR3 = 0; /* clear MMR3 */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001018 cpu_bme = 0; /* (also clear bme) */
1019 for (i = 0; i < IPL_HLVL; i++)
1020 int_req[i] = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001021 trap_req = trap_req & ~TRAP_INT;
1022 dsenable = calc_ds (cm);
1023 }
1024 break;
1025 case 6: /* RTT */
1026 if (!CPUT (HAS_RTT)) {
1027 setTRAP (TRAP_ILL);
1028 break;
1029 }
1030 case 2: /* RTI */
1031 src = ReadW (SP | dsenable);
1032 src2 = ReadW (((SP + 2) & 0177777) | dsenable);
1033 STACKFILE[cm] = SP = (SP + 4) & 0177777;
1034 oldrs = rs;
1035 put_PSW (src2, (cm != MD_KER)); /* store PSW, prot */
1036 if (rs != oldrs) {
1037 for (i = 0; i < 6; i++) {
1038 REGFILE[i][oldrs] = R[i];
1039 R[i] = REGFILE[i][rs];
1040 }
1041 }
1042 SP = STACKFILE[cm];
1043 isenable = calc_is (cm);
1044 dsenable = calc_ds (cm);
1045 trap_req = calc_ints (ipl, trap_req);
1046 JMP_PC (src);
1047 if (CPUT (HAS_RTT) && tbit && /* RTT impl? */
Mark Pizzolato4064cc02013-06-02 06:52:32 -07001048 (IR == 000002))
1049 setTRAP (TRAP_TRC); /* RTI immed trap */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001050 break;
1051 case 7: /* MFPT */
1052 if (CPUT (HAS_MFPT)) /* implemented? */
1053 R[0] = cpu_tab[cpu_model].mfpt; /* get type */
1054 else setTRAP (TRAP_ILL);
1055 break;
1056 } /* end switch no ops */
1057 break; /* end case no ops */
Bob Supnik9af6fd22001-11-06 20:44:00 -08001058
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001059 case 001: /* JMP */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001060 if (dstreg)
1061 setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001062 else {
1063 dst = GeteaW (dstspec) & 0177777; /* get eff addr */
1064 if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */
1065 ((dstspec & 070) == 020)) /* JMP (R)+? */
1066 dst = R[dstspec & 07]; /* use post incr */
Paul Koning66fb70b2016-04-07 15:21:59 -04001067 if (hst_ent)
1068 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001069 JMP_PC (dst);
1070 }
1071 break; /* end JMP */
Bob Supnik9af6fd22001-11-06 20:44:00 -08001072
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001073 case 002: /* RTS et al*/
1074 if (IR < 000210) { /* RTS */
1075 dstspec = dstspec & 07;
Paul Koning66fb70b2016-04-07 15:21:59 -04001076 if (hst_ent)
1077 hst_ent->dst = R[dstspec];
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001078 JMP_PC (R[dstspec]);
1079 R[dstspec] = ReadW (SP | dsenable);
Bob Supnik9c4779c2009-02-08 09:06:00 -08001080 if (dstspec != 6)
1081 SP = (SP + 2) & 0177777;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001082 break;
1083 } /* end if RTS */
1084 if (IR < 000230) {
1085 setTRAP (TRAP_ILL);
1086 break;
1087 }
1088 if (IR < 000240) { /* SPL */
1089 if (CPUT (HAS_SPL)) {
Bob Supnik9c4779c2009-02-08 09:06:00 -08001090 if (cm == MD_KER)
1091 ipl = IR & 07;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001092 trap_req = calc_ints (ipl, trap_req);
1093 }
1094 else setTRAP (TRAP_ILL);
1095 break;
1096 } /* end if SPL */
1097 if (IR < 000260) { /* clear CC */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001098 if (IR & 010)
1099 N = 0;
1100 if (IR & 004)
1101 Z = 0;
1102 if (IR & 002)
1103 V = 0;
1104 if (IR & 001)
1105 C = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001106 break;
1107 } /* end if clear CCs */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001108 if (IR & 010) /* set CC */
1109 N = 1;
1110 if (IR & 004)
1111 Z = 1;
1112 if (IR & 002)
1113 V = 1;
1114 if (IR & 001)
1115 C = 1;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001116 break; /* end case RTS et al */
Bob Supnik9af6fd22001-11-06 20:44:00 -08001117
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001118 case 003: /* SWAB */
1119 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1120 dst = ((dst & 0377) << 8) | ((dst >> 8) & 0377);
1121 N = GET_SIGN_B (dst & 0377);
1122 Z = GET_Z (dst & 0377);
Bob Supnik9c4779c2009-02-08 09:06:00 -08001123 if (!CPUT (CPUT_20))
1124 V = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001125 C = 0;
Paul Koning66fb70b2016-04-07 15:21:59 -04001126 if (hst_ent)
1127 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001128 if (dstreg)
1129 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001130 else PWriteW (dst, last_pa);
1131 break; /* end SWAB */
Bob Supnik9af6fd22001-11-06 20:44:00 -08001132
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001133 case 004: case 005: /* BR */
1134 BRANCH_F (IR);
1135 break;
Bob Supnik9af6fd22001-11-06 20:44:00 -08001136
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001137 case 006: case 007: /* BR */
1138 BRANCH_B (IR);
1139 break;
Bob Supnik9af6fd22001-11-06 20:44:00 -08001140
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001141 case 010: case 011: /* BNE */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001142 if (Z == 0) {
1143 BRANCH_F (IR);
1144 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001145 break;
1146
1147 case 012: case 013: /* BNE */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001148 if (Z == 0) {
1149 BRANCH_B (IR);
1150 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001151 break;
1152
1153 case 014: case 015: /* BEQ */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001154 if (Z) {
1155 BRANCH_F (IR);
1156 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001157 break;
1158
1159 case 016: case 017: /* BEQ */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001160 if (Z) {
1161 BRANCH_B (IR);
1162 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001163 break;
1164
1165 case 020: case 021: /* BGE */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001166 if ((N ^ V) == 0) {
1167 BRANCH_F (IR);
1168 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001169 break;
1170
1171 case 022: case 023: /* BGE */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001172 if ((N ^ V) == 0) {
1173 BRANCH_B (IR);
1174 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001175 break;
1176
1177 case 024: case 025: /* BLT */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001178 if (N ^ V) {
1179 BRANCH_F (IR);
1180 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001181 break;
1182
1183 case 026: case 027: /* BLT */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001184 if (N ^ V) {
1185 BRANCH_B (IR);
1186 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001187 break;
1188
1189 case 030: case 031: /* BGT */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001190 if ((Z | (N ^ V)) == 0) {
1191 BRANCH_F (IR);
1192 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001193 break;
1194
1195 case 032: case 033: /* BGT */
1196 if ((Z | (N ^ V)) == 0) { BRANCH_B (IR); }
1197 break;
1198
1199 case 034: case 035: /* BLE */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001200 if (Z | (N ^ V)) {
1201 BRANCH_F (IR);
1202 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001203 break;
1204
1205 case 036: case 037: /* BLE */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001206 if (Z | (N ^ V)) {
1207 BRANCH_B (IR);
1208 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001209 break;
1210
1211 case 040: case 041: case 042: case 043: /* JSR */
1212 case 044: case 045: case 046: case 047:
Bob Supnik9c4779c2009-02-08 09:06:00 -08001213 if (dstreg)
1214 setTRAP (CPUT (HAS_JREG4)? TRAP_PRV: TRAP_ILL);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001215 else {
1216 srcspec = srcspec & 07;
1217 dst = GeteaW (dstspec);
1218 if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */
1219 ((dstspec & 070) == 020)) /* JSR (R)+? */
1220 dst = R[dstspec & 07]; /* use post incr */
1221 SP = (SP - 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04001222 reg_mods = calc_MMR1 (0366);
Bob Supnik9c4779c2009-02-08 09:06:00 -08001223 if (update_MM)
Paul Koning89ffed42016-09-13 15:22:35 -04001224 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001225 WriteW (R[srcspec], SP | dsenable);
1226 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
1227 set_stack_trap (SP);
1228 R[srcspec] = PC;
Paul Koning66fb70b2016-04-07 15:21:59 -04001229 if (hst_ent)
1230 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001231 JMP_PC (dst & 0177777);
1232 }
1233 break; /* end JSR */
1234
1235 case 050: /* CLR */
1236 N = V = C = 0;
1237 Z = 1;
Paul Koning66fb70b2016-04-07 15:21:59 -04001238 if (hst_ent)
1239 hst_ent->dst = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001240 if (dstreg)
1241 R[dstspec] = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001242 else WriteW (0, GeteaW (dstspec));
1243 break;
1244
1245 case 051: /* COM */
1246 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1247 dst = dst ^ 0177777;
1248 N = GET_SIGN_W (dst);
1249 Z = GET_Z (dst);
1250 V = 0;
1251 C = 1;
Paul Koning66fb70b2016-04-07 15:21:59 -04001252 if (hst_ent)
1253 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001254 if (dstreg)
1255 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001256 else PWriteW (dst, last_pa);
1257 break;
1258
1259 case 052: /* INC */
1260 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1261 dst = (dst + 1) & 0177777;
1262 N = GET_SIGN_W (dst);
1263 Z = GET_Z (dst);
1264 V = (dst == 0100000);
Paul Koning66fb70b2016-04-07 15:21:59 -04001265 if (hst_ent)
1266 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001267 if (dstreg)
1268 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001269 else PWriteW (dst, last_pa);
1270 break;
1271
1272 case 053: /* DEC */
1273 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1274 dst = (dst - 1) & 0177777;
1275 N = GET_SIGN_W (dst);
1276 Z = GET_Z (dst);
1277 V = (dst == 077777);
Paul Koning66fb70b2016-04-07 15:21:59 -04001278 if (hst_ent)
1279 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001280 if (dstreg)
1281 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001282 else PWriteW (dst, last_pa);
1283 break;
1284
1285 case 054: /* NEG */
1286 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1287 dst = (-dst) & 0177777;
1288 N = GET_SIGN_W (dst);
1289 Z = GET_Z (dst);
1290 V = (dst == 0100000);
1291 C = Z ^ 1;
Paul Koning66fb70b2016-04-07 15:21:59 -04001292 if (hst_ent)
1293 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001294 if (dstreg)
1295 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001296 else PWriteW (dst, last_pa);
1297 break;
1298
1299 case 055: /* ADC */
1300 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1301 dst = (dst + C) & 0177777;
1302 N = GET_SIGN_W (dst);
1303 Z = GET_Z (dst);
1304 V = (C && (dst == 0100000));
1305 C = C & Z;
Paul Koning66fb70b2016-04-07 15:21:59 -04001306 if (hst_ent)
1307 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001308 if (dstreg)
1309 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001310 else PWriteW (dst, last_pa);
1311 break;
1312
1313 case 056: /* SBC */
1314 dst = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1315 dst = (dst - C) & 0177777;
1316 N = GET_SIGN_W (dst);
1317 Z = GET_Z (dst);
1318 V = (C && (dst == 077777));
1319 C = (C && (dst == 0177777));
Paul Koning66fb70b2016-04-07 15:21:59 -04001320 if (hst_ent)
1321 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001322 if (dstreg)
1323 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001324 else PWriteW (dst, last_pa);
1325 break;
1326
1327 case 057: /* TST */
1328 dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
Paul Koning66fb70b2016-04-07 15:21:59 -04001329 if (hst_ent)
1330 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001331 N = GET_SIGN_W (dst);
1332 Z = GET_Z (dst);
1333 V = C = 0;
1334 break;
1335
1336 case 060: /* ROR */
1337 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1338 dst = (src >> 1) | (C << 15);
1339 N = GET_SIGN_W (dst);
1340 Z = GET_Z (dst);
1341 C = (src & 1);
1342 V = N ^ C;
Paul Koning66fb70b2016-04-07 15:21:59 -04001343 if (hst_ent)
1344 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001345 if (dstreg)
1346 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001347 else PWriteW (dst, last_pa);
1348 break;
1349
1350 case 061: /* ROL */
1351 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1352 dst = ((src << 1) | C) & 0177777;
1353 N = GET_SIGN_W (dst);
1354 Z = GET_Z (dst);
1355 C = GET_SIGN_W (src);
1356 V = N ^ C;
Paul Koning66fb70b2016-04-07 15:21:59 -04001357 if (hst_ent)
1358 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001359 if (dstreg)
1360 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001361 else PWriteW (dst, last_pa);
1362 break;
1363
1364 case 062: /* ASR */
1365 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1366 dst = (src >> 1) | (src & 0100000);
1367 N = GET_SIGN_W (dst);
1368 Z = GET_Z (dst);
1369 C = (src & 1);
1370 V = N ^ C;
Paul Koning66fb70b2016-04-07 15:21:59 -04001371 if (hst_ent)
1372 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001373 if (dstreg)
1374 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001375 else PWriteW (dst, last_pa);
1376 break;
1377
1378 case 063: /* ASL */
1379 src = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1380 dst = (src << 1) & 0177777;
1381 N = GET_SIGN_W (dst);
1382 Z = GET_Z (dst);
1383 C = GET_SIGN_W (src);
1384 V = N ^ C;
Paul Koning66fb70b2016-04-07 15:21:59 -04001385 if (hst_ent)
1386 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001387 if (dstreg)
1388 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001389 else PWriteW (dst, last_pa);
1390 break;
1391
1392/* Notes:
Bob Supnik9af6fd22001-11-06 20:44:00 -08001393 - MxPI must mask GeteaW returned address to force ispace
1394 - MxPI must set MMR1 for SP recovery in case of fault
1395*/
1396
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001397 case 064: /* MARK */
1398 if (CPUT (HAS_MARK)) {
1399 i = (PC + dstspec + dstspec) & 0177777;
1400 JMP_PC (R[5]);
1401 R[5] = ReadW (i | dsenable);
1402 SP = (i + 2) & 0177777;
1403 }
1404 else setTRAP (TRAP_ILL);
1405 break;
Bob Supnik9af6fd22001-11-06 20:44:00 -08001406
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001407 case 065: /* MFPI */
1408 if (CPUT (HAS_MXPY)) {
1409 if (dstreg) {
Bob Supnik9c4779c2009-02-08 09:06:00 -08001410 if ((dstspec == 6) && (cm != pm))
1411 dst = STACKFILE[pm];
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001412 else dst = R[dstspec];
1413 }
1414 else {
Mark Pizzolatoc71e0c32012-12-13 15:21:07 -08001415 i = ((cm == pm) && (cm == MD_USR))? (int32)calc_ds (pm): (int32)calc_is (pm);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001416 dst = ReadW ((GeteaW (dstspec) & 0177777) | i);
1417 }
1418 N = GET_SIGN_W (dst);
1419 Z = GET_Z (dst);
1420 V = 0;
1421 SP = (SP - 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04001422 reg_mods = calc_MMR1 (0366);
Bob Supnik9c4779c2009-02-08 09:06:00 -08001423 if (update_MM)
Paul Koning89ffed42016-09-13 15:22:35 -04001424 MMR1 = reg_mods;
Paul Koning66fb70b2016-04-07 15:21:59 -04001425 if (hst_ent)
1426 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001427 WriteW (dst, SP | dsenable);
1428 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
1429 set_stack_trap (SP);
1430 }
1431 else setTRAP (TRAP_ILL);
1432 break;
1433
1434 case 066: /* MTPI */
1435 if (CPUT (HAS_MXPY)) {
1436 dst = ReadW (SP | dsenable);
1437 N = GET_SIGN_W (dst);
1438 Z = GET_Z (dst);
1439 V = 0;
1440 SP = (SP + 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04001441 reg_mods = 026;
1442 if (update_MM) MMR1 = reg_mods;
Paul Koning66fb70b2016-04-07 15:21:59 -04001443 if (hst_ent)
1444 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001445 if (dstreg) {
Bob Supnik9c4779c2009-02-08 09:06:00 -08001446 if ((dstspec == 6) && (cm != pm))
1447 STACKFILE[pm] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001448 else R[dstspec] = dst;
1449 }
1450 else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_is (pm));
1451 }
1452 else setTRAP (TRAP_ILL);
1453 break;
1454
1455 case 067: /* SXT */
1456 if (CPUT (HAS_SXS)) {
1457 dst = N? 0177777: 0;
1458 Z = N ^ 1;
1459 V = 0;
Paul Koning66fb70b2016-04-07 15:21:59 -04001460 if (hst_ent)
1461 hst_ent->dst = dst;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001462 if (dstreg)
1463 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001464 else WriteW (dst, GeteaW (dstspec));
1465 }
1466 else setTRAP (TRAP_ILL);
1467 break;
1468
1469 case 070: /* CSM */
Mark Pizzolato2daa41e2013-12-06 10:54:56 -08001470 if (CPUT (HAS_CSM) && (MMR3 & MMR3_CSM) && (cm != MD_KER)) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001471 dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
1472 PSW = get_PSW () & ~PSW_CC; /* PSW, cc = 0 */
1473 STACKFILE[cm] = SP;
1474 WriteW (PSW, ((SP - 2) & 0177777) | calc_ds (MD_SUP));
1475 WriteW (PC, ((SP - 4) & 0177777) | calc_ds (MD_SUP));
1476 WriteW (dst, ((SP - 6) & 0177777) | calc_ds (MD_SUP));
1477 SP = (SP - 6) & 0177777;
1478 pm = cm;
1479 cm = MD_SUP;
1480 tbit = 0;
1481 isenable = calc_is (cm);
1482 dsenable = calc_ds (cm);
1483 PC = ReadW (010 | isenable);
1484 }
1485 else setTRAP (TRAP_ILL);
1486 break;
1487
1488 case 072: /* TSTSET */
1489 if (CPUT (HAS_TSWLK) && !dstreg) {
1490 dst = ReadMW (GeteaW (dstspec));
1491 N = GET_SIGN_W (dst);
1492 Z = GET_Z (dst);
1493 V = 0;
1494 C = (dst & 1);
1495 R[0] = dst; /* R[0] <- dst */
Paul Koning66fb70b2016-04-07 15:21:59 -04001496 if (hst_ent)
1497 hst_ent->dst = dst | 1;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001498 PWriteW (R[0] | 1, last_pa); /* dst <- R[0] | 1 */
1499 }
1500 else setTRAP (TRAP_ILL);
1501 break;
1502
1503 case 073: /* WRTLCK */
1504 if (CPUT (HAS_TSWLK) && !dstreg) {
1505 N = GET_SIGN_W (R[0]);
1506 Z = GET_Z (R[0]);
1507 V = 0;
1508 WriteW (R[0], GeteaW (dstspec));
Paul Koning66fb70b2016-04-07 15:21:59 -04001509 if (hst_ent)
1510 hst_ent->dst = R[0];
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001511 }
1512 else setTRAP (TRAP_ILL);
1513 break;
1514
1515 default:
1516 setTRAP (TRAP_ILL);
1517 break;
1518 } /* end switch SOPs */
1519 break; /* end case 000 */
1520
Bob Supnik9af6fd22001-11-06 20:44:00 -08001521/* Opcodes 01 - 06: double operand word instructions
1522
Bob Supnikdf647512002-07-14 15:20:00 -07001523 J-11 (and F-11) optimize away register source operand decoding.
1524 As a result, dop R,+/-(R) use the modified version of R as source.
1525 Most (but not all) other PDP-11's fetch the source operand before
1526 any destination operand decoding.
1527
Bob Supnik9af6fd22001-11-06 20:44:00 -08001528 Add: v = [sign (src) = sign (src2)] and [sign (src) != sign (result)]
1529 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
1530*/
1531
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001532 case 001: /* MOV */
1533 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
1534 ea = GeteaW (dstspec);
1535 dst = R[srcspec];
1536 }
1537 else {
1538 dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
Mark Pizzolato4064cc02013-06-02 06:52:32 -07001539 if (!dstreg)
1540 ea = GeteaW (dstspec);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001541 }
1542 N = GET_SIGN_W (dst);
1543 Z = GET_Z (dst);
1544 V = 0;
Paul Koning66fb70b2016-04-07 15:21:59 -04001545 if (hst_ent) {
1546 hst_ent->src = dst;
1547 hst_ent->dst = dst;
1548 }
Bob Supnik9c4779c2009-02-08 09:06:00 -08001549 if (dstreg)
1550 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001551 else WriteW (dst, ea);
1552 break;
1553
1554 case 002: /* CMP */
1555 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
1556 src2 = ReadW (GeteaW (dstspec));
1557 src = R[srcspec];
1558 }
1559 else {
1560 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
1561 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
1562 }
1563 dst = (src - src2) & 0177777;
Paul Koning66fb70b2016-04-07 15:21:59 -04001564 if (hst_ent) {
1565 hst_ent->src = src;
1566 hst_ent->dst = src2;
1567 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001568 N = GET_SIGN_W (dst);
1569 Z = GET_Z (dst);
1570 V = GET_SIGN_W ((src ^ src2) & (~src2 ^ dst));
1571 C = (src < src2);
1572 break;
1573
1574 case 003: /* BIT */
1575 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
1576 src2 = ReadW (GeteaW (dstspec));
1577 src = R[srcspec];
1578 }
1579 else {
1580 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
1581 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
1582 }
1583 dst = src2 & src;
Paul Koning66fb70b2016-04-07 15:21:59 -04001584 if (hst_ent) {
1585 hst_ent->src = src;
1586 hst_ent->dst = dst;
1587 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001588 N = GET_SIGN_W (dst);
1589 Z = GET_Z (dst);
1590 V = 0;
1591 break;
1592
1593 case 004: /* BIC */
1594 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
1595 src2 = ReadMW (GeteaW (dstspec));
1596 src = R[srcspec];
1597 }
1598 else {
1599 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
1600 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1601 }
1602 dst = src2 & ~src;
Paul Koning66fb70b2016-04-07 15:21:59 -04001603 if (hst_ent) {
1604 hst_ent->src = src;
1605 hst_ent->dst = dst;
1606 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001607 N = GET_SIGN_W (dst);
1608 Z = GET_Z (dst);
1609 V = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001610 if (dstreg)
1611 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001612 else PWriteW (dst, last_pa);
1613 break;
1614
1615 case 005: /* BIS */
1616 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
1617 src2 = ReadMW (GeteaW (dstspec));
1618 src = R[srcspec];
1619 }
1620 else {
1621 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
1622 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1623 }
1624 dst = src2 | src;
Paul Koning66fb70b2016-04-07 15:21:59 -04001625 if (hst_ent) {
1626 hst_ent->src = src;
1627 hst_ent->dst = dst;
1628 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001629 N = GET_SIGN_W (dst);
1630 Z = GET_Z (dst);
1631 V = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001632 if (dstreg)
1633 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001634 else PWriteW (dst, last_pa);
1635 break;
1636
1637 case 006: /* ADD */
1638 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
1639 src2 = ReadMW (GeteaW (dstspec));
1640 src = R[srcspec];
1641 }
1642 else {
1643 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
1644 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1645 }
1646 dst = (src2 + src) & 0177777;
Paul Koning66fb70b2016-04-07 15:21:59 -04001647 if (hst_ent) {
1648 hst_ent->src = src;
1649 hst_ent->dst = dst;
1650 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001651 N = GET_SIGN_W (dst);
1652 Z = GET_Z (dst);
1653 V = GET_SIGN_W ((~src ^ src2) & (src ^ dst));
1654 C = (dst < src);
Bob Supnik9c4779c2009-02-08 09:06:00 -08001655 if (dstreg)
1656 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001657 else PWriteW (dst, last_pa);
1658 break;
1659
Bob Supnik53d02f72007-02-03 14:59:00 -08001660/* Opcode 07: EIS, FIS, CIS
Bob Supnik9af6fd22001-11-06 20:44:00 -08001661
1662 Notes:
1663 - The code assumes that the host int length is at least 32 bits.
1664 - MUL carry: C is set if the (signed) result doesn't fit in 16 bits.
1665 - Divide has three error cases:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001666 1. Divide by zero.
1667 2. Divide largest negative number by -1.
1668 3. (Signed) quotient doesn't fit in 16 bits.
Bob Supnik9af6fd22001-11-06 20:44:00 -08001669 Cases 1 and 2 must be tested in advance, to avoid C runtime errors.
1670 - ASHx left: overflow if the bits shifted out do not equal the sign
1671 of the result (convert shift out to 1/0, xor against sign).
1672 - ASHx right: if right shift sign extends, then the shift and
1673 conditional or of shifted -1 is redundant. If right shift zero
1674 extends, then the shift and conditional or does sign extension.
1675*/
1676
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001677 case 007:
1678 srcspec = srcspec & 07;
1679 switch ((IR >> 9) & 07) { /* decode IR<11:9> */
Bob Supnik9af6fd22001-11-06 20:44:00 -08001680
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001681 case 0: /* MUL */
1682 if (!CPUO (OPT_EIS)) {
1683 setTRAP (TRAP_ILL);
1684 break;
1685 }
1686 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
1687 src = R[srcspec];
Bob Supnik9c4779c2009-02-08 09:06:00 -08001688 if (GET_SIGN_W (src2))
1689 src2 = src2 | ~077777;
1690 if (GET_SIGN_W (src))
1691 src = src | ~077777;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001692 dst = src * src2;
Paul Koning66fb70b2016-04-07 15:21:59 -04001693 if (hst_ent) {
1694 hst_ent->src = src;
1695 hst_ent->dst = dst;
1696 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001697 R[srcspec] = (dst >> 16) & 0177777;
1698 R[srcspec | 1] = dst & 0177777;
1699 N = (dst < 0);
1700 Z = GET_Z (dst);
1701 V = 0;
1702 C = ((dst > 077777) || (dst < -0100000));
1703 break;
Bob Supnik9af6fd22001-11-06 20:44:00 -08001704
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001705 case 1: /* DIV */
1706 if (!CPUO (OPT_EIS)) {
1707 setTRAP (TRAP_ILL);
1708 break;
1709 }
1710 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
1711 src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1];
1712 if (src2 == 0) {
1713 N = 0; /* J11,11/70 compat */
1714 Z = V = C = 1; /* N = 0, Z = 1 */
1715 break;
1716 }
Mark Pizzolatoc548b342014-10-27 17:14:28 -07001717 if ((((uint32)src) == 020000000000) && (src2 == 0177777)) {
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001718 V = 1; /* J11,11/70 compat */
1719 N = Z = C = 0; /* N = Z = 0 */
1720 break;
1721 }
Bob Supnik9c4779c2009-02-08 09:06:00 -08001722 if (GET_SIGN_W (src2))
1723 src2 = src2 | ~077777;
1724 if (GET_SIGN_W (R[srcspec]))
1725 src = src | ~017777777777;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001726 dst = src / src2;
Paul Koning66fb70b2016-04-07 15:21:59 -04001727 if (hst_ent) {
1728 hst_ent->src = src;
1729 hst_ent->dst = dst;
1730 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001731 N = (dst < 0); /* N set on 32b result */
1732 if ((dst > 077777) || (dst < -0100000)) {
1733 V = 1; /* J11,11/70 compat */
1734 Z = C = 0; /* Z = C = 0 */
1735 break;
1736 }
1737 R[srcspec] = dst & 0177777;
1738 R[srcspec | 1] = (src - (src2 * dst)) & 0177777;
1739 Z = GET_Z (dst);
1740 V = C = 0;
1741 break;
1742
1743 case 2: /* ASH */
1744 if (!CPUO (OPT_EIS)) {
1745 setTRAP (TRAP_ILL);
1746 break;
1747 }
1748 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
1749 src2 = src2 & 077;
1750 sign = GET_SIGN_W (R[srcspec]);
1751 src = sign? R[srcspec] | ~077777: R[srcspec];
1752 if (src2 == 0) { /* [0] */
1753 dst = src;
1754 V = C = 0;
1755 }
1756 else if (src2 <= 15) { /* [1,15] */
1757 dst = src << src2;
1758 i = (src >> (16 - src2)) & 0177777;
1759 V = (i != ((dst & 0100000)? 0177777: 0));
1760 C = (i & 1);
1761 }
1762 else if (src2 <= 31) { /* [16,31] */
1763 dst = 0;
1764 V = (src != 0);
1765 C = (src << (src2 - 16)) & 1;
1766 }
1767 else if (src2 == 32) { /* [32] = -32 */
1768 dst = -sign;
Bob Supnik53d02f72007-02-03 14:59:00 -08001769 V = 0;
1770 C = sign;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001771 }
1772 else { /* [33,63] = -31,-1 */
1773 dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
1774 V = 0;
1775 C = ((src >> (63 - src2)) & 1);
1776 }
Paul Koning66fb70b2016-04-07 15:21:59 -04001777 if (hst_ent) {
1778 hst_ent->src = src;
1779 hst_ent->dst = dst;
1780 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001781 dst = R[srcspec] = dst & 0177777;
1782 N = GET_SIGN_W (dst);
1783 Z = GET_Z (dst);
1784 break;
1785
1786 case 3: /* ASHC */
1787 if (!CPUO (OPT_EIS)) {
1788 setTRAP (TRAP_ILL);
1789 break;
1790 }
1791 src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
1792 src2 = src2 & 077;
1793 sign = GET_SIGN_W (R[srcspec]);
1794 src = (((uint32) R[srcspec]) << 16) | R[srcspec | 1];
1795 if (src2 == 0) { /* [0] */
1796 dst = src;
1797 V = C = 0;
1798 }
1799 else if (src2 <= 31) { /* [1,31] */
1800 dst = ((uint32) src) << src2;
1801 i = (src >> (32 - src2)) | (-sign << src2);
1802 V = (i != ((dst & 020000000000)? -1: 0));
1803 C = (i & 1);
1804 }
1805 else if (src2 == 32) { /* [32] = -32 */
1806 dst = -sign;
1807 V = 0;
Bob Supnik53d02f72007-02-03 14:59:00 -08001808 C = sign;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001809 }
1810 else { /* [33,63] = -31,-1 */
1811 dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
1812 V = 0;
1813 C = ((src >> (63 - src2)) & 1);
1814 }
1815 i = R[srcspec] = (dst >> 16) & 0177777;
Paul Koning66fb70b2016-04-07 15:21:59 -04001816 if (hst_ent) {
1817 hst_ent->src = src;
1818 hst_ent->dst = dst;
1819 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001820 dst = R[srcspec | 1] = dst & 0177777;
1821 N = GET_SIGN_W (i);
1822 Z = GET_Z (dst | i);
1823 break;
1824
1825 case 4: /* XOR */
1826 if (CPUT (HAS_SXS)) {
Bob Supnikdc871fa2006-05-27 11:34:00 -07001827 if (CPUT (IS_SDSD) && !dstreg) { /* R,not R */
1828 src2 = ReadMW (GeteaW (dstspec));
1829 src = R[srcspec];
1830 }
1831 else {
1832 src = R[srcspec];
1833 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
1834 }
1835 dst = src ^ src2;
Paul Koning66fb70b2016-04-07 15:21:59 -04001836 if (hst_ent) {
1837 hst_ent->src = src;
1838 hst_ent->dst = dst;
1839 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001840 N = GET_SIGN_W (dst);
1841 Z = GET_Z (dst);
1842 V = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001843 if (dstreg)
1844 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001845 else PWriteW (dst, last_pa);
1846 }
1847 else setTRAP (TRAP_ILL);
1848 break;
1849
1850 case 5: /* FIS */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001851 if (CPUO (OPT_FIS))
1852 fis11 (IR);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001853 else setTRAP (TRAP_ILL);
1854 break;
1855
1856 case 6: /* CIS */
1857 if (CPUT (CPUT_60) && (cm == MD_KER) && /* 11/60 MED? */
1858 (IR == 076600)) {
1859 ReadE (PC | isenable); /* read immediate */
1860 PC = (PC + 2) & 0177777;
1861 }
Bob Supnik15919a22006-07-20 13:36:00 -07001862 else if (CPUO (OPT_CIS)) /* CIS option? */
1863 reason = cis11 (IR);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001864 else setTRAP (TRAP_ILL);
1865 break;
1866
1867 case 7: /* SOB */
1868 if (CPUT (HAS_SXS)) {
1869 R[srcspec] = (R[srcspec] - 1) & 0177777;
Paul Koning66fb70b2016-04-07 15:21:59 -04001870 if (hst_ent)
1871 hst_ent->dst = R[srcspec];
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001872 if (R[srcspec]) {
1873 JMP_PC ((PC - dstspec - dstspec) & 0177777);
1874 }
1875 }
1876 else setTRAP (TRAP_ILL);
1877 break;
1878 } /* end switch EIS */
1879 break; /* end case 007 */
1880
Bob Supnik9af6fd22001-11-06 20:44:00 -08001881/* Opcode 10: branches, traps, SOPs */
1882
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001883 case 010:
1884 switch ((IR >> 6) & 077) { /* decode IR<11:6> */
Bob Supnik9af6fd22001-11-06 20:44:00 -08001885
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001886 case 000: case 001: /* BPL */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001887 if (N == 0) {
1888 BRANCH_F (IR);
1889 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001890 break;
Bob Supnik9af6fd22001-11-06 20:44:00 -08001891
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001892 case 002: case 003: /* BPL */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001893 if (N == 0) {
1894 BRANCH_B (IR);
1895 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001896 break;
Bob Supnik9af6fd22001-11-06 20:44:00 -08001897
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001898 case 004: case 005: /* BMI */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001899 if (N) {
1900 BRANCH_F (IR);
1901 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001902 break;
1903
1904 case 006: case 007: /* BMI */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001905 if (N) {
1906 BRANCH_B (IR);
1907 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001908 break;
1909
1910 case 010: case 011: /* BHI */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001911 if ((C | Z) == 0) {
1912 BRANCH_F (IR);
1913 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001914 break;
1915
1916 case 012: case 013: /* BHI */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001917 if ((C | Z) == 0) {
1918 BRANCH_B (IR);
1919 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001920 break;
1921
1922 case 014: case 015: /* BLOS */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001923 if (C | Z) {
1924 BRANCH_F (IR);
1925 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001926 break;
1927
1928 case 016: case 017: /* BLOS */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001929 if (C | Z) {
1930 BRANCH_B (IR);
1931 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001932 break;
1933
1934 case 020: case 021: /* BVC */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001935 if (V == 0) {
1936 BRANCH_F (IR);
1937 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001938 break;
1939
1940 case 022: case 023: /* BVC */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001941 if (V == 0) {
1942 BRANCH_B (IR);
1943 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001944 break;
1945
1946 case 024: case 025: /* BVS */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001947 if (V) {
1948 BRANCH_F (IR);
1949 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001950 break;
1951
1952 case 026: case 027: /* BVS */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001953 if (V) {
1954 BRANCH_B (IR);
1955 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001956 break;
1957
1958 case 030: case 031: /* BCC */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001959 if (C == 0) {
1960 BRANCH_F (IR);
1961 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001962 break;
1963
1964 case 032: case 033: /* BCC */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001965 if (C == 0) {
1966 BRANCH_B (IR);
1967 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001968 break;
1969
1970 case 034: case 035: /* BCS */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001971 if (C) {
1972 BRANCH_F (IR);
1973 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001974 break;
1975
1976 case 036: case 037: /* BCS */
Bob Supnik9c4779c2009-02-08 09:06:00 -08001977 if (C) {
1978 BRANCH_B (IR);
1979 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001980 break;
1981
1982 case 040: case 041: case 042: case 043: /* EMT */
1983 setTRAP (TRAP_EMT);
1984 break;
1985
1986 case 044: case 045: case 046: case 047: /* TRAP */
1987 setTRAP (TRAP_TRAP);
1988 break;
1989
1990 case 050: /* CLRB */
1991 N = V = C = 0;
1992 Z = 1;
Bob Supnik9c4779c2009-02-08 09:06:00 -08001993 if (dstreg)
1994 R[dstspec] = R[dstspec] & 0177400;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001995 else WriteB (0, GeteaB (dstspec));
Paul Koning66fb70b2016-04-07 15:21:59 -04001996 if (hst_ent) {
1997 if (dstreg)
1998 hst_ent->dst = R[dstspec];
1999 else hst_ent->dst = 0;
2000 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002001 break;
2002
2003 case 051: /* COMB */
2004 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2005 dst = (dst ^ 0377) & 0377;
2006 N = GET_SIGN_B (dst);
2007 Z = GET_Z (dst);
2008 V = 0;
2009 C = 1;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002010 if (dstreg)
2011 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002012 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002013 if (hst_ent) {
2014 if (dstreg)
2015 hst_ent->dst = R[dstspec];
2016 else hst_ent->dst = dst;
2017 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002018 break;
2019
2020 case 052: /* INCB */
2021 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2022 dst = (dst + 1) & 0377;
2023 N = GET_SIGN_B (dst);
2024 Z = GET_Z (dst);
2025 V = (dst == 0200);
Bob Supnik9c4779c2009-02-08 09:06:00 -08002026 if (dstreg)
2027 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002028 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002029 if (hst_ent) {
2030 if (dstreg)
2031 hst_ent->dst = R[dstspec];
2032 else hst_ent->dst = dst;
2033 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002034 break;
2035
2036 case 053: /* DECB */
2037 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2038 dst = (dst - 1) & 0377;
2039 N = GET_SIGN_B (dst);
2040 Z = GET_Z (dst);
2041 V = (dst == 0177);
Bob Supnik9c4779c2009-02-08 09:06:00 -08002042 if (dstreg)
2043 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002044 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002045 if (hst_ent) {
2046 if (dstreg)
2047 hst_ent->dst = R[dstspec];
2048 else hst_ent->dst = dst;
2049 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002050 break;
2051
2052 case 054: /* NEGB */
2053 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2054 dst = (-dst) & 0377;
2055 N = GET_SIGN_B (dst);
2056 Z = GET_Z (dst);
2057 V = (dst == 0200);
2058 C = (Z ^ 1);
Bob Supnik9c4779c2009-02-08 09:06:00 -08002059 if (dstreg)
2060 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002061 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002062 if (hst_ent) {
2063 if (dstreg)
2064 hst_ent->dst = R[dstspec];
2065 else hst_ent->dst = dst;
2066 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002067 break;
2068
2069 case 055: /* ADCB */
2070 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2071 dst = (dst + C) & 0377;
2072 N = GET_SIGN_B (dst);
2073 Z = GET_Z (dst);
2074 V = (C && (dst == 0200));
2075 C = C & Z;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002076 if (dstreg)
2077 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002078 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002079 if (hst_ent) {
2080 if (dstreg)
2081 hst_ent->dst = R[dstspec];
2082 else hst_ent->dst = dst;
2083 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002084 break;
2085
2086 case 056: /* SBCB */
2087 dst = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2088 dst = (dst - C) & 0377;
2089 N = GET_SIGN_B (dst);
2090 Z = GET_Z (dst);
2091 V = (C && (dst == 0177));
2092 C = (C && (dst == 0377));
Bob Supnik9c4779c2009-02-08 09:06:00 -08002093 if (dstreg)
2094 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002095 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002096 if (hst_ent) {
2097 if (dstreg)
2098 hst_ent->dst = R[dstspec];
2099 else hst_ent->dst = dst;
2100 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002101 break;
2102
2103 case 057: /* TSTB */
2104 dst = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec));
Paul Koning66fb70b2016-04-07 15:21:59 -04002105 if (hst_ent)
2106 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002107 N = GET_SIGN_B (dst);
2108 Z = GET_Z (dst);
2109 V = C = 0;
2110 break;
2111
2112 case 060: /* RORB */
2113 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2114 dst = ((src & 0377) >> 1) | (C << 7);
2115 N = GET_SIGN_B (dst);
2116 Z = GET_Z (dst);
2117 C = (src & 1);
2118 V = N ^ C;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002119 if (dstreg)
2120 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002121 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002122 if (hst_ent) {
2123 if (dstreg)
2124 hst_ent->dst = R[dstspec];
2125 else hst_ent->dst = dst;
2126 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002127 break;
2128
2129 case 061: /* ROLB */
2130 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2131 dst = ((src << 1) | C) & 0377;
2132 N = GET_SIGN_B (dst);
2133 Z = GET_Z (dst);
2134 C = GET_SIGN_B (src & 0377);
2135 V = N ^ C;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002136 if (dstreg)
2137 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002138 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002139 if (hst_ent) {
2140 if (dstreg)
2141 hst_ent->dst = R[dstspec];
2142 else hst_ent->dst = dst;
2143 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002144 break;
2145
2146 case 062: /* ASRB */
2147 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2148 dst = ((src & 0377) >> 1) | (src & 0200);
2149 N = GET_SIGN_B (dst);
2150 Z = GET_Z (dst);
2151 C = (src & 1);
2152 V = N ^ C;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002153 if (dstreg)
2154 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002155 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002156 if (hst_ent) {
2157 if (dstreg)
2158 hst_ent->dst = R[dstspec];
2159 else hst_ent->dst = dst;
2160 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002161 break;
2162
2163 case 063: /* ASLB */
2164 src = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2165 dst = (src << 1) & 0377;
2166 N = GET_SIGN_B (dst);
2167 Z = GET_Z (dst);
2168 C = GET_SIGN_B (src & 0377);
2169 V = N ^ C;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002170 if (dstreg)
2171 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002172 else PWriteB (dst, last_pa);
Paul Koning66fb70b2016-04-07 15:21:59 -04002173 if (hst_ent) {
2174 if (dstreg)
2175 hst_ent->dst = R[dstspec];
2176 else hst_ent->dst = dst;
2177 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002178 break;
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002179
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002180/* Notes:
Bob Supnik9af6fd22001-11-06 20:44:00 -08002181 - MTPS cannot alter the T bit
2182 - MxPD must mask GeteaW returned address, dspace is from cm not pm
2183 - MxPD must set MMR1 for SP recovery in case of fault
2184*/
2185
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002186 case 064: /* MTPS */
2187 if (CPUT (HAS_MXPS)) {
2188 dst = dstreg? R[dstspec]: ReadB (GeteaB (dstspec));
2189 if (cm == MD_KER) {
2190 ipl = (dst >> PSW_V_IPL) & 07;
2191 trap_req = calc_ints (ipl, trap_req);
2192 }
2193 N = (dst >> PSW_V_N) & 01;
2194 Z = (dst >> PSW_V_Z) & 01;
2195 V = (dst >> PSW_V_V) & 01;
2196 C = (dst >> PSW_V_C) & 01;
2197 }
2198 else setTRAP (TRAP_ILL);
2199 break;
2200
2201 case 065: /* MFPD */
2202 if (CPUT (HAS_MXPY)) {
2203 if (dstreg) {
Bob Supnik9c4779c2009-02-08 09:06:00 -08002204 if ((dstspec == 6) && (cm != pm))
2205 dst = STACKFILE[pm];
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002206 else dst = R[dstspec];
2207 }
2208 else dst = ReadW ((GeteaW (dstspec) & 0177777) | calc_ds (pm));
2209 N = GET_SIGN_W (dst);
2210 Z = GET_Z (dst);
2211 V = 0;
2212 SP = (SP - 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002213 reg_mods = calc_MMR1 (0366);
Bob Supnik9c4779c2009-02-08 09:06:00 -08002214 if (update_MM)
Paul Koning89ffed42016-09-13 15:22:35 -04002215 MMR1 = reg_mods;
Paul Koning66fb70b2016-04-07 15:21:59 -04002216 if (hst_ent)
2217 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002218 WriteW (dst, SP | dsenable);
2219 if ((cm == MD_KER) && (SP < (STKLIM + STKL_Y)))
2220 set_stack_trap (SP);
2221 }
2222 else setTRAP (TRAP_ILL);
2223 break;
2224
2225 case 066: /* MTPD */
2226 if (CPUT (HAS_MXPY)) {
2227 dst = ReadW (SP | dsenable);
2228 N = GET_SIGN_W (dst);
2229 Z = GET_Z (dst);
2230 V = 0;
2231 SP = (SP + 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002232 reg_mods = 026;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002233 if (update_MM)
Paul Koning89ffed42016-09-13 15:22:35 -04002234 MMR1 = reg_mods;
Paul Koning66fb70b2016-04-07 15:21:59 -04002235 if (hst_ent)
2236 hst_ent->dst = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002237 if (dstreg) {
Bob Supnik9c4779c2009-02-08 09:06:00 -08002238 if ((dstspec == 6) && (cm != pm))
2239 STACKFILE[pm] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002240 else R[dstspec] = dst;
2241 }
2242 else WriteW (dst, (GeteaW (dstspec) & 0177777) | calc_ds (pm));
2243 }
2244 else setTRAP (TRAP_ILL);
2245 break;
2246
2247 case 067: /* MFPS */
2248 if (CPUT (HAS_MXPS)) {
2249 dst = get_PSW () & 0377;
2250 N = GET_SIGN_B (dst);
2251 Z = GET_Z (dst);
2252 V = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002253 if (dstreg)
2254 R[dstspec] = (dst & 0200)? 0177400 | dst: dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002255 else WriteB (dst, GeteaB (dstspec));
2256 }
2257 else setTRAP (TRAP_ILL);
2258 break;
2259
2260 default:
2261 setTRAP (TRAP_ILL);
2262 break;
2263 } /* end switch SOPs */
2264 break; /* end case 010 */
2265
Bob Supnik9af6fd22001-11-06 20:44:00 -08002266/* Opcodes 11 - 16: double operand byte instructions
2267
2268 Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
2269 Sub: v = [sign (src) != sign (src2)] and [sign (src) = sign (result)]
2270*/
2271
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002272 case 011: /* MOVB */
2273 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
2274 ea = GeteaB (dstspec);
2275 dst = R[srcspec] & 0377;
2276 }
2277 else {
2278 dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002279 if (!dstreg)
2280 ea = GeteaB (dstspec);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002281 }
2282 N = GET_SIGN_B (dst);
2283 Z = GET_Z (dst);
2284 V = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002285 if (dstreg)
2286 R[dstspec] = (dst & 0200)? 0177400 | dst: dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002287 else WriteB (dst, ea);
Paul Koning66fb70b2016-04-07 15:21:59 -04002288 if (hst_ent) {
2289 hst_ent->src = srcreg? R[srcspec]: dst;
2290 hst_ent->dst = dstreg? R[dstspec]: dst;
2291 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002292 break;
2293
2294 case 012: /* CMPB */
2295 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
2296 src2 = ReadB (GeteaB (dstspec));
2297 src = R[srcspec] & 0377;
2298 }
2299 else {
2300 src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
2301 src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec));
Paul Koning66fb70b2016-04-07 15:21:59 -04002302 }
2303 if (hst_ent) {
2304 hst_ent->src = src;
2305 hst_ent->dst = src2;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002306 }
2307 dst = (src - src2) & 0377;
2308 N = GET_SIGN_B (dst);
2309 Z = GET_Z (dst);
2310 V = GET_SIGN_B ((src ^ src2) & (~src2 ^ dst));
2311 C = (src < src2);
2312 break;
2313
2314 case 013: /* BITB */
2315 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
2316 src2 = ReadB (GeteaB (dstspec));
2317 src = R[srcspec] & 0377;
2318 }
2319 else {
2320 src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
2321 src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec));
2322 }
2323 dst = (src2 & src) & 0377;
Paul Koning66fb70b2016-04-07 15:21:59 -04002324 if (hst_ent) {
2325 hst_ent->src = src;
2326 hst_ent->dst = dst;
2327 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002328 N = GET_SIGN_B (dst);
2329 Z = GET_Z (dst);
2330 V = 0;
2331 break;
2332
2333 case 014: /* BICB */
2334 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
2335 src2 = ReadMB (GeteaB (dstspec));
2336 src = R[srcspec];
2337 }
2338 else {
2339 src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));
2340 src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2341 }
2342 dst = (src2 & ~src) & 0377;
Paul Koning66fb70b2016-04-07 15:21:59 -04002343 if (hst_ent) {
2344 hst_ent->src = src;
2345 hst_ent->dst = dst;
2346 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002347 N = GET_SIGN_B (dst);
2348 Z = GET_Z (dst);
2349 V = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002350 if (dstreg)
2351 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002352 else PWriteB (dst, last_pa);
2353 break;
2354
2355 case 015: /* BISB */
2356 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
2357 src2 = ReadMB (GeteaB (dstspec));
2358 src = R[srcspec];
2359 }
2360 else {
2361 src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));
2362 src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec));
2363 }
2364 dst = (src2 | src) & 0377;
Paul Koning66fb70b2016-04-07 15:21:59 -04002365 if (hst_ent) {
2366 hst_ent->src = src;
2367 hst_ent->dst = dst;
2368 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002369 N = GET_SIGN_B (dst);
2370 Z = GET_Z (dst);
2371 V = 0;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002372 if (dstreg)
2373 R[dstspec] = (R[dstspec] & 0177400) | dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002374 else PWriteB (dst, last_pa);
2375 break;
2376
2377 case 016: /* SUB */
2378 if (CPUT (IS_SDSD) && srcreg && !dstreg) { /* R,not R */
2379 src2 = ReadMW (GeteaW (dstspec));
2380 src = R[srcspec];
2381 }
2382 else {
2383 src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
2384 src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec));
2385 }
2386 dst = (src2 - src) & 0177777;
Paul Koning66fb70b2016-04-07 15:21:59 -04002387 if (hst_ent) {
2388 hst_ent->src = src;
2389 hst_ent->dst = dst;
2390 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002391 N = GET_SIGN_W (dst);
2392 Z = GET_Z (dst);
2393 V = GET_SIGN_W ((src ^ src2) & (~src ^ dst));
2394 C = (src2 < src);
Bob Supnik9c4779c2009-02-08 09:06:00 -08002395 if (dstreg)
2396 R[dstspec] = dst;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002397 else PWriteW (dst, last_pa);
2398 break;
2399
Bob Supnik9af6fd22001-11-06 20:44:00 -08002400/* Opcode 17: floating point */
2401
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002402 case 017:
Bob Supnik9c4779c2009-02-08 09:06:00 -08002403 if (CPUO (OPT_FPP))
2404 fp11 (IR); /* call fpp */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002405 else setTRAP (TRAP_ILL);
2406 break; /* end case 017 */
2407 } /* end switch op */
2408 } /* end main loop */
Bob Supnik9af6fd22001-11-06 20:44:00 -08002409
2410/* Simulation halted */
2411
Bob Supnikb6393b32004-11-23 15:49:00 -08002412PSW = get_PSW ();
Bob Supnik9c4779c2009-02-08 09:06:00 -08002413for (i = 0; i < 6; i++)
2414 REGFILE[i][rs] = R[i];
Bob Supnik9af6fd22001-11-06 20:44:00 -08002415STACKFILE[cm] = SP;
2416saved_PC = PC & 0177777;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002417pcq_r->qptr = pcq_p; /* update pc q ptr */
Bob Supnikf20f5c62003-02-07 21:28:00 -08002418set_r_display (rs, cm);
Bob Supnik9af6fd22001-11-06 20:44:00 -08002419return reason;
2420}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002421
Bob Supnik9af6fd22001-11-06 20:44:00 -08002422/* Effective address calculations
2423
2424 Inputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002425 spec = specifier <5:0>
Bob Supnik9af6fd22001-11-06 20:44:00 -08002426 Outputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002427 ea = effective address
2428 <15:0> = virtual address
2429 <16> = instruction/data data space
2430 <18:17> = mode
Bob Supnik9af6fd22001-11-06 20:44:00 -08002431
2432 Data space calculation: the PDP-11 features both instruction and data
2433 spaces. Instruction space contains the instruction and any sequential
2434 add ons (eg, immediates, absolute addresses). Data space contains all
2435 data operands and indirect addresses. If data space is enabled, then
2436 memory references are directed according to these rules:
2437
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002438 Mode Index ref Indirect ref Direct ref
2439 10..16 na na data
2440 17 na na instruction
2441 20..26 na na data
2442 27 na na instruction
2443 30..36 na data data
2444 37 na instruction (absolute) data
2445 40..46 na na data
2446 47 na na instruction
2447 50..56 na data data
2448 57 na instruction data
2449 60..67 instruction na data
2450 70..77 instruction data data
Bob Supnik9af6fd22001-11-06 20:44:00 -08002451
2452 According to the PDP-11 Architecture Handbook, MMR1 records all
2453 autoincrement and autodecrement operations, including those which
2454 explicitly reference the PC. For the J-11, this is only true for
2455 autodecrement operands, autodecrement deferred operands, and
2456 autoincrement destination operands that involve a write to memory.
2457 The simulator follows the Handbook, for simplicity.
2458
2459 Notes:
2460
2461 - dsenable will direct a reference to data space if data space is enabled
2462 - ds will direct a reference to data space if data space is enabled AND if
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002463 the specifier register is not PC; this is used for 17, 27, 37, 47, 57
Bob Supnik9af6fd22001-11-06 20:44:00 -08002464 - Modes 2x, 3x, 4x, and 5x must update MMR1 if updating enabled
2465 - Modes 46 and 56 must check for stack overflow if kernel mode
2466*/
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002467
Bob Supnik9af6fd22001-11-06 20:44:00 -08002468/* Effective address calculation for words */
2469
2470int32 GeteaW (int32 spec)
2471{
2472int32 adr, reg, ds;
2473
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002474reg = spec & 07; /* register number */
2475ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */
2476switch (spec >> 3) { /* decode spec<5:3> */
2477
2478 default: /* can't get here */
2479 case 1: /* (R) */
2480 return (R[reg] | ds);
2481
2482 case 2: /* (R)+ */
2483 R[reg] = ((adr = R[reg]) + 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002484 reg_mods = calc_MMR1 (020 | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002485 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002486 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002487 return (adr | ds);
2488
2489 case 3: /* @(R)+ */
2490 R[reg] = ((adr = R[reg]) + 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002491 reg_mods = calc_MMR1 (020 | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002492 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002493 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002494 adr = ReadW (adr | ds);
2495 return (adr | dsenable);
2496
2497 case 4: /* -(R) */
2498 adr = R[reg] = (R[reg] - 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002499 reg_mods = calc_MMR1 (0360 | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002500 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002501 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002502 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
2503 set_stack_trap (adr);
2504 return (adr | ds);
2505
2506 case 5: /* @-(R) */
2507 adr = R[reg] = (R[reg] - 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002508 reg_mods = calc_MMR1 (0360 | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002509 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002510 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002511 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
2512 set_stack_trap (adr);
2513 adr = ReadW (adr | ds);
2514 return (adr | dsenable);
2515
2516 case 6: /* d(r) */
2517 adr = ReadW (PC | isenable);
2518 PC = (PC + 2) & 0177777;
2519 return (((R[reg] + adr) & 0177777) | dsenable);
2520
2521 case 7: /* @d(R) */
2522 adr = ReadW (PC | isenable);
2523 PC = (PC + 2) & 0177777;
2524 adr = ReadW (((R[reg] + adr) & 0177777) | dsenable);
2525 return (adr | dsenable);
2526 } /* end switch */
Bob Supnik9af6fd22001-11-06 20:44:00 -08002527}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002528
Bob Supnik9af6fd22001-11-06 20:44:00 -08002529/* Effective address calculation for bytes */
2530
2531int32 GeteaB (int32 spec)
2532{
2533int32 adr, reg, ds, delta;
2534
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002535reg = spec & 07; /* reg number */
2536ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */
2537switch (spec >> 3) { /* decode spec<5:3> */
2538
2539 default: /* can't get here */
2540 case 1: /* (R) */
2541 return (R[reg] | ds);
2542
2543 case 2: /* (R)+ */
2544 delta = 1 + (reg >= 6); /* 2 if R6, PC */
2545 R[reg] = ((adr = R[reg]) + delta) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002546 reg_mods = calc_MMR1 ((delta << 3) | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002547 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002548 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002549 return (adr | ds);
2550
2551 case 3: /* @(R)+ */
2552 R[reg] = ((adr = R[reg]) + 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002553 reg_mods = calc_MMR1 (020 | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002554 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002555 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002556 adr = ReadW (adr | ds);
2557 return (adr | dsenable);
2558
2559 case 4: /* -(R) */
2560 delta = 1 + (reg >= 6); /* 2 if R6, PC */
2561 adr = R[reg] = (R[reg] - delta) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002562 reg_mods = calc_MMR1 ((((-delta) & 037) << 3) | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002563 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002564 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002565 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
2566 set_stack_trap (adr);
2567 return (adr | ds);
2568
2569 case 5: /* @-(R) */
2570 adr = R[reg] = (R[reg] - 2) & 0177777;
Paul Koning89ffed42016-09-13 15:22:35 -04002571 reg_mods = calc_MMR1 (0360 | reg);
Mark Pizzolato4064cc02013-06-02 06:52:32 -07002572 if (update_MM && (reg != 7))
Paul Koning89ffed42016-09-13 15:22:35 -04002573 MMR1 = reg_mods;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002574 if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
2575 set_stack_trap (adr);
2576 adr = ReadW (adr | ds);
2577 return (adr | dsenable);
2578
2579 case 6: /* d(r) */
2580 adr = ReadW (PC | isenable);
2581 PC = (PC + 2) & 0177777;
2582 return (((R[reg] + adr) & 0177777) | dsenable);
2583
2584 case 7: /* @d(R) */
2585 adr = ReadW (PC | isenable);
2586 PC = (PC + 2) & 0177777;
2587 adr = ReadW (((R[reg] + adr) & 0177777) | dsenable);
2588 return (adr | dsenable);
2589 } /* end switch */
Bob Supnik9af6fd22001-11-06 20:44:00 -08002590}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002591
Bob Supnik9af6fd22001-11-06 20:44:00 -08002592/* Read byte and word routines, read only and read-modify-write versions
2593
2594 Inputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002595 va = virtual address, <18:16> = mode, I/D space
Bob Supnik9af6fd22001-11-06 20:44:00 -08002596 Outputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002597 data = data read from memory or I/O space
Bob Supnik9af6fd22001-11-06 20:44:00 -08002598*/
2599
Bob Supnikb6393b32004-11-23 15:49:00 -08002600int32 ReadE (int32 va)
2601{
2602int32 pa, data;
2603
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002604if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
2605 setCPUERR (CPUE_ODD);
2606 ABORT (TRAP_ODD);
2607 }
2608pa = relocR (va); /* relocate */
Paul Koning89ffed42016-09-13 15:22:35 -04002609if (BPT_SUMM_RD &&
2610 (sim_brk_test (va & 0177777, BPT_RDVIR) ||
2611 sim_brk_test (pa, BPT_RDPHY))) /* read breakpoint? */
2612 ABORT (ABRT_BKPT); /* stop simulation */
Bob Supnik9c4779c2009-02-08 09:06:00 -08002613if (ADDR_IS_MEM (pa)) /* memory address? */
Paul Koning998cf5c2017-02-04 12:19:41 -08002614 return RdMemW (pa);
Bob Supnik53d02f72007-02-03 14:59:00 -08002615if ((pa < IOPAGEBASE) || /* not I/O address */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002616 (CPUT (CPUT_J) && (pa >= IOBA_CPU))) { /* or J11 int reg? */
2617 setCPUERR (CPUE_NXM);
2618 ABORT (TRAP_NXM);
2619 }
2620if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */
2621 setCPUERR (CPUE_TMO);
2622 ABORT (TRAP_NXM);
2623 }
Bob Supnikb6393b32004-11-23 15:49:00 -08002624return data;
2625}
2626
Bob Supnik9af6fd22001-11-06 20:44:00 -08002627int32 ReadW (int32 va)
2628{
Paul Koning89ffed42016-09-13 15:22:35 -04002629int32 pa;
Bob Supnik9af6fd22001-11-06 20:44:00 -08002630
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002631if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
2632 setCPUERR (CPUE_ODD);
2633 ABORT (TRAP_ODD);
2634 }
2635pa = relocR (va); /* relocate */
Paul Koning89ffed42016-09-13 15:22:35 -04002636if (BPT_SUMM_RD &&
2637 (sim_brk_test (va & 0177777, BPT_RDVIR) ||
2638 sim_brk_test (pa, BPT_RDPHY))) /* read breakpoint? */
2639 ABORT (ABRT_BKPT); /* stop simulation */
2640return PReadW (pa);
2641}
2642
2643int32 ReadB (int32 va)
2644{
2645int32 pa;
2646
2647pa = relocR (va); /* relocate */
2648if (BPT_SUMM_RD &&
2649 (sim_brk_test (va & 0177777, BPT_RDVIR) ||
2650 sim_brk_test (pa, BPT_RDPHY))) /* read breakpoint? */
2651 ABORT (ABRT_BKPT); /* stop simulation */
2652return PReadB (pa);
2653}
2654
2655/* Read word with breakpoint check: if a data breakpoint is encountered,
2656 set reason accordingly but don't do an ABORT. This is used when we want
2657 to break after doing the operation, used for interrupt processing. */
2658int32 ReadCW (int32 va)
2659{
2660int32 pa;
2661
2662if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
2663 setCPUERR (CPUE_ODD);
2664 ABORT (TRAP_ODD);
2665 }
2666pa = relocR (va); /* relocate */
2667if (BPT_SUMM_RD &&
2668 (sim_brk_test (va & 0177777, BPT_RDVIR) ||
2669 sim_brk_test (pa, BPT_RDPHY))) /* read breakpoint? */
2670 reason = STOP_IBKPT; /* report that */
2671return PReadW (pa);
2672}
2673
2674int32 ReadMW (int32 va)
2675{
2676if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
2677 setCPUERR (CPUE_ODD);
2678 ABORT (TRAP_ODD);
2679 }
2680last_pa = relocW (va); /* reloc, wrt chk */
2681if (BPT_SUMM_RW &&
2682 (sim_brk_test (va & 0177777, BPT_RWVIR) ||
2683 sim_brk_test (last_pa, BPT_RWPHY))) /* read or write breakpoint? */
2684 ABORT (ABRT_BKPT); /* stop simulation */
2685return PReadW (last_pa);
2686}
2687
2688int32 ReadMB (int32 va)
2689{
2690last_pa = relocW (va); /* reloc, wrt chk */
2691if (BPT_SUMM_RW &&
2692 (sim_brk_test (va & 0177777, BPT_RWVIR) ||
2693 sim_brk_test (last_pa, BPT_RWPHY))) /* read or write breakpoint? */
2694 ABORT (ABRT_BKPT); /* stop simulation */
2695return PReadB (last_pa);
2696}
2697
2698int32 PReadW (int32 pa)
2699{
2700int32 data;
2701
Bob Supnik9c4779c2009-02-08 09:06:00 -08002702if (ADDR_IS_MEM (pa)) /* memory address? */
Paul Koning998cf5c2017-02-04 12:19:41 -08002703 return RdMemW (pa);
Bob Supnik53d02f72007-02-03 14:59:00 -08002704if (pa < IOPAGEBASE) { /* not I/O address? */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002705 setCPUERR (CPUE_NXM);
2706 ABORT (TRAP_NXM);
2707 }
2708if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */
2709 setCPUERR (CPUE_TMO);
2710 ABORT (TRAP_NXM);
2711 }
Bob Supnik9af6fd22001-11-06 20:44:00 -08002712return data;
2713}
2714
Paul Koning89ffed42016-09-13 15:22:35 -04002715int32 PReadB (int32 pa)
Bob Supnik9af6fd22001-11-06 20:44:00 -08002716{
Paul Koning89ffed42016-09-13 15:22:35 -04002717int32 data;
Bob Supnik9af6fd22001-11-06 20:44:00 -08002718
Paul Koning998cf5c2017-02-04 12:19:41 -08002719if (ADDR_IS_MEM (pa)) /* memory address? */
2720 return RdMemB (pa);
Bob Supnik53d02f72007-02-03 14:59:00 -08002721if (pa < IOPAGEBASE) { /* not I/O address? */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002722 setCPUERR (CPUE_NXM);
2723 ABORT (TRAP_NXM);
2724 }
2725if (iopageR (&data, pa, READ) != SCPE_OK) { /* invalid I/O addr? */
2726 setCPUERR (CPUE_TMO);
2727 ABORT (TRAP_NXM);
2728 }
Paul Koning89ffed42016-09-13 15:22:35 -04002729return ((pa & 1)? data >> 8: data) & 0377;
Bob Supnik9af6fd22001-11-06 20:44:00 -08002730}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002731
Bob Supnik9af6fd22001-11-06 20:44:00 -08002732/* Write byte and word routines
2733
2734 Inputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002735 data = data to be written
2736 va = virtual address, <18:16> = mode, I/D space, or
2737 pa = physical address
Bob Supnik9af6fd22001-11-06 20:44:00 -08002738 Outputs: none
2739*/
2740
2741void WriteW (int32 data, int32 va)
2742{
2743int32 pa;
2744
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002745if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
2746 setCPUERR (CPUE_ODD);
2747 ABORT (TRAP_ODD);
2748 }
2749pa = relocW (va); /* relocate */
Paul Koning89ffed42016-09-13 15:22:35 -04002750if (BPT_SUMM_WR &&
2751 (sim_brk_test (va & 0177777, BPT_WRVIR) ||
2752 sim_brk_test (pa, BPT_WRPHY))) /* write breakpoint? */
2753 ABORT (ABRT_BKPT); /* stop simulation */
2754PWriteW (data, pa);
Bob Supnik9af6fd22001-11-06 20:44:00 -08002755}
2756
2757void WriteB (int32 data, int32 va)
2758{
2759int32 pa;
2760
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002761pa = relocW (va); /* relocate */
Paul Koning89ffed42016-09-13 15:22:35 -04002762if (BPT_SUMM_WR &&
2763 (sim_brk_test (va & 0177777, BPT_WRVIR) ||
2764 sim_brk_test (pa, BPT_WRPHY))) /* write breakpoint? */
2765 ABORT (ABRT_BKPT); /* stop simulation */
2766PWriteB (data, pa);
2767}
2768
2769/* Write word with breakpoint check: if a data breakpoint is encountered,
2770 set reason accordingly but don't do an ABORT. This is used when we want
2771 to break after doing the operation, used for interrupt processing. */
2772void WriteCW (int32 data, int32 va)
2773{
2774int32 pa;
2775
2776if ((va & 1) && CPUT (HAS_ODD)) { /* odd address? */
2777 setCPUERR (CPUE_ODD);
2778 ABORT (TRAP_ODD);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002779 }
Paul Koning89ffed42016-09-13 15:22:35 -04002780pa = relocW (va); /* relocate */
2781if (BPT_SUMM_WR &&
2782 (sim_brk_test (va & 0177777, BPT_WRVIR) ||
2783 sim_brk_test (pa, BPT_WRPHY))) /* write breakpoint? */
2784 reason = STOP_IBKPT; /* report that */
2785PWriteW (data, pa);
Bob Supnik9af6fd22001-11-06 20:44:00 -08002786}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002787
Bob Supnik9af6fd22001-11-06 20:44:00 -08002788void PWriteW (int32 data, int32 pa)
2789{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002790if (ADDR_IS_MEM (pa)) { /* memory address? */
Paul Koning998cf5c2017-02-04 12:19:41 -08002791 WrMemW (pa, data);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002792 return;
2793 }
Bob Supnik53d02f72007-02-03 14:59:00 -08002794if (pa < IOPAGEBASE) { /* not I/O address? */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002795 setCPUERR (CPUE_NXM);
2796 ABORT (TRAP_NXM);
2797 }
2798if (iopageW (data, pa, WRITE) != SCPE_OK) { /* invalid I/O addr? */
2799 setCPUERR (CPUE_TMO);
2800 ABORT (TRAP_NXM);
2801 }
Bob Supnik9af6fd22001-11-06 20:44:00 -08002802return;
2803}
2804
2805void PWriteB (int32 data, int32 pa)
2806{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002807if (ADDR_IS_MEM (pa)) { /* memory address? */
Paul Koning998cf5c2017-02-04 12:19:41 -08002808 WrMemB (pa, data);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002809 return;
2810 }
Bob Supnik53d02f72007-02-03 14:59:00 -08002811if (pa < IOPAGEBASE) { /* not I/O address? */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002812 setCPUERR (CPUE_NXM);
2813 ABORT (TRAP_NXM);
2814 }
2815if (iopageW (data, pa, WRITEB) != SCPE_OK) { /* invalid I/O addr? */
2816 setCPUERR (CPUE_TMO);
2817 ABORT (TRAP_NXM);
2818 }
Bob Supnik9af6fd22001-11-06 20:44:00 -08002819return;
2820}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002821
Bob Supnik9af6fd22001-11-06 20:44:00 -08002822/* Relocate virtual address, read access
2823
2824 Inputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002825 va = virtual address, <18:16> = mode, I/D space
Bob Supnik9af6fd22001-11-06 20:44:00 -08002826 Outputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002827 pa = physical address
Bob Supnik9af6fd22001-11-06 20:44:00 -08002828 On aborts, this routine aborts back to the top level simulator
2829 with an appropriate trap code.
2830
2831 Notes:
Bob Supnikb6393b32004-11-23 15:49:00 -08002832 - The 'normal' read codes (010, 110) are done in-line; all
2833 others in a subroutine
Bob Supnik9af6fd22001-11-06 20:44:00 -08002834 - APRFILE[UNUSED] is all zeroes, forcing non-resident abort
2835 - Aborts must update MMR0<15:13,6:1> if updating is enabled
2836*/
2837
2838int32 relocR (int32 va)
2839{
Bob Supnikb6393b32004-11-23 15:49:00 -08002840int32 apridx, apr, pa;
Bob Supnik9af6fd22001-11-06 20:44:00 -08002841
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002842if (MMR0 & MMR0_MME) { /* if mmgt */
2843 apridx = (va >> VA_V_APF) & 077; /* index into APR */
2844 apr = APRFILE[apridx]; /* with va<18:13> */
2845 if ((apr & PDR_PRD) != 2) /* not 2, 6? */
2846 relocR_test (va, apridx); /* long test */
2847 if (PLF_test (va, apr)) /* pg lnt error? */
2848 reloc_abort (MMR0_PL, apridx);
2849 pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK;
2850 if ((MMR3 & MMR3_M22E) == 0) {
2851 pa = pa & 0777777;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002852 if (pa >= 0760000)
2853 pa = 017000000 | pa;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002854 }
2855 }
2856else {
2857 pa = va & 0177777; /* mmgt off */
Bob Supnik9c4779c2009-02-08 09:06:00 -08002858 if (pa >= 0160000)
2859 pa = 017600000 | pa;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002860 }
Bob Supnik9af6fd22001-11-06 20:44:00 -08002861return pa;
Bob Supnikb6393b32004-11-23 15:49:00 -08002862}
2863
2864/* Read relocation, access control field != read only or read/write
2865
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002866 ACF value 11/45,11/70 all others
Bob Supnikb6393b32004-11-23 15:49:00 -08002867
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002868 0 abort NR abort NR
2869 1 trap -
2870 2 ok ok
2871 3 abort NR -
2872 4 trap abort NR
2873 5 ok -
2874 6 ok ok
2875 7 abort NR -
Bob Supnikb6393b32004-11-23 15:49:00 -08002876*/
2877
2878void relocR_test (int32 va, int32 apridx)
2879{
2880int32 apr, err;
2881
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002882err = 0; /* init status */
2883apr = APRFILE[apridx]; /* get APR */
2884switch (apr & PDR_ACF) { /* case on ACF */
2885
2886 case 1: case 4: /* trap read */
2887 if (CPUT (HAS_MMTR)) { /* traps implemented? */
2888 APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */
2889 if (MMR0 & MMR0_TENB) { /* traps enabled? */
Bob Supnik9c4779c2009-02-08 09:06:00 -08002890 if (update_MM) /* update MMR0 */
2891 MMR0 = (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002892 MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */
2893 setTRAP (TRAP_MME); /* set trap */
2894 }
2895 return; /* continue op */
2896 } /* not impl, abort NR */
2897 case 0: case 3: case 7: /* non-resident */
2898 err = MMR0_NR; /* set MMR0 */
2899 break; /* go test PLF, abort */
2900
2901 case 2: case 5: case 6: /* readable */
2902 return; /* continue */
2903 } /* end switch */
2904
Bob Supnik9c4779c2009-02-08 09:06:00 -08002905if (PLF_test (va, apr)) /* pg lnt error? */
2906 err = err | MMR0_PL;
Bob Supnikb6393b32004-11-23 15:49:00 -08002907reloc_abort (err, apridx);
2908return;
2909}
2910
2911t_bool PLF_test (int32 va, int32 apr)
2912{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002913int32 dbn = va & VA_BN; /* extr block num */
2914int32 plf = (apr & PDR_PLF) >> 2; /* extr page length */
Bob Supnikb6393b32004-11-23 15:49:00 -08002915
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002916return ((apr & PDR_ED)? (dbn < plf): (dbn > plf)); /* pg lnt error? */
Bob Supnikb6393b32004-11-23 15:49:00 -08002917}
2918
2919void reloc_abort (int32 err, int32 apridx)
2920{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002921if (update_MM) MMR0 = /* update MMR0 */
2922 (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE);
2923APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */
2924MMR0 = MMR0 | err; /* set aborts */
2925ABORT (TRAP_MME); /* abort ref */
Bob Supnikb6393b32004-11-23 15:49:00 -08002926return;
Bob Supnik9af6fd22001-11-06 20:44:00 -08002927}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002928
Bob Supnik9af6fd22001-11-06 20:44:00 -08002929/* Relocate virtual address, write access
2930
2931 Inputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002932 va = virtual address, <18:16> = mode, I/D space
Bob Supnik9af6fd22001-11-06 20:44:00 -08002933 Outputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002934 pa = physical address
Bob Supnik9af6fd22001-11-06 20:44:00 -08002935 On aborts, this routine aborts back to the top level simulator
2936 with an appropriate trap code.
2937
2938 Notes:
Bob Supnikb6393b32004-11-23 15:49:00 -08002939 - The 'normal' write code (110) is done in-line; all others
2940 in a subroutine
Bob Supnik9af6fd22001-11-06 20:44:00 -08002941 - APRFILE[UNUSED] is all zeroes, forcing non-resident abort
2942 - Aborts must update MMR0<15:13,6:1> if updating is enabled
2943*/
2944
2945int32 relocW (int32 va)
2946{
Bob Supnikb6393b32004-11-23 15:49:00 -08002947int32 apridx, apr, pa;
Bob Supnik9af6fd22001-11-06 20:44:00 -08002948
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002949if (MMR0 & MMR0_MME) { /* if mmgt */
2950 apridx = (va >> VA_V_APF) & 077; /* index into APR */
2951 apr = APRFILE[apridx]; /* with va<18:13> */
2952 if ((apr & PDR_ACF) != 6) /* not writeable? */
2953 relocW_test (va, apridx); /* long test */
2954 if (PLF_test (va, apr)) /* pg lnt error? */
2955 reloc_abort (MMR0_PL, apridx);
2956 APRFILE[apridx] = apr | PDR_W; /* set W */
2957 pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK;
2958 if ((MMR3 & MMR3_M22E) == 0) {
2959 pa = pa & 0777777;
Bob Supnik9c4779c2009-02-08 09:06:00 -08002960 if (pa >= 0760000)
2961 pa = 017000000 | pa;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002962 }
2963 }
2964else {
2965 pa = va & 0177777; /* mmgt off */
Bob Supnik9c4779c2009-02-08 09:06:00 -08002966 if (pa >= 0160000)
2967 pa = 017600000 | pa;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002968 }
Bob Supnik9af6fd22001-11-06 20:44:00 -08002969return pa;
Bob Supnikb6393b32004-11-23 15:49:00 -08002970}
2971
2972/* Write relocation, access control field != read/write
2973
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002974 ACF value 11/45,11/70 all others
Bob Supnikb6393b32004-11-23 15:49:00 -08002975
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002976 0 abort NR abort NR
2977 1 abort RO -
2978 2 abort RO abort RO
2979 3 abort NR -
2980 4 trap abort NR
2981 5 trap -
2982 6 ok ok
2983 7 abort NR -
Bob Supnikb6393b32004-11-23 15:49:00 -08002984*/
2985
2986void relocW_test (int32 va, int32 apridx)
2987{
2988int32 apr, err;
2989
Bob Supnikb7c1eae2005-09-09 18:09:00 -07002990err = 0; /* init status */
2991apr = APRFILE[apridx]; /* get APR */
2992switch (apr & PDR_ACF) { /* case on ACF */
2993
2994 case 4: case 5: /* trap write */
2995 if (CPUT (HAS_MMTR)) { /* traps implemented? */
2996 APRFILE[apridx] = APRFILE[apridx] | PDR_A; /* set A */
2997 if (MMR0 & MMR0_TENB) { /* traps enabled? */
Bob Supnik9c4779c2009-02-08 09:06:00 -08002998 if (update_MM) /* update MMR0 */
2999 MMR0 = (MMR0 & ~MMR0_PAGE) | (apridx << MMR0_V_PAGE);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003000 MMR0 = MMR0 | MMR0_TRAP; /* set trap flag */
3001 setTRAP (TRAP_MME); /* set trap */
3002 }
3003 return; /* continue op */
3004 } /* not impl, abort NR */
3005 case 0: case 3: case 7: /* non-resident */
3006 err = MMR0_NR; /* MMR0 status */
3007 break; /* go test PLF, abort */
3008
3009 case 1: case 2: /* read only */
3010 err = MMR0_RO; /* MMR0 status */
3011 break;
3012
3013 case 6: /* read/write */
3014 return; /* continue */
3015 } /* end switch */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003016if (PLF_test (va, apr)) /* pg lnt error? */
3017 err = err | MMR0_PL;
Bob Supnikb6393b32004-11-23 15:49:00 -08003018reloc_abort (err, apridx);
3019return;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003020}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003021
Bob Supnik9af6fd22001-11-06 20:44:00 -08003022/* Relocate virtual address, console access
3023
3024 Inputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003025 va = virtual address
3026 sw = switches
Bob Supnik9af6fd22001-11-06 20:44:00 -08003027 Outputs:
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003028 pa = physical address
Bob Supnik2c2dd5e2002-11-17 15:54:00 -08003029 On aborts, this routine returns MAXMEMSIZE
Bob Supnik9af6fd22001-11-06 20:44:00 -08003030*/
3031
3032int32 relocC (int32 va, int32 sw)
3033{
3034int32 mode, dbn, plf, apridx, apr, pa;
3035
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003036if (MMR0 & MMR0_MME) { /* if mmgt */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003037 if (sw & SWMASK ('K'))
3038 mode = MD_KER;
3039 else if (sw & SWMASK ('S'))
3040 mode = MD_SUP;
3041 else if (sw & SWMASK ('U'))
3042 mode = MD_USR;
3043 else if (sw & SWMASK ('P'))
3044 mode = (PSW >> PSW_V_PM) & 03;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003045 else mode = (PSW >> PSW_V_CM) & 03;
Mark Pizzolato8eb36722016-08-30 13:10:56 -07003046 va = va | ((sw & SWMASK ('T'))? calc_ds (mode): calc_is (mode));
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003047 apridx = (va >> VA_V_APF) & 077; /* index into APR */
3048 apr = APRFILE[apridx]; /* with va<18:13> */
3049 dbn = va & VA_BN; /* extr block num */
3050 plf = (apr & PDR_PLF) >> 2; /* extr page length */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003051 if ((apr & PDR_PRD) == 0) /* not readable? */
3052 return MAXMEMSIZE;
3053 if ((apr & PDR_ED)? dbn < plf: dbn > plf)
3054 return MAXMEMSIZE;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003055 pa = ((va & VA_DF) + ((apr >> 10) & 017777700)) & PAMASK;
3056 if ((MMR3 & MMR3_M22E) == 0) {
3057 pa = pa & 0777777;
Bob Supnik9c4779c2009-02-08 09:06:00 -08003058 if (pa >= 0760000)
3059 pa = 017000000 | pa;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003060 }
3061 }
3062else {
3063 pa = va & 0177777; /* mmgt off */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003064 if (pa >= 0160000)
3065 pa = 017600000 | pa;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003066 }
Bob Supnik9af6fd22001-11-06 20:44:00 -08003067return pa;
3068}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003069
Bob Supnikb6393b32004-11-23 15:49:00 -08003070/* Memory management registers
Bob Supnik9af6fd22001-11-06 20:44:00 -08003071
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003072 MMR0 17777572 read/write, certain bits unimplemented or read only
3073 MMR1 17777574 read only
3074 MMR2 17777576 read only
3075 MMR3 17777516 read/write, certain bits unimplemented
Bob Supnik9af6fd22001-11-06 20:44:00 -08003076*/
3077
Bob Supnikb6393b32004-11-23 15:49:00 -08003078t_stat MMR012_rd (int32 *data, int32 pa, int32 access)
Bob Supnik9af6fd22001-11-06 20:44:00 -08003079{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003080switch ((pa >> 1) & 3) { /* decode pa<2:1> */
3081
3082 case 0: /* SR */
3083 return SCPE_NXM;
3084
3085 case 1: /* MMR0 */
3086 *data = MMR0 & cpu_tab[cpu_model].mm0;
3087 break;
3088
3089 case 2: /* MMR1 */
3090 *data = MMR1;
3091 break;
3092
3093 case 3: /* MMR2 */
3094 *data = MMR2;
3095 break;
Bob Supnik53d02f72007-02-03 14:59:00 -08003096 } /* end switch pa */
3097
Bob Supnik89bcd022001-11-06 20:58:00 -08003098return SCPE_OK;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003099}
3100
Bob Supnikb6393b32004-11-23 15:49:00 -08003101t_stat MMR012_wr (int32 data, int32 pa, int32 access)
Bob Supnik9af6fd22001-11-06 20:44:00 -08003102{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003103switch ((pa >> 1) & 3) { /* decode pa<2:1> */
3104
3105 case 0: /* DR */
3106 return SCPE_NXM;
3107
3108 case 1: /* MMR0 */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003109 if (access == WRITEB)
3110 data = (pa & 1)? (MMR0 & 0377) | (data << 8): (MMR0 & ~0377) | data;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003111 data = data & cpu_tab[cpu_model].mm0;
3112 MMR0 = (MMR0 & ~MMR0_WR) | (data & MMR0_WR);
3113 return SCPE_OK;
3114
3115 default: /* MMR1, MMR2 */
3116 return SCPE_OK;
3117 } /* end switch pa */
Bob Supnik9af6fd22001-11-06 20:44:00 -08003118}
3119
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003120t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */
Bob Supnik9af6fd22001-11-06 20:44:00 -08003121{
Bob Supnikb6393b32004-11-23 15:49:00 -08003122*data = MMR3 & cpu_tab[cpu_model].mm3;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003123return SCPE_OK;
3124}
3125
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003126t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */
Bob Supnik9af6fd22001-11-06 20:44:00 -08003127{
Bob Supnik9c4779c2009-02-08 09:06:00 -08003128if (pa & 1)
3129 return SCPE_OK;
Bob Supnikb6393b32004-11-23 15:49:00 -08003130MMR3 = data & cpu_tab[cpu_model].mm3;
3131cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM);
Bob Supnik9af6fd22001-11-06 20:44:00 -08003132dsenable = calc_ds (cm);
3133return SCPE_OK;
3134}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003135
Bob Supnik9af6fd22001-11-06 20:44:00 -08003136/* PARs and PDRs. These are grouped in I/O space as follows:
3137
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003138 17772200 - 17772276 supervisor block
3139 17772300 - 17772376 kernel block
3140 17777600 - 17777676 user block
Bob Supnik9af6fd22001-11-06 20:44:00 -08003141
3142 Within each block, the subblocks are I PDR's, D PDR's, I PAR's, D PAR's
3143
3144 Thus, the algorithm for converting between I/O space addresses and
3145 APRFILE indices is as follows:
3146
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003147 idx<3:0> = dspace'page = pa<4:1>
3148 par = PDR vs PAR = pa<5>
3149 idx<5:4> = ker/sup/user = pa<8>'~pa<6>
Bob Supnik9af6fd22001-11-06 20:44:00 -08003150
Bob Supnikb6393b32004-11-23 15:49:00 -08003151 Note: the A,W bits are read only; they are cleared by any write to an APR
Bob Supnik9af6fd22001-11-06 20:44:00 -08003152*/
3153
3154t_stat APR_rd (int32 *data, int32 pa, int32 access)
3155{
3156t_stat left, idx;
3157
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003158idx = (pa >> 1) & 017; /* dspace'page */
3159left = (pa >> 5) & 1; /* PDR vs PAR */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003160if ((pa & 0100) == 0) /* 1 for super, user */
3161 idx = idx | 020;
3162if (pa & 0400) /* 1 for user only */
3163 idx = idx | 040;
3164if (left)
3165 *data = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par;
Bob Supnikb6393b32004-11-23 15:49:00 -08003166else *data = APRFILE[idx] & cpu_tab[cpu_model].pdr;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003167return SCPE_OK;
3168}
3169
3170t_stat APR_wr (int32 data, int32 pa, int32 access)
3171{
3172int32 left, idx, curr;
3173
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003174idx = (pa >> 1) & 017; /* dspace'page */
3175left = (pa >> 5) & 1; /* PDR vs PAR */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003176if ((pa & 0100) == 0) /* 1 for super, user */
3177 idx = idx | 020;
3178if (pa & 0400) /* 1 for user only */
3179 idx = idx | 040;
3180if (left)
3181 curr = (APRFILE[idx] >> 16) & cpu_tab[cpu_model].par;
Bob Supnikb6393b32004-11-23 15:49:00 -08003182else curr = APRFILE[idx] & cpu_tab[cpu_model].pdr;
Bob Supnik9c4779c2009-02-08 09:06:00 -08003183if (access == WRITEB)
3184 data = (pa & 1)? (curr & 0377) | (data << 8): (curr & ~0377) | data;
3185if (left)
3186 APRFILE[idx] = ((APRFILE[idx] & 0177777) |
3187 (((uint32) (data & cpu_tab[cpu_model].par)) << 16)) & ~(PDR_A|PDR_W);
Bob Supnikb6393b32004-11-23 15:49:00 -08003188else APRFILE[idx] = ((APRFILE[idx] & ~0177777) |
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003189 (data & cpu_tab[cpu_model].pdr)) & ~(PDR_A|PDR_W);
Bob Supnik9af6fd22001-11-06 20:44:00 -08003190return SCPE_OK;
3191}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003192
Bob Supnikb6393b32004-11-23 15:49:00 -08003193/* Explicit PSW read */
Bob Supnik9af6fd22001-11-06 20:44:00 -08003194
Bob Supnikb6393b32004-11-23 15:49:00 -08003195t_stat PSW_rd (int32 *data, int32 pa, int32 access)
Bob Supnik9af6fd22001-11-06 20:44:00 -08003196{
Bob Supnik9c4779c2009-02-08 09:06:00 -08003197if (access == READC)
3198 *data = PSW;
Bob Supnikb6393b32004-11-23 15:49:00 -08003199else *data = get_PSW ();
3200return SCPE_OK;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003201}
Bob Supnik9af6fd22001-11-06 20:44:00 -08003202
Bob Supnikb6393b32004-11-23 15:49:00 -08003203/* Assemble PSW from pieces */
3204
3205int32 get_PSW (void)
Bob Supnik9af6fd22001-11-06 20:44:00 -08003206{
Bob Supnikb6393b32004-11-23 15:49:00 -08003207return (cm << PSW_V_CM) | (pm << PSW_V_PM) |
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003208 (rs << PSW_V_RS) | (fpd << PSW_V_FPD) |
3209 (ipl << PSW_V_IPL) | (tbit << PSW_V_TBIT) |
3210 (N << PSW_V_N) | (Z << PSW_V_Z) |
3211 (V << PSW_V_V) | (C << PSW_V_C);
Bob Supnikb6393b32004-11-23 15:49:00 -08003212}
Bob Supnik9af6fd22001-11-06 20:44:00 -08003213
Bob Supnikb6393b32004-11-23 15:49:00 -08003214/* Explicit PSW write - T-bit may be protected */
Bob Supnik9af6fd22001-11-06 20:44:00 -08003215
Bob Supnikb6393b32004-11-23 15:49:00 -08003216t_stat PSW_wr (int32 data, int32 pa, int32 access)
3217{
3218int32 i, curr, oldrs;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003219
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003220if (access == WRITEC) { /* console access? */
3221 PSW = data & cpu_tab[cpu_model].psw;
3222 return SCPE_OK;
3223 }
3224curr = get_PSW (); /* get current */
3225oldrs = rs; /* save reg set */
3226STACKFILE[cm] = SP; /* save curr SP */
Bob Supnikb6393b32004-11-23 15:49:00 -08003227if (access == WRITEB) data = (pa & 1)?
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003228 (curr & 0377) | (data << 8): (curr & ~0377) | data;
3229if (!CPUT (HAS_EXPT)) /* expl T writes? */
3230 data = (data & ~PSW_TBIT) | (curr & PSW_TBIT); /* no, use old T */
3231put_PSW (data, 0); /* call calc_is,ds */
3232if (rs != oldrs) { /* switch reg set */
3233 for (i = 0; i < 6; i++) {
3234 REGFILE[i][oldrs] = R[i];
3235 R[i] = REGFILE[i][rs];
3236 }
3237 }
3238SP = STACKFILE[cm]; /* switch SP */
Bob Supnikb6393b32004-11-23 15:49:00 -08003239isenable = calc_is (cm);
3240dsenable = calc_ds (cm);
3241return SCPE_OK;
3242}
3243
3244/* Store pieces of new PSW - implements RTI/RTT protection */
3245
3246void put_PSW (int32 val, t_bool prot)
3247{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003248val = val & cpu_tab[cpu_model].psw; /* mask off invalid bits */
3249if (prot) { /* protected? */
3250 cm = cm | ((val >> PSW_V_CM) & 03); /* or to cm,pm,rs */
3251 pm = pm | ((val >> PSW_V_PM) & 03); /* can't change ipl */
3252 rs = rs | ((val >> PSW_V_RS) & 01);
3253 }
3254else {
3255 cm = (val >> PSW_V_CM) & 03; /* write cm,pm,rs,ipl */
3256 pm = (val >> PSW_V_PM) & 03;
3257 rs = (val >> PSW_V_RS) & 01;
3258 ipl = (val >> PSW_V_IPL) & 07;
3259 }
3260fpd = (val >> PSW_V_FPD) & 01; /* always writeable */
Bob Supnikb6393b32004-11-23 15:49:00 -08003261tbit = (val >> PSW_V_TBIT) & 01;
3262N = (val >> PSW_V_N) & 01;
3263Z = (val >> PSW_V_Z) & 01;
3264V = (val >> PSW_V_V) & 01;
3265C = (val >> PSW_V_C) & 01;
3266return;
3267}
3268
3269/* PIRQ write routine */
3270
3271void put_PIRQ (int32 val)
3272{
3273int32 pl;
3274
3275PIRQ = val & PIRQ_RW;
3276pl = 0;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003277if (PIRQ & PIRQ_PIR1) {
3278 SET_INT (PIR1);
3279 pl = 0042;
3280 }
Bob Supnikb6393b32004-11-23 15:49:00 -08003281else CLR_INT (PIR1);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003282if (PIRQ & PIRQ_PIR2) {
3283 SET_INT (PIR2);
3284 pl = 0104;
3285 }
Bob Supnikb6393b32004-11-23 15:49:00 -08003286else CLR_INT (PIR2);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003287if (PIRQ & PIRQ_PIR3) {
3288 SET_INT (PIR3);
3289 pl = 0146;
3290 }
Bob Supnikb6393b32004-11-23 15:49:00 -08003291else CLR_INT (PIR3);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003292if (PIRQ & PIRQ_PIR4) {
3293 SET_INT (PIR4);
3294 pl = 0210;
3295 }
Bob Supnikb6393b32004-11-23 15:49:00 -08003296else CLR_INT (PIR4);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003297if (PIRQ & PIRQ_PIR5) {
3298 SET_INT (PIR5);
3299 pl = 0252;
3300 }
Bob Supnikb6393b32004-11-23 15:49:00 -08003301else CLR_INT (PIR5);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003302if (PIRQ & PIRQ_PIR6) {
3303 SET_INT (PIR6);
3304 pl = 0314;
3305 }
Bob Supnikb6393b32004-11-23 15:49:00 -08003306else CLR_INT (PIR6);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003307if (PIRQ & PIRQ_PIR7) {
3308 SET_INT (PIR7);
3309 pl = 0356;
3310 }
Bob Supnikb6393b32004-11-23 15:49:00 -08003311else CLR_INT (PIR7);
3312PIRQ = PIRQ | pl;
3313return;
3314}
3315
3316/* Stack trap routine */
3317
3318void set_stack_trap (int32 adr)
3319{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003320if (CPUT (HAS_STKLF)) { /* fixed stack? */
3321 setTRAP (TRAP_YEL); /* always yellow trap */
3322 setCPUERR (CPUE_YEL);
3323 }
3324else if (CPUT (HAS_STKLR)) { /* register limit? */
3325 if (adr >= (STKLIM + STKL_R)) { /* yellow zone? */
3326 setTRAP (TRAP_YEL); /* still yellow trap */
3327 setCPUERR (CPUE_YEL);
3328 }
3329 else { /* red zone abort */
3330 setCPUERR (CPUE_RED);
3331 STACKFILE[MD_KER] = 4;
3332 SP = 4;
3333 ABORT (TRAP_RED);
3334 }
3335 }
3336return; /* no stack limit */
Bob Supnik9af6fd22001-11-06 20:44:00 -08003337}
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003338
Bob Supnik9af6fd22001-11-06 20:44:00 -08003339/* Reset routine */
3340
3341t_stat cpu_reset (DEVICE *dptr)
3342{
Bob Supnikb6393b32004-11-23 15:49:00 -08003343PIRQ = 0;
3344STKLIM = 0;
Mark Pizzolatof0d41f12013-10-27 05:30:13 -07003345if (CPUT (CPUT_T)) /* T11? */
3346 PSW = 000340; /* start at IPL 7 */
Mark Pizzolatoac837e52015-12-29 10:11:39 -08003347else
3348 PSW = 0; /* else at IPL 0 */
Bob Supnikb6393b32004-11-23 15:49:00 -08003349MMR0 = 0;
3350MMR1 = 0;
3351MMR2 = 0;
3352MMR3 = 0;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003353trap_req = 0;
3354wait_state = 0;
Mark Pizzolatoac837e52015-12-29 10:11:39 -08003355if (M == NULL) { /* First time init */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003356 M = (uint16 *) calloc (MEMSIZE >> 1, sizeof (uint16));
Mark Pizzolatoac837e52015-12-29 10:11:39 -08003357 if (M == NULL)
3358 return SCPE_MEM;
Mark Pizzolato6582aee2016-01-02 05:07:18 -08003359 sim_set_pchar (0, "01000023640"); /* ESC, CR, LF, TAB, BS, BEL, ENQ */
Mark Pizzolatoe2a8f0f2016-08-24 21:19:09 -07003360 sim_brk_dflt = SWMASK ('E');
Paul Koning89ffed42016-09-13 15:22:35 -04003361 sim_brk_types = sim_brk_dflt|SWMASK ('P')|
3362 SWMASK ('R')|SWMASK ('S')|
3363 SWMASK ('W')|SWMASK ('X');
3364 sim_brk_type_desc = cpu_breakpoints;
Mark Pizzolatoac837e52015-12-29 10:11:39 -08003365 sim_vm_is_subroutine_call = &cpu_is_pc_a_subroutine_call;
3366 auto_config(NULL, 0); /* do an initial auto configure */
3367 }
Bob Supnikdf647512002-07-14 15:20:00 -07003368pcq_r = find_reg ("PCQ", NULL, dptr);
Bob Supnik9c4779c2009-02-08 09:06:00 -08003369if (pcq_r)
3370 pcq_r->qptr = 0;
Mark Pizzolatoac837e52015-12-29 10:11:39 -08003371else
3372 return SCPE_IERR;
Bob Supnikf20f5c62003-02-07 21:28:00 -08003373set_r_display (0, MD_KER);
Mark Pizzolato59947e82015-12-30 12:01:58 -08003374return build_dib_tab (); /* build, chk dib_tab */
Bob Supnik9af6fd22001-11-06 20:44:00 -08003375}
3376
Mark Pizzolato3946eb72014-04-19 05:45:29 -07003377static const char *cpu_next_caveats =
3378"The NEXT command in the PDP11 simulator currently will enable stepping\n"
3379"across subroutine calls which are initiated by the JSR instruction.\n"
3380"This stepping works by dynamically establishing breakpoints at the\n"
3381"10 memory addresses immediately following the instruction which initiated\n"
3382"the subroutine call. These dynamic breakpoints are automatically\n"
3383"removed once the simulator returns to the sim> prompt for any reason.\n"
3384"If the called routine returns somewhere other than one of these\n"
3385"locations due to a trap, stack unwind or any other reason, instruction\n"
3386"execution will continue until some other reason causes execution to stop.\n";
3387
Mark Pizzolatoe7a93492014-04-17 13:07:37 -07003388t_bool cpu_is_pc_a_subroutine_call (t_addr **ret_addrs)
3389{
3390#define MAX_SUB_RETURN_SKIP 10
3391static t_addr returns[MAX_SUB_RETURN_SKIP + 1] = {0};
Mark Pizzolato3946eb72014-04-19 05:45:29 -07003392static t_bool caveats_displayed = FALSE;
Mark Pizzolatoe2a8f0f2016-08-24 21:19:09 -07003393static int32 swmap[4] = {
3394 SWMASK ('K') | SWMASK ('V'), SWMASK ('S') | SWMASK ('V'),
3395 SWMASK ('U') | SWMASK ('V'), SWMASK ('U') | SWMASK ('V')
3396 };
3397int32 cm = ((PSW >> PSW_V_CM) & 03);
Mark Pizzolatoe7a93492014-04-17 13:07:37 -07003398
Mark Pizzolato3946eb72014-04-19 05:45:29 -07003399if (!caveats_displayed) {
3400 caveats_displayed = TRUE;
Mark Pizzolato3256c102014-10-22 17:12:14 -07003401 sim_printf ("%s", cpu_next_caveats);
Mark Pizzolato3946eb72014-04-19 05:45:29 -07003402 }
Mark Pizzolatoe2a8f0f2016-08-24 21:19:09 -07003403if (SCPE_OK != get_aval (relocC(PC, swmap[cm]), &cpu_dev, &cpu_unit))/* get data */
Mark Pizzolatoe7a93492014-04-17 13:07:37 -07003404 return FALSE;
3405if ((sim_eval[0] & 0177000) == 0004000) { /* JSR */
3406 int32 dst, dstspec;
3407 t_addr i, max_returns = MAX_SUB_RETURN_SKIP;
3408 int32 save_Regs[8];
3409
3410 memcpy (save_Regs, R, sizeof(R)); /* save register state */
3411 PC = PC + 2; /* account for instruction fetch */
3412 dstspec = sim_eval[0] & 077;
3413 dst = GeteaW (dstspec);
3414 if (CPUT (CPUT_05|CPUT_20) && /* 11/05, 11/20 */
3415 ((dstspec & 070) == 020)) /* JSR (R)+? */
3416 dst = R[dstspec & 07]; /* use post incr */
3417 memcpy (R, save_Regs, sizeof(R)); /* restore register state */
3418 returns[0] = PC + (1 - fprint_sym (stdnul, PC, sim_eval, &cpu_unit, SWMASK ('M')));
3419 if (((t_addr)dst > returns[0]) && ((dst - returns[0]) < max_returns*2))
3420 max_returns = (dst - returns[0])/2;
3421 for (i=1; i<max_returns; i++)
3422 returns[i] = returns[i-1] + 2; /* Possible skip return */
3423 returns[i] = 0; /* Make sure the address list ends with a zero */
3424 *ret_addrs = returns;
3425 return TRUE;
3426 }
3427return FALSE;
3428}
3429
Mark Pizzolatof0d41f12013-10-27 05:30:13 -07003430/* Boot setup routine */
3431
3432void cpu_set_boot (int32 pc)
3433{
Mark Pizzolato235ce922014-10-28 10:19:39 -07003434saved_PC = pc;
Mark Pizzolatof0d41f12013-10-27 05:30:13 -07003435PSW = 000340;
3436return;
3437}
3438
Bob Supnik9af6fd22001-11-06 20:44:00 -08003439/* Memory examine */
3440
3441t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
3442{
3443int32 iodata;
3444t_stat stat;
3445
Bob Supnik9c4779c2009-02-08 09:06:00 -08003446if (vptr == NULL)
3447 return SCPE_ARG;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003448if (sw & SWMASK ('V')) { /* -v */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003449 if (addr >= VASIZE)
3450 return SCPE_NXM;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003451 addr = relocC (addr, sw); /* relocate */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003452 if (addr >= MAXMEMSIZE)
3453 return SCPE_REL;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003454 }
Paul Koning998cf5c2017-02-04 12:19:41 -08003455if (ADDR_IS_MEM (addr)) {
3456 *vptr = RdMemW (addr) & 0177777;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003457 return SCPE_OK;
3458 }
Bob Supnik9c4779c2009-02-08 09:06:00 -08003459if (addr < IOPAGEBASE)
3460 return SCPE_NXM;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003461stat = iopageR (&iodata, addr, READC);
3462*vptr = iodata;
3463return stat;
3464}
3465
3466/* Memory deposit */
3467
3468t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
3469{
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003470if (sw & SWMASK ('V')) { /* -v */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003471 if (addr >= VASIZE)
3472 return SCPE_NXM;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003473 addr = relocC (addr, sw); /* relocate */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003474 if (addr >= MAXMEMSIZE)
3475 return SCPE_REL;
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003476 }
Paul Koning998cf5c2017-02-04 12:19:41 -08003477if (ADDR_IS_MEM (addr)) {
3478 WrMemW (addr, val & 0177777);
Bob Supnikb7c1eae2005-09-09 18:09:00 -07003479 return SCPE_OK;
3480 }
Bob Supnik9c4779c2009-02-08 09:06:00 -08003481if (addr < IOPAGEBASE)
3482 return SCPE_NXM;
Bob Supnik9af6fd22001-11-06 20:44:00 -08003483return iopageW ((int32) val, addr, WRITEC);
Bob Supnik2c2dd5e2002-11-17 15:54:00 -08003484}
3485
Bob Supnikf20f5c62003-02-07 21:28:00 -08003486/* Set R, SP register display addresses */
3487
3488void set_r_display (int32 rs, int32 cm)
3489{
Bob Supnikf20f5c62003-02-07 21:28:00 -08003490REG *rptr;
3491int32 i;
3492
3493rptr = find_reg ("R0", NULL, &cpu_dev);
Bob Supnik9c4779c2009-02-08 09:06:00 -08003494if (rptr == NULL)
3495 return;
3496for (i = 0; i < 6; i++, rptr++)
3497 rptr->loc = (void *) &REGFILE[i][rs];
Bob Supnikf20f5c62003-02-07 21:28:00 -08003498rptr->loc = (void *) &STACKFILE[cm];
3499return;
3500}
Bob Supnikdc871fa2006-05-27 11:34:00 -07003501
3502/* Set history */
3503
Mark Pizzolato5531ccb2016-05-15 15:25:33 -07003504t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
Bob Supnikdc871fa2006-05-27 11:34:00 -07003505{
3506int32 i, lnt;
3507t_stat r;
3508
3509if (cptr == NULL) {
Bob Supnik9c4779c2009-02-08 09:06:00 -08003510 for (i = 0; i < hst_lnt; i++)
3511 hst[i].pc = 0;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003512 hst_p = 0;
3513 return SCPE_OK;
3514 }
3515lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
Bob Supnik9c4779c2009-02-08 09:06:00 -08003516if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN)))
3517 return SCPE_ARG;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003518hst_p = 0;
3519if (hst_lnt) {
3520 free (hst);
3521 hst_lnt = 0;
3522 hst = NULL;
3523 }
3524if (lnt) {
3525 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
Bob Supnik9c4779c2009-02-08 09:06:00 -08003526 if (hst == NULL)
3527 return SCPE_MEM;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003528 hst_lnt = lnt;
3529 }
3530return SCPE_OK;
3531}
3532
3533/* Show history */
3534
Mark Pizzolato5531ccb2016-05-15 15:25:33 -07003535t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
Bob Supnikdc871fa2006-05-27 11:34:00 -07003536{
3537int32 j, k, di, lnt, ir;
Mark Pizzolato5531ccb2016-05-15 15:25:33 -07003538const char *cptr = (const char *) desc;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003539t_value sim_eval[HIST_ILNT];
3540t_stat r;
3541InstHistory *h;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003542
Bob Supnik9c4779c2009-02-08 09:06:00 -08003543if (hst_lnt == 0) /* enabled? */
3544 return SCPE_NOFNC;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003545if (cptr) {
3546 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
Bob Supnik9c4779c2009-02-08 09:06:00 -08003547 if ((r != SCPE_OK) || (lnt == 0))
3548 return SCPE_ARG;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003549 }
3550else lnt = hst_lnt;
3551di = hst_p - lnt; /* work forward */
Bob Supnik9c4779c2009-02-08 09:06:00 -08003552if (di < 0)
3553 di = di + hst_lnt;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003554fprintf (st, "PC PSW src dst IR\n\n");
3555for (k = 0; k < lnt; k++) { /* print specified */
3556 h = &hst[(di++) % hst_lnt]; /* entry pointer */
3557 if (h->pc & HIST_VLD) { /* instruction? */
3558 ir = h->inst[0];
3559 fprintf (st, "%06o %06o|", h->pc & ~HIST_VLD, h->psw);
3560 if (((ir & 0070000) != 0) || /* dops, eis, fpp */
3561 ((ir & 0177000) == 0004000)) /* jsr */
3562 fprintf (st, "%06o %06o ", h->src, h->dst);
3563 else if ((ir >= 0000100) && /* not no opnd */
3564 (((ir & 0007700) < 0000300) || /* not branch */
3565 ((ir & 0007700) >= 0004000)))
3566 fprintf (st, " %06o ", h->dst);
3567 else fprintf (st, " ");
Bob Supnik9c4779c2009-02-08 09:06:00 -08003568 for (j = 0; j < HIST_ILNT; j++)
3569 sim_eval[j] = h->inst[j];
Bob Supnikdc871fa2006-05-27 11:34:00 -07003570 if ((fprint_sym (st, h->pc & ~HIST_VLD, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
3571 fprintf (st, "(undefined) %06o", h->inst[0]);
3572 fputc ('\n', st); /* end line */
3573 } /* end else instruction */
3574 } /* end for */
3575return SCPE_OK;
3576}
3577
3578/* Virtual address translation */
3579
Mark Pizzolato5531ccb2016-05-15 15:25:33 -07003580t_stat cpu_show_virt (FILE *of, UNIT *uptr, int32 val, CONST void *desc)
Bob Supnikdc871fa2006-05-27 11:34:00 -07003581{
3582t_stat r;
Mark Pizzolato5531ccb2016-05-15 15:25:33 -07003583const char *cptr = (const char *) desc;
Bob Supnikdc871fa2006-05-27 11:34:00 -07003584uint32 va, pa;
3585
3586if (cptr) {
3587 va = (uint32) get_uint (cptr, 8, VAMASK, &r);
3588 if (r == SCPE_OK) {
3589 pa = relocC (va, sim_switches); /* relocate */
3590 if (pa < MAXMEMSIZE)
3591 fprintf (of, "Virtual %-o = physical %-o\n", va, pa);
3592 else fprintf (of, "Virtual %-o is not valid\n", va);
3593 return SCPE_OK;
3594 }
3595 }
3596fprintf (of, "Invalid argument\n");
3597return SCPE_OK;
3598}