1 /* pdp18b_cpu.c: 18b PDP CPU simulator
2
3 Copyright (c) 1993-2008, Robert M Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 cpu PDP-4/7/9/15 central processor
27
28 28-Apr-07 RMS Removed clock initialization
29 26-Dec-06 RMS Fixed boundary test in KT15/XVM (Andrew Warkentin)
30 30-Oct-06 RMS Added idle and infinite loop detection
31 08-Oct-06 RMS Added RDCLK instruction
32 Fixed bug, PC off by one on fetch mem mmgt error
33 PDP-15 sets API 3 on mem mmgt trap (like PI)
34 PDP-15 sets API 4 on CAL only if 0-3 inactive
35 CAF clears memory management mode register
36 27-Jun-06 RMS Reset clears AC, L, and MQ
37 22-Sep-05 RMS Fixed declarations (Sterling Garwood)
38 16-Aug-05 RMS Fixed C++ declaration and cast problems
39 22-Jul-05 RMS Removed AAS, error in V1 reference manual
40 06-Nov-04 RMS Added =n to SHOW HISTORY
41 26-Mar-04 RMS Fixed warning from -std=c99
42 14-Jan-04 RMS Fixed g_mode in XVM implementation
43 PDP-15 index, autoincrement generate 18b addresses
44 Revised IO device call interface
45 31-Dec-03 RMS Fixed bug in cpu_set_hist
46 02-Nov-03 RMS Changed PDP-9,-15 default to API
47 26-Oct-03 RMS Fixed bug in PDP-4,-7,-9 autoincrement addressing
48 19-Sep-03 RMS Changed instruction history to be dynamically sized
49 31-Aug-03 RMS Added instruction history
50 Fixed PDP-15-specific implementation of API priorities
51 16-Aug-03 RMS Fixed PDP-15-specific handling of EAE unsigned mul/div
52 27-Jul-03 RMS Added FP15 support
53 Added XVM support
54 Added EAE option to PDP-4
55 Added PDP-15 "re-entrancy ECO"
56 Fixed memory protect/skip interaction
57 Fixed CAF not to reset CPU
58 12-Mar-03 RMS Added logical name support
59 18-Feb-03 RMS Fixed three EAE bugs (Hans Pufal)
60 05-Oct-02 RMS Added DIBs, device number support
61 25-Jul-02 RMS Added DECtape support for PDP-4
62 06-Jan-02 RMS Revised enable/disable support
63 30-Dec-01 RMS Added old PC queue
64 30-Nov-01 RMS Added extended SET/SHOW support
65 25-Nov-01 RMS Revised interrupt structure
66 19-Sep-01 RMS Fixed bug in EAE (Dave Conroy)
67 17-Sep-01 RMS Fixed typo in conditional
68 10-Aug-01 RMS Removed register from declarations
69 17-Jul-01 RMS Moved function prototype
70 27-May-01 RMS Added second Teletype support, fixed bug in API
71 18-May-01 RMS Added PDP-9,-15 API option
72 16-May-01 RMS Fixed bugs in protection checks
73 26-Apr-01 RMS Added device enable/disable support
74 25-Jan-01 RMS Added DECtape support
75 18-Dec-00 RMS Added PDP-9,-15 memm init register
76 30-Nov-00 RMS Fixed numerous PDP-15 bugs
77 14-Apr-99 RMS Changed t_addr to unsigned
78
79 The 18b PDP family has five distinct architectural variants: PDP-1,
80 PDP-4, PDP-7, PDP-9, and PDP-15. Of these, the PDP-1 is so unique
81 as to require a different simulator. The PDP-4, PDP-7, PDP-9, and
82 PDP-15 are "upward compatible", with each new variant adding
83 distinct architectural features and incompatibilities.
84
85 The register state for the 18b PDP's is:
86
87 all AC<0:17> accumulator
88 all MQ<0:17> multiplier-quotient
89 all L link flag
90 all PC<0:x> program counter
91 all IORS I/O status register
92 PDP-7, PDP-9 EXTM extend mode
93 PDP-15 BANKM bank mode
94 PDP-7 USMD trap mode
95 PDP-9, PDP-15 USMD user mode
96 PDP-9, PDP-15 BR bounds register
97 PDP-15 RR relocation register
98 PDP-15 XVM MMR memory management register
99 PDP-15 XR index register
100 PDP-15 LR limit register
101
102 The PDP-4, PDP-7, and PDP-9 have five instruction formats: memory
103 reference, load immediate, I/O transfer, EAE, and operate. The PDP-15
104 adds a sixth, index operate, and a seventh, floating point. The memory
105 reference format for the PDP-4, PDP-7, and PDP-9, and for the PDP-15
106 in bank mode, is:
107
108 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
109 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
110 | op |in| address | memory reference
111 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
112
113 The PDP-15 in page mode trades an address bit for indexing capability:
114
115 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
116 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
117 | op |in| X| address | memory reference
118 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
119
120 <0:3> mnemonic action
121
122 00 CAL JMS with MA = 20
123 04 DAC M[MA] = AC
124 10 JMS M[MA] = L'mem'user'PC, PC = MA + 1
125 14 DZM M[MA] = 0
126 20 LAC AC = M[MA]
127 24 XOR AC = AC ^ M[MA]
128 30 ADD L'AC = AC + M[MA] one's complement
129 34 TAD L'AC = AC + M[MA]
130 40 XCT M[MA] is executed as an instruction
131 44 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0
132 50 AND AC = AC & M[MA]
133 54 SAD skip if AC != M[MA]
134 60 JMP PC = MA
135
136 On the PDP-4, PDP-7, and PDP-9, and the PDP-15 in bank mode, memory
137 reference instructions can access an address space of 32K words. The
138 address space is divided into four 8K word fields. An instruction can
139 directly address, via its 13b address, the entire current field. On the
140 PDP-4, PDP-7, and PDP-9, if extend mode is off, indirect addresses access
141 the current field; if on (or a PDP-15), they can access all 32K.
142
143 On the PDP-15 in page mode, memory reference instructions can access
144 an address space of 128K words. The address is divided into four 32K
145 word blocks, each of which consists of eight 4K pages. An instruction
146 can directly address, via its 12b address, the current page. Indirect
147 addresses can access the current block. Indexed and autoincrement
148 addresses can access all 128K.
149
150 On the PDP-4 and PDP-7, if an indirect address in in locations 00010-
151 00017 of any field, the indirect address is incremented and rewritten
152 to memory before use. On the PDP-9 and PDP-15, only locations 00010-
153 00017 of field zero autoincrement; special logic will redirect indirect
154 references to 00010-00017 to field zero, even if (on the PDP-9) extend
155 mode is off.
156
157 The EAE format is:
158
159 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
160 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
161 | 1 1 0 1| | | | | | | | | | | | | | | EAE
162 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
163 | | | | | | | | | | | | | |
164 | | | | | | | | | | | | | +- or SC (3)
165 | | | | | | | | | | | | +---- or MQ (3)
166 | | | | | | | | | | | +------- compl MQ (3)
167 | | | | | | | | \______________/
168 | | | | | | | | |
169 | | | | | \_____/ +--------- shift count
170 | | | | | |
171 | | | | | +---------------------- EAE command (3)
172 | | | | +---------------------------- clear AC (2)
173 | | | +------------------------------- or AC (2)
174 | | +---------------------------------- load EAE sign (1)
175 | +------------------------------------- clear MQ (1)
176 +---------------------------------------- load link (1)
177
178 The I/O transfer format is:
179
180 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
181 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
182 | 1 1 1 0 0 0| device | sdv |cl| pulse | I/O transfer
183 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
184
185 The IO transfer instruction sends the the specified pulse to the
186 specified I/O device and sub-device. The I/O device may take data
187 from the AC, return data to the AC, initiate or cancel operations,
188 or skip on status. On the PDP-4, PDP-7, and PDP-9, bits <4:5>
189 were designated as subdevice bits but were never used; the PDP-15
190 requires them to be zero.
191
192 On the PDP-15, the floating point format is:
193
194 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
195 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
196 | 1 1 1 0 0 1| subopcode | floating point
197 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
198 |in| address |
199 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
200
201 Indirection is always single level.
202
203 On the PDP-15, the index operate format is:
204
205 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
206 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
207 | 1 1 1 0 1| subopcode | immediate | index operate
208 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
209
210 The index operate instructions provide various operations on the
211 index and limit registers.
212
213 The operate format is:
214
215 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
216 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
217 | 1 1 1 1 0| | | | | | | | | | | | | | operate
218 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
219 | | | | | | | | | | | | |
220 | | | | | | | | | | | | +- CMA (3)
221 | | | | | | | | | | | +---- CML (3)
222 | | | | | | | | | | +------- OAS (3)
223 | | | | | | | | | +---------- RAL (3)
224 | | | | | | | | +------------- RAR (3)
225 | | | | | | | +---------------- HLT (4)
226 | | | | | | +------------------- SMA (1)
227 | | | | | +---------------------- SZA (1)
228 | | | | +------------------------- SNL (1)
229 | | | +---------------------------- invert skip (1)
230 | | +------------------------------- rotate twice (2)
231 | +---------------------------------- CLL (2)
232 +------------------------------------- CLA (2)
233
234 The operate instruction can be microprogrammed to perform operations
235 on the AC and link.
236
237 The load immediate format is:
238
239 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
240 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
241 | 1 1 1 1 1| immediate | LAW
242 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
243
244 <0:4> mnemonic action
245
246 76 LAW AC = IR
247
248 This routine is the instruction decode routine for the 18b PDP's.
249 It is called from the simulator control program to execute
250 instructions in simulated memory, starting at the simulated PC.
251 It runs until 'reason' is set non-zero.
252
253 General notes:
254
255 1. Reasons to stop. The simulator can be stopped by:
256
257 HALT instruction
258 breakpoint encountered
259 unimplemented instruction and STOP_INST flag set
260 nested XCT's
261 I/O error in I/O simulator
262
263 2. Interrupts. Interrupt requests are maintained in the int_hwre
264 array. int_hwre[0:3] corresponds to API levels 0-3; int_hwre[4]
265 holds PI requests.
266
267 3. Arithmetic. The 18b PDP's implements both 1's and 2's complement
268 arithmetic for signed numbers. In 1's complement arithmetic, a
269 negative number is represented by the complement (XOR 0777777) of
270 its absolute value. Addition of 1's complement numbers requires
271 propagating the carry out of the high order bit back to the low
272 order bit.
273
274 4. Adding I/O devices. Three modules must be modified:
275
276 pdp18b_defs.h add interrupt request definition
277 pdp18b_sys.c add sim_devices table entry
278 */
279
280 #include "pdp18b_defs.h"
281
282 #define SEXT(x) ((int32) (((x) & SIGN)? (x) | ~DMASK: (x) & DMASK))
283
284 #define UNIT_V_NOEAE (UNIT_V_UF + 0) /* EAE absent */
285 #define UNIT_V_NOAPI (UNIT_V_UF + 1) /* API absent */
286 #define UNIT_V_PROT (UNIT_V_UF + 2) /* protection */
287 #define UNIT_V_RELOC (UNIT_V_UF + 3) /* relocation */
288 #define UNIT_V_XVM (UNIT_V_UF + 4) /* XVM */
289 #define UNIT_V_MSIZE (UNIT_V_UF + 5) /* dummy mask */
290 #define UNIT_NOEAE (1 << UNIT_V_NOEAE)
291 #define UNIT_NOAPI (1 << UNIT_V_NOAPI)
292 #define UNIT_PROT (1 << UNIT_V_PROT)
293 #define UNIT_RELOC (1 << UNIT_V_RELOC)
294 #define UNIT_XVM (1 << UNIT_V_XVM)
295 #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
296 #define OP_KSF 0700301
297
298 #define HIST_API 0x40000000
299 #define HIST_PI 0x20000000
300 #define HIST_PC 0x10000000
301 #define HIST_MIN 64
302 #define HIST_MAX 65536
303 #define HIST_M_LVL 0x3F
304 #define HIST_V_LVL 6
305
306 typedef struct {
307 int32 pc;
308 int32 ir;
309 int32 ir1;
310 int32 lac;
311 int32 mq;
312 } InstHistory;
313
314 #define XVM (cpu_unit.flags & UNIT_XVM)
315 #define RELOC (cpu_unit.flags & UNIT_RELOC)
316 #define PROT (cpu_unit.flags & UNIT_PROT)
317
318 #if defined (PDP4)
319 #define EAE_DFLT UNIT_NOEAE
320 #else
321 #define EAE_DFLT 0
322 #endif
323 #if defined (PDP4) || defined (PDP7)
324 #define API_DFLT UNIT_NOAPI
325 #define PROT_DFLT 0
326 #define ASW_DFLT 017763
327 #else
328 #define API_DFLT 0
329 #define PROT_DFLT UNIT_PROT
330 #define ASW_DFLT 017720
331 #endif
332
333 int32 M[MAXMEMSIZE] = { 0 }; /* memory */
334 int32 LAC = 0; /* link'AC */
335 int32 MQ = 0; /* MQ */
336 int32 PC = 0; /* PC */
337 int32 iors = 0; /* IORS */
338 int32 ion = 0; /* int on */
339 int32 ion_defer = 0; /* int defer */
340 int32 ion_inh = 0; /* int inhibit */
341 int32 int_pend = 0; /* int pending */
342 int32 int_hwre[API_HLVL+1] = { 0 }; /* int requests */
343 int32 api_enb = 0; /* API enable */
344 int32 api_req = 0; /* API requests */
345 int32 api_act = 0; /* API active */
346 int32 memm = 0; /* mem mode */
347 #if defined (PDP15)
348 int32 memm_init = 1; /* mem init */
349 #else
350 int32 memm_init = 0;
351 #endif
352 int32 usmd = 0; /* user mode */
353 int32 usmd_buf = 0; /* user mode buffer */
354 int32 usmd_defer = 0; /* user mode defer */
355 int32 trap_pending = 0; /* trap pending */
356 int32 emir_pending = 0; /* emir pending */
357 int32 rest_pending = 0; /* restore pending */
358 int32 BR = 0; /* mem mgt bounds */
359 int32 RR = 0; /* mem mgt reloc */
360 int32 MMR = 0; /* XVM mem mgt */
361 int32 nexm = 0; /* nx mem flag */
362 int32 prvn = 0; /* priv viol flag */
363 int32 SC = 0; /* shift count */
364 int32 eae_ac_sign = 0; /* EAE AC sign */
365 int32 SR = 0; /* switch register */
366 int32 ASW = ASW_DFLT; /* address switches */
367 int32 XR = 0; /* index register */
368 int32 LR = 0; /* limit register */
369 int32 stop_inst = 0; /* stop on rsrv inst */
370 int32 xct_max = 16; /* nested XCT limit */
371 #if defined (PDP15)
372 int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
373 #else
374 int16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
375 #endif
376 int32 pcq_p = 0; /* PC queue ptr */
377 REG *pcq_r = NULL; /* PC queue reg ptr */
378 int32 hst_p = 0; /* history pointer */
379 int32 hst_lnt = 0; /* history length */
380 InstHistory *hst = NULL; /* instruction history */
381
382 extern int32 sim_int_char;
383 extern int32 sim_interval;
384 extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
385 extern t_bool sim_idle_enab;
386 extern DEVICE *sim_devices[];
387 extern FILE *sim_log;
388
389 t_bool build_dev_tab (void);
390 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
391 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
392 t_stat cpu_reset (DEVICE *dptr);
393 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
394 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
395 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
396 void cpu_caf (void);
397 void cpu_inst_hist (int32 addr, int32 inst);
398 void cpu_intr_hist (int32 flag, int32 lvl);
399 int32 upd_iors (void);
400 int32 api_eval (int32 *pend);
401 t_stat Read (int32 ma, int32 *dat, int32 cyc);
402 t_stat Write (int32 ma, int32 dat, int32 cyc);
403 t_stat Ia (int32 ma, int32 *ea, t_bool jmp);
404 int32 Incr_addr (int32 addr);
405 int32 Jms_word (int32 t);
406 #if defined (PDP15)
407 #define INDEX(i,x) if (!memm && ((i) & I_IDX)) \
408 x = ((x) + XR) & DMASK
409 int32 Prot15 (int32 ma, t_bool bndchk);
410 int32 Reloc15 (int32 ma, int32 acc);
411 int32 RelocXVM (int32 ma, int32 acc);
412 extern t_stat fp15 (int32 ir);
413 extern int32 clk_task_upd (t_bool clr);
414 #else
415 #define INDEX(i,x)
416 #endif
417
418 extern int32 clk (int32 dev, int32 pulse, int32 AC);
419
420 int32 (*dev_tab[DEV_MAX])(int32 dev, int32 pulse, int32 AC); /* device dispatch */
421
422 int32 (*dev_iors[DEV_MAX])(void); /* IORS dispatch */
423
424 static const int32 api_ffo[256] = {
425 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
426 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
427 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
428 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
429 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
430 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
431 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
432 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
433 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
434 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
435 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
436 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
438 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
439 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
440 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
441 };
442
443 static const int32 api_vec[API_HLVL][32] = {
444 { ACH_PWRFL }, /* API 0 */
445 { ACH_DTA, ACH_MTA, ACH_DRM, ACH_RF, ACH_RP, ACH_RB }, /* API 1 */
446 { ACH_PTR, ACH_LPT, ACH_LPT }, /* API 2 */
447 { ACH_CLK, ACH_TTI1, ACH_TTO1 } /* API 3 */
448 };
449
450 /* CPU data structures
451
452 cpu_dev CPU device descriptor
453 cpu_unit CPU unit
454 cpu_reg CPU register list
455 cpu_mod CPU modifier list
456 */
457
458 UNIT cpu_unit = {
459 UDATA (NULL, UNIT_FIX+UNIT_BINK+EAE_DFLT+API_DFLT+PROT_DFLT,
460 MAXMEMSIZE)
461 };
462
463 REG cpu_reg[] = {
464 { ORDATA (PC, PC, ADDRSIZE) },
465 { ORDATA (AC, LAC, 18) },
466 { FLDATA (L, LAC, 18) },
467 { ORDATA (MQ, MQ, 18) },
468 { ORDATA (SC, SC, 6) },
469 { FLDATA (EAE_AC_SIGN, eae_ac_sign, 18) },
470 { ORDATA (SR, SR, 18) },
471 { ORDATA (ASW, ASW, ADDRSIZE) },
472 { ORDATA (IORS, iors, 18), REG_RO },
473 { BRDATA (INT, int_hwre, 8, 32, API_HLVL+1), REG_RO },
474 { FLDATA (INT_PEND, int_pend, 0), REG_RO },
475 { FLDATA (ION, ion, 0) },
476 { ORDATA (ION_DELAY, ion_defer, 2) },
477 #if defined (PDP7)
478 { FLDATA (TRAPM, usmd, 0) },
479 { FLDATA (TRAPP, trap_pending, 0) },
480 { FLDATA (EXTM, memm, 0) },
481 { FLDATA (EXTM_INIT, memm_init, 0) },
482 { FLDATA (EMIRP, emir_pending, 0) },
483 #endif
484 #if defined (PDP9)
485 { FLDATA (APIENB, api_enb, 0) },
486 { ORDATA (APIREQ, api_req, 8) },
487 { ORDATA (APIACT, api_act, 8) },
488 { ORDATA (BR, BR, ADDRSIZE) },
489 { FLDATA (USMD, usmd, 0) },
490 { FLDATA (USMDBUF, usmd_buf, 0) },
491 { FLDATA (USMDDEF, usmd_defer, 0) },
492 { FLDATA (NEXM, nexm, 0) },
493 { FLDATA (PRVN, prvn, 0) },
494 { FLDATA (TRAPP, trap_pending, 0) },
495 { FLDATA (EXTM, memm, 0) },
496 { FLDATA (EXTM_INIT, memm_init, 0) },
497 { FLDATA (EMIRP, emir_pending, 0) },
498 { FLDATA (RESTP, rest_pending, 0) },
499 { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) },
500 #endif
501 #if defined (PDP15)
502 { FLDATA (ION_INH, ion_inh, 0) },
503 { FLDATA (APIENB, api_enb, 0) },
504 { ORDATA (APIREQ, api_req, 8) },
505 { ORDATA (APIACT, api_act, 8) },
506 { ORDATA (XR, XR, 18) },
507 { ORDATA (LR, LR, 18) },
508 { ORDATA (BR, BR, 18) },
509 { ORDATA (RR, RR, 18) },
510 { ORDATA (MMR, MMR, 18) },
511 { FLDATA (USMD, usmd, 0) },
512 { FLDATA (USMDBUF, usmd_buf, 0) },
513 { FLDATA (USMDDEF, usmd_defer, 0) },
514 { FLDATA (NEXM, nexm, 0) },
515 { FLDATA (PRVN, prvn, 0) },
516 { FLDATA (TRAPP, trap_pending, 0) },
517 { FLDATA (BANKM, memm, 0) },
518 { FLDATA (BANKM_INIT, memm_init, 0) },
519 { FLDATA (RESTP, rest_pending, 0) },
520 { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) },
521 #endif
522 { BRDATA (PCQ, pcq, 8, ADDRSIZE, PCQ_SIZE), REG_RO+REG_CIRC },
523 { ORDATA (PCQP, pcq_p, 6), REG_HRO },
524 { FLDATA (STOP_INST, stop_inst, 0) },
525 { DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ },
526 { ORDATA (WRU, sim_int_char, 8) },
527 { NULL } };
528
529 MTAB cpu_mod[] = {
530 { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL },
531 { UNIT_NOEAE, 0, "EAE", "EAE", NULL },
532 #if defined (PDP9) || defined (PDP15)
533 { UNIT_NOAPI, UNIT_NOAPI, "no API", "NOAPI", NULL },
534 { UNIT_NOAPI, 0, "API", "API", NULL },
535 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, 0, "no memory protect",
536 "NOPROTECT", NULL },
537 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT, "memory protect",
538 "PROTECT", NULL },
539 #endif
540 #if defined (PDP15)
541 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC,
542 "memory relocation", "RELOCATION", NULL },
543 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC+UNIT_XVM,
544 "XVM", "XVM", NULL },
545 #endif
546 { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
547 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
548 #if defined (PDP4)
549 { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
550 #endif
551 { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
552 #if (MAXMEMSIZE > 8192)
553 { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
554 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
555 { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
556 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
557 { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
558 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
559 #endif
560 #if (MAXMEMSIZE > 32768)
561 { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
562 { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
563 { UNIT_MSIZE, 81920, NULL, "80K", &cpu_set_size },
564 { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size },
565 { UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size },
566 { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
567 #endif
568 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
569 &cpu_set_hist, &cpu_show_hist },
570 { 0 }
571 };
572
573 DEVICE cpu_dev = {
574 "CPU", &cpu_unit, cpu_reg, cpu_mod,
575 1, 8, ADDRSIZE, 1, 8, 18,
576 &cpu_ex, &cpu_dep, &cpu_reset,
577 NULL, NULL, NULL
578 };
579
sim_instr(void)580 t_stat sim_instr (void)
581 {
582 int32 api_int, api_usmd, skp;
583 int32 iot_data, device, pulse;
584 int32 last_IR;
585 t_stat reason;
586
587 if (build_dev_tab ()) /* build, chk tables */
588 return SCPE_STOP;
589 PC = PC & AMASK; /* clean variables */
590 LAC = LAC & LACMASK;
591 MQ = MQ & DMASK;
592 reason = 0;
593 last_IR = -1;
594 if (cpu_unit.flags & UNIT_NOAPI) /* no API? */
595 api_enb = api_req = api_act = 0;
596 api_int = api_eval (&int_pend); /* eval API */
597 api_usmd = 0; /* not API user cycle */
598
599 /* Main instruction fetch/decode loop */
600
601 while (reason == 0) { /* loop until halted */
602
603 int32 IR, MA, MB, esc, t, xct_count;
604 int32 link_init, fill;
605
606 if (sim_interval <= 0) { /* check clock queue */
607 if ((reason = sim_process_event ()))
608 break;
609 api_int = api_eval (&int_pend); /* eval API */
610 }
611
612 /* PDP-4 and PDP-7 traps and interrupts
613
614 PDP-4 no trap
615 PDP-7 trap: extend mode forced on, M[0] = PC, PC = 2
616 PDP-4, PDP-7 programmable interrupts only */
617
618 #if defined (PDP4) || defined (PDP7)
619 #if defined (PDP7)
620
621 if (trap_pending) { /* trap pending? */
622 PCQ_ENTRY; /* save old PC */
623 MB = Jms_word (1); /* save state */
624 ion = 0; /* interrupts off */
625 memm = 1; /* extend on */
626 emir_pending = trap_pending = 0; /* emir, trap off */
627 usmd = usmd_buf = 0; /* user mode off */
628 Write (0, MB, WR); /* save in 0 */
629 PC = 2; /* fetch next from 2 */
630 }
631
632 #endif
633
634 if (int_pend && ion && !ion_defer) { /* interrupt? */
635 PCQ_ENTRY; /* save old PC */
636 MB = Jms_word (usmd); /* save state */
637 ion = 0; /* interrupts off */
638 memm = 0; /* extend off */
639 emir_pending = rest_pending = 0; /* emir, restore off */
640 usmd = usmd_buf = 0; /* user mode off */
641 Write (0, MB, WR); /* physical write */
642 PC = 1; /* fetch next from 1 */
643 }
644
645 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
646 reason = STOP_IBKPT; /* stop simulation */
647 break;
648 }
649
650 #endif /* end PDP-4/PDP-7 */
651
652 /* PDP-9 and PDP-15 traps and interrupts
653
654 PDP-9 trap: extend mode ???, M[0/20] = PC, PC = 0/21
655 PDP-15 trap: bank mode unchanged, M[0/20] = PC, PC = 0/21
656 PDP-9, PDP-15 API and program interrupts */
657
658 #if defined (PDP9) || defined (PDP15)
659
660 if (trap_pending) { /* trap pending? */
661 PCQ_ENTRY; /* save old PC */
662 MB = Jms_word (1); /* save state */
663 if (ion) { /* int on? */
664 ion = 0; /* interrupts off */
665 MA = 0; /* treat like PI */
666 #if defined (PDP15)
667 ion_defer = 2; /* free instruction */
668 if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */
669 api_act = api_act | API_ML3; /* set lev 3 active */
670 api_int = api_eval (&int_pend); /* re-evaluate */
671 }
672 #endif
673 }
674 else MA = 020; /* sortof like CAL */
675 emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */
676 usmd = usmd_buf = 0; /* user mode off */
677 Write (MA, MB, WR); /* physical write */
678 PC = MA + 1; /* fetch next */
679 }
680
681 if (api_int && !ion_defer) { /* API intr? */
682 int32 i, lvl = api_int - 1; /* get req level */
683 if (hst_lnt) /* record */
684 cpu_intr_hist (HIST_API, lvl);
685 api_act = api_act | (API_ML0 >> lvl); /* set level active */
686 if (lvl >= API_HLVL) { /* software req? */
687 MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */
688 api_req = api_req & ~(API_ML0 >> lvl); /* remove request */
689 }
690 else {
691 MA = 0; /* assume fails */
692 for (i = 0; i < 32; i++) { /* loop hi to lo */
693 if ((int_hwre[lvl] >> i) & 1) { /* int req set? */
694 MA = api_vec[lvl][i]; /* get vector */
695 break; /* and stop */
696 }
697 }
698 }
699 if (MA == 0) { /* bad channel? */
700 reason = STOP_API; /* API error */
701 break;
702 }
703 api_int = api_eval (&int_pend); /* no API int */
704 api_usmd = usmd; /* API user mode cycle */
705 usmd = usmd_buf = 0; /* user mode off */
706 emir_pending = rest_pending = 0; /* emir, restore off */
707 xct_count = 0;
708 Read (MA, &IR, FE); /* fetch instruction */
709 goto xct_instr;
710 }
711
712 if (int_pend && ion && !ion_defer && /* int pending, enabled? */
713 !(api_enb && (api_act & API_MASKPI))) { /* API off or not masking PI? */
714 PCQ_ENTRY; /* save old PC */
715 if (hst_lnt) /* record */
716 cpu_intr_hist (HIST_PI, 0);
717 MB = Jms_word (usmd); /* save state */
718 ion = 0; /* interrupts off */
719 ion_defer = 2; /* free instruction */
720 #if defined (PDP9) /* PDP-9, */
721 memm = 0; /* extend off */
722 #else /* PDP-15 */
723 if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */
724 api_act = api_act | API_ML3; /* set lev 3 active */
725 api_int = api_eval (&int_pend); /* re-evaluate */
726 }
727 #endif
728 emir_pending = rest_pending = 0; /* emir, restore off */
729 usmd = usmd_buf = 0; /* user mode off */
730 Write (0, MB, WR); /* physical write */
731 PC = 1; /* fetch next from 1 */
732 }
733
734 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
735 reason = STOP_IBKPT; /* stop simulation */
736 break;
737 }
738 if (!usmd_defer) /* no IOT? load usmd */
739 usmd = usmd_buf;
740 else usmd_defer = 0; /* cancel defer */
741
742 #endif /* PDP-9/PDP-15 */
743
744 /* Instruction fetch and address decode */
745
746 xct_count = 0; /* track nested XCT's */
747 MA = PC; /* fetch at PC */
748 if (Read (MA, &IR, FE)) /* fetch instruction */
749 continue;
750 PC = Incr_addr (PC); /* increment PC */
751
752 xct_instr: /* label for API, XCT */
753 if (hst_lnt) /* history? */
754 cpu_inst_hist (MA, IR);
755 if (ion_defer) /* count down defer */
756 ion_defer = ion_defer - 1;
757 if (sim_interval)
758 sim_interval = sim_interval - 1;
759
760 #if defined (PDP15) /* PDP15 */
761
762 if (memm) /* bank mode dir addr */
763 MA = (MA & B_EPCMASK) | (IR & B_DAMASK);
764 else MA = (MA & P_EPCMASK) | (IR & P_DAMASK); /* page mode dir addr */
765
766 #else /* others */
767
768 MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode only */
769
770 #endif
771
772 switch ((IR >> 13) & 037) { /* decode IR<0:4> */
773
774 /* LAC: opcode 20 */
775
776 case 011: /* LAC, indir */
777 if (Ia (MA, &MA, 0))
778 break;
779 case 010: /* LAC, dir */
780 INDEX (IR, MA);
781 if (Read (MA, &MB, RD))
782 break;
783 LAC = (LAC & LINK) | MB;
784 break;
785
786 /* DAC: opcode 04 */
787
788 case 003: /* DAC, indir */
789 if (Ia (MA, &MA, 0))
790 break;
791 case 002: /* DAC, dir */
792 INDEX (IR, MA);
793 Write (MA, LAC & DMASK, WR);
794 break;
795
796 /* DZM: opcode 14 */
797
798 case 007: /* DZM, indir */
799 if (Ia (MA, &MA, 0))
800 break;
801 case 006: /* DZM, direct */
802 INDEX (IR, MA);
803 Write (MA, 0, WR);
804 break;
805
806 /* AND: opcode 50 */
807
808 case 025: /* AND, ind */
809 if (Ia (MA, &MA, 0))
810 break;
811 case 024: /* AND, dir */
812 INDEX (IR, MA);
813 if (Read (MA, &MB, RD))
814 break;
815 LAC = LAC & (MB | LINK);
816 break;
817
818 /* XOR: opcode 24 */
819
820 case 013: /* XOR, ind */
821 if (Ia (MA, &MA, 0))
822 break;
823 case 012: /* XOR, dir */
824 INDEX (IR, MA);
825 if (Read (MA, &MB, RD))
826 break;
827 LAC = LAC ^ MB;
828 break;
829
830 /* ADD: opcode 30 */
831
832 case 015: /* ADD, indir */
833 if (Ia (MA, &MA, 0))
834 break;
835 case 014: /* ADD, dir */
836 INDEX (IR, MA);
837 if (Read (MA, &MB, RD))
838 break;
839 t = (LAC & DMASK) + MB;
840 if (t > DMASK) /* end around carry */
841 t = (t + 1) & DMASK;
842 if (((~LAC ^ MB) & (LAC ^ t)) & SIGN) /* overflow? */
843 LAC = LINK | t; /* set link */
844 else LAC = (LAC & LINK) | t;
845 break;
846
847 /* TAD: opcode 34 */
848
849 case 017: /* TAD, indir */
850 if (Ia (MA, &MA, 0))
851 break;
852 case 016: /* TAD, dir */
853 INDEX (IR, MA);
854 if (Read (MA, &MB, RD))
855 break;
856 LAC = (LAC + MB) & LACMASK;
857 break;
858
859 /* ISZ: opcode 44 */
860
861 case 023: /* ISZ, indir */
862 if (Ia (MA, &MA, 0))
863 break;
864 case 022: /* ISZ, dir */
865 INDEX (IR, MA);
866 if (Read (MA, &MB, RD))
867 break;
868 MB = (MB + 1) & DMASK;
869 if (Write (MA, MB, WR))
870 break;
871 if (MB == 0)
872 PC = Incr_addr (PC);
873 break;
874
875 /* SAD: opcode 54 */
876
877 case 027: /* SAD, indir */
878 if (Ia (MA, &MA, 0))
879 break;
880 case 026: /* SAD, dir */
881 INDEX (IR, MA);
882 if (Read (MA, &MB, RD))
883 break;
884 if ((LAC & DMASK) != MB)
885 PC = Incr_addr (PC);
886 break;
887
888 /* XCT: opcode 40 */
889
890 case 021: /* XCT, indir */
891 if (Ia (MA, &MA, 0))
892 break;
893 case 020: /* XCT, dir */
894 INDEX (IR, MA);
895 if ((api_usmd | usmd) && (xct_count != 0)) { /* chained and usmd? */
896 if (usmd) /* trap if usmd */
897 prvn = trap_pending = 1;
898 break; /* nop if api_usmd */
899 }
900 if (xct_count >= xct_max) { /* too many XCT's? */
901 reason = STOP_XCT;
902 break;
903 }
904 xct_count = xct_count + 1; /* count XCT's */
905 #if defined (PDP9)
906 ion_defer = 1; /* defer intr */
907 #endif
908 if (Read (MA, &IR, FE)) /* fetch inst, mm err? */
909 break;
910 goto xct_instr; /* go execute */
911
912 /* CAL: opcode 00 - api_usmd records whether usmd = 1 at start of API cycle
913
914 On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20
915 On the PDP-9 and PDP-15, CAL clears user mode
916 On the PDP-9 and PDP-15 with API, CAL activates level 4
917 On the PDP-15, CAL goes to absolute 20, regardless of mode */
918
919 case 001: case 000: /* CAL */
920 t = usmd; /* save user mode */
921 #if defined (PDP15) /* PDP15 */
922 MA = 020; /* MA = abs 20 */
923 ion_defer = 1; /* "free instruction" */
924 #else /* others */
925 if (memm) /* if ext, abs 20 */
926 MA = 020;
927 else MA = (PC & B_EPCMASK) | 020; /* else bank-rel 20 */
928 #endif
929 #if defined (PDP9) || defined (PDP15)
930 usmd = usmd_buf = 0; /* clear user mode */
931 if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */
932 #if defined (PDP15) /* PDP15: if 0-3 inactive */
933 if ((api_act & (API_ML0|API_ML1|API_ML2|API_ML3)) == 0)
934 #endif
935 api_act = api_act | API_ML4;
936 api_int = api_eval (&int_pend);
937 }
938 #endif
939 if (IR & I_IND) { /* indirect? */
940 if (Ia (MA, &MA, 0))
941 break;
942 }
943 PCQ_ENTRY;
944 MB = Jms_word (api_usmd | t); /* save state */
945 Write (MA, MB, WR);
946 PC = Incr_addr (MA);
947 break;
948
949 /* JMS: opcode 010 - api_usmd records whether usmd = 1 at start of API cycle */
950
951 case 005: /* JMS, indir */
952 if (Ia (MA, &MA, 0))
953 break;
954 case 004: /* JMS, dir */
955 INDEX (IR, MA);
956 PCQ_ENTRY;
957 #if defined (PDP15) /* PDP15 */
958 if (!usmd) /* "free instruction" */
959 ion_defer = 1;
960 #endif
961 MB = Jms_word (api_usmd | usmd); /* save state */
962 if (Write (MA, MB, WR))
963 break;
964 PC = Incr_addr (MA) & AMASK;
965 break;
966
967 /* JMP: opcode 60 */
968
969 case 031: /* JMP, indir */
970 if (Ia (MA, &MA, 1))
971 break;
972 INDEX (IR, MA);
973 PCQ_ENTRY; /* save old PC */
974 PC = MA & AMASK;
975 break;
976
977 /* JMP direct - check for idle */
978
979 case 030: /* JMP, dir */
980 INDEX (IR, MA);
981 PCQ_ENTRY; /* save old PC */
982 if (sim_idle_enab) { /* idling enabled? */
983 t_bool iof = (ion_inh != 0) || /* IOF if inhibited */
984 ((ion == 0) && (api_enb == 0)); /* or PI and api off */
985 if (((MA ^ (PC - 2)) & AMASK) == 0) { /* 1) JMP *-1? */
986 if (iof && (last_IR == OP_KSF) && /* iof, prv KSF, */
987 !TST_INT (TTI)) /* no TTI flag? */
988 sim_idle (0, FALSE); /* we're idle */
989 }
990 else if (((MA ^ (PC - 1)) & AMASK) == 0) { /* 2) JMP *? */
991 if (iof) /* iof? inf loop */
992 reason = STOP_LOOP;
993 else sim_idle (0, FALSE); /* ion? idle */
994 }
995 } /* end idle */
996 PC = MA & AMASK;
997 break;
998
999 /* OPR: opcode 74 */
1000
1001 case 037: /* OPR, indir */
1002 LAC = (LAC & LINK) | IR; /* LAW */
1003 break;
1004
1005 case 036: /* OPR, dir */
1006 skp = 0; /* assume no skip */
1007 switch ((IR >> 6) & 017) { /* decode IR<8:11> */
1008 case 0: /* nop */
1009 break;
1010 case 1: /* SMA */
1011 if ((LAC & SIGN) != 0)
1012 skp = 1;
1013 break;
1014 case 2: /* SZA */
1015 if ((LAC & DMASK) == 0)
1016 skp = 1;
1017 break;
1018 case 3: /* SZA | SMA */
1019 if (((LAC & DMASK) == 0) || ((LAC & SIGN) != 0))
1020 skp = 1;
1021 break;
1022 case 4: /* SNL */
1023 if (LAC >= LINK)
1024 skp = 1;
1025 break;
1026 case 5: /* SNL | SMA */
1027 if (LAC >= SIGN)
1028 skp = 1;
1029 break;
1030 case 6: /* SNL | SZA */
1031 if ((LAC >= LINK) || (LAC == 0))
1032 skp = 1;
1033 break;
1034 case 7: /* SNL | SZA | SMA */
1035 if ((LAC >= SIGN) || (LAC == 0))
1036 skp = 1;
1037 break;
1038 case 010: /* SKP */
1039 skp = 1;
1040 break;
1041 case 011: /* SPA */
1042 if ((LAC & SIGN) == 0)
1043 skp = 1;
1044 break;
1045 case 012: /* SNA */
1046 if ((LAC & DMASK) != 0)
1047 skp = 1;
1048 break;
1049 case 013: /* SNA & SPA */
1050 if (((LAC & DMASK) != 0) && ((LAC & SIGN) == 0))
1051 skp = 1;
1052 break;
1053 case 014: /* SZL */
1054 if (LAC < LINK)
1055 skp = 1;
1056 break;
1057 case 015: /* SZL & SPA */
1058 if (LAC < SIGN)
1059 skp = 1;
1060 break;
1061 case 016: /* SZL & SNA */
1062 if ((LAC < LINK) && (LAC != 0))
1063 skp = 1;
1064 break;
1065 case 017: /* SZL & SNA & SPA */
1066 if ((LAC < SIGN) && (LAC != 0))
1067 skp = 1;
1068 break;
1069 } /* end switch skips */
1070
1071 switch (((IR >> 9) & 014) | (IR & 03)) { /* IR<5:6,16:17> */
1072 case 0: /* NOP */
1073 break;
1074 case 1: /* CMA */
1075 LAC = LAC ^ DMASK;
1076 break;
1077 case 2: /* CML */
1078 LAC = LAC ^ LINK;
1079 break;
1080 case 3: /* CML CMA */
1081 LAC = LAC ^ LACMASK;
1082 break;
1083 case 4: /* CLL */
1084 LAC = LAC & DMASK;
1085 break;
1086 case 5: /* CLL CMA */
1087 LAC = (LAC & DMASK) ^ DMASK;
1088 break;
1089 case 6: /* CLL CML = STL */
1090 LAC = LAC | LINK;
1091 break;
1092 case 7: /* CLL CML CMA */
1093 LAC = (LAC | LINK) ^ DMASK;
1094 break;
1095 case 010: /* CLA */
1096 LAC = LAC & LINK;
1097 break;
1098 case 011: /* CLA CMA = STA */
1099 LAC = LAC | DMASK;
1100 break;
1101 case 012: /* CLA CML */
1102 LAC = (LAC & LINK) ^ LINK;
1103 break;
1104 case 013: /* CLA CML CMA */
1105 LAC = (LAC | DMASK) ^ LINK;
1106 break;
1107 case 014: /* CLA CLL */
1108 LAC = 0;
1109 break;
1110 case 015: /* CLA CLL CMA */
1111 LAC = DMASK;
1112 break;
1113 case 016: /* CLA CLL CML */
1114 LAC = LINK;
1115 break;
1116 case 017: /* CLA CLL CML CMA */
1117 LAC = LACMASK;
1118 break;
1119 } /* end decode */
1120
1121 if (IR & 0000004) { /* OAS */
1122 #if defined (PDP9) || defined (PDP15)
1123 if (usmd) /* trap if usmd */
1124 prvn = trap_pending = 1;
1125 else if (!api_usmd) /* nop if api_usmd */
1126 #endif
1127 LAC = LAC | SR;
1128 }
1129
1130 switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */
1131 case 1: /* RAL */
1132 LAC = ((LAC << 1) | (LAC >> 18)) & LACMASK;
1133 break;
1134 case 2: /* RAR */
1135 LAC = ((LAC >> 1) | (LAC << 18)) & LACMASK;
1136 break;
1137 case 3: /* RAL RAR */
1138 #if defined (PDP15) /* PDP-15 */
1139 LAC = (LAC + 1) & LACMASK; /* IAC */
1140 #else /* PDP-4,-7,-9 */
1141 reason = stop_inst; /* undefined */
1142 #endif
1143 break;
1144 case 5: /* RTL */
1145 LAC = ((LAC << 2) | (LAC >> 17)) & LACMASK;
1146 break;
1147 case 6: /* RTR */
1148 LAC = ((LAC >> 2) | (LAC << 17)) & LACMASK;
1149 break;
1150 case 7: /* RTL RTR */
1151 #if defined (PDP15) /* PDP-15 */
1152 LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) |
1153 (LAC & LINK); /* BSW */
1154 #else /* PDP-4,-7,-9 */
1155 reason = stop_inst; /* undefined */
1156 #endif
1157 break;
1158 } /* end switch rotate */
1159
1160 if (IR & 0000040) { /* HLT */
1161 if (usmd) /* trap if usmd */
1162 prvn = trap_pending = 1;
1163 else if (!api_usmd) /* nop if api_usmd */
1164 reason = STOP_HALT;
1165 }
1166 if (skp) /* if skip, inc PC */
1167 PC = Incr_addr (PC);
1168 break; /* end OPR */
1169
1170 /* EAE: opcode 64
1171
1172 The EAE is microprogrammed to execute variable length signed and
1173 unsigned shift, multiply, divide, and normalize. Most commands are
1174 controlled by a six bit step counter (SC). In the hardware, the step
1175 counter is complemented on load and then counted up to zero; timing
1176 guarantees an initial increment, which completes the two's complement
1177 load. In the simulator, the SC is loaded normally and then counted
1178 down to zero; the read SC command compensates. */
1179
1180 case 033: case 032: /* EAE */
1181 if (cpu_unit.flags & UNIT_NOEAE) /* disabled? */
1182 break;
1183 if (IR & 0020000) /* IR<4>? AC0 to L */
1184 LAC = ((LAC << 1) & LINK) | (LAC & DMASK);
1185 if (IR & 0010000) /* IR<5>? clear MQ */
1186 MQ = 0;
1187 if ((IR & 0004000) && (LAC & SIGN)) /* IR<6> and minus? */
1188 eae_ac_sign = LINK; /* set eae_ac_sign */
1189 else eae_ac_sign = 0; /* if not, unsigned */
1190 if (IR & 0002000) /* IR<7>? or AC */
1191 MQ = (MQ | LAC) & DMASK;
1192 else if (eae_ac_sign) /* if not, |AC| */
1193 LAC = LAC ^ DMASK;
1194 if (IR & 0001000) /* IR<8>? clear AC */
1195 LAC = LAC & LINK;
1196 link_init = LAC & LINK; /* link temporary */
1197 fill = link_init? DMASK: 0; /* fill = link */
1198 esc = IR & 077; /* get eff SC */
1199 switch ((IR >> 6) & 07) { /* case on IR<9:11> */
1200
1201 case 0: /* setup */
1202 if (IR & 04) /* IR<15>? ~MQ */
1203 MQ = MQ ^ DMASK;
1204 if (IR & 02) /* IR<16>? or MQ */
1205 LAC = LAC | MQ;
1206 if (IR & 01) /* IR<17>? or SC */
1207 LAC = LAC | ((-SC) & 077);
1208 break;
1209
1210 /* Multiply uses a shift and add algorithm. The PDP-15, unlike prior
1211 implementations, factors IR<6> (signed multiply) into the calculation
1212 of the result sign. */
1213
1214 case 1: /* multiply */
1215 if (Read (PC, &MB, FE)) /* get next word */
1216 break;
1217 PC = Incr_addr (PC); /* increment PC */
1218 if (eae_ac_sign) /* EAE AC sign? ~MQ */
1219 MQ = MQ ^ DMASK;
1220 LAC = LAC & DMASK; /* clear link */
1221 SC = esc; /* init SC */
1222 do { /* loop */
1223 if (MQ & 1) /* MQ<17>? add */
1224 LAC = LAC + MB;
1225 MQ = (MQ >> 1) | ((LAC & 1) << 17);
1226 LAC = LAC >> 1; /* shift AC'MQ right */
1227 SC = (SC - 1) & 077; /* decrement SC */
1228 } while (SC != 0); /* until SC = 0 */
1229 #if defined (PDP15)
1230 if ((IR & 0004000) && (eae_ac_sign ^ link_init)) {
1231 #else
1232 if (eae_ac_sign ^ link_init) { /* result negative? */
1233 #endif
1234 LAC = LAC ^ DMASK;
1235 MQ = MQ ^ DMASK;
1236 }
1237 break;
1238
1239 /* Divide uses a non-restoring divide. Divide uses a subtract and shift
1240 algorithm. The quotient is generated in true form. The PDP-15, unlike
1241 prior implementations, factors IR<6> (signed divide) into the calculation
1242 of the result sign. */
1243
1244 case 3: /* divide */
1245 if (Read (PC, &MB, FE)) /* get next word */
1246 break;
1247 PC = Incr_addr (PC); /* increment PC */
1248 if (eae_ac_sign) /* EAE AC sign? ~MQ */
1249 MQ = MQ ^ DMASK;
1250 if ((LAC & DMASK) >= MB) { /* overflow? */
1251 LAC = (LAC - MB) | LINK; /* set link */
1252 break;
1253 }
1254 LAC = LAC & DMASK; /* clear link */
1255 t = 0; /* init loop */
1256 SC = esc; /* init SC */
1257 do { /* loop */
1258 if (t)
1259 LAC = (LAC + MB) & LACMASK;
1260 else LAC = (LAC - MB) & LACMASK;
1261 t = (LAC >> 18) & 1; /* quotient bit */
1262 if (SC > 1) /* skip if last */
1263 LAC =((LAC << 1) | (MQ >> 17)) & LACMASK;
1264 MQ = ((MQ << 1) | (t ^ 1)) & DMASK; /* shift in quo bit */
1265 SC = (SC - 1) & 077; /* decrement SC */
1266 } while (SC != 0); /* until SC = 0 */
1267 if (t)
1268 LAC = (LAC + MB) & LACMASK;
1269 if (eae_ac_sign) /* sgn rem = sgn divd */
1270 LAC = LAC ^ DMASK;
1271 #if defined (PDP15)
1272 if ((IR & 0004000) && (eae_ac_sign ^ link_init))
1273 #else
1274 if (eae_ac_sign ^ link_init) /* result negative? */
1275 #endif
1276 MQ = MQ ^ DMASK;
1277 break;
1278
1279 /* EAE shifts, whether left or right, fill from the link. If the
1280 operand sign has been copied to the link, this provides correct
1281 sign extension for one's complement numbers. */
1282
1283 case 4: /* normalize */
1284 #if defined (PDP15)
1285 if (!usmd) /* free instructions */
1286 ion_defer = 2;
1287 #endif
1288 for (SC = esc; ((LAC & SIGN) == ((LAC << 1) & SIGN)); ) {
1289 LAC = (LAC << 1) | ((MQ >> 17) & 1);
1290 MQ = (MQ << 1) | (link_init >> 18);
1291 SC = (SC - 1) & 077;
1292 if (SC == 0)
1293 break;
1294 }
1295 LAC = link_init | (LAC & DMASK); /* trim AC, restore L */
1296 MQ = MQ & DMASK; /* trim MQ */
1297 SC = SC & 077; /* trim SC */
1298 break;
1299
1300 case 5: /* long right shift */
1301 if (esc < 18) {
1302 MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & DMASK;
1303 LAC = ((fill << (18 - esc)) | (LAC >> esc)) & LACMASK;
1304 }
1305 else {
1306 if (esc < 36)
1307 MQ = ((fill << (36 - esc)) | (LAC >> (esc - 18))) & DMASK;
1308 else MQ = fill;
1309 LAC = link_init | fill;
1310 }
1311 SC = 0; /* clear step count */
1312 break;
1313
1314 case 6: /* long left shift */
1315 if (esc < 18) {
1316 LAC = link_init | (((LAC << esc) | (MQ >> (18 - esc))) & DMASK);
1317 MQ = ((MQ << esc) | (fill >> (18 - esc))) & DMASK;
1318 }
1319 else {
1320 if (esc < 36)
1321 LAC = link_init | (((MQ << (esc - 18)) | (fill >> (36 - esc))) & DMASK);
1322 else LAC = link_init | fill;
1323 MQ = fill;
1324 }
1325 SC = 0; /* clear step count */
1326 break;
1327
1328 case 7: /* AC left shift */
1329 if (esc < 18)
1330 LAC = link_init | (((LAC << esc) | (fill >> (18 - esc))) & DMASK);
1331 else LAC = link_init | fill;
1332 SC = 0; /* clear step count */
1333 break;
1334 } /* end switch IR */
1335 break; /* end case EAE */
1336
1337 /* PDP-15 index operates: opcode 72 */
1338
1339 case 035: /* index operates */
1340
1341 #if defined (PDP15)
1342 t = (IR & 0400)? (IR | 0777000): (IR & 0377); /* sext immediate */
1343 switch ((IR >> 9) & 017) { /* case on IR<5:8> */
1344 case 001: /* PAX */
1345 XR = LAC & DMASK;
1346 break;
1347 case 002: /* PAL */
1348 LR = LAC & DMASK;
1349 break;
1350 case 003: /* AAC */
1351 LAC = (LAC & LINK) | ((LAC + t) & DMASK);
1352 break;
1353 case 004: /* PXA */
1354 LAC = (LAC & LINK) | XR;
1355 break;
1356 case 005: /* AXS */
1357 XR = (XR + t) & DMASK;
1358 if (SEXT (XR) >= SEXT (LR))
1359 PC = Incr_addr (PC);
1360 break;
1361 case 006: /* PXL */
1362 LR = XR;
1363 break;
1364 case 010: /* PLA */
1365 LAC = (LAC & LINK) | LR;
1366 break;
1367 case 011: /* PLX */
1368 XR = LR;
1369 break;
1370 case 014: /* CLAC */
1371 LAC = LAC & LINK;
1372 break;
1373 case 015: /* CLX */
1374 XR = 0;
1375 break;
1376 case 016: /* CLLR */
1377 LR = 0;
1378 break;
1379 case 017: /* AXR */
1380 XR = (XR + t) & DMASK;
1381 break;
1382 } /* end switch IR */
1383 break; /* end case */
1384 #endif
1385
1386 /* IOT: opcode 70
1387
1388 The 18b PDP's have different definitions of various control IOT's.
1389
1390 IOT PDP-4 PDP-7 PDP-9 PDP-15
1391
1392 700002 IOF IOF IOF IOF
1393 700022 undefined undefined undefined ORMM (XVM)
1394 700042 ION ION ION ION
1395 700024 undefined undefined undefined LDMM (XVM)
1396 700062 undefined ITON undefined undefined
1397 701701 undefined undefined MPSK MPSK
1398 701741 undefined undefined MPSNE MPSNE
1399 701702 undefined undefined MPCV MPCV
1400 701722 undefined undefined undefined MPRC (XVM)
1401 701742 undefined undefined MPEU MPEU
1402 701704 undefined undefined MPLD MPLD
1403 701724 undefined undefined undefined MPLR (KT15, XVM)
1404 701744 undefined undefined MPCNE MPCNE
1405 701764 undefined undefined undefined IPFH (XVM)
1406 703201 undefined undefined PFSF PFSF
1407 703301 undefined TTS TTS TTS
1408 703341 undefined SKP7 SKP7 SPCO
1409 703302 undefined CAF CAF CAF
1410 703304 undefined undefined DBK DBK
1411 703344 undefined undefined DBR DBR
1412 705501 undefined undefined SPI SPI
1413 705521 undefined undefined undefined ENB
1414 705502 undefined undefined RPL RPL
1415 705522 undefined undefined undefined INH
1416 705504 undefined undefined ISA ISA
1417 707701 undefined SEM SEM undefined
1418 707741 undefined undefined undefined SKP15
1419 707761 undefined undefined undefined SBA
1420 707702 undefined EEM EEM undefined
1421 707742 undefined EMIR EMIR RES
1422 707762 undefined undefined undefined DBA
1423 707704 undefined LEM LEM undefined
1424 707764 undefined undefined undefined EBA */
1425
1426 case 034: /* IOT */
1427 #if defined (PDP15)
1428 if (IR & 0010000) { /* floating point? */
1429 reason = fp15 (IR); /* process */
1430 break;
1431 }
1432 #endif
1433 if ((api_usmd | usmd) && /* user, not XVM UIOT? */
1434 (!XVM || !(MMR & MM_UIOT))) {
1435 if (usmd) /* trap if user */
1436 prvn = trap_pending = 1;
1437 break; /* nop if api_usmd */
1438 }
1439 device = (IR >> 6) & 077; /* device = IR<6:11> */
1440 pulse = IR & 067; /* pulse = IR<12:17> */
1441 if (IR & 0000010) /* clear AC? */
1442 LAC = LAC & LINK;
1443 iot_data = LAC & DMASK; /* AC unchanged */
1444
1445 /* PDP-4 system IOT's */
1446
1447 #if defined (PDP4)
1448 switch (device) { /* decode IR<6:11> */
1449
1450 case 0: /* CPU and clock */
1451 if (pulse == 002) /* IOF */
1452 ion = 0;
1453 else if (pulse == 042) /* ION */
1454 ion = ion_defer = 1;
1455 else iot_data = clk (device, pulse, iot_data);
1456 break;
1457 #endif
1458
1459 /* PDP-7 system IOT's */
1460
1461 #if defined (PDP7)
1462 switch (device) { /* decode IR<6:11> */
1463
1464 case 0: /* CPU and clock */
1465 if (pulse == 002) /* IOF */
1466 ion = 0;
1467 else if (pulse == 042) /* ION */
1468 ion = ion_defer = 1;
1469 else if (pulse == 062) /* ITON */
1470 usmd = usmd_buf = ion = ion_defer = 1;
1471 else iot_data = clk (device, pulse, iot_data);
1472 break;
1473
1474 case 033: /* CPU control */
1475 if ((pulse == 001) || (pulse == 041))
1476 PC = Incr_addr (PC);
1477 else if (pulse == 002) /* CAF - skip CPU */
1478 reset_all (1);
1479 break;
1480
1481 case 077: /* extended memory */
1482 if ((pulse == 001) && memm)
1483 PC = Incr_addr (PC);
1484 else if (pulse == 002) /* EEM */
1485 memm = 1;
1486 else if (pulse == 042) /* EMIR */
1487 memm = emir_pending = 1; /* ext on, restore */
1488 else if (pulse == 004) /* LEM */
1489 memm = 0;
1490 break;
1491 #endif
1492
1493 /* PDP-9 system IOT's */
1494
1495 #if defined (PDP9)
1496 ion_defer = 1; /* delay interrupts */
1497 usmd_defer = 1; /* defer load user */
1498 switch (device) { /* decode IR<6:11> */
1499
1500 case 000: /* CPU and clock */
1501 if (pulse == 002) /* IOF */
1502 ion = 0;
1503 else if (pulse == 042) /* ION */
1504 ion = ion_defer = 1;
1505 else iot_data = clk (device, pulse, iot_data);
1506 break;
1507
1508 case 017: /* mem protection */
1509 if (PROT) { /* enabled? */
1510 if ((pulse == 001) && prvn) /* MPSK */
1511 PC = Incr_addr (PC);
1512 else if ((pulse == 041) && nexm) /* MPSNE */
1513 PC = Incr_addr (PC);
1514 else if (pulse == 002) /* MPCV */
1515 prvn = 0;
1516 else if (pulse == 042) /* MPEU */
1517 usmd_buf = 1;
1518 else if (pulse == 004) /* MPLD */
1519 BR = LAC & BRMASK;
1520 else if (pulse == 044) /* MPCNE */
1521 nexm = 0;
1522 }
1523 else reason = stop_inst;
1524 break;
1525
1526 case 032: /* power fail */
1527 if ((pulse == 001) && (TST_INT (PWRFL)))
1528 PC = Incr_addr (PC);
1529 break;
1530
1531 case 033: /* CPU control */
1532 if ((pulse == 001) || (pulse == 041))
1533 PC = Incr_addr (PC);
1534 else if (pulse == 002) { /* CAF */
1535 reset_all (1); /* reset all exc CPU */
1536 cpu_caf (); /* CAF to CPU */
1537 }
1538 else if (pulse == 044) /* DBR */
1539 rest_pending = 1;
1540 if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
1541 int32 t = api_ffo[api_act & 0377];
1542 api_act = api_act & ~(API_ML0 >> t);
1543 }
1544 break;
1545
1546 case 055: /* API control */
1547 if (cpu_unit.flags & UNIT_NOAPI)
1548 reason = stop_inst;
1549 else if (pulse == 001) { /* SPI */
1550 if (((LAC & SIGN) && api_enb) ||
1551 ((LAC & 0377) > api_act))
1552 iot_data = iot_data | IOT_SKP;
1553 }
1554 else if (pulse == 002) { /* RPL */
1555 iot_data = iot_data | (api_enb << 17) |
1556 (api_req << 8) | api_act;
1557 }
1558 else if (pulse == 004) { /* ISA */
1559 api_enb = (iot_data & SIGN)? 1: 0;
1560 api_req = api_req | ((LAC >> 8) & 017);
1561 api_act = api_act | (LAC & 0377);
1562 }
1563 break;
1564
1565 case 077: /* extended memory */
1566 if ((pulse == 001) && memm)
1567 PC = Incr_addr (PC);
1568 else if (pulse == 002) /* EEM */
1569 memm = 1;
1570 else if (pulse == 042) /* EMIR */
1571 memm = emir_pending = 1; /* ext on, restore */
1572 else if (pulse == 004) /* LEM */
1573 memm = 0;
1574 break;
1575 #endif
1576
1577 /* PDP-15 system IOT's - includes "re-entrancy ECO" ENB/INH as standard */
1578
1579 #if defined (PDP15)
1580 ion_defer = 1; /* delay interrupts */
1581 usmd_defer = 1; /* defer load user */
1582 switch (device) { /* decode IR<6:11> */
1583
1584 case 000: /* CPU and clock */
1585 if (pulse == 002) /* IOF */
1586 ion = 0;
1587 else if (pulse == 042) /* ION */
1588 ion = ion_defer = 1;
1589 else if (XVM && (pulse == 022)) /* ORMM/RDMM */
1590 iot_data = MMR;
1591 else if (XVM && (pulse == 024)) /* LDMM */
1592 MMR = iot_data;
1593 else iot_data = clk (device, pulse, iot_data);
1594 break;
1595
1596 case 017: /* mem protection */
1597 if (PROT) { /* enabled? */
1598 t = XVM? BRMASK_XVM: BRMASK;
1599 if ((pulse == 001) && prvn) /* MPSK */
1600 PC = Incr_addr (PC);
1601 else if ((pulse == 041) && nexm) /* MPSNE */
1602 PC = Incr_addr (PC);
1603 else if (pulse == 002) /* MPCV */
1604 prvn = 0;
1605 else if (pulse == 042) /* MPEU */
1606 usmd_buf = 1;
1607 else if (XVM && (pulse == 062)) /* RDCLK */
1608 iot_data = clk_task_upd (TRUE);
1609 else if (pulse == 004) /* MPLD */
1610 BR = LAC & t;
1611 else if (RELOC && (pulse == 024)) /* MPLR */
1612 RR = LAC & t;
1613 else if (pulse == 044) /* MPCNE */
1614 nexm = 0;
1615 }
1616 else reason = stop_inst;
1617 break;
1618
1619 case 032: /* power fail */
1620 if ((pulse == 001) && (TST_INT (PWRFL)))
1621 PC = Incr_addr (PC);
1622 break;
1623
1624 case 033: /* CPU control */
1625 if ((pulse == 001) || (pulse == 041))
1626 PC = Incr_addr (PC);
1627 else if (pulse == 002) { /* CAF */
1628 reset_all (2); /* reset all exc CPU, FP15 */
1629 cpu_caf (); /* CAF to CPU */
1630 }
1631 else if (pulse == 044) /* DBR */
1632 rest_pending = 1;
1633 if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
1634 int32 t = api_ffo[api_act & 0377];
1635 api_act = api_act & ~(API_ML0 >> t);
1636 }
1637 break;
1638
1639 case 055: /* API control */
1640 if (cpu_unit.flags & UNIT_NOAPI)
1641 reason = stop_inst;
1642 else if (pulse == 001) { /* SPI */
1643 if (((LAC & SIGN) && api_enb) ||
1644 ((LAC & 0377) > api_act))
1645 iot_data = iot_data | IOT_SKP;
1646 }
1647 else if (pulse == 002) { /* RPL */
1648 iot_data = iot_data | (api_enb << 17) |
1649 (api_req << 8) | api_act;
1650 }
1651 else if (pulse == 004) { /* ISA */
1652 api_enb = (iot_data & SIGN)? 1: 0;
1653 api_req = api_req | ((LAC >> 8) & 017);
1654 api_act = api_act | (LAC & 0377);
1655 }
1656 else if (pulse == 021) /* ENB */
1657 ion_inh = 0;
1658 else if (pulse == 022) /* INH */
1659 ion_inh = 1;
1660 break;
1661
1662 case 077: /* bank addressing */
1663 if ((pulse == 041) || ((pulse == 061) && memm))
1664 PC = Incr_addr (PC); /* SKP15, SBA */
1665 else if (pulse == 042) /* RES */
1666 rest_pending = 1;
1667 else if (pulse == 062) /* DBA */
1668 memm = 0;
1669 else if (pulse == 064) /* EBA */
1670 memm = 1;
1671 break;
1672 #endif
1673
1674 /* IOT, continued */
1675
1676 default: /* devices */
1677 if (dev_tab[device]) /* defined? */
1678 iot_data = dev_tab[device] (device, pulse, iot_data);
1679 else reason = stop_inst; /* stop on flag */
1680 break;
1681 } /* end switch device */
1682
1683 LAC = LAC | (iot_data & DMASK);
1684 if (iot_data & IOT_SKP)
1685 PC = Incr_addr (PC);
1686 if (iot_data >= IOT_REASON)
1687 reason = iot_data >> IOT_V_REASON;
1688 api_int = api_eval (&int_pend); /* eval API */
1689 break; /* end case IOT */
1690 } /* end switch opcode */
1691
1692 api_usmd = 0; /* API cycle over */
1693 last_IR = IR; /* save IR for next */
1694 } /* end while */
1695
1696 /* Simulation halted */
1697
1698 iors = upd_iors (); /* get IORS */
1699 pcq_r->qptr = pcq_p; /* update pc q ptr */
1700 return reason;
1701 }
1702
1703 /* Evaluate API */
1704
1705 int32 api_eval (int32 *pend)
1706 {
1707 int32 i, hi;
1708
1709 *pend = 0; /* assume no intr */
1710 #if defined (PDP15) /* PDP15 only */
1711 if (ion_inh) /* inhibited? */
1712 return 0;
1713 #endif
1714 for (i = 0; i < API_HLVL+1; i++) { /* any intr? */
1715 if (int_hwre[i])
1716 *pend = 1;
1717 }
1718 if (api_enb == 0) /* off? no req */
1719 return 0;
1720 api_req = api_req & ~(API_ML0|API_ML1|API_ML2|API_ML3); /* clr req<0:3> */
1721 for (i = 0; i < API_HLVL; i++) { /* loop thru levels */
1722 if (int_hwre[i]) /* req on level? */
1723 api_req = api_req | (API_ML0 >> i); /* set api req */
1724 }
1725 hi = api_ffo[api_req & 0377]; /* find hi req */
1726 if (hi < api_ffo[api_act & 0377])
1727 return (hi + 1);
1728 return 0;
1729 }
1730
1731 /* Process IORS instruction */
1732
1733 int32 upd_iors (void)
1734 {
1735 int32 d, p;
1736
1737 d = (ion? IOS_ION: 0); /* ION */
1738 for (p = 0; dev_iors[p] != NULL; p++) /* loop thru table */
1739 d = d | dev_iors[p](); /* OR in results */
1740 return d;
1741 }
1742
1743 #if defined (PDP4) || defined (PDP7)
1744
1745 /* Read, write, indirect, increment routines
1746 On the PDP-4 and PDP-7,
1747 There are autoincrement locations in every field. If a field
1748 does not exist, it is impossible to generate an
1749 autoincrement reference (all instructions are CAL).
1750 Indirect addressing range is determined by extend mode.
1751 JMP I with EMIR pending can only clear extend
1752 There is no memory protection, nxm reads zero and ignores writes. */
1753
1754 t_stat Read (int32 ma, int32 *dat, int32 cyc)
1755 {
1756 ma = ma & AMASK;
1757 if (MEM_ADDR_OK (ma))
1758 *dat = M[ma] & DMASK;
1759 else *dat = 0;
1760 return MM_OK;
1761 }
1762
1763 t_stat Write (int32 ma, int32 dat, int32 cyc)
1764 {
1765 ma = ma & AMASK;
1766 if (MEM_ADDR_OK (ma))
1767 M[ma] = dat & DMASK;
1768 return MM_OK;
1769 }
1770
1771 t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
1772 {
1773 int32 t;
1774 t_stat sta = MM_OK;
1775
1776 if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */
1777 Read (ma, &t, DF); /* add 1 before use */
1778 t = (t + 1) & DMASK;
1779 sta = Write (ma, t, DF);
1780 }
1781 else sta = Read (ma, &t, DF); /* fetch indirect */
1782 if (jmp) { /* jmp i? */
1783 if (emir_pending && (((t >> 16) & 1) == 0))
1784 memm = 0;
1785 emir_pending = rest_pending = 0;
1786 }
1787 if (memm) /* extend? 15b ia */
1788 *ea = t & IAMASK;
1789 else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */
1790 return sta;
1791 }
1792
1793 int32 Incr_addr (int32 ma)
1794 {
1795 return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK));
1796 }
1797
1798 int32 Jms_word (int32 t)
1799 {
1800 return (((LAC & LINK) >> 1) | ((memm & 1) << 16) |
1801 ((t & 1) << 15) | (PC & IAMASK));
1802 }
1803
1804 #endif
1805
1806 #if defined (PDP9)
1807
1808 /* Read, write, indirect, increment routines
1809 On the PDP-9,
1810 The autoincrement registers are in field zero only. Regardless
1811 of extend mode, indirect addressing through 00010-00017
1812 will access absolute locations 00010-00017.
1813 Indirect addressing range is determined by extend mode. If
1814 extend mode is off, and autoincrementing is used, the
1815 resolved address is in bank 0 (KG09B maintenance manual).
1816 JMP I with EMIR pending can only clear extend
1817 JMP I with DBK pending restores L, user mode, extend mode
1818 Memory protection is implemented for foreground/background operation. */
1819
1820 t_stat Read (int32 ma, int32 *dat, int32 cyc)
1821 {
1822 ma = ma & AMASK;
1823 if (usmd) { /* user mode? */
1824 if (!MEM_ADDR_OK (ma)) { /* nxm? */
1825 nexm = prvn = trap_pending = 1; /* set flags, trap */
1826 *dat = 0;
1827 return MM_ERR;
1828 }
1829 if ((cyc != DF) && (ma < BR)) { /* boundary viol? */
1830 prvn = trap_pending = 1; /* set flag, trap */
1831 *dat = 0;
1832 return MM_ERR;
1833 }
1834 }
1835 if (MEM_ADDR_OK (ma)) /* valid mem? ok */
1836 *dat = M[ma] & DMASK;
1837 else {
1838 *dat = 0; /* set flag, no trap */
1839 nexm = 1;
1840 }
1841 return MM_OK;
1842 }
1843
1844 t_stat Write (int32 ma, int32 dat, int32 cyc)
1845 {
1846 ma = ma & AMASK;
1847 if (usmd) {
1848 if (!MEM_ADDR_OK (ma)) { /* nxm? */
1849 nexm = prvn = trap_pending = 1; /* set flags, trap */
1850 return MM_ERR;
1851 }
1852 if ((cyc != DF) && (ma < BR)) { /* boundary viol? */
1853 prvn = trap_pending = 1; /* set flag, trap */
1854 return MM_ERR;
1855 }
1856 }
1857 if (MEM_ADDR_OK (ma)) /* valid mem? ok */
1858 M[ma] = dat & DMASK;
1859 else nexm = 1; /* set flag, no trap */
1860 return MM_OK;
1861 }
1862
1863 t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
1864 {
1865 int32 t;
1866 t_stat sta = MM_OK;
1867
1868 if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */
1869 ma = ma & 017; /* always in bank 0 */
1870 Read (ma, &t, DF); /* +1 before use */
1871 t = (t + 1) & DMASK;
1872 sta = Write (ma, t, DF);
1873 }
1874 else sta = Read (ma, &t, DF);
1875 if (jmp) { /* jmp i? */
1876 if (emir_pending && (((t >> 16) & 1) == 0))
1877 memm = 0;
1878 if (rest_pending) { /* restore pending? */
1879 LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */
1880 memm = (t >> 16) & 1; /* restore extend */
1881 usmd = usmd_buf = (t >> 15) & 1; /* restore user */
1882 }
1883 emir_pending = rest_pending = 0;
1884 }
1885 if (memm) /* extend? 15b ia */
1886 *ea = t & IAMASK;
1887 else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */
1888 return sta;
1889 }
1890
1891 int32 Incr_addr (int32 ma)
1892 {
1893 return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK));
1894 }
1895
1896 int32 Jms_word (int32 t)
1897 {
1898 return (((LAC & LINK) >> 1) | ((memm & 1) << 16) |
1899 ((t & 1) << 15) | (PC & IAMASK));
1900 }
1901
1902 #endif
1903
1904 #if defined (PDP15)
1905
1906 /* Read, write, indirect, increment routines
1907 On the PDP-15,
1908 The autoincrement registers are in page zero only. Regardless
1909 of bank mode, indirect addressing through 00010-00017
1910 will access absolute locations 00010-00017.
1911 Indirect addressing range is determined by autoincrementing.
1912 Any indirect can trigger a restore.
1913 Memory protection is implemented for foreground/background operation.
1914 Read and write mask addresses to 17b except for XVM systems */
1915
1916 t_stat Read (int32 ma, int32 *dat, int32 cyc)
1917 {
1918 int32 pa;
1919
1920 if (usmd) { /* user mode? */
1921 if (XVM) /* XVM relocation? */
1922 pa = RelocXVM (ma, REL_R);
1923 else if (RELOC) /* PDP-15 relocation? */
1924 pa = Reloc15 (ma, REL_R);
1925 else pa = Prot15 (ma, cyc == FE); /* PDP-15 prot, fetch only */
1926 if (pa < 0) { /* error? */
1927 *dat = 0;
1928 return MM_ERR;
1929 }
1930 }
1931 else pa = ma & AMASK; /* no prot or reloc */
1932 if (MEM_ADDR_OK (pa)) /* valid mem? ok */
1933 *dat = M[pa] & DMASK;
1934 else {
1935 nexm = 1; /* set flag, no trap */
1936 *dat = 0;
1937 }
1938 return MM_OK;
1939 }
1940
1941 t_stat Write (int32 ma, int32 dat, int32 cyc)
1942 {
1943 int32 pa;
1944
1945 if (usmd) { /* user mode? */
1946 if (XVM) /* XVM relocation? */
1947 pa = RelocXVM (ma, REL_W);
1948 else if (RELOC) /* PDP-15 relocation? */
1949 pa = Reloc15 (ma, REL_W);
1950 else pa = Prot15 (ma, cyc != DF); /* PDP-15 prot, !defer */
1951 if (pa < 0) /* error? */
1952 return MM_ERR;
1953 }
1954 else pa = ma & AMASK; /* no prot or reloc */
1955 if (MEM_ADDR_OK (pa)) /* valid mem? ok */
1956 M[pa] = dat & DMASK;
1957 else nexm = 1; /* set flag, no trap */
1958 return MM_OK;
1959 }
1960
1961 /* XVM will do 18b defers if user_mode and G_Mode != 0 */
1962
1963 t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
1964 {
1965 int32 gmode, t;
1966 int32 damask = memm? B_DAMASK: P_DAMASK;
1967 static const int32 g_mask[4] = { MM_G_W0, MM_G_W1, MM_G_W2, MM_G_W3 };
1968 t_stat sta = MM_OK;
1969
1970 if ((ma & damask & ~07) == 010) { /* autoincrement? */
1971 ma = ma & 017; /* always in bank 0 */
1972 Read (ma, &t, DF); /* +1 before use */
1973 t = (t + 1) & DMASK;
1974 sta = Write (ma, t, DF);
1975 }
1976 else sta = Read (ma, &t, DF);
1977 if (rest_pending) { /* restore pending? */
1978 LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */
1979 memm = (t >> 16) & 1; /* restore bank */
1980 usmd = usmd_buf = (t >> 15) & 1; /* restore user */
1981 emir_pending = rest_pending = 0;
1982 }
1983 gmode = MM_GETGM (MMR); /* get G_mode */
1984 if (usmd && XVM && gmode) /* XVM user mode? */
1985 *ea = t & g_mask[gmode]; /* mask ia to size */
1986 else if ((ma & damask & ~07) == 010) /* autoindex? */
1987 *ea = t & DMASK;
1988 else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */
1989 return sta;
1990 }
1991
1992 int32 Incr_addr (int32 ma)
1993 {
1994 if (memm)
1995 return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK));
1996 return ((ma & P_EPCMASK) | ((ma + 1) & P_DAMASK));
1997 }
1998
1999 /* XVM will store all 18b of PC if user mode and G_mode != 0 */
2000
2001 int32 Jms_word (int32 t)
2002 {
2003 if (usmd && XVM && (MMR & MM_GM))
2004 return PC;
2005 return (((LAC & LINK) >> 1) | ((memm & 1) << 16) |
2006 ((t & 1) << 15) | (PC & IAMASK));
2007 }
2008
2009 /* PDP-15 protection (KM15 option) */
2010
2011 int32 Prot15 (int32 ma, t_bool bndchk)
2012 {
2013 ma = ma & AMASK; /* 17b addressing */
2014 if (!MEM_ADDR_OK (ma)) { /* nxm? */
2015 nexm = prvn = trap_pending = 1; /* set flags, trap */
2016 return -1;
2017 }
2018 if (bndchk && (ma < BR)) { /* boundary viol? */
2019 prvn = trap_pending = 1; /* set flag, trap */
2020 return -1;
2021 }
2022 return ma; /* no relocation */
2023 }
2024
2025 /* PDP-15 relocation and protection (KT15 option) */
2026
2027 int32 Reloc15 (int32 ma, int32 rc)
2028 {
2029 int32 pa;
2030
2031 ma = ma & AMASK; /* 17b addressing */
2032 if (ma > (BR | 0377)) { /* boundary viol? */
2033 if (rc != REL_C) /* set flag, trap */
2034 prvn = trap_pending = 1;
2035 return -1;
2036 }
2037 pa = (ma + RR) & AMASK; /* relocate address */
2038 if (!MEM_ADDR_OK (pa)) { /* nxm? */
2039 if (rc != REL_C) /* set flags, trap */
2040 nexm = prvn = trap_pending = 1;
2041 return -1;
2042 }
2043 return pa;
2044 }
2045
2046 /* XVM relocation and protection option */
2047
2048 int32 RelocXVM (int32 ma, int32 rc)
2049 {
2050 int32 pa, gmode, slr;
2051 static const int32 g_base[4] = { MM_G_B0, MM_G_B1, MM_G_B2, MM_G_B3 };
2052 static const int32 slr_lnt[4] = { MM_SLR_L0, MM_SLR_L1, MM_SLR_L2, MM_SLR_L3 };
2053
2054 gmode = MM_GETGM (MMR); /* get G_mode */
2055 slr = MM_GETSLR (MMR); /* get segment length */
2056 if (MMR & MM_RDIS) /* reloc disabled? */
2057 pa = ma;
2058 else if ((MMR & MM_SH) && /* shared enabled and */
2059 (ma >= g_base[gmode]) && /* >= shared base and */
2060 (ma < (g_base[gmode] + slr_lnt[slr]))) { /* < shared end? */
2061 if (ma & 017400) { /* ESAS? */
2062 if ((rc == REL_W) && (MMR & MM_WP)) { /* write and protected? */
2063 prvn = trap_pending = 1; /* set flag, trap */
2064 return -1;
2065 }
2066 pa = (((MMR & MM_SBR_MASK) << 8) + ma) & DMASK; /* ESAS reloc */
2067 }
2068 else pa = RR + (ma & 0377); /* no, ISAS reloc */
2069 }
2070 else {
2071 if (ma > (BR | 0377)) { /* normal reloc, viol? */
2072 if (rc != REL_C) /* set flag, trap */
2073 prvn = trap_pending = 1;
2074 return -1;
2075 }
2076 pa = (RR + ma) & DMASK; /* relocate address */
2077 }
2078 if (!MEM_ADDR_OK (pa)) { /* nxm? */
2079 if (rc != REL_C) /* set flags, trap */
2080 nexm = prvn = trap_pending = 1;
2081 return -1;
2082 }
2083 return pa;
2084 }
2085
2086 #endif
2087
2088 /* Reset routine */
2089
2090 t_stat cpu_reset (DEVICE *dptr)
2091 {
2092 LAC = 0;
2093 MQ = 0;
2094 SC = 0;
2095 eae_ac_sign = 0;
2096 ion = ion_defer = ion_inh = 0;
2097 CLR_INT (PWRFL);
2098 api_enb = api_req = api_act = 0;
2099 BR = 0;
2100 RR = 0;
2101 MMR = 0;
2102 usmd = usmd_buf = usmd_defer = 0;
2103 memm = memm_init;
2104 nexm = prvn = trap_pending = 0;
2105 emir_pending = rest_pending = 0;
2106 pcq_r = find_reg ("PCQ", NULL, dptr);
2107 if (pcq_r)
2108 pcq_r->qptr = 0;
2109 else return SCPE_IERR;
2110 sim_brk_types = sim_brk_dflt = SWMASK ('E');
2111 return SCPE_OK;
2112 }
2113
2114 /* CAF routine (CPU reset isn't called by CAF) */
2115
2116 void cpu_caf (void)
2117 {
2118 api_enb = api_req = api_act = 0; /* reset API system */
2119 nexm = prvn = trap_pending = 0; /* reset MM system */
2120 usmd = usmd_buf = usmd_defer = 0;
2121 MMR = 0;
2122 return;
2123 }
2124
2125 /* Memory examine */
2126
2127 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
2128 {
2129 #if defined (PDP15)
2130 if (usmd && (sw & SWMASK ('V'))) {
2131 if (XVM)
2132 addr = RelocXVM (addr, REL_C);
2133 else if (RELOC)
2134 addr = Reloc15 (addr, REL_C);
2135 if (((int32) addr) < 0)
2136 return STOP_MME;
2137 }
2138 #endif
2139 if (addr >= MEMSIZE)
2140 return SCPE_NXM;
2141 if (vptr != NULL)
2142 *vptr = M[addr] & DMASK;
2143 return SCPE_OK;
2144 }
2145
2146 /* Memory deposit */
2147
2148 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
2149 {
2150 #if defined (PDP15)
2151 if (usmd && (sw & SWMASK ('V'))) {
2152 if (XVM)
2153 addr = RelocXVM (addr, REL_C);
2154 else if (RELOC)
2155 addr = Reloc15 (addr, REL_C);
2156 if (((int32) addr) < 0)
2157 return STOP_MME;
2158 }
2159 #endif
2160 if (addr >= MEMSIZE)
2161 return SCPE_NXM;
2162 M[addr] = val & DMASK;
2163 return SCPE_OK;
2164 }
2165
2166 /* Change memory size */
2167
2168 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
2169 {
2170 int32 mc = 0;
2171 uint32 i;
2172
2173 if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
2174 return SCPE_ARG;
2175 for (i = val; i < MEMSIZE; i++)
2176 mc = mc | M[i];
2177 if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
2178 return SCPE_OK;
2179 MEMSIZE = val;
2180 for (i = MEMSIZE; i < MAXMEMSIZE; i++)
2181 M[i] = 0;
2182 return SCPE_OK;
2183 }
2184
2185 /* Change device number for a device */
2186
2187 t_stat set_devno (UNIT *uptr, int32 val, char *cptr, void *desc)
2188 {
2189 DEVICE *dptr;
2190 DIB *dibp;
2191 uint32 newdev;
2192 t_stat r;
2193
2194 if (cptr == NULL)
2195 return SCPE_ARG;
2196 if (uptr == NULL)
2197 return SCPE_IERR;
2198 dptr = find_dev_from_unit (uptr);
2199 if (dptr == NULL)
2200 return SCPE_IERR;
2201 dibp = (DIB *) dptr->ctxt;
2202 if (dibp == NULL)
2203 return SCPE_IERR;
2204 newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */
2205 if ((r != SCPE_OK) || (newdev == dibp->dev))
2206 return r;
2207 dibp->dev = newdev; /* store */
2208 return SCPE_OK;
2209 }
2210
2211 /* Show device number for a device */
2212
2213 t_stat show_devno (FILE *st, UNIT *uptr, int32 val, void *desc)
2214 {
2215 DEVICE *dptr;
2216 DIB *dibp;
2217
2218 if (uptr == NULL)
2219 return SCPE_IERR;
2220 dptr = find_dev_from_unit (uptr);
2221 if (dptr == NULL)
2222 return SCPE_IERR;
2223 dibp = (DIB *) dptr->ctxt;
2224 if (dibp == NULL)
2225 return SCPE_IERR;
2226 fprintf (st, "devno=%02o", dibp->dev);
2227 if (dibp->num > 1)
2228 fprintf (st, "-%2o", dibp->dev + dibp->num - 1);
2229 return SCPE_OK;
2230 }
2231
2232 /* CPU device handler - should never get here! */
2233
2234 int32 bad_dev (int32 dev, int32 pulse, int32 AC)
2235 {
2236 return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */
2237 }
2238
2239 /* Build device dispatch table */
2240
2241 t_bool build_dev_tab (void)
2242 {
2243 DEVICE *dptr;
2244 DIB *dibp;
2245 uint32 i, j, p;
2246 static const uint8 std_dev[] =
2247 #if defined (PDP4)
2248 { 000 };
2249 #elif defined (PDP7)
2250 { 000, 033, 077 };
2251 #else
2252 { 000, 017, 033, 055, 077 };
2253 #endif
2254
2255 for (i = 0; i < DEV_MAX; i++) { /* clr tables */
2256 dev_tab[i] = NULL;
2257 dev_iors[i] = NULL;
2258 }
2259 for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */
2260 dev_tab[std_dev[i]] = &bad_dev;
2261 for (i = p = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */
2262 dibp = (DIB *) dptr->ctxt; /* get DIB */
2263 if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */
2264 if (dibp->iors) /* if IORS, add */
2265 dev_iors[p++] = dibp->iors;
2266 for (j = 0; j < dibp->num; j++) { /* loop thru disp */
2267 if (dibp->dsp[j]) { /* any dispatch? */
2268 if (dev_tab[dibp->dev + j]) { /* already filled? */
2269 printf ("%s device number conflict at %02o\n",
2270 sim_dname (dptr), dibp->dev + j);
2271 if (sim_log)
2272 fprintf (sim_log, "%s device number conflict at %02o\n",
2273 sim_dname (dptr), dibp->dev + j);
2274 return TRUE;
2275 }
2276 dev_tab[dibp->dev + j] = dibp->dsp[j]; /* fill */
2277 } /* end if dsp */
2278 } /* end for j */
2279 } /* end if enb */
2280 } /* end for i */
2281 return FALSE;
2282 }
2283
2284 /* Set history */
2285
2286 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
2287 {
2288 int32 i, lnt;
2289 t_stat r;
2290
2291 if (cptr == NULL) {
2292 for (i = 0; i < hst_lnt; i++)
2293 hst[i].pc = 0;
2294 hst_p = 0;
2295 return SCPE_OK;
2296 }
2297 lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
2298 if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN)))
2299 return SCPE_ARG;
2300 hst_p = 0;
2301 if (hst_lnt) {
2302 free (hst);
2303 hst_lnt = 0;
2304 hst = NULL;
2305 }
2306 if (lnt) {
2307 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
2308 if (hst == NULL)
2309 return SCPE_MEM;
2310 hst_lnt = lnt;
2311 }
2312 return SCPE_OK;
2313 }
2314
2315 /* Show history */
2316
2317 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
2318 {
2319 int32 l, j, k, di, lnt;
2320 char *cptr = (char *) desc;
2321 t_value sim_eval[2];
2322 t_stat r;
2323 InstHistory *h;
2324 extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
2325 UNIT *uptr, int32 sw);
2326
2327 if (hst_lnt == 0) /* enabled? */
2328 return SCPE_NOFNC;
2329 if (cptr) {
2330 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
2331 if ((r != SCPE_OK) || (lnt == 0))
2332 return SCPE_ARG;
2333 }
2334 else lnt = hst_lnt;
2335 di = hst_p - lnt; /* work forward */
2336 if (di < 0)
2337 di = di + hst_lnt;
2338 fprintf (st, "PC L AC MQ IR\n\n");
2339 for (k = 0; k < lnt; k++) { /* print specified */
2340 h = &hst[(di++) % hst_lnt]; /* entry pointer */
2341 if (h->pc & HIST_PC) { /* instruction? */
2342 l = (h->lac >> 18) & 1; /* link */
2343 fprintf (st, "%06o %o %06o %06o ", h->pc & AMASK, l, h->lac & DMASK, h->mq);
2344 sim_eval[0] = h->ir;
2345 sim_eval[1] = h->ir1;
2346 if ((fprint_sym (st, h->pc & AMASK, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
2347 fprintf (st, "(undefined) %06o", h->ir);
2348 } /* end else instruction */
2349 else if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */
2350 if (h->pc & HIST_PI) /* PI? */
2351 fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK);
2352 else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq);
2353 for (j = API_HLVL; j >= 0; j--)
2354 fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL);
2355 }
2356 else continue; /* invalid */
2357 fputc ('\n', st); /* end line */
2358 } /* end for */
2359 return SCPE_OK;
2360 }
2361
2362 /* Record events in history table */
2363
2364 void cpu_inst_hist (int32 addr, int32 inst)
2365 {
2366 t_value word = 0;
2367
2368 hst[hst_p].pc = addr | HIST_PC;
2369 hst[hst_p].ir = inst;
2370 if (cpu_ex (&word, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V')))
2371 hst[hst_p].ir1 = 0;
2372 else hst[hst_p].ir1 = word;
2373 hst[hst_p].lac = LAC;
2374 hst[hst_p].mq = MQ;
2375 hst_p = (hst_p + 1);
2376 if (hst_p >= hst_lnt)
2377 hst_p = 0;
2378 return;
2379 }
2380
2381 void cpu_intr_hist (int32 flag, int32 lvl)
2382 {
2383 int32 j;
2384
2385 hst[hst_p].pc = PC | flag;
2386 hst[hst_p].ir = 0;
2387 for (j = 0; j < API_HLVL+1; j++)
2388 hst[hst_p].ir = (hst[hst_p].ir << HIST_V_LVL) | (int_hwre[j] & HIST_M_LVL);
2389 hst[hst_p].ir1 = 0;
2390 hst[hst_p].lac = 0;
2391 hst[hst_p].mq = lvl;
2392 hst_p = (hst_p + 1);
2393 if (hst_p >= hst_lnt)
2394 hst_p = 0;
2395 return;
2396 }
2397