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