First Commit of my working state
[simh.git] / PDP18B / pdp18b_cpu.c
1 /* pdp18b_cpu.c: 18b PDP CPU simulator
2
3 Copyright (c) 1993-2007, 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 (reported by 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 (from 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 (found by 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 (found by 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)) x = ((x) + XR) & DMASK
408 int32 Prot15 (int32 ma, t_bool bndchk);
409 int32 Reloc15 (int32 ma, int32 acc);
410 int32 RelocXVM (int32 ma, int32 acc);
411 extern t_stat fp15 (int32 ir);
412 extern int32 clk_task_upd (t_bool clr);
413 #else
414 #define INDEX(i,x)
415 #endif
416
417 extern int32 clk (int32 dev, int32 pulse, int32 AC);
418
419 int32 (*dev_tab[DEV_MAX])(int32 dev, int32 pulse, int32 AC); /* device dispatch */
420
421 int32 (*dev_iors[DEV_MAX])(void); /* IORS dispatch */
422
423 static const int32 api_ffo[256] = {
424 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
425 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
426 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
427 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
428 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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 };
441
442 static const int32 api_vec[API_HLVL][32] = {
443 { ACH_PWRFL }, /* API 0 */
444 { ACH_DTA, ACH_MTA, ACH_DRM, ACH_RF, ACH_RP, ACH_RB }, /* API 1 */
445 { ACH_PTR, ACH_LPT, ACH_LPT }, /* API 2 */
446 { ACH_CLK, ACH_TTI1, ACH_TTO1 } /* API 3 */
447 };
448
449 /* CPU data structures
450
451 cpu_dev CPU device descriptor
452 cpu_unit CPU unit
453 cpu_reg CPU register list
454 cpu_mod CPU modifier list
455 */
456
457 UNIT cpu_unit = {
458 UDATA (NULL, UNIT_FIX+UNIT_BINK+EAE_DFLT+API_DFLT+PROT_DFLT,
459 MAXMEMSIZE)
460 };
461
462 REG cpu_reg[] = {
463 { ORDATA (PC, PC, ADDRSIZE) },
464 { ORDATA (AC, LAC, 18) },
465 { FLDATA (L, LAC, 18) },
466 { ORDATA (MQ, MQ, 18) },
467 { ORDATA (SC, SC, 6) },
468 { FLDATA (EAE_AC_SIGN, eae_ac_sign, 18) },
469 { ORDATA (SR, SR, 18) },
470 { ORDATA (ASW, ASW, ADDRSIZE) },
471 { ORDATA (IORS, iors, 18), REG_RO },
472 { BRDATA (INT, int_hwre, 8, 32, API_HLVL+1), REG_RO },
473 { FLDATA (INT_PEND, int_pend, 0), REG_RO },
474 { FLDATA (ION, ion, 0) },
475 { ORDATA (ION_DELAY, ion_defer, 2) },
476 #if defined (PDP7)
477 { FLDATA (TRAPM, usmd, 0) },
478 { FLDATA (TRAPP, trap_pending, 0) },
479 { FLDATA (EXTM, memm, 0) },
480 { FLDATA (EXTM_INIT, memm_init, 0) },
481 { FLDATA (EMIRP, emir_pending, 0) },
482 #endif
483 #if defined (PDP9)
484 { FLDATA (APIENB, api_enb, 0) },
485 { ORDATA (APIREQ, api_req, 8) },
486 { ORDATA (APIACT, api_act, 8) },
487 { ORDATA (BR, BR, ADDRSIZE) },
488 { FLDATA (USMD, usmd, 0) },
489 { FLDATA (USMDBUF, usmd_buf, 0) },
490 { FLDATA (USMDDEF, usmd_defer, 0) },
491 { FLDATA (NEXM, nexm, 0) },
492 { FLDATA (PRVN, prvn, 0) },
493 { FLDATA (TRAPP, trap_pending, 0) },
494 { FLDATA (EXTM, memm, 0) },
495 { FLDATA (EXTM_INIT, memm_init, 0) },
496 { FLDATA (EMIRP, emir_pending, 0) },
497 { FLDATA (RESTP, rest_pending, 0) },
498 { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) },
499 #endif
500 #if defined (PDP15)
501 { FLDATA (ION_INH, ion_inh, 0) },
502 { FLDATA (APIENB, api_enb, 0) },
503 { ORDATA (APIREQ, api_req, 8) },
504 { ORDATA (APIACT, api_act, 8) },
505 { ORDATA (XR, XR, 18) },
506 { ORDATA (LR, LR, 18) },
507 { ORDATA (BR, BR, 18) },
508 { ORDATA (RR, RR, 18) },
509 { ORDATA (MMR, MMR, 18) },
510 { FLDATA (USMD, usmd, 0) },
511 { FLDATA (USMDBUF, usmd_buf, 0) },
512 { FLDATA (USMDDEF, usmd_defer, 0) },
513 { FLDATA (NEXM, nexm, 0) },
514 { FLDATA (PRVN, prvn, 0) },
515 { FLDATA (TRAPP, trap_pending, 0) },
516 { FLDATA (BANKM, memm, 0) },
517 { FLDATA (BANKM_INIT, memm_init, 0) },
518 { FLDATA (RESTP, rest_pending, 0) },
519 { FLDATA (PWRFL, int_hwre[API_PWRFL], INT_V_PWRFL) },
520 #endif
521 { BRDATA (PCQ, pcq, 8, ADDRSIZE, PCQ_SIZE), REG_RO+REG_CIRC },
522 { ORDATA (PCQP, pcq_p, 6), REG_HRO },
523 { FLDATA (STOP_INST, stop_inst, 0) },
524 { DRDATA (XCT_MAX, xct_max, 8), PV_LEFT + REG_NZ },
525 { ORDATA (WRU, sim_int_char, 8) },
526 { NULL } };
527
528 MTAB cpu_mod[] = {
529 { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL },
530 { UNIT_NOEAE, 0, "EAE", "EAE", NULL },
531 #if defined (PDP9) || defined (PDP15)
532 { UNIT_NOAPI, UNIT_NOAPI, "no API", "NOAPI", NULL },
533 { UNIT_NOAPI, 0, "API", "API", NULL },
534 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, 0, "no memory protect",
535 "NOPROTECT", NULL },
536 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT, "memory protect",
537 "PROTECT", NULL },
538 #endif
539 #if defined (PDP15)
540 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC,
541 "memory relocation", "RELOCATION", NULL },
542 { UNIT_PROT+UNIT_RELOC+UNIT_XVM, UNIT_PROT+UNIT_RELOC+UNIT_XVM,
543 "XVM", "XVM", NULL },
544 #endif
545 { MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle },
546 { MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL },
547 #if defined (PDP4)
548 { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
549 #endif
550 { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
551 #if (MAXMEMSIZE > 8192)
552 { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
553 { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
554 { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
555 { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
556 { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
557 { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
558 #endif
559 #if (MAXMEMSIZE > 32768)
560 { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
561 { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
562 { UNIT_MSIZE, 81920, NULL, "80K", &cpu_set_size },
563 { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size },
564 { UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size },
565 { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
566 #endif
567 { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
568 &cpu_set_hist, &cpu_show_hist },
569 { 0 }
570 };
571
572 DEVICE cpu_dev = {
573 "CPU", &cpu_unit, cpu_reg, cpu_mod,
574 1, 8, ADDRSIZE, 1, 8, 18,
575 &cpu_ex, &cpu_dep, &cpu_reset,
576 NULL, NULL, NULL
577 };
578
579 t_stat sim_instr (void)
580 {
581 int32 api_int, api_usmd, skp;
582 int32 iot_data, device, pulse;
583 int32 last_IR;
584 t_stat reason;
585
586 if (build_dev_tab ()) return SCPE_STOP; /* build, chk tables */
587 PC = PC & AMASK; /* clean variables */
588 LAC = LAC & LACMASK;
589 MQ = MQ & DMASK;
590 reason = 0;
591 last_IR = -1;
592 if (cpu_unit.flags & UNIT_NOAPI) /* no API? */
593 api_enb = api_req = api_act = 0;
594 api_int = api_eval (&int_pend); /* eval API */
595 api_usmd = 0; /* not API user cycle */
596
597 /* Main instruction fetch/decode loop */
598
599 while (reason == 0) { /* loop until halted */
600
601 int32 IR, MA, MB, esc, t, xct_count;
602 int32 link_init, fill;
603
604 if (sim_interval <= 0) { /* check clock queue */
605 if (reason = sim_process_event ()) break;
606 api_int = api_eval (&int_pend); /* eval API */
607 }
608
609 /* PDP-4 and PDP-7 traps and interrupts
610
611 PDP-4 no trap
612 PDP-7 trap: extend mode forced on, M[0] = PC, PC = 2
613 PDP-4, PDP-7 programmable interrupts only */
614
615 #if defined (PDP4) || defined (PDP7)
616 #if defined (PDP7)
617
618 if (trap_pending) { /* trap pending? */
619 PCQ_ENTRY; /* save old PC */
620 MB = Jms_word (1); /* save state */
621 ion = 0; /* interrupts off */
622 memm = 1; /* extend on */
623 emir_pending = trap_pending = 0; /* emir, trap off */
624 usmd = usmd_buf = 0; /* user mode off */
625 Write (0, MB, WR); /* save in 0 */
626 PC = 2; /* fetch next from 2 */
627 }
628
629 #endif
630
631 if (int_pend && ion && !ion_defer) { /* interrupt? */
632 PCQ_ENTRY; /* save old PC */
633 MB = Jms_word (usmd); /* save state */
634 ion = 0; /* interrupts off */
635 memm = 0; /* extend off */
636 emir_pending = rest_pending = 0; /* emir, restore off */
637 usmd = usmd_buf = 0; /* user mode off */
638 Write (0, MB, WR); /* physical write */
639 PC = 1; /* fetch next from 1 */
640 }
641
642 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
643 reason = STOP_IBKPT; /* stop simulation */
644 break;
645 }
646
647 #endif /* end PDP-4/PDP-7 */
648
649 /* PDP-9 and PDP-15 traps and interrupts
650
651 PDP-9 trap: extend mode ???, M[0/20] = PC, PC = 0/21
652 PDP-15 trap: bank mode unchanged, M[0/20] = PC, PC = 0/21
653 PDP-9, PDP-15 API and program interrupts */
654
655 #if defined (PDP9) || defined (PDP15)
656
657 if (trap_pending) { /* trap pending? */
658 PCQ_ENTRY; /* save old PC */
659 MB = Jms_word (1); /* save state */
660 if (ion) { /* int on? */
661 ion = 0; /* interrupts off */
662 MA = 0; /* treat like PI */
663 #if defined (PDP15)
664 ion_defer = 2; /* free instruction */
665 if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */
666 api_act = api_act | API_ML3; /* set lev 3 active */
667 api_int = api_eval (&int_pend); /* re-evaluate */
668 }
669 #endif
670 }
671 else MA = 020; /* sortof like CAL */
672 emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */
673 usmd = usmd_buf = 0; /* user mode off */
674 Write (MA, MB, WR); /* physical write */
675 PC = MA + 1; /* fetch next */
676 }
677
678 if (api_int && !ion_defer) { /* API intr? */
679 int32 i, lvl = api_int - 1; /* get req level */
680 if (hst_lnt) cpu_intr_hist (HIST_API, lvl); /* record */
681 api_act = api_act | (API_ML0 >> lvl); /* set level active */
682 if (lvl >= API_HLVL) { /* software req? */
683 MA = ACH_SWRE + lvl - API_HLVL; /* vec = 40:43 */
684 api_req = api_req & ~(API_ML0 >> lvl); /* remove request */
685 }
686 else {
687 MA = 0; /* assume fails */
688 for (i = 0; i < 32; i++) { /* loop hi to lo */
689 if ((int_hwre[lvl] >> i) & 1) { /* int req set? */
690 MA = api_vec[lvl][i]; /* get vector */
691 break; /* and stop */
692 }
693 }
694 }
695 if (MA == 0) { /* bad channel? */
696 reason = STOP_API; /* API error */
697 break;
698 }
699 api_int = api_eval (&int_pend); /* no API int */
700 api_usmd = usmd; /* API user mode cycle */
701 usmd = usmd_buf = 0; /* user mode off */
702 emir_pending = rest_pending = 0; /* emir, restore off */
703 xct_count = 0;
704 Read (MA, &IR, FE); /* fetch instruction */
705 goto xct_instr;
706 }
707
708 if (int_pend && ion && !ion_defer && /* int pending, enabled? */
709 !(api_enb && (api_act & API_MASKPI))) { /* API off or not masking PI? */
710 PCQ_ENTRY; /* save old PC */
711 if (hst_lnt) cpu_intr_hist (HIST_PI, 0); /* record */
712 MB = Jms_word (usmd); /* save state */
713 ion = 0; /* interrupts off */
714 ion_defer = 2; /* free instruction */
715 #if defined (PDP9) /* PDP-9, */
716 memm = 0; /* extend off */
717 #else /* PDP-15 */
718 if (!(cpu_unit.flags & UNIT_NOAPI)) { /* API? */
719 api_act = api_act | API_ML3; /* set lev 3 active */
720 api_int = api_eval (&int_pend); /* re-evaluate */
721 }
722 #endif
723 emir_pending = rest_pending = 0; /* emir, restore off */
724 usmd = usmd_buf = 0; /* user mode off */
725 Write (0, MB, WR); /* physical write */
726 PC = 1; /* fetch next from 1 */
727 }
728
729 if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
730 reason = STOP_IBKPT; /* stop simulation */
731 break;
732 }
733 if (!usmd_defer) usmd = usmd_buf; /* no IOT? load usmd */
734 else usmd_defer = 0; /* cancel defer */
735
736 #endif /* PDP-9/PDP-15 */
737
738 /* Instruction fetch and address decode */
739
740 xct_count = 0; /* track nested XCT's */
741 MA = PC; /* fetch at PC */
742 if (Read (MA, &IR, FE)) continue; /* fetch instruction */
743 PC = Incr_addr (PC); /* increment PC */
744
745 xct_instr: /* label for API, XCT */
746 if (hst_lnt) cpu_inst_hist (MA, IR); /* history? */
747 if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */
748 if (sim_interval) sim_interval = sim_interval - 1;
749
750 #if defined (PDP15) /* PDP15 */
751
752 if (memm) MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode dir addr */
753 else MA = (MA & P_EPCMASK) | (IR & P_DAMASK); /* page mode dir addr */
754
755 #else /* others */
756
757 MA = (MA & B_EPCMASK) | (IR & B_DAMASK); /* bank mode only */
758
759 #endif
760
761 switch ((IR >> 13) & 037) { /* decode IR<0:4> */
762
763 /* LAC: opcode 20 */
764
765 case 011: /* LAC, indir */
766 if (Ia (MA, &MA, 0)) break;
767 case 010: /* LAC, dir */
768 INDEX (IR, MA);
769 if (Read (MA, &MB, RD)) break;
770 LAC = (LAC & LINK) | MB;
771 break;
772
773 /* DAC: opcode 04 */
774
775 case 003: /* DAC, indir */
776 if (Ia (MA, &MA, 0)) break;
777 case 002: /* DAC, dir */
778 INDEX (IR, MA);
779 Write (MA, LAC & DMASK, WR);
780 break;
781
782 /* DZM: opcode 14 */
783
784 case 007: /* DZM, indir */
785 if (Ia (MA, &MA, 0)) break;
786 case 006: /* DZM, direct */
787 INDEX (IR, MA);
788 Write (MA, 0, WR);
789 break;
790
791 /* AND: opcode 50 */
792
793 case 025: /* AND, ind */
794 if (Ia (MA, &MA, 0)) break;
795 case 024: /* AND, dir */
796 INDEX (IR, MA);
797 if (Read (MA, &MB, RD)) break;
798 LAC = LAC & (MB | LINK);
799 break;
800
801 /* XOR: opcode 24 */
802
803 case 013: /* XOR, ind */
804 if (Ia (MA, &MA, 0)) break;
805 case 012: /* XOR, dir */
806 INDEX (IR, MA);
807 if (Read (MA, &MB, RD)) break;
808 LAC = LAC ^ MB;
809 break;
810
811 /* ADD: opcode 30 */
812
813 case 015: /* ADD, indir */
814 if (Ia (MA, &MA, 0)) break;
815 case 014: /* ADD, dir */
816 INDEX (IR, MA);
817 if (Read (MA, &MB, RD)) break;
818 t = (LAC & DMASK) + MB;
819 if (t > DMASK) t = (t + 1) & DMASK; /* end around carry */
820 if (((~LAC ^ MB) & (LAC ^ t)) & SIGN) /* overflow? */
821 LAC = LINK | t; /* set link */
822 else LAC = (LAC & LINK) | t;
823 break;
824
825 /* TAD: opcode 34 */
826
827 case 017: /* TAD, indir */
828 if (Ia (MA, &MA, 0)) break;
829 case 016: /* TAD, dir */
830 INDEX (IR, MA);
831 if (Read (MA, &MB, RD)) break;
832 LAC = (LAC + MB) & LACMASK;
833 break;
834
835 /* ISZ: opcode 44 */
836
837 case 023: /* ISZ, indir */
838 if (Ia (MA, &MA, 0)) break;
839 case 022: /* ISZ, dir */
840 INDEX (IR, MA);
841 if (Read (MA, &MB, RD)) break;
842 MB = (MB + 1) & DMASK;
843 if (Write (MA, MB, WR)) break;
844 if (MB == 0) PC = Incr_addr (PC);
845 break;
846
847 /* SAD: opcode 54 */
848
849 case 027: /* SAD, indir */
850 if (Ia (MA, &MA, 0)) break;
851 case 026: /* SAD, dir */
852 INDEX (IR, MA);
853 if (Read (MA, &MB, RD)) break;
854 if ((LAC & DMASK) != MB) PC = Incr_addr (PC);
855 break;
856
857 /* XCT: opcode 40 */
858
859 case 021: /* XCT, indir */
860 if (Ia (MA, &MA, 0)) break;
861 case 020: /* XCT, dir */
862 INDEX (IR, MA);
863 if ((api_usmd | usmd) && (xct_count != 0)) { /* chained and usmd? */
864 if (usmd) prvn = trap_pending = 1; /* trap if usmd */
865 break; /* nop if api_usmd */
866 }
867 if (xct_count >= xct_max) { /* too many XCT's? */
868 reason = STOP_XCT;
869 break;
870 }
871 xct_count = xct_count + 1; /* count XCT's */
872 #if defined (PDP9)
873 ion_defer = 1; /* defer intr */
874 #endif
875 if (Read (MA, &IR, FE)) break; /* fetch inst, mm err? */
876 goto xct_instr; /* go execute */
877
878 /* CAL: opcode 00 - api_usmd records whether usmd = 1 at start of API cycle
879
880 On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20
881 On the PDP-9 and PDP-15, CAL clears user mode
882 On the PDP-9 and PDP-15 with API, CAL activates level 4
883 On the PDP-15, CAL goes to absolute 20, regardless of mode */
884
885 case 001: case 000: /* CAL */
886 t = usmd; /* save user mode */
887 #if defined (PDP15) /* PDP15 */
888 MA = 020; /* MA = abs 20 */
889 ion_defer = 1; /* "free instruction" */
890 #else /* others */
891 if (memm) MA = 020; /* if ext, abs 20 */
892 else MA = (PC & B_EPCMASK) | 020; /* else bank-rel 20 */
893 #endif
894 #if defined (PDP9) || defined (PDP15)
895 usmd = usmd_buf = 0; /* clear user mode */
896 if ((cpu_unit.flags & UNIT_NOAPI) == 0) { /* if API, act lvl 4 */
897 #if defined (PDP15) /* PDP15: if 0-3 inactive */
898 if ((api_act & (API_ML0|API_ML1|API_ML2|API_ML3)) == 0)
899 #endif
900 api_act = api_act | API_ML4;
901 api_int = api_eval (&int_pend);
902 }
903 #endif
904 if (IR & I_IND) { /* indirect? */
905 if (Ia (MA, &MA, 0)) break;
906 }
907 PCQ_ENTRY;
908 MB = Jms_word (api_usmd | t); /* save state */
909 Write (MA, MB, WR);
910 PC = Incr_addr (MA);
911 break;
912
913 /* JMS: opcode 010 - api_usmd records whether usmd = 1 at start of API cycle */
914
915 case 005: /* JMS, indir */
916 if (Ia (MA, &MA, 0)) break;
917 case 004: /* JMS, dir */
918 INDEX (IR, MA);
919 PCQ_ENTRY;
920 #if defined (PDP15) /* PDP15 */
921 if (!usmd) ion_defer = 1; /* "free instruction" */
922 #endif
923 MB = Jms_word (api_usmd | usmd); /* save state */
924 if (Write (MA, MB, WR)) break;
925 PC = Incr_addr (MA) & AMASK;
926 break;
927
928 /* JMP: opcode 60 */
929
930 case 031: /* JMP, indir */
931 if (Ia (MA, &MA, 1)) break;
932 INDEX (IR, MA);
933 PCQ_ENTRY; /* save old PC */
934 PC = MA & AMASK;
935 break;
936
937 /* JMP direct - check for idle */
938
939 case 030: /* JMP, dir */
940 INDEX (IR, MA);
941 PCQ_ENTRY; /* save old PC */
942 if (sim_idle_enab) { /* idling enabled? */
943 t_bool iof = (ion_inh != 0) || /* IOF if inhibited */
944 ((ion == 0) && (api_enb == 0)); /* or PI and api off */
945 if (((MA ^ (PC - 2)) & AMASK) == 0) { /* 1) JMP *-1? */
946 if (iof && (last_IR == OP_KSF) && /* iof, prv KSF, */
947 !TST_INT (TTI)) /* no TTI flag? */
948 sim_idle (0, FALSE); /* we're idle */
949 }
950 else if (((MA ^ (PC - 1)) & AMASK) == 0) { /* 2) JMP *? */
951 if (iof) reason = STOP_LOOP; /* iof? inf loop */
952 else sim_idle (0, FALSE); /* ion? idle */
953 }
954 } /* end idle */
955 PC = MA & AMASK;
956 break;
957
958 /* OPR: opcode 74 */
959
960 case 037: /* OPR, indir */
961 LAC = (LAC & LINK) | IR; /* LAW */
962 break;
963
964 case 036: /* OPR, dir */
965 skp = 0; /* assume no skip */
966 switch ((IR >> 6) & 017) { /* decode IR<8:11> */
967 case 0: /* nop */
968 break;
969 case 1: /* SMA */
970 if ((LAC & SIGN) != 0) skp = 1;
971 break;
972 case 2: /* SZA */
973 if ((LAC & DMASK) == 0) skp = 1;
974 break;
975 case 3: /* SZA | SMA */
976 if (((LAC & DMASK) == 0) || ((LAC & SIGN) != 0))
977 skp = 1;
978 break;
979 case 4: /* SNL */
980 if (LAC >= LINK) skp = 1;
981 break;
982 case 5: /* SNL | SMA */
983 if (LAC >= SIGN) skp = 1;
984 break;
985 case 6: /* SNL | SZA */
986 if ((LAC >= LINK) || (LAC == 0)) skp = 1;
987 break;
988 case 7: /* SNL | SZA | SMA */
989 if ((LAC >= SIGN) || (LAC == 0)) skp = 1;
990 break;
991 case 010: /* SKP */
992 skp = 1;
993 break;
994 case 011: /* SPA */
995 if ((LAC & SIGN) == 0) skp = 1;
996 break;
997 case 012: /* SNA */
998 if ((LAC & DMASK) != 0) skp = 1;
999 break;
1000 case 013: /* SNA & SPA */
1001 if (((LAC & DMASK) != 0) && ((LAC & SIGN) == 0))
1002 skp = 1;
1003 break;
1004 case 014: /* SZL */
1005 if (LAC < LINK) skp = 1;
1006 break;
1007 case 015: /* SZL & SPA */
1008 if (LAC < SIGN) skp = 1;
1009 break;
1010 case 016: /* SZL & SNA */
1011 if ((LAC < LINK) && (LAC != 0)) skp = 1;
1012 break;
1013 case 017: /* SZL & SNA & SPA */
1014 if ((LAC < SIGN) && (LAC != 0)) skp = 1;
1015 break;
1016 } /* end switch skips */
1017
1018 switch (((IR >> 9) & 014) | (IR & 03)) { /* IR<5:6,16:17> */
1019 case 0: /* NOP */
1020 break;
1021 case 1: /* CMA */
1022 LAC = LAC ^ DMASK;
1023 break;
1024 case 2: /* CML */
1025 LAC = LAC ^ LINK;
1026 break;
1027 case 3: /* CML CMA */
1028 LAC = LAC ^ LACMASK;
1029 break;
1030 case 4: /* CLL */
1031 LAC = LAC & DMASK;
1032 break;
1033 case 5: /* CLL CMA */
1034 LAC = (LAC & DMASK) ^ DMASK;
1035 break;
1036 case 6: /* CLL CML = STL */
1037 LAC = LAC | LINK;
1038 break;
1039 case 7: /* CLL CML CMA */
1040 LAC = (LAC | LINK) ^ DMASK;
1041 break;
1042 case 010: /* CLA */
1043 LAC = LAC & LINK;
1044 break;
1045 case 011: /* CLA CMA = STA */
1046 LAC = LAC | DMASK;
1047 break;
1048 case 012: /* CLA CML */
1049 LAC = (LAC & LINK) ^ LINK;
1050 break;
1051 case 013: /* CLA CML CMA */
1052 LAC = (LAC | DMASK) ^ LINK;
1053 break;
1054 case 014: /* CLA CLL */
1055 LAC = 0;
1056 break;
1057 case 015: /* CLA CLL CMA */
1058 LAC = DMASK;
1059 break;
1060 case 016: /* CLA CLL CML */
1061 LAC = LINK;
1062 break;
1063 case 017: /* CLA CLL CML CMA */
1064 LAC = LACMASK;
1065 break;
1066 } /* end decode */
1067
1068 if (IR & 0000004) { /* OAS */
1069 #if defined (PDP9) || defined (PDP15)
1070 if (usmd) prvn = trap_pending = 1; /* trap if usmd */
1071 else if (!api_usmd) /* nop if api_usmd */
1072 #endif
1073 LAC = LAC | SR;
1074 }
1075
1076 switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */
1077 case 1: /* RAL */
1078 LAC = ((LAC << 1) | (LAC >> 18)) & LACMASK;
1079 break;
1080 case 2: /* RAR */
1081 LAC = ((LAC >> 1) | (LAC << 18)) & LACMASK;
1082 break;
1083 case 3: /* RAL RAR */
1084 #if defined (PDP15) /* PDP-15 */
1085 LAC = (LAC + 1) & LACMASK; /* IAC */
1086 #else /* PDP-4,-7,-9 */
1087 reason = stop_inst; /* undefined */
1088 #endif
1089 break;
1090 case 5: /* RTL */
1091 LAC = ((LAC << 2) | (LAC >> 17)) & LACMASK;
1092 break;
1093 case 6: /* RTR */
1094 LAC = ((LAC >> 2) | (LAC << 17)) & LACMASK;
1095 break;
1096 case 7: /* RTL RTR */
1097 #if defined (PDP15) /* PDP-15 */
1098 LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) |
1099 (LAC & LINK); /* BSW */
1100 #else /* PDP-4,-7,-9 */
1101 reason = stop_inst; /* undefined */
1102 #endif
1103 break;
1104 } /* end switch rotate */
1105
1106 if (IR & 0000040) { /* HLT */
1107 if (usmd) prvn = trap_pending = 1; /* trap if usmd */
1108 else if (!api_usmd) reason = STOP_HALT; /* nop if api_usmd */
1109 }
1110 if (skp) PC = Incr_addr (PC); /* if skip, inc PC */
1111 break; /* end OPR */
1112
1113 /* EAE: opcode 64
1114
1115 The EAE is microprogrammed to execute variable length signed and
1116 unsigned shift, multiply, divide, and normalize. Most commands are
1117 controlled by a six bit step counter (SC). In the hardware, the step
1118 counter is complemented on load and then counted up to zero; timing
1119 guarantees an initial increment, which completes the two's complement
1120 load. In the simulator, the SC is loaded normally and then counted
1121 down to zero; the read SC command compensates. */
1122
1123 case 033: case 032: /* EAE */
1124 if (cpu_unit.flags & UNIT_NOEAE) break; /* disabled? */
1125 if (IR & 0020000) /* IR<4>? AC0 to L */
1126 LAC = ((LAC << 1) & LINK) | (LAC & DMASK);
1127 if (IR & 0010000) MQ = 0; /* IR<5>? clear MQ */
1128 if ((IR & 0004000) && (LAC & SIGN)) /* IR<6> and minus? */
1129 eae_ac_sign = LINK; /* set eae_ac_sign */
1130 else eae_ac_sign = 0; /* if not, unsigned */
1131 if (IR & 0002000) MQ = (MQ | LAC) & DMASK; /* IR<7>? or AC */
1132 else if (eae_ac_sign) LAC = LAC ^ DMASK; /* if not, |AC| */
1133 if (IR & 0001000) LAC = LAC & LINK; /* IR<8>? clear AC */
1134 link_init = LAC & LINK; /* link temporary */
1135 fill = link_init? DMASK: 0; /* fill = link */
1136 esc = IR & 077; /* get eff SC */
1137 switch ((IR >> 6) & 07) { /* case on IR<9:11> */
1138
1139 case 0: /* setup */
1140 if (IR & 04) MQ = MQ ^ DMASK; /* IR<15>? ~MQ */
1141 if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */
1142 if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */
1143 break;
1144
1145 /* Multiply uses a shift and add algorithm. The PDP-15, unlike prior
1146 implementations, factors IR<6> (signed multiply) into the calculation
1147 of the result sign. */
1148
1149 case 1: /* multiply */
1150 if (Read (PC, &MB, FE)) break; /* get next word */
1151 PC = Incr_addr (PC); /* increment PC */
1152 if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */
1153 LAC = LAC & DMASK; /* clear link */
1154 SC = esc; /* init SC */
1155 do { /* loop */
1156 if (MQ & 1) LAC = LAC + MB; /* MQ<17>? add */
1157 MQ = (MQ >> 1) | ((LAC & 1) << 17);
1158 LAC = LAC >> 1; /* shift AC'MQ right */
1159 SC = (SC - 1) & 077; /* decrement SC */
1160 } while (SC != 0); /* until SC = 0 */
1161 #if defined (PDP15)
1162 if ((IR & 0004000) && (eae_ac_sign ^ link_init)) {
1163 #else
1164 if (eae_ac_sign ^ link_init) { /* result negative? */
1165 #endif
1166 LAC = LAC ^ DMASK;
1167 MQ = MQ ^ DMASK;
1168 }
1169 break;
1170
1171 /* Divide uses a non-restoring divide. Divide uses a subtract and shift
1172 algorithm. The quotient is generated in true form. The PDP-15, unlike
1173 prior implementations, factors IR<6> (signed multiply) into the calculation
1174 of the result sign. */
1175
1176 case 3: /* divide */
1177 if (Read (PC, &MB, FE)) break; /* get next word */
1178 PC = Incr_addr (PC); /* increment PC */
1179 if (eae_ac_sign) MQ = MQ ^ DMASK; /* EAE AC sign? ~MQ */
1180 if ((LAC & DMASK) >= MB) { /* overflow? */
1181 LAC = (LAC - MB) | LINK; /* set link */
1182 break;
1183 }
1184 LAC = LAC & DMASK; /* clear link */
1185 t = 0; /* init loop */
1186 SC = esc; /* init SC */
1187 do { /* loop */
1188 if (t) LAC = (LAC + MB) & LACMASK;
1189 else LAC = (LAC - MB) & LACMASK;
1190 t = (LAC >> 18) & 1; /* quotient bit */
1191 if (SC > 1) LAC = /* skip if last */
1192 ((LAC << 1) | (MQ >> 17)) & LACMASK;
1193 MQ = ((MQ << 1) | (t ^ 1)) & DMASK; /* shift in quo bit */
1194 SC = (SC - 1) & 077; /* decrement SC */
1195 } while (SC != 0); /* until SC = 0 */
1196 if (t) LAC = (LAC + MB) & LACMASK;
1197 if (eae_ac_sign) LAC = LAC ^ DMASK; /* sgn rem = sgn divd */
1198 #if defined (PDP15)
1199 if ((IR & 0004000) && (eae_ac_sign ^ link_init))
1200 #else
1201 if (eae_ac_sign ^ link_init) /* result negative? */
1202 #endif
1203 MQ = MQ ^ DMASK;
1204 break;
1205
1206 /* EAE shifts, whether left or right, fill from the link. If the
1207 operand sign has been copied to the link, this provides correct
1208 sign extension for one's complement numbers. */
1209
1210 case 4: /* normalize */
1211 #if defined (PDP15)
1212 if (!usmd) ion_defer = 2; /* free instructions */
1213 #endif
1214 for (SC = esc; ((LAC & SIGN) == ((LAC << 1) & SIGN)); ) {
1215 LAC = (LAC << 1) | ((MQ >> 17) & 1);
1216 MQ = (MQ << 1) | (link_init >> 18);
1217 SC = (SC - 1) & 077;
1218 if (SC == 0) break;
1219 }
1220 LAC = link_init | (LAC & DMASK); /* trim AC, restore L */
1221 MQ = MQ & DMASK; /* trim MQ */
1222 SC = SC & 077; /* trim SC */
1223 break;
1224
1225 case 5: /* long right shift */
1226 if (esc < 18) {
1227 MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & DMASK;
1228 LAC = ((fill << (18 - esc)) | (LAC >> esc)) & LACMASK;
1229 }
1230 else {
1231 if (esc < 36) MQ =
1232 ((fill << (36 - esc)) | (LAC >> (esc - 18))) & DMASK;
1233 else MQ = fill;
1234 LAC = link_init | fill;
1235 }
1236 SC = 0; /* clear step count */
1237 break;
1238
1239 case 6: /* long left shift */
1240 if (esc < 18) {
1241 LAC = link_init |
1242 (((LAC << esc) | (MQ >> (18 - esc))) & DMASK);
1243 MQ = ((MQ << esc) | (fill >> (18 - esc))) & DMASK;
1244 }
1245 else {
1246 if (esc < 36) LAC = link_init |
1247 (((MQ << (esc - 18)) | (fill >> (36 - esc))) & DMASK);
1248 else LAC = link_init | fill;
1249 MQ = fill;
1250 }
1251 SC = 0; /* clear step count */
1252 break;
1253
1254 case 7: /* AC left shift */
1255 if (esc < 18) LAC = link_init |
1256 (((LAC << esc) | (fill >> (18 - esc))) & DMASK);
1257 else LAC = link_init | fill;
1258 SC = 0; /* clear step count */
1259 break;
1260 } /* end switch IR */
1261 break; /* end case EAE */
1262
1263 /* PDP-15 index operates: opcode 72 */
1264
1265 case 035: /* index operates */
1266
1267 #if defined (PDP15)
1268 t = (IR & 0400)? (IR | 0777000): (IR & 0377); /* sext immediate */
1269 switch ((IR >> 9) & 017) { /* case on IR<5:8> */
1270 case 001: /* PAX */
1271 XR = LAC & DMASK;
1272 break;
1273 case 002: /* PAL */
1274 LR = LAC & DMASK;
1275 break;
1276 case 003: /* AAC */
1277 LAC = (LAC & LINK) | ((LAC + t) & DMASK);
1278 break;
1279 case 004: /* PXA */
1280 LAC = (LAC & LINK) | XR;
1281 break;
1282 case 005: /* AXS */
1283 XR = (XR + t) & DMASK;
1284 if (SEXT (XR) >= SEXT (LR)) PC = Incr_addr (PC);
1285 break;
1286 case 006: /* PXL */
1287 LR = XR;
1288 break;
1289 case 010: /* PLA */
1290 LAC = (LAC & LINK) | LR;
1291 break;
1292 case 011: /* PLX */
1293 XR = LR;
1294 break;
1295 case 014: /* CLAC */
1296 LAC = LAC & LINK;
1297 break;
1298 case 015: /* CLX */
1299 XR = 0;
1300 break;
1301 case 016: /* CLLR */
1302 LR = 0;
1303 break;
1304 case 017: /* AXR */
1305 XR = (XR + t) & DMASK;
1306 break;
1307 } /* end switch IR */
1308 break; /* end case */
1309 #endif
1310
1311 /* IOT: opcode 70
1312
1313 The 18b PDP's have different definitions of various control IOT's.
1314
1315 IOT PDP-4 PDP-7 PDP-9 PDP-15
1316
1317 700002 IOF IOF IOF IOF
1318 700022 undefined undefined undefined ORMM (XVM)
1319 700042 ION ION ION ION
1320 700024 undefined undefined undefined LDMM (XVM)
1321 700062 undefined ITON undefined undefined
1322 701701 undefined undefined MPSK MPSK
1323 701741 undefined undefined MPSNE MPSNE
1324 701702 undefined undefined MPCV MPCV
1325 701722 undefined undefined undefined MPRC (XVM)
1326 701742 undefined undefined MPEU MPEU
1327 701704 undefined undefined MPLD MPLD
1328 701724 undefined undefined undefined MPLR (KT15, XVM)
1329 701744 undefined undefined MPCNE MPCNE
1330 701764 undefined undefined undefined IPFH (XVM)
1331 703201 undefined undefined PFSF PFSF
1332 703301 undefined TTS TTS TTS
1333 703341 undefined SKP7 SKP7 SPCO
1334 703302 undefined CAF CAF CAF
1335 703304 undefined undefined DBK DBK
1336 703344 undefined undefined DBR DBR
1337 705501 undefined undefined SPI SPI
1338 705521 undefined undefined undefined ENB
1339 705502 undefined undefined RPL RPL
1340 705522 undefined undefined undefined INH
1341 705504 undefined undefined ISA ISA
1342 707701 undefined SEM SEM undefined
1343 707741 undefined undefined undefined SKP15
1344 707761 undefined undefined undefined SBA
1345 707702 undefined EEM EEM undefined
1346 707742 undefined EMIR EMIR RES
1347 707762 undefined undefined undefined DBA
1348 707704 undefined LEM LEM undefined
1349 707764 undefined undefined undefined EBA */
1350
1351 case 034: /* IOT */
1352 #if defined (PDP15)
1353 if (IR & 0010000) { /* floating point? */
1354 reason = fp15 (IR); /* process */
1355 break;
1356 }
1357 #endif
1358 if ((api_usmd | usmd) && /* user, not XVM UIOT? */
1359 (!XVM || !(MMR & MM_UIOT))) {
1360 if (usmd) prvn = trap_pending = 1; /* trap if user */
1361 break; /* nop if api_usmd */
1362 }
1363 device = (IR >> 6) & 077; /* device = IR<6:11> */
1364 pulse = IR & 067; /* pulse = IR<12:17> */
1365 if (IR & 0000010) LAC = LAC & LINK; /* clear AC? */
1366 iot_data = LAC & DMASK; /* AC unchanged */
1367
1368 /* PDP-4 system IOT's */
1369
1370 #if defined (PDP4)
1371 switch (device) { /* decode IR<6:11> */
1372
1373 case 0: /* CPU and clock */
1374 if (pulse == 002) ion = 0; /* IOF */
1375 else if (pulse == 042) ion = ion_defer = 1; /* ION */
1376 else iot_data = clk (device, pulse, iot_data);
1377 break;
1378 #endif
1379
1380 /* PDP-7 system IOT's */
1381
1382 #if defined (PDP7)
1383 switch (device) { /* decode IR<6:11> */
1384
1385 case 0: /* CPU and clock */
1386 if (pulse == 002) ion = 0; /* IOF */
1387 else if (pulse == 042) ion = ion_defer = 1; /* ION */
1388 else if (pulse == 062) /* ITON */
1389 usmd = usmd_buf = ion = ion_defer = 1;
1390 else iot_data = clk (device, pulse, iot_data);
1391 break;
1392
1393 case 033: /* CPU control */
1394 if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC);
1395 else if (pulse == 002) reset_all (1); /* CAF - skip CPU */
1396 break;
1397
1398 case 077: /* extended memory */
1399 if ((pulse == 001) && memm) PC = Incr_addr (PC);
1400 else if (pulse == 002) memm = 1; /* EEM */
1401 else if (pulse == 042) /* EMIR */
1402 memm = emir_pending = 1; /* ext on, restore */
1403 else if (pulse == 004) memm = 0; /* LEM */
1404 break;
1405 #endif
1406
1407 /* PDP-9 system IOT's */
1408
1409 #if defined (PDP9)
1410 ion_defer = 1; /* delay interrupts */
1411 usmd_defer = 1; /* defer load user */
1412 switch (device) { /* decode IR<6:11> */
1413
1414 case 000: /* CPU and clock */
1415 if (pulse == 002) ion = 0; /* IOF */
1416 else if (pulse == 042) ion = 1; /* ION */
1417 else iot_data = clk (device, pulse, iot_data);
1418 break;
1419
1420 case 017: /* mem protection */
1421 if (PROT) { /* enabled? */
1422 if ((pulse == 001) && prvn) /* MPSK */
1423 PC = Incr_addr (PC);
1424 else if ((pulse == 041) && nexm) /* MPSNE */
1425 PC = Incr_addr (PC);
1426 else if (pulse == 002) prvn = 0; /* MPCV */
1427 else if (pulse == 042) usmd_buf = 1; /* MPEU */
1428 else if (pulse == 004) /* MPLD */
1429 BR = LAC & BRMASK;
1430 else if (pulse == 044) nexm = 0; /* MPCNE */
1431 }
1432 else reason = stop_inst;
1433 break;
1434
1435 case 032: /* power fail */
1436 if ((pulse == 001) && (TST_INT (PWRFL)))
1437 PC = Incr_addr (PC);
1438 break;
1439
1440 case 033: /* CPU control */
1441 if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC);
1442 else if (pulse == 002) { /* CAF */
1443 reset_all (1); /* reset all exc CPU */
1444 cpu_caf (); /* CAF to CPU */
1445 }
1446 else if (pulse == 044) rest_pending = 1; /* DBR */
1447 if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
1448 int32 t = api_ffo[api_act & 0377];
1449 api_act = api_act & ~(API_ML0 >> t);
1450 }
1451 break;
1452
1453 case 055: /* API control */
1454 if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst;
1455 else if (pulse == 001) { /* SPI */
1456 if (((LAC & SIGN) && api_enb) ||
1457 ((LAC & 0377) > api_act))
1458 iot_data = iot_data | IOT_SKP;
1459 }
1460 else if (pulse == 002) { /* RPL */
1461 iot_data = iot_data | (api_enb << 17) |
1462 (api_req << 8) | api_act;
1463 }
1464 else if (pulse == 004) { /* ISA */
1465 api_enb = (iot_data & SIGN)? 1: 0;
1466 api_req = api_req | ((LAC >> 8) & 017);
1467 api_act = api_act | (LAC & 0377);
1468 }
1469 break;
1470
1471 case 077: /* extended memory */
1472 if ((pulse == 001) && memm) PC = Incr_addr (PC);
1473 else if (pulse == 002) memm = 1; /* EEM */
1474 else if (pulse == 042) /* EMIR */
1475 memm = emir_pending = 1; /* ext on, restore */
1476 else if (pulse == 004) memm = 0; /* LEM */
1477 break;
1478 #endif
1479
1480 /* PDP-15 system IOT's - includes "re-entrancy ECO" ENB/INH as standard */
1481
1482 #if defined (PDP15)
1483 ion_defer = 1; /* delay interrupts */
1484 usmd_defer = 1; /* defer load user */
1485 switch (device) { /* decode IR<6:11> */
1486
1487 case 000: /* CPU and clock */
1488 if (pulse == 002) ion = 0; /* IOF */
1489 else if (pulse == 042) ion = 1; /* ION */
1490 else if (XVM && (pulse == 022)) /* ORMM/RDMM */
1491 iot_data = MMR;
1492 else if (XVM && (pulse == 024)) /* LDMM */
1493 MMR = iot_data;
1494 else iot_data = clk (device, pulse, iot_data);
1495 break;
1496
1497 case 017: /* mem protection */
1498 if (PROT) { /* enabled? */
1499 t = XVM? BRMASK_XVM: BRMASK;
1500 if ((pulse == 001) && prvn) /* MPSK */
1501 PC = Incr_addr (PC);
1502 else if ((pulse == 041) && nexm) /* MPSNE */
1503 PC = Incr_addr (PC);
1504 else if (pulse == 002) prvn = 0; /* MPCV */
1505 else if (pulse == 042) /* MPEU */
1506 usmd_buf = 1;
1507 else if (XVM && (pulse == 062)) /* RDCLK */
1508 iot_data = clk_task_upd (TRUE);
1509 else if (pulse == 004) BR = LAC & t; /* MPLD */
1510 else if (RELOC && (pulse == 024)) /* MPLR */
1511 RR = LAC & t;
1512 else if (pulse == 044) nexm = 0; /* MPCNE */
1513 }
1514 else reason = stop_inst;
1515 break;
1516
1517 case 032: /* power fail */
1518 if ((pulse == 001) && (TST_INT (PWRFL)))
1519 PC = Incr_addr (PC);
1520 break;
1521
1522 case 033: /* CPU control */
1523 if ((pulse == 001) || (pulse == 041)) PC = Incr_addr (PC);
1524 else if (pulse == 002) { /* CAF */
1525 reset_all (2); /* reset all exc CPU, FP15 */
1526 cpu_caf (); /* CAF to CPU */
1527 }
1528 else if (pulse == 044) rest_pending = 1; /* DBR */
1529 if (((cpu_unit.flags & UNIT_NOAPI) == 0) && (pulse & 004)) {
1530 int32 t = api_ffo[api_act & 0377];
1531 api_act = api_act & ~(API_ML0 >> t);
1532 }
1533 break;
1534
1535 case 055: /* API control */
1536 if (cpu_unit.flags & UNIT_NOAPI) reason = stop_inst;
1537 else if (pulse == 001) { /* SPI */
1538 if (((LAC & SIGN) && api_enb) ||
1539 ((LAC & 0377) > api_act))
1540 iot_data = iot_data | IOT_SKP;
1541 }
1542 else if (pulse == 002) { /* RPL */
1543 iot_data = iot_data | (api_enb << 17) |
1544 (api_req << 8) | api_act;
1545 }
1546 else if (pulse == 004) { /* ISA */
1547 api_enb = (iot_data & SIGN)? 1: 0;
1548 api_req = api_req | ((LAC >> 8) & 017);
1549 api_act = api_act | (LAC & 0377);
1550 }
1551 else if (pulse == 021) ion_inh = 0; /* ENB */
1552 else if (pulse == 022) ion_inh = 1; /* INH */
1553 break;
1554
1555 case 077: /* bank addressing */
1556 if ((pulse == 041) || ((pulse == 061) && memm))
1557 PC = Incr_addr (PC); /* SKP15, SBA */
1558 else if (pulse == 042) rest_pending = 1; /* RES */
1559 else if (pulse == 062) memm = 0; /* DBA */
1560 else if (pulse == 064) memm = 1; /* EBA */
1561 break;
1562 #endif
1563
1564 /* IOT, continued */
1565
1566 default: /* devices */
1567 if (dev_tab[device]) /* defined? */
1568 iot_data = dev_tab[device] (device, pulse, iot_data);
1569 else reason = stop_inst; /* stop on flag */
1570 break;
1571 } /* end switch device */
1572
1573 LAC = LAC | (iot_data & DMASK);
1574 if (iot_data & IOT_SKP) PC = Incr_addr (PC);
1575 if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON;
1576 api_int = api_eval (&int_pend); /* eval API */
1577 break; /* end case IOT */
1578 } /* end switch opcode */
1579
1580 api_usmd = 0; /* API cycle over */
1581 last_IR = IR; /* save IR for next */
1582 } /* end while */
1583
1584 /* Simulation halted */
1585
1586 iors = upd_iors (); /* get IORS */
1587 pcq_r->qptr = pcq_p; /* update pc q ptr */
1588 return reason;
1589 }
1590
1591 /* Evaluate API */
1592
1593 int32 api_eval (int32 *pend)
1594 {
1595 int32 i, hi;
1596
1597 *pend = 0; /* assume no intr */
1598 #if defined (PDP15) /* PDP15 only */
1599 if (ion_inh) return 0; /* inhibited? */
1600 #endif
1601 for (i = 0; i < API_HLVL+1; i++) { /* any intr? */
1602 if (int_hwre[i]) *pend = 1;
1603 }
1604 if (api_enb == 0) return 0; /* off? no req */
1605 api_req = api_req & ~(API_ML0|API_ML1|API_ML2|API_ML3); /* clr req<0:3> */
1606 for (i = 0; i < API_HLVL; i++) { /* loop thru levels */
1607 if (int_hwre[i]) /* req on level? */
1608 api_req = api_req | (API_ML0 >> i); /* set api req */
1609 }
1610 hi = api_ffo[api_req & 0377]; /* find hi req */
1611 if (hi < api_ffo[api_act & 0377]) return (hi + 1);
1612 return 0;
1613 }
1614
1615 /* Process IORS instruction */
1616
1617 int32 upd_iors (void)
1618 {
1619 int32 d, p;
1620
1621 d = (ion? IOS_ION: 0); /* ION */
1622 for (p = 0; dev_iors[p] != NULL; p++) /* loop thru table */
1623 d = d | dev_iors[p](); /* OR in results */
1624 return d;
1625 }
1626
1627 #if defined (PDP4) || defined (PDP7)
1628
1629 /* Read, write, indirect, increment routines
1630 On the PDP-4 and PDP-7,
1631 There are autoincrement locations in every field. If a field
1632 does not exist, it is impossible to generate an
1633 autoincrement reference (all instructions are CAL).
1634 Indirect addressing range is determined by extend mode.
1635 JMP I with EMIR pending can only clear extend
1636 There is no memory protection, nxm reads zero and ignores writes. */
1637
1638 t_stat Read (int32 ma, int32 *dat, int32 cyc)
1639 {
1640 ma = ma & AMASK;
1641 if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK;
1642 else *dat = 0;
1643 return MM_OK;
1644 }
1645
1646 t_stat Write (int32 ma, int32 dat, int32 cyc)
1647 {
1648 ma = ma & AMASK;
1649 if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK;
1650 return MM_OK;
1651 }
1652
1653 t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
1654 {
1655 int32 t;
1656 t_stat sta = MM_OK;
1657
1658 if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */
1659 Read (ma, &t, DF); /* add 1 before use */
1660 t = (t + 1) & DMASK;
1661 sta = Write (ma, t, DF);
1662 }
1663 else sta = Read (ma, &t, DF); /* fetch indirect */
1664 if (jmp) { /* jmp i? */
1665 if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0;
1666 emir_pending = rest_pending = 0;
1667 }
1668 if (memm) *ea = t & IAMASK; /* extend? 15b ia */
1669 else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */
1670 return sta;
1671 }
1672
1673 int32 Incr_addr (int32 ma)
1674 {
1675 return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK));
1676 }
1677
1678 int32 Jms_word (int32 t)
1679 {
1680 return (((LAC & LINK) >> 1) | ((memm & 1) << 16) |
1681 ((t & 1) << 15) | (PC & IAMASK));
1682 }
1683
1684 #endif
1685
1686 #if defined (PDP9)
1687
1688 /* Read, write, indirect, increment routines
1689 On the PDP-9,
1690 The autoincrement registers are in field zero only. Regardless
1691 of extend mode, indirect addressing through 00010-00017
1692 will access absolute locations 00010-00017.
1693 Indirect addressing range is determined by extend mode. If
1694 extend mode is off, and autoincrementing is used, the
1695 resolved address is in bank 0 (KG09B maintenance manual).
1696 JMP I with EMIR pending can only clear extend
1697 JMP I with DBK pending restores L, user mode, extend mode
1698 Memory protection is implemented for foreground/background operation. */
1699
1700 t_stat Read (int32 ma, int32 *dat, int32 cyc)
1701 {
1702 ma = ma & AMASK;
1703 if (usmd) { /* user mode? */
1704 if (!MEM_ADDR_OK (ma)) { /* nxm? */
1705 nexm = prvn = trap_pending = 1; /* set flags, trap */
1706 *dat = 0;
1707 return MM_ERR;
1708 }
1709 if ((cyc != DF) && (ma < BR)) { /* boundary viol? */
1710 prvn = trap_pending = 1; /* set flag, trap */
1711 *dat = 0;
1712 return MM_ERR;
1713 }
1714 }
1715 if (MEM_ADDR_OK (ma)) *dat = M[ma] & DMASK; /* valid mem? ok */
1716 else {
1717 *dat = 0; /* set flag, no trap */
1718 nexm = 1;
1719 }
1720 return MM_OK;
1721 }
1722
1723 t_stat Write (int32 ma, int32 dat, int32 cyc)
1724 {
1725 ma = ma & AMASK;
1726 if (usmd) {
1727 if (!MEM_ADDR_OK (ma)) { /* nxm? */
1728 nexm = prvn = trap_pending = 1; /* set flags, trap */
1729 return MM_ERR;
1730 }
1731 if ((cyc != DF) && (ma < BR)) { /* boundary viol? */
1732 prvn = trap_pending = 1; /* set flag, trap */
1733 return MM_ERR;
1734 }
1735 }
1736 if (MEM_ADDR_OK (ma)) M[ma] = dat & DMASK; /* valid mem? ok */
1737 else nexm = 1; /* set flag, no trap */
1738 return MM_OK;
1739 }
1740
1741 t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
1742 {
1743 int32 t;
1744 t_stat sta = MM_OK;
1745
1746 if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */
1747 ma = ma & 017; /* always in bank 0 */
1748 Read (ma, &t, DF); /* +1 before use */
1749 t = (t + 1) & DMASK;
1750 sta = Write (ma, t, DF);
1751 }
1752 else sta = Read (ma, &t, DF);
1753 if (jmp) { /* jmp i? */
1754 if (emir_pending && (((t >> 16) & 1) == 0)) memm = 0;
1755 if (rest_pending) { /* restore pending? */
1756 LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */
1757 memm = (t >> 16) & 1; /* restore extend */
1758 usmd = usmd_buf = (t >> 15) & 1; /* restore user */
1759 }
1760 emir_pending = rest_pending = 0;
1761 }
1762 if (memm) *ea = t & IAMASK; /* extend? 15b ia */
1763 else *ea = (ma & B_EPCMASK) | (t & B_DAMASK); /* bank-rel ia */
1764 return sta;
1765 }
1766
1767 int32 Incr_addr (int32 ma)
1768 {
1769 return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK));
1770 }
1771
1772 int32 Jms_word (int32 t)
1773 {
1774 return (((LAC & LINK) >> 1) | ((memm & 1) << 16) |
1775 ((t & 1) << 15) | (PC & IAMASK));
1776 }
1777
1778 #endif
1779
1780 #if defined (PDP15)
1781
1782 /* Read, write, indirect, increment routines
1783 On the PDP-15,
1784 The autoincrement registers are in page zero only. Regardless
1785 of bank mode, indirect addressing through 00010-00017
1786 will access absolute locations 00010-00017.
1787 Indirect addressing range is determined by autoincrementing.
1788 Any indirect can trigger a restore.
1789 Memory protection is implemented for foreground/background operation.
1790 Read and write mask addresses to 17b except for XVM systems */
1791
1792 t_stat Read (int32 ma, int32 *dat, int32 cyc)
1793 {
1794 int32 pa;
1795
1796 if (usmd) { /* user mode? */
1797 if (XVM) pa = RelocXVM (ma, REL_R); /* XVM relocation? */
1798 else if (RELOC) pa = Reloc15 (ma, REL_R); /* PDP-15 relocation? */
1799 else pa = Prot15 (ma, cyc == FE); /* PDP-15 prot, fetch only */
1800 if (pa < 0) { /* error? */
1801 *dat = 0;
1802 return MM_ERR;
1803 }
1804 }
1805 else pa = ma & AMASK; /* no prot or reloc */
1806 if (MEM_ADDR_OK (pa)) *dat = M[pa] & DMASK; /* valid mem? ok */
1807 else {
1808 nexm = 1; /* set flag, no trap */
1809 *dat = 0;
1810 }
1811 return MM_OK;
1812 }
1813
1814 t_stat Write (int32 ma, int32 dat, int32 cyc)
1815 {
1816 int32 pa;
1817
1818 if (usmd) { /* user mode? */
1819 if (XVM) pa = RelocXVM (ma, REL_W); /* XVM relocation? */
1820 else if (RELOC) pa = Reloc15 (ma, REL_W); /* PDP-15 relocation? */
1821 else pa = Prot15 (ma, cyc != DF); /* PDP-15 prot, !defer */
1822 if (pa < 0) return MM_ERR; /* error? */
1823 }
1824 else pa = ma & AMASK; /* no prot or reloc */
1825 if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK; /* valid mem? ok */
1826 else nexm = 1; /* set flag, no trap */
1827 return MM_OK;
1828 }
1829
1830 /* XVM will do 18b defers if user_mode and G_Mode != 0 */
1831
1832 t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
1833 {
1834 int32 gmode, t;
1835 int32 damask = memm? B_DAMASK: P_DAMASK;
1836 static const int32 g_mask[4] = { MM_G_W0, MM_G_W1, MM_G_W2, MM_G_W3 };
1837 t_stat sta = MM_OK;
1838
1839 if ((ma & damask & ~07) == 010) { /* autoincrement? */
1840 ma = ma & 017; /* always in bank 0 */
1841 Read (ma, &t, DF); /* +1 before use */
1842 t = (t + 1) & DMASK;
1843 sta = Write (ma, t, DF);
1844 }
1845 else sta = Read (ma, &t, DF);
1846 if (rest_pending) { /* restore pending? */
1847 LAC = ((t << 1) & LINK) | (LAC & DMASK); /* restore L */
1848 memm = (t >> 16) & 1; /* restore bank */
1849 usmd = usmd_buf = (t >> 15) & 1; /* restore user */
1850 emir_pending = rest_pending = 0;
1851 }
1852 gmode = MM_GETGM (MMR); /* get G_mode */
1853 if (usmd && XVM && gmode) /* XVM user mode? */
1854 *ea = t & g_mask[gmode]; /* mask ia to size */
1855 else if ((ma & damask & ~07) == 010) *ea = t & DMASK; /* autoindex? */
1856 else *ea = (PC & BLKMASK) | (t & IAMASK); /* within 32K */
1857 return sta;
1858 }
1859
1860 t_stat Incr_addr (int32 ma)
1861 {
1862 if (memm) return ((ma & B_EPCMASK) | ((ma + 1) & B_DAMASK));
1863 return ((ma & P_EPCMASK) | ((ma + 1) & P_DAMASK));
1864 }
1865
1866 /* XVM will store all 18b of PC if user mode and G_mode != 0 */
1867
1868 int32 Jms_word (int32 t)
1869 {
1870 if (usmd && XVM && (MMR & MM_GM)) return PC;
1871 return (((LAC & LINK) >> 1) | ((memm & 1) << 16) |
1872 ((t & 1) << 15) | (PC & IAMASK));
1873 }
1874
1875 /* PDP-15 protection (KM15 option) */
1876
1877 int32 Prot15 (int32 ma, t_bool bndchk)
1878 {
1879 ma = ma & AMASK; /* 17b addressing */
1880 if (!MEM_ADDR_OK (ma)) { /* nxm? */
1881 nexm = prvn = trap_pending = 1; /* set flags, trap */
1882 return -1;
1883 }
1884 if (bndchk && (ma < BR)) { /* boundary viol? */
1885 prvn = trap_pending = 1; /* set flag, trap */
1886 return -1;
1887 }
1888 return ma; /* no relocation */
1889 }
1890
1891 /* PDP-15 relocation and protection (KT15 option) */
1892
1893 int32 Reloc15 (int32 ma, int32 rc)
1894 {
1895 int32 pa;
1896
1897 ma = ma & AMASK; /* 17b addressing */
1898 if (ma > (BR | 0377)) { /* boundary viol? */
1899 if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */
1900 return -1;
1901 }
1902 pa = (ma + RR) & AMASK; /* relocate address */
1903 if (!MEM_ADDR_OK (pa)) { /* nxm? */
1904 if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */
1905 return -1;
1906 }
1907 return pa;
1908 }
1909
1910 /* XVM relocation and protection option */
1911
1912 int32 RelocXVM (int32 ma, int32 rc)
1913 {
1914 int32 pa, gmode, slr;
1915 static const int32 g_base[4] = { MM_G_B0, MM_G_B1, MM_G_B2, MM_G_B3 };
1916 static const int32 slr_lnt[4] = { MM_SLR_L0, MM_SLR_L1, MM_SLR_L2, MM_SLR_L3 };
1917
1918 gmode = MM_GETGM (MMR); /* get G_mode */
1919 slr = MM_GETSLR (MMR); /* get segment length */
1920 if (MMR & MM_RDIS) pa = ma; /* reloc disabled? */
1921 else if ((MMR & MM_SH) && /* shared enabled and */
1922 (ma >= g_base[gmode]) && /* >= shared base and */
1923 (ma < (g_base[gmode] + slr_lnt[slr]))) { /* < shared end? */
1924 if (ma & 017400) { /* ESAS? */
1925 if ((rc == REL_W) && (MMR & MM_WP)) { /* write and protected? */
1926 prvn = trap_pending = 1; /* set flag, trap */
1927 return -1;
1928 }
1929 pa = (((MMR & MM_SBR_MASK) << 8) + ma) & DMASK; /* ESAS reloc */
1930 }
1931 else pa = RR + (ma & 0377); /* no, ISAS reloc */
1932 }
1933 else {
1934 if (ma > (BR | 0377)) { /* normal reloc, viol? */
1935 if (rc != REL_C) prvn = trap_pending = 1; /* set flag, trap */
1936 return -1;
1937 }
1938 pa = (RR + ma) & DMASK; /* relocate address */
1939 }
1940 if (!MEM_ADDR_OK (pa)) { /* nxm? */
1941 if (rc != REL_C) nexm = prvn = trap_pending = 1; /* set flags, trap */
1942 return -1;
1943 }
1944 return pa;
1945 }
1946
1947 #endif
1948
1949 /* Reset routine */
1950
1951 t_stat cpu_reset (DEVICE *dptr)
1952 {
1953 LAC = 0;
1954 MQ = 0;
1955 SC = 0;
1956 eae_ac_sign = 0;
1957 ion = ion_defer = ion_inh = 0;
1958 CLR_INT (PWRFL);
1959 api_enb = api_req = api_act = 0;
1960 BR = 0;
1961 RR = 0;
1962 MMR = 0;
1963 usmd = usmd_buf = usmd_defer = 0;
1964 memm = memm_init;
1965 nexm = prvn = trap_pending = 0;
1966 emir_pending = rest_pending = 0;
1967 pcq_r = find_reg ("PCQ", NULL, dptr);
1968 if (pcq_r) pcq_r->qptr = 0;
1969 else return SCPE_IERR;
1970 sim_brk_types = sim_brk_dflt = SWMASK ('E');
1971 return SCPE_OK;
1972 }
1973
1974 /* CAF routine (CPU reset isn't called by CAF) */
1975
1976 void cpu_caf (void)
1977 {
1978 api_enb = api_req = api_act = 0; /* reset API system */
1979 nexm = prvn = trap_pending = 0; /* reset MM system */
1980 usmd = usmd_buf = usmd_defer = 0;
1981 MMR = 0;
1982 return;
1983 }
1984
1985 /* Memory examine */
1986
1987 t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
1988 {
1989 #if defined (PDP15)
1990 if (usmd && (sw & SWMASK ('V'))) {
1991 if (XVM) addr = RelocXVM (addr, REL_C);
1992 else if (RELOC) addr = Reloc15 (addr, REL_C);
1993 if ((int32) addr < 0) return STOP_MME;
1994 }
1995 #endif
1996 if (addr >= MEMSIZE) return SCPE_NXM;
1997 if (vptr != NULL) *vptr = M[addr] & DMASK;
1998 return SCPE_OK;
1999 }
2000
2001 /* Memory deposit */
2002
2003 t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
2004 {
2005 #if defined (PDP15)
2006 if (usmd && (sw & SWMASK ('V'))) {
2007 if (XVM) addr = RelocXVM (addr, REL_C);
2008 else if (RELOC) addr = Reloc15 (addr, REL_C);
2009 if ((int32) addr < 0) return STOP_MME;
2010 }
2011 #endif
2012 if (addr >= MEMSIZE) return SCPE_NXM;
2013 M[addr] = val & DMASK;
2014 return SCPE_OK;
2015 }
2016
2017 /* Change memory size */
2018
2019 t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
2020 {
2021 int32 mc = 0;
2022 uint32 i;
2023
2024 if ((val <= 0) || (val > MAXMEMSIZE) || ((val & 07777) != 0))
2025 return SCPE_ARG;
2026 for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
2027 if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
2028 return SCPE_OK;
2029 MEMSIZE = val;
2030 for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
2031 return SCPE_OK;
2032 }
2033
2034 /* Change device number for a device */
2035
2036 t_stat set_devno (UNIT *uptr, int32 val, char *cptr, void *desc)
2037 {
2038 DEVICE *dptr;
2039 DIB *dibp;
2040 uint32 newdev;
2041 t_stat r;
2042
2043 if (cptr == NULL) return SCPE_ARG;
2044 if (uptr == NULL) return SCPE_IERR;
2045 dptr = find_dev_from_unit (uptr);
2046 if (dptr == NULL) return SCPE_IERR;
2047 dibp = (DIB *) dptr->ctxt;
2048 if (dibp == NULL) return SCPE_IERR;
2049 newdev = get_uint (cptr, 8, DEV_MAX - 1, &r); /* get new */
2050 if ((r != SCPE_OK) || (newdev == dibp->dev)) return r;
2051 dibp->dev = newdev; /* store */
2052 return SCPE_OK;
2053 }
2054
2055 /* Show device number for a device */
2056
2057 t_stat show_devno (FILE *st, UNIT *uptr, int32 val, void *desc)
2058 {
2059 DEVICE *dptr;
2060 DIB *dibp;
2061
2062 if (uptr == NULL) return SCPE_IERR;
2063 dptr = find_dev_from_unit (uptr);
2064 if (dptr == NULL) return SCPE_IERR;
2065 dibp = (DIB *) dptr->ctxt;
2066 if (dibp == NULL) return SCPE_IERR;
2067 fprintf (st, "devno=%02o", dibp->dev);
2068 if (dibp->num > 1) fprintf (st, "-%2o", dibp->dev + dibp->num - 1);
2069 return SCPE_OK;
2070 }
2071
2072 /* CPU device handler - should never get here! */
2073
2074 int32 bad_dev (int32 dev, int32 pulse, int32 AC)
2075 {
2076 return (SCPE_IERR << IOT_V_REASON) | AC; /* broken! */
2077 }
2078
2079 /* Build device dispatch table */
2080
2081 t_bool build_dev_tab (void)
2082 {
2083 DEVICE *dptr;
2084 DIB *dibp;
2085 uint32 i, j, p;
2086 static const uint8 std_dev[] =
2087 #if defined (PDP4)
2088 { 000 };
2089 #elif defined (PDP7)
2090 { 000, 033, 077 };
2091 #else
2092 { 000, 017, 033, 055, 077 };
2093 #endif
2094
2095 for (i = 0; i < DEV_MAX; i++) { /* clr tables */
2096 dev_tab[i] = NULL;
2097 dev_iors[i] = NULL;
2098 }
2099 for (i = 0; i < ((uint32) sizeof (std_dev)); i++) /* std entries */
2100 dev_tab[std_dev[i]] = &bad_dev;
2101 for (i = p = 0; (dptr = sim_devices[i]) != NULL; i++) { /* add devices */
2102 dibp = (DIB *) dptr->ctxt; /* get DIB */
2103 if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */
2104 if (dibp->iors) dev_iors[p++] = dibp->iors; /* if IORS, add */
2105 for (j = 0; j < dibp->num; j++) { /* loop thru disp */
2106 if (dibp->dsp[j]) { /* any dispatch? */
2107 if (dev_tab[dibp->dev + j]) { /* already filled? */
2108 printf ("%s device number conflict at %02o\n",
2109 sim_dname (dptr), dibp->dev + j);
2110 if (sim_log) fprintf (sim_log,
2111 "%s device number conflict at %02o\n",
2112 sim_dname (dptr), dibp->dev + j);
2113 return TRUE;
2114 }
2115 dev_tab[dibp->dev + j] = dibp->dsp[j]; /* fill */
2116 } /* end if dsp */
2117 } /* end for j */
2118 } /* end if enb */
2119 } /* end for i */
2120 return FALSE;
2121 }
2122
2123 /* Set history */
2124
2125 t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
2126 {
2127 int32 i, lnt;
2128 t_stat r;
2129
2130 if (cptr == NULL) {
2131 for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
2132 hst_p = 0;
2133 return SCPE_OK;
2134 }
2135 lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
2136 if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
2137 hst_p = 0;
2138 if (hst_lnt) {
2139 free (hst);
2140 hst_lnt = 0;
2141 hst = NULL;
2142 }
2143 if (lnt) {
2144 hst = (InstHistory *) calloc (lnt, sizeof (InstHistory));
2145 if (hst == NULL) return SCPE_MEM;
2146 hst_lnt = lnt;
2147 }
2148 return SCPE_OK;
2149 }
2150
2151 /* Show history */
2152
2153 t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
2154 {
2155 int32 l, j, k, di, lnt;
2156 char *cptr = (char *) desc;
2157 t_value sim_eval[2];
2158 t_stat r;
2159 InstHistory *h;
2160 extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
2161 UNIT *uptr, int32 sw);
2162
2163 if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
2164 if (cptr) {
2165 lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
2166 if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG;
2167 }
2168 else lnt = hst_lnt;
2169 di = hst_p - lnt; /* work forward */
2170 if (di < 0) di = di + hst_lnt;
2171 fprintf (st, "PC L AC MQ IR\n\n");
2172 for (k = 0; k < lnt; k++) { /* print specified */
2173 h = &hst[(di++) % hst_lnt]; /* entry pointer */
2174 if (h->pc & HIST_PC) { /* instruction? */
2175 l = (h->lac >> 18) & 1; /* link */
2176 fprintf (st, "%06o %o %06o %06o ", h->pc & AMASK, l, h->lac & DMASK, h->mq);
2177 sim_eval[0] = h->ir;
2178 sim_eval[1] = h->ir1;
2179 if ((fprint_sym (st, h->pc & AMASK, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
2180 fprintf (st, "(undefined) %06o", h->ir);
2181 } /* end else instruction */
2182 else if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */
2183 if (h->pc & HIST_PI) /* PI? */
2184 fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK);
2185 else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq);
2186 for (j = API_HLVL; j >= 0; j--)
2187 fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL);
2188 }
2189 else continue; /* invalid */
2190 fputc ('\n', st); /* end line */
2191 } /* end for */
2192 return SCPE_OK;
2193 }
2194
2195 /* Record events in history table */
2196
2197 void cpu_inst_hist (int32 addr, int32 inst)
2198 {
2199 t_value word = 0;
2200
2201 hst[hst_p].pc = addr | HIST_PC;
2202 hst[hst_p].ir = inst;
2203 if (cpu_ex (&word, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V')))
2204 hst[hst_p].ir1 = 0;
2205 else hst[hst_p].ir1 = word;
2206 hst[hst_p].lac = LAC;
2207 hst[hst_p].mq = MQ;
2208 hst_p = (hst_p + 1);
2209 if (hst_p >= hst_lnt) hst_p = 0;
2210 return;
2211 }
2212
2213 void cpu_intr_hist (int32 flag, int32 lvl)
2214 {
2215 int32 j;
2216
2217 hst[hst_p].pc = PC | flag;
2218 hst[hst_p].ir = 0;
2219 for (j = 0; j < API_HLVL+1; j++) hst[hst_p].ir =
2220 (hst[hst_p].ir << HIST_V_LVL) | (int_hwre[j] & HIST_M_LVL);
2221 hst[hst_p].ir1 = 0;
2222 hst[hst_p].lac = 0;
2223 hst[hst_p].mq = lvl;
2224 hst_p = (hst_p + 1);
2225 if (hst_p >= hst_lnt) hst_p = 0;
2226 return;
2227 }