home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Boot_Images / 2.11_on_rl02 / pdpsim.tz / pdpsim / pdp9_cpu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-02  |  25.7 KB  |  900 lines

  1. /*
  2.  * pdp9_cpu.c    pdp-9 CPU simulator
  3.  *
  4.  *                          Copyright 1995 by
  5.  *              Megan Gentry, Digital Equipment Corporation
  6.  *                         All rights reserved
  7.  *                      Commercial use prohibited
  8.  *
  9.  * The following code is based liberally upon pdp-8 emulator code
  10.  * developed by Robert Supnik of Digital Equipment Corporation.
  11.  *
  12.  * The register state for the PDP-9 is:
  13.  *
  14.  *    AC<0:17>    accumulater
  15.  *    L        link
  16.  *    MB<0:17>    memory buffer
  17.  *    MQ<0:17>    multiplier quotient
  18.  *    EM        extended memory mode
  19.  *    MP        memory protect mode
  20.  *    PC<0:17>    program counter
  21.  *    IR<0:17>    instruction register
  22.  *
  23.  * The PDP-9 has four instruction formats:
  24.  *    o memory reference
  25.  *    o EAE
  26.  *    o I/O transfer
  27.  *    o operate.
  28.  *
  29.  * The memory reference format is:
  30.  *
  31.  *     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  32.  *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  33.  *   |     op    |in|               address                |
  34.  *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  35.  *
  36.  *   <0:3>    mnemonic    action
  37.  *    000    CAL        M[20]<0> = L
  38.  *                M[20]<1> = EM
  39.  *                M[20]<2> = MP
  40.  *                M[20]<03:17> = PC
  41.  *                PC = 21
  42.  *    004    DAC        M[MA] = AC
  43.  *    010    JMS        M[MA]<0> = L
  44.  *                M[MA]<1> = EM
  45.  *                M[MA]<2> = MP
  46.  *                M[MA]<03:17> = PC
  47.  *                PC = MA + 1
  48.  *    014    DZM        M[MA] = 0
  49.  *    020    LAC        AC = M[MA]
  50.  *    024    XOR        AC = AC XOR M[MA]
  51.  *    030    ADD        L'AC = AC + M[MA], ones complement
  52.  *    034    TAD        L'AC = AC + M[MA], twos complement
  53.  *    040    XCT        IR = M[MA]
  54.  *    044    ISZ        M[MA] = M[MA] + 1, skip if M[MA] == 0
  55.  *    050    AND        AC = AC & M[MA]
  56.  *    054    SAD        if M[MA] != AC, PC = PC + 1
  57.  *    060    JMP        PC = MA
  58.  *
  59.  *   
  60.  *   <4>    mode        action
  61.  *    0        direct        MA = M[IR<5:17>]
  62.  *    1        indirect    MA = M[M[IR<5:17>]]
  63.  *
  64.  * Memory reference instructions can access an address space of 8k
  65.  * 18-bit words.
  66.  */
  67.  
  68.  
  69. /*
  70.  * The I/O transfer format is:
  71.  *
  72.  *     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  73.  *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  74.  *   | 1  1  1  0| res |  device select  | sub |           |
  75.  *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  76.  *                                               ^  ^  ^  ^
  77.  *                                               |  |  |  + IOP1 at time 1
  78.  *                                               |  |  +--- IOP2 at time 2
  79.  *                                               |  +------ IOP4 at time 3
  80.  *                                               +--------- Clear AC at time 1
  81.  *
  82.  * The IO Transfer instruction sends the specified pulse to the
  83.  * selected I/O device (and subdevice).  The I/O device make take
  84.  * data from the AC, return data to the AC, initiate or cancel
  85.  * operations, or skip on status.  The AC can optionally be cleared
  86.  * before any pulses are generated.
  87.  */
  88.  
  89.  
  90. /*
  91.  * The operate format is as follows:
  92.  *
  93.  *     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17
  94.  *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  95.  *   | 1| 1| 1| 1| x|  |  |  |  |  |  |  |  |  |  |  |  |  |
  96.  *   +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  97.  *                    ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^
  98.  *       OPR | NOP ---+  |  |  |  |  |  |  |  |  |  |  |  +--- CMA
  99.  *       CLA ------------+  |  |  |  |  |  |  |  |  |  +------ CML
  100.  *       CLL ---------------+  |  |  |  |  |  |  |  +--------- OAS
  101.  *   RAx/RTx ------------------+  |  |  |  |  |  +------------ RAL/RTL
  102.  *       OR / AND ----------------+  |  |  |  +--------------- RAR/RTR
  103.  *       (see <10:12>)     <9> 0 = SNL!SZA!SMA
  104.  *                         <9> 1 = SZL&SNA&SPA
  105.  */
  106.  
  107.  
  108. /*
  109.  * This routine is the instruction decode routine for the PDP-9.
  110.  * It is called from the simulator control program to execute
  111.  * instructions in simulated memory, starting at the simulated PC.
  112.  * It runs until 'reason' is set non-zero.
  113.  *
  114.  * General notes:
  115.  *
  116.  *   1. Reasons to stop.  The simulator can be stopped by:
  117.  *
  118.  *    HALT instruction
  119.  *    breakpoint encountered
  120.  *    unimplemented instruction and stop_inst flag set
  121.  *    I/O error in I/O simulator
  122.  *
  123.  *   2. Interrupts.  Interrupts are maintained by three parallel variables:
  124.  *
  125.  *    dev_done     device done flags
  126.  *    dev_enable    device interrupt enable flags
  127.  *    int_req        interrupt requests
  128.  *
  129.  *      In addition, int_req contains the interrupt enable flag, the
  130.  *      CIF not pending flag, and the ION not pending flag.  If all
  131.  *      three of these flags are set, and at least one interrupt request
  132.  *      is set, then an interrupt occurs.
  133.  *
  134.  *   3. Non-existent memory.  On the PDP-8, reads to non-existent memory
  135.  *      return zero, and writes are ignored.  In the simulator, the
  136.  *      largest possible memory is instantiated and initialized to zero.
  137.  *      Thus, only writes outside the current field (indirect writes) need
  138.  *      be checked against actual memory size.
  139.  *
  140.  *   3. Adding I/O devices.  Three modules must be modified:
  141.  *
  142.  *    pdp9_defs.h    add interrupt request definition
  143.  *    pdp9_cpu.c    add IOT dispatch
  144.  *    pdp9_sys.c    add pointer to data structures to sim_devices
  145.  */
  146.  
  147.  
  148. #include "pdp9_defs.h"
  149.  
  150. #define ILL_ADR_FLAG 0100000                /* invalid addr flag */
  151. #define save_ibkpt (cpu_unit.u3)            /* saved bkpt addr */
  152. #define UNIT_V_NOEAE    (UNIT_V_UF)            /* EAE absent */
  153. #define UNIT_NOEAE    (1 << UNIT_V_NOEAE)
  154.  
  155. unsigned long M[MAXMEMSIZE] = { 0 };            /* main memory */
  156.  
  157. long saved_LINKAC = 0;                    /* saved LINKAC */
  158. long saved_MQ = 0;                    /* saved MQ */
  159. long saved_PC = 0;                    /* saved IF'PC */
  160. long saved_DF = 0;                    /* saved Data Field */
  161. long IB = 0;                        /* Instruction Buffer */
  162. long SF = 0;                        /* Save Field */
  163. long emode = 0;                        /* EAE mode */
  164. long gtf = 0;                        /* EAE gtf flag */
  165. long SC = 0;                        /* EAE shift count */
  166. long UB = 0;                        /* User mode Buffer */
  167. long UF = 0;                        /* User mode Flag */
  168. long OSR = 0;                        /* Switch Register */
  169. long old_PC = 0;                    /* old PC */
  170. long dev_enable = INT_INIT_ENABLE;            /* dev intr enables */
  171. long dev_done = 0;                    /* dev done flags */
  172. long int_req = 0;                    /* intr requests */
  173. long ibkpt_addr = ILL_ADR_FLAG;                /* breakpoint addr */
  174. long stop_inst = 0;                    /* trap on ill inst */
  175.  
  176. extern int sim_int_char;
  177.  
  178. int cpu_ex (int *vptr, int addr, UNIT *uptr, int sw);
  179. int cpu_dep (int val, int addr, UNIT *uptr, int sw);
  180. int cpu_reset (DEVICE *dptr);
  181. int cpu_svc (UNIT *uptr);
  182.  
  183.  
  184. /*
  185.  * CPU data structures
  186.  *
  187.  *    cpu_dev        CPU device descriptor
  188.  *    cpu_unit    CPU unit descriptor
  189.  *    cpu_reg        CPU register list
  190.  *    cpu_mod        CPU modifier list
  191.  */
  192.  
  193. UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX, MEMSIZE) };
  194.  
  195. REG cpu_reg[] = {
  196.     { ORDATA (PC, saved_PC, 15) },
  197.     { ORDATA (AC, saved_LINKAC, 12) },
  198.     { FLDATA (L, saved_LINKAC, 12) },
  199.     { ORDATA (MQ, saved_MQ, 12) },
  200.     { ORDATA (SR, OSR, 12) },
  201.     { GRDATA (IF, saved_PC, 8, 3, 12) },
  202.     { GRDATA (DF, saved_DF, 8, 3, 12) },
  203.     { GRDATA (IB, IB, 8, 3, 12) },
  204.     { ORDATA (SF, SF, 7) },
  205.     { FLDATA (UB, UB, 0) },
  206.     { FLDATA (UF, UF, 0) },
  207.     { ORDATA (SC, SC, 5) },
  208.     { FLDATA (GTF, gtf, 0) },
  209.     { FLDATA (EMODE, emode, 0) },
  210.     { FLDATA (ION, int_req, INT_V_ION) },
  211.     { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) },
  212.     { FLDATA (CIF_DELAY, int_req, INT_V_NO_CIF_PENDING) },
  213.     { FLDATA (PWR_INT, int_req, INT_V_PWR) },
  214.     { FLDATA (UF_INT, int_req, INT_V_UF) },
  215.     { ORDATA (INT, int_req, INT_V_ION+1), REG_RO },
  216.     { ORDATA (DONE, dev_done, INT_V_DIRECT), REG_RO },
  217.     { ORDATA (ENABLE, dev_enable, INT_V_DIRECT), REG_RO },
  218.     { FLDATA (NOEAE, cpu_unit.flags, UNIT_V_NOEAE), REG_HRO },
  219.     { ORDATA (OLDPC, old_PC, 15), REG_RO },
  220.     { FLDATA (STOP_INST, stop_inst, 0) },
  221.     { ORDATA (BREAK, ibkpt_addr, 16) },
  222.     { ORDATA (WRU, sim_int_char, 8) },
  223.     { NULL }  };
  224.  
  225. MTAB cpu_mod[] = {
  226.     { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL },
  227.     { UNIT_NOEAE, 0, "EAE", "EAE", NULL },
  228.     { 0 }  };
  229.  
  230. DEVICE cpu_dev = {
  231.     "CPU", &cpu_unit, cpu_reg, cpu_mod,
  232.     1, 8, 15, 1, 8, 12,
  233.     &cpu_ex, &cpu_dep, &cpu_reset,
  234.     NULL, NULL, NULL };
  235.  
  236.  
  237. int
  238. sim_instr (void)
  239. {
  240.     long PC, IR, MA, MB, MQ, LINK, LINKAC;
  241.  
  242.     extern int sim_interval;
  243.  
  244.     int device, pulse, temp, iot_data, reason;
  245.  
  246.     extern int tti (int pulse, int AC);
  247.     extern int tto (int pulse, int AC);
  248.     extern int ptr (int pulse, int AC);
  249.     extern int ptp (int pulse, int AC);
  250.     extern int clk (int pulse, int AC);
  251.     extern int lpt (int pulse, int AC);
  252.     extern int rk (int pulse, int AC);
  253.     extern int rx (int pulse, int AC);
  254.     extern int rf60 (int pulse, int AC);
  255.     extern int rf61 (int pulse, int AC);
  256.     extern int rf62 (int pulse, int AC);
  257.     extern int rf64 (int pulse, int AC);
  258.     extern int sim_process_event (void);
  259.     extern int sim_activate (UNIT *uptr, int interval);
  260.  
  261. /* Restore register state */
  262.  
  263.     PC = saved_PC & 0777777;        /* load local copies */
  264.     LINKAC = saved_LINKAC & 0777777;
  265.     MQ = saved_MQ & 0777777;
  266.     int_req = INT_UPDATE;
  267.  
  268.     reason = 0;
  269.  
  270. /* Main instruction fetch/decode loop */
  271.  
  272.     while (reason == 0) {                /* loop until halted */
  273.     if (sim_interval <= 0)                /* check clock queue */
  274.         if (reason = sim_process_event ())
  275.         break;
  276.  
  277.     if (int_req > INT_PENDING) { /* interrupt? */
  278.         int_req = int_req & ~INT_ION;        /* interrupts off */
  279.         SF = (UF << 6) | (IF >> 9) | (DF >> 12);    /* form save field */
  280.         IF = IB = DF = UF = UB = 0;            /* clear mem ext */
  281.         old_PC = M[0] = PC;                /* save PC in 0 */
  282.         PC = 1;
  283.     } /* fetch next from 1 */
  284.  
  285.     MA = PC;                    /* form PC */
  286.  
  287.     if (MA == ibkpt_addr) {                /* breakpoint? */
  288.         save_ibkpt = ibkpt_addr;            /* save ibkpt */
  289.         ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG;    /* disable */
  290.         sim_activate (&cpu_unit, 1);        /* sched re-enable */
  291.         reason = STOP_IBKPT;            /* stop simulation */
  292.         break;
  293.     }
  294.  
  295.     IR = M[MA];                    /* fetch instruction */
  296.  
  297.     PC = (PC + 1) & 0777777;            /* increment PC */
  298.  
  299.     int_req = int_req | INT_NO_ION_PENDING;        /* clear ION delay */
  300.  
  301.     sim_interval = sim_interval - 1;
  302.  
  303.  
  304. /*
  305.  * Instruction decoding.
  306.  *
  307.  * The opcode (IR<0:3>) and indirect flag (IR<4>) are decoded together.
  308.  * This produces 32 decode points, 2 per major opcode.  For IOT, the
  309.  * extra decode points are not useful.
  310.  */
  311.  
  312. #define INDIRECT (0020000)
  313. #define DEFERP    if (IR && INDIRECT) \
  314.             MA = M[IR & 017777]; \
  315.         else \
  316.             MA = IR & 017777;
  317.  
  318.     /* decode IR<00:03> */
  319.     switch ((IR >> 14) & 017) {
  320.  
  321.  
  322. /*
  323.  * Opcode 000, CAL (call subroutine)
  324.  *    Note: bits <04:17> are not used in this instruction
  325.  */
  326.  
  327.     case opCAL:
  328.     case opCAL | INDIRECT:
  329.         M[20] = ((L & 01) << 17) | ((EM & 01) << 16) |
  330.             ((MP & 01) << 15) | (MA & 017777);
  331.         PC = 21;
  332.         break;
  333.  
  334. /* Opcode 004, DAC, deposit AC to memory */
  335.  
  336.     case opDAC:
  337.         DEFERP;
  338.         M[MA] = AC;
  339.         break;
  340.  
  341. /* Opcode 010, JMS, jump to subroutine */
  342.  
  343.     case opJMS:
  344.         DEFERP;
  345.         M[MA] = ((L & 01) << 17) | ((EM & 01) << 16) |
  346.             ((MP & 01) << 15) | (PC & 017777);
  347.         PC = MA + 1;
  348.         break;
  349.  
  350. /* Opcode 014, DZM, deposit zero to memory */
  351.  
  352.     case opDZM:
  353.         DEFERP;
  354.         M[MA] = 0;
  355.         break;
  356.  
  357. /* Opcode 020, LAC, load AC */
  358.  
  359.     case opLAC:
  360.         DEFERP;
  361.         AC = M[MA] & 0777777;
  362.         break;
  363.  
  364. /* Opcode 024, XOR, exclusive or memory with AC */
  365.  
  366.     case opXOR:
  367.         DEFERP;
  368.         AC = AC ^ M[MA];
  369.         break;
  370.  
  371. /* Opcode 030, ADD, add memory to AC */
  372.  
  373.     case opADD:
  374.         DEFERP;
  375.         AC += M[MA];
  376.         break;
  377.  
  378. case 034:case 035:                    /* OPR, group 1 */
  379.     switch ((IR >> 4) & 017) {            /* decode IR<4:7> */
  380.     case 0:                        /* nop */
  381.         break;
  382.     case 1:                        /* CML */
  383.         LAC = LAC ^ 010000; break;
  384.     case 2:                        /* CMA */
  385.         LAC = LAC ^ 07777; break;
  386.     case 3:                        /* CMA CML */
  387.         LAC = LAC ^ 017777; break;
  388.     case 4:                        /* CLL */
  389.         LAC = LAC & 07777; break;
  390.     case 5:                        /* CLL CML = STL */
  391.         LAC = LAC | 010000; break;
  392.     case 6:                        /* CLL CMA */
  393.         LAC = (LAC ^ 07777) & 07777; break;
  394.     case 7:                        /* CLL CMA CML */
  395.         LAC = (LAC ^ 07777) | 010000; break;
  396.     case 010:                    /* CLA */
  397.         LAC = LAC & 010000; break;
  398.     case 011:                    /* CLA CML */
  399.         LAC = (LAC & 010000) ^ 010000; break;
  400.     case 012:                    /* CLA CMA = STA */
  401.         LAC = LAC | 07777; break;
  402.     case 013:                    /* CLA CMA CML */
  403.         LAC = (LAC | 07777) ^ 010000; break;
  404.     case 014:                    /* CLA CLL */
  405.         LAC = 0; break;
  406.     case 015:                    /* CLA CLL CML */
  407.         LAC = 010000; break;
  408.     case 016:                    /* CLA CLL CMA */
  409.         LAC = 07777; break;
  410.     case 017:                    /* CLA CLL CMA CML */
  411.         LAC = 017777; break;  }            /* end switch opers */
  412.     if (IR & 01) LAC = (LAC + 1) & 017777;        /* IAC */
  413.     switch ((IR >> 1) & 07) {            /* decode IR<8:10> */
  414.     case 0:                     /* nop */
  415.         break;
  416.     case 1:                        /* BSW */
  417.         LAC = (LAC & 010000) | ((LAC >> 6) & 077)
  418.             | ((LAC & 077) << 6); break;
  419.     case 2:                        /* RAL */
  420.         LAC = ((LAC << 1) | (LAC >> 12)) & 017777; break;
  421.     case 3:                        /* RTL */
  422.         LAC = ((LAC << 2) | (LAC >> 11)) & 017777; break;
  423.     case 4:                        /* RAR */
  424.         LAC = ((LAC >> 1) | (LAC << 12)) & 017777; break;
  425.     case 5:                        /* RTR */
  426.         LAC = ((LAC >> 2) | (LAC << 11)) & 017777; break;
  427.     case 6:                        /* RAL RAR - undef */
  428.         LAC = LAC & (IR | 010000); break;    /* uses AND path */
  429.     case 7:                        /* RTL RTR - undef */
  430.         LAC = (LAC & 010000) | (MA & 07600) | (IR & 0177);
  431.         break;  }                /* uses address path */
  432.     break;                        /* end group 1 */
  433.  
  434. /* OPR group 2 */
  435.  
  436. case 036:case 037:                    /* OPR, groups 2, 3 */
  437.     if ((IR & 01) == 0) {                /* group 2 */
  438.         switch ((IR >> 3) & 017) {        /* decode IR<6:8> */
  439.         case 0:                 /* nop */
  440.             break;
  441.         case 1:                    /* SKP */
  442.             PC = (PC + 1) & 07777; break;
  443.         case 2:                 /* SNL */
  444.             if (LAC >= 010000) PC = (PC + 1) & 07777; break;
  445.         case 3:                 /* SZL */
  446.             if (LAC < 010000) PC = (PC + 1) & 07777; break;
  447.         case 4:                 /* SZA */
  448.             if ((LAC & 07777) == 0) PC = (PC + 1) & 07777; break;
  449.         case 5:                 /* SNA */
  450.             if ((LAC & 07777) != 0) PC = (PC + 1) & 07777; break;
  451.         case 6:                    /* SZA | SNL */
  452.             if ((LAC == 0) || (LAC >= 010000))
  453.                 PC = (PC + 1) & 07777; break;
  454.         case 7:                    /* SNA & SZL */
  455.             if ((LAC != 0) && (LAC < 010000))
  456.                 PC = (PC + 1) & 07777; break;
  457.         case 010:                 /* SMA */
  458.             if ((LAC & 04000) != 0) PC = (PC + 1) & 07777; break;
  459.         case 011:                 /* SPA */
  460.             if ((LAC & 04000) == 0) PC = (PC + 1) & 07777; break;
  461.         case 012:                /* SMA | SNL */
  462.             if (LAC >= 04000) PC = (PC + 1) & 07777; break;
  463.         case 013:                /* SPA & SZL */
  464.             if (LAC < 04000) PC = (PC + 1) & 07777; break;
  465.         case 014:                /* SMA | SZA */
  466.             if (((LAC & 04000) != 0) || ((LAC & 07777) == 0))
  467.                 PC = (PC + 1) & 07777; break;
  468.         case 015:                /* SPA & SNA */
  469.             if (((LAC & 04000) == 0) && ((LAC & 07777) != 0))
  470.                 PC = (PC + 1) & 07777; break;
  471.         case 016:                /* SMA | SZA | SNL */
  472.             if ((LAC >= 04000) || (LAC == 0))
  473.                 PC = (PC + 1) & 07777; break;
  474.         case 017:                /* SPA & SNA & SZL */
  475.             if ((LAC < 04000) && (LAC != 0))
  476.                 PC = (PC + 1) & 07777; break;
  477.             }                /* end switch skips */
  478.         if (IR & 0200) LAC = LAC & 010000;    /* CLA */
  479.         if ((IR & 06) && UF) {            /* privileged? */
  480.             int_req = int_req | INT_UF; break;  }
  481.         if (IR & 04) LAC = LAC | OSR;        /* OSR */
  482.         if (IR & 02) reason = STOP_HALT;    /* HLT */
  483.         break;  }                              /* end group 2 */
  484.  
  485. /* OPR group 3 standard
  486.  
  487.    MQA!MQL exchanges AC and MQ, as follows:
  488.  
  489.     temp = MQ;
  490.     MQ = LAC & 07777;
  491.     LAC = LAC & 010000 | temp;
  492. */
  493.  
  494.     temp = MQ;                    /* group 3 */
  495.     if (IR & 0200) LAC = LAC & 010000;        /* CLA */
  496.     if (IR & 0020) {                /* MQL */
  497.         MQ = LAC & 07777;
  498.         LAC = LAC & 010000;  }
  499.     if (IR & 0100) LAC = LAC | temp;        /* MQA */
  500.     if ((IR & 0056) && (cpu_unit.flags & UNIT_NOEAE)) {
  501.         reason = stop_inst;            /* EAE not present */
  502.         break;  }
  503.  
  504. /* OPR group 3 EAE
  505.  
  506.    The EAE operates in two modes:
  507.  
  508.     Mode A, PDP-8/I compatible
  509.     Mode B, extended capability
  510.  
  511.    Mode B provides eight additional subfunctions; in addition, some
  512.    of the Mode A functions operate differently in Mode B.
  513.  
  514.    The mode switch instructions are decoded explicitly and cannot be
  515.    microprogrammed with other EAE functions (SWAB performs an MQL as
  516.    part of standard group 3 decoding).  If mode switching is decoded,
  517.    all other EAE timing is suppressed.
  518. */
  519.  
  520.     if (IR == 07431) {                /* SWAB */
  521.         emode = 1;                /* set mode flag */
  522.         break;  }
  523.     if (IR == 07447) {                /* SWBA */
  524.         emode = gtf = 0;            /* clear mode, gtf */
  525.         break;  }
  526.  
  527. /* If not switching modes, the EAE operation is determined by the mode
  528.    and IR<6,8:10>:
  529.  
  530.    <6:10>    mode A        mode B        comments
  531.  
  532.    0x000    NOP        NOP
  533.    0x001    SCL        ACS
  534.    0x010    MUY        MUY        if mode B, next = address
  535.    0x011    DVI        DVI        if mode B, next = address
  536.    0x100    NMI        NMI        if mode B, clear AC if
  537.                          result = 4000'0000
  538.    0x101    SHL        SHL        if mode A, extra shift
  539.    0x110    ASR        ASR        if mode A, extra shift
  540.    0x111    LSR        LSR        if mode A, extra shift
  541.    1x000    SCA        SCA
  542.    1x001    SCA + SCL    DAD
  543.    1x010    SCA + MUY    DST
  544.    1x011    SCA + DVI    SWBA            NOP if not detected earlier
  545.    1x100    SCA + NMI    DPSZ        
  546.    1x101    SCA + SHL    DPIC            must be combined with MQA!MQL
  547.    1x110    SCA + ASR    DCM        must be combined with MQA!MQL
  548.    1x111    SCA + LSR    SAM
  549.  
  550.    EAE instructions which fetch memory operands use the CPU's DEFER
  551.    state to read the first word; if the address operand is in locations
  552.    x0010 - x0017, it is autoincremented.
  553. */
  554.  
  555. /* EAE continued */
  556.  
  557.     switch ((IR >> 1) & 027) {            /* decode IR<6,8:10> */
  558.     case 020:                    /* mode A, B: SCA */
  559.         LAC = LAC | SC;
  560.         break;
  561.     case 0:                        /* mode A, B: NOP */
  562.         break;
  563.     case 021:                    /* mode B: DAD */
  564.         if (emode) {
  565.             MA = IF | PC; INDIRECT;        /* defer state */
  566.             MQ = MQ + M[MA];
  567.             MA = DF | ((MA + 1) & 07777);
  568.             LAC = (LAC & 07777) + M[MA] + (MQ >> 12);
  569.             MQ = MQ & 07777;
  570.             PC = (PC + 1) & 07777;
  571.             break;  }
  572.         LAC = LAC | SC;                /* mode A: SCA then */
  573.     case 1:                        /* mode B: ACS */
  574.         if (emode) {
  575.             SC = LAC & 037;
  576.             LAC = LAC & 010000;
  577.             break;  }
  578.         SC = (~M[IF | PC]) & 037;        /* mode A: SCL */
  579.         PC = (PC + 1) & 07777;
  580.         break;
  581.     case 022:                    /* mode B: DST */
  582.         if (emode) {
  583.             MA = IF | PC; INDIRECT;        /* defer state */
  584.             if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777;
  585.             MA = DF | ((MA + 1) & 07777);
  586.             if (MEM_ADDR_OK (MA))  M[MA] = LAC & 07777;
  587.             PC = (PC + 1) & 07777;
  588.             break;  }
  589.         LAC = LAC | SC;                /* mode A: SCA then */
  590.     case 2:                        /* MUY */
  591.         MA = IF | PC;
  592.         if (emode) { INDIRECT; }        /* mode B: defer */
  593.         temp = (MQ * M[MA]) + (LAC & 07777);
  594.         LAC = (temp >> 12) & 07777;
  595.         MQ = temp & 07777;
  596.         PC = (PC + 1) & 07777;
  597.         SC = 014;                /* 12 shifts */
  598.         break;
  599.  
  600. /* EAE continued */
  601.  
  602.     case 023:                    /* mode B: SWBA */
  603.         if (emode) break;
  604.         LAC = LAC | SC;                /* mode A: SCA then */
  605.     case 3:                        /* DVI */
  606.         MA = IF | PC;
  607.         if (emode) { INDIRECT; };        /* mode B: defer */
  608.         if ((LAC & 07777) >= M[MA]) {        /* overflow? */
  609.             LAC = LAC | 010000;        /* set link */
  610.             MQ = ((MQ << 1) + 1) & 07777;    /* rotate MQ */
  611.             SC = 01;  }            /* 1 shift */
  612.         else {    temp = ((LAC & 07777) << 12) | MQ;
  613.             MQ = temp / M[MA];
  614.             LAC = temp % M[MA];
  615.             SC = 015;  }            /* 13 shifts */
  616.         PC = (PC + 1) & 07777;
  617.         break;
  618.     case 024:                    /* mode B: DPSZ */
  619.         if (emode) {
  620.             if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777;
  621.             break;  }
  622.         LAC = LAC | SC;                /* mode A: SCA then */
  623.     case 4:                        /* NMI */
  624.         temp = (LAC << 12) | MQ;        /* preserve link */
  625.         for (SC = 0; ((temp & 017777777) != 0) &&
  626.             (temp & 040000000) == ((temp << 1) & 040000000); SC++)
  627.             temp = temp << 1;
  628.         LAC = (temp >> 12) & 017777;
  629.         MQ = temp & 07777;
  630.         if (emode && ((LAC & 07777) == 04000) && (MQ == 0))
  631.             LAC = LAC & 010000;        /* clr if 4000'0000 */
  632.         break;
  633.     case 025:                    /* mode B: DPIC */
  634.         if (emode) {
  635.             temp = (LAC + 1) & 07777;    /* SWP already done! */
  636.             LAC = MQ + (temp == 0);
  637.             MQ = temp;
  638.             break;  }
  639.         LAC = LAC | SC;                /* mode A: SCA then */
  640.     case 5:                        /* SHL */
  641.         SC = (M[IF | PC] & 037) + (emode ^ 1);    /* shift+1 if mode A */
  642.         temp = ((LAC << 12) | MQ) << SC;    /* preserve link */
  643.         LAC = (temp >> 12) & 017777;
  644.         MQ = temp & 07777;
  645.         PC = (PC + 1) & 07777;
  646.         SC = emode? 037: 0;            /* SC = 0 if mode A */
  647.         break;
  648.  
  649. /* EAE continued */
  650.  
  651.     case 026:                    /* mode B: DCM */
  652.         if (emode) {
  653.             temp = (-LAC) & 07777;        /* SWP already done! */
  654.             LAC = (MQ ^ 07777) + (temp == 0);
  655.             MQ = temp;
  656.             break;  }
  657.         LAC = LAC | SC;                /* mode A: SCA then */
  658.     case 6:                        /* ASR */
  659.         SC = (M[IF | PC] & 037) + (emode ^ 1);    /* shift+1 if mode A */
  660.         temp = ((LAC & 07777) << 12) | MQ;    /* sext from AC0 */
  661.         if (LAC & 04000) temp = temp | ~037777777;
  662.         if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1;
  663.         temp = temp >> SC;
  664.         if (LAC & 04000) temp = temp | (-1 << (32 - SC));
  665.         LAC = (temp >> 12) & 017777;
  666.         MQ = temp & 07777;
  667.         PC = (PC + 1) & 07777;
  668.         SC = emode? 037: 0;            /* SC = 0 if mode A */
  669.         break;
  670.     case 027:                    /* mode B: SAM */
  671.         if (emode) {
  672.             MA = LAC & 07777;
  673.             LAC = MQ + (MA ^ 07777) + 1;    /* L'AC = MQ - AC */
  674.             gtf = (MA <= MQ) ^ ((MA ^ MQ) >> 11);
  675.             break;  }
  676.         LAC = LAC | SC;                /* mode A: SCA then */
  677.     case 7:                        /* LSR */
  678.         SC = (M[IF | PC] & 037) + (emode ^ 1);    /* shift+1 if mode A */
  679.         temp = ((LAC & 07777) << 12) | MQ;    /* clear link */
  680.         if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1;
  681.         temp = temp >> SC;
  682.         LAC = (temp >> 12) & 07777;
  683.         MQ = temp & 07777;
  684.         PC = (PC + 1) & 07777;
  685.         SC = emode? 037: 0;            /* SC = 0 if mode A */
  686.         break;  }                /* end switch */
  687.     break;                        /* end case 7 */
  688.  
  689. /* Opcode 6, IOT */
  690.  
  691. case 030:case 031:case 032:case 033:            /* IOT */
  692.     if (UF) {                    /* privileged? */
  693.         int_req = int_req | INT_UF;
  694.         break;  }
  695.     device = (IR >> 3) & 077;            /* device = IR<3:8> */
  696.     pulse = IR & 07;                /* pulse = IR<9:11> */
  697.     iot_data = LAC & 07777;                /* AC unchanged */
  698.     switch (device) {                /* decode IR<3:8> */
  699.     case 0:                        /* CPU control */
  700.         switch (pulse) {            /* decode IR<9:11> */
  701.         case 0:                    /* SKON */
  702.             if (int_req & INT_ION) PC = (PC + 1) & 07777;
  703.             int_req = int_req & ~INT_ION;
  704.             break;
  705.         case 1:                    /* ION */
  706.             int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING;
  707.             break;
  708.         case 2:                    /* IOF */
  709.             int_req = int_req & ~INT_ION;
  710.             break;
  711.         case 3:                    /* SRQ */
  712.             if (int_req & INT_ALL) PC = (PC + 1) & 07777;
  713.             break;
  714.         case 4:                    /* GTF */
  715.             LAC = (LAC & 010000) |
  716.                   ((LAC & 010000) >> 1) | (gtf << 10) |
  717.                   (((int_req & INT_ALL) != 0) << 9) |
  718.                   (((int_req & INT_ION) != 0) << 7) | SF;
  719.             break;
  720.         case 5:                    /* RTF */
  721.             gtf = ((LAC & 02000) >> 10);
  722.             UB = (LAC & 0100) >> 6;
  723.             IB = (LAC & 0070) << 9;
  724.             DF = (LAC & 0007) << 12;
  725.             LAC = ((LAC & 04000) << 1) | iot_data;
  726.             int_req = (int_req | INT_ION) & ~INT_NO_CIF_PENDING;
  727.             break;
  728.         case 6:                    /* SGT */
  729.             if (gtf) PC = (PC + 1) & 07777;
  730.             break;
  731.         case 7:                    /* CAF */
  732.             gtf = 0;
  733.             emode = 0;
  734.             int_req = int_req & INT_NO_CIF_PENDING;
  735.             dev_done = 0;
  736.             dev_enable = INT_INIT_ENABLE;
  737.             LAC = 0;
  738.             break;  }            /* end switch pulse */
  739.         continue;                /* skip rest of IOT */
  740.  
  741. /* IOT, continued: memory extension */
  742.  
  743.     case 020:case 021:case 022:case 023:
  744.     case 024:case 025:case 026:case 027:        /* memory extension */
  745.         switch (pulse) {            /* decode IR<9:11> */
  746.         case 1:                 /* CDF */
  747.             DF = (IR & 0070) << 9;
  748.             break;
  749.         case 2:                    /* CIF */
  750.             IB = (IR & 0070) << 9;
  751.             int_req = int_req & ~INT_NO_CIF_PENDING;
  752.             break;
  753.         case 3:                    /* CDF CIF */
  754.             DF = IB = (IR & 0070) << 9;
  755.             int_req = int_req & ~INT_NO_CIF_PENDING;
  756.             break;
  757.         case 4:
  758.             switch (device & 07) {        /* decode IR<5:3> */
  759.             case 0:                /* CINT */
  760.                 int_req = int_req & ~INT_UF;
  761.                 break;
  762.             case 1:                /* RDF */
  763.                 LAC = LAC | (DF >> 9);
  764.                 break;
  765.             case 2:                /* RIF */
  766.                 LAC = LAC | (IF >> 9);
  767.                 break;
  768.             case 3:                /* RIB */
  769.                 LAC = LAC | SF;
  770.                 break;
  771.             case 4:                /* RMF */
  772.                 UB = (SF & 0100) >> 6;
  773.                 IB = (SF & 0070) << 9;
  774.                 DF = (SF & 0007) << 12;
  775.                 int_req = int_req & ~INT_NO_CIF_PENDING;
  776.                 break;
  777.             case 5:                /* SINT */
  778.                 if (int_req & INT_UF) PC = (PC + 1) & 07777;
  779.                 break;
  780.             case 6:                /* CUF */
  781.                 UB = 0;
  782.                 int_req = int_req & ~INT_NO_CIF_PENDING;
  783.                 break;
  784.             case 7:                /* SUF */
  785.                 UB = 1;
  786.                 int_req = int_req & ~INT_NO_CIF_PENDING;
  787.                 break;  }         /* end switch device */
  788.             break;
  789.         default:
  790.             reason = stop_inst;
  791.             break;  }            /* end switch pulse */
  792.         continue;                /* skip rest of IOT */
  793.  
  794. /* IOT, continued: I/O devices */
  795.  
  796.     default:                    /* unknown device */
  797.         reason = stop_inst;            /* stop on flag */
  798.         continue;                /* skip rest of IOT */
  799.     case 010:                    /* power fail */
  800.         switch (pulse) {            /* decode IR<9:11> */
  801.         case 1:                    /* SBE */
  802.             break;
  803.         case 2:                 /* SPL */
  804.             if (int_req & INT_PWR) PC = (PC + 1) & 07777;
  805.             break;
  806.         case 3:                 /* CAL */
  807.             int_req = int_req & ~INT_PWR;
  808.             break;
  809.         default:
  810.             reason = stop_inst;
  811.             break;  }            /* end switch pulse */
  812.         continue;                /* skip rest of IOT */
  813.     case 1:                        /* PTR */
  814.         iot_data = ptr (pulse, iot_data);
  815.         break;
  816.     case 2:                        /* PTP */
  817.         iot_data = ptp (pulse, iot_data);
  818.         break;
  819.     case 3:                        /* TTI */
  820.         iot_data = tti (pulse, iot_data);
  821.         break;
  822.     case 4:                     /* TTO */
  823.         iot_data = tto (pulse, iot_data);
  824.         break;
  825.     case 013:                    /* CLK */
  826.         iot_data = clk (pulse, iot_data);
  827.         break;
  828.     case 060:                    /* RF08 */
  829.         iot_data = rf60 (pulse, iot_data);
  830.         break;
  831.     case 061:
  832.         iot_data = rf61 (pulse, iot_data);
  833.         break;
  834.     case 062:
  835.         iot_data = rf62 (pulse, iot_data);
  836.         break;
  837.     case 064:
  838.         iot_data = rf64 (pulse, iot_data);
  839.         break;
  840.     case 066:                    /* LPT */
  841.         iot_data = lpt (pulse, iot_data);
  842.         break;
  843.     case 074:                    /* RK8E */
  844.         iot_data = rk (pulse, iot_data);
  845.         break;
  846.     case 075:                    /* RX8E */
  847.         iot_data = rx (pulse, iot_data);
  848.         break;  }                /* end switch device */
  849.     LAC = (LAC & 010000) | (iot_data & 07777);
  850.     if (iot_data & IOT_SKP) PC = (PC + 1) & 07777;
  851.     if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON;
  852.     break;                        /* end case 6 */
  853.     }                        /* end switch opcode */
  854. }                            /* end while */
  855.  
  856. /* Simulation halted */
  857.  
  858. saved_PC = IF | (PC & 07777);                /* save copies */
  859. saved_DF = DF & 070000;
  860. saved_LAC = LAC & 017777;
  861. saved_MQ = MQ & 07777;
  862. return reason;
  863. }                            /* end sim_instr */
  864.  
  865. /* Other CPU routines
  866.  
  867.     cpu_ex        read simulated memory
  868.     cpu_dep        write simulated memory
  869.     cpu_reset    reset the CPU
  870.     cpu_svc        restore breakpoint after SCP service
  871. */
  872.  
  873. int cpu_ex (int *vptr, int addr, UNIT *uptr, int sw)
  874. {
  875. if (addr >= MEMSIZE) return SCPE_NXM;
  876. if (vptr != NULL) *vptr = M[addr] & 07777;
  877. return SCPE_OK;
  878. }
  879.  
  880. int cpu_dep (int val, int addr, UNIT *uptr, int sw)
  881. {
  882. if (addr >= MEMSIZE) return SCPE_NXM;
  883. M[addr] = val & 07777;
  884. return SCPE_OK;
  885. }
  886.  
  887. int cpu_reset (DEVICE *dptr)
  888. {
  889. int_req = (int_req & (~INT_ION)) | INT_NO_CIF_PENDING;
  890. saved_DF = IB = (saved_PC >> 12) & 03;
  891. UF = UB = gtf = emode = 0;
  892. return SCPE_OK;
  893. }
  894.  
  895. int cpu_svc (UNIT *uptr)
  896. {
  897. if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
  898. return SCPE_OK;
  899. }
  900.