diff options
Diffstat (limited to 'trunk/src/emu/cpu/am29000/am29ops.h')
-rw-r--r-- | trunk/src/emu/cpu/am29000/am29ops.h | 1725 |
1 files changed, 1725 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/am29000/am29ops.h b/trunk/src/emu/cpu/am29000/am29ops.h new file mode 100644 index 00000000000..f23189a043a --- /dev/null +++ b/trunk/src/emu/cpu/am29000/am29ops.h @@ -0,0 +1,1725 @@ +/*************************************************************************** + + am29ops.h + Am29000 instructions + +***************************************************************************/ + +/*************************************************************************** + DEFINES +***************************************************************************/ + +#define IFLAG_ILLEGAL (1 << 0) +#define IFLAG_SUPERVISOR_ONLY (1 << 1) +#define IFLAG_RA_PRESENT (1 << 2) +#define IFLAG_RB_PRESENT (1 << 3) +#define IFLAG_RC_PRESENT (1 << 4) + +#define IFLAG_SPR_ACCESS (1 << 6) +#define IFLAG_MEMORY_ACCESS (1 << 8) +#define IFLAG_CONTROL (1 << 9) + + +#define GET_RA_VAL (am29000->r[RA]) +#define GET_RB_VAL (am29000->r[RB]) + +#define RA (get_abs_reg(am29000, am29000->exec_ir >> 8, am29000->ipa)) +#define RB (get_abs_reg(am29000, am29000->exec_ir >> 0, am29000->ipb)) +#define RC (get_abs_reg(am29000, am29000->exec_ir >> 16, am29000->ipc)) + +#define INST_SA ((am29000->exec_ir >> 8) & 0xff) +#define INST_VN ((am29000->exec_ir >> 16) & 0xff) +#define INST_M_BIT (am29000->exec_ir & (1 << 24)) +#define INST_CE_BIT (am29000->exec_ir & (1 << 23)) +#define INST_AS_BIT (am29000->exec_ir & (1 << 22)) +#define INST_PA_BIT (am29000->exec_ir & (1 << 21)) +#define INST_SB_BIT (am29000->exec_ir & (1 << 20)) +#define INST_UA_BIT (am29000->exec_ir & (1 << 19)) +#define INST_OPT_MASK (7) +#define INST_OPT_SHIFT (16) +#define INST_OPT_FIELD (((am29000->exec_ir) >> INST_OPT_SHIFT) & INST_OPT_MASK) +#define INST_CNTL_MASK (0x7f) +#define INST_CNTL_SHIFT (16) + +#define I8 (am29000->exec_ir & 0xff) +#define I16 (((am29000->exec_ir >> 8) & 0xff00) | (am29000->exec_ir & 0xff)) +#define I16_ZEX ((UINT32)(I16)) +#define I16_SEX ((INT32)(INT16)I16) +#define I16_OEX (0xffff0000 | I16) + +#define JMP_ZEX (I16 << 2) +#define JMP_SEX ((INT32)(INT16)(((am29000->exec_ir >> 8) & 0xff00) | (am29000->exec_ir & 0xff)) << 2) + +#define BOOLEAN_MASK (1 << 31) +#define BOOLEAN_TRUE (1 << 31) +#define BOOLEAN_FALSE (0) + +#define UNHANDLED_OP fatalerror("Am29000: Unhandled inst %s at %x\n", __FUNCTION__, am29000->exec_pc); + + +/*************************************************************************** + STRUCTS +***************************************************************************/ + +typedef struct _op_info +{ + void (*opcode)(am29000_state *); + UINT32 flags; +} op_info; + + +/*************************************************************************** + ALU FLAG CALCULATION +***************************************************************************/ + +#define SET_ALU_Z(r) am29000->alu &= ~ALU_Z; \ + am29000->alu |= (r == 0) << ALU_Z_SHIFT; + +#define SET_ALU_N(r) am29000->alu &= ~ALU_N; \ + am29000->alu |= ((UINT32)r & 0x80000000) >> (31 - ALU_N_SHIFT); + +#define CALC_C_ADD(r, a) ((UINT32)(r) < (UINT32)(a)) + +#define SET_ALU_C_ADD(r, a) am29000->alu &= ~ALU_C; \ + am29000->alu |= CALC_C_ADD(r, a) << ALU_C_SHIFT; + +#define CALC_C_SUB(a, b) (!((UINT32)(a) < (UINT32)(b))) + +#define SET_ALU_C_SUB(a, b) am29000->alu &= ~ALU_C; \ + am29000->alu |= CALC_C_SUB(a, b) << ALU_C_SHIFT; + +#define SET_ALU_V_ADD(r, a, b) am29000->alu &= ~ALU_V; \ + am29000->alu |= (((INT32)(~((a) ^ (b)) & ((a) ^ (r))) < 0)) << ALU_V_SHIFT; + +#define SET_ALU_V_SUB(r, a, b) am29000->alu &= ~ALU_V; \ + am29000->alu |= ((INT32)(((a) ^ (b)) & ((a) ^ (r))) < 0) << ALU_V_SHIFT; + +#define GET_CARRY ((am29000->alu >> ALU_C_SHIFT) & 1) + + + +static UINT32 read_spr(am29000_state *am29000, UINT32 idx) +{ + UINT32 val = 0; + + switch (idx) + { + case SPR_VAB: val = am29000->vab; break; + case SPR_OPS: val = am29000->ops; break; + case SPR_CPS: val = am29000->cps; break; + case SPR_CFG: val = am29000->cfg; break; + case SPR_CHA: val = am29000->cha; break; + case SPR_CHD: val = am29000->chd; break; + case SPR_CHC: val = am29000->chc; break; + case SPR_RBP: val = am29000->rbp; break; + case SPR_TMC: val = am29000->tmc; break; + case SPR_TMR: val = am29000->tmr; break; + case SPR_PC0: val = am29000->pc0; break; + case SPR_PC1: val = am29000->pc1; break; + case SPR_PC2: val = am29000->pc2; break; + case SPR_MMU: val = am29000->mmu; break; + case SPR_LRU: val = am29000->lru; break; + case SPR_IPC: val = am29000->ipc; break; + case SPR_IPA: val = am29000->ipa; break; + case SPR_IPB: val = am29000->ipb; break; + case SPR_Q: val = am29000->q; break; + case SPR_ALU: val = am29000->alu; break; + case SPR_BP: val = GET_ALU_BP; break; + case SPR_FC: val = GET_ALU_FC; break; + case SPR_CR: val = GET_CHC_CR; break; + case SPR_FPE: val = am29000->fpe; break; + case SPR_INTE: val = am29000->inte; break; + case SPR_FPS: val = am29000->fps; break; + default: + logerror("Unknown SPR read (%d)\n", idx); + } + + return val; +} + + +static void write_spr(am29000_state *am29000, UINT32 idx, UINT32 val) +{ + switch (idx) + { + case SPR_VAB: am29000->vab = val & (VAB_MASK << VAB_SHIFT); + break; + case SPR_OPS: am29000->ops = val & (CPS_CA | CPS_IP | CPS_TE | CPS_TP | CPS_TU | CPS_FZ | CPS_LK | CPS_RE | + CPS_WM | CPS_PD | CPS_PI | CPS_SM | (CPS_IM_MASK << CPS_IM_SHIFT) | CPS_DI | CPS_DA); + break; + case SPR_CPS: am29000->cps = val & (CPS_CA | CPS_IP | CPS_TE | CPS_TP | CPS_TU | CPS_FZ | CPS_LK | CPS_RE | + CPS_WM | CPS_PD | CPS_PI | CPS_SM | (CPS_IM_MASK << CPS_IM_SHIFT) | CPS_DI | CPS_DA); + break; + case SPR_CFG: am29000->cfg = val & (CFG_DW | CFG_VF | CFG_RV | CFG_BO | CFG_CP | CFG_CD); + am29000->cfg |= PROCESSOR_REL_FIELD << CFG_PRL_SHIFT; + break; + case SPR_CHA: am29000->cha = val; + break; + case SPR_CHD: am29000->chd = val; + break; + case SPR_CHC: am29000->chc = val; + break; + case SPR_RBP: am29000->rbp = val & RBP_MASK; + break; + case SPR_TMC: am29000->tmc = val & TCV_MASK; + break; + case SPR_TMR: am29000->tmr = val & (TMR_OV | TMR_IN | TMR_IE | TMR_TRV_MASK); + break; + case SPR_PC0: am29000->pc0 = val & PC_MASK; + break; + case SPR_PC1: am29000->pc1 = val & PC_MASK; + break; + case SPR_PC2: am29000->pc2 = val & PC_MASK; + break; + case SPR_MMU: am29000->mmu = val & ((MMU_PS_MASK << MMU_PS_SHIFT) | MMU_PID_MASK); + break; + case SPR_LRU: am29000->lru = val & (LRU_MASK << LRU_SHIFT); + break; + case SPR_IPC: am29000->ipc = val;// & IPX_MASK; + break; + case SPR_IPA: am29000->ipa = val;// & IPX_MASK; + break; + case SPR_IPB: am29000->ipb = val;// & IPX_MASK; + break; + case SPR_Q: am29000->q = val; + break; + case SPR_ALU: am29000->alu = val & (ALU_DF | ALU_V | ALU_N | ALU_Z | ALU_C | (ALU_BP_MASK << ALU_BP_SHIFT) | (ALU_FC_MASK << ALU_FC_SHIFT)); + break; + case SPR_BP: am29000->alu &= ~(ALU_BP_MASK << ALU_BP_SHIFT); + am29000->alu |= (val & ALU_BP_MASK) << ALU_BP_SHIFT; + break; + case SPR_FC: am29000->alu &= ~(ALU_FC_MASK << ALU_FC_SHIFT); + am29000->alu |= (val & ALU_FC_MASK) << ALU_FC_SHIFT; + break; + case SPR_CR: am29000->chc &= ~(CHC_CR_MASK << CHC_CR_SHIFT); + am29000->chc |= (val & CHC_CR_MASK) << CHC_CR_SHIFT; + break; +// case SPR_FPE: +// case SPR_INTE: +// case SPR_FPS: + default: logerror("Unhandled SPR write (%d)\n", idx); + } +} + + +/*************************************************************************** + INSTRUCTIONS +***************************************************************************/ + +/*************************************************************************** + INTEGER ARITHMETIC +***************************************************************************/ + +static void ADD(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a + b; + + if (!FREEZE_MODE) + { + SET_ALU_V_ADD(r, a, b); + SET_ALU_Z(r); + SET_ALU_N(r); + SET_ALU_C_ADD(r, a); + } + + am29000->r[RC] = r; +} + +static void ADDS(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void ADDU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void ADDC(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void ADDCS(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a + b + GET_CARRY; + + if (!FREEZE_MODE) + { + UINT32 carry = GET_CARRY; + UINT32 tmp = a + b; + + SET_ALU_V_ADD(r, a, b); + SET_ALU_Z(r); + SET_ALU_N(r); + + carry = CALC_C_ADD(tmp, a) || CALC_C_ADD(tmp + carry, carry); + am29000->alu &= ~ALU_C; + am29000->alu |= carry << ALU_C_SHIFT; + } + + // TODO: Trap on signed overflow + am29000->r[RC] = r; +} + +static void ADDCU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUB(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r = a - b; + + if (!FREEZE_MODE) + { + SET_ALU_V_SUB(r, a, b); + SET_ALU_Z(r); + SET_ALU_N(r); + SET_ALU_C_SUB(a, b); + } + + // TODO: Trap on unsigned overflow + am29000->r[RC] = r; +} + +static void SUBS(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r = a - b; + + if (!FREEZE_MODE) + { + SET_ALU_V_SUB(r, a, b); + SET_ALU_Z(r); + SET_ALU_N(r); + SET_ALU_C_SUB(a, b); + } + + if ((INT32)(((a) ^ (b)) & ((a) ^ (r))) < 0) + SIGNAL_EXCEPTION(EXCEPTION_OUT_OF_RANGE); + + am29000->r[RC] = r; +} + +static void SUBU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUBC(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUBCS(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUBCU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUBR(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r = b - a; + + if (!FREEZE_MODE) + { + SET_ALU_V_SUB(r, a, b); + SET_ALU_Z(r); + SET_ALU_N(r); + SET_ALU_C_SUB(a, b); + } + + am29000->r[RC] = r; +} + +static void SUBRS(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUBRU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUBRC(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r = b - a - 1 + GET_CARRY; + + if (!FREEZE_MODE) + { + SET_ALU_V_SUB(r, a, b); + SET_ALU_Z(r); + SET_ALU_N(r); + SET_ALU_C_SUB(a, b); + } + + am29000->r[RC] = r; +} + +static void SUBRCS(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SUBRCU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void MULTIPLU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void MULTIPLY(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void MUL(am29000_state *am29000) +{ + /* TODO: Zero/Neg flags ? */ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r; + UINT64 v; + UINT32 sign; + + if (am29000->q & 1) + { + r = a + b; + sign = (r >> 31) ^ (((INT32)(~((a) ^ (b)) & ((a) ^ (r))) < 0)); + } + else + { + r = b; + sign = b >> 31; + } + + v = ((((UINT64)r << 32) | am29000->q) >> 1) | ((UINT64)sign << 63); + am29000->q = v & 0xffffffff; + + am29000->r[RC] = v >> 32; +} + +static void MULL(am29000_state *am29000) +{ + /* TODO: Zero/Neg flags ? */ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r; + UINT64 v; + UINT32 sign; + + if (am29000->q & 1) + { + r = b - a; + sign = (r >> 31) ^ ((INT32)(((a) ^ (b)) & ((a) ^ (r))) < 0); + } + else + { + r = b; + sign = b >> 31; + } + + v = ((((UINT64)r << 32) | am29000->q) >> 1) | ((UINT64)sign << 63); + am29000->q = v & 0xffffffff; + + am29000->r[RC] = v >> 32; +} + +static void MULU(am29000_state *am29000) +{ + /* TODO: Zero/Neg flags ? */ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r; + UINT64 v; + UINT32 c; + + if (am29000->q & 1) + { + r = a + b; + c = (UINT32)(r) < (UINT32)(a); + } + else + { + r = b; + c = 0; + } + + v = ((((UINT64)r << 32) | am29000->q) >> 1) | ((UINT64)c << 63); + am29000->q = v & 0xffffffff; + + am29000->r[RC] = v >> 32; +} + +static void DIVIDE(am29000_state *am29000) +{ + am29000->ipa = RA << IPX_SHIFT; + am29000->ipb = RB << IPX_SHIFT; + am29000->ipc = RC << IPX_SHIFT; + + SIGNAL_EXCEPTION(EXCEPTION_DIVIDE); +} + +static void DIVIDU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void DIV0(am29000_state *am29000) +{ + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT64 v; + + if (!FREEZE_MODE) + { + am29000->alu |= ALU_DF; + SET_ALU_N(b); + } + + v = (((UINT64)b << 32) | am29000->q) << 1; + + am29000->q = v & 0xffffffff; + + am29000->r[RC] = v >> 32; +} + +static void DIV(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 c; + UINT32 r; + UINT64 r64; + UINT32 df; + + if (am29000->alu & ALU_DF) + { + r = a - b; + c = !((UINT32)(a) < (UINT32)(b)); + } + else + { + r = a + b; + c = (UINT32)(r) < (UINT32)(a); + } + + + df = (~(c ^ (am29000->alu >> ALU_DF_SHIFT) ^ (am29000->alu >> ALU_N_SHIFT)) & 1); + + if (!FREEZE_MODE) + { + am29000->alu &= ~ALU_DF; + am29000->alu |= df << ALU_DF_SHIFT; + SET_ALU_N(r); + } + + r64 = ((((UINT64)r << 32) | am29000->q) << 1) | df; + am29000->q = r64 & 0xffffffff; + + am29000->r[RC] = r64 >> 32; +} + +static void DIVL(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 c; + UINT32 r; + UINT32 df; + + if (am29000->alu & ALU_DF) + { + r = a - b; + c = !((UINT32)(a) < (UINT32)(b)); + } + else + { + r = a + b; + c = (UINT32)(r) < (UINT32)(a); + } + + df = (~(c ^ (am29000->alu >> ALU_DF_SHIFT) ^ (am29000->alu >> ALU_N_SHIFT)) & 1); + + if (!FREEZE_MODE) + { + am29000->alu &= ~ALU_DF; + am29000->alu |= df << ALU_DF_SHIFT; + SET_ALU_N(r); + } + + am29000->q = (am29000->q << 1) | df; + am29000->r[RC] = r; +} + +static void DIVREM(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + + if (am29000->alu & ALU_DF) + am29000->r[RC] = a; + else + am29000->r[RC] = a + b; +} + + +/*************************************************************************** + COMPARE +***************************************************************************/ + +static void CPEQ(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a == b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPNEQ(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a != b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPLT(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (INT32)a < (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPLTU(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (UINT32)a < (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPLE(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (INT32)a <= (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPLEU(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (UINT32)a <= (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPGT(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (INT32)a > (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPGTU(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (UINT32)a > (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPGE(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (INT32)a >= (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPGEU(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = (UINT32)a >= (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void CPBYTE(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL; + UINT32 r = + ((a & 0xff000000) == (b & 0xff000000)) || + ((a & 0x00ff0000) == (b & 0x00ff0000)) || + ((a & 0x0000ff00) == (b & 0x0000ff00)) || + ((a & 0x000000ff) == (b & 0x000000ff)) + ? BOOLEAN_TRUE : BOOLEAN_FALSE; + + am29000->r[RC] = r; +} + +static void ASEQ(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!(GET_RA_VAL == GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASNEQ(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!(GET_RA_VAL != GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASLT(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((INT32)GET_RA_VAL < (INT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASLTU(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((UINT32)GET_RA_VAL < (UINT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASLE(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((INT32)GET_RA_VAL <= (INT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASLEU(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((UINT32)GET_RA_VAL <= (UINT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASGT(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((INT32)GET_RA_VAL > (INT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASGTU(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((UINT32)GET_RA_VAL > (UINT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASGE(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((INT32)GET_RA_VAL >= (INT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + +static void ASGEU(am29000_state *am29000) +{ + if (USER_MODE && INST_VN < 64) + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + else if (!((UINT32)GET_RA_VAL >= (UINT32)GET_RB_VAL)) + SIGNAL_EXCEPTION(INST_VN); +} + + +/*************************************************************************** + LOGICAL +***************************************************************************/ + +static void AND(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a & b; + + if (!FREEZE_MODE) + { + SET_ALU_Z(r); + SET_ALU_N(r); + } + + am29000->r[RC] = r; +} + +static void ANDN(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a & ~b; + + if (!FREEZE_MODE) + { + SET_ALU_Z(r); + SET_ALU_N(r); + } + + am29000->r[RC] = r; +} + +static void NAND(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = ~(a & b); + + if (!FREEZE_MODE) + { + SET_ALU_Z(r); + SET_ALU_N(r); + } + + am29000->r[RC] = r; +} + +static void OR(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a | b; + + if (!FREEZE_MODE) + { + SET_ALU_Z(r); + SET_ALU_N(r); + } + + am29000->r[RC] = r; +} + +static void NOR(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = ~(a | b); + + if (!FREEZE_MODE) + { + SET_ALU_Z(r); + SET_ALU_N(r); + } + + am29000->r[RC] = r; +} + +static void XOR(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = a ^ b; + + if (!FREEZE_MODE) + { + SET_ALU_Z(r); + SET_ALU_N(r); + } + + am29000->r[RC] = r; +} + +static void XNOR(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r = ~(a ^ b); + + if (!FREEZE_MODE) + { + SET_ALU_Z(r); + SET_ALU_N(r); + } + + am29000->r[RC] = r; +} + + +/*************************************************************************** + SHIFT +***************************************************************************/ + +static void SLL(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL) & 0x1f; + UINT32 r = a << b; + + am29000->r[RC] = r; +} + +static void SRL(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL) & 0x1f; + UINT32 r = a >> b; + + am29000->r[RC] = r; +} + +static void SRA(am29000_state *am29000) +{ + INT32 a = GET_RA_VAL; + UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL) & 0x1f; + UINT32 r = a >> b; + + am29000->r[RC] = r; +} + +static void EXTRACT(am29000_state *am29000) +{ + INT32 a = GET_RA_VAL; + UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL); + UINT64 r; + + r = (((UINT64)a << 32) | b) << GET_ALU_FC; + + am29000->r[RC] = r >> 32; +} + + +/*************************************************************************** + DATA MOVEMENT +***************************************************************************/ + +static void LOAD(am29000_state *am29000) +{ + UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r; + + if (INST_UA_BIT) + fatalerror("Am29000: UA bit set on LOAD\n"); + + if (INST_CE_BIT) + { + logerror("Am29000: Attempting a co-processor LOAD!\n"); + r = 0; + } + else + { + if (!INST_PA_BIT && !(am29000->cps & CPS_PD)) + { + fatalerror("Am29000: Address translation on LOAD\n"); + } + else + { + if (USER_MODE) + { + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + return; + } + + r = am29000->data->read_dword(addr); + } + } + +// if (opt & 2) +// logerror("Am29000: Half word LOAD\n"); + + if (!FREEZE_MODE) + { + am29000->chc = ((am29000->exec_ir << 8) & 0xff) | + CHC_LS | + RA << CHC_TR_SHIFT | + CHC_CV; + + am29000->cha = addr; + am29000->chd = r; + + if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT)) + SET_ALU_BP(addr & 3); + } + + am29000->r[RA] = r; + + if (am29000->cfg & CFG_DW) + logerror("DW ON A STORE"); +} + +static void LOADL(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void LOADSET(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void LOADM(am29000_state *am29000) +{ + UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r; + + if (INST_UA_BIT) + fatalerror("Am29000: UA bit set on LOAD\n"); + + if (INST_CE_BIT) + { + logerror("Am29000: Attempting a co-processor LOAD!\n"); + r = 0; + } + else + { + if (!INST_PA_BIT && !(am29000->cps & CPS_PD)) + { + fatalerror("Am29000: Address translation on LOAD\n"); + } + else + { + if (USER_MODE) + { + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + return; + } + + r = am29000->data->read_dword(addr); + } + } + + if (!FREEZE_MODE) + { + // TODO + am29000->chc &= (CHC_CR_MASK << CHC_CR_SHIFT); + am29000->chc |= ((am29000->exec_ir << 8) & 0xff) | + RA << CHC_TR_SHIFT | + CHC_CV; + + am29000->cha = addr; + am29000->chd = r; // ????? + + if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT)) + SET_ALU_BP(addr & 3); + } + + r = RA; + + { + int cnt; + for (cnt = 0; cnt <= GET_CHC_CR; ++cnt) + { + am29000->r[r] = am29000->data->read_dword(addr); + +// SET_CHC_CR(cnt - 1); + addr += 4; + + if (++r == 256) + r = 128; + } + } +} + +static void STORE(am29000_state *am29000) +{ + UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL; +// UINT32 r; + + if (INST_UA_BIT) + fatalerror("Am29000: UA bit set on LOAD\n"); + + if (INST_CE_BIT) + { + logerror("Am29000: Attempting a co-processor LOAD!\n"); +// r = 0; + } + else + { + if (!INST_PA_BIT && !(am29000->cps & CPS_PD)) + { + fatalerror("Am29000: Address translation on LOAD\n"); + } + else + { + if (USER_MODE) + { + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + return; + } + + } + } + + am29000->data->write_dword(addr, am29000->r[RA]); + + if (!FREEZE_MODE) + { + am29000->chc = ((am29000->exec_ir << 8) & 0xff) | + RA << CHC_TR_SHIFT | + CHC_CV; + + am29000->cha = addr; + + if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT)) + SET_ALU_BP(addr & 3); + } + + if (am29000->cfg & CFG_DW) + logerror("DW ON A STORE"); +} + +static void STOREL(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void STOREM(am29000_state *am29000) +{ + UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 r; + + if (INST_UA_BIT) + fatalerror("Am29000: UA bit set on LOAD\n"); + + if (INST_CE_BIT) + { + logerror("Am29000: Attempting a co-processor LOAD!\n"); + r = 0; + } + else + { + if (!INST_PA_BIT && !(am29000->cps & CPS_PD)) + { + fatalerror("Am29000: Address translation on LOAD\n"); + } + else + { + if (USER_MODE) + { + SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION); + return; + } + + } + } + + if (!FREEZE_MODE) + { + // TODO + am29000->chc &= (CHC_CR_MASK << CHC_CR_SHIFT); + am29000->chc |= ((am29000->exec_ir << 8) & 0xff) | + RA << CHC_TR_SHIFT | + CHC_CV; + + am29000->cha = addr; + + if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT)) + SET_ALU_BP(addr & 3); + } + + r = RA; + + { + int cnt; + for (cnt = 0; cnt <= GET_CHC_CR; ++cnt) + { + am29000->data->write_dword(addr, am29000->r[r]); + +// SET_CHC_CR(cnt - 1); + addr += 4; + + if (++r == 256) + r = 128; + } + } +} + +static void EXBYTE(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 bp = GET_ALU_BP; + UINT8 srcbyte; + UINT32 r; + + if (am29000->cfg & CFG_BO) + srcbyte = a >> 8 * bp; + else + srcbyte = a >> (8 * (3 - bp)); + + r = (b & 0xffffff00) | srcbyte; + + am29000->r[RC] = r; +} + +static void EXHW(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 wp = ((am29000->alu >> ALU_BP_SHIFT) & ALU_BP_MASK) >> 1; + UINT16 srcword; + UINT32 r; + + if (am29000->cfg & CFG_BO) + srcword = a >> 16 * wp; + else + srcword = a >> (16 * (1 - wp)); + + r = (b & 0xffff0000) | srcword; + + am29000->r[RC] = r; +} + +static void EXHWS(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 wp = ((am29000->alu >> ALU_BP_SHIFT) & ALU_BP_MASK) >> 1; + UINT16 srcword; + UINT32 r; + + if (am29000->cfg & CFG_BO) + srcword = a >> 16 * wp; + else + srcword = a >> (16 * (1 - wp)); + + r = (INT32)(INT16)srcword; + + am29000->r[RC] = r; +} + +static void INBYTE(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 bp = GET_ALU_BP; + UINT8 shift = (am29000->cfg & CFG_BO) ? 8 * bp : (8 * (3 - bp)); + UINT32 r; + + r = (a & ~(0xff << shift)) | ((b & 0xff) << shift); + + am29000->r[RC] = r; +} + +static void INHW(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + UINT32 wp = ((am29000->alu >> ALU_BP_SHIFT) & ALU_BP_MASK) >> 1; + UINT32 shift = (am29000->cfg & CFG_BO) ? 16 * wp : (16 * (1 - wp)); + UINT32 r; + + r = (a & ~(0xffff << shift)) | ((b & 0xffff) << shift); + + am29000->r[RC] = r; +} + +static void MFSR(am29000_state *am29000) +{ + am29000->r[RC] = read_spr(am29000, INST_SA); +} + +static void MFTLB(am29000_state *am29000) +{ + am29000->r[RC] = am29000->tlb[GET_RA_VAL & 0x7f]; +} + +static void MTSR(am29000_state *am29000) +{ + write_spr(am29000, INST_SA, GET_RB_VAL); +} + +static void MTSRIM(am29000_state *am29000) +{ + write_spr(am29000, INST_SA, I16_ZEX); +} + +static void MTTLB(am29000_state *am29000) +{ + am29000->tlb[GET_RA_VAL & 0x7f] = GET_RB_VAL; +} + + +/*************************************************************************** + CONSTANT +***************************************************************************/ + +static void CONST(am29000_state *am29000) +{ + am29000->r[RA] = I16_ZEX; +} + +static void CONSTH(am29000_state *am29000) +{ + am29000->r[RA] = (I16 << 16) | GET_RA_VAL; +} + +static void CONSTN(am29000_state *am29000) +{ + am29000->r[RA] = I16_OEX; +} + + +/*************************************************************************** + BRANCH INSTRUCTIONS +***************************************************************************/ + +static void CALL(am29000_state *am29000) +{ + UINT32 ret = am29000->next_pc; + + if (INST_M_BIT) + am29000->next_pc = JMP_ZEX; + else + am29000->next_pc = am29000->exec_pc + JMP_SEX; + + am29000->r[RA] = ret; +am29000->next_pl_flags |= PFLAG_JUMP; +} + +static void CALLI(am29000_state *am29000) +{ + UINT32 ret = am29000->next_pc; + am29000->next_pc = GET_RB_VAL; + am29000->r[RA] = ret; + am29000->next_pl_flags |= PFLAG_JUMP; +} + +static void JMP(am29000_state *am29000) +{ + if (INST_M_BIT) + am29000->next_pc = JMP_ZEX; + else + am29000->next_pc = am29000->exec_pc + JMP_SEX; + + am29000->next_pl_flags |= PFLAG_JUMP; +} + +static void JMPI(am29000_state *am29000) +{ + am29000->next_pc = GET_RB_VAL; + + am29000->next_pl_flags |= PFLAG_JUMP; +} + +static void JMPT(am29000_state *am29000) +{ + if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_TRUE) + { + if (INST_M_BIT) + am29000->next_pc = JMP_ZEX; + else + am29000->next_pc = am29000->exec_pc + JMP_SEX; + + am29000->next_pl_flags |= PFLAG_JUMP; + } +} + +static void JMPTI(am29000_state *am29000) +{ + if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_TRUE) + { + am29000->next_pc = GET_RB_VAL; + am29000->next_pl_flags |= PFLAG_JUMP; + } +} + +static void JMPF(am29000_state *am29000) +{ + if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_FALSE) + { + if (INST_M_BIT) + am29000->next_pc = JMP_ZEX; + else + am29000->next_pc = am29000->exec_pc + JMP_SEX; + + am29000->next_pl_flags |= PFLAG_JUMP; + } +} + +static void JMPFI(am29000_state *am29000) +{ + if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_FALSE) + { + am29000->next_pc = GET_RB_VAL; + am29000->next_pl_flags |= PFLAG_JUMP; + } +} + +static void JMPFDEC(am29000_state *am29000) +{ + UINT32 a = GET_RA_VAL; + + if ((a & BOOLEAN_MASK) == BOOLEAN_FALSE) + { + if (INST_M_BIT) + am29000->next_pc = JMP_ZEX; + else + am29000->next_pc = am29000->exec_pc + JMP_SEX; + + am29000->next_pl_flags |= PFLAG_JUMP; + } + + am29000->r[RA] = a - 1; +} + + +/*************************************************************************** + MISCELLANEOUS INSTRUCTIONS +***************************************************************************/ + +static void CLZ(am29000_state *am29000) +{ + UINT32 b = INST_M_BIT ? I8: GET_RB_VAL; + + am29000->r[RC] = count_leading_zeros(b); +} + +static void SETIP(am29000_state *am29000) +{ + am29000->ipa = RA << IPX_SHIFT; + am29000->ipb = RB << IPX_SHIFT; + am29000->ipc = RC << IPX_SHIFT; +} + +static void EMULATE(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void INV(am29000_state *am29000) +{ + /* Nothing to do yet */ +} + +static void IRET(am29000_state *am29000) +{ + am29000->iret_pc = am29000->pc0; + am29000->next_pc = am29000->pc1; + am29000->cps = am29000->ops; + am29000->next_pl_flags = PFLAG_IRET; +} + +static void IRETINV(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void HALT(am29000_state *am29000) +{ + UNHANDLED_OP; +} + + +static void ILLEGAL(am29000_state *am29000) +{ + fatalerror("Am29000: Executed illegal instruction - this should never happen! %x (%x)\n", am29000->pc2, am29000->exec_pc); +} + + + +/*************************************************************************** + UNHANDLED +***************************************************************************/ + +static void CONVERT(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void SQRT(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void CLASS(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void MULTM(am29000_state *am29000) +{ + UNHANDLED_OP; +} + +static void MULTMU(am29000_state *am29000) +{ + UNHANDLED_OP; +} + + +const op_info op_table[256] = +{ + { ILLEGAL, IFLAG_ILLEGAL }, + { CONSTN, IFLAG_RA_PRESENT }, + { CONSTH, IFLAG_RA_PRESENT }, + { CONST, IFLAG_RA_PRESENT }, + { MTSRIM, 0 }, + { ILLEGAL, IFLAG_ILLEGAL }, + { LOADL, 0 }, + { LOADL, 0 }, + { CLZ, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT }, + { CLZ, IFLAG_RC_PRESENT }, + { EXBYTE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { EXBYTE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { INBYTE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { INBYTE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { STOREL, 0 }, + { STOREL, 0 }, + { ADDS, 0 }, + { ADDS, 0 }, + { ADDU, 0 }, + { ADDU, 0 }, + { ADD, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { ADD, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { LOAD, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { LOAD, IFLAG_RA_PRESENT }, + { ADDCS, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { ADDCS, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ADDCU, 0 }, + { ADDCU, 0 }, + { ADDC, 0 }, + { ADDC, 0 }, + { STORE, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { STORE, IFLAG_RA_PRESENT }, + { SUBS, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { SUBS, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { SUBU, 0 }, + { SUBU, 0 }, + { SUB, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { SUB, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { LOADSET, 0 }, + { LOADSET, 0 }, + { SUBCS, 0 }, + { SUBCS, 0 }, + { SUBCU, 0 }, + { SUBCU, 0 }, + { SUBC, 0 }, + { SUBC, 0 }, + { CPBYTE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPBYTE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { SUBRS, 0 }, + { SUBRS, 0 }, + { SUBRU, 0 }, + { SUBRU, 0 }, + { SUBR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { SUBR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { LOADM, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { LOADM, IFLAG_RA_PRESENT }, + { SUBRCS, 0 }, + { SUBRCS, 0 }, + { SUBRCU, 0 }, + { SUBRCU, 0 }, + { SUBRC, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { SUBRC, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { STOREM, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { STOREM, IFLAG_RA_PRESENT }, + { CPLT, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPLT, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPLTU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPLTU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPLE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPLE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPLEU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPLEU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPGT, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPGT, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPGTU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPGTU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPGE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPGE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPGEU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPGEU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ASLT, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASLT, IFLAG_RA_PRESENT }, + { ASLTU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASLTU, IFLAG_RA_PRESENT }, + { ASLE, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASLE, IFLAG_RA_PRESENT }, + { ASLEU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASLEU, IFLAG_RA_PRESENT }, + { ASGT, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASGT, IFLAG_RA_PRESENT }, + { ASGTU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASGTU, IFLAG_RA_PRESENT }, + { ASGE, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASGE, IFLAG_RA_PRESENT }, + { ASGEU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASGEU, IFLAG_RA_PRESENT }, + { CPEQ, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPEQ, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { CPNEQ, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { CPNEQ, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { MUL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { MUL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { MULL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { MULL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { DIV0, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT }, + { DIV0, IFLAG_RC_PRESENT }, + { DIV, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { DIV, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { DIVL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { DIVL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { DIVREM, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { DIVREM, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ASEQ, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASEQ, IFLAG_RA_PRESENT }, + { ASNEQ, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ASNEQ, IFLAG_RA_PRESENT }, + { MULU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { MULU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { INHW, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { INHW, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { EXTRACT, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { EXTRACT, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { EXHW, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { EXHW, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { EXHWS, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { SLL, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { SLL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { SRL, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { SRL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { SRA, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { SRA, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { IRET, IFLAG_SUPERVISOR_ONLY }, + { HALT, IFLAG_SUPERVISOR_ONLY }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { IRETINV, IFLAG_SUPERVISOR_ONLY }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { AND, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { AND, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { OR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { OR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { XOR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { XOR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { XNOR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { XNOR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { NOR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { NOR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { NAND, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { NAND, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ANDN, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT }, + { ANDN, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { SETIP, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT | IFLAG_RC_PRESENT }, + { INV, IFLAG_SUPERVISOR_ONLY }, + { JMP, 0 }, + { JMP, 0 }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { JMPF, IFLAG_RA_PRESENT }, + { JMPF, IFLAG_RA_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { CALL, IFLAG_RA_PRESENT }, + { CALL, IFLAG_RA_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { JMPT, IFLAG_RA_PRESENT }, + { JMPT, IFLAG_RA_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { JMPFDEC, IFLAG_RA_PRESENT }, + { JMPFDEC, IFLAG_RA_PRESENT }, + { MFTLB, IFLAG_SUPERVISOR_ONLY | IFLAG_RC_PRESENT | IFLAG_RA_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { MTTLB, IFLAG_SUPERVISOR_ONLY | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { JMPI, IFLAG_RB_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { JMPFI, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { MFSR, IFLAG_RC_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { CALLI, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { JMPTI, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { MTSR, IFLAG_RB_PRESENT }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { EMULATE, 0 }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { MULTM, 0 }, + { MULTMU, 0 }, + { MULTIPLY, 0 }, + { DIVIDE, 0 }, + { MULTIPLU, 0 }, + { DIVIDU, 0 }, + { CONVERT, 0 }, + { SQRT, 0 }, + { CLASS, 0 }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + { ILLEGAL, IFLAG_ILLEGAL }, + // FEQ + // DEQ + // TODO! etc +}; |