home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-29 | 41.3 KB | 1,401 lines |
- /* pdp18b_cpu.c: 18b PDP CPU simulator
-
- Copyright (c) 1994, 1995, 1996, Robert M Supnik,
- Digital Equipment Corporation
- All rights reserved
-
- The 18b PDP family has five distinct architectural variants: PDP-1,
- PDP-4, PDP-7, PDP-9, and PDP-15. Of these, the PDP-1 is so unique
- as to require a different simulator. The PDP-4, PDP-7, PDP-9, and
- PDP-15 are "upward compatible", with each new variant adding
- distinct architectural features and incompatibilities.
-
- The register state for the 18b PDP's is:
-
- all AC<0:17> accumulator
- all MQ<0:17> multiplier-quotient
- all L link flag
- all PC<0:x> program counter
- all IORS I/O status register
- PDP-7, PDP-9 EXTM extend mode
- PDP-15 BANKM bank mode
- PDP-7 TRAPM trap mode
- PDP-9, PDP-15 USMD user mode
- PDP-9, PDP-15 BR bounds register
- PDP-15 XR index register
- PDP-15 LR limit register
- */
-
- /* The PDP-4, PDP-7, and PDP-9 have five instruction formats: memory
- reference, load immediate, I/O transfer, EAE, and operate. The PDP-15
- adds a sixth, index operate, and a seventh, floating point. The memory
- reference format for the PDP-4, PDP-7, and PDP-9, and for the PDP-15
- in bank mode, is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | op |in| address | memory reference
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- The PDP-15 in page mode trades an address bit for indexing capability:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | op |in| X| address | memory reference
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- <0:3> mnemonic action
-
- 00 CAL JMS with MA = 20
- 04 DAC M[MA] = AC
- 10 JMS M[MA] = L'mem'user'PC, PC = MA + 1
- 14 DZM M[MA] = 0
- 20 LAC AC = M[MA]
- 24 XOR AC = AC ^ M[MA]
- 30 ADD L'AC = AC + M[MA] one's complement
- 34 TAD L'AC = AC + M[MA]
- 40 XCT M[MA] is executed as an instruction
- 44 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0
- 50 AND AC = AC & M[MA]
- 54 SAD skip if AC != M[MA]
- 60 JMP PC = MA
-
- On the PDP-4, PDP-7, and PDP-9, and the PDP-15 in bank mode, memory
- reference instructions can access an address space of 32K words. The
- address space is divided into four 8K word fields. An instruction can
- directly address, via its 13b address, the entire current field. On the
- PDP-4, PDP-7, and PDP-9, if extend mode is off, indirect addresses access
- the current field; if on (or a PDP-15), they can access all 32K.
-
- On the PDP-15 in page mode, memory reference instructions can access
- an address space of 128K words. The address is divided into four 32K
- word blocks, each of which consists of eight 4K pages. An instruction
- can directly address, via its 12b address, the current page. Indirect
- addresses can access the current block. Indexed and autoincrement
- addresses can access all 128K.
-
- On the PDP-4 and PDP-7, if an indirect address in in locations 00010-
- 00017 of any field, the indirect address is incremented and rewritten
- to memory before use. On the PDP-9 and PDP-15, only locations 00010-
- 00017 of field zero autoincrement; special logic will redirect indirect
- references to 00010-00017 to field zero, even if (on the PDP-9) extend
- mode is off.
- */
-
- /* The EAE format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 1 1 0 1| | | | | | | | | | | | | | | EAE
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | | | | | | | | | | | | | |
- | | | | | | | | | | | | | +- or SC (3)
- | | | | | | | | | | | | +---- or MQ (3)
- | | | | | | | | | | | +------- compl MQ (3)
- | | | | | | | | \______________/
- | | | | | | | | |
- | | | | | \_____/ +--------- shift count
- | | | | | |
- | | | | | +---------------------- EAE command (3)
- | | | | +---------------------------- clear AC (2)
- | | | +------------------------------- or AC (2)
- | | +---------------------------------- load EAE sign (1)
- | +------------------------------------- clear MQ (1)
- +---------------------------------------- load link (1)
-
- 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 0 0| device | sdv |cl| pulse | I/O transfer
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- The IO transfer instruction sends the the specified pulse to the
- specified I/O device and sub-device. The I/O device may take data
- from the AC, return data to the AC, initiate or cancel operations,
- or skip on status. On the PDP-4, PDP-7, and PDP-9, bits <4:5>
- were designated as subdevice bits but were never used; the PDP-15
- requires them to be zero.
-
- On the PDP-15, the floating point format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 1 1 1 0 0 1| subopcode | floating point
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- |in| address |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- Indirection is always single level.
- */
-
- /* On the PDP-15, the index operate format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 1 1 1 0 1| subopcode | immediate | index operate
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- The index operate instructions provide various operations on the
- index and limit registers.
-
- The operate format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 1 1 1 1 0| | | | | | | | | | | | | | operate
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | | | | | | | | | | | | |
- | | | | | | | | | | | | +- CMA (3)
- | | | | | | | | | | | +---- CML (3)
- | | | | | | | | | | +------- OAS (3)
- | | | | | | | | | +---------- RAL (3)
- | | | | | | | | +------------- RAR (3)
- | | | | | | | +---------------- HLT (4)
- | | | | | | +------------------- SMA (1)
- | | | | | +---------------------- SZA (1)
- | | | | +------------------------- SNL (1)
- | | | +---------------------------- invert skip (1)
- | | +------------------------------- rotate twice (2)
- | +---------------------------------- CLL (2)
- +------------------------------------- CLA (2)
-
- The operate instruction can be microprogrammed to perform operations
- on the AC and link.
-
- The load immediate format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 1 1 1 1 1| immediate | LAW
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- <0:4> mnemonic action
-
- 76 LAW AC = IR
- */
-
- /* This routine is the instruction decode routine for the 18b PDP's.
- 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
- nested XCT's
- I/O error in I/O simulator
-
- 2. Interrupts. Interrupt requests are maintained in the int_req
- register. If interrupts are on and not deferred, and at least
- one interrupt request is set, a program interrupt occurs.
-
- 3. Arithmetic. The 18b PDP's implements both 1's and 2's complement
- arithmetic for signed numbers. In 1's complement arithmetic, a
- negative number is represented by the complement (XOR 0777777) of
- its absolute value. Addition of 1's complement numbers requires
- propagating the carry out of the high order bit back to the low
- order bit.
-
- 4. Adding I/O devices. Three modules must be modified:
-
- pdp18b_defs.h add interrupt request definition
- pdp18b_cpu.c add IOT and IORS dispatches
- pdp18b_sys.c add pointer to data structures to sim_devices
- */
-
- #include "pdp18b_defs.h"
-
- #define ILL_ADR_FLAG (1 << ADDRSIZE)
- #define save_ibkpt (cpu_unit.u3)
- #define UNIT_V_NOEAE (UNIT_V_UF) /* EAE absent */
- #define UNIT_NOEAE (1 << UNIT_V_NOEAE)
- #define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
- #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
- #if defined (PDP4)
- #define EAE_DFLT UNIT_NOEAE
- #else
- #define EAE_DFLT 0
- #endif
-
- unsigned int M[MAXMEMSIZE] = { 0 };
- int saved_LAC = 0; /* link'AC */
- int saved_MQ = 0; /* MQ */
- int saved_PC = 0; /* PC */
- int int_req = 0; /* int requests */
- int iors = 0; /* IORS */
- int ion = 0; /* int on */
- int ion_defer = 0; /* int defer */
- int memm = 0; /* ext mem mode */
- int usmd = 0; /* user mode */
- int usmdbuf = 0; /* user mode buffer */
- int trap_pending = 0; /* trap pending */
- int emir_pending = 0; /* emir pending */
- int rest_pending = 0; /* restore pending */
- int BR = 0; /* mem mgt bounds */
- int nexm = 0; /* nx mem flag */
- int prvn = 0; /* priv viol flag */
- int SC = 0; /* shift count */
- int eae_ac_sign = 0; /* EAE AC sign */
- int SR = 0; /* switch register */
- int XR = 0; /* index register */
- int LR = 0; /* limit register */
- int stop_inst = 0; /* stop on rsrv inst */
- int xct_max = 16; /* nested XCT limit */
- int old_PC = 0; /* old PC */
- int ibkpt_addr = ILL_ADR_FLAG | ADDRMASK; /* breakpoint addr */
- 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);
- int cpu_set_size (UNIT *uptr, int value);
- int upd_iors (void);
-
- /* CPU data structures
-
- cpu_dev CPU device descriptor
- cpu_unit CPU unit
- cpu_reg CPU register list
- cpu_mod CPU modifier list
- */
-
- UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX+EAE_DFLT, MAXMEMSIZE) };
-
- REG cpu_reg[] = {
- { ORDATA (PC, saved_PC, ADDRSIZE) },
- { ORDATA (AC, saved_LAC, 18) },
- { FLDATA (L, saved_LAC, 18) },
- #if !defined (PDP4)
- { ORDATA (MQ, saved_MQ, 18) },
- { ORDATA (SC, SC, 6) },
- { FLDATA (EAE_AC_SIGN, eae_ac_sign, 18) },
- #endif
- { ORDATA (SR, SR, 18) },
- { ORDATA (IORS, iors, 18), REG_RO },
- { ORDATA (INT, int_req, 32), REG_RO },
- { FLDATA (ION, ion, 0) },
- { ORDATA (ION_DELAY, ion_defer, 2) },
- #if defined (PDP7)
- { FLDATA (TRAPM, usmd, 0) },
- { FLDATA (TRAPP, trap_pending, 0) },
- { FLDATA (EXTM, memm, 0) },
- { FLDATA (EMIRP, emir_pending, 0) },
- #elif defined (PDP9)
- { ORDATA (BR, BR, ADDRSIZE) },
- { FLDATA (USMD, usmd, 0) },
- { FLDATA (USMDBUF, usmdbuf, 0) },
- { FLDATA (NEXM, nexm, 0) },
- { FLDATA (PRVN, prvn, 0) },
- { FLDATA (TRAPP, trap_pending, 0) },
- { FLDATA (EXTM, memm, 0) },
- { FLDATA (EMIRP, emir_pending, 0) },
- { FLDATA (RESTP, rest_pending, 0) },
- { FLDATA (PWRFL, int_req, INT_V_PWRFL) },
- #elif defined (PDP15)
- { ORDATA (XR, XR, 18) },
- { ORDATA (LR, LR, 18) },
- { ORDATA (BR, BR, ADDRSIZE) },
- { FLDATA (NEXM, nexm, 0) },
- { FLDATA (PRVN, prvn, 0) },
- { FLDATA (TRAPP, trap_pending, 0) },
- { FLDATA (USMD, usmd, 0) },
- { FLDATA (USMDBUF, usmdbuf, 0) },
- { FLDATA (BANKM, memm, 0) },
- { FLDATA (RESP, rest_pending, 0) },
- { FLDATA (PWRFL, int_req, INT_V_PWRFL) },
- #endif
- { ORDATA (OLDPC, old_PC, ADDRSIZE), REG_RO },
- { FLDATA (STOP_INST, stop_inst, 0) },
- { FLDATA (NOEAE, cpu_unit.flags, UNIT_V_NOEAE), REG_HRO },
- { DRDATA (XCT_MAX, xct_max, 8), REG_NZ },
- { ORDATA (BREAK, ibkpt_addr, ADDRSIZE + 1) },
- { ORDATA (WRU, sim_int_char, 8) },
- { NULL } };
-
- MTAB cpu_mod[] = {
- #if !defined (PDP4)
- { UNIT_NOEAE, UNIT_NOEAE, "no EAE", "NOEAE", NULL },
- { UNIT_NOEAE, 0, "EAE", "EAE", NULL },
- #endif
- { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
- { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
- #if (MAXMEMSIZE > 8192)
- { UNIT_MSIZE, 12288, NULL, "12K", &cpu_set_size },
- { UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
- { UNIT_MSIZE, 20480, NULL, "20K", &cpu_set_size },
- { UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
- { UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
- { UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
- #endif
- #if (MAXMEMSIZE > 32768)
- { UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
- { UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
- { UNIT_MSIZE, 81920, NULL, "80K", &cpu_set_size },
- { UNIT_MSIZE, 98304, NULL, "96K", &cpu_set_size },
- { UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size },
- { UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
- #endif
- { 0 } };
-
- DEVICE cpu_dev = {
- "CPU", &cpu_unit, cpu_reg, cpu_mod,
- 1, 8, ADDRSIZE, 1, 8, 18,
- &cpu_ex, &cpu_dep, &cpu_reset,
- NULL, NULL, NULL };
-
- int sim_instr (void)
- {
- extern int sim_interval;
- register int PC, LAC, MQ;
- int iot_data, device, pulse, 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 lpt65 (int pulse, int AC);
- extern int lpt66 (int pulse, int AC);
- #if defined (DRM)
- extern int drm60 (int pulse, int AC);
- extern int drm61 (int pulse, int AC);
- extern int drm62 (int pulse, int AC);
- #endif
- #if defined (RF)
- extern int rf70 (int pulse, int AC);
- extern int rf72 (int pulse, int AC);
- #endif
- #if defined (RP)
- extern int rp63 (int pulse, int AC);
- extern int rp64 (int pulse, int AC);
- #endif
- #if defined (MTA)
- extern int mt (int pulse, int AC);
- #endif
- extern int sim_process_event (void);
- extern int sim_activate (UNIT *uptr, int interval);
- extern int reset_all (int start);
-
- #define JMS_WORD(t) ((LAC & 01000000) >> 1) | ((memm & 1) << 16) | \
- ((t & 1) << 15) | ((PC) & 077777)
- #define INCR_ADDR(x) ((x & epcmask) | ((x + 1) & damask))
- #define SEXT(x) ((int) (((x) & 0400000)? (x) | ~0777777: (x) & 0777777))
-
- /* Restore register state */
-
- #if defined (PDP15)
- register int epcmask, damask;
-
- damask = memm? 017777: 07777; /* set dir addr mask */
- epcmask = ADDRMASK & ~damask; /* extended PC mask */
-
- #else
- #define damask 017777 /* direct addr mask */
- #define epcmask (ADDRMASK & ~damask) /* extended PC mask */
- #endif
-
- PC = saved_PC & ADDRMASK; /* load local copies */
- LAC = saved_LAC & 01777777;
- MQ = saved_MQ & 0777777;
- reason = 0;
-
- /* Main instruction fetch/decode loop: check trap and interrupt */
-
- while (reason == 0) { /* loop until halted */
- register int IR, MA, t, xct_count;
- register int link_init, fill;
-
- if (sim_interval <= 0) { /* check clock queue */
- if (reason = sim_process_event ()) break; }
-
- /* Protection traps work like interrupts, with these quirks:
-
- PDP-7 extend mode forced on, M[0] = PC, PC = 2
- PDP-9, PDP-15 extend/bank mode forced off, M[0/20] = PC, PC = 0/21
- */
-
- #if defined (PDP7)
- if (trap_pending) { /* trap pending? */
- old_PC = PC; /* save old PC */
- M[0] = JMS_WORD (1); /* save state */
- PC = 2; /* fetch next from 2 */
- ion = 0; /* interrupts off */
- memm = 1; /* extend on */
- emir_pending = trap_pending = 0; /* emir, trap off */
- usmd = 0; } /* protect off */
- #endif
-
- #if defined (PDP9) || defined (PDP15)
- if (trap_pending) { /* trap pending? */
- old_PC = PC; /* save old PC */
- MA = ion? 0: 020; /* save in 0 or 20 */
- M[MA] = JMS_WORD (1); /* save state */
- PC = MA + 1; /* fetch next */
- ion = 0; /* interrupts off */
- memm = 0; /* extend/bank off */
- emir_pending = rest_pending = trap_pending = 0; /* emir,rest,trap off */
- usmd = 0; } /* protect off */
- #endif
-
- if (ion && !ion_defer && int_req) { /* interrupt? */
- old_PC = PC; /* save old PC */
- M[0] = JMS_WORD (usmd); /* save state */
- PC = 1; /* fetch next from 1 */
- ion = 0; /* interrupts off */
- memm = 0; /* extend/bank off */
- emir_pending = rest_pending = 0; /* emir, restore off */
- usmd = 0; } /* protect off */
-
- if (PC == 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; }
-
- /* The following macros implement addressing. They account for autoincrement
- addressing, extended addressing, and memory protection, if it exists.
-
- CHECK_AUTO_INC check auto increment
- INDIRECT indirect addressing
- CHECK_INDEX check indexing
- CHECK_ADDR_R check address for read
- CHECK_ADDR_W check address for write
-
- On the PDP-4 and PDP-7,
- There are autoincrement locations in every field. If a field
- does not exist, it is impossible to generate an
- autoincrement reference (all instructions are CAL).
- Indirect addressing range is determined by extend mode.
- There is no indexing.
- There is no memory protection, nxm reads zero and ignores writes.
- */
-
- #if defined (PDP4) || defined (PDP7)
- #define CHECK_AUTO_INC \
- if ((IR & 017770) == 010) M[MA] = (M[MA] + 1) & 0777777
- #define INDIRECT \
- MA = memm? M[MA] & IAMASK: (MA & epcmask) | (M[MA] & damask)
- #define CHECK_INDEX /* no indexing capability */
- #define CHECK_ADDR_R(x) /* no read protection */
- #define CHECK_ADDR_W(x) \
- if ((x) >= MEMSIZE) break
- #endif
-
- /* On the PDP-9,
- The autoincrement registers are in field zero only. Regardless
- of extend mode, indirect addressing through 00010-00017
- will access absolute locations 00010-00017.
- Indirect addressing range is determined by extend mode. If
- extend mode is off, and autoincrementing is used, the
- resolved address is in bank 0 (KG09B maintenance manual).
- There is no indexing.
- Memory protection is implemented for foreground/background operation.
- */
-
- #if defined (PDP9)
- #define CHECK_AUTO_INC \
- if ((IR & 017770) == 010) { \
- MA = MA & 017; \
- M[MA] = (M[MA] + 1) & 0777777; }
- #define INDIRECT \
- MA = memm? M[MA] & IAMASK: (MA & epcmask) | (M[MA] & damask)
- #define CHECK_ADDR_R(x) \
- if (usmd) { \
- if ((x) >= MEMSIZE) { \
- nexm = prvn = trap_pending = 1; \
- break; } \
- if ((x) >= BR) { \
- prvn = trap_pending = 1; \
- break; } } \
- if ((x) >= MEMSIZE) nexm = 1
- #define CHECK_INDEX /* no indexing capability */
- #define CHECK_ADDR_W(x) \
- CHECK_ADDR_R (x); \
- if ((x) >= MEMSIZE) break
- #endif
-
- /* On the PDP-15,
- The autoincrement registers are in page zero only. Regardless
- of bank mode, indirect addressing through 00010-00017
- will access absolute locations 00010-00017.
- Indirect addressing range is determined by autoincrementing.
- Indexing is available if bank mode is off.
- Memory protection is implemented for foreground/background operation.
- */
-
- #if defined (PDP15)
- #define CHECK_AUTO_INC \
- if ((IR & damask & ~07) == 00010) { \
- MA = MA & 017; \
- M[MA] = (M[MA] + 1) & 0777777; }
- #define INDIRECT \
- if (rest_pending) { \
- rest_pending = 0; \
- LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777); \
- memm = (M[MA] >> 16) & 1; \
- usmd = (M[MA] >> 15) & 1; } \
- MA = ((IR & damask & ~07) != 00010)? \
- (PC & BLKMASK) | (M[MA] & IAMASK): (M[MA] & ADDRMASK)
- #define CHECK_INDEX \
- if ((IR & 0010000) && (memm == 0)) MA = (MA + XR) & ADDRMASK
- #define CHECK_ADDR_R(x) \
- if (usmd) { \
- if ((x) >= MEMSIZE) { \
- nexm = prvn = trap_pending = 1; \
- break; } \
- if ((x) >= BR) { \
- prvn = trap_pending = 1; \
- break; } } \
- if ((x) >= MEMSIZE) nexm = 1
- #define CHECK_ADDR_W(x) \
- CHECK_ADDR_R (x); \
- if ((x) >= MEMSIZE) break
- #endif
-
- /* Fetch, decode instruction */
-
- CHECK_ADDR_R (PC); /* validate PC */
- IR = M[PC]; /* fetch instruction */
- PC = INCR_ADDR (PC); /* increment PC */
- #if defined (PDP9) || defined (PDP15)
- if (!ion_defer) usmd = usmdbuf; /* no IOT? load usmd */
- #endif
- if (ion_defer) ion_defer = ion_defer - 1; /* count down defer */
- xct_count = 0; /* track nested XCT's */
- sim_interval = sim_interval - 1;
-
- xct_instr: /* label for XCT */
- MA = (PC & epcmask) | (IR & damask); /* effective address */
- switch ((IR >> 13) & 037) { /* decode IR<0:4> */
-
- /* LAC: opcode 20 */
-
- case 011: /* LAC, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 010: /* LAC, dir */
- CHECK_INDEX;
- CHECK_ADDR_R (MA);
- LAC = (LAC & 01000000) | M[MA];
- break;
-
- /* DAC: opcode 04 */
-
- case 003: /* DAC, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 002: /* DAC, dir */
- CHECK_INDEX;
- CHECK_ADDR_W (MA);
- M[MA] = LAC & 0777777;
- break;
-
- /* DZM: opcode 14 */
-
- case 007: /* DZM, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 006: /* DZM, direct */
- CHECK_INDEX;
- CHECK_ADDR_W (MA);
- M[MA] = 0;
- break;
-
- /* AND: opcode 50 */
-
- case 025: /* AND, ind */
- CHECK_AUTO_INC;
- INDIRECT;
- case 024: /* AND, dir */
- CHECK_INDEX;
- CHECK_ADDR_R (MA);
- LAC = LAC & (M[MA] | 01000000);
- break;
-
- /* XOR: opcode 24 */
-
- case 013: /* XOR, ind */
- CHECK_AUTO_INC;
- INDIRECT;
- case 012: /* XOR, dir */
- CHECK_INDEX;
- CHECK_ADDR_R (MA);
- LAC = LAC ^ M[MA];
- break;
-
- /* ADD: opcode 30 */
-
- case 015: /* ADD, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 014: /* ADD, dir */
- CHECK_INDEX;
- CHECK_ADDR_R (MA);
- t = (LAC & 0777777) + M[MA];
- if (t > 0777777) t = (t + 1) & 0777777;
- if (((~LAC ^ M[MA]) & (LAC ^ t)) & 0400000) /* overflow? */
- LAC = 01000000 | t; /* set link */
- else LAC = (LAC & 01000000) | t;
- break;
-
- /* TAD: opcode 34 */
-
- case 017: /* TAD, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 016: /* TAD, dir */
- CHECK_INDEX;
- CHECK_ADDR_R (MA);
- LAC = (LAC + M[MA]) & 01777777;
- break;
-
- /* ISZ: opcode 44 */
-
- case 023: /* ISZ, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 022: /* ISZ, dir */
- CHECK_INDEX;
- CHECK_ADDR_W (MA);
- M[MA] = (M[MA] + 1) & 0777777;
- if (M[MA] == 0) PC = INCR_ADDR (PC);
- break;
-
- /* SAD: opcode 54 */
-
- case 027: /* SAD, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 026: /* SAD, dir */
- CHECK_INDEX;
- CHECK_ADDR_R (MA);
- if ((LAC & 0777777) != M[MA]) PC = INCR_ADDR (PC);
- break;
-
- /* XCT: opcode 40 */
-
- case 021: /* XCT, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 020: /* XCT, dir */
- CHECK_INDEX;
- CHECK_ADDR_R (MA);
- if (usmd && (xct_count != 0)) { /* trap and chained? */
- prvn = trap_pending = 1;
- break; }
- if (xct_count >= xct_max) { /* too many XCT's? */
- reason = STOP_XCT;
- break; }
- xct_count = xct_count + 1; /* count XCT's */
- #if defined (PDP9)
- ion_defer = 1; /* defer intr */
- #endif
- IR = M[MA]; /* get instruction */
- goto xct_instr; /* go execute */
-
- /* CAL: opcode 00
-
- On the PDP-4 and PDP-7, CAL (I) is exactly the same as JMS (I) 20
- On the PDP-9, CAL clears user mode
- On the PDP-15, CAL goes to absolute 20, regardless of mode
- */
-
- case 001: case 000: /* CAL */
- t = usmd;
- #if defined (PDP15)
- MA = 020;
- #else
- MA = (memm? 0: PC & epcmask) | 020; /* MA = 20 */
- #endif
- #if defined (PDP9) || defined (PDP15)
- usmd = 0; /* clear user mode */
- #endif
- if (IR & 0020000) { INDIRECT; } /* indirect? */
- CHECK_ADDR_W (MA);
- old_PC = PC;
- M[MA] = JMS_WORD (t); /* save state */
- PC = INCR_ADDR (MA);
- break;
-
- /* JMS: opcode 010 */
-
- case 005: /* JMS, indir */
- CHECK_AUTO_INC;
- INDIRECT;
- case 004: /* JMS, dir */
- CHECK_INDEX;
- CHECK_ADDR_W (MA);
- old_PC = PC;
- M[MA] = JMS_WORD (usmd); /* save state */
- PC = INCR_ADDR (MA);
- break;
-
- /* JMP: opcode 60
-
- Restore quirks:
- On the PDP-7 and PDP-9, EMIR can only clear extend
- On the PDP-15, any I triggers restore, but JMP I is conventional
- */
-
- case 031: /* JMP, indir */
- CHECK_AUTO_INC; /* check auto inc */
- #if defined (PDP7) || defined (PDP9)
- if (emir_pending && (((M[MA] >> 16) & 1) == 0)) memm = 0;
- #elif defined (PDP9)
- if (rest_pending) { /* restore pending? */
- LAC = ((M[MA] << 1) & 01000000) | (LAC & 0777777);
- memm = (M[MA] >> 16) & 1;
- usmd = (M[MA] >> 15) & 1); }
- #endif
- INDIRECT; /* complete indirect */
- emir_pending = rest_pending = 0;
- case 030: /* JMP, dir */
- CHECK_INDEX;
- old_PC = PC; /* save old PC */
- PC = MA;
- break;
-
- /* OPR: opcode 74 */
-
- case 037: /* OPR, indir */
- LAC = (LAC & 01000000) | IR; /* LAW */
- break;
-
- case 036: /* OPR, dir */
- switch ((IR >> 6) & 017) { /* decode IR<8:11> */
- case 0: /* nop */
- break;
- case 1: /* SMA */
- if ((LAC & 0400000) != 0) PC = INCR_ADDR (PC);
- break;
- case 2: /* SZA */
- if ((LAC & 0777777) == 0) PC = INCR_ADDR (PC);
- break;
- case 3: /* SZA | SMA */
- if (((LAC & 0777777) == 0) || ((LAC & 0400000) != 0))
- PC = INCR_ADDR (PC);
- break;
- case 4: /* SNL */
- if (LAC >= 01000000) PC = INCR_ADDR (PC);
- break;
- case 5: /* SNL | SMA */
- if (LAC >= 0400000) PC = INCR_ADDR (PC);
- break;
- case 6: /* SNL | SZA */
- if ((LAC >= 01000000) || (LAC == 0)) PC = INCR_ADDR (PC);
- break;
- case 7: /* SNL | SZA | SMA */
- if ((LAC >= 0400000) || (LAC == 0)) PC = INCR_ADDR (PC);
- break;
- case 010: /* SKP */
- PC = INCR_ADDR (PC);
- break;
- case 011: /* SPA */
- if ((LAC & 0400000) == 0) PC = INCR_ADDR (PC);
- break;
- case 012: /* SNA */
- if ((LAC & 0777777) != 0) PC = INCR_ADDR (PC);
- break;
- case 013: /* SNA & SPA */
- if (((LAC & 0777777) != 0) && ((LAC & 0400000) == 0))
- PC = INCR_ADDR (PC);
- break;
- case 014: /* SZL */
- if (LAC < 01000000) PC = INCR_ADDR (PC);
- break;
- case 015: /* SZL & SPA */
- if (LAC < 0400000) PC = INCR_ADDR (PC);
- break;
- case 016: /* SZL & SNA */
- if ((LAC < 01000000) && (LAC != 0)) PC = INCR_ADDR (PC);
- break;
- case 017: /* SZL & SNA & SPA */
- if ((LAC < 0400000) && (LAC != 0)) PC = INCR_ADDR (PC);
- break; } /* end switch skips */
-
- /* OPR, continued */
-
- switch (((IR >> 9) & 014) | (IR & 03)) { /* IR<5:6,16:17> */
- case 0: /* NOP */
- break;
- case 1: /* CMA */
- LAC = LAC ^ 0777777;
- break;
- case 2: /* CML */
- LAC = LAC ^ 01000000;
- break;
- case 3: /* CML CMA */
- LAC = LAC ^ 01777777;
- break;
- case 4: /* CLL */
- LAC = LAC & 0777777;
- break;
- case 5: /* CLL CMA */
- LAC = (LAC & 0777777) ^ 0777777;
- break;
- case 6: /* CLL CML = STL */
- LAC = LAC | 01000000;
- break;
- case 7: /* CLL CML CMA */
- LAC = (LAC | 01000000) ^ 0777777;
- break;
- case 010: /* CLA */
- LAC = LAC & 01000000;
- break;
- case 011: /* CLA CMA = STA */
- LAC = LAC | 0777777;
- break;
- case 012: /* CLA CML */
- LAC = (LAC & 01000000) ^ 01000000;
- break;
- case 013: /* CLA CML CMA */
- LAC = (LAC | 0777777) ^ 01000000;
- break;
- case 014: /* CLA CLL */
- LAC = 0;
- break;
- case 015: /* CLA CLL CMA */
- LAC = 0777777;
- break;
- case 016: /* CLA CLL CML */
- LAC = 01000000;
- break;
- case 017: /* CLA CLL CML CMA */
- LAC = 01777777;
- break; } /* end decode */
-
- /* OPR, continued */
-
- if (IR & 0000004) { /* OAS */
- #if defined (PDP9) || defined (PDP15)
- if (usmd) prvn = trap_pending = 1;
- else
- #endif
- LAC = LAC | SR; }
-
- switch (((IR >> 8) & 04) | ((IR >> 3) & 03)) { /* decode IR<7,13:14> */
- case 1: /* RAL */
- LAC = ((LAC << 1) | (LAC >> 18)) & 01777777;
- break;
- case 2: /* RAR */
- LAC = ((LAC >> 1) | (LAC << 18)) & 01777777;
- break;
- case 3: /* RAL RAR */
- #if defined (PDP15) /* PDP-15 */
- LAC = (LAC + 1) & 01777777; /* IAC */
- #else /* PDP-4,-7,-9 */
- reason = stop_inst; /* undefined */
- #endif
- break;
- case 5: /* RTL */
- LAC = ((LAC << 2) | (LAC >> 17)) & 01777777;
- break;
- case 6: /* RTR */
- LAC = ((LAC >> 2) | (LAC << 17)) & 01777777;
- break;
- case 7: /* RTL RTR */
- #if defined (PDP15) /* PDP-15 */
- LAC = ((LAC >> 9) & 0777) | ((LAC & 0777) << 9) |
- (LAC & 01000000); /* BSW */
- #else /* PDP-4,-7,-9 */
- reason = stop_inst; /* undefined */
- #endif
- break; } /* end switch rotate */
-
- if (IR & 0000040) { /* HLT */
- if (usmd) prvn = trap_pending = 1;
- else reason = STOP_HALT; }
- break; /* end OPR */
-
- /* EAE: opcode 64
-
- The EAE is microprogrammed to execute variable length signed and
- unsigned shift, multiply, divide, and normalize. Most commands are
- controlled by a six bit step counter (SC). In the hardware, the step
- counter is complemented on load and then counted up to zero; timing
- guarantees an initial increment, which completes the two's complement
- load. In the simulator, the SC is loaded normally and then counted
- down to zero; the read SC command compensates.
- */
-
- case 033: case 032: /* EAE */
- if (cpu_unit.flags & UNIT_NOEAE) break; /* disabled? */
- if (IR & 0020000) /* IR<4>? AC0 to L */
- LAC = ((LAC << 1) & 01000000) | (LAC & 0777777);
- if (IR & 0010000) MQ = 0; /* IR<5>? clear MQ */
- if ((IR & 0004000) && (LAC & 0400000)) /* IR<6> and minus? */
- eae_ac_sign = 01000000; /* set eae_ac_sign */
- else eae_ac_sign = 0; /* if not, unsigned */
- if (IR & 0002000) MQ = (MQ | LAC) & 0777777; /* IR<7>? or AC */
- else if (eae_ac_sign) LAC = LAC ^ 0777777; /* if not, |AC| */
- if (IR & 0001000) LAC = LAC & 01000000; /* IR<8>? clear AC */
- link_init = LAC & 01000000; /* link temporary */
- fill = link_init? 0777777: 0; /* fill = link */
-
- switch ((IR >> 6) & 07) { /* case on IR<9:11> */
- case 0: /* setup */
- if (IR & 04) LAC = LAC ^ 0777777; /* IR<15>? ~AC */
- if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */
- if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */
- break;
-
- case 1: /* multiply */
- CHECK_ADDR_R (PC); /* validate PC */
- MA = M[PC]; /* get next word */
- PC = INCR_ADDR (PC); /* increment PC */
- if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */
- LAC = LAC & 0777777; /* clear link */
- for (SC = IR & 077; SC != 0; SC--) { /* loop per step cnt */
- if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */
- MQ = (MQ >> 1) | ((LAC & 1) << 17);
- LAC = LAC >> 1; } /* shift AC'MQ right */
- if (eae_ac_sign ^ link_init) { /* result negative? */
- LAC = LAC ^ 0777777;
- MQ = MQ ^ 0777777; }
- break;
-
- /* EAE, continued
-
- Divide uses a non-restoring divide. This code duplicates the PDP-7
- algorithm, except for its use of two's complement arithmetic instead
- of 1's complement.
-
- The quotient is generated in one's complement form; therefore, the
- quotient is complemented if the input operands had the same sign
- (that is, if the quotient is positive).
- */
-
- case 3: /* divide */
- CHECK_ADDR_R (PC); /* validate PC */
- MA = M[PC]; /* get next word */
- PC = INCR_ADDR (PC); /* increment PC */
- if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */
- if ((LAC & 0777777) >= MA) { /* overflow? */
- LAC = (LAC - MA) | 01000000; /* set link */
- break; }
- LAC = LAC & 0777777; /* clear link */
- t = 0; /* init loop */
- for (SC = IR & 077; SC != 0; SC--) {
- if (t) LAC = (LAC + MA) & 01777777;
- else LAC = (LAC - MA) & 01777777;
- t = (LAC >> 18) & 1; /* quotient bit */
- if (SC > 1) LAC = /* skip if last */
- ((LAC << 1) | (MQ >> 17)) & 01777777;
- MQ = ((MQ << 1) | t) & 0777777; }
- if (t) LAC = (LAC + MA) & 01777777;
- if (eae_ac_sign) LAC = LAC ^ 0777777; /* sgn rem = sgn divd */
- if (eae_ac_sign ^ ~link_init) MQ = MQ ^ 0777777;
- break;
-
- /* EAE, continued
-
- EAE shifts, whether left or right, fill from the link. If the
- operand sign has been copied to the link, this provides correct
- sign extension for one's complement numbers.
- */
-
- case 4: /* normalize */
- #if defined (PDP15)
- if (!usmd) ion_defer = 2; /* free cycles */
- #endif
- for (SC = IR & 077; ((LAC & 0400000) ==
- ((LAC << 1) & 0400000)) && (SC != 0); SC--) {
- LAC = (LAC << 1) | ((MQ >> 17) & 1);
- MQ = (MQ << 1) | (link_init >> 18); }
- LAC = link_init | (LAC & 0777777); /* trim AC, restore L */
- MQ = MQ & 0777777; /* trim MQ */
- break;
- case 5: /* long right shift */
- t = IR & 077; /* get shift count */
- if (t < 18) {
- MQ = ((LAC << (18 - t)) | (MQ >> t)) & 0777777;
- LAC = ((fill << (18 - t)) | (LAC >> t)) & 01777777; }
- else { if (t < 36) MQ =
- ((fill << (36 - t)) | (LAC >> (t - 18))) & 0777777;
- else MQ = fill;
- LAC = link_init | fill; }
- SC = 0; /* clear step count */
- break;
- case 6: /* long left shift */
- t = IR & 077; /* get shift count */
- if (t < 18) {
- LAC = link_init |
- (((LAC << t) | (MQ >> (18 - t))) & 0777777);
- MQ = ((MQ << t) | (fill >> (18 - t))) & 0777777; }
- else { if (t < 36) LAC = link_init |
- (((MQ << (t - 18)) | (fill >> (36 - t))) & 0777777);
- else LAC = link_init | fill;
- MQ = fill; }
- SC = 0; /* clear step count */
- break;
- case 7: /* AC left shift */
- t = IR & 077; /* get shift count */
- if (t < 18) LAC = link_init |
- (((LAC << t) | (fill >> (18 - t))) & 0777777);
- else LAC = link_init | fill;
- SC = 0; /* clear step count */
- break; } /* end switch IR */
- break; /* end case EAE */
-
- /* PDP-15 index operates: opcode 72 */
-
- case 035: /* index operates */
- #if defined (PDP15)
- t = (IR & 0400)? IR | 0777000: IR & 0377; /* sext immediate */
- switch ((IR >> 9) & 017) { /* case on IR<5:8> */
- case 001: /* PAX */
- XR = LAC & 0777777;
- break;
- case 002: /* PAL */
- LR = LAC & 0777777;
- break;
- case 003:
- LAC = (LAC & 01000000) | ((LAC + t) & 0777777); /* AAC */
- break;
- case 004: /* PXA */
- LAC = (LAC & 01000000) | XR;
- break;
- case 005: /* AXS */
- XR = (XR + t) & 0777777;
- if (SEXT (XR) >= SEXT (LR)) PC = INCR_ADDR (PC);
- break;
- case 006: /* PXL */
- LR = XR;
- break;
- case 010: /* PLA */
- LAC = (LAC & 01000000) | LR;
- break;
- case 011: /* PLX */
- XR = LR;
- break;
- case 015: /* CLX */
- XR = 0;
- break;
- case 016: /* CLL */
- LR = 0;
- break;
- case 017: /* AXR */
- XR = (XR + t) & 0777777;
- break; } /* end switch IR */
- break; /* end case */
- #endif
-
- /* IOT: opcode 70
-
- The 18b PDP's have different definitions of various control IOT's.
-
- IOT PDP-4 PDP-7 PDP-9 PDP-15
-
- 700002 IOF IOF IOF IOF
- 700042 ION ION ION ION
- 700062 undefined ITON undefined undefined
- 701701 undefined undefined MPSK MPSK
- 701741 undefined undefined MPSNE MPSNE
- 701702 undefined undefined MPCV MPCV
- 701742 undefined undefined MPEU MPEU
- 701704 undefined undefined MPLD MPLD
- 701744 undefined undefined MPCNE MPCNE
- 703201 undefined undefined PFSF PFSF
- 703301 undefined TTS TTS TTS
- 703341 undefined SKP7 SKP7 SPCO
- 703302 undefined CAF CAF CAF
- 703344 undefined undefined DBR DBR
- 707701 undefined SEM SEM undefined
- 707741 undefined undefined undefined SKP15
- 707761 undefined undefined undefined SBA
- 707702 undefined EEM EEM undefined
- 707742 undefined EMIR EMIR RES
- 707762 undefined undefined undefined DBA
- 707704 undefined LEM LEM undefined
- 707764 undefined undefined undefined EBA
- */
-
- case 034: /* IOT */
- #if defined (PDP15)
- if (IR & 0010000) { /* floating point? */
- /* PC = fp15 (PC, IR); /* process */
- break; }
- #endif
- if (usmd) { /* user mode? */
- prvn = trap_pending = 1; /* trap */
- break; }
- device = (IR >> 6) & 077; /* device = IR<6:11> */
- pulse = IR & 067; /* pulse = IR<12:17> */
- if (IR & 0000010) LAC = LAC & 01000000; /* clear AC? */
- iot_data = LAC & 0777777; /* AC unchanged */
-
- /* PDP-4 system IOT's */
-
- #if defined (PDP4)
- switch (device) { /* decode IR<6:11> */
- case 0: /* CPU and clock */
- if (pulse == 002) ion = 0; /* IOF */
- else if (pulse == 042) ion = ion_defer = 1; /* ION */
- else iot_data = clk (pulse, iot_data);
- break;
-
- /* PDP-7 system IOT's */
-
- #elif defined (PDP7)
- switch (device) { /* decode IR<6:11> */
- case 0: /* CPU and clock */
- if (pulse == 002) ion = 0; /* IOF */
- else if (pulse == 042) ion = ion_defer = 1; /* ION */
- else if (pulse == 062) /* ITON */
- usmd = ion = ion_defer = 1;
- else iot_data = clk (pulse, iot_data);
- break;
- case 033: /* CPU control */
- if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
- else if (pulse == 002) reset_all (0); /* CAF */
- break;
- case 077: /* extended memory */
- if ((pulse == 001) && memm) PC = INCR_ADDR (PC);
- else if (pulse == 002) memm = 1; /* EEM */
- else if (pulse == 042) /* EMIR */
- memm = emir_pending = 1; /* ext on, restore */
- else if (pulse == 004) memm = 0; /* LEM */
- break;
-
- /* PDP-9 system IOT's */
-
- #elif defined (PDP9)
- ion_defer = 1; /* delay interrupts */
- switch (device) { /* decode IR<6:11> */
- case 000: /* CPU and clock */
- if (pulse == 002) ion = 0; /* IOF */
- else if (pulse == 042) ion = 1; /* ION */
- else iot_data = clk (pulse, iot_data);
- break;
- case 017: /* mem protection */
- if ((pulse == 001) && prvn) PC = INCR_ADDR (PC);
- else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC);
- else if (pulse == 002) prvn = 0;
- else if (pulse == 042) usmdbuf = 1;
- else if (pulse == 004) BR = LAC & 076000;
- else if (pulse == 044) nexm = 0;
- break;
- case 032: /* power fail */
- if ((pulse == 001) && (int_req & INT_PWRFL))
- PC = INCR_ADDR (PC);
- break;
- case 033: /* CPU control */
- if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
- else if (pulse == 002) reset_all (0); /* CAF */
- else if (pulse == 044) rest_pending = 1; /* DBR */
- break;
- case 077: /* extended memory */
- if ((pulse == 001) && memm) PC = INCR_ADDR (PC);
- else if (pulse == 002) memm = 1; /* EEM */
- else if (pulse == 042) /* EMIR */
- memm = emir_pending = 1; /* ext on, restore */
- else if (pulse == 004) memm = 0; /* LEM */
- break;
-
- /* PDP-15 system IOT's */
-
- #elif defined (PDP15)
- ion_defer = 1; /* delay interrupts */
- switch (device) { /* decode IR<6:11> */
- case 000: /* CPU and clock */
- if (pulse == 002) ion = 0; /* IOF */
- else if (pulse == 042) ion = 1; /* ION */
- else iot_data = clk (pulse, iot_data);
- break;
- case 017: /* mem protection */
- if ((pulse == 001) && prvn) PC = INCR_ADDR (PC);
- else if ((pulse == 041) && nexm) PC = INCR_ADDR (PC);
- else if (pulse == 002) prvn = 0;
- else if (pulse == 042) usmdbuf = 1;
- else if (pulse == 004) BR = LAC & 0377400;
- else if (pulse == 044) nexm = 0;
- break;
- case 032: /* power fail */
- if ((pulse == 001) && (int_req & INT_PWRFL))
- PC = INCR_ADDR (PC);
- break;
- case 033: /* CPU control */
- if ((pulse == 001) || (pulse == 041)) PC = INCR_ADDR (PC);
- else if (pulse == 002) reset_all (0); /* CAF */
- else if (pulse == 044) rest_pending = 1; /* DBR */
- break;
- case 077: /* bank addressing */
- if ((pulse == 041) || ((pulse == 061) && memm))
- PC = INCR_ADDR (PC); /* SKP15, SBA */
- else if (pulse == 042) rest_pending = 1; /* RES */
- else if (pulse == 062) memm = 0; /* DBA */
- else if (pulse == 064) memm = 1; /* EBA */
- break;
- #endif
-
- /* IOT, continued */
-
- case 1: /* PTR */
- iot_data = ptr (pulse, iot_data);
- break;
- case 2: /* PTP */
- iot_data = ptp (pulse, iot_data);
- break;
- case 3: /* TTI */
- if (pulse == 004) iot_data = upd_iors ();
- else iot_data = tti (pulse, iot_data);
- break;
- case 4: /* TTO */
- iot_data = tto (pulse, iot_data);
- break;
- #if defined (DRM)
- case 060: /* drum */
- iot_data = drm60 (pulse, iot_data);
- break;
- case 061:
- iot_data = drm61 (pulse, iot_data);
- break;
- case 062:
- iot_data = drm62 (pulse, iot_data);
- break;
- #endif
- #if defined (RP)
- case 063: /* RP15 */
- iot_data = rp63 (pulse, iot_data);
- break;
- case 064:
- iot_data = rp64 (pulse, iot_data);
- break;
- #endif
- case 065: /* LPT */
- iot_data = lpt65 (pulse, iot_data);
- break;
- case 066:
- iot_data = lpt66 (pulse, iot_data);
- break;
- #if defined (RF)
- case 070: /* RF09 */
- iot_data = rf70 (pulse, iot_data);
- break;
- case 072:
- iot_data = rf72 (pulse, iot_data);
- break;
- #endif
- #if defined (MTA)
- case 073: /* TC59 */
- iot_data = mt (pulse, iot_data);
- break;
- #endif
- default: /* unknown device */
- reason = stop_inst; /* stop on flag */
- break; } /* end switch device */
- LAC = LAC | (iot_data & 0777777);
- if (iot_data & IOT_SKP) PC = INCR_ADDR (PC);
- if (iot_data >= IOT_REASON) reason = iot_data >> IOT_V_REASON;
- break; /* end case IOT */
- } /* end switch opcode */
- } /* end while */
-
- /* Simulation halted */
-
- saved_PC = PC & ADDRMASK; /* save copies */
- saved_LAC = LAC & 01777777;
- saved_MQ = MQ & 0777777;
- iors = upd_iors (); /* get IORS */
- return reason;
- }
-
- /* Reset routine */
-
- int cpu_reset (DEVICE *dptr)
- {
- SC = 0;
- eae_ac_sign = 0;
- ion = ion_defer = 0;
- int_req = int_req & ~INT_PWRFL;
- BR = 0;
- memm = usmd = usmdbuf = 0;
- nexm = prvn = trap_pending = 0;
- emir_pending = rest_pending = 0;
- return cpu_svc (&cpu_unit);
- }
-
- /* Process IORS instruction */
-
- int upd_iors (void)
- {
- extern int std_iors (void);
- extern int lpt_iors (void);
- #if defined (DRM)
- extern int drm_iors (void);
- #endif
- #if defined (RF)
- extern int rf_iors (void);
- #endif
- #if defined (RP)
- extern int rp_iors (void);
- #endif
- #if defined (MTA)
- extern int mt_iors (void);
- #endif
-
- return (ion? IOS_ION: 0) |
- #if defined (DRM)
- drm_iors () |
- #endif
- #if defined (RP)
- rp_iors () |
- #endif
- #if defined (RF)
- rf_iors () |
- #endif
- #if defined (MTA)
- mt_iors () |
- #endif
- std_iors () | lpt_iors ();
- }
-
- /* Memory examine */
-
- int cpu_ex (int *vptr, int addr, UNIT *uptr, int sw)
- {
- if (addr >= MEMSIZE) return SCPE_NXM;
- if (vptr != NULL) *vptr = M[addr] & 0777777;
- return SCPE_OK;
- }
-
- /* Memory deposit */
-
- int cpu_dep (int val, int addr, UNIT *uptr, int sw)
- {
- if (addr >= MEMSIZE) return SCPE_NXM;
- M[addr] = val & 0777777;
- return SCPE_OK;
- }
-
- /* Service breakpoint */
-
- int cpu_svc (UNIT *uptr)
- {
- if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
- save_ibkpt = -1;
- return SCPE_OK;
- }
-
- /* Change memory size */
-
- int cpu_set_size (UNIT *uptr, int value)
- {
- int i, mc = 0;
- extern int get_yn (char *ques, int deflt);
-
- if ((value <= 0) || (value > MAXMEMSIZE) || ((value & 07777) != 0))
- return SCPE_ARG;
- for (i = value; i < MEMSIZE; i++) mc = mc | M[i];
- if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
- return SCPE_OK;
- MEMSIZE = value;
- for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
- return SCPE_OK;
- }
-