RESTRICTION: The HP DS disk is not debugged. DO NOT enable this feature for normal operations. WARNING: Massive changes in the PDP-11 make all previous SAVEd file obsolete. Do not attempt to use a PDP-11 SAVE file from a prior release with V3.3! 1. New Features in 3.3 1.1 SCP - Added -p (powerup) qualifier to RESET - Changed SET <unit> ONLINE/OFFLINE to SET <unit> ENABLED/DISABLED - Moved SET DEBUG under SET CONSOLE hierarchy - Added optional parameter value to SHOW command - Added output file option to SHOW command 1.2 PDP-11 - Separated RH Massbus adapter from RP controller - Added TU tape support - Added model emulation framework - Added model details 1.3 VAX - Separated out CVAX-specific features from core instruction simulator - Implemented capability for CIS, octaword, compatibility mode instructions - Added instruction display and parse for compatibility mode - Changed SET CPU VIRTUAL=n to SHOW CPU VIRTUAL=n - Added =n optional parameter to SHOW CPU HISTORY 1.4 Unibus/Qbus simulators (PDP-11, VAX, PDP-10) - Simplified DMA API's - Modified DMA peripherals to use simplified API's 1.5 HP2100 (all changes from Dave Bryan) CPU - moved MP into its own device; added MP option jumpers - modified DMA to allow disabling - modified SET CPU 2100/2116 to truncate memory > 32K - added -F switch to SET CPU to force memory truncation - modified WRU to be REG_HRO - added BRK and DEL to save console settings DR - provided protected tracks and "Writing Enabled" status bit - added "parity error" status return on writes for 12606 - added track origin test for 12606 - added SCP test for 12606 - added "Sector Flag" status bit - added "Read Inhibit" status bit for 12606 - added TRACKPROT modifier LPS - added SET OFFLINE/ONLINE, POWEROFF/POWERON - added fast/realistic timing - added debug printouts LPT - added SET OFFLINE/ONLINE, POWEROFF/POWERON PTR - added paper tape loop mode, DIAG/READER modifiers to PTR - added PV_LEFT to PTR TRLLIM register CLK - modified CLK to permit disable 1.6 IBM 1401, IBM 1620, Interdata 16b, SDS 940, PDP-10 - Added instruction history 1.7 H316, PDP-15, PDP-8 - Added =n optional value to SHOW CPU HISTORY 2. Bugs Fixed in 3.3 2.1 SCP - Fixed comma-separated SET options (from Dave Bryan) - Fixed duplicate HELP displays with user-specified commands 2.2 PDP-10 - Replicated RP register state per drive - Fixed TU to set FCE on short record - Fixed TU to return bit<15> in drive type - Fixed TU format specification, 1:0 are don't cares - Fixed TU handling of TMK status - Fixed TU handling of DONE, ATA at end of operation - Implemented TU write check 2.3 PDP-11 - Replicated RP register state per drive - Fixed RQ, TQ to report correct controller type and stage 1 configuration flags on a Unibus system - Fixed HK CS2<output_ready> flag 2.4 VAX - Fixed parsing of indirect displacement modes in instruction input 2.5 HP2100 (all fixes from Dave Bryan) CPU - fixed S-register behavior on 2116 - fixed LIx/MIx behavior for DMA on 2116 and 2100 - fixed LIx/MIx behavior for empty I/O card slots DP - fixed enable/disable from either device - fixed ANY ERROR status for 12557A interface - fixed unattached drive status for 12557A interface - status cmd without prior STC DC now completes (12557A) - OTA/OTB CC on 13210A interface also does CLC CC - fixed RAR model - fixed seek check on 13210 if sector out of range DQ - fixed enable/disable from either device - shortened xtime from 5 to 3 (drive avg 156KW/second) - fixed not ready/any error status - fixed RAR model DR - fixed enable/disable from either device - fixed sector return in status word - fixed DMA last word write, incomplete sector fill value - fixed 12610 SFC operation - fixed current-sector determination IPL - fixed enable/disable from either device LPS - fixed status returns for error conditions - fixed handling of non-printing characters - fixed handling of characters after column 80 - improved timing model accuracy for RTE LPT - fixed status returns for error conditions - fixed TOF handling so form remains on line 0 SYS - fixed display of CCA/CCB/CCE instructions 2.5 PDP-15 FPP - fixed URFST to mask low 9b of fraction - fixed exception PC setting
1020 lines
31 KiB
C
1020 lines
31 KiB
C
/* vax_cmode.c: VAX compatibility mode
|
||
|
||
Copyright (c) 2004, Robert M Supnik
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a
|
||
copy of this software and associated documentation files (the "Software"),
|
||
to deal in the Software without restriction, including without limitation
|
||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
and/or sell copies of the Software, and to permit persons to whom the
|
||
Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||
in this Software without prior written authorization from Robert M Supnik.
|
||
|
||
On a full VAX, this module implements PDP-11 compatibility mode.
|
||
On a subset VAX, this module forces a fault if REI attempts to set PSL<cm>.
|
||
|
||
24-Aug-04 RMS Cloned from PDP-11 CPU
|
||
|
||
In compatibility mode, the Istream prefetch mechanism is not used. The
|
||
prefetcher will be explicitly resynchronized through intexc on any exit
|
||
from compatibility mode.
|
||
*/
|
||
|
||
#include "vax_defs.h"
|
||
|
||
#if defined (FULL_VAX)
|
||
|
||
#define RdMemB(a) Read (a, L_BYTE, RA)
|
||
#define RdMemMB(a) Read (a, L_BYTE, WA)
|
||
#define WrMemB(d,a) Write (a, d, L_BYTE, WA)
|
||
#define BRANCH_F(x) CMODE_JUMP ((PC + (((x) + (x)) & BMASK)) & WMASK)
|
||
#define BRANCH_B(x) CMODE_JUMP ((PC + (((x) + (x)) | 0177400)) & WMASK)
|
||
#define CC_XOR_NV(x) ((((x) & CC_N) != 0) ^ (((x) & CC_V) != 0))
|
||
#define CC_XOR_NC(x) ((((x) & CC_N) != 0) ^ (((x) & CC_C) != 0))
|
||
|
||
extern int32 R[16];
|
||
extern int32 PSL;
|
||
extern int32 trpirq;
|
||
extern int32 p1;
|
||
extern int32 fault_PC;
|
||
extern int32 recq[]; /* recovery queue */
|
||
extern int32 recqptr; /* recq pointer */
|
||
extern int32 pcq[];
|
||
extern int32 pcq_p;
|
||
extern int32 ibcnt, ppc;
|
||
extern int32 sim_interval;
|
||
extern int32 sim_brk_summ;
|
||
|
||
extern int32 Read (uint32 va, int32 lnt, int32 access);
|
||
extern void Write (uint32 va, int32 val, int32 lnt, int32 access);
|
||
extern jmp_buf save_env;
|
||
|
||
int32 GeteaB (int32 spec);
|
||
int32 GeteaW (int32 spec);
|
||
int32 RdMemW (int32 a);
|
||
int32 RdMemMW (int32 a);
|
||
void WrMemW (int32 d, int32 a);
|
||
int32 RdRegB (int32 rn);
|
||
int32 RdRegW (int32 rn);
|
||
void WrRegB (int32 val, int32 rn);
|
||
void WrRegW (int32 val, int32 rn);
|
||
|
||
/* Validate PSL for compatibility mode */
|
||
|
||
t_bool BadCmPSL (int32 newpsl)
|
||
{
|
||
if ((newpsl & (PSL_FPD|PSL_IS|PSL_CUR|PSL_PRV|PSL_IPL)) !=
|
||
((USER << PSL_V_CUR) | (USER << PSL_V_PRV)))
|
||
return TRUE;
|
||
else return FALSE;
|
||
}
|
||
|
||
/* Compatibility mode execution */
|
||
|
||
int32 op_cmode (int32 cc)
|
||
{
|
||
int32 IR, srcspec, dstspec, srcreg, dstreg, ea;
|
||
int32 i, t, src, src2, dst, sign, oc;
|
||
int32 acc = ACC_MASK (USER);
|
||
|
||
PC = PC & WMASK; /* PC must be 16b */
|
||
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||
ABORT (STOP_IBKPT); } /* stop simulation */
|
||
sim_interval = sim_interval - 1; /* count instr */
|
||
|
||
IR = RdMemW (PC); /* fetch instruction */
|
||
PC = (PC + 2) & WMASK; /* incr PC, mod 65k */
|
||
srcspec = (IR >> 6) & 077; /* src, dst specs */
|
||
dstspec = IR & 077;
|
||
srcreg = (srcspec <= 07); /* src, dst = rmode? */
|
||
dstreg = (dstspec <= 07);
|
||
switch ((IR >> 12) & 017) { /* decode IR<15:12> */
|
||
|
||
/* Opcode 0: no operands, specials, branches, JSR, SOPs */
|
||
|
||
case 000: /* 00xxxx */
|
||
switch ((IR >> 6) & 077) { /* decode IR<11:6> */
|
||
case 000: /* 0000xx */
|
||
switch (IR) { /* decode IR<5:0> */
|
||
case 3: /* BPT */
|
||
CMODE_FAULT (CMODE_BPT);
|
||
break;
|
||
case 4: /* IOT */
|
||
CMODE_FAULT (CMODE_IOT);
|
||
break;
|
||
case 2: /* RTI */
|
||
case 6: /* RTT */
|
||
src = RdMemW (R[6] & WMASK); /* new PC */
|
||
src2 = RdMemW ((R[6] + 2) & WMASK); /* new PSW */
|
||
R[6] = (R[6] + 4) & WMASK;
|
||
cc = src2 & CC_MASK; /* update cc, T */
|
||
if (src2 & PSW_T) PSL = PSL | PSW_T;
|
||
else PSL = PSL & ~PSW_T;
|
||
CMODE_JUMP (src); /* update PC */
|
||
break;
|
||
default: /* undefined */
|
||
CMODE_FAULT (CMODE_RSVI);
|
||
break;
|
||
} /* end switch IR */
|
||
break; /* end case 0000xx */
|
||
|
||
/* Opcode 0: specials, continued */
|
||
|
||
case 001: /* JMP */
|
||
if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */
|
||
else { CMODE_JUMP (GeteaW (dstspec)); }
|
||
break;
|
||
case 002: /* 0002xx */
|
||
if (IR < 000210) { /* RTS */
|
||
dstspec = dstspec & 07;
|
||
if (dstspec != 7) { /* PC <- r */
|
||
CMODE_JUMP (RdRegW (dstspec));
|
||
}
|
||
dst = RdMemW (R[6]); /* t <- (sp)+ */
|
||
R[6] = (R[6] + 2) & WMASK;
|
||
WrRegW (dst, dstspec); /* r <- t */
|
||
break; } /* end if RTS */
|
||
if (IR < 000240) { /* [210:237] */
|
||
CMODE_FAULT (CMODE_RSVI);
|
||
break;
|
||
}
|
||
if (IR < 000260) cc = cc & ~(IR & CC_MASK); /* clear CC */
|
||
else cc = cc | (IR & CC_MASK); /* set CC */
|
||
break;
|
||
case 003: /* SWAB */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = ((src & 0xFF) << 8) | ((src >> 8) & 0xFF);
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_B ((dst & BMASK));
|
||
break;
|
||
|
||
/* Opcode 0: branches, JSR */
|
||
|
||
case 004: case 005: /* BR */
|
||
BRANCH_F (IR);
|
||
break;
|
||
case 006: case 007: /* BR */
|
||
BRANCH_B (IR);
|
||
break;
|
||
case 010: case 011: /* BNE */
|
||
if ((cc & CC_Z) == 0) { BRANCH_F (IR); }
|
||
break;
|
||
case 012: case 013: /* BNE */
|
||
if ((cc & CC_Z) == 0) { BRANCH_B (IR); }
|
||
break;
|
||
case 014: case 015: /* BEQ */
|
||
if (cc & CC_Z) { BRANCH_F (IR); }
|
||
break;
|
||
case 016: case 017: /* BEQ */
|
||
if (cc & CC_Z) { BRANCH_B (IR); }
|
||
break;
|
||
case 020: case 021: /* BGE */
|
||
if (CC_XOR_NV (cc) == 0) { BRANCH_F (IR); }
|
||
break;
|
||
case 022: case 023: /* BGE */
|
||
if (CC_XOR_NV (cc) == 0) { BRANCH_B (IR); }
|
||
break;
|
||
case 024: case 025: /* BLT */
|
||
if (CC_XOR_NV (cc)) { BRANCH_F (IR); }
|
||
break;
|
||
case 026: case 027: /* BLT */
|
||
if (CC_XOR_NV (cc)) { BRANCH_B (IR); }
|
||
break;
|
||
case 030: case 031: /* BGT */
|
||
if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_F (IR); }
|
||
break;
|
||
case 032: case 033: /* BGT */
|
||
if (((cc & CC_Z) || CC_XOR_NV (cc)) == 0) { BRANCH_B (IR); }
|
||
break;
|
||
case 034: case 035: /* BLE */
|
||
if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_F (IR); }
|
||
break;
|
||
case 036: case 037: /* BLE */
|
||
if ((cc & CC_Z) || CC_XOR_NV (cc)) { BRANCH_B (IR); }
|
||
break;
|
||
case 040: case 041: case 042: case 043: /* JSR */
|
||
case 044: case 045: case 046: case 047:
|
||
if (dstreg) CMODE_FAULT (CMODE_ILLI); /* mode 0 illegal */
|
||
else {
|
||
srcspec = srcspec & 07; /* get reg num */
|
||
dst = GeteaW (dstspec); /* get dst addr */
|
||
src = RdRegW (srcspec); /* get src reg */
|
||
WrMemW (src, (R[6] - 2) & WMASK); /* -(sp) <- r */
|
||
R[6] = (R[6] - 2) & WMASK;
|
||
if (srcspec != 7) R[srcspec] = PC; /* r <- PC */
|
||
CMODE_JUMP (dst); /* PC <- dst */
|
||
}
|
||
break; /* end JSR */
|
||
|
||
/* Opcode 0: SOPs */
|
||
|
||
case 050: /* CLR */
|
||
if (dstreg) WrRegW (0, dstspec);
|
||
else WrMemW (0, GeteaW (dstspec));
|
||
cc = CC_Z;
|
||
break;
|
||
case 051: /* COM */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = src ^ WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
cc = cc | CC_C;
|
||
break;
|
||
case 052: /* INC */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src + 1) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZP_W (dst);
|
||
if (dst == 0100000) cc = cc | CC_V;
|
||
break;
|
||
case 053: /* DEC */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src - 1) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZP_W (dst);
|
||
if (dst == 077777) cc = cc | CC_V;
|
||
break;
|
||
case 054: /* NEG */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (-src) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if (dst == 0100000) cc = cc | CC_V;
|
||
if (dst) cc = cc | CC_C;
|
||
break;
|
||
case 055: /* ADC */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src + (cc & CC_C)) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if ((src == 077777) && (dst == 0100000)) cc = cc | CC_V;
|
||
if ((src == 0177777) && (dst == 0)) cc = cc | CC_C;
|
||
break;
|
||
case 056: /* SBC */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src - (cc & CC_C)) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if ((src == 0100000) && (dst == 077777)) cc = cc | CC_V;
|
||
if ((src == 0) && (dst == 0177777)) cc = cc | CC_C;
|
||
break;
|
||
case 057: /* TST */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemW (GeteaW (dstspec));
|
||
CC_IIZZ_W (src);
|
||
break;
|
||
case 060: /* ROR */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src >> 1) | ((cc & CC_C)? WSIGN: 0);
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if (src & 1) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 061: /* ROL */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if (src & WSIGN) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 062: /* ASR */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src & WSIGN) | (src >> 1);
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if (src & 1) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 063: /* ASL */
|
||
if (dstreg) src = RdRegW (dstspec);
|
||
else src = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src << 1) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if (src & WSIGN) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 065: /* MFPI */
|
||
if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */
|
||
else dst = RdMemW (GeteaW (dstspec));
|
||
WrMemW (dst, (R[6] - 2) & WMASK);
|
||
R[6] = (R[6] - 2) & WMASK;
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
case 066: /* MTPI */
|
||
dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */
|
||
R[6] = (R[6] + 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (AIN|RW, 6);
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, (GeteaW (dstspec) & WMASK));
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
default: /* undefined */
|
||
CMODE_FAULT (CMODE_RSVI);
|
||
break;
|
||
} /* end switch SOPs */
|
||
break; /* end case 000 */
|
||
|
||
/* Opcodes 01 - 06: double operand word instructions
|
||
|
||
Compatibility mode requires source address decode, source fetch,
|
||
dest address decode, dest fetch/store.
|
||
|
||
Add: v = [sign (src) = sign (src2)] and [sign (src) != sign (result)]
|
||
Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
|
||
*/
|
||
|
||
case 001: /* MOV */
|
||
if (srcreg) src = RdRegW (srcspec);
|
||
else src = RdMemW (GeteaW (srcspec));
|
||
if (dstreg) WrRegW (src, dstspec);
|
||
else WrMemW (src, GeteaW (dstspec));
|
||
CC_IIZP_W (src);
|
||
break;
|
||
case 002: /* CMP */
|
||
if (srcreg) src = RdRegW (srcspec);
|
||
else src = RdMemW (GeteaW (srcspec));
|
||
if (dstreg) src2 = RdRegW (dstspec);
|
||
else src2 = RdMemW (GeteaW (dstspec));
|
||
dst = (src - src2) & WMASK;
|
||
CC_IIZZ_W (dst);
|
||
if (((src ^ src2) & (~src2 ^ dst)) & WSIGN) cc = cc | CC_V;
|
||
if (src < src2) cc = cc | CC_C;
|
||
break;
|
||
case 003: /* BIT */
|
||
if (srcreg) src = RdRegW (srcspec);
|
||
else src = RdMemW (GeteaW (srcspec));
|
||
if (dstreg) src2 = RdRegW (dstspec);
|
||
else src2 = RdMemW (GeteaW (dstspec));
|
||
dst = src2 & src;
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
case 004: /* BIC */
|
||
if (srcreg) src = RdRegW (srcspec);
|
||
else src = RdMemW (GeteaW (srcspec));
|
||
if (dstreg) src2 = RdRegW (dstspec);
|
||
else src2 = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = src2 & ~src;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
case 005: /* BIS */
|
||
if (srcreg) src = RdRegW (srcspec);
|
||
else src = RdMemW (GeteaW (srcspec));
|
||
if (dstreg) src2 = RdRegW (dstspec);
|
||
else src2 = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = src2 | src;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
case 006: /* ADD */
|
||
if (srcreg) src = RdRegW (srcspec);
|
||
else src = RdMemW (GeteaW (srcspec));
|
||
if (dstreg) src2 = RdRegW (dstspec);
|
||
else src2 = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src2 + src) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_ADD_W (dst, src, src2);
|
||
break;
|
||
|
||
/* Opcode 07: EIS, FIS (not implemented), CIS
|
||
|
||
Notes:
|
||
- MUL carry: C is set if the (signed) result doesn't fit in 16 bits.
|
||
- Divide has three error cases:
|
||
1. Divide by zero.
|
||
2. Divide largest negative number by -1.
|
||
3. (Signed) quotient doesn't fit in 16 bits.
|
||
Cases 1 and 2 must be tested in advance, to avoid C runtime errors.
|
||
- ASHx left: overflow if the bits shifted out do not equal the sign
|
||
of the result (convert shift out to 1/0, xor against sign).
|
||
- ASHx right: if right shift sign extends, then the shift and
|
||
conditional or of shifted -1 is redundant. If right shift zero
|
||
extends, then the shift and conditional or does sign extension.
|
||
*/
|
||
|
||
case 007: /* EIS */
|
||
srcspec = srcspec & 07; /* get src reg */
|
||
switch ((IR >> 9) & 07) { /* decode IR<11:9> */
|
||
|
||
case 0: /* MUL */
|
||
if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
|
||
else src2 = RdMemW (GeteaW (dstspec));
|
||
src = RdRegW (srcspec); /* get src */
|
||
if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */
|
||
if (src & WSIGN) src = src | ~WMASK;
|
||
dst = src * src2; /* multiply */
|
||
WrRegW ((dst >> 16) & WMASK, srcspec); /* high 16b */
|
||
WrRegW (dst & WMASK, srcspec | 1); /* low 16b */
|
||
CC_IIZZ_L (dst & LMASK);
|
||
if ((dst > 077777) || (dst < -0100000)) cc = cc | CC_C;
|
||
break;
|
||
|
||
case 1: /* DIV */
|
||
if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
|
||
else src2 = RdMemW (GeteaW (dstspec));
|
||
t = RdRegW (srcspec);
|
||
src = (((uint32) t) << 16) | RdRegW (srcspec | 1);
|
||
if (src2 == 0) { /* div by 0? */
|
||
cc = CC_V | CC_C; /* set cc's */
|
||
break; /* done */
|
||
}
|
||
if ((src == LSIGN) && (src2 == WMASK)) { /* -2^31 / -1? */
|
||
cc = CC_V; /* overflow */
|
||
break; /* done */
|
||
}
|
||
if (src2 & WSIGN) src2 = src2 | ~WMASK; /* sext src, src2 */
|
||
if (t & WSIGN) src = src | ~LMASK;
|
||
dst = src / src2; /* divide */
|
||
if ((dst > 077777) || (dst < -0100000)) { /* out of range? */
|
||
cc = CC_V; /* overflow */
|
||
break;
|
||
}
|
||
CC_IIZZ_W (dst & WMASK); /* set cc's */
|
||
WrRegW (dst & WMASK, srcspec); /* quotient */
|
||
WrRegW ((src - (src2 * dst)) & WMASK, srcspec | 1);
|
||
break;
|
||
|
||
/* Opcode 7: EIS, continued */
|
||
|
||
case 2: /* ASH */
|
||
if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
|
||
else src2 = RdMemW (GeteaW (dstspec));
|
||
src2 = src2 & 077;
|
||
src = RdRegW (srcspec); /* get src */
|
||
if (sign = ((src & WSIGN)? 1: 0)) src = src | ~WMASK;
|
||
if (src2 == 0) { /* [0] */
|
||
dst = src; /* result */
|
||
oc = 0; /* last bit out */
|
||
}
|
||
else if (src2 <= 15) { /* [1,15] */
|
||
dst = src << src2;
|
||
i = (src >> (16 - src2)) & WMASK;
|
||
oc = (i & 1)? CC_C: 0;
|
||
if ((dst & WSIGN)? (i != WMASK): (i != 0)) oc = oc | CC_V;
|
||
}
|
||
else if (src2 <= 31) { /* [16,31] */
|
||
dst = 0;
|
||
oc = ((src << (src2 - 16)) & 1)? CC_C: 0;
|
||
if (src) oc = oc | CC_V;
|
||
}
|
||
else if (src2 == 32) { /* [32] = -32 */
|
||
dst = -sign;
|
||
oc = sign? CC_C: 0;
|
||
}
|
||
else { /* [33,63] = -31,-1 */
|
||
dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
|
||
oc = ((src >> (63 - src2)) & 1)? CC_C: 0;
|
||
}
|
||
WrRegW (dst = dst & WMASK, srcspec); /* result */
|
||
CC_IIZZ_W (dst);
|
||
cc = cc | oc;
|
||
break;
|
||
|
||
case 3: /* ASHC */
|
||
if (dstreg) src2 = RdRegW (dstspec); /* get src2 */
|
||
else src2 = RdMemW (GeteaW (dstspec));
|
||
src2 = src2 & 077;
|
||
t = RdRegW (srcspec);
|
||
src = (((uint32) t) << 16) | RdRegW (srcspec | 1);
|
||
sign = (t & WSIGN)? 1: 0; /* get src sign */
|
||
if (src2 == 0) { /* [0] */
|
||
dst = src; /* result */
|
||
oc = 0; /* last bit out */
|
||
}
|
||
else if (src2 <= 31) { /* [1,31] */
|
||
dst = ((uint32) src) << src2;
|
||
i = ((src >> (32 - src2)) | (-sign << src2)) & LMASK;
|
||
oc = (i & 1)? CC_C: 0;
|
||
if ((dst & LSIGN)? (i != LMASK): (i != 0)) oc = oc | CC_V;
|
||
}
|
||
else if (src2 == 32) { /* [32] = -32 */
|
||
dst = -sign;
|
||
oc = sign? CC_C: 0;
|
||
}
|
||
else { /* [33,63] = -31,-1 */
|
||
dst = (src >> (64 - src2)) | (-sign << (src2 - 32));
|
||
oc = ((src >> (63 - src2)) & 1)? CC_C: 0;
|
||
}
|
||
WrRegW ((dst >> 16) & WMASK, srcspec); /* high result */
|
||
WrRegW (dst & WMASK, srcspec | 1); /* low result */
|
||
CC_IIZZ_L (dst & LMASK);
|
||
cc = cc | oc;
|
||
break;
|
||
|
||
/* Opcode 7: EIS, continued */
|
||
|
||
case 4: /* XOR */
|
||
if (dstreg) src2 = RdRegW (dstspec); /* get dst */
|
||
else src2 = RdMemMW (ea = GeteaW (dstspec));
|
||
src = RdRegW (srcspec); /* get src */
|
||
dst = src2 ^ src;
|
||
if (dstreg) WrRegW (dst, dstspec); /* result */
|
||
else WrMemW (dst, ea);
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
|
||
case 7: /* SOB */
|
||
dst = (RdRegW (srcspec) - 1) & WMASK; /* decr reg */
|
||
WrRegW (dst, srcspec); /* result */
|
||
if (dst != 0) { /* br if zero */
|
||
CMODE_JUMP ((PC - dstspec - dstspec) & WMASK);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
CMODE_FAULT (CMODE_RSVI); } /* end switch EIS */
|
||
break; /* end case 007 */
|
||
|
||
/* Opcode 10: branches, traps, SOPs */
|
||
|
||
case 010:
|
||
switch ((IR >> 6) & 077) { /* decode IR<11:6> */
|
||
case 000: case 001: /* BPL */
|
||
if ((cc & CC_N) == 0) { BRANCH_F (IR); }
|
||
break;
|
||
case 002: case 003: /* BPL */
|
||
if ((cc & CC_N) == 0) { BRANCH_B (IR); }
|
||
break;
|
||
case 004: case 005: /* BMI */
|
||
if (cc & CC_N) { BRANCH_F (IR); }
|
||
break;
|
||
case 006: case 007: /* BMI */
|
||
if (cc & CC_N) { BRANCH_B (IR); }
|
||
break;
|
||
case 010: case 011: /* BHI */
|
||
if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_F (IR); }
|
||
break;
|
||
case 012: case 013: /* BHI */
|
||
if ((cc & (CC_C | CC_Z)) == 0) { BRANCH_B (IR); }
|
||
break;
|
||
case 014: case 015: /* BLOS */
|
||
if (cc & (CC_C | CC_Z)) { BRANCH_F (IR); }
|
||
break;
|
||
case 016: case 017: /* BLOS */
|
||
if (cc & (CC_C | CC_Z)) { BRANCH_B (IR); }
|
||
break;
|
||
case 020: case 021: /* BVC */
|
||
if ((cc & CC_V) == 0) { BRANCH_F (IR); }
|
||
break;
|
||
case 022: case 023: /* BVC */
|
||
if ((cc & CC_V) == 0) { BRANCH_B (IR); }
|
||
break;
|
||
case 024: case 025: /* BVS */
|
||
if (cc & CC_V) { BRANCH_F (IR); }
|
||
break;
|
||
case 026: case 027: /* BVS */
|
||
if (cc & CC_V) { BRANCH_B (IR); }
|
||
break;
|
||
case 030: case 031: /* BCC */
|
||
if ((cc & CC_C) == 0) { BRANCH_F (IR); }
|
||
break;
|
||
case 032: case 033: /* BCC */
|
||
if ((cc & CC_C) == 0) { BRANCH_B (IR); }
|
||
break;
|
||
case 034: case 035: /* BCS */
|
||
if (cc & CC_C) { BRANCH_F (IR); }
|
||
break;
|
||
case 036: case 037: /* BCS */
|
||
if (cc & CC_C) { BRANCH_B (IR); }
|
||
break;
|
||
case 040: case 041: case 042: case 043: /* EMT */
|
||
CMODE_FAULT (CMODE_EMT);
|
||
break;
|
||
case 044: case 045: case 046: case 047: /* TRAP */
|
||
CMODE_FAULT (CMODE_TRAP);
|
||
break;
|
||
|
||
/* Opcode 10, continued: SOPs */
|
||
|
||
case 050: /* CLRB */
|
||
if (dstreg) R[dstspec] = R[dstspec] & ~BMASK;
|
||
else WrMemB (0, GeteaB (dstspec));
|
||
cc = CC_Z;
|
||
break;
|
||
case 051: /* COMB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = src ^ BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
cc = cc | CC_C;
|
||
break;
|
||
case 052: /* INCB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (src + 1) & BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZP_B (dst);
|
||
if (dst == 0200) cc = cc | CC_V;
|
||
break;
|
||
case 053: /* DECB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (src - 1) & BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZP_B (dst);
|
||
if (dst == 0177) cc = cc | CC_V;
|
||
break;
|
||
case 054: /* NEGB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (-src) & BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
if (dst == 0200) cc = cc | CC_V;
|
||
if (dst) cc = cc | CC_C;
|
||
break;
|
||
case 055: /* ADCB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (src + (cc & CC_C)) & BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
if ((src == 0177) && (dst == 0200)) cc = cc | CC_V;
|
||
if ((src == 0377) && (dst == 0)) cc = cc | CC_C;
|
||
break;
|
||
case 056: /* SBCB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (src - (cc & CC_C)) & BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
if ((src == 0200) && (dst == 0177)) cc = cc | CC_V;
|
||
if ((src == 0) && (dst == 0377)) cc = cc | CC_C;
|
||
break;
|
||
case 057: /* TSTB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemB (GeteaB (dstspec));
|
||
CC_IIZZ_B (src);
|
||
break;
|
||
case 060: /* RORB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (src >> 1) | ((cc & CC_C)? BSIGN: 0);
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
if (src & 1) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 061: /* ROLB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = ((src << 1) | ((cc & CC_C)? 1: 0)) & BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
if (src & BSIGN) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 062: /* ASRB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (src >> 1) | (src & BSIGN);
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
if (src & 1) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 063: /* ASLB */
|
||
if (dstreg) src = RdRegB (dstspec);
|
||
else src = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = (src << 1) & BMASK;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZZ_B (dst);
|
||
if (src & BSIGN) cc = cc | CC_C;
|
||
if (CC_XOR_NC (cc)) cc = cc | CC_V;
|
||
break;
|
||
case 065: /* MFPD */
|
||
if (dstreg) dst = RdRegW (dstspec); /* "mov dst,-(sp)" */
|
||
else dst = RdMemW (GeteaW (dstspec));
|
||
WrMemW (dst, (R[6] - 2) & WMASK);
|
||
R[6] = (R[6] - 2) & WMASK;
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
case 066: /* MTPD */
|
||
dst = RdMemW (R[6] & WMASK); /* "mov (sp)+,dst" */
|
||
R[6] = (R[6] + 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (AIN|RW, 6);
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, (GeteaW (dstspec) & WMASK));
|
||
CC_IIZP_W (dst);
|
||
break;
|
||
default:
|
||
CMODE_FAULT (CMODE_RSVI);
|
||
break; } /* end switch SOPs */
|
||
break; /* end case 010 */
|
||
|
||
/* Opcodes 11 - 16: double operand byte instructions
|
||
|
||
Cmp: v = [sign (src) != sign (src2)] and [sign (src2) = sign (result)]
|
||
Sub: v = [sign (src) != sign (src2)] and [sign (src) = sign (result)]
|
||
*/
|
||
|
||
case 011: /* MOVB */
|
||
if (srcreg) src = RdRegB (srcspec);
|
||
else src = RdMemB (GeteaB (srcspec));
|
||
if (dstreg) WrRegW ((src & BSIGN)? (0xFF00 | src): src, dstspec);
|
||
else WrMemB (src, GeteaB (dstspec));
|
||
CC_IIZP_B (src);
|
||
break;
|
||
case 012: /* CMPB */
|
||
if (srcreg) src = RdRegB (srcspec);
|
||
else src = RdMemB (GeteaB (srcspec));
|
||
if (dstreg) src2 = RdRegB (dstspec);
|
||
else src2 = RdMemB (GeteaB (dstspec));
|
||
dst = (src - src2) & BMASK;
|
||
CC_IIZZ_B (dst);
|
||
if (((src ^ src2) & (~src2 ^ dst)) & BSIGN) cc = cc | CC_V;
|
||
if (src < src2) cc = cc | CC_C;
|
||
break;
|
||
case 013: /* BITB */
|
||
if (srcreg) src = RdRegB (srcspec);
|
||
else src = RdMemB (GeteaB (srcspec));
|
||
if (dstreg) src2 = RdRegB (dstspec);
|
||
else src2 = RdMemB (GeteaB (dstspec));
|
||
dst = src2 & src;
|
||
CC_IIZP_B (dst);
|
||
break;
|
||
case 014: /* BICB */
|
||
if (srcreg) src = RdRegB (srcspec);
|
||
else src = RdMemB (GeteaB (srcspec));
|
||
if (dstreg) src2 = RdRegB (dstspec);
|
||
else src2 = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = src2 & ~src;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZP_B (dst);
|
||
break;
|
||
case 015: /* BISB */
|
||
if (srcreg) src = RdRegB (srcspec);
|
||
else src = RdMemB (GeteaB (srcspec));
|
||
if (dstreg) src2 = RdRegB (dstspec);
|
||
else src2 = RdMemMB (ea = GeteaB (dstspec));
|
||
dst = src2 | src;
|
||
if (dstreg) WrRegB (dst, dstspec);
|
||
else WrMemB (dst, ea);
|
||
CC_IIZP_B (dst);
|
||
break;
|
||
case 016: /* SUB */
|
||
if (srcreg) src = RdRegW (srcspec);
|
||
else src = RdMemW (GeteaW (srcspec));
|
||
if (dstreg) src2 = RdRegW (dstspec);
|
||
else src2 = RdMemMW (ea = GeteaW (dstspec));
|
||
dst = (src2 - src) & WMASK;
|
||
if (dstreg) WrRegW (dst, dstspec);
|
||
else WrMemW (dst, ea);
|
||
CC_IIZZ_W (dst);
|
||
if (((src ^ src2) & (~src ^ dst)) & WSIGN) cc = cc | CC_V;
|
||
if (src2 < src) cc = cc | CC_C;
|
||
break;
|
||
default:
|
||
CMODE_FAULT (CMODE_RSVI);
|
||
break;
|
||
} /* end switch op */
|
||
return cc;
|
||
}
|
||
|
||
/* Effective address calculations
|
||
|
||
Inputs:
|
||
spec = specifier <5:0>
|
||
Outputs:
|
||
ea = effective address
|
||
*/
|
||
|
||
int32 GeteaW (int32 spec)
|
||
{
|
||
int32 adr, reg;
|
||
|
||
reg = spec & 07; /* register number */
|
||
switch (spec >> 3) { /* decode spec<5:3> */
|
||
default: /* can't get here */
|
||
case 1: /* (R) */
|
||
if (reg == 7) return (PC & WMASK);
|
||
else return (R[reg] & WMASK);
|
||
case 2: /* (R)+ */
|
||
if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
|
||
else {
|
||
R[reg] = ((adr = R[reg]) + 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (AIN|RW, reg);
|
||
}
|
||
return adr;
|
||
case 3: /* @(R)+ */
|
||
if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
|
||
else {
|
||
R[reg] = ((adr = R[reg]) + 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (AIN|RW, reg);
|
||
}
|
||
return RdMemW (adr);
|
||
case 4: /* -(R) */
|
||
if (reg == 7) adr = PC = (PC - 2) & WMASK;
|
||
else {
|
||
adr = R[reg] = (R[reg] - 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (ADC|RW, reg);
|
||
}
|
||
return adr;
|
||
case 5: /* @-(R) */
|
||
if (reg == 7) adr = PC = (PC - 2) & WMASK;
|
||
else {
|
||
adr = R[reg] = (R[reg] - 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (ADC|RW, reg);
|
||
}
|
||
return RdMemW (adr);
|
||
case 6: /* d(r) */
|
||
adr = RdMemW (PC);
|
||
PC = (PC + 2) & WMASK;
|
||
if (reg == 7) return ((PC + adr) & WMASK);
|
||
else return ((R[reg] + adr) & WMASK);
|
||
case 7: /* @d(R) */
|
||
adr = RdMemW (PC);
|
||
PC = (PC + 2) & WMASK;
|
||
if (reg == 7) adr = (PC + adr) & WMASK;
|
||
else adr = (R[reg] + adr) & WMASK;
|
||
return RdMemW (adr);
|
||
} /* end switch */
|
||
}
|
||
|
||
int32 GeteaB (int32 spec)
|
||
{
|
||
int32 adr, reg;
|
||
|
||
reg = spec & 07; /* reg number */
|
||
switch (spec >> 3) { /* decode spec<5:3> */
|
||
default: /* can't get here */
|
||
case 1: /* (R) */
|
||
if (reg == 7) return (PC & WMASK);
|
||
else return (R[reg] & WMASK);
|
||
case 2: /* (R)+ */
|
||
if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
|
||
else if (reg == 6) {
|
||
R[reg] = ((adr = R[reg]) + 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (AIN|RW, reg);
|
||
}
|
||
else {
|
||
R[reg] = ((adr = R[reg]) + 1) & WMASK;
|
||
recq[recqptr++] = RQ_REC (AIN|RB, reg);
|
||
}
|
||
return adr;
|
||
case 3: /* @(R)+ */
|
||
if (reg == 7) PC = ((adr = PC) + 2) & WMASK;
|
||
else {
|
||
R[reg] = ((adr = R[reg]) + 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (AIN|RW, reg);
|
||
}
|
||
return RdMemW (adr);
|
||
case 4: /* -(R) */
|
||
if (reg == 7) adr = PC = (PC - 2) & WMASK;
|
||
else if (reg == 6) {
|
||
adr = R[reg] = (R[reg] - 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (ADC|RW, reg);
|
||
}
|
||
else {
|
||
adr = R[reg] = (R[reg] - 1) & WMASK;
|
||
recq[recqptr++] = RQ_REC (ADC|RB, reg);
|
||
}
|
||
return adr;
|
||
case 5: /* @-(R) */
|
||
if (reg == 7) adr = PC = (PC - 2) & WMASK;
|
||
else {
|
||
adr = R[reg] = (R[reg] - 2) & WMASK;
|
||
recq[recqptr++] = RQ_REC (ADC|RW, reg);
|
||
}
|
||
return RdMemW (adr);
|
||
case 6: /* d(r) */
|
||
adr = RdMemW (PC);
|
||
PC = (PC + 2) & WMASK;
|
||
if (reg == 7) return ((PC + adr) & WMASK);
|
||
else return ((R[reg] + adr) & WMASK);
|
||
case 7: /* @d(R) */
|
||
adr = RdMemW (PC);
|
||
PC = (PC + 2) & WMASK;
|
||
if (reg == 7) adr = (PC + adr) & WMASK;
|
||
else adr = (R[reg] + adr) & WMASK;
|
||
return RdMemW (adr);
|
||
} /* end switch */
|
||
}
|
||
|
||
/* Memory and register access routines */
|
||
|
||
int32 RdMemW (int32 a)
|
||
{
|
||
int32 acc = ACC_MASK (USER);
|
||
|
||
if (a & 1) CMODE_FAULT (CMODE_ODD);
|
||
return Read (a, L_WORD, RA);
|
||
}
|
||
|
||
int32 RdMemMW (int32 a)
|
||
{
|
||
int32 acc = ACC_MASK (USER);
|
||
|
||
if (a & 1) CMODE_FAULT (CMODE_ODD);
|
||
return Read (a, L_WORD, WA);
|
||
}
|
||
|
||
void WrMemW (int32 d, int32 a)
|
||
{
|
||
int32 acc = ACC_MASK (USER);
|
||
|
||
if (a & 1) CMODE_FAULT (CMODE_ODD);
|
||
Write (a, d, L_WORD, WA);
|
||
return;
|
||
}
|
||
|
||
int32 RdRegB (int32 rn)
|
||
{
|
||
if (rn == 7) return (PC & BMASK);
|
||
else return (R[rn] & BMASK);
|
||
}
|
||
|
||
int32 RdRegW (int32 rn)
|
||
{
|
||
if (rn == 7) return (PC & WMASK);
|
||
else return (R[rn] & WMASK);
|
||
}
|
||
|
||
void WrRegB (int32 val, int32 rn)
|
||
{
|
||
if (rn == 7) { CMODE_JUMP ((PC & ~BMASK) | val); }
|
||
else R[rn] = (R[rn] & ~BMASK) | val;
|
||
return;
|
||
}
|
||
|
||
void WrRegW (int32 val, int32 rn)
|
||
{
|
||
if (rn == 7) { CMODE_JUMP (val); }
|
||
else R[rn] = val;
|
||
return;
|
||
}
|
||
|
||
#else
|
||
|
||
/* Subset VAX
|
||
|
||
Never legal to set CM in PSL
|
||
Should never get to instruction execution
|
||
*/
|
||
|
||
extern jmp_buf save_env;
|
||
|
||
t_bool BadCmPSL (int32 newpsl)
|
||
{
|
||
return TRUE; /* always bad */
|
||
}
|
||
|
||
int32 op_cmode (int32 cc)
|
||
{
|
||
RSVD_INST_FAULT;
|
||
return cc;
|
||
}
|
||
|
||
#endif
|