diff options
Diffstat (limited to 'src/devices/cpu/t11/t11ops.hxx')
| -rw-r--r-- | src/devices/cpu/t11/t11ops.hxx | 245 |
1 files changed, 239 insertions, 6 deletions
diff --git a/src/devices/cpu/t11/t11ops.hxx b/src/devices/cpu/t11/t11ops.hxx index 90c0a4121f3..1aeaace16dd 100644 --- a/src/devices/cpu/t11/t11ops.hxx +++ b/src/devices/cpu/t11/t11ops.hxx @@ -33,6 +33,7 @@ /* extracts the source/destination register index from the opcode into 'sreg' or 'dreg' */ #define GET_SREG sreg = (op >> 6) & 7 #define GET_DREG dreg = op & 7 +#define EIS_SWAP op = ((op & 7) << 6) | ((op >> 6) & 7) /* for a byte-sized source operand: extracts 'sreg', computes 'ea', and loads the value into 'source' */ #define GET_SB_RG GET_SREG; source = REGB(sreg) @@ -144,6 +145,11 @@ #define SETW_NZV SETW_N; SETW_Z; SETW_V #define SETW_NZVC SETW_N; SETW_Z; SETW_V; SETW_C +/* SIMH */ +#define GET_ZERO(v) ((v) == 0) +#define GET_SIGN_W(v) (((v) >> 15) & 1) +#define GET_SIGN_B(v) (((v) >> 7) & 1) + /* operations */ /* ADC: dst += C */ #define ADC_R(d) int dreg, source, dest, result; source = GET_C; GET_DW_##d; CLR_NZVC; result = dest + source; SETW_NZVC; PUT_DW_DREG(result) @@ -187,9 +193,9 @@ #define BR(c) if (c) { PC += 2 * (signed char)(op & 0xff); } /* CLR: dst = 0 */ #define CLR_R(d) int dreg; PUT_DW_##d(0); CLR_NZVC; SET_Z -#define CLR_M(d) int dreg, ea; PUT_DWT_##d(0); CLR_NZVC; SET_Z +#define CLR_M(d) int dreg, ea; if (c_insn_set & (IS_T11|IS_VM1)) { PUT_DWT_##d(0); } else { PUT_DW_##d(0); } CLR_NZVC; SET_Z #define CLRB_R(d) int dreg; PUT_DB_##d(0); CLR_NZVC; SET_Z -#define CLRB_M(d) int dreg, ea; PUT_DBT_##d(0); CLR_NZVC; SET_Z +#define CLRB_M(d) int dreg, ea; if (c_insn_set & (IS_T11|IS_VM1|IS_VM2)) { PUT_DBT_##d(0); } else { PUT_DB_##d(0); } CLR_NZVC; SET_Z /* CMP: flags = src - dst */ #define CMP_R(s,d) int sreg, dreg, source, dest, result; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = source - dest; SETW_NZVC; #define CMP_M(s,d) int sreg, dreg, source, dest, result, ea; GET_SW_##s; GET_DW_##d; CLR_NZVC; result = source - dest; SETW_NZVC; @@ -216,13 +222,13 @@ #define JSR(d) int sreg, dreg, ea; GET_SREG; GET_DREG; MAKE_EAW_##d(dreg); PUSH(REGW(sreg)); REGW(sreg) = PC; PC = ea /* MFPS: dst = flags */ #define MFPS_R(d) int dreg, result; result = PSW; CLR_NZV; SETB_NZ; PUT_DW_##d((signed char)result) -#define MFPS_M(d) int dreg, result, ea; result = PSW; CLR_NZV; SETB_NZ; PUT_DB_##d(result) +#define MFPS_M(d) int dreg, result, ea; result = PSW; CLR_NZV; SETB_NZ; if (c_insn_set & (IS_VM1|IS_VM2)) { PUT_DBT_##d(result); } else { PUT_DB_##d(result); } /* MOV: dst = src */ #define MOV_R(s,d) int sreg, dreg, source, result; GET_SW_##s; CLR_NZV; result = source; SETW_NZ; PUT_DW_##d(result) -#define MOV_M(s,d) int sreg, dreg, source, result, ea; GET_SW_##s; CLR_NZV; result = source; SETW_NZ; if (c_insn_set & IS_VM1) { PUT_DW_##d(result); } else { PUT_DWT_##d(result); } +#define MOV_M(s,d) int sreg, dreg, source, result, ea; GET_SW_##s; CLR_NZV; result = source; SETW_NZ; if (c_insn_set & IS_T11) { PUT_DWT_##d(result); } else { PUT_DW_##d(result); } #define MOVB_R(s,d) int sreg, dreg, source, result; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; PUT_DW_##d((signed char)result) #define MOVB_X(s,d) int sreg, dreg, source, result, ea; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; PUT_DW_##d((signed char)result) -#define MOVB_M(s,d) int sreg, dreg, source, result, ea; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; if (c_insn_set & IS_VM1) { PUT_DB_##d(result); } else { PUT_DBT_##d(result); } +#define MOVB_M(s,d) int sreg, dreg, source, result, ea; GET_SB_##s; CLR_NZV; result = source; SETB_NZ; if (c_insn_set & (IS_T11|IS_VM2)) { PUT_DBT_##d(result); } else { PUT_DB_##d(result); } /* MTPS: flags = src */ #define MTPS_R(d) int dreg, dest; GET_DB_##d; PSW = (PSW & ~0xef) | (dest & 0xef); m_check_irqs = true #define MTPS_M(d) int dreg, dest, ea; GET_DB_##d; PSW = (PSW & ~0xef) | (dest & 0xef); m_check_irqs = true @@ -258,7 +264,7 @@ #define SWAB_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = ((dest >> 8) & 0xff) + (dest << 8); SETB_NZ; PUT_DW_EA(result) /* SXT: dst = sign-extend dst */ #define SXT_R(d) int dreg, result; CLR_ZV; if (GET_N) result = -1; else { result = 0; SET_Z; } PUT_DW_##d(result) -#define SXT_M(d) int dreg, result, ea; CLR_ZV; if (GET_N) result = -1; else { result = 0; SET_Z; } PUT_DWT_##d(result) +#define SXT_M(d) int dreg, result, ea; CLR_ZV; if (GET_N) result = -1; else { result = 0; SET_Z; } if (c_insn_set & (IS_T11|IS_VM1)) { PUT_DWT_##d(result); } else { PUT_DW_##d(result); } /* TST: dst = ~dst */ #define TST_R(d) int dreg, dest, result; GET_DW_##d; CLR_NZVC; result = dest; SETW_NZ; #define TST_M(d) int dreg, dest, result, ea; GET_DW_##d; CLR_NZVC; result = dest; SETW_NZ; @@ -271,6 +277,191 @@ /* test if insn is supported by the CPU */ #define CHECK_IS(d) do { if (!(c_insn_set & (d))) { illegal(op); return; } } while (false) +/* Extended Instruction Set -- SIMH impl */ + +int t11_device::_mul(int src, int src2, int *psw) { + int dst; + int N, Z, V, C; + + if (GET_SIGN_W (src2)) + src2 = src2 | ~077777; + if (GET_SIGN_W (src)) + src = src | ~077777; + dst = src * src2; + N = (dst < 0); + Z = GET_ZERO (dst); + V = 0; + C = ((dst > 077777) || (dst < -0100000)); + *psw = (*psw & ~15) | ((N&1) << 3) | ((Z&1) << 2) | ((V&1) << 1) | (C&1); + + return dst; +} + +#define MUL_M(s) \ +int sreg, dreg, source, dest, result, ea = 0, _psw = PSW; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _mul(dest, source, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +PUT_DW_DREG(result >> 16); REGW(dreg|1) = result + +#define MUL_R(s) \ +int sreg, dreg, source, dest, result, _psw = PSW; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _mul(dest, source, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +PUT_DW_DREG(result >> 16); REGW(dreg|1) = result + +int t11_device::_div(int source, int source1, int src2, int *remainder, int *psw) { + int src, dst = 0; + int N, Z, V, C; + + src = (((uint32_t) source) << 16) | source1; + if (src2 == 0) { + N = 0; /* J11,11/70 compat */ + Z = V = C = 1; /* N = 0, Z = 1 */ + if (c_insn_set & IS_VM2) Z = 0; + } else if ((((uint32_t)src) == 020000000000) && (src2 == 0177777)) { + V = 1; /* J11,11/70 compat */ + N = Z = C = 0; /* N = Z = 0 */ + } else { + if (GET_SIGN_W (src2)) + src2 = src2 | ~077777; + if (GET_SIGN_W (source)) + src = src | ~017777777777; + dst = src / src2; + N = (dst < 0); /* N set on 32b result */ + if ((dst > 077777) || (dst < -0100000)) { + V = 1; /* J11,11/70 compat */ + Z = C = 0; /* Z = C = 0 */ + if (c_insn_set & IS_VM2) N = 0; + } else { + Z = GET_ZERO (dst); + V = C = 0; + } + *remainder = (src - (src2 * dst)) & 0177777; + } + *psw = (*psw & ~15) | ((N&1) << 3) | ((Z&1) << 2) | ((V&1) << 1) | (C&1); + return dst; +} + +#define DIV_M(s) \ +int sreg, dreg, source, dest, result, remainder = 0, ea = 0, _psw = PSW; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _div(dest, REGD(dreg|1), source, &remainder, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +if (!(PSW & VFLAG)) { REGW((dreg|1)) = remainder; PUT_DW_DREG(result); } + +#define DIV_R(s) \ +int sreg, dreg, source, dest, result, remainder = 0, _psw = PSW; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _div(dest, REGD(dreg|1), source, &remainder, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +if (!(PSW & VFLAG)) { REGW((dreg|1)) = remainder; PUT_DW_DREG(result); } + +int t11_device::_ash(int source, int dest, int *psw) { + int src, src2, dst, sign, i; + int N, Z, V, C; + + N = BIT(*psw, 3); + Z = BIT(*psw, 2); + V = BIT(*psw, 1); + C = BIT(*psw, 0); + + src2 = dest & 077; + sign = GET_SIGN_W (source); + src = sign? source | ~077777: source; + if (src2 == 0) { /* [0] */ + dst = src; + V = C = 0; + } + else if (src2 <= 15) { /* [1,15] */ + dst = src << src2; + i = (src >> (16 - src2)) & 0177777; + V = (i != ((dst & 0100000)? 0177777: 0)); + C = (i & 1); + } + else if (src2 <= 31) { /* [16,31] */ + dst = 0; + V = (src != 0); + C = (src << (src2 - 16)) & 1; + } + else if (src2 == 32) { /* [32] = -32 */ + dst = -sign; + V = 0; + C = sign; + } + else { /* [33,63] = -31,-1 */ + dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); + V = 0; + C = ((src >> (63 - src2)) & 1); + } + N = GET_SIGN_W (dst); + Z = GET_ZERO (dst); + *psw = (*psw & ~15) | ((N&1) << 3) | ((Z&1) << 2) | ((V&1) << 1) | (C&1); + return dst & 0177777; +} + +#define ASH_M(s) \ +int sreg, dreg, source, dest, result, _psw = PSW, ea = 0; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _ash(dest, source, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +PUT_DW_DREG(result) + +#define ASH_R(s) \ +int sreg, dreg, source, dest, result, _psw = PSW; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _ash(dest, source, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +PUT_DW_DREG(result) + +int t11_device::_ashc(int source, int source1, int dest, int *psw) { + int src, src2, dst, sign, i; + int N, Z, V, C; + + N = BIT(*psw, 3); + Z = BIT(*psw, 2); + V = BIT(*psw, 1); + C = BIT(*psw, 0); + + src2 = dest & 077; + sign = GET_SIGN_W (source); + + src = (((uint32_t) source) << 16) | source1; + if (src2 == 0) { /* [0] */ + dst = src; + V = C = 0; + } + else if (src2 <= 31) { /* [1,31] */ + dst = ((uint32_t) src) << src2; + i = (src >> (32 - src2)) | (-sign << src2); + V = (i != ((dst & 020000000000)? -1: 0)); + C = (i & 1); + } + else if (src2 == 32) { /* [32] = -32 */ + dst = -sign; + V = 0; + C = sign; + } + else { /* [33,63] = -31,-1 */ + dst = (src >> (64 - src2)) | (-sign << (src2 - 32)); + V = 0; + C = ((src >> (63 - src2)) & 1); + } + i = (dst >> 16) & 0177777; + N = GET_SIGN_W (i); + Z = GET_ZERO (dst | i); + *psw = (*psw & ~15) | ((N&1) << 3) | ((Z&1) << 2) | ((V&1) << 1) | (C&1); + return dst; +} + +#define ASHC_M(s) \ +int sreg, dreg, source, dest, result, ea = 0, _psw = PSW; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _ashc(dest, REGD(dreg|1), source, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +PUT_DW_DREG(result >> 16); REGW(dreg|1) = result + +#define ASHC_R(s) \ +int sreg, dreg, source, dest, result, _psw = PSW; \ +EIS_SWAP; GET_SW_##s; GET_DW_RG; \ +result = _ashc(dest, REGD(dreg|1), source, &_psw); PSW = (PSW & ~15) | (_psw & 15); \ +PUT_DW_DREG(result >> 16); REGW(dreg|1) = result + + void t11_device::trap_to(uint16_t vector) { PUSH(PSW); @@ -329,6 +520,12 @@ void t11_device::halt(uint16_t op) m_mcir = MCIR_HALT; m_vsel = VM1_HALT; } + else if (c_insn_set & IS_VM2) + { + m_mcir = MCIR_HALT; + m_vsel = VM2_HALT; + m_check_irqs = true; + } else { PUSH(PSW); @@ -927,6 +1124,42 @@ void t11_device::xor_ded(uint16_t op) { CHECK_IS(IS_LEIS); m_icount -= 30; void t11_device::xor_ix(uint16_t op) { CHECK_IS(IS_LEIS); m_icount -= 30; { XOR_M(IX); } } void t11_device::xor_ixd(uint16_t op) { CHECK_IS(IS_LEIS); m_icount -= 36; { XOR_M(IXD); } } +void t11_device::ash_rg(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 12; { ASH_R(RG); } } // XXX icount is fake +void t11_device::ash_rgd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { ASH_M(RGD); } } +void t11_device::ash_in(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { ASH_M(IN); } } +void t11_device::ash_ind(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 27; { ASH_M(IND); } } +void t11_device::ash_de(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 24; { ASH_M(DE); } } +void t11_device::ash_ded(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { ASH_M(DED); } } +void t11_device::ash_ix(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { ASH_M(IX); } } +void t11_device::ash_ixd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 36; { ASH_M(IXD); } } + +void t11_device::ashc_rg(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 12; { ASHC_R(RG); } } // XXX icount is fake +void t11_device::ashc_rgd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { ASHC_M(RGD); } } +void t11_device::ashc_in(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { ASHC_M(IN); } } +void t11_device::ashc_ind(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 27; { ASHC_M(IND); } } +void t11_device::ashc_de(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 24; { ASHC_M(DE); } } +void t11_device::ashc_ded(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { ASHC_M(DED); } } +void t11_device::ashc_ix(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { ASHC_M(IX); } } +void t11_device::ashc_ixd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 36; { ASHC_M(IXD); } } + +void t11_device::mul_rg(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 12; { MUL_R(RG); } } // XXX icount is fake +void t11_device::mul_rgd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { MUL_M(RGD); } } +void t11_device::mul_in(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { MUL_M(IN); } } +void t11_device::mul_ind(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 27; { MUL_M(IND); } } +void t11_device::mul_de(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 24; { MUL_M(DE); } } +void t11_device::mul_ded(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { MUL_M(DED); } } +void t11_device::mul_ix(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { MUL_M(IX); } } +void t11_device::mul_ixd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 36; { MUL_M(IXD); } } + +void t11_device::div_rg(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 12; { DIV_R(RG); } } // XXX icount is fake +void t11_device::div_rgd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { DIV_M(RGD); } } +void t11_device::div_in(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 21; { DIV_M(IN); } } +void t11_device::div_ind(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 27; { DIV_M(IND); } } +void t11_device::div_de(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 24; { DIV_M(DE); } } +void t11_device::div_ded(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { DIV_M(DED); } } +void t11_device::div_ix(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 30; { DIV_M(IX); } } +void t11_device::div_ixd(uint16_t op) { CHECK_IS(IS_EIS); m_icount -= 36; { DIV_M(IXD); } } + void t11_device::sob(uint16_t op) { int sreg, source; |
