home *** CD-ROM | disk | FTP | other *** search
- /*
- * pdp9_cpu.c pdp-9 CPU simulator
- *
- * Copyright 1995 by
- * Megan Gentry, Digital Equipment Corporation
- * All rights reserved
- * Commercial use prohibited
- *
- * The following code is based liberally upon pdp-8 emulator code
- * developed by Robert Supnik of Digital Equipment Corporation.
- *
- * The register state for the PDP-9 is:
- *
- * AC<0:17> accumulater
- * L link
- * MB<0:17> memory buffer
- * MQ<0:17> multiplier quotient
- * EM extended memory mode
- * MP memory protect mode
- * PC<0:17> program counter
- * IR<0:17> instruction register
- *
- * The PDP-9 has four instruction formats:
- * o memory reference
- * o EAE
- * o I/O transfer
- * o operate.
- *
- * The memory reference format is:
- *
- * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | op |in| address |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- *
- * <0:3> mnemonic action
- * 000 CAL M[20]<0> = L
- * M[20]<1> = EM
- * M[20]<2> = MP
- * M[20]<03:17> = PC
- * PC = 21
- * 004 DAC M[MA] = AC
- * 010 JMS M[MA]<0> = L
- * M[MA]<1> = EM
- * M[MA]<2> = MP
- * M[MA]<03:17> = PC
- * PC = MA + 1
- * 014 DZM M[MA] = 0
- * 020 LAC AC = M[MA]
- * 024 XOR AC = AC XOR M[MA]
- * 030 ADD L'AC = AC + M[MA], ones complement
- * 034 TAD L'AC = AC + M[MA], twos complement
- * 040 XCT IR = M[MA]
- * 044 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0
- * 050 AND AC = AC & M[MA]
- * 054 SAD if M[MA] != AC, PC = PC + 1
- * 060 JMP PC = MA
- *
- *
- * <4> mode action
- * 0 direct MA = M[IR<5:17>]
- * 1 indirect MA = M[M[IR<5:17>]]
- *
- * Memory reference instructions can access an address space of 8k
- * 18-bit words.
- */
-
-
- /*
- * The I/O transfer format is:
- *
- * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | 1 1 1 0| res | device select | sub | |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * ^ ^ ^ ^
- * | | | + IOP1 at time 1
- * | | +--- IOP2 at time 2
- * | +------ IOP4 at time 3
- * +--------- Clear AC at time 1
- *
- * The IO Transfer instruction sends the specified pulse to the
- * selected I/O device (and subdevice). The I/O device make take
- * data from the AC, return data to the AC, initiate or cancel
- * operations, or skip on status. The AC can optionally be cleared
- * before any pulses are generated.
- */
-
-
- /*
- * The operate format is as follows:
- *
- * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * | 1| 1| 1| 1| x| | | | | | | | | | | | | |
- * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
- * OPR | NOP ---+ | | | | | | | | | | | +--- CMA
- * CLA ------------+ | | | | | | | | | +------ CML
- * CLL ---------------+ | | | | | | | +--------- OAS
- * RAx/RTx ------------------+ | | | | | +------------ RAL/RTL
- * OR / AND ----------------+ | | | +--------------- RAR/RTR
- * (see <10:12>) <9> 0 = SNL!SZA!SMA
- * <9> 1 = SZL&SNA&SPA
- */
-
-
- /*
- * This routine is the instruction decode routine for the PDP-9.
- * It is called from the simulator control program to execute
- * instructions in simulated memory, starting at the simulated PC.
- * It runs until 'reason' is set non-zero.
- *
- * General notes:
- *
- * 1. Reasons to stop. The simulator can be stopped by:
- *
- * HALT instruction
- * breakpoint encountered
- * unimplemented instruction and stop_inst flag set
- * I/O error in I/O simulator
- *
- * 2. Interrupts. Interrupts are maintained by three parallel variables:
- *
- * dev_done device done flags
- * dev_enable device interrupt enable flags
- * int_req interrupt requests
- *
- * In addition, int_req contains the interrupt enable flag, the
- * CIF not pending flag, and the ION not pending flag. If all
- * three of these flags are set, and at least one interrupt request
- * is set, then an interrupt occurs.
- *
- * 3. Non-existent memory. On the PDP-8, reads to non-existent memory
- * return zero, and writes are ignored. In the simulator, the
- * largest possible memory is instantiated and initialized to zero.
- * Thus, only writes outside the current field (indirect writes) need
- * be checked against actual memory size.
- *
- * 3. Adding I/O devices. Three modules must be modified:
- *
- * pdp9_defs.h add interrupt request definition
- * pdp9_cpu.c add IOT dispatch
- * pdp9_sys.c add pointer to data structures to sim_devices
- */
-
-
- #include "pdp9_defs.h"
-
- #define ILL_ADR_FLAG 0100000 /* invalid addr flag */
- #define save_ibkpt (cpu_unit.u3) /* saved bkpt addr */
- #define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */
- #define UNIT_NOEAE (1 << UNIT_V_NOEAE)
-
- unsigned long M[MAXMEMSIZE] = { 0 }; /* main memory */
-
- long saved_LINKAC = 0; /* saved LINKAC */
- long saved_MQ = 0; /* saved MQ */
- long saved_PC = 0; /* saved IF'PC */
- long saved_DF = 0; /* saved Data Field */
- long IB = 0; /* Instruction Buffer */
- long SF = 0; /* Save Field */
- long emode = 0; /* EAE mode */
- long gtf = 0; /* EAE gtf flag */
- long SC = 0; /* EAE shift count */
- long UB = 0; /* User mode Buffer */
- long UF = 0; /* User mode Flag */
- long OSR = 0; /* Switch Register */
- long old_PC = 0; /* old PC */
- long dev_enable = INT_INIT_ENABLE; /* dev intr enables */
- long dev_done = 0; /* dev done flags */
- long int_req = 0; /* intr requests */
- long ibkpt_addr = ILL_ADR_FLAG; /* breakpoint addr */
- long stop_inst = 0; /* trap on ill inst */
-
- extern int sim_int_char;
-
- int cpu_ex (int *vptr, int addr, UNIT *uptr, int sw);
- int cpu_dep (int val, int addr, UNIT *uptr, int sw);
- int cpu_reset (DEVICE *dptr);
- int cpu_svc (UNIT *uptr);
-
-
- /*
- * CPU data structures
- *
- * cpu_dev CPU device descriptor
- * cpu_unit CPU unit descriptor
- * cpu_reg CPU register list
- * cpu_mod CPU modifier list
- */
-
- UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX, MEMSIZE) };
-
- REG cpu_reg[] = {
- { ORDATA (PC, saved_PC, 15) },
- { ORDATA (AC, saved_LINKAC, 12) },
- { FLDATA (L, saved_LINKAC, 12) },
- { ORDATA (MQ, saved_MQ, 12) },
- { ORDATA (SR, OSR, 12) },
- { GRDATA (IF, saved_PC, 8, 3, 12) },
- { GRDATA (DF, saved_DF, 8, 3, 12) },
- { GRDATA (IB, IB, 8, 3, 12) },
- { ORDATA (SF, SF, 7) },
- { FLDATA (UB, UB, 0) },
- { FLDATA (UF, UF, 0) },
- { ORDATA (SC, SC, 5) },
- { FLDATA (GTF, gtf, 0) },
- { FLDATA (EMODE, emode, 0) },
- { FLDATA (ION, int_req, INT_V_ION) },
- { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) },
- { FLDATA (CIF_DELAY, int_req, INT_V_NO_CIF_PENDING) },
- { FLDATA (PWR_INT, int_req, INT_V_PWR) },
- { FLDATA (UF_INT, int_req, INT_V_UF) },
- { ORDATA (INT, int_req, INT_V_ION+1), REG_RO },
- { ORDATA (DONE, dev_done, INT_V_DIRECT), REG_RO },
- { ORDATA (ENABLE, dev_enable, INT_V_DIRECT), REG_RO },
- { FLDATA (NOEAE, cpu_unit.flags, UNIT_V_NOEAE), REG_HRO },
- { ORDATA (OLDPC, old_PC, 15), REG_RO },
- { FLDATA (STOP_INST, stop_inst, 0) },
- { ORDATA (BREAK, ibkpt_addr, 16) },
- { ORDATA (WRU, sim_int_char, 8) },
- { NULL } };
-
- MTAB cpu_mod[] = {
- { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL },
- { UNIT_NOEAE, 0, "EAE", "EAE", NULL },
- { 0 } };
-
- DEVICE cpu_dev = {
- "CPU", &cpu_unit, cpu_reg, cpu_mod,
- 1, 8, 15, 1, 8, 12,
- &cpu_ex, &cpu_dep, &cpu_reset,
- NULL, NULL, NULL };
-
-
- int
- sim_instr (void)
- {
- long PC, IR, MA, MB, MQ, LINK, LINKAC;
-
- extern int sim_interval;
-
- int device, pulse, temp, iot_data, reason;
-
- extern int tti (int pulse, int AC);
- extern int tto (int pulse, int AC);
- extern int ptr (int pulse, int AC);
- extern int ptp (int pulse, int AC);
- extern int clk (int pulse, int AC);
- extern int lpt (int pulse, int AC);
- extern int rk (int pulse, int AC);
- extern int rx (int pulse, int AC);
- extern int rf60 (int pulse, int AC);
- extern int rf61 (int pulse, int AC);
- extern int rf62 (int pulse, int AC);
- extern int rf64 (int pulse, int AC);
- extern int sim_process_event (void);
- extern int sim_activate (UNIT *uptr, int interval);
-
- /* Restore register state */
-
- PC = saved_PC & 0777777; /* load local copies */
- LINKAC = saved_LINKAC & 0777777;
- MQ = saved_MQ & 0777777;
- int_req = INT_UPDATE;
-
- reason = 0;
-
- /* Main instruction fetch/decode loop */
-
- while (reason == 0) { /* loop until halted */
- if (sim_interval <= 0) /* check clock queue */
- if (reason = sim_process_event ())
- break;
-
- if (int_req > INT_PENDING) { /* interrupt? */
- int_req = int_req & ~INT_ION; /* interrupts off */
- SF = (UF << 6) | (IF >> 9) | (DF >> 12); /* form save field */
- IF = IB = DF = UF = UB = 0; /* clear mem ext */
- old_PC = M[0] = PC; /* save PC in 0 */
- PC = 1;
- } /* fetch next from 1 */
-
- MA = PC; /* form PC */
-
- if (MA == ibkpt_addr) { /* breakpoint? */
- save_ibkpt = ibkpt_addr; /* save ibkpt */
- ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
- sim_activate (&cpu_unit, 1); /* sched re-enable */
- reason = STOP_IBKPT; /* stop simulation */
- break;
- }
-
- IR = M[MA]; /* fetch instruction */
-
- PC = (PC + 1) & 0777777; /* increment PC */
-
- int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */
-
- sim_interval = sim_interval - 1;
-
-
- /*
- * Instruction decoding.
- *
- * The opcode (IR<0:3>) and indirect flag (IR<4>) are decoded together.
- * This produces 32 decode points, 2 per major opcode. For IOT, the
- * extra decode points are not useful.
- */
-
- #define INDIRECT (0020000)
- #define DEFERP if (IR && INDIRECT) \
- MA = M[IR & 017777]; \
- else \
- MA = IR & 017777;
-
- /* decode IR<00:03> */
- switch ((IR >> 14) & 017) {
-
-
- /*
- * Opcode 000, CAL (call subroutine)
- * Note: bits <04:17> are not used in this instruction
- */
-
- case opCAL:
- case opCAL | INDIRECT:
- M[20] = ((L & 01) << 17) | ((EM & 01) << 16) |
- ((MP & 01) << 15) | (MA & 017777);
- PC = 21;
- break;
-
- /* Opcode 004, DAC, deposit AC to memory */
-
- case opDAC:
- DEFERP;
- M[MA] = AC;
- break;
-
- /* Opcode 010, JMS, jump to subroutine */
-
- case opJMS:
- DEFERP;
- M[MA] = ((L & 01) << 17) | ((EM & 01) << 16) |
- ((MP & 01) << 15) | (PC & 017777);
- PC = MA + 1;
- break;
-
- /* Opcode 014, DZM, deposit zero to memory */
-
- case opDZM:
- DEFERP;
- M[MA] = 0;
- break;
-
- /* Opcode 020, LAC, load AC */
-
- case opLAC:
- DEFERP;
- AC = M[MA] & 0777777;
- break;
-
- /* Opcode 024, XOR, exclusive or memory with AC */
-
- case opXOR:
- DEFERP;
- AC = AC ^ M[MA];
- break;
-
- /* Opcode 030, ADD, add memory to AC */
-
- case opADD:
- DEFERP;
- AC += M[MA];
- break;
-
- case 034:case 035: /* OPR, group 1 */
- switch ((IR >> 4) & 017) { /* decode IR<4:7> */
- case 0: /* nop */
- break;
- case 1: /* CML */
- LAC = LAC ^ 010000; break;
- case 2: /* CMA */
- LAC = LAC ^ 07777; break;
- case 3: /* CMA CML */
- LAC = LAC ^ 017777; break;
- case 4: /* CLL */
- LAC = LAC & 07777; break;
- case 5: /* CLL CML = STL */
- LAC = LAC | 010000; break;
- case 6: /* CLL CMA */
- LAC = (LAC ^ 07777) & 07777; break;
- case 7: /* CLL CMA CML */
- LAC = (LAC ^ 07777) | 010000; break;
- case 010: /* CLA */
- LAC = LAC & 010000; break;
- case 011: /* CLA CML */
- LAC = (LAC & 010000) ^ 010000; break;
- case 012: /* CLA CMA = STA */
- LAC = LAC | 07777; break;
- case 013: /* CLA CMA CML */
- LAC = (LAC | 07777) ^ 010000; break;
- case 014: /* CLA CLL */
- LAC = 0; break;
- case 015: /* CLA CLL CML */
- LAC = 010000; break;
- case 016: /* CLA CLL CMA */
- LAC = 07777; break;
- case 017: /* CLA CLL CMA CML */
- LAC = 017777; break; } /* end switch opers */
- if (IR & 01) LAC = (LAC + 1) & 017777; /* IAC */
- switch ((IR >> 1) & 07) { /* decode IR<8:10> */
- case 0: /* nop */
- break;
- case 1: /* BSW */
- LAC = (LAC & 010000) | ((LAC >> 6) & 077)
- | ((LAC & 077) << 6); break;
- case 2: /* RAL */
- LAC = ((LAC << 1) | (LAC >> 12)) & 017777; break;
- case 3: /* RTL */
- LAC = ((LAC << 2) | (LAC >> 11)) & 017777; break;
- case 4: /* RAR */
- LAC = ((LAC >> 1) | (LAC << 12)) & 017777; break;
- case 5: /* RTR */
- LAC = ((LAC >> 2) | (LAC << 11)) & 017777; break;
- case 6: /* RAL RAR - undef */
- LAC = LAC & (IR | 010000); break; /* uses AND path */
- case 7: /* RTL RTR - undef */
- LAC = (LAC & 010000) | (MA & 07600) | (IR & 0177);
- break; } /* uses address path */
- break; /* end group 1 */
-
- /* OPR group 2 */
-
- case 036:case 037: /* OPR, groups 2, 3 */
- if ((IR & 01) == 0) { /* group 2 */
- switch ((IR >> 3) & 017) { /* decode IR<6:8> */
- case 0: /* nop */
- break;
- case 1: /* SKP */
- PC = (PC + 1) & 07777; break;
- case 2: /* SNL */
- if (LAC >= 010000) PC = (PC + 1) & 07777; break;
- case 3: /* SZL */
- if (LAC < 010000) PC = (PC + 1) & 07777; break;
- case 4: /* SZA */
- if ((LAC & 07777) == 0) PC = (PC + 1) & 07777; break;
- case 5: /* SNA */
- if ((LAC & 07777) != 0) PC = (PC + 1) & 07777; break;
- case 6: /* SZA | SNL */
- if ((LAC == 0) || (LAC >= 010000))
- PC = (PC + 1) & 07777; break;
- case 7: /* SNA & SZL */
- if ((LAC != 0) && (LAC < 010000))
- PC = (PC + 1) & 07777; break;
- case 010: /* SMA */
- if ((LAC & 04000) != 0) PC = (PC + 1) & 07777; break;
- case 011: /* SPA */
- if ((LAC & 04000) == 0) PC = (PC + 1) & 07777; break;
- case 012: /* SMA | SNL */
- if (LAC >= 04000) PC = (PC + 1) & 07777; break;
- case 013: /* SPA & SZL */
- if (LAC < 04000) PC = (PC + 1) & 07777; break;
- case 014: /* SMA | SZA */
- if (((LAC & 04000) != 0) || ((LAC & 07777) == 0))
- PC = (PC + 1) & 07777; break;
- case 015: /* SPA & SNA */
- if (((LAC & 04000) == 0) && ((LAC & 07777) != 0))
- PC = (PC + 1) & 07777; break;
- case 016: /* SMA | SZA | SNL */
- if ((LAC >= 04000) || (LAC == 0))
- PC = (PC + 1) & 07777; break;
- case 017: /* SPA & SNA & SZL */
- if ((LAC < 04000) && (LAC != 0))
- PC = (PC + 1) & 07777; break;
- } /* end switch skips */
- if (IR & 0200) LAC = LAC & 010000; /* CLA */
- if ((IR & 06) && UF) { /* privileged? */
- int_req = int_req | INT_UF; break; }
- if (IR & 04) LAC = LAC | OSR; /* OSR */
- if (IR & 02) reason = STOP_HALT; /* HLT */
- break; } /* end group 2 */
-
- /* OPR group 3 standard
-
- MQA!MQL exchanges AC and MQ, as follows:
-
- temp = MQ;
- MQ = LAC & 07777;
- LAC = LAC & 010000 | temp;
- */
-
- temp = MQ; /* group 3 */
- if (IR & 0200) LAC = LAC & 010000; /* CLA */
- if (IR & 0020) { /* MQL */
- MQ = LAC & 07777;
- LAC = LAC & 010000; }
- if (IR & 0100) LAC = LAC | temp; /* MQA */
- if ((IR & 0056) && (cpu_unit.flags & UNIT_NOEAE)) {
- reason = stop_inst; /* EAE not present */
- break; }
-
- /* OPR group 3 EAE
-
- The EAE operates in two modes:
-
- Mode A, PDP-8/I compatible
- Mode B, extended capability
-
- Mode B provides eight additional subfunctions; in addition, some
- of the Mode A functions operate differently in Mode B.
-
- The mode switch instructions are decoded explicitly and cannot be
- microprogrammed with other EAE functions (SWAB performs an MQL as
- part of standard group 3 decoding). If mode switching is decoded,
- all other EAE timing is suppressed.
- */
-
- if (IR == 07431) { /* SWAB */
- emode = 1; /* set mode flag */
- break; }
- if (IR == 07447) { /* SWBA */
- emode = gtf = 0; /* clear mode, gtf */
- break; }
-
- /* If not switching modes, the EAE operation is determined by the mode
- and IR<6,8:10>:
-
- <6:10> mode A mode B comments
-
- 0x000 NOP NOP
- 0x001 SCL ACS
- 0x010 MUY MUY if mode B, next = address
- 0x011 DVI DVI if mode B, next = address
- 0x100 NMI NMI if mode B, clear AC if
- result = 4000'0000
- 0x101 SHL SHL if mode A, extra shift
- 0x110 ASR ASR if mode A, extra shift
- 0x111 LSR LSR if mode A, extra shift
- 1x000 SCA SCA
- 1x001 SCA + SCL DAD
- 1x010 SCA + MUY DST
- 1x011 SCA + DVI SWBA NOP if not detected earlier
- 1x100 SCA + NMI DPSZ
- 1x101 SCA + SHL DPIC must be combined with MQA!MQL
- 1x110 SCA + ASR DCM must be combined with MQA!MQL
- 1x111 SCA + LSR SAM
-
- EAE instructions which fetch memory operands use the CPU's DEFER
- state to read the first word; if the address operand is in locations
- x0010 - x0017, it is autoincremented.
- */
-
- /* EAE continued */
-
- switch ((IR >> 1) & 027) { /* decode IR<6,8:10> */
- case 020: /* mode A, B: SCA */
- LAC = LAC | SC;
- break;
- case 0: /* mode A, B: NOP */
- break;
- case 021: /* mode B: DAD */
- if (emode) {
- MA = IF | PC; INDIRECT; /* defer state */
- MQ = MQ + M[MA];
- MA = DF | ((MA + 1) & 07777);
- LAC = (LAC & 07777) + M[MA] + (MQ >> 12);
- MQ = MQ & 07777;
- PC = (PC + 1) & 07777;
- break; }
- LAC = LAC | SC; /* mode A: SCA then */
- case 1: /* mode B: ACS */
- if (emode) {
- SC = LAC & 037;
- LAC = LAC & 010000;
- break; }
- SC = (~M[IF | PC]) & 037; /* mode A: SCL */
- PC = (PC + 1) & 07777;
- break;
- case 022: /* mode B: DST */
- if (emode) {
- MA = IF | PC; INDIRECT; /* defer state */
- if (MEM_ADDR_OK (MA)) M[MA] = MQ & 07777;
- MA = DF | ((MA + 1) & 07777);
- if (MEM_ADDR_OK (MA)) M[MA] = LAC & 07777;
- PC = (PC + 1) & 07777;
- break; }
- LAC = LAC | SC; /* mode A: SCA then */
- case 2: /* MUY */
- MA = IF | PC;
- if (emode) { INDIRECT; } /* mode B: defer */
- temp = (MQ * M[MA]) + (LAC & 07777);
- LAC = (temp >> 12) & 07777;
- MQ = temp & 07777;
- PC = (PC + 1) & 07777;
- SC = 014; /* 12 shifts */
- break;
-
- /* EAE continued */
-
- case 023: /* mode B: SWBA */
- if (emode) break;
- LAC = LAC | SC; /* mode A: SCA then */
- case 3: /* DVI */
- MA = IF | PC;
- if (emode) { INDIRECT; }; /* mode B: defer */
- if ((LAC & 07777) >= M[MA]) { /* overflow? */
- LAC = LAC | 010000; /* set link */
- MQ = ((MQ << 1) + 1) & 07777; /* rotate MQ */
- SC = 01; } /* 1 shift */
- else { temp = ((LAC & 07777) << 12) | MQ;
- MQ = temp / M[MA];
- LAC = temp % M[MA];
- SC = 015; } /* 13 shifts */
- PC = (PC + 1) & 07777;
- break;
- case 024: /* mode B: DPSZ */
- if (emode) {
- if (((LAC | MQ) & 07777) == 0) PC = (PC + 1) & 07777;
- break; }
- LAC = LAC | SC; /* mode A: SCA then */
- case 4: /* NMI */
- temp = (LAC << 12) | MQ; /* preserve link */
- for (SC = 0; ((temp & 017777777) != 0) &&
- (temp & 040000000) == ((temp << 1) & 040000000); SC++)
- temp = temp << 1;
- LAC = (temp >> 12) & 017777;
- MQ = temp & 07777;
- if (emode && ((LAC & 07777) == 04000) && (MQ == 0))
- LAC = LAC & 010000; /* clr if 4000'0000 */
- break;
- case 025: /* mode B: DPIC */
- if (emode) {
- temp = (LAC + 1) & 07777; /* SWP already done! */
- LAC = MQ + (temp == 0);
- MQ = temp;
- break; }
- LAC = LAC | SC; /* mode A: SCA then */
- case 5: /* SHL */
- SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */
- temp = ((LAC << 12) | MQ) << SC; /* preserve link */
- LAC = (temp >> 12) & 017777;
- MQ = temp & 07777;
- PC = (PC + 1) & 07777;
- SC = emode? 037: 0; /* SC = 0 if mode A */
- break;
-
- /* EAE continued */
-
- case 026: /* mode B: DCM */
- if (emode) {
- temp = (-LAC) & 07777; /* SWP already done! */
- LAC = (MQ ^ 07777) + (temp == 0);
- MQ = temp;
- break; }
- LAC = LAC | SC; /* mode A: SCA then */
- case 6: /* ASR */
- SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */
- temp = ((LAC & 07777) << 12) | MQ; /* sext from AC0 */
- if (LAC & 04000) temp = temp | ~037777777;
- if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1;
- temp = temp >> SC;
- if (LAC & 04000) temp = temp | (-1 << (32 - SC));
- LAC = (temp >> 12) & 017777;
- MQ = temp & 07777;
- PC = (PC + 1) & 07777;
- SC = emode? 037: 0; /* SC = 0 if mode A */
- break;
- case 027: /* mode B: SAM */
- if (emode) {
- MA = LAC & 07777;
- LAC = MQ + (MA ^ 07777) + 1; /* L'AC = MQ - AC */
- gtf = (MA <= MQ) ^ ((MA ^ MQ) >> 11);
- break; }
- LAC = LAC | SC; /* mode A: SCA then */
- case 7: /* LSR */
- SC = (M[IF | PC] & 037) + (emode ^ 1); /* shift+1 if mode A */
- temp = ((LAC & 07777) << 12) | MQ; /* clear link */
- if (emode && (SC != 0)) gtf = (temp >> (SC - 1)) & 1;
- temp = temp >> SC;
- LAC = (temp >> 12) & 07777;
- MQ = temp & 07777;
- PC = (PC + 1) & 07777;
- SC = emode? 037: 0; /* SC = 0 if mode A */
- break; } /* end switch */
- break; /* end case 7 */
-
- /* Opcode 6, IOT */
-
- case 030:case 031:case 032:case 033: /* IOT */
- if (UF) { /* privileged? */
- int_req = int_req | INT_UF;
- break; }
- device = (IR >> 3) & 077; /* device = IR<3:8> */
- pulse = IR & 07; /* pulse = IR<9:11> */
- iot_data = LAC & 07777; /* AC unchanged */
- switch (device) { /* decode IR<3:8> */
- case 0: /* CPU control */
- switch (pulse) { /* decode IR<9:11> */
- case 0: /* SKON */
- if (int_req & INT_ION) PC = (PC + 1) & 07777;
- int_req = int_req & ~INT_ION;
- break;
- case 1: /* ION */
- int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING;
- break;
- case 2: /* IOF */
- int_req = int_req & ~INT_ION;
- break;
- case 3: /* SRQ */
- if (int_req & INT_ALL) PC = (PC + 1) & 07777;
- break;
- case 4: /* GTF */
- LAC = (LAC & 010000) |
- ((LAC & 010000) >> 1) | (gtf << 10) |
- (((int_req & INT_ALL) != 0) << 9) |
- (((int_req & INT_ION) != 0) << 7) | SF;
- break;
- case 5: /* RTF */
- gtf = ((LAC & 02000) >> 10);
- UB = (LAC & 0100) >> 6;
- IB = (LAC & 0070) << 9;
- DF = (LAC & 0007) << 12;
- LAC = ((LAC & 04000) << 1) | iot_data;
- int_req = (int_req | INT_ION) & ~INT_NO_CIF_PENDING;
- break;
- case 6: /* SGT */
- if (gtf) PC = (PC + 1) & 07777;
- break;
- case 7: /* CAF */
- gtf = 0;
- emode = 0;
- int_req = int_req & INT_NO_CIF_PENDING;
- dev_done = 0;
- dev_enable = INT_INIT_ENABLE;
- LAC = 0;
- break; } /* end switch pulse */
- continue; /* skip rest of IOT */
-
- /* IOT, continued: memory extension */
-
- case 020:case 021:case 022:case 023:
- case 024:case 025:case 026:case 027: /* memory extension */
- switch (pulse) { /* decode IR<9:11> */
- case 1: /* CDF */
- DF = (IR & 0070) << 9;
- break;
- case 2: /* CIF */
- IB = (IR & 0070) << 9;
- int_req = int_req & ~INT_NO_CIF_PENDING;
- break;
- case 3: /* CDF CIF */
- DF = IB = (IR & 0070) << 9;
- int_req = int_req & ~INT_NO_CIF_PENDING;
- break;
- case 4:
- switch (device & 07) { /* decode IR<5:3> */
- case 0: /* CINT */
- int_req = int_req & ~INT_UF;
- break;
- case 1: /* RDF */
- LAC = LAC | (DF >> 9);
- break;
- case 2: /* RIF */
- LAC = LAC | (IF >> 9);
- break;
- case 3: /* RIB */
- LAC = LAC | SF;
- break;
- case 4: /* RMF */
- UB = (SF & 0100) >> 6;
- IB = (SF & 0070) << 9;
- DF = (SF & 0007) << 12;
- int_req = int_req & ~INT_NO_CIF_PENDING;
- break;
- case 5: /* SINT */
- if (int_req & INT_UF) PC = (PC + 1) & 07777;
- break;
- case 6: /* CUF */
- UB = 0;
- int_req = int_req & ~INT_NO_CIF_PENDING;
- break;
- case 7: /* SUF */
- UB = 1;
- int_req = int_req & ~INT_NO_CIF_PENDING;
- break; } /* end switch device */
- break;
- default:
- reason = stop_inst;
- break; } /* end switch pulse */
- continue; /* skip rest of IOT */
-
- /* IOT, continued: I/O devices */
-
- default: /* unknown device */
- reason = stop_inst; /* stop on flag */
- continue; /* skip rest of IOT */
- case 010: /* power fail */
- switch (pulse) { /* decode IR<9:11> */
- case 1: /* SBE */
- break;
- case 2: /* SPL */
- if (int_req & INT_PWR) PC = (PC + 1) & 07777;
- break;
- case 3: /* CAL */
- int_req = int_req & ~INT_PWR;
- break;
- default:
- reason = stop_inst;
- break; } /* end switch pulse */
- continue; /* skip rest of IOT */
- case 1: /* PTR */
- iot_data = ptr (pulse, iot_data);
- break;
- case 2: /* PTP */
- iot_data = ptp (pulse, iot_data);
- break;
- case 3: /* TTI */
- iot_data = tti (pulse, iot_data);
- break;
- case 4: /* TTO */
- iot_data = tto (pulse, iot_data);
- break;
- case 013: /* CLK */
- iot_data = clk (pulse, iot_data);
- break;
- case 060: /* RF08 */
- iot_data = rf60 (pulse, iot_data);
- break;
- case 061:
- iot_data = rf61 (pulse, iot_data);
- break;
- case 062:
- iot_data = rf62 (pulse, iot_data);
- break;
- case 064:
- iot_data = rf64 (pulse, iot_data);
- break;
- case 066: /* LPT */
- iot_data = lpt (pulse, iot_data);
- break;
- case 074: /* RK8E */
- iot_data = rk (pulse, iot_data);
- break;
- case 075: /* RX8E */
- iot_data = rx (pulse, iot_data);
- break; } /* end switch device */
- LAC = (LAC & 010000) | (iot_data & 07777);
- if (iot_data & IOT_SKP) PC = (PC + 1) & 07777;
- if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON;
- break; /* end case 6 */
- } /* end switch opcode */
- } /* end while */
-
- /* Simulation halted */
-
- saved_PC = IF | (PC & 07777); /* save copies */
- saved_DF = DF & 070000;
- saved_LAC = LAC & 017777;
- saved_MQ = MQ & 07777;
- return reason;
- } /* end sim_instr */
-
- /* Other CPU routines
-
- cpu_ex read simulated memory
- cpu_dep write simulated memory
- cpu_reset reset the CPU
- cpu_svc restore breakpoint after SCP service
- */
-
- int cpu_ex (int *vptr, int addr, UNIT *uptr, int sw)
- {
- if (addr >= MEMSIZE) return SCPE_NXM;
- if (vptr != NULL) *vptr = M[addr] & 07777;
- return SCPE_OK;
- }
-
- int cpu_dep (int val, int addr, UNIT *uptr, int sw)
- {
- if (addr >= MEMSIZE) return SCPE_NXM;
- M[addr] = val & 07777;
- return SCPE_OK;
- }
-
- int cpu_reset (DEVICE *dptr)
- {
- int_req = (int_req & (~INT_ION)) | INT_NO_CIF_PENDING;
- saved_DF = IB = (saved_PC >> 12) & 03;
- UF = UB = gtf = emode = 0;
- return SCPE_OK;
- }
-
- int cpu_svc (UNIT *uptr)
- {
- if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
- return SCPE_OK;
- }
-