home *** CD-ROM | disk | FTP | other *** search
- /* nova_cpu.c: NOVA CPU simulator
-
- Copyright (c) 1993, 1994, 1995,
- Robert M Supnik, Digital Equipment Corporation
- Commercial use prohibited
-
- The register state for the NOVA CPU is:
-
- AC[0:3]<0:15> general registers
- C carry flag
- PC<0:14> program counter
-
- The NOVA has three instruction formats: memory reference, I/O transfer,
- and operate. The memory reference format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 0| op | AC |in| mode| displacement | memory reference
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- <0:4> mnemonic action
-
- 00000 JMP PC = MA
- 00001 JMS AC3 = PC, PC = MA
- 00010 ISZ M[MA] = M[MA] + 1, skip if M[MA] == 0
- 00011 DSZ M[MA] = M[MA] - 1, skip if M[MA] == 0
- 001'n LDA ACn = M[MA]
- 010'n STA M[MA] = ACn
-
- <5:7> mode action
-
- 000 page zero direct MA = zext (IR<8:15>)
- 001 PC relative direct MA = PC + sext (IR<8:15>)
- 010 AC2 relative direct MA = AC2 + sext (IR<8:15>)
- 011 AC3 relative direct MA = AC3 + sext (IR<8:15>)
- 100 page zero indirect MA = M[zext (IR<8:15>)]
- 101 PC relative dinirect MA = M[PC + sext (IR<8:15>)]
- 110 AC2 relative indirect MA = M[AC2 + sext (IR<8:15>)]
- 111 AC3 relative indirect MA = M[AC3 + sext (IR<8:15>)]
-
- Memory reference instructions can access an address space of 32K words.
- An instruction can directly reference the first 256 words of memory
- (called page zero), as well as 256 words relative to the PC, AC2, or
- AC3; it can indirectly access all 32K words. If an indirect address
- is in locations 00020-00027, the indirect address is incremented and
- rewritten to memory before use; if in 00030-00037, decremented and
- rewritten.
- */
-
- /* The I/O transfer format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 0 1 1| AC | opcode |pulse| device | I/O transfer
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-
- The IOT instruction sends the opcode, pulse, and specified AC to the
- specified I/O device. The device may accept data, provide data,
- initiate or cancel operations, or skip on status.
-
- The operate format is:
-
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- | 1|srcAC|dstAC| opcode |shift|carry|nl| skip | operate
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- \______/ \___/ \___/ | | | |
- | | | | | | +--- reverse skip sense
- | | | | | +--- skip if C == 0
- | | | | +--- skip if result == 0
- | | | +--- don't load result
- | | +--- carry in (load as is,
- | | set to Zero,
- | | set to One,
- | | load Complement)
- | +--- shift (none,
- | left one,
- | right one,
- | byte swap)
- +--- operation (complement,
- negate,
- move,
- increment,
- add complement,
- subtract,
- add,
- and)
-
- The operate instruction can be microprogrammed to perform operations
- on the source and destination AC's and the Carry flag.
- */
-
- /* This routine is the instruction decode routine for the NOVA.
- 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
- infinite indirection loop
- unknown I/O device and STOP_DEV flag set
- I/O error in I/O simulator
-
- 2. Interrupts. Interrupts are maintained by four parallel variables:
-
- dev_done device done flags
- dev_disable device interrupt disable flags
- dev_busy device busy flags
- int_req interrupt requests
-
- In addition, int_req contains the interrupt enable and ION pending
- flags. If ION and ION pending are set, and at least one interrupt
- request is pending, then an interrupt occurs. Note that the 16b PIO
- mask must be mapped to the simulator's device bit mapping.
-
- 3. Non-existent memory. On the NOVA, 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 need be checked against actual memory size.
-
- 4. Adding I/O devices. These modules must be modified:
-
- nova_defs.h add interrupt request definition
- nova_cpu.c add IOT mask, PI mask, and routine to dev_table
- nova_sys.c add pointer to data structures to sim_devices
- */
-
- #include "nova_defs.h"
-
- #define ILL_ADR_FLAG 0100000
- #define save_ibkpt (cpu_unit.u3)
- #define UNIT_V_MDV (UNIT_V_UF) /* MDV absent */
- #define UNIT_MDV (1 << UNIT_V_MDV)
- #define UNIT_V_MSIZE (UNIT_V_UF+1) /* dummy mask */
- #define UNIT_MSIZE (1 << UNIT_V_MSIZE)
-
- unsigned short M[MAXMEMSIZE] = { 0 }; /* memory */
- int AC[4] = { 0 }; /* accumulators */
- int C = 0; /* carry flag */
- int saved_PC = 0; /* program counter */
- int SR = 0; /* switch register */
- int dev_done = 0; /* device done flags */
- int dev_busy = 0; /* device busy flags */
- int dev_disable = 0; /* int disable flags */
- int int_req = 0; /* interrupt requests */
- int pimask = 0; /* priority int mask */
- int pwr_low = 0; /* power fail flag */
- int ind_max = 16; /* iadr nest limit */
- int stop_dev = 0; /* stop on ill dev */
- int ibkpt_addr = ILL_ADR_FLAG | ADDRMASK; /* breakpoint addr */
- int old_PC = 0; /* previous PC */
-
- 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);
- extern int ptr (int pulse, int code, int AC);
- extern int ptp (int pulse, int code, int AC);
- extern int tti (int pulse, int code, int AC);
- extern int tto (int pulse, int code, int AC);
- extern int clk (int pulse, int code, int AC);
- extern int lpt (int pulse, int code, int AC);
- extern int dsk (int pulse, int code, int AC);
- extern int dkp (int pulse, int code, int AC);
- extern int mta (int pulse, int code, int AC);
- int nulldev (int pulse, int code, int AC);
-
- /* IOT dispatch table */
-
- struct ndev dev_table[64] = {
- { 0, 0, &nulldev }, { 0, 0, &nulldev }, /* 0 - 7 */
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { INT_TTI, PI_TTI, &tti }, { INT_TTO, PI_TTO, &tto }, /* 10 - 17 */
- { INT_PTR, PI_PTR, &ptr }, { INT_PTP, PI_PTP, &ptp },
- { INT_CLK, PI_CLK, &clk }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { INT_LPT, PI_LPT, &lpt },
- { INT_DSK, PI_DSK, &dsk }, { 0, 0, &nulldev }, /* 20 - 27 */
- { INT_MTA, PI_MTA, &mta }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev }, /* 30 - 37 */
- { 0, 0, &nulldev }, {INT_DKP, PI_DKP, &dkp },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev }, /* 40 - 47 */
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev }, /* 50 - 57 */
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev }, /* 60 - 67 */
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev }, /* 70 - 77 */
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev },
- { 0, 0, &nulldev }, { 0, 0, &nulldev } };
-
- /* CPU data structures
-
- cpu_dev CPU device descriptor
- cpu_unit CPU unit descriptor
- cpu_reg CPU register list
- cpu_mod CPU modifiers list
- */
-
- UNIT cpu_unit = { UDATA (&cpu_svc, UNIT_FIX+UNIT_MDV, MAXMEMSIZE) };
-
- REG cpu_reg[] = {
- { ORDATA (PC, saved_PC, 15) },
- { ORDATA (AC0, AC[0], 16) },
- { ORDATA (AC1, AC[1], 16) },
- { ORDATA (AC2, AC[2], 16) },
- { ORDATA (AC3, AC[3], 16) },
- { FLDATA (C, C, 16) },
- { ORDATA (SR, SR, 16) },
- { ORDATA (PI, pimask, 16) },
- { FLDATA (ION, int_req, INT_V_ION) },
- { FLDATA (ION_DELAY, int_req, INT_V_NO_ION_PENDING) },
- { FLDATA (PWR, pwr_low, 0) },
- { ORDATA (INT, int_req, INT_V_ION+1), REG_RO },
- { ORDATA (BUSY, dev_busy, INT_V_ION+1), REG_RO },
- { ORDATA (DONE, dev_done, INT_V_ION+1), REG_RO },
- { ORDATA (DISABLE, dev_disable, INT_V_ION+1), REG_RO },
- { FLDATA (STOP_DEV, stop_dev, 0) },
- { FLDATA (MDV, cpu_unit.flags, UNIT_V_MDV), REG_HRO },
- { DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
- { ORDATA (OLDPC, old_PC, 15), REG_RO },
- { ORDATA (BREAK, ibkpt_addr, 16) },
- { ORDATA (WRU, sim_int_char, 8) },
- { NULL } };
-
- MTAB cpu_mod[] = {
- { UNIT_MDV, UNIT_MDV, "MDV", "MDV", NULL },
- { UNIT_MDV, 0, "no MDV", "NOMDV", NULL },
- { UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
- { UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
- { 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 },
- { 0 } };
-
- DEVICE cpu_dev = {
- "CPU", &cpu_unit, cpu_reg, cpu_mod,
- 1, 8, 15, 1, 8, 16,
- &cpu_ex, &cpu_dep, &cpu_reset,
- NULL, NULL, NULL };
-
- int sim_instr (void)
- {
- extern int sim_interval;
- register int PC, IR, i, t, reason;
- extern int sim_process_event (void);
- extern int sim_activate (UNIT *uptr, int interval);
- extern int reset_all (int starting_device);
- void mask_out (int mask);
-
- /* Restore register state */
-
- PC = saved_PC & ADDRMASK; /* load local PC */
- C = C & 0200000;
- mask_out (pimask); /* reset int system */
- 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? */
- register int MA;
- int_req = int_req & ~INT_ION;
- old_PC = M[0] = PC;
- MA = M[1];
- for (i = 0; i < ind_max; i++) { /* count indirects */
- if ((MA & 0100000) == 0) break;
- if ((MA & 077770) == 020)
- MA = (M[MA] = (M[MA] + 1) & 0177777);
- else if ((MA & 077770) == 030)
- MA = (M[MA] = (M[MA] - 1) & 0177777);
- else MA = M[MA]; }
- if (i >= ind_max) {
- reason = STOP_IND_INT;
- break; }
- PC = MA; } /* end interrupt */
-
- if (PC == ibkpt_addr) { /* breakpoint? */
- save_ibkpt = ibkpt_addr; /* save address */
- ibkpt_addr = ibkpt_addr | ILL_ADR_FLAG; /* disable */
- sim_activate (&cpu_unit, 1); /* sched re-enable */
- reason = STOP_IBKPT; /* stop simulation */
- break; }
-
- IR = M[PC]; /* fetch instr */
- PC = (PC + 1) & ADDRMASK;
- int_req = int_req | INT_NO_ION_PENDING; /* clear ION delay */
- sim_interval = sim_interval - 1;
- t = IR >> 11; /* prepare to decode */
-
- /* Memory reference instructions */
-
- if (t < 014) { /* mem ref? */
- register int src, MA;
- MA = IR & 0377;
- switch ((IR >> 8) & 03) { /* decode IR<6:7> */
- case 0: /* page zero */
- break;
- case 1: /* PC relative */
- if (MA & 0200) MA = 077400 | MA;
- MA = (MA + PC - 1) & ADDRMASK;
- break;
- case 2: /* AC2 relative */
- if (MA & 0200) MA = 077400 | MA;
- MA = (MA + AC[2]) & ADDRMASK;
- break;
- case 3: /* AC3 relative */
- if (MA & 0200) MA = 077400 | MA;
- MA = (MA + AC[3]) & ADDRMASK;
- break; } /* end switch mode */
-
- if (IR & 002000) { /* indirect? */
- for (i = 0; i < ind_max; i++) { /* count indirects */
- if ((MA & 077770) == 020)
- MA = (M[MA] = (M[MA] + 1) & 0177777);
- else if ((MA & 077770) == 030)
- MA = (M[MA] = (M[MA] - 1) & 0177777);
- else MA = M[MA];
- if ((MA & 0100000) == 0) break; }
- if (i >= ind_max) {
- reason = STOP_IND;
- break; } }
-
- /* Memory reference, continued */
-
- switch (t) { /* decode IR<1:4> */
- case 001: /* JSR */
- AC[3] = PC;
- case 000: /* JMP */
- old_PC = PC;
- PC = MA;
- break;
- case 002: /* ISZ */
- src = (M[MA] + 1) & 0177777;
- if (MEM_ADDR_OK (MA)) M[MA] = src;
- if (src == 0) PC = (PC + 1) & ADDRMASK;
- break;
- case 003: /* DSZ */
- src = (M[MA] - 1) & 0177777;
- if (MEM_ADDR_OK (MA)) M[MA] = src;
- if (src == 0) PC = (PC + 1) & ADDRMASK;
- break;
- case 004: /* LDA 0 */
- AC[0] = M[MA];
- break;
- case 005: /* LDA 1 */
- AC[1] = M[MA];
- break;
- case 006: /* LDA 2 */
- AC[2] = M[MA];
- break;
- case 007: /* LDA 3 */
- AC[3] = M[MA];
- break;
- case 010: /* STA 0 */
- if (MEM_ADDR_OK (MA)) M[MA] = AC[0];
- break;
- case 011: /* STA 1 */
- if (MEM_ADDR_OK (MA)) M[MA] = AC[1];
- break;
- case 012: /* STA 2 */
- if (MEM_ADDR_OK (MA)) M[MA] = AC[2];
- break;
- case 013: /* STA 3 */
- if (MEM_ADDR_OK (MA)) M[MA] = AC[3];
- break; } /* end switch */
- } /* end mem ref */
-
- /* Operate instruction */
-
- else if (t & 020) { /* operate? */
- register int src, srcAC, dstAC;
- srcAC = (t >> 2) & 3; /* get reg decodes */
- dstAC = t & 03;
- switch ((IR >> 4) & 03) { /* decode IR<10:11> */
- case 0: /* load */
- src = AC[srcAC] | C;
- break;
- case 1: /* clear */
- src = AC[srcAC];
- break;
- case 2: /* set */
- src = AC[srcAC] | 0200000;
- break;
- case 3: /* complement */
- src = AC[srcAC] | (C ^ 0200000);
- break; } /* end switch carry */
- switch ((IR >> 8) & 07) { /* decode IR<5:7> */
- case 0: /* COM */
- src = src ^ 0177777;
- break;
- case 1: /* NEG */
- src = ((src ^ 0177777) + 1) & 0377777;
- break;
- case 2: /* MOV */
- break;
- case 3: /* INC */
- src = (src + 1) & 0377777;
- break;
- case 4: /* ADC */
- src = ((src ^ 0177777) + AC[dstAC]) & 0377777;
- break;
- case 5: /* SUB */
- src = ((src ^ 0177777) + AC[dstAC] + 1) & 0377777;
- break;
- case 6: /* ADD */
- src = (src + AC[dstAC]) & 0377777;
- break;
- case 7: /* AND */
- src = src & (AC[dstAC] | 0200000);
- break; } /* end switch oper */
-
- /* Operate, continued */
-
- switch ((IR >> 6) & 03) { /* decode IR<8:9> */
- case 0: /* nop */
- break;
- case 1: /* L */
- src = ((src << 1) | (src >> 16)) & 0377777;
- break;
- case 2: /* R */
- src = ((src >> 1) | (src << 16)) & 0377777;
- break;
- case 3: /* S */
- src = ((src & 0377) << 8) | ((src >> 8) & 0377) |
- (src & 0200000);
- break; } /* end switch shift */
- switch (IR & 07) { /* decode IR<13:15> */
- case 0: /* nop */
- break;
- case 1: /* SKP */
- PC = (PC + 1) & ADDRMASK;
- break;
- case 2: /* SZC */
- if (src < 0200000) PC = (PC + 1) & ADDRMASK;
- break;
- case 3: /* SNC */
- if (src >= 0200000) PC = (PC + 1) & ADDRMASK;
- break;
- case 4: /* SZR */
- if ((src & 0177777) == 0) PC = (PC + 1) & ADDRMASK;
- break;
- case 5: /* SNR */
- if ((src & 0177777) != 0) PC = (PC + 1) & ADDRMASK;
- break;
- case 6: /* SEZ */
- if (src <= 0200000) PC = (PC + 1) & ADDRMASK;
- break;
- case 7: /* SBN */
- if (src > 0200000) PC = (PC + 1) & ADDRMASK;
- break; } /* end switch skip */
- if ((IR & 000010) == 0) { /* load? */
- AC[dstAC] = src & 0177777;
- C = src & 0200000; } /* end if load */
- } /* end if operate */
-
- /* IOT instruction */
-
- else { /* IOT */
- register int dstAC, pulse, code, device, iodata;
- dstAC = t & 03; /* decode fields */
- code = (IR >> 8) & 07;
- pulse = (IR >> 6) & 03;
- device = IR & 077;
- if (code == ioSKP) { /* IO skip? */
- switch (pulse) { /* decode IR<8:9> */
- case 0: /* skip if busy */
- if ((device == 077)? (int_req & INT_ION) != 0:
- (dev_busy & dev_table[device].mask) != 0)
- PC = (PC + 1) & ADDRMASK;
- break;
- case 1: /* skip if not busy */
- if ((device == 077)? (int_req & INT_ION) == 0:
- (dev_busy & dev_table[device].mask) == 0)
- PC = (PC + 1) & ADDRMASK;
- break;
- case 2: /* skip if done */
- if ((device == 077)? pwr_low != 0:
- (dev_done & dev_table[device].mask) != 0)
- PC = (PC + 1) & ADDRMASK;
- break;
- case 3: /* skip if not done */
- if ((device == 077)? pwr_low == 0:
- (dev_done & dev_table[device].mask) == 0)
- PC = (PC + 1) & ADDRMASK;
- break; } /* end switch */
- } /* end IO skip */
-
- else if ((device == DEV_MDV) && (dstAC == 2) &&
- (code == ioDOC) && (cpu_unit.flags && UNIT_MDV)) {
- register unsigned int mddata, uAC0, uAC1, uAC2;
- uAC0 = (unsigned int) AC[0];
- uAC1 = (unsigned int) AC[1];
- uAC2 = (unsigned int) AC[2];
-
- if (pulse == iopP) { /* mul */
- mddata = (uAC1 * uAC2) + uAC0;
- AC[0] = (mddata >> 16) & 0177777;
- AC[1] = mddata & 0177777; }
- else if (pulse == iopS) { /* divide */
- if (uAC0 >= uAC2) C = 0200000;
- else { C = 0;
- mddata = (uAC0 << 16) | uAC1;
- AC[1] = mddata / uAC2;
- AC[0] = mddata % uAC2; } }
- } /* end mul/div */
-
- /* IOT, continued */
-
- else if (device == DEV_CPU) { /* CPU control */
- switch (code) { /* decode IR<5:7> */
- case ioDIA: /* read switches */
- AC[dstAC] = SR;
- break;
- case ioDIB: /* int ack */
- AC[dstAC] = 0;
- int_req = (int_req & ~INT_DEV) |
- (dev_done & ~dev_disable);
- iodata = int_req & (-int_req);
- for (i = DEV_LOW; i <= DEV_HIGH; i++) {
- if (iodata & dev_table[i].mask) {
- AC[dstAC] = i; break; } }
- break;
- case ioDOB: /* mask out */
- mask_out (pimask = AC[dstAC]);
- break;
- case ioDIC: /* io reset */
- reset_all (0); /* reset devices */
- break;
- case ioDOC: /* halt */
- reason = STOP_HALT;
- break; } /* end switch code */
- switch (pulse) { /* decode IR<8:9> */
- case iopS: /* ion */
- int_req = (int_req | INT_ION) & ~INT_NO_ION_PENDING;
- break;
- case iopC: /* iof */
- int_req = int_req & ~INT_ION;
- break; } /* end switch pulse */
- } /* end CPU control */
- else { /* normal device */
- iodata = dev_table[device].routine (pulse, code, AC[dstAC]);
- reason = iodata >> IOT_V_REASON;
- if (code & 1) AC[dstAC] = iodata & 0177777; }
- } /* end if IOT */
- } /* end while */
-
- /* Simulation halted */
-
- saved_PC = PC;
- return reason;
- }
-
- /* Null device */
-
- int nulldev (int pulse, int code, int AC)
- {
- return stop_dev << IOT_V_REASON;
- }
-
- /* New priority mask out */
-
- void mask_out (int newmask)
- {
- int i;
-
- dev_disable = 0;
- for (i = DEV_LOW; i <= DEV_HIGH; i++) {
- if (newmask & dev_table[i].pi)
- dev_disable = dev_disable | dev_table[i].mask; }
- int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
- return;
- }
-
- /* Reset routine */
-
- int cpu_reset (DEVICE *dptr)
- {
- C = 0;
- int_req = int_req & ~INT_ION;
- pimask = 0;
- dev_disable = 0;
- pwr_low = 0;
- return cpu_svc (&cpu_unit);
- }
-
- /* 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] & 0177777;
- 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 & 0177777;
- return SCPE_OK;
- }
-
- /* Breakpoint service */
-
- int cpu_svc (UNIT *uptr)
- {
- if ((ibkpt_addr & ~ILL_ADR_FLAG) == save_ibkpt) ibkpt_addr = save_ibkpt;
- save_ibkpt = -1;
- return SCPE_OK;
- }
-
- 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;
- }
-