home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Boot_Images / 2.11_on_rl02 / pdpsim.tz / pdpsim / pdp18b_cpu.c < prev    next >
Encoding:
Text File  |  1996-01-29  |  41.3 KB  |  1,401 lines

  1. /* pdp18b_cpu.c: 18b PDP CPU simulator
  2.  
  3.    Copyright (c) 1994, 1995, 1996, Robert M Supnik,
  4.    Digital Equipment Corporation
  5.    All rights reserved
  6.  
  7.    The 18b PDP family has five distinct architectural variants: PDP-1,
  8.    PDP-4, PDP-7, PDP-9, and PDP-15.  Of these, the PDP-1 is so unique
  9.    as to require a different simulator.  The PDP-4, PDP-7, PDP-9, and
  10.    PDP-15 are "upward compatible", with each new variant adding
  11.    distinct architectural features and incompatibilities.
  12.  
  13.    The register state for the 18b PDP's is:
  14.  
  15.    all            AC<0:17>    accumulator
  16.    all            MQ<0:17>    multiplier-quotient
  17.    all            L        link flag
  18.    all            PC<0:x>        program counter
  19.    all            IORS        I/O status register
  20.    PDP-7, PDP-9        EXTM        extend mode
  21.    PDP-15        BANKM        bank mode
  22.    PDP-7        TRAPM        trap mode
  23.    PDP-9, PDP-15    USMD        user mode
  24.    PDP-9, PDP-15    BR        bounds register
  25.    PDP-15        XR        index register
  26.    PDP-15        LR        limit register
  27. */
  28.  
  29. /* The PDP-4, PDP-7, and PDP-9 have five instruction formats: memory
  30.    reference, load immediate, I/O transfer, EAE, and operate.  The PDP-15
  31.    adds a sixth, index operate, and a seventh, floating point.  The memory
  32.    reference format for the PDP-4, PDP-7, and PDP-9, and for the PDP-15
  33.    in bank mode, is:
  34.  
  35.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  36.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  37.    |     op    |in|               address                | memory reference
  38.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  39.  
  40.    The PDP-15 in page mode trades an address bit for indexing capability:
  41.  
  42.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  43.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  44.    |     op    |in| X|             address               | memory reference
  45.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  46.  
  47.    <0:3>    mnemonic    action
  48.  
  49.    00        CAL        JMS with MA = 20
  50.    04        DAC        M[MA] = AC
  51.    10         JMS        M[MA] = L'mem'user'PC, PC = MA + 1
  52.    14        DZM        M[MA] = 0
  53.    20        LAC        AC = M[MA]
  54.    24         XOR        AC = AC ^ M[MA]
  55.    30         ADD        L'AC = AC + M[MA] one's complement
  56.    34         TAD        L'AC = AC + M[MA]
  57.    40        XCT        M[MA] is executed as an instruction
  58.    44         ISZ        M[MA] = M[MA] + 1, skip if M[MA] == 0
  59.    50         AND        AC = AC & M[MA]
  60.    54        SAD        skip if AC != M[MA]
  61.    60         JMP        PC = MA
  62.  
  63.    On the PDP-4, PDP-7, and PDP-9, and the PDP-15 in bank mode, memory
  64.    reference instructions can access an address space of 32K words.  The
  65.    address space is divided into four 8K word fields.  An instruction can
  66.    directly address, via its 13b address, the entire current field.  On the
  67.    PDP-4, PDP-7, and PDP-9, if extend mode is off, indirect addresses access
  68.    the current field; if on (or a PDP-15), they can access all 32K.
  69.  
  70.    On the PDP-15 in page mode, memory reference instructions can access
  71.    an address space of 128K words.  The address is divided into four 32K
  72.    word blocks, each of which consists of eight 4K pages.  An instruction
  73.    can directly address, via its 12b address, the current page.  Indirect
  74.    addresses can access the current block.  Indexed and autoincrement
  75.    addresses can access all 128K.
  76.  
  77.    On the PDP-4 and PDP-7, if an indirect address in in locations 00010-
  78.    00017 of any field, the indirect address is incremented and rewritten
  79.    to memory before use.  On the PDP-9 and PDP-15, only locations 00010-
  80.    00017 of field zero autoincrement; special logic will redirect indirect
  81.    references to 00010-00017 to field zero, even if (on the PDP-9) extend
  82.    mode is off.
  83. */
  84.  
  85. /* The EAE format is:
  86.  
  87.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  88.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  89.    | 1  1  0  1|  |  |  |  |  |  |  |  |  |  |  |  |  |  | EAE
  90.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  91.          |  |  |  |  |  |  |  |  |  |  |  |  |  |
  92.          |  |  |  |  |  |  |  |  |  |  |  |  |  +- or SC (3)
  93.          |  |  |  |  |  |  |  |  |  |  |  |  +---- or MQ (3)
  94.          |  |  |  |  |  |  |  |  |  |  |  +------- compl MQ (3)
  95.          |  |  |  |  |  |  |  |  \______________/
  96.          |  |  |  |  |  |  |  |         |
  97.          |  |  |  |  |  \_____/         +--------- shift count
  98.          |  |  |  |  |     |
  99.          |  |  |  |  |     +---------------------- EAE command (3)
  100.          |  |  |  |  +---------------------------- clear AC (2)
  101.          |  |  |  +------------------------------- or AC (2)
  102.          |  |  +---------------------------------- load EAE sign (1)
  103.          |  +------------------------------------- clear MQ (1)
  104.          +---------------------------------------- load link (1)
  105.  
  106.    The I/O transfer format is:
  107.  
  108.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  109.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  110.    | 1  1  1  0  0  0|      device     | sdv |cl|  pulse | I/O transfer
  111.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  112.  
  113.    The IO transfer instruction sends the the specified pulse to the
  114.    specified I/O device and sub-device.  The I/O device may take data
  115.    from the AC, return data to the AC, initiate or cancel operations,
  116.    or skip on status.  On the PDP-4, PDP-7, and PDP-9, bits <4:5>
  117.    were designated as subdevice bits but were never used; the PDP-15
  118.    requires them to be zero.
  119.  
  120.    On the PDP-15, the floating point format is:
  121.  
  122.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  123.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  124.    | 1  1  1  0  0  1|            subopcode              | floating point
  125.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  126.    |in|                   address                        |
  127.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  128.  
  129.    Indirection is always single level.
  130. */
  131.  
  132. /* On the PDP-15, the index operate format is:
  133.  
  134.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  135.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  136.    | 1  1  1  0  1| subopcode |        immediate         | index operate
  137.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  138.  
  139.    The index operate instructions provide various operations on the
  140.    index and limit registers.
  141.  
  142.    The operate format is:
  143.  
  144.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  145.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  146.    | 1  1  1  1  0|  |  |  |  |  |  |  |  |  |  |  |  |  | operate
  147.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  148.             |  |  |  |  |  |  |  |  |  |  |  |  |
  149.             |  |  |  |  |  |  |  |  |  |  |  |  +- CMA (3)
  150.             |  |  |  |  |  |  |  |  |  |  |  +---- CML (3)
  151.             |  |  |  |  |  |  |  |  |  |  +------- OAS (3)
  152.             |  |  |  |  |  |  |  |  |  +---------- RAL (3)
  153.             |  |  |  |  |  |  |  |  +------------- RAR (3)
  154.             |  |  |  |  |  |  |  +---------------- HLT (4)
  155.             |  |  |  |  |  |  +------------------- SMA (1)
  156.             |  |  |  |  |  +---------------------- SZA (1)
  157.             |  |  |  |  +------------------------- SNL (1)
  158.             |  |  |  +---------------------------- invert skip (1)
  159.             |  |  +------------------------------- rotate twice (2)
  160.             |  +---------------------------------- CLL (2)
  161.             +------------------------------------- CLA (2)
  162.  
  163.    The operate instruction can be microprogrammed to perform operations
  164.    on the AC and link.
  165.  
  166.    The load immediate format is:
  167.  
  168.      0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  169.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  170.    | 1  1  1  1  1|            immediate                 | LAW
  171.    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  172.  
  173.    <0:4>    mnemonic    action
  174.  
  175.    76        LAW        AC = IR
  176. */
  177.  
  178. /* This routine is the instruction decode routine for the 18b PDP's.
  179.    It is called from the simulator control program to execute
  180.    instructions in simulated memory, starting at the simulated PC.
  181.    It runs until 'reason' is set non-zero.
  182.  
  183.    General notes:
  184.  
  185.    1. Reasons to stop.  The simulator can be stopped by:
  186.  
  187.     HALT instruction
  188.     breakpoint encountered
  189.     unimplemented instruction and STOP_INST flag set
  190.     nested XCT's
  191.     I/O error in I/O simulator
  192.  
  193.    2. Interrupts.  Interrupt requests are maintained in the int_req
  194.       register.  If interrupts are on and not deferred, and at least
  195.       one interrupt request is set, a program interrupt occurs.
  196.  
  197.    3. Arithmetic.  The 18b PDP's implements both 1's and 2's complement
  198.       arithmetic for signed numbers.  In 1's complement arithmetic, a
  199.       negative number is represented by the complement (XOR 0777777) of
  200.       its absolute value.  Addition of 1's complement numbers requires
  201.       propagating the carry out of the high order bit back to the low
  202.       order bit.
  203.  
  204.    4. Adding I/O devices.  Three modules must be modified:
  205.  
  206.     pdp18b_defs.h    add interrupt request definition
  207.     pdp18b_cpu.c    add IOT and IORS dispatches
  208.     pdp18b_sys.c    add pointer to data structures to sim_devices
  209. */
  210.  
  211. #include "pdp18b_defs.h"
  212.  
  213. #define ILL_ADR_FLAG    (1 << ADDRSIZE)
  214. #define save_ibkpt    (cpu_unit.u3)
  215. #define UNIT_V_NOEAE    (UNIT_V_UF)            /* EAE absent */
  216. #define UNIT_NOEAE    (1 << UNIT_V_NOEAE)
  217. #define UNIT_V_MSIZE    (UNIT_V_UF+1)            /* dummy mask */
  218. #define UNIT_MSIZE    (1 << UNIT_V_MSIZE)
  219. #if defined (PDP4)
  220. #define EAE_DFLT    UNIT_NOEAE
  221. #else
  222. #define EAE_DFLT    0
  223. #endif
  224.  
  225. unsigned int M[MAXMEMSIZE] = { 0 };
  226. int saved_LAC = 0;                    /* link'AC */
  227. int saved_MQ = 0;                    /* MQ */
  228. int saved_PC = 0;                    /* PC */
  229. int int_req = 0;                    /* int requests */
  230. int iors = 0;                        /* IORS */
  231. int ion = 0;                        /* int on */
  232. int ion_defer = 0;                    /* int defer */
  233. int memm = 0;                        /* ext mem mode */
  234. int usmd = 0;                        /* user mode */
  235. int usmdbuf = 0;                    /* user mode buffer */
  236. int trap_pending = 0;                    /* trap pending */
  237. int emir_pending = 0;                    /* emir pending */
  238. int rest_pending = 0;                    /* restore pending */
  239. int BR = 0;                        /* mem mgt bounds */
  240. int nexm = 0;                        /* nx mem flag */
  241. int prvn = 0;                        /* priv viol flag */
  242. int SC = 0;                        /* shift count */
  243. int eae_ac_sign = 0;                    /* EAE AC sign */
  244. int SR = 0;                        /* switch register */
  245. int XR = 0;                        /* index register */
  246. int LR = 0;                        /* limit register */
  247. int stop_inst = 0;                    /* stop on rsrv inst */
  248. int xct_max = 16;                    /* nested XCT limit */
  249. int old_PC = 0;                        /* old PC */
  250. int ibkpt_addr = ILL_ADR_FLAG | ADDRMASK;        /* breakpoint addr */
  251. extern int sim_int_char;
  252. int cpu_ex (int *vptr, int addr, UNIT *uptr, int sw);
  253. int cpu_dep (int val, int addr, UNIT *uptr, int sw);
  254. int cpu_reset (DEVICE *dptr);
  255. int cpu_svc (UNIT *uptr);
  256. int cpu_set_size (UNIT *uptr, int value);
  257. int upd_iors (void);
  258.  
  259. /* CPU data structures
  260.  
  261.    cpu_dev    CPU device descriptor
  262.    cpu_unit    CPU unit
  263.    cpu_reg    CPU register list
  264.    cpu_mod    CPU modifier list
  265. */
  266.  
  267. UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX+EAE_DFLT, MAXMEMSIZE) };
  268.  
  269. REG cpu_reg[] = {
  270.     { ORDATA (PC, saved_PC, ADDRSIZE) },
  271.     { ORDATA (AC, saved_LAC, 18) },
  272.     { FLDATA (L, saved_LAC, 18) },
  273. #if !defined (PDP4)
  274.     { ORDATA (MQ, saved_MQ, 18) },
  275.     { ORDATA (SC, SC, 6) },
  276.     { FLDATA (EAE_AC_SIGN, eae_ac_sign, 18) },
  277. #endif
  278.     { ORDATA (SR, SR, 18) },
  279.     { ORDATA (IORS, iors, 18), REG_RO },
  280.     { ORDATA (INT, int_req, 32), REG_RO },
  281.     { FLDATA (ION, ion, 0) },
  282.     { ORDATA (ION_DELAY, ion_defer, 2) },
  283. #if defined (PDP7) 
  284.     { FLDATA (TRAPM, usmd, 0) },
  285.     { FLDATA (TRAPP, trap_pending, 0) },
  286.     { FLDATA (EXTM, memm, 0) },
  287.     { FLDATA (EMIRP, emir_pending, 0) },
  288. #elif defined (PDP9)
  289.     { ORDATA (BR, BR, ADDRSIZE) },
  290.     { FLDATA (USMD, usmd, 0) },
  291.     { FLDATA (USMDBUF, usmdbuf, 0) },
  292.     { FLDATA (NEXM, nexm, 0) },
  293.     { FLDATA (PRVN, prvn, 0) },
  294.     { FLDATA (TRAPP, trap_pending, 0) },
  295.     { FLDATA (EXTM, memm, 0) },
  296.     { FLDATA (EMIRP, emir_pending, 0) },
  297.     { FLDATA (RESTP, rest_pending, 0) },
  298.     { FLDATA (PWRFL, int_req, INT_V_PWRFL) },
  299. #elif defined (PDP15)
  300.     { ORDATA (XR, XR, 18) },
  301.     { ORDATA (LR, LR, 18) },
  302.     { ORDATA (BR, BR, ADDRSIZE) },
  303.     { FLDATA (NEXM, nexm, 0) },
  304.     { FLDATA (PRVN, prvn, 0) },
  305.     { FLDATA (TRAPP, trap_pending, 0) },
  306.     { FLDATA (USMD, usmd, 0) },
  307.     { FLDATA (USMDBUF, usmdbuf, 0) },
  308.     { FLDATA (BANKM, memm, 0) },
  309.     { FLDATA (RESP, rest_pending, 0) },
  310.     { FLDATA (PWRFL, int_req, INT_V_PWRFL) },
  311. #endif
  312.     { ORDATA (OLDPC, old_PC, ADDRSIZE), REG_RO },
  313.     { FLDATA (STOP_INST, stop_inst, 0) },
  314.     { FLDATA (NOEAE, cpu_unit.flags, UNIT_V_NOEAE), REG_HRO },
  315.     { DRDATA (XCT_MAX, xct_max, 8), REG_NZ },
  316.     { ORDATA (BREAK, ibkpt_addr, ADDRSIZE + 1) },
  317.     { ORDATA (WRU, sim_int_char, 8) },
  318.     { NULL }  };
  319.  
  320. MTAB cpu_mod[] = {
  321. #if !defined (PDP4)
  322.     { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL },
  323.     { UNIT_NOEAE, 0, "EAE", "EAE", NULL },
  324. #endif
  325.     { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
  326.     { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
  327. #if (MAXMEMSIZE > 8192)
  328.     { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
  329.     { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
  330.     { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
  331.     { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
  332.     { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
  333.     { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
  334. #endif
  335. #if (MAXMEMSIZE > 32768)
  336.     { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
  337.     { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
  338.     { UNIT_MSIZE, 81920, NULL, "80K", &cpu_set_size },
  339.     { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size },
  340.     { UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size },
  341.     { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
  342. #endif
  343.     { 0 }  };
  344.  
  345. DEVICE cpu_dev = {
  346.     "CPU", &cpu_unit, cpu_reg, cpu_mod,
  347.     1, 8, ADDRSIZE, 1, 8, 18,
  348.     &cpu_ex, &cpu_dep, &cpu_reset,
  349.     NULL, NULL, NULL };
  350.  
  351. int sim_instr (void)
  352. {
  353. extern int sim_interval;
  354. register int PC, LAC, MQ;
  355. int iot_data, device, pulse, reason;
  356. extern int tti (int pulse, int AC);
  357. extern int tto (int pulse, int AC);
  358. extern int ptr (int pulse, int AC);
  359. extern int ptp (int pulse, int AC);
  360. extern int clk (int pulse, int AC);
  361. extern int lpt65 (int pulse, int AC);
  362. extern int lpt66 (int pulse, int AC);
  363. #if defined (DRM)
  364. extern int drm60 (int pulse, int AC);
  365. extern int drm61 (int pulse, int AC);
  366. extern int drm62 (int pulse, int AC);
  367. #endif
  368. #if defined (RF)
  369. extern int rf70 (int pulse, int AC);
  370. extern int rf72 (int pulse, int AC);
  371. #endif
  372. #if defined (RP)
  373. extern int rp63 (int pulse, int AC);
  374. extern int rp64 (int pulse, int AC);
  375. #endif
  376. #if defined (MTA)
  377. extern int mt (int pulse, int AC);
  378. #endif
  379. extern int sim_process_event (void);
  380. extern int sim_activate (UNIT *uptr, int interval);
  381. extern int reset_all (int start);
  382.  
  383. #define JMS_WORD(t) ((LAC & 01000000) >> 1) | ((memm & 1) << 16) | \
  384.     ((t & 1) << 15) | ((PC) & 077777)
  385. #define INCR_ADDR(x) ((x & epcmask) | ((x + 1) & damask))
  386. #define SEXT(x) ((int) (((x) & 0400000)? (x) | ~0777777: (x) & 0777777))
  387.  
  388. /* Restore register state */
  389.  
  390. #if defined (PDP15)
  391. register int epcmask, damask;
  392.  
  393. damask = memm? 017777: 07777;                /* set dir addr mask */
  394. epcmask = ADDRMASK & ~damask;                /* extended PC mask */
  395.  
  396. #else
  397. #define damask    017777                    /* direct addr mask */
  398. #define epcmask    (ADDRMASK & ~damask)            /* extended PC mask */
  399. #endif
  400.  
  401. PC = saved_PC & ADDRMASK;                /* load local copies */
  402. LAC = saved_LAC & 01777777;
  403. MQ = saved_MQ & 0777777;
  404. reason = 0;
  405.  
  406. /* Main instruction fetch/decode loop: check trap and interrupt */
  407.  
  408. while (reason == 0) {                    /* loop until halted */
  409. register int IR, MA, t, xct_count;
  410. register int link_init, fill;
  411.  
  412. if (sim_interval <= 0) {                /* check clock queue */
  413.     if (reason = sim_process_event ()) break;  }
  414.  
  415. /* Protection traps work like interrupts, with these quirks:
  416.  
  417.    PDP-7        extend mode forced on, M[0] = PC, PC = 2
  418.    PDP-9, PDP-15    extend/bank mode forced off, M[0/20] = PC, PC = 0/21
  419. */
  420.  
  421. #if defined (PDP7)
  422. if (trap_pending) {                    /* trap pending? */
  423.     old_PC = PC;                    /* save old PC */
  424.     M[0] = JMS_WORD (1);                /* save state */
  425.     PC = 2;                        /* fetch next from 2 */
  426.     ion = 0;                    /* interrupts off */
  427.     memm = 1;                    /* extend on */
  428.     emir_pending = trap_pending = 0;        /* emir, trap off */
  429.     usmd = 0;  }                    /* protect off */
  430. #endif
  431.  
  432. #if defined (PDP9) || defined (PDP15)
  433. if (trap_pending) {                    /* trap pending? */
  434.     old_PC = PC;                    /* save old PC */
  435.     MA = ion? 0: 020;                /* save in 0 or 20 */
  436.     M[MA] = JMS_WORD (1);                /* save state */
  437.     PC = MA + 1;                    /* fetch next */
  438.     ion = 0;                    /* interrupts off */
  439.     memm = 0;                    /* extend/bank off */
  440.     emir_pending = rest_pending = trap_pending = 0;    /* emir,rest,trap off */
  441.     usmd = 0;  }                    /* protect off */
  442. #endif
  443.  
  444. if (ion && !ion_defer && int_req) {            /* interrupt? */
  445.     old_PC = PC;                    /* save old PC */
  446.     M[0] = JMS_WORD (usmd);                /* save state */
  447.     PC = 1;                        /* fetch next from 1 */
  448.     ion = 0;                    /* interrupts off */
  449.     memm = 0;                    /* extend/bank off */
  450.     emir_pending = rest_pending = 0;        /* emir, restore off */
  451.     usmd = 0;  }                    /* protect off */
  452.  
  453. if (PC == ibkpt_addr) {                    /* breakpoint? */
  454.     save_ibkpt = ibkpt_addr;            /* save ibkpt */
  455.     ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG;        /* disable */
  456.     sim_activate (&cpu_unit, 1);            /* sched re-enable */
  457.     reason = STOP_IBKPT;                /* stop simulation */
  458.     break;  }
  459.  
  460. /* The following macros implement addressing.  They account for autoincrement
  461.    addressing, extended addressing, and memory protection, if it exists.
  462.  
  463.    CHECK_AUTO_INC        check auto increment
  464.    INDIRECT            indirect addressing
  465.    CHECK_INDEX            check indexing
  466.    CHECK_ADDR_R            check address for read
  467.    CHECK_ADDR_W            check address for write
  468.  
  469.    On the PDP-4 and PDP-7,
  470.     There are autoincrement locations in every field.  If a field
  471.         does not exist, it is impossible to generate an
  472.         autoincrement reference (all instructions are CAL).
  473.     Indirect addressing range is determined by extend mode.
  474.     There is no indexing.
  475.     There is no memory protection, nxm reads zero and ignores writes.
  476. */
  477.  
  478. #if defined (PDP4) || defined (PDP7)
  479. #define CHECK_AUTO_INC \
  480.     if ((IR & 017770) == 010) M[MA] = (M[MA] + 1) & 0777777
  481. #define INDIRECT \
  482.     MA = memm? M[MA] & IAMASK: (MA & epcmask) | (M[MA] & damask)
  483. #define CHECK_INDEX             /* no indexing capability */
  484. #define CHECK_ADDR_R(x)            /* no read protection */
  485. #define CHECK_ADDR_W(x) \
  486.     if ((x) >= MEMSIZE) break
  487. #endif
  488.  
  489. /* On the PDP-9,
  490.     The autoincrement registers are in field zero only.  Regardless
  491.         of extend mode, indirect addressing through 00010-00017
  492.         will access absolute locations 00010-00017.
  493.     Indirect addressing range is determined by extend mode.  If
  494.         extend mode is off, and autoincrementing is used, the
  495.         resolved address is in bank 0 (KG09B maintenance manual).
  496.     There is no indexing.
  497.     Memory protection is implemented for foreground/background operation.
  498. */
  499.  
  500. #if defined (PDP9)
  501. #define CHECK_AUTO_INC \
  502.     if ((IR & 017770) == 010) { \
  503.         MA = MA & 017; \
  504.         M[MA] = (M[MA] + 1) & 0777777;  }
  505. #define INDIRECT \
  506.     MA = memm? M[MA] & IAMASK: (MA & epcmask) | (M[MA] & damask)
  507. #define CHECK_ADDR_R(x) \
  508.     if (usmd) { \
  509.         if ((x) >= MEMSIZE) { \
  510.             nexm = prvn = trap_pending = 1; \
  511.             break;  } \
  512.         if ((x) >= BR) { \
  513.             prvn = trap_pending = 1;  \
  514.             break;  }  }  \
  515.     if ((x) >= MEMSIZE) nexm = 1
  516. #define CHECK_INDEX             /* no indexing capability */
  517. #define CHECK_ADDR_W(x) \
  518.     CHECK_ADDR_R (x); \
  519.     if ((x) >= MEMSIZE) break
  520. #endif
  521.  
  522. /*  On the PDP-15,
  523.     The autoincrement registers are in page zero only.  Regardless
  524.         of bank mode, indirect addressing through 00010-00017
  525.         will access absolute locations 00010-00017.
  526.     Indirect addressing range is determined by autoincrementing.
  527.     Indexing is available if bank mode is off.
  528.     Memory protection is implemented for foreground/background operation.
  529. */
  530.  
  531. #if defined (PDP15)
  532. #define CHECK_AUTO_INC \
  533.     if ((IR & damask & ~07) == 00010) { \
  534.         MA = MA & 017; \
  535.         M[MA] = (M[MA] + 1) & 0777777;  }
  536. #define INDIRECT \
  537.     if (rest_pending) { \
  538.         rest_pending = 0; \
  539.         LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); \
  540.         memm = (M[MA] >> 16) & 1; \
  541.         usmd = (M[MA] >> 15) & 1;  } \
  542.     MA = ((IR & damask & ~07) != 00010)? \
  543.         (PC & BLKMASK) | (M[MA] & IAMASK): (M[MA] & ADDRMASK)
  544. #define CHECK_INDEX \
  545.     if ((IR & 0010000) && (memm == 0)) MA = (MA + XR) & ADDRMASK
  546. #define CHECK_ADDR_R(x) \
  547.     if (usmd) { \
  548.         if ((x) >= MEMSIZE) { \
  549.             nexm = prvn = trap_pending = 1; \
  550.             break;  } \
  551.         if ((x) >= BR) { \
  552.             prvn = trap_pending = 1;  \
  553.             break;  }  }  \
  554.     if ((x) >= MEMSIZE) nexm = 1
  555. #define CHECK_ADDR_W(x) \
  556.     CHECK_ADDR_R (x); \
  557.     if ((x) >= MEMSIZE) break
  558. #endif
  559.  
  560. /* Fetch, decode instruction */
  561.  
  562. CHECK_ADDR_R (PC);                    /* validate PC */
  563. IR = M[PC];                        /* fetch instruction */
  564. PC = INCR_ADDR (PC);                    /* increment PC */
  565. #if defined (PDP9) || defined (PDP15)
  566. if (!ion_defer) usmd = usmdbuf;                /* no IOT? load usmd */
  567. #endif
  568. if (ion_defer) ion_defer = ion_defer - 1;        /* count down defer */
  569. xct_count = 0;                        /* track nested XCT's */
  570. sim_interval = sim_interval - 1;
  571.  
  572. xct_instr:                        /* label for XCT */
  573. MA = (PC & epcmask) | (IR & damask);            /* effective address */
  574. switch ((IR >> 13) & 037) {                /* decode IR<0:4> */
  575.  
  576. /* LAC: opcode 20 */
  577.  
  578. case 011:                        /* LAC, indir */
  579.     CHECK_AUTO_INC;
  580.     INDIRECT;
  581. case 010:                        /* LAC, dir */
  582.     CHECK_INDEX;
  583.     CHECK_ADDR_R (MA);
  584.     LAC = (LAC & 01000000) | M[MA];
  585.     break;
  586.  
  587. /* DAC: opcode 04 */
  588.  
  589. case 003:                        /* DAC, indir */
  590.     CHECK_AUTO_INC;
  591.     INDIRECT;
  592. case 002:                        /* DAC, dir */
  593.     CHECK_INDEX;
  594.     CHECK_ADDR_W (MA);
  595.     M[MA] = LAC & 0777777;
  596.     break;
  597.  
  598. /* DZM: opcode 14 */
  599.  
  600. case 007:                        /* DZM, indir */
  601.     CHECK_AUTO_INC;
  602.     INDIRECT;
  603. case 006:                        /* DZM, direct */
  604.     CHECK_INDEX;
  605.     CHECK_ADDR_W (MA);
  606.     M[MA] = 0;
  607.     break;
  608.  
  609. /* AND: opcode 50 */
  610.  
  611. case 025:                        /* AND, ind */
  612.     CHECK_AUTO_INC;
  613.     INDIRECT;
  614. case 024:                        /* AND, dir */
  615.     CHECK_INDEX;
  616.     CHECK_ADDR_R (MA);
  617.     LAC = LAC & (M[MA] | 01000000);
  618.     break;
  619.  
  620. /* XOR: opcode 24 */
  621.  
  622. case 013:                        /* XOR, ind */
  623.     CHECK_AUTO_INC;
  624.     INDIRECT;
  625. case 012:                        /* XOR, dir */
  626.     CHECK_INDEX;
  627.     CHECK_ADDR_R (MA);
  628.     LAC = LAC ^ M[MA];
  629.     break;
  630.  
  631. /* ADD: opcode 30 */
  632.  
  633. case 015:                        /* ADD, indir */
  634.     CHECK_AUTO_INC;
  635.     INDIRECT;
  636. case 014:                        /* ADD, dir */
  637.     CHECK_INDEX;
  638.     CHECK_ADDR_R (MA);
  639.     t = (LAC & 0777777) + M[MA];
  640.     if (t > 0777777) t = (t + 1) & 0777777;
  641.     if (((~LAC ^ M[MA]) & (LAC ^ t)) & 0400000)    /* overflow? */
  642.         LAC = 01000000 | t;            /* set link */
  643.     else LAC = (LAC & 01000000) | t;
  644.     break;
  645.  
  646. /* TAD: opcode 34 */
  647.  
  648. case 017:                        /* TAD, indir */
  649.     CHECK_AUTO_INC;
  650.     INDIRECT;
  651. case 016:                        /* TAD, dir */
  652.     CHECK_INDEX;
  653.     CHECK_ADDR_R (MA);
  654.     LAC = (LAC + M[MA]) & 01777777;
  655.     break;
  656.  
  657. /* ISZ: opcode 44 */
  658.  
  659. case 023:                        /* ISZ, indir */
  660.     CHECK_AUTO_INC;
  661.     INDIRECT;
  662. case 022:                        /* ISZ, dir */
  663.     CHECK_INDEX;
  664.     CHECK_ADDR_W (MA);
  665.     M[MA] = (M[MA] + 1) & 0777777;
  666.     if (M[MA] == 0) PC = INCR_ADDR (PC);
  667.     break;
  668.  
  669. /* SAD: opcode 54 */
  670.  
  671. case 027:                        /* SAD, indir */
  672.     CHECK_AUTO_INC;
  673.     INDIRECT;
  674. case 026:                        /* SAD, dir */
  675.     CHECK_INDEX;
  676.     CHECK_ADDR_R (MA);
  677.     if ((LAC & 0777777) != M[MA]) PC = INCR_ADDR (PC);
  678.     break;
  679.  
  680. /* XCT: opcode 40 */
  681.  
  682. case 021:                        /* XCT, indir */
  683.     CHECK_AUTO_INC;
  684.     INDIRECT;
  685. case 020:                        /* XCT, dir  */
  686.     CHECK_INDEX;
  687.     CHECK_ADDR_R (MA);
  688.     if (usmd && (xct_count != 0)) {            /* trap and chained? */
  689.         prvn = trap_pending = 1;
  690.         break;  }
  691.     if (xct_count >= xct_max) {            /* too many XCT's? */
  692.         reason = STOP_XCT;
  693.         break;  }
  694.     xct_count = xct_count + 1;            /* count XCT's */
  695. #if defined (PDP9)
  696.     ion_defer = 1;                    /* defer intr */
  697. #endif
  698.     IR = M[MA];                    /* get instruction */
  699.     goto xct_instr;                    /* go execute */
  700.  
  701. /* CAL: opcode 00 
  702.  
  703.    On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20
  704.    On the PDP-9, CAL clears user mode
  705.    On the PDP-15, CAL goes to absolute 20, regardless of mode
  706. */
  707.  
  708. case 001: case 000:                    /* CAL */
  709.     t = usmd;
  710. #if defined (PDP15)
  711.     MA = 020;
  712. #else
  713.     MA = (memm? 0: PC & epcmask) | 020;        /* MA = 20 */
  714. #endif
  715. #if defined (PDP9) || defined (PDP15)
  716.     usmd = 0;                    /* clear user mode */
  717. #endif
  718.     if (IR & 0020000) { INDIRECT;  }        /* indirect? */
  719.     CHECK_ADDR_W (MA);
  720.     old_PC = PC;
  721.     M[MA] = JMS_WORD (t);                /* save state */
  722.     PC = INCR_ADDR (MA);
  723.     break;
  724.  
  725. /* JMS: opcode 010 */
  726.  
  727. case 005:                        /* JMS, indir */
  728.     CHECK_AUTO_INC;
  729.     INDIRECT;
  730. case 004:                        /* JMS, dir */
  731.     CHECK_INDEX;
  732.     CHECK_ADDR_W (MA);
  733.     old_PC = PC;
  734.     M[MA] = JMS_WORD (usmd);            /* save state */
  735.     PC = INCR_ADDR (MA);
  736.     break;
  737.  
  738. /* JMP: opcode 60
  739.  
  740.    Restore quirks:
  741.     On the PDP-7 and PDP-9, EMIR can only clear extend
  742.     On the PDP-15, any I triggers restore, but JMP I is conventional
  743. */
  744.  
  745. case 031:                        /* JMP, indir */
  746.     CHECK_AUTO_INC;                    /* check auto inc */
  747. #if defined (PDP7) || defined (PDP9)
  748.     if (emir_pending && (((M[MA] >> 16) & 1) == 0)) memm = 0;
  749. #elif defined (PDP9)
  750.     if (rest_pending) {                /* restore pending? */
  751.         LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777);
  752.         memm = (M[MA] >> 16) & 1;
  753.         usmd = (M[MA] >> 15) & 1);  }
  754. #endif
  755.     INDIRECT;                    /* complete indirect */
  756.     emir_pending = rest_pending = 0;
  757. case 030:                        /* JMP, dir */
  758.     CHECK_INDEX;
  759.     old_PC = PC;                    /* save old PC */
  760.     PC = MA;
  761.     break;
  762.  
  763. /* OPR: opcode 74 */
  764.  
  765. case 037:                        /* OPR, indir */
  766.     LAC = (LAC & 01000000) | IR;            /* LAW */
  767.     break;
  768.  
  769. case 036:                        /* OPR, dir */
  770.     switch ((IR >> 6) & 017) {            /* decode IR<8:11> */
  771.     case 0:                         /* nop */
  772.         break;
  773.     case 1:                     /* SMA */
  774.         if ((LAC & 0400000) != 0) PC = INCR_ADDR (PC);
  775.         break;
  776.     case 2:                     /* SZA */
  777.         if ((LAC & 0777777) == 0) PC = INCR_ADDR (PC);
  778.         break;
  779.     case 3:                        /* SZA | SMA */
  780.         if (((LAC & 0777777) == 0) || ((LAC & 0400000) != 0))
  781.             PC = INCR_ADDR (PC); 
  782.         break;
  783.     case 4:                     /* SNL */
  784.         if (LAC >= 01000000) PC = INCR_ADDR (PC);
  785.         break;
  786.     case 5:                        /* SNL | SMA */
  787.         if (LAC >= 0400000) PC = INCR_ADDR (PC);
  788.         break;
  789.     case 6:                        /* SNL | SZA */
  790.         if ((LAC >= 01000000) || (LAC == 0)) PC = INCR_ADDR (PC);
  791.         break;
  792.     case 7:                        /* SNL | SZA | SMA */
  793.         if ((LAC >= 0400000) || (LAC == 0)) PC = INCR_ADDR (PC);
  794.         break;
  795.     case 010:                    /* SKP */
  796.         PC = INCR_ADDR (PC);
  797.         break;
  798.     case 011:                     /* SPA */
  799.         if ((LAC & 0400000) == 0) PC = INCR_ADDR (PC);
  800.         break;
  801.     case 012:                     /* SNA */
  802.         if ((LAC & 0777777) != 0) PC = INCR_ADDR (PC);
  803.         break;
  804.     case 013:                    /* SNA & SPA */
  805.         if (((LAC & 0777777) != 0) && ((LAC & 0400000) == 0))
  806.             PC = INCR_ADDR (PC);
  807.         break;
  808.     case 014:                     /* SZL */
  809.         if (LAC < 01000000) PC = INCR_ADDR (PC);
  810.         break;
  811.     case 015:                    /* SZL & SPA */
  812.         if (LAC < 0400000) PC = INCR_ADDR (PC);
  813.         break;
  814.     case 016:                    /* SZL & SNA */
  815.         if ((LAC < 01000000) && (LAC != 0)) PC = INCR_ADDR (PC);
  816.         break;
  817.     case 017:                    /* SZL & SNA & SPA */
  818.         if ((LAC < 0400000) && (LAC != 0)) PC = INCR_ADDR (PC);
  819.         break;  }                /* end switch skips */
  820.  
  821. /* OPR, continued */
  822.  
  823.     switch (((IR >> 9) & 014) | (IR & 03)) {    /* IR<5:6,16:17> */
  824.     case 0:                        /* NOP */
  825.         break;
  826.     case 1:                        /* CMA */
  827.         LAC = LAC ^ 0777777;
  828.         break;
  829.     case 2:                        /* CML */
  830.         LAC = LAC ^ 01000000;
  831.         break;
  832.     case 3:                        /* CML CMA */
  833.         LAC = LAC ^ 01777777;
  834.         break;
  835.     case 4:                        /* CLL */
  836.         LAC = LAC & 0777777;
  837.         break;
  838.     case 5:                        /* CLL CMA */
  839.         LAC = (LAC & 0777777) ^ 0777777;
  840.         break;
  841.     case 6:                        /* CLL CML = STL */
  842.         LAC = LAC | 01000000;
  843.         break;
  844.     case 7:                        /* CLL CML CMA */
  845.         LAC = (LAC | 01000000) ^ 0777777;
  846.         break;
  847.     case 010:                    /* CLA */
  848.         LAC = LAC & 01000000;
  849.         break;
  850.     case 011:                    /* CLA CMA = STA */
  851.         LAC = LAC | 0777777;
  852.         break;
  853.     case 012:                    /* CLA CML */
  854.         LAC = (LAC & 01000000) ^ 01000000;
  855.         break;
  856.     case 013:                    /* CLA CML CMA */
  857.         LAC = (LAC | 0777777) ^ 01000000;
  858.         break;
  859.     case 014:                    /* CLA CLL */
  860.         LAC = 0;
  861.         break;
  862.     case 015:                    /* CLA CLL CMA */
  863.         LAC = 0777777;
  864.         break;
  865.     case 016:                    /* CLA CLL CML */
  866.         LAC = 01000000;
  867.         break;
  868.     case 017:                    /* CLA CLL CML CMA */
  869.         LAC = 01777777;
  870.         break;  }                /* end decode */
  871.  
  872. /* OPR, continued */
  873.  
  874.     if (IR & 0000004) {                /* OAS */
  875. #if defined (PDP9) || defined (PDP15)
  876.         if (usmd) prvn = trap_pending = 1;
  877.         else
  878. #endif
  879.         LAC = LAC | SR;  }
  880.  
  881.     switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) {    /* decode IR<7,13:14> */
  882.     case 1:                        /* RAL */
  883.         LAC = ((LAC << 1) | (LAC >> 18)) & 01777777;
  884.         break;
  885.     case 2:                        /* RAR */
  886.         LAC = ((LAC >> 1) | (LAC << 18)) & 01777777;
  887.         break;
  888.     case 3:                        /* RAL RAR */
  889. #if defined (PDP15)                    /* PDP-15 */
  890.         LAC = (LAC + 1) & 01777777;        /* IAC */
  891. #else                            /* PDP-4,-7,-9 */
  892.         reason = stop_inst;            /* undefined */
  893. #endif
  894.         break;
  895.     case 5:                        /* RTL */
  896.         LAC = ((LAC << 2) | (LAC >> 17)) & 01777777;
  897.         break;
  898.     case 6:                        /* RTR */
  899.         LAC = ((LAC >> 2) | (LAC << 17)) & 01777777;
  900.         break;
  901.     case 7:                        /* RTL RTR */
  902. #if defined (PDP15)                    /* PDP-15 */
  903.         LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) |
  904.             (LAC & 01000000);        /* BSW */
  905. #else                            /* PDP-4,-7,-9 */
  906.         reason = stop_inst;            /* undefined */
  907. #endif
  908.         break;  }                /* end switch rotate */
  909.  
  910.     if (IR & 0000040) {                /* HLT */
  911.         if (usmd) prvn = trap_pending = 1;
  912.         else reason = STOP_HALT;  }
  913.     break;                        /* end OPR */
  914.  
  915. /* EAE: opcode 64 
  916.  
  917.    The EAE is microprogrammed to execute variable length signed and
  918.    unsigned shift, multiply, divide, and normalize.  Most commands are
  919.    controlled by a six bit step counter (SC).  In the hardware, the step
  920.    counter is complemented on load and then counted up to zero; timing
  921.    guarantees an initial increment, which completes the two's complement
  922.    load.  In the simulator, the SC is loaded normally and then counted
  923.    down to zero; the read SC command compensates.
  924. */
  925.  
  926. case 033: case 032:                    /* EAE */
  927.     if (cpu_unit.flags & UNIT_NOEAE) break;        /* disabled? */
  928.     if (IR & 0020000)                /* IR<4>? AC0 to L */
  929.         LAC = ((LAC << 1) & 01000000) | (LAC & 0777777);
  930.     if (IR & 0010000) MQ = 0;            /* IR<5>? clear MQ */
  931.     if ((IR & 0004000) && (LAC & 0400000))        /* IR<6> and minus? */
  932.         eae_ac_sign = 01000000;            /* set eae_ac_sign */
  933.     else eae_ac_sign = 0;                /* if not, unsigned */
  934.     if (IR & 0002000) MQ = (MQ | LAC) & 0777777;    /* IR<7>? or AC */
  935.     else if (eae_ac_sign) LAC = LAC ^ 0777777;    /* if not, |AC| */
  936.     if (IR & 0001000) LAC = LAC & 01000000;        /* IR<8>? clear AC */
  937.     link_init = LAC & 01000000;            /* link temporary */
  938.     fill = link_init? 0777777: 0;            /* fill = link */
  939.  
  940.     switch ((IR >> 6) & 07) {            /* case on IR<9:11> */
  941.     case 0:                        /* setup */
  942.         if (IR & 04) LAC = LAC ^ 0777777;    /* IR<15>? ~AC */
  943.         if (IR & 02) LAC = LAC | MQ;        /* IR<16>? or MQ */
  944.         if (IR & 01) LAC = LAC | ((-SC) & 077);    /* IR<17>? or SC */
  945.         break;
  946.  
  947.     case 1:                        /* multiply */
  948.         CHECK_ADDR_R (PC);            /* validate PC */
  949.         MA = M[PC];                /* get next word */
  950.         PC = INCR_ADDR (PC);            /* increment PC */
  951.         if (eae_ac_sign) MQ = MQ ^ 0777777;    /* EAE AC sign? ~MQ */
  952.         LAC = LAC & 0777777;            /* clear link */
  953.         for (SC = IR & 077; SC != 0; SC--) {    /* loop per step cnt */
  954.             if (MQ & 1) LAC = LAC + MA;    /* MQ<17>? add */
  955.             MQ = (MQ >> 1) | ((LAC & 1) << 17);
  956.             LAC = LAC >> 1;  }        /* shift AC'MQ right */
  957.         if (eae_ac_sign ^ link_init) {        /* result negative? */
  958.             LAC = LAC ^ 0777777;
  959.             MQ = MQ ^ 0777777;  }
  960.         break;
  961.  
  962. /* EAE, continued
  963.  
  964.    Divide uses a non-restoring divide.  This code duplicates the PDP-7
  965.    algorithm, except for its use of two's complement arithmetic instead
  966.    of 1's complement.
  967.  
  968.    The quotient is generated in one's complement form; therefore, the
  969.    quotient is complemented if the input operands had the same sign
  970.    (that is, if the quotient is positive).
  971. */
  972.  
  973.     case 3:                        /* divide */
  974.         CHECK_ADDR_R (PC);            /* validate PC */
  975.         MA = M[PC];                /* get next word */
  976.         PC = INCR_ADDR (PC);            /* increment PC */
  977.         if (eae_ac_sign) MQ = MQ ^ 0777777;    /* EAE AC sign? ~MQ */
  978.         if ((LAC & 0777777) >= MA) {        /* overflow? */
  979.             LAC = (LAC - MA) | 01000000;    /* set link */
  980.             break;  }
  981.         LAC = LAC & 0777777;            /* clear link */
  982.         t = 0;                    /* init loop */
  983.         for (SC = IR & 077; SC != 0; SC--) {
  984.             if (t) LAC = (LAC + MA) & 01777777;
  985.             else LAC = (LAC - MA) & 01777777;
  986.             t = (LAC >> 18) & 1;        /* quotient bit */
  987.             if (SC > 1) LAC =        /* skip if last */
  988.                 ((LAC << 1) | (MQ >> 17)) & 01777777;
  989.             MQ = ((MQ << 1) | t) & 0777777;  }
  990.         if (t) LAC = (LAC + MA) & 01777777;
  991.         if (eae_ac_sign) LAC = LAC ^ 0777777;    /* sgn rem = sgn divd */
  992.         if (eae_ac_sign ^ ~link_init) MQ = MQ ^ 0777777;
  993.         break;
  994.  
  995. /* EAE, continued
  996.  
  997.    EAE shifts, whether left or right, fill from the link.  If the
  998.    operand sign has been copied to the link, this provides correct
  999.    sign extension for one's complement numbers.
  1000. */
  1001.  
  1002.     case 4:                        /* normalize */
  1003. #if defined (PDP15)
  1004.         if (!usmd) ion_defer = 2;        /* free cycles */
  1005. #endif
  1006.         for (SC = IR & 077; ((LAC & 0400000) ==
  1007.             ((LAC << 1) & 0400000)) && (SC != 0); SC--) {
  1008.             LAC = (LAC << 1) | ((MQ >> 17) & 1);
  1009.             MQ = (MQ << 1) | (link_init >> 18);  }
  1010.         LAC = link_init | (LAC & 0777777);    /* trim AC, restore L */
  1011.         MQ = MQ & 0777777;            /* trim MQ */
  1012.         break;
  1013.     case 5:                        /* long right shift */
  1014.         t = IR & 077;                /* get shift count */
  1015.         if (t < 18) {
  1016.             MQ = ((LAC << (18 - t)) | (MQ >> t)) & 0777777;
  1017.             LAC = ((fill << (18 - t)) | (LAC >> t)) & 01777777;  }
  1018.         else {    if (t < 36) MQ =
  1019.               ((fill << (36 - t)) | (LAC >> (t - 18))) & 0777777;
  1020.             else MQ = fill;
  1021.             LAC = link_init | fill;  }
  1022.         SC = 0;                    /* clear step count */
  1023.         break;
  1024.     case 6:                        /* long left shift */
  1025.         t = IR & 077;                /* get shift count */
  1026.         if (t < 18) {
  1027.             LAC = link_init |
  1028.               (((LAC << t) | (MQ >> (18 - t))) & 0777777);
  1029.             MQ = ((MQ << t) | (fill >> (18 - t))) & 0777777;  }
  1030.         else {    if (t < 36) LAC = link_init | 
  1031.               (((MQ << (t - 18)) | (fill >> (36 - t))) & 0777777);
  1032.             else LAC = link_init | fill;
  1033.             MQ = fill;  }
  1034.         SC = 0;                    /* clear step count */
  1035.         break;
  1036.     case 7:                        /* AC left shift */
  1037.         t = IR & 077;                /* get shift count */
  1038.         if (t < 18) LAC = link_init |
  1039.             (((LAC << t) | (fill >> (18 - t))) & 0777777);
  1040.         else LAC = link_init | fill;
  1041.         SC = 0;                    /* clear step count */
  1042.         break;  }                /* end switch IR */
  1043.     break;                        /* end case EAE */
  1044.  
  1045. /* PDP-15 index operates: opcode 72 */
  1046.  
  1047. case 035:                        /* index operates */
  1048. #if defined (PDP15)
  1049.     t = (IR & 0400)? IR | 0777000: IR & 0377;    /* sext immediate */
  1050.     switch ((IR >> 9) & 017) {            /* case on IR<5:8> */
  1051.     case 001:                    /* PAX */
  1052.         XR = LAC & 0777777;
  1053.         break;
  1054.     case 002:                    /* PAL */
  1055.         LR = LAC & 0777777;
  1056.         break;
  1057.     case 003:
  1058.         LAC = (LAC & 01000000) | ((LAC + t) & 0777777); /* AAC */
  1059.         break;
  1060.     case 004:                    /* PXA */
  1061.         LAC = (LAC & 01000000) | XR;
  1062.         break;
  1063.     case 005:                    /* AXS */
  1064.         XR = (XR + t) & 0777777;
  1065.         if (SEXT (XR) >= SEXT (LR)) PC = INCR_ADDR (PC);
  1066.         break;
  1067.     case 006:                    /* PXL */
  1068.         LR = XR;
  1069.         break;
  1070.     case 010:                    /* PLA */
  1071.         LAC = (LAC & 01000000) | LR;
  1072.         break;
  1073.     case 011:                    /* PLX */
  1074.         XR = LR;
  1075.         break;
  1076.     case 015:                    /* CLX */
  1077.         XR = 0;
  1078.         break;
  1079.     case 016:                    /* CLL */
  1080.         LR = 0;
  1081.         break;
  1082.     case 017:                    /* AXR */
  1083.         XR = (XR + t) & 0777777;
  1084.         break;  }                /* end switch IR */
  1085.     break;                        /* end case */
  1086. #endif
  1087.  
  1088. /* IOT: opcode 70 
  1089.  
  1090.    The 18b PDP's have different definitions of various control IOT's.
  1091.  
  1092.    IOT        PDP-4        PDP-7        PDP-9        PDP-15
  1093.  
  1094.    700002    IOF        IOF        IOF        IOF
  1095.    700042    ION        ION        ION        ION
  1096.    700062    undefined    ITON        undefined    undefined
  1097.    701701    undefined    undefined    MPSK        MPSK
  1098.    701741    undefined    undefined    MPSNE        MPSNE
  1099.    701702    undefined    undefined    MPCV        MPCV
  1100.    701742    undefined    undefined    MPEU        MPEU
  1101.    701704    undefined    undefined    MPLD        MPLD
  1102.    701744    undefined    undefined    MPCNE        MPCNE
  1103.    703201    undefined    undefined    PFSF        PFSF
  1104.    703301    undefined    TTS        TTS        TTS
  1105.    703341    undefined    SKP7        SKP7        SPCO
  1106.    703302    undefined    CAF        CAF        CAF
  1107.    703344    undefined    undefined    DBR        DBR
  1108.    707701    undefined    SEM        SEM        undefined
  1109.    707741    undefined    undefined    undefined    SKP15
  1110.    707761    undefined    undefined    undefined    SBA
  1111.    707702    undefined    EEM        EEM        undefined
  1112.    707742    undefined    EMIR        EMIR        RES
  1113.    707762    undefined    undefined    undefined    DBA
  1114.    707704    undefined    LEM        LEM        undefined
  1115.    707764    undefined    undefined    undefined    EBA
  1116. */
  1117.  
  1118. case 034:                        /* IOT */
  1119. #if defined (PDP15)
  1120.     if (IR & 0010000) {                /* floating point? */
  1121. /*        PC = fp15 (PC, IR);            /* process */
  1122.         break;  }
  1123. #endif
  1124.     if (usmd) {                    /* user mode? */
  1125.         prvn = trap_pending = 1;        /* trap */
  1126.         break;  }
  1127.     device = (IR >> 6) & 077;            /* device = IR<6:11> */
  1128.     pulse = IR & 067;                /* pulse = IR<12:17> */
  1129.     if (IR & 0000010) LAC = LAC & 01000000;        /* clear AC? */
  1130.     iot_data = LAC & 0777777;            /* AC unchanged */
  1131.  
  1132. /* PDP-4 system IOT's */
  1133.  
  1134. #if defined (PDP4)
  1135.     switch (device) {                /* decode IR<6:11> */
  1136.     case 0:                        /* CPU and clock */
  1137.         if (pulse == 002) ion = 0;        /* IOF */
  1138.         else if (pulse == 042) ion = ion_defer = 1;    /* ION */
  1139.         else iot_data = clk (pulse, iot_data);
  1140.         break;
  1141.  
  1142. /* PDP-7 system IOT's */
  1143.  
  1144. #elif defined (PDP7)
  1145.     switch (device) {                /* decode IR<6:11> */
  1146.     case 0:                        /* CPU and clock */
  1147.         if (pulse == 002) ion = 0;        /* IOF */
  1148.         else if (pulse == 042) ion = ion_defer = 1;    /* ION */
  1149.         else if (pulse == 062)            /* ITON */
  1150.             usmd = ion = ion_defer = 1;
  1151.         else iot_data = clk (pulse, iot_data);
  1152.         break;
  1153.     case 033:                    /* CPU control */
  1154.         if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
  1155.         else if (pulse == 002) reset_all (0);    /* CAF */
  1156.         break;
  1157.     case 077:                    /* extended memory */
  1158.         if ((pulse == 001) && memm) PC = INCR_ADDR (PC);
  1159.         else if (pulse == 002) memm = 1;    /* EEM */
  1160.         else if (pulse == 042)            /* EMIR */
  1161.             memm = emir_pending = 1;    /* ext on, restore */
  1162.         else if (pulse == 004) memm = 0;    /* LEM */
  1163.         break;
  1164.  
  1165. /* PDP-9 system IOT's */
  1166.  
  1167. #elif defined (PDP9)
  1168.     ion_defer = 1;                    /* delay interrupts */
  1169.     switch (device) {                /* decode IR<6:11> */
  1170.     case 000:                    /* CPU and clock */
  1171.         if (pulse == 002) ion = 0;        /* IOF */
  1172.         else if (pulse == 042) ion = 1;        /* ION */
  1173.         else iot_data = clk (pulse, iot_data);
  1174.         break;
  1175.     case 017:                    /* mem protection */
  1176.         if ((pulse == 001) && prvn) PC = INCR_ADDR (PC);
  1177.         else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC);
  1178.         else if (pulse == 002) prvn = 0;
  1179.         else if (pulse == 042) usmdbuf = 1;
  1180.         else if (pulse == 004) BR = LAC & 076000;
  1181.         else if (pulse == 044) nexm = 0;
  1182.         break;
  1183.     case 032:                    /* power fail */
  1184.         if ((pulse == 001) && (int_req & INT_PWRFL))
  1185.              PC = INCR_ADDR (PC);
  1186.         break;
  1187.     case 033:                    /* CPU control */
  1188.         if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
  1189.         else if (pulse == 002) reset_all (0);    /* CAF */
  1190.         else if (pulse == 044) rest_pending = 1;    /* DBR */
  1191.         break;
  1192.     case 077:                    /* extended memory */
  1193.         if ((pulse == 001) && memm) PC = INCR_ADDR (PC);
  1194.         else if (pulse == 002) memm = 1;    /* EEM */
  1195.         else if (pulse == 042)            /* EMIR */
  1196.             memm = emir_pending = 1;    /* ext on, restore */
  1197.         else if (pulse == 004) memm = 0;    /* LEM */
  1198.         break;
  1199.  
  1200. /* PDP-15 system IOT's */
  1201.  
  1202. #elif defined (PDP15)
  1203.     ion_defer = 1;                    /* delay interrupts */
  1204.     switch (device) {                /* decode IR<6:11> */
  1205.     case 000:                    /* CPU and clock */
  1206.         if (pulse == 002) ion = 0;        /* IOF */
  1207.         else if (pulse == 042) ion = 1;        /* ION */
  1208.         else iot_data = clk (pulse, iot_data);
  1209.         break;
  1210.     case 017:                    /* mem protection */
  1211.         if ((pulse == 001) && prvn) PC = INCR_ADDR (PC);
  1212.         else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC);
  1213.         else if (pulse == 002) prvn = 0;
  1214.         else if (pulse == 042) usmdbuf = 1;
  1215.         else if (pulse == 004) BR = LAC & 0377400;
  1216.         else if (pulse == 044) nexm = 0;
  1217.         break;
  1218.     case 032:                    /* power fail */
  1219.         if ((pulse == 001) && (int_req & INT_PWRFL))
  1220.             PC = INCR_ADDR (PC);
  1221.         break;
  1222.     case 033:                    /* CPU control */
  1223.         if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
  1224.         else if (pulse == 002) reset_all (0);    /* CAF */
  1225.         else if (pulse == 044) rest_pending = 1;    /* DBR */
  1226.         break;
  1227.     case 077:                    /* bank addressing */
  1228.         if ((pulse == 041) || ((pulse == 061) && memm))
  1229.              PC = INCR_ADDR (PC);        /* SKP15, SBA */
  1230.         else if (pulse == 042) rest_pending = 1;    /* RES */
  1231.         else if (pulse == 062) memm = 0;    /* DBA */
  1232.         else if (pulse == 064) memm = 1;    /* EBA */
  1233.         break;
  1234. #endif
  1235.  
  1236. /* IOT, continued */
  1237.  
  1238.     case 1:                        /* PTR */
  1239.         iot_data = ptr (pulse, iot_data);
  1240.         break;
  1241.     case 2:                        /* PTP */
  1242.         iot_data = ptp (pulse, iot_data);
  1243.         break;
  1244.     case 3:                        /* TTI */
  1245.         if (pulse == 004) iot_data = upd_iors ();
  1246.         else iot_data = tti (pulse, iot_data);
  1247.         break;
  1248.     case 4:                     /* TTO */
  1249.         iot_data = tto (pulse, iot_data);
  1250.         break;
  1251. #if defined (DRM)
  1252.     case 060:                    /* drum */
  1253.         iot_data = drm60 (pulse, iot_data);
  1254.         break;
  1255.     case 061:
  1256.         iot_data = drm61 (pulse, iot_data);
  1257.         break;
  1258.     case 062:
  1259.         iot_data = drm62 (pulse, iot_data);
  1260.         break;
  1261. #endif
  1262. #if defined (RP)
  1263.     case 063:                    /* RP15 */
  1264.         iot_data = rp63 (pulse, iot_data);
  1265.         break;
  1266.     case 064:
  1267.         iot_data = rp64 (pulse, iot_data);
  1268.         break;
  1269. #endif
  1270.     case 065:                    /* LPT */
  1271.         iot_data = lpt65 (pulse, iot_data);
  1272.         break;
  1273.     case 066:
  1274.         iot_data = lpt66 (pulse, iot_data);
  1275.         break;
  1276. #if defined (RF)
  1277.     case 070:                    /* RF09 */
  1278.         iot_data = rf70 (pulse, iot_data);
  1279.         break;
  1280.     case 072:
  1281.         iot_data = rf72 (pulse, iot_data);
  1282.         break;
  1283. #endif
  1284. #if defined (MTA)
  1285.     case 073:                    /* TC59 */
  1286.         iot_data = mt (pulse, iot_data);
  1287.         break;
  1288. #endif
  1289.     default:                    /* unknown device */
  1290.         reason = stop_inst;            /* stop on flag */
  1291.         break;  }                /* end switch device */
  1292.     LAC = LAC | (iot_data & 0777777);
  1293.     if (iot_data & IOT_SKP) PC = INCR_ADDR (PC);
  1294.     if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON;
  1295.     break;                        /* end case IOT */
  1296.     }                        /* end switch opcode */
  1297. }                            /* end while */
  1298.  
  1299. /* Simulation halted */
  1300.  
  1301. saved_PC = PC & ADDRMASK;                /* save copies */
  1302. saved_LAC = LAC & 01777777;
  1303. saved_MQ = MQ & 0777777;
  1304. iors = upd_iors ();                    /* get IORS */
  1305. return reason;
  1306. }
  1307.  
  1308. /* Reset routine */
  1309.  
  1310. int cpu_reset (DEVICE *dptr)
  1311. {
  1312. SC = 0;
  1313. eae_ac_sign = 0;
  1314. ion = ion_defer = 0;
  1315. int_req = int_req & ~INT_PWRFL;
  1316. BR = 0;
  1317. memm = usmd = usmdbuf = 0;
  1318. nexm = prvn = trap_pending = 0;
  1319. emir_pending = rest_pending = 0;
  1320. return cpu_svc (&cpu_unit);
  1321. }
  1322.  
  1323. /* Process IORS instruction */
  1324.  
  1325. int upd_iors (void)
  1326. {
  1327. extern int std_iors (void);
  1328. extern int lpt_iors (void);
  1329. #if defined (DRM)
  1330. extern int drm_iors (void);
  1331. #endif
  1332. #if defined (RF)
  1333. extern int rf_iors (void);
  1334. #endif
  1335. #if defined (RP)
  1336. extern int rp_iors (void);
  1337. #endif
  1338. #if defined (MTA)
  1339. extern int mt_iors (void);
  1340. #endif
  1341.  
  1342. return    (ion? IOS_ION: 0) |
  1343. #if defined (DRM)
  1344.     drm_iors () |
  1345. #endif
  1346. #if defined (RP)
  1347.     rp_iors () |
  1348. #endif
  1349. #if defined (RF)
  1350.     rf_iors () |
  1351. #endif
  1352. #if defined (MTA)
  1353.     mt_iors () |
  1354. #endif
  1355.     std_iors () | lpt_iors ();
  1356. }
  1357.  
  1358. /* Memory examine */
  1359.  
  1360. int cpu_ex (int *vptr, int addr, UNIT *uptr, int sw)
  1361. {
  1362. if (addr >= MEMSIZE) return SCPE_NXM;
  1363. if (vptr != NULL) *vptr = M[addr] & 0777777;
  1364. return SCPE_OK;
  1365. }
  1366.  
  1367. /* Memory deposit */
  1368.  
  1369. int cpu_dep (int val, int addr, UNIT *uptr, int sw)
  1370. {
  1371. if (addr >= MEMSIZE) return SCPE_NXM;
  1372. M[addr] = val & 0777777;
  1373. return SCPE_OK;
  1374. }
  1375.  
  1376. /* Service breakpoint */
  1377.  
  1378. int cpu_svc (UNIT *uptr)
  1379. {
  1380. if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
  1381. save_ibkpt = -1;
  1382. return SCPE_OK;
  1383. }
  1384.  
  1385. /* Change memory size */
  1386.  
  1387. int cpu_set_size (UNIT *uptr, int value)
  1388. {
  1389. int i, mc = 0;
  1390. extern int get_yn (char *ques, int deflt);
  1391.  
  1392. if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
  1393.     return SCPE_ARG;
  1394. for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
  1395. if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
  1396.     return SCPE_OK;
  1397. MEMSIZE = value;
  1398. for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
  1399. return SCPE_OK;
  1400. }
  1401.