diff options
Diffstat (limited to 'sim/mips/mips3264r6.igen')
-rw-r--r-- | sim/mips/mips3264r6.igen | 1226 |
1 files changed, 1226 insertions, 0 deletions
diff --git a/sim/mips/mips3264r6.igen b/sim/mips/mips3264r6.igen new file mode 100644 index 00000000000..b83c3098077 --- /dev/null +++ b/sim/mips/mips3264r6.igen @@ -0,0 +1,1226 @@ +110010,26.OFFSET:POOL32X:32::BC +"bc <OFFSET>" +*mips32r6: +*mips64r6: +{ + NIA = CIA + (EXTEND26 (OFFSET) << 2) + 4; +} + +111010,26.OFFSET:POOL32X:32::BALC +"balc <OFFSET>" +*mips32r6: +*mips64r6: +{ + RA = CIA + 4; + NIA = CIA + (EXTEND26 (OFFSET) << 2) + 4; +} + +110110,5.RS!0,21.OFFSET:POOL32X:32::BEQZC +"beqzc r<RS>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (GPR[RS] == 0) + NIA = CIA + (EXTEND21 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); +} + +110110,00000,5.RT,16.OFFSET:POOL32X:32::JIC +"jic r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + NIA = GPR[RT] + (EXTEND16(OFFSET) << 2); +} + +111110,5.RS!0,21.OFFSET:POOL32X:32::BNEZC +"bnezc r<RS>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (GPR[RS] != 0) + NIA = CIA + (EXTEND21 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); +} + +111110,00000,5.RT,16.OFFSET:POOL32X:32::JIALC +"jialc r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + RA = CIA + 4; + NIA = GPR[RT] + EXTEND16(OFFSET); +} + +010110,5.RS,5.RT,16.OFFSET:POOL32X:32::B1xxC +"blezc r<RT>, <OFFSET>": RS==0&&RT!=0 +"bgezc r<RT>, <OFFSET>":RS!=0&&RS==RT +"bgec r<RS>, r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (RS == 0 && RT != 0) + { + //BLEZC + if ((signed_word)GPR[RT] <= 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else if (RS != 0 && RS == RT) + { + //BGEZC + if ((signed_word)GPR[RT] >= 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else + { + //BGEC + if ((signed_word) GPR[RS] >= (signed_word) GPR[RT]) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } +} + +010111,5.RS,5.RT,16.OFFSET:POOL32X:32::B2xxC +"bgtzc r<RT>, <OFFSET>":RS==0&&RT!=0 +"bltzc r<RT>, <OFFSET>":RS!=0&&RS==RT +"bltc r<RS>, r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (RS == 0 && RT != 0) + { + //BGTZC + if ((signed_word)GPR[RT] > 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else if (RS != 0 && RS == RT) + { + //BLTZC + if ((signed_word)GPR[RT] < 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else + { + //BLTC + if ((signed_word) GPR[RS] < (signed_word) GPR[RT]) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } +} + +000110,5.RS,5.RT!0,16.OFFSET:POOL32X:32::B3xxC +"blezalc r<RT>, <OFFSET>":RS==0 +"bgezalc r<RT>, <OFFSET>":RS!=0&&RS==RT +"bgeuc r<RS>, r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (RS == 0 && RT != 0) + { + //BLEZALC + RA = CIA + 4; + if ((signed_word)GPR[RT] <= 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else if (RS != 0 && RS == RT) + { + //BGEZALC + RA = CIA + 4; + if ((signed_word)GPR[RT] >= 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else + { + //BGEUC + if (GPR[RS] >= GPR[RT]) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } +} + +000111,5.RS,5.RT!0,16.OFFSET:POOL32X:32::B4xxC +"bgtzalc r<RT>, <OFFSET>":RS==0 +"bltzalc r<RT>, <OFFSET>":RS!=0&&RS==RT +"bltuc r<RS>, r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (RS == 0 && RT != 0) + { + //BGTZALC + RA = CIA + 4; + if ((signed_word)GPR[RT] > 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else if (RS != 0 && RS == RT) + { + //BLTZALC + RA = CIA + 4; + if ((signed_word)GPR[RT] < 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else + { + //BLTUC + if (GPR[RS] < GPR[RT]) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } +} + +001000,5.RS,5.RT,16.OFFSET:POOL32X:32::BxxxC +"bovc r<RS>, r<RT>, <OFFSET>":RS>=RT +"beqzalc r<RT>, <OFFSET>":RS==0&&RT>RS +"beqc r<RS>, r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (RS >= RT) + { + //BOVC + ALU32_BEGIN (GPR[RS] & 0x0ffffffff); + ALU32_ADD (GPR[RT] & 0x0ffffffff); + + if (ALU32_HAD_OVERFLOW) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else if (RS == 0) + { + RA = CIA + 4; + //BEQZALC + if (GPR[RT] == 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else + { + //BEQC + if (GPR[RS] == GPR[RT]) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } +} + +011000,5.RS,5.RT,16.OFFSET:POOL32X:32::BNxxxC +"bnvc r<RS>, r<RT>, <OFFSET>":RS>=RT +"bnezalc r<RT>, <OFFSET>":RS==0&&RT>RS +"bnec r<RS>, r<RT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + if (RS >= RT) + { + //BNVC + ALU32_BEGIN (GPR[RS] & 0x0ffffffff); + ALU32_ADD (GPR[RT] & 0x0ffffffff); + + if (!ALU32_HAD_OVERFLOW) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else if (RS == 0 && RT > RS) + { + //BNEZALC + RA = CIA + 4; + if (GPR[RT] != 0) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } + else + { + //BNEC + if (GPR[RT] != GPR[RS]) + NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4; + else + FORBIDDEN_SLOT (); + } +} + +:%s::::R6COND:int r6cond +{ + switch (r6cond) + { + case FP_R6CMP_SAF: + return "SAF"; + case FP_R6CMP_SUN: + return "SUN"; + case FP_R6CMP_SOR: + return "SOR"; + case FP_R6CMP_SEQ: + return "SEQ"; + case FP_R6CMP_SUNE: + return "SUNE"; + case FP_R6CMP_SUEQ: + return "SUEQ"; + case FP_R6CMP_SNE: + return "SNE"; + case FP_R6CMP_SLT: + return "SLT"; + case FP_R6CMP_SULT: + return "SULT"; + case FP_R6CMP_SLE: + return "SLE"; + case FP_R6CMP_SULE: + return "SULE"; + case FP_R6CMP_AF: + return "AF"; + case FP_R6CMP_UN: + return "UN"; + case FP_R6CMP_OR: + return "OR"; + case FP_R6CMP_EQ: + return "EQ"; + case FP_R6CMP_UNE: + return "UNE"; + case FP_R6CMP_UEQ: + return "UEQ"; + case FP_R6CMP_NE: + return "NE"; + case FP_R6CMP_LT: + return "LT"; + case FP_R6CMP_ULT: + return "ULT"; + case FP_R6CMP_LE: + return "LE"; + case FP_R6CMP_ULE: + return "ULE"; + default: + abort (); + } +} + +010001,1010,1.FMT,5.FT,5.FS,5.FD,0,5.R6COND:POOL32X:32,f::CMP.cond.fmt +"cmp.%s<R6COND>.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + uint64_t result; + check_fpu (SD_); + TRACE_ALU_INPUT2 (ValueFPR (FS, FMT), ValueFPR (FT, FMT)); + + result = R6Compare (ValueFPR (FS, FMT), ValueFPR (FT, FMT), FMT, R6COND); + StoreFPR (FD, FMT, result); + TRACE_ALU_RESULT (result); +} + +010001,01001,5.FT,16.OFFSET:POOL32X:32,f::BC1EQZ +"bc1eqz f<FT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_fpu (SD_); + TRACE_ALU_INPUT1 (FGR[FT]); + if ((FGR[FT] & 0x01) == 0) + DELAY_SLOT (NIA + offset); +} + +010001,01101,5.FT,16.OFFSET:POOL32X:32,f::BC1NEZ +"bc1nez f<FT>, <OFFSET>" +*mips32r6: +*mips64r6: +{ + address_word offset = EXTEND16 (OFFSET) << 2; + check_fpu (SD_); + TRACE_ALU_INPUT1 (FGR[FT]); + if ((FGR[FT] & 0x01) != 0) + DELAY_SLOT (NIA + offset); +} +010001,1000,1.FMT,5.FT,5.FS,5.FD,011000:POOLX:32,f::MADDF.fmt +"maddf.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + TRACE_ALU_INPUT3 (FGR[FD], FGR[FS], FGR[FT]); + StoreFPR (FD, fmt, FusedMultiplyAdd (ValueFPR (FS, fmt), + ValueFPR (FT, fmt), + ValueFPR (FD, fmt), fmt)); + TRACE_ALU_RESULT (FGR[FD]); +} + +010001,1000,1.FMT,5.FT,5.FS,5.FD,011001:POOLX:32,f::MSUBF.fmt +"msubf.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + TRACE_ALU_INPUT3 (FGR[FD], FGR[FS], FGR[FT]); + StoreFPR (FD, fmt, FusedMultiplySub (ValueFPR (FS, fmt), + ValueFPR (FT, fmt), + ValueFPR (FD, fmt), fmt)); + TRACE_ALU_RESULT (FGR[FD]); +} + +000000,5.RS,5.RT,5.RD,000,2.IMM,000101:SPECIAL:32::LSA +"lsa r<RD>, r<RS>, r<RT>, <IMM + 1>" +*mips32r6: +*mips64r6: +{ + uint32_t t = GPR[RS] << (IMM + 1); + GPR[RD] = EXTEND32(GPR[RT] + t); + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,000,2.IMM,010101:SPECIAL:64::DLSA +"dlsa r<RD>, r<RS>, r<RT>, <IMM + 1>" +*mips64r6: +{ + uint64_t t = GPR[RS] << (IMM + 1); + GPR[RD] = GPR[RT] + t; + TRACE_ALU_RESULT (GPR[RD]); +} + +001111,5.RS!0,5.RT,16.IMMEDIATE:POOL32X:32::AUI +"aui r<RS>, r<RT>, <IMMEDIATE>" +*mips32r6: +*mips64r6: +{ + TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE); + GPR[RT] = EXTEND32 (GPR[RS] + (EXTEND16 (IMMEDIATE) << 16)); + TRACE_ALU_RESULT (GPR[RT]); +} + +011101,5.RS!0,5.RT,16.IMMEDIATE:POOL32X:64::DAUI +"daui r<RS>, r<RT>, <IMMEDIATE>" +*mips64r6: +{ + TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE); + GPR[RT] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 16); + TRACE_ALU_RESULT (GPR[RT]); +} + +000001,5.RS,00110,16.IMMEDIATE:POOL32X:64::DAHI +"dahi r<RS>, <IMMEDIATE>" +*mips64r6: +{ + TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE); + GPR[RS] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 32); + TRACE_ALU_RESULT (GPR[RS]); +} + +000001,5.RS,11110,16.IMMEDIATE:POOL32X:64::DATI +"dati r<RS>, <IMMEDIATE>" +*mips64r6: +{ + TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE); + GPR[RS] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 48); + TRACE_ALU_RESULT (GPR[RS]); +} + +011111,5.RS,5.RT,5.RD,010,2.IMMEDIATE,100000:POOL32X:32::ALIGN +"align r<RD>, r<RS>, r<RT>, <IMMEDIATE>" +*mips32r6: +*mips64r6: +{ + uint32_t rs = GPR[RS]; + uint32_t rt = GPR[RT]; + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + GPR[RD] = EXTEND32 (rs >> 8 * (4 - IMMEDIATE) | rt << 8 * IMMEDIATE); + TRACE_ALU_RESULT (GPR[RD]); +} + +011111,5.RS,5.RT,5.RD,01,3.IMMEDIATE,100100:POOL32X:64::DALIGN +"dalign r<RD>, r<RS>, r<RT>, <IMMEDIATE>" +*mips64r6: +{ + uint64_t rs = GPR[RS]; + uint64_t rt = GPR[RT]; + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + GPR[RD] = rs >> 8 * (8 - IMMEDIATE) | rt << 8 * IMMEDIATE; + TRACE_ALU_RESULT (GPR[RD]); +} + +011111,00000,5.RT,5.RD,00000,100000:POOL32X:32::BITSWAP +"bitswap r<RD>, r<RT>" +*mips32r6: +*mips64r6: +{ + /* Taken from: http://graphics.stanford.edu/~seander/bithacks.html */ + uint32_t v = GPR[RT]; + + TRACE_ALU_INPUT1 (v); + v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); + v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); + v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); + GPR[RD] = EXTEND32 (v); + TRACE_ALU_RESULT(GPR[RD]); +} + +011111,00000,5.RT,5.RD,00000,100100:POOL32X:64::DBITSWAP +"dbitswap r<RD>, r<RT>" +*mips64r6: +{ + /* Taken from: http://graphics.stanford.edu/~seander/bithacks.html */ + uint64_t v = GPR[RT]; + + TRACE_ALU_INPUT1 (v); + v = ((v >> 1) & 0x5555555555555555) | ((v & 0x5555555555555555) << 1); + v = ((v >> 2) & 0x3333333333333333) | ((v & 0x3333333333333333) << 2); + v = ((v >> 4) & 0x0F0F0F0F0F0F0F0F) | ((v & 0x0F0F0F0F0F0F0F0F) << 4); + TRACE_ALU_RESULT(v); + GPR[RD] = v; +} + +111011,5.RS,00,19.IMMEDIATE:POOL32X:32::ADDIUPC +"addiupc r<RS>, <IMMEDIATE>" +*mips32r6: +*mips64r6: +{ + TRACE_ALU_INPUT1 (IMMEDIATE); + GPR[RS] = loadstore_ea (SD_, CIA, EXTEND19 (IMMEDIATE) << 2); + TRACE_ALU_RESULT (GPR[RS]); +} + +111011,5.RS,11110,16.IMMEDIATE:POOL32X:32::AUIPC +"auipc r<RS>, <IMMEDIATE>" +*mips32r6: +*mips64r6: +{ + TRACE_ALU_INPUT1 (IMMEDIATE); + GPR[RS] = loadstore_ea (SD_, CIA, EXTEND32 (IMMEDIATE << 16)); + TRACE_ALU_RESULT (GPR[RS]); +} + +111011,5.RS,11111,16.IMMEDIATE:POOL32X:32::ALUIPC +"aluipc r<RS>, <IMMEDIATE>" +*mips32r6: +*mips64r6: +{ + TRACE_ALU_INPUT1 (IMMEDIATE); + GPR[RS] = ~0x0FFFF & loadstore_ea (SD_, CIA, EXTEND32 (IMMEDIATE << 16)); + TRACE_ALU_RESULT (GPR[RS]); +} + +111011,5.RS,01,19.IMMEDIATE:POOL32X:32::LWPC +"lwpc r<RS>, <IMMEDIATE>" +*mips32r6: +*mips64r6: +{ + uint32_t offset = EXTEND19 (IMMEDIATE) << 2; + TRACE_ALU_INPUT1 (IMMEDIATE); + GPR[RS] = EXTEND32 (do_load (SD_, AccessLength_WORD, CIA, offset)); + TRACE_ALU_RESULT (GPR[RS]); +} + +111011,5.RS,10,19.IMMEDIATE:POOL32X:64::LWUPC +"lwupc r<RS>, <IMMEDIATE>" +*mips64r6: +{ + uint32_t offset = EXTEND19 (IMMEDIATE) << 2; + TRACE_ALU_INPUT1 (CIA + offset); + GPR[RS] = do_load (SD_, AccessLength_WORD, CIA, offset); + TRACE_ALU_RESULT (GPR[RS]); +} + +111011,5.RS,110,18.IMMEDIATE:POOL32X:64::LDPC +"ldpc r<RS>, <IMMEDIATE>" +*mips64r6: +{ + uint32_t offset = EXTEND18 (IMMEDIATE) << 3; + TRACE_ALU_INPUT1 (IMMEDIATE); + GPR[RS] = do_load (SD_, AccessLength_DOUBLEWORD, CIA, offset); + TRACE_ALU_RESULT (GPR[RS]); +} +010001,1000,1.FMT,00000,5.FS,5.FD,011010::32,64,f::RINT.fmt +"rint.%s<FMT> f<FD>, f<FS>" +*mips32r6: +*mips64r6: +{ + uint64_t result; + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + TRACE_ALU_INPUT1 (FGR[FS]); + RoundToIntegralExact (ValueFPR (FS, fmt), &result, fmt); + StoreFPR (FD, fmt, result); + TRACE_ALU_RESULT (FGR[FD]); +} + +010001,1000,1.FMT,00000,5.FS,5.FD,011011::32,64,f::CLASS.fmt +"class.%s<FMT> f<FD>, f<FS>" +*mips32r6: +*mips64r6: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, Classify (ValueFPR (FS, fmt), fmt)); +} + +010001,1000,1.FMT,5.FT,5.FS,5.FD,011100::32,64,f::MIN.fmt +"min.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + TRACE_ALU_INPUT2 (FGR[FS], FGR[FT]); + StoreFPR (FD, fmt, Min (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + TRACE_ALU_RESULT (FGR[FD]); +} + +010001,1000,1.FMT,5.FT,5.FS,5.FD,011110::32,64,f::MAX.fmt +"max.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + TRACE_ALU_INPUT2 (FGR[FS], FGR[FT]); + StoreFPR (FD, fmt, Max (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + TRACE_ALU_RESULT (FGR[FD]); +} + +010001,1000,1.FMT,5.FT,5.FS,5.FD,011101::32,64,f::MINA.fmt +"mina.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + TRACE_ALU_INPUT2 (FGR[FS], FGR[FT]); + StoreFPR (FD, fmt, MinA (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + TRACE_ALU_RESULT (FGR[FD]); +} + +010001,1000,1.FMT,5.FT,5.FS,5.FD,011111::32,64,f::MAXA.fmt +"maxa.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + TRACE_ALU_INPUT2 (FGR[FS], FGR[FT]); + StoreFPR (FD, fmt, MaxA (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); + TRACE_ALU_RESULT (FGR[FD]); +} +000000,5.RS,5.RT,5.RD,00010,011000:POOL32X:32::MUL +"mul r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + int64_t prod; + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + prod = ((int64_t)(int32_t) GPR[RS]) + * ((int64_t)(int32_t) GPR[RT]); + GPR[RD] = EXTEND32 (VL4_8 (prod)); + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011000:POOL32X:32::MUH +"muh r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + int64_t prod; + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + prod = ((int64_t)(int32_t) GPR[RS]) + * ((int64_t)(int32_t) GPR[RT]); + GPR[RD] = EXTEND32 (VH4_8 (prod)); + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00010,011001:POOL32X:32::MULU +"mulu r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + uint64_t prod; + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + prod = ((uint64_t)(uint32_t) GPR[RS]) + * ((uint64_t)(uint32_t) GPR[RT]); + GPR[RD] = EXTEND32 (VL4_8 (prod)); + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011001:POOL32X:32::MUHU +"muhu r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + uint64_t prod; + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + prod = ((uint64_t)(uint32_t) GPR[RS]) + * ((uint64_t)(uint32_t) GPR[RT]); + GPR[RD] = EXTEND32 (VH4_8 (prod)); + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00010,011010:POOL32X:32::DIV +"div r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + int32_t n = GPR[RS]; + int32_t d = GPR[RT]; + TRACE_ALU_INPUT2 (n,d); + if (d == 0) + GPR[RD] = EXTEND32 (0x80000000); + else if (n == SIGNED32 (0x80000000) && d == -1) + GPR[RD] = EXTEND32 (0x80000000); + else + GPR[RD] = EXTEND32 (n / d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011010:POOL32X:32::MOD +"mod r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + int32_t n = GPR[RS]; + int32_t d = GPR[RT]; + TRACE_ALU_INPUT2 (n,d); + if (d == 0 || (n == SIGNED32 (0x80000000) && d == -1)) + GPR[RD] = EXTEND32 (0); + else + GPR[RD] = EXTEND32 (n % d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00010,011011:POOL32X:32::DIVU +"divu r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + uint32_t n = GPR[RS]; + uint32_t d = GPR[RT]; + TRACE_ALU_INPUT2 (n,d); + if (d == 0) + GPR[RD] = EXTEND32 (0x80000000); + else + GPR[RD] = EXTEND32 (n / d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011011:POOL32X:32::MODU +"modu r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + uint32_t n = GPR[RS]; + uint32_t d = GPR[RT]; + TRACE_ALU_INPUT2 (n,d); + if (d == 0) + GPR[RD] = EXTEND32 (0); + else + GPR[RD] = EXTEND32 (n % d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00010,011100:POOL32X:64::DMUL +"dmul r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + uint64_t lo; + uint64_t m00; + uint64_t m01; + uint64_t m10; + uint64_t mid; + int sign; + uint64_t op1 = GPR[RS]; + uint64_t op2 = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (op1, op2); + /* make signed multiply unsigned */ + sign = 0; + if ((int64_t) op1 < 0) + { + op1 = - op1; + ++sign; + } + if ((int64_t) op2 < 0) + { + op2 = - op2; + ++sign; + } + /* multiply out the sub products */ + m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2)); + m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2)); + m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2)); + /* add the products */ + mid = ((uint64_t) VH4_8 (m00) + + (uint64_t) VL4_8 (m10) + + (uint64_t) VL4_8 (m01)); + lo = U8_4 (mid, m00); + /* fix the sign */ + if (sign & 1) + lo = -lo; + + GPR[RD] = lo; + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011100:POOL32X:64::DMUH +"dmuh r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + uint64_t lo; + uint64_t hi; + uint64_t m00; + uint64_t m01; + uint64_t m10; + uint64_t m11; + uint64_t mid; + int sign; + uint64_t op1 = GPR[RS]; + uint64_t op2 = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (op1, op2); + /* make signed multiply unsigned */ + sign = 0; + if ((int64_t) op1 < 0) + { + op1 = - op1; + ++sign; + } + if ((int64_t) op2 < 0) + { + op2 = - op2; + ++sign; + } + /* multiply out the 4 sub products */ + m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2)); + m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2)); + m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2)); + m11 = ((uint64_t) VH4_8 (op1) * (uint64_t) VH4_8 (op2)); + /* add the products */ + mid = ((uint64_t) VH4_8 (m00) + + (uint64_t) VL4_8 (m10) + + (uint64_t) VL4_8 (m01)); + lo = U8_4 (mid, m00); + hi = (m11 + + (uint64_t) VH4_8 (mid) + + (uint64_t) VH4_8 (m01) + + (uint64_t) VH4_8 (m10)); + /* fix the sign */ + if (sign & 1) + { + lo = -lo; + if (lo == 0) + hi = -hi; + else + hi = -hi - 1; + } + + GPR[RD] = hi; + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00010,011101:POOL32X:64::DMULU +"dmulu r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + uint64_t lo; + uint64_t m00; + uint64_t m01; + uint64_t m10; + uint64_t mid; + uint64_t op1 = GPR[RS]; + uint64_t op2 = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (op1, op2); + /* multiply out the sub products */ + m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2)); + m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2)); + m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2)); + /* add the products */ + mid = ((uint64_t) VH4_8 (m00) + + (uint64_t) VL4_8 (m10) + + (uint64_t) VL4_8 (m01)); + lo = U8_4 (mid, m00); + + GPR[RD] = lo; + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011101:POOL32X:64::DMUHU +"dmuhu r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + uint64_t lo; + uint64_t hi; + uint64_t m00; + uint64_t m01; + uint64_t m10; + uint64_t m11; + uint64_t mid; + uint64_t op1 = GPR[RS]; + uint64_t op2 = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (op1, op2); + /* multiply out the 4 sub products */ + m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2)); + m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2)); + m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2)); + m11 = ((uint64_t) VH4_8 (op1) * (uint64_t) VH4_8 (op2)); + /* add the products */ + mid = ((uint64_t) VH4_8 (m00) + + (uint64_t) VL4_8 (m10) + + (uint64_t) VL4_8 (m01)); + lo = U8_4 (mid, m00); + hi = (m11 + + (uint64_t) VH4_8 (mid) + + (uint64_t) VH4_8 (m01) + + (uint64_t) VH4_8 (m10)); + + GPR[RD] = hi; + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00010,011110:POOL32X:64::DDIV +"ddiv r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + int64_t n = GPR[RS]; + int64_t d = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (n, d); + if (d == 0) + GPR[RD] = SIGNED64 (0x8000000000000000); + else if (d == -1 && n == SIGNED64 (0x8000000000000000)) + GPR[RD] = SIGNED64 (0x8000000000000000); + else + GPR[RD] = (n / d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011110:POOL32X:64::DMOD +"dmod r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + int64_t n = GPR[RS]; + int64_t d = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (n, d); + if (d == 0 || (d == -1 && n == SIGNED64 (0x8000000000000000))) + GPR[RD] = SIGNED64 (0); + else + GPR[RD] = (n % d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00010,011111:POOL32X:64::DDIVU +"ddivu r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + uint64_t n = GPR[RS]; + uint64_t d = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (n, d); + if (d == 0) + GPR[RD] = UNSIGNED64 (0x8000000000000000); + else + GPR[RD] = (n / d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00011,011111:POOL32X:64::DMODU +"dmodu r<RD>, r<RS>, r<RT>" +*mips64r6: +{ + uint64_t n = GPR[RS]; + uint64_t d = GPR[RT]; + + check_u64 (SD_, instruction_0); + TRACE_ALU_INPUT2 (n, d); + if (d == 0) + GPR[RD] = UNSIGNED64 (0); + else + GPR[RD] = (n % d); + + TRACE_ALU_RESULT (GPR[RD]); +} + +011111,5.BASE,5.RT,9.OFFSET,0,110110:SPECIAL3:32::LL +"ll r<RT>, <OFFSET>(r<BASE>)" +*mips32r6: +*mips64r6: +{ + do_ll (SD_, RT, EXTEND9 (OFFSET), BASE); +} + +011111,5.BASE,5.RT,5.RD,0000,1,110110:SPECIAL3:32::LLWP +"llwp r<RT>, r<RD>, (r<BASE>)" +*mips32r6: +*mips64r6: +{ + int first, second; + int offset; + + if (RT == BASE) + { + first = RD; + second = RT; + offset = BigEndianCPU ? 0 : 4; + } + else + { + first = RT; + second = RD; + offset = BigEndianCPU ? 4 : 0; + } + + do_ll (SD_, first, offset, BASE); + do_ll (SD_, second, offset ^ 4, BASE); +} + + +011111,5.BASE,5.RT,9.OFFSET,0,100110:SPECIAL3:32::SC +"sc r<RT>, <OFFSET>(r<BASE>)" +*mips32r6: +*mips64r6: +{ + do_sc (SD_, RT, EXTEND9 (OFFSET), BASE, instruction_0, 1); +} + +011111,5.BASE,5.RT,9.OFFSET,0,110111:SPECIAL3:64::LLD +"lld r<RT>, <OFFSET>(r<BASE>)" +*mips64r6: +{ + check_u64 (SD_, instruction_0); + do_lld (SD_, RT, EXTEND9 (OFFSET), BASE); +} + + +011111,5.BASE,5.RT,5.RD,0000,1,100110:SPECIAL3:32::SCWP +"scwp r<RT>, r<RD>, (r<BASE>)" +*mips32r6: +*mips64r6: +{ + int offset = BigEndianCPU ? 0 : 4; + + do_sc (SD_, RD, offset, BASE, instruction_0, 0); + do_sc (SD_, RT, offset ^ 4, BASE, instruction_0, 1); +} + +011111,5.BASE,5.RT,5.RD,0000,1,110111:SPECIAL3:64::LLDP +"lldp r<RT>, r<RD>, (r<BASE>)" +*mips64r6: +{ + int first, second; + int offset; + + check_u64 (SD_, instruction_0); + + if (RT == BASE) + { + first = RD; + second = RT; + offset = BigEndianCPU ? 0 : 8; + } + else + { + first = RT; + second = RD; + offset = BigEndianCPU ? 8 : 0; + } + + do_lld (SD_, first, offset, BASE); + do_lld (SD_, second, offset ^ 8, BASE); +} + +011111,5.BASE,5.RT,9.OFFSET,0,100111:SPECIAL3:64::SCD +"scd r<RT>, <OFFSET>(r<BASE>)" +*mips64r6: +{ + check_u64 (SD_, instruction_0); + do_scd (SD_, RT, EXTEND9 (OFFSET), BASE, 1); +} + +011111,5.BASE,5.RT,5.RD,0000,1,100111:SPECIAL3:64::SCDP +"scdp r<RT>, r<RD>, (r<BASE>)" +*mips64r6: +{ + int offset = BigEndianCPU ? 0 : 8; + check_u64 (SD_, instruction_0); + + do_scd (SD_, RD, offset, BASE, 0); + do_scd (SD_, RT, offset ^ 8, BASE, 1); +} + +011111,5.BASE,5.HINT,9.OFFSET,0,110101:SPECIAL3:32::PREF +"pref <HINT>, <OFFSET>(r<BASE>)" +*mips32r6: +*mips64r6: +{ + do_pref (SD_, HINT, EXTEND9 (OFFSET), BASE); +} + +011111,5.BASE,5.HINT,9.OFFSET,0,100101:SPECIAL3:32::CACHE +"cache <HINT>, <OFFSET>(r<BASE>)" +*mips32r6: +*mips64r6: +{ + do_cache (SD_, HINT, BASE, EXTEND9 (OFFSET), instruction_0); +} + + +000000,5.RS,00000,5.RD,00001,010000:POOL32X:32::CLZ +"clz r<RD>, r<RS>" +*mips32r6: +*mips64r6: +{ + do_clz (SD_, RD, RS); +} + +000000,5.RS,00000,5.RD,00001,010001:POOL32X:32::CLO +"clo r<RD>, r<RS>" +*mips32r6: +*mips64r6: +{ + do_clo (SD_, RD, RS); +} + +000000,5.RS,00000,5.RD,00001,010010:POOL32X:64::DCLZ +"dclz r<RD>, r<RS>" +*mips64r6: +{ + check_u64 (SD_, instruction_0); + do_dclz (SD_, RD, RS); +} + +000000,5.RS,00000,5.RD,00001,010011:POOL32X:64::DCLO +"dclo r<RD>, r<RS>" +*mips64r6: +{ + check_u64 (SD_, instruction_0); + do_dclo (SD_, RD, RS); +} +010001,1000,1.FMT,5.FT,5.FS,5.FD,010000:POOL32X:32,f::SEL.fmt +"sel.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + check_fpu (SD_); + check_fmt_p (SD_, FMT, instruction_0); + TRACE_ALU_INPUT3 (FGR[FD], ValueFPR(FS, FMT), ValueFPR(FT, FMT)); + if ((FGR[FD] & 0x01) != 0) + StoreFPR (FD, FMT, ValueFPR (FT, FMT)); + else + StoreFPR (FD, FMT, ValueFPR (FS, FMT)); + TRACE_ALU_RESULT (ValueFPR(FD, FMT)); +} + +010001,1000,1.FMT,5.FT,5.FS,5.FD,010100:POOL32X:32,f::SELEQZ.fmt +"seleqz.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + check_fpu (SD_); + check_fmt_p (SD_, FMT, instruction_0); + TRACE_ALU_INPUT2 (ValueFPR(FS, FMT), FGR[FT]); + if ((FGR[FT] & 0x01) == 0) + StoreFPR (FD, FMT, ValueFPR (FS, FMT)); + else + StoreFPR (FD, FMT, 0); + TRACE_ALU_RESULT (ValueFPR(FD, FMT)); +} + +010001,1000,1.FMT,5.FT,5.FS,5.FD,010111:POOL32X:32,f::SELNEZ.fmt +"selnez.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips32r6: +*mips64r6: +{ + check_fpu (SD_); + check_fmt_p (SD_, FMT, instruction_0); + TRACE_ALU_INPUT2 (ValueFPR(FS, FMT), FGR[FT]); + if ((FGR[FT] & 0x01) == 0) + StoreFPR (FD, FMT, 0); + else + StoreFPR (FD, FMT, ValueFPR (FS, FMT)); + TRACE_ALU_RESULT (ValueFPR(FD, FMT)); +} + +000000,5.RS,5.RT,5.RD,00000,110101:POOL32X:32::SELEQZ +"seleqz r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + if (GPR[RT] != 0) + GPR[RD] = 0; + else + GPR[RD] = GPR[RS]; + TRACE_ALU_RESULT (GPR[RD]); +} + +000000,5.RS,5.RT,5.RD,00000,110111:POOL32X:32::SELNEZ +"selnez r<RD>, r<RS>, r<RT>" +*mips32r6: +*mips64r6: +{ + TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); + if (GPR[RT] != 0) + GPR[RD] = GPR[RS]; + else + GPR[RD] = 0; + TRACE_ALU_RESULT (GPR[RD]); +} |