summaryrefslogtreecommitdiff
path: root/arch/mips/il.cpp
diff options
context:
space:
mode:
authornoone <you@example.com>2024-06-11 04:44:24 -0500
committerMason Reed <mason@vector35.com>2024-07-08 16:02:37 -0400
commiteed70ad4d270ca1d134d325362f23c831fe98b0b (patch)
tree991fa3ba7f62bc57f42b3164529e6317b84f17ad /arch/mips/il.cpp
parentc3040ecfc43983af6f05da13cf2242d085b1e230 (diff)
Add Cavium Octeon MIPS Instructions and more general MIPS fixes
Diffstat (limited to 'arch/mips/il.cpp')
-rw-r--r--arch/mips/il.cpp1305
1 files changed, 1119 insertions, 186 deletions
diff --git a/arch/mips/il.cpp b/arch/mips/il.cpp
index 76a62274..37785db2 100644
--- a/arch/mips/il.cpp
+++ b/arch/mips/il.cpp
@@ -62,33 +62,33 @@ static void ConditionExecute(LowLevelILFunction& il, ExprId cond, ExprId trueCas
}
-static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, InstructionOperand& operand, size_t addrSize)
+static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, InstructionOperand& operand, size_t addrSize, int32_t delta=0)
{
size_t offset = 0;
if (operand.reg == REG_ZERO)
- return il.ConstPointer(addrSize, operand.immediate);
+ return il.ConstPointer(addrSize, operand.immediate + (int64_t)delta);
if (operand.operandClass == MEM_IMM)
{
- if (operand.immediate >= 0x80000000)
+ if (operand.immediate + (uint64_t)((int64_t)delta) >= 0x80000000)
offset = il.Sub(addrSize,
il.Register(addrSize, operand.reg),
- il.Const(addrSize, -(int32_t)operand.immediate));
+ il.Const(addrSize, -((int32_t)operand.immediate + delta)));
else
offset = il.Add(addrSize,
il.Register(addrSize, operand.reg),
- il.Const(addrSize, operand.immediate));
+ il.Const(addrSize, operand.immediate + delta));
}
else if (operand.operandClass == MEM_REG)
{
- if (operand.immediate >= 0x80000000)
+ if (operand.immediate + (uint64_t)((int64_t)delta) >= 0x80000000)
offset = il.Sub(addrSize,
il.Register(addrSize, operand.reg),
- il.Register(addrSize, -(int32_t)operand.immediate));
+ il.Register(addrSize, -((int32_t)operand.immediate + delta)));
else
offset = il.Add(addrSize,
il.Register(addrSize, operand.reg),
- il.Register(addrSize, operand.immediate));
+ il.Register(addrSize, operand.immediate + delta));
}
return offset;
}
@@ -101,7 +101,8 @@ static size_t ReadILOperand(LowLevelILFunction& il,
size_t opSize = SIZE_MAX,
bool isAddress = false)
{
- if (opSize == SIZE_MAX) {
+ if (opSize == SIZE_MAX)
+ {
opSize = registerSize;
}
InstructionOperand operand = instr.operands[i - 1];
@@ -199,6 +200,8 @@ ExprId GetConditionForInstruction(LowLevelILFunction& il, Instruction& instr, si
return il.CompareNotEqual(registerSize, ReadILOperand(il, instr, 1, registerSize), ReadILOperand(il, instr, 2, registerSize));
case MIPS_BEQZ:
return il.CompareEqual(registerSize, ReadILOperand(il, instr, 1, registerSize), il.Const(registerSize, 0));
+ case MIPS_BNEZ:
+ return il.CompareNotEqual(registerSize, ReadILOperand(il, instr, 1, registerSize), il.Const(registerSize, 0));
case MIPS_BGEZ:
case MIPS_BGEZL:
case MIPS_BGEZAL:
@@ -223,19 +226,87 @@ ExprId GetConditionForInstruction(LowLevelILFunction& il, Instruction& instr, si
if (instr.operands[0].operandClass == FLAG)
return il.Flag(instr.operands[0].reg);
return il.Flag(FPCCREG_FCC0);
+ case CNMIPS_BBIT0:
+ return il.CompareEqual(registerSize,
+ il.And(registerSize,
+ ReadILOperand(il, instr, 1, registerSize),
+ il.Const(registerSize, 1 << instr.operands[1].immediate)
+ ),
+ il.Const(registerSize, 0)
+ );
+ case CNMIPS_BBIT032:
+ return il.CompareEqual(registerSize,
+ il.And(registerSize,
+ ReadILOperand(il, instr, 1, registerSize),
+ il.Const(registerSize, ((uint64_t)1) << (instr.operands[1].immediate + 32))
+ ),
+ il.Const(registerSize, 0)
+ );
+ case CNMIPS_BBIT1:
+ return il.CompareNotEqual(registerSize,
+ il.And(registerSize,
+ ReadILOperand(il, instr, 1, registerSize),
+ il.Const(registerSize, 1 << instr.operands[1].immediate)
+ ),
+ il.Const(registerSize, 0)
+ );
+ case CNMIPS_BBIT132:
+ return il.CompareNotEqual(registerSize,
+ il.And(registerSize,
+ ReadILOperand(il, instr, 1, registerSize),
+ il.Const(registerSize, ((uint64_t)1) << (instr.operands[1].immediate + 32))
+ ),
+ il.Const(registerSize, 0)
+ );
+
default:
LogError("Missing conditional: %d", instr.operation);
return il.Unimplemented();
}
}
+static bool IsCop0ImplementationDefined(uint32_t reg, uint64_t sel)
+{
+ switch (reg)
+ {
+ case 9:
+ switch (sel)
+ {
+ case 6:
+ case 7: return true;
+ default: return false;
+ }
+ break;
+ case 11:
+ switch (sel)
+ {
+ case 6:
+ case 7: return true;
+ default: return false;
+ }
+ break;
+ case 16:
+ switch (sel)
+ {
+ case 6:
+ case 7: return true;
+ default: return false;
+ }
+ break;
+ case 22: return true;
+ default: return false;
+ }
+}
+
// Get the IL Register for a given cop0 register/selector pair.
// Returns REG_ZERO for unsupported/unimplemented values.
static Reg GetCop0Register(uint32_t reg, uint64_t sel)
{
- switch (reg) {
+ switch (reg)
+ {
case 0:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_INDEX;
case 1: return REG_MVP_CONTROL;
case 2: return REG_MVP_CONF0;
@@ -243,7 +314,8 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 1:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_RANDOM;
case 1: return REG_VPE_CONTROL;
case 2: return REG_VPE_CONF0;
@@ -255,7 +327,8 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 2:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_ENTRY_LO0;
case 1: return REG_TC_STATUS;
case 2: return REG_TC_BIND;
@@ -267,24 +340,28 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 3:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_ENTRY_LO1;
}
break;
case 4:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_CONTEXT;
case 1: return REG_CONTEXT_CONFIG;
}
break;
case 5:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_PAGE_MASK;
case 1: return REG_PAGE_GRAIN;
}
break;
case 6:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_WIRED;
case 1: return REG_SRS_CONF0;
case 2: return REG_SRS_CONF1;
@@ -294,32 +371,38 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 7:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_HWR_ENA;
}
break;
case 8:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_BAD_VADDR;
}
break;
case 9:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_COUNT;
}
break;
case 10:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_ENTRY_HI;
}
break;
case 11:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_COMPARE;
}
break;
case 12:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_STATUS;
case 1: return REG_INT_CTL;
case 2: return REG_SRS_CTL;
@@ -327,23 +410,27 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 13:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_CAUSE;
}
break;
case 14:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_EPC;
}
break;
case 15:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_PR_ID;
case 1: return REG_EBASE;
}
break;
case 16:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_CONFIG;
case 1: return REG_CONFIG1;
case 2: return REG_CONFIG2;
@@ -351,17 +438,20 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 17:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_LLADDR;
}
break;
case 20:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_XCONTEXT;
}
break;
case 23:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_DEBUG;
case 1: return REG_TRACE_CONTROL;
case 2: return REG_TRACE_CONTROL2;
@@ -370,17 +460,20 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 24:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_DEPC;
}
break;
case 26:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_ERR_CTL;
}
break;
case 27:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_CACHE_ERR0;
case 1: return REG_CACHE_ERR1;
case 2: return REG_CACHE_ERR2;
@@ -388,12 +481,14 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
}
break;
case 30:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_ERROR_EPC;
}
break;
case 31:
- switch (sel) {
+ switch (sel)
+ {
case 0: return REG_DESAVE;
}
break;
@@ -401,18 +496,224 @@ static Reg GetCop0Register(uint32_t reg, uint64_t sel)
return REG_ZERO;
}
-static ExprId MoveFromCoprocessor(unsigned cop, LowLevelILFunction& il, size_t loadSize, uint32_t outReg, uint32_t reg, uint64_t sel)
+static Reg GetCaviumCop0Register(uint32_t reg, uint64_t sel)
{
- if (cop == 0) {
+ switch (reg)
+ {
+ case 9:
+ switch (sel)
+ {
+ case 6: return CNREG0_CVM_COUNT;
+ case 7: return CNREG0_CVM_CTL;
+ default: return REG_ZERO;
+ }
+ break;
+
+ case 11:
+ switch (sel)
+ {
+ case 6: return CNREG0_POWTHROTTLE;
+ case 7: return CNREG0_CVM_MEM_CTL;
+ default: return REG_ZERO;
+ }
+ break;
+ case 22:
+ switch (sel)
+ {
+ case 0: return CNREG0_MULTICORE_DBG;
+ default: return REG_ZERO;
+ }
+ break;
+
+ default: return REG_ZERO;
+ }
+}
+
+static Reg GetCaviumCop2Register(uint32_t reg)
+{
+ switch (reg)
+ {
+ case 0x0040: return CNREG2_0040_HSH_DAT0;
+ case 0x0041: return CNREG2_0041_HSH_DAT1;
+ case 0x0042: return CNREG2_0042_HSH_DAT2;
+ case 0x0043: return CNREG2_0043_HSH_DAT3;
+ case 0x0044: return CNREG2_0044_HSH_DAT4;
+ case 0x0045: return CNREG2_0045_HSH_DAT5;
+ case 0x0046: return CNREG2_0046_HSH_DAT6;
+ case 0x0048: return CNREG2_0048_HSH_IV0;
+ case 0x0049: return CNREG2_0049_HSH_IV1;
+ case 0x004a: return CNREG2_004A_HSH_IV2;
+ case 0x004b: return CNREG2_004B_HSH_IV3;
+ case 0x0050: return CNREG2_0050_SHA3_DAT24;
+ case 0x0051: return CNREG2_0051_SHA3_DAT15_RD;
+ case 0x0058: return CNREG2_0058_GFM_MUL_REFLECT0;
+ case 0x0059: return CNREG2_0059_GFM_MUL_REFLECT1;
+ case 0x005a: return CNREG2_005A_GFM_RESINP_REFLECT0;
+ case 0x005b: return CNREG2_005B_GFM_RESINP_REFLECT1;
+ case 0x005c: return CNREG2_005C_GFM_XOR0_REFLECT;
+ case 0x0080: return CNREG2_0080_3DES_KEY0;
+ case 0x0081: return CNREG2_0081_3DES_KEY1;
+ case 0x0082: return CNREG2_0082_3DES_KEY2;
+ case 0x0084: return CNREG2_0084_3DES_IV;
+ case 0x0088: return CNREG2_0088_3DES_RESULT_RD;
+ case 0x0098: return CNREG2_0098_3DES_RESULT_WR;
+ case 0x0100: return CNREG2_0100_AES_RESULT0;
+ case 0x0101: return CNREG2_0101_AES_RESULT1;
+ case 0x0102: return CNREG2_0102_AES_IV0;
+ case 0x0103: return CNREG2_0103_AES_IV1;
+ case 0x0104: return CNREG2_0104_AES_KEY0;
+ case 0x0105: return CNREG2_0105_AES_KEY1;
+ case 0x0106: return CNREG2_0106_AES_KEY2;
+ case 0x0107: return CNREG2_0107_AES_KEY3;
+ case 0x0108: return CNREG2_0108_AES_ENC_CBC0;
+ case 0x010a: return CNREG2_010A_AES_ENC0;
+ case 0x010c: return CNREG2_010C_AES_DEC_CBC0;
+ case 0x010e: return CNREG2_010E_AES_DEC0;
+ case 0x0110: return CNREG2_0110_AES_KEYLENGTH;
+ case 0x0111: return CNREG2_0111_AES_DAT0;
+ case 0x0115: return CNREG2_0115_CAMELLIA_FL;
+ case 0x0116: return CNREG2_0116_CAMELLIA_FLINV;
+ case 0x0200: return CNREG2_0200_CRC_POLYNOMIAL;
+ case 0x0201: return CNREG2_0201_CRC_IV;
+ case 0x0202: return CNREG2_0202_CRC_LEN;
+ case 0x0203: return CNREG2_0203_CRC_IV_REFLECT_RD;
+ case 0x0204: return CNREG2_0204_CRC_BYTE;
+ case 0x0205: return CNREG2_0205_CRC_HALF;
+ case 0x0206: return CNREG2_0206_CRC_WORD;
+ case 0x0211: return CNREG2_0211_CRC_IV_REFLECT_WR;
+ case 0x0214: return CNREG2_0214_CRC_BYTE_REFLECT;
+ case 0x0215: return CNREG2_0215_CRC_HALF_REFLECT;
+ case 0x0216: return CNREG2_0216_CRC_WORD_REFLECT;
+ case 0x0240: return CNREG2_0240_HSH_DATW0;
+ case 0x0241: return CNREG2_0241_HSH_DATW1;
+ case 0x0242: return CNREG2_0242_HSH_DATW2;
+ case 0x0243: return CNREG2_0243_HSH_DATW3;
+ case 0x0244: return CNREG2_0244_HSH_DATW4;
+ case 0x0245: return CNREG2_0245_HSH_DATW5;
+ case 0x0246: return CNREG2_0246_HSH_DATW6;
+ case 0x0247: return CNREG2_0247_HSH_DATW7;
+ case 0x0248: return CNREG2_0248_HSH_DATW8;
+ case 0x0249: return CNREG2_0249_HSH_DATW9;
+ case 0x024a: return CNREG2_024A_HSH_DATW10;
+ case 0x024b: return CNREG2_024B_HSH_DATW11;
+ case 0x024c: return CNREG2_024C_HSH_DATW12;
+ case 0x024d: return CNREG2_024D_HSH_DATW13;
+ case 0x024e: return CNREG2_024E_HSH_DATW14;
+ case 0x024f: return CNREG2_024F_SHA3_DAT15_RD;
+ case 0x0250: return CNREG2_0250_HSH_IVW0;
+ case 0x0251: return CNREG2_0251_HSH_IVW1;
+ case 0x0252: return CNREG2_0252_HSH_IVW2;
+ case 0x0253: return CNREG2_0253_HSH_IVW3;
+ case 0x0254: return CNREG2_0254_HSH_IVW4;
+ case 0x0255: return CNREG2_0255_HSH_IVW5;
+ case 0x0256: return CNREG2_0256_HSH_IVW6;
+ case 0x0257: return CNREG2_0257_HSH_IVW7;
+ case 0x0258: return CNREG2_0258_GFM_MUL0;
+ case 0x0259: return CNREG2_0259_GFM_MUL1;
+ case 0x025a: return CNREG2_025A_GFM_RESINP0;
+ case 0x025b: return CNREG2_025B_GFM_RESINP1;
+ case 0x025c: return CNREG2_025C_GFM_XOR0;
+ case 0x025e: return CNREG2_025E_GFM_POLY;
+ case 0x02c0: return CNREG2_02C0_SHA3_XORDAT0;
+ case 0x02c1: return CNREG2_02C1_SHA3_XORDAT1;
+ case 0x02c2: return CNREG2_02C2_SHA3_XORDAT2;
+ case 0x02c3: return CNREG2_02C3_SHA3_XORDAT3;
+ case 0x02c4: return CNREG2_02C4_SHA3_XORDAT4;
+ case 0x02c5: return CNREG2_02C5_SHA3_XORDAT5;
+ case 0x02c6: return CNREG2_02C6_SHA3_XORDAT6;
+ case 0x02c7: return CNREG2_02C7_SHA3_XORDAT7;
+ case 0x02c8: return CNREG2_02C8_SHA3_XORDAT8;
+ case 0x02c9: return CNREG2_02C9_SHA3_XORDAT9;
+ case 0x02ca: return CNREG2_02CA_SHA3_XORDAT10;
+ case 0x02cb: return CNREG2_02CB_SHA3_XORDAT11;
+ case 0x02cc: return CNREG2_02CC_SHA3_XORDAT12;
+ case 0x02cd: return CNREG2_02CD_SHA3_XORDAT13;
+ case 0x02ce: return CNREG2_02CE_SHA3_XORDAT14;
+ case 0x02cf: return CNREG2_02CF_SHA3_XORDAT15;
+ case 0x02d0: return CNREG2_02D0_SHA3_XORDAT16;
+ case 0x02d1: return CNREG2_02D1_SHA3_XORDAT17;
+ case 0x0400: return CNREG2_0400_LLM_READ_ADDR0;
+ case 0x0401: return CNREG2_0401_LLM_WRITE_ADDR_INTERNAL0;
+ case 0x0402: return CNREG2_0402_LLM_DATA0;
+ case 0x0404: return CNREG2_0404_LLM_READ64_ADDR0;
+ case 0x0405: return CNREG2_0405_LLM_WRITE64_ADDR_INTERNAL0;
+ case 0x0408: return CNREG2_0408_LLM_READ_ADDR1;
+ case 0x0409: return CNREG2_0409_LLM_WRITE_ADDR_INTERNAL1;
+ case 0x040a: return CNREG2_040a_LLM_DATA1;
+ case 0x040c: return CNREG2_040c_LLM_READ64_ADDR1;
+ case 0x040d: return CNREG2_040d_LLM_WRITE64_ADDR_INTERNAL1;
+ case 0x1202: return CNREG2_1202_CRC_LEN;
+ case 0x1207: return CNREG2_1207_CRC_DWORD;
+ case 0x1208: return CNREG2_1208_CRC_VAR;
+ case 0x1217: return CNREG2_1217_CRC_DWORD_REFLECT;
+ case 0x1218: return CNREG2_1218_CRC_VAR_REFLECT;
+ case 0x3109: return CNREG2_3109_AES_ENC_CBC1;
+ case 0x310b: return CNREG2_310B_AES_ENC1;
+ case 0x310d: return CNREG2_310D_AES_DEC_CBC1;
+ case 0x310f: return CNREG2_310F_AES_DEC1;
+ case 0x3114: return CNREG2_3114_CAMELLIA_ROUND;
+ case 0x3119: return CNREG2_3119_SMS4_ENC_CBC1;
+ case 0x311b: return CNREG2_311B_SMS4_ENC1;
+ case 0x311d: return CNREG2_311D_SMS4_DEC_CBC1;
+ case 0x311f: return CNREG2_311F_SMS4_DEC1;
+ case 0x4052: return CNREG2_4052_SHA3_STARTOP;
+ case 0x4047: return CNREG2_4047_HSH_STARTMD5;
+ case 0x404d: return CNREG2_404D_SNOW3G_START;
+ case 0x4055: return CNREG2_4055_ZUC_START;
+ case 0x4056: return CNREG2_4056_ZUC_MORE;
+ case 0x405d: return CNREG2_405D_GFM_XORMUL1_REFLECT;
+ case 0x404e: return CNREG2_404E_SNOW3G_MORE;
+ case 0x404f: return CNREG2_404F_HSH_STARTSHA256;
+ case 0x4057: return CNREG2_4057_HSH_STARTSHA;
+ case 0x4088: return CNREG2_4088_3DES_ENC_CBC;
+ case 0x4089: return CNREG2_4089_KAS_ENC_CBC;
+ case 0x408a: return CNREG2_408A_3DES_ENC;
+ case 0x408b: return CNREG2_408B_KAS_ENC;
+ case 0x408c: return CNREG2_408C_3DES_DEC_CBC;
+ case 0x408e: return CNREG2_408E_3DES_DEC;
+ case 0x4200: return CNREG2_4200_CRC_POLYNOMIAL_WR;
+ case 0x4210: return CNREG2_4210_CRC_POLYNOMIAL_REFLECT;
+ case 0x424f: return CNREG2_424F_HSH_STARTSHA512;
+ case 0x425d: return CNREG2_425D_GFM_XORMUL1;
+
+ default: return REG_ZERO;
+ }
+}
+
+static ExprId MoveFromCoprocessor(unsigned cop, LowLevelILFunction& il, size_t loadSize, uint32_t outReg, uint32_t reg, uint64_t sel, uint32_t decomposeFlags)
+{
+ if (cop == 0)
+ {
Reg copReg = GetCop0Register(reg, sel);
- switch (copReg) {
- case REG_ZERO: /* Unimplemented coprocessor register */
- break;
- default:
+ if (copReg == REG_ZERO && IsCop0ImplementationDefined(reg, sel))
+ {
+ if ((decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ copReg = GetCaviumCop0Register(reg, sel);
+ }
+ }
+
+ if (copReg != REG_ZERO)
+ {
+ return il.Intrinsic(
+ {RegisterOrFlag::Register(outReg)},
+ loadSize == 4 ? MIPS_INTRIN_MFC0 : MIPS_INTRIN_DMFC0,
+ {il.Register(loadSize, copReg)});
+
+ }
+ }
+ else if (cop == 2)
+ {
+ if ((decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ Reg cop2Reg = GetCaviumCop2Register(reg);
+ if (cop2Reg != REG_ZERO)
+ {
return il.Intrinsic(
- {RegisterOrFlag::Register(outReg)},
- loadSize == 4 ? MIPS_INTRIN_MFC0 : MIPS_INTRIN_DMFC0,
- {il.Register(loadSize, copReg)});
+ {RegisterOrFlag::Register(outReg)},
+ loadSize == 4 ? MIPS_INTRIN_MFC2 : MIPS_INTRIN_DMFC2,
+ {il.Register(loadSize, cop2Reg)});
+ }
}
}
@@ -422,18 +723,39 @@ static ExprId MoveFromCoprocessor(unsigned cop, LowLevelILFunction& il, size_t l
{il.Const(4, cop), il.Const(4, reg), il.Const(4, sel)});
}
-static ExprId MoveToCoprocessor(unsigned cop, LowLevelILFunction& il, size_t storeSize, uint32_t reg, uint64_t sel, ExprId srcExpr)
+static ExprId MoveToCoprocessor(unsigned cop, LowLevelILFunction& il, size_t storeSize, uint32_t reg, uint64_t sel, ExprId srcExpr, uint32_t decomposeFlags)
{
- if (cop == 0) {
+ if (cop == 0)
+ {
Reg copReg = GetCop0Register(reg, sel);
- switch (copReg) {
- case REG_ZERO: /* Unimplemented coprocessor register */
- break;
- default:
+ if (copReg == REG_ZERO && IsCop0ImplementationDefined(reg, sel))
+ {
+ if ((decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ copReg = GetCaviumCop0Register(reg, sel);
+ }
+ }
+
+ if (copReg != REG_ZERO)
+ {
+ return il.Intrinsic(
+ {},
+ storeSize == 4 ? MIPS_INTRIN_MTC0 : MIPS_INTRIN_DMTC0,
+ {il.Register(storeSize, copReg), srcExpr});
+ }
+ }
+ else if (cop == 2)
+ {
+ if ((decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ Reg cop2Reg = GetCaviumCop2Register(reg);
+ if (cop2Reg != REG_ZERO)
+ {
return il.Intrinsic(
{},
- storeSize == 4 ? MIPS_INTRIN_MTC0 : MIPS_INTRIN_DMTC0,
- {il.Register(storeSize, copReg), srcExpr});
+ storeSize == 4 ? MIPS_INTRIN_MTC2 : MIPS_INTRIN_DMTC2,
+ {il.Register(storeSize, cop2Reg), srcExpr});
+ }
}
}
@@ -443,7 +765,24 @@ static ExprId MoveToCoprocessor(unsigned cop, LowLevelILFunction& il, size_t sto
{il.Const(4, cop), il.Const(4, reg), il.Const(4, sel), srcExpr});
}
-bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFunction& il, Instruction& instr, size_t addrSize)
+static ExprId SimpleIntrinsic(LowLevelILFunction& il, MipsIntrinsic intrinsic)
+{
+ return il.Intrinsic({}, intrinsic, {});
+}
+
+// returns 256-bit value of [0:64] || [regHi] || [regMid] || [regLo]
+static ExprId Concat3to256(LowLevelILFunction& il, uint32_t regHi, uint32_t regMid, uint32_t regLo)
+{
+ return il.Or(0x20,
+ il.ShiftLeft(0x20, il.ZeroExtend(0x20, il.Register(8, regHi)), il.Const(4, 0x80)),
+ il.Or(0x20,
+ il.ShiftLeft(0x20, il.ZeroExtend(0x20, il.Register(8, regMid)), il.Const(4, 0x40)),
+ il.ZeroExtend(0x20, il.Register(8, regLo))
+ )
+ );
+}
+
+bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFunction& il, Instruction& instr, size_t addrSize, uint32_t decomposeFlags)
{
LowLevelILLabel trueLabel, falseLabel, doneLabel, dirFlagSet, dirFlagClear, dirFlagDone;
InstructionOperand& op1 = instr.operands[0];
@@ -452,6 +791,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
InstructionOperand& op4 = instr.operands[3];
LowLevelILLabel trueCode, falseCode, again;
size_t registerSize = addrSize;
+ BNEndianness endian = arch->GetEndianness();
switch (instr.operation)
{
case MIPS_ADD:
@@ -487,15 +827,22 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
ReadILOperand(il, instr, 2, registerSize, 4),
ReadILOperand(il, instr, 3, registerSize, 4))));
break;
+ case MIPS_DSUB:
+ case MIPS_DSUBU:
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.Sub(8,
+ ReadILOperand(il, instr, 2, registerSize, 8),
+ ReadILOperand(il, instr, 3, registerSize, 8))));
+ break;
case MIPS_AND:
il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
- il.And(4,
+ il.And(registerSize,
ReadILOperand(il, instr, 2, registerSize),
ReadILOperand(il, instr, 3, registerSize))));
break;
case MIPS_ANDI:
il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
- il.And(4,
+ il.And(registerSize,
ReadILOperand(il, instr, 2, registerSize),
il.Operand(1, il.Const(4, 0x0000ffff & op3.immediate)))));
break;
@@ -519,6 +866,26 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
ReadILOperand(il, instr, 1, registerSize, 4),
ReadILOperand(il, instr, 2, registerSize, 4))));
break;
+ case MIPS_DDIV:
+ il.AddInstruction(il.SetRegister(8, REG_LO,
+ il.DivSigned(8,
+ ReadILOperand(il, instr, 1, registerSize, 8),
+ ReadILOperand(il, instr, 2, registerSize, 8))));
+ il.AddInstruction(il.SetRegister(8, REG_HI,
+ il.ModSigned(8,
+ ReadILOperand(il, instr, 1, registerSize, 8),
+ ReadILOperand(il, instr, 2, registerSize, 8))));
+ break;
+ case MIPS_DDIVU:
+ il.AddInstruction(il.SetRegister(8, REG_LO,
+ il.DivUnsigned(8,
+ ReadILOperand(il, instr, 1, registerSize, 8),
+ ReadILOperand(il, instr, 2, registerSize, 8))));
+ il.AddInstruction(il.SetRegister(8, REG_HI,
+ il.ModUnsigned(8,
+ ReadILOperand(il, instr, 1, registerSize, 8),
+ ReadILOperand(il, instr, 2, registerSize, 8))));
+ break;
case MIPS_MUL:
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
il.Mult(4,
@@ -526,15 +893,15 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
ReadILOperand(il, instr, 3, registerSize, 4))));
break;
case MIPS_XOR:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Xor(4,
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
+ il.Xor(registerSize,
ReadILOperand(il, instr, 2, registerSize),
ReadILOperand(il, instr, 3, registerSize))));
break;
case MIPS_XORI:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Xor(4,
- ReadILOperand(il, instr, 2, registerSize, 4),
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
+ il.Xor(registerSize,
+ ReadILOperand(il, instr, 2, registerSize),
il.Operand(1,il.Const(4, 0x0000ffff & op3.immediate)))));
break;
case MIPS_B:
@@ -546,7 +913,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
if (op1.immediate == (addr + 8)) // Get PC construct
il.AddInstruction(il.SetRegister(addrSize, REG_RA, il.ConstPointer(addrSize ,addr + 8)));
else
- il.AddInstruction(il.Call(il.ConstPointer(4, op1.immediate)));
+ il.AddInstruction(il.Call(il.ConstPointer(addrSize, op1.immediate)));
break;
case MIPS_BEQ:
@@ -561,6 +928,7 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
case MIPS_BGTZ:
case MIPS_BLEZ:
case MIPS_BLTZ:
+ case MIPS_BNEZ:
case MIPS_BGEZL: //Branch likely
case MIPS_BGTZL:
case MIPS_BLEZL:
@@ -617,13 +985,35 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
il.AddInstruction(il.Goto(again));
il.MarkLabel(falseCode);
break;
- case MIPS_CLZ:
+ case MIPS_DCLO:
//count leading ones
//algorithm is as follows
//
//tmp0 = 0;
//again:
- //if (((op2 << tmp) & 0x80000000) != 0)
+ //if (((op2 << tmp) & 0x80000000_00000000) != 0)
+ //{
+ // tmp0 += 1;
+ // goto again;
+ //}
+ //
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(0), il.Const(4,0)));
+ il.MarkLabel(again);
+ il.AddInstruction(il.If(il.CompareNotEqual(8,
+ il.And(8, il.ShiftLeft(8, ReadILOperand(il, instr, 2, registerSize, 8), il.Register(1, LLIL_TEMP(0))), il.Const(8, 0x8000000000000000)),
+ il.Const(8,0)), trueCode, falseCode));
+ il.MarkLabel(trueCode);
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(0), il.Add(1, il.Const(1,1), il.Register(1, LLIL_TEMP(0)))));
+ il.AddInstruction(il.Goto(again));
+ il.MarkLabel(falseCode);
+ break;
+ case MIPS_CLZ:
+ //count leading zeroes
+ //algorithm is as follows
+ //
+ //tmp0 = 0;
+ //again:
+ //if (((op2 << tmp) & 0x80000000) == 0)
//{
// tmp0 += 1;
// goto again;
@@ -639,6 +1029,28 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
il.AddInstruction(il.Goto(again));
il.MarkLabel(falseCode);
break;
+ case MIPS_DCLZ:
+ //count leading zeroes
+ //algorithm is as follows
+ //
+ //tmp0 = 0;
+ //again:
+ //if (((op2 << tmp) & 0x80000000_00000000) == 0)
+ //{
+ // tmp0 += 1;
+ // goto again;
+ //}
+ //
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(0), il.Const(4,0)));
+ il.MarkLabel(again);
+ il.AddInstruction(il.If(il.CompareEqual(8,
+ il.And(8, il.ShiftLeft(8, ReadILOperand(il, instr, 2, registerSize, 8), il.Register(1, LLIL_TEMP(0))), il.Const(8, 0x8000000000000000)),
+ il.Const(8,0)), trueCode, falseCode));
+ il.MarkLabel(trueCode);
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(0), il.Add(1, il.Const(1,1), il.Register(1, LLIL_TEMP(0)))));
+ il.AddInstruction(il.Goto(again));
+ il.MarkLabel(falseCode);
+ break;
case MIPS_JALR:
case MIPS_JALR_HB:
{
@@ -680,28 +1092,34 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
il.AddInstruction(il.SetRegister(registerSize, REG_LO, ReadILOperand(il, instr, 1, registerSize)));
break;
case MIPS_DMFC0:
- il.AddInstruction(MoveFromCoprocessor(0, il, 8, op1.reg, op2.immediate, op3.immediate));
+ il.AddInstruction(MoveFromCoprocessor(0, il, 8, op1.reg, op2.immediate, op3.immediate, decomposeFlags));
break;
case MIPS_MFC0:
- il.AddInstruction(MoveFromCoprocessor(0, il, 4, op1.reg, op2.immediate, op3.immediate));
+ il.AddInstruction(MoveFromCoprocessor(0, il, 4, op1.reg, op2.immediate, op3.immediate, decomposeFlags));
break;
case MIPS_MFC1:
- il.AddInstruction(MoveFromCoprocessor(1, il, 4, op1.reg, op2.immediate, op3.immediate));
+ il.AddInstruction(MoveFromCoprocessor(1, il, 4, op1.reg, op2.immediate, op3.immediate, decomposeFlags));
+ break;
+ case MIPS_DMFC2:
+ il.AddInstruction(MoveFromCoprocessor(2, il, 8, op1.reg, op2.immediate, 0, decomposeFlags));
break;
case MIPS_MFC2:
- il.AddInstruction(MoveFromCoprocessor(2, il, 4, op1.reg, op2.immediate, op3.immediate));
+ il.AddInstruction(MoveFromCoprocessor(2, il, 4, op1.reg, op2.immediate, 0, decomposeFlags));
break;
case MIPS_DMTC0:
- il.AddInstruction(MoveToCoprocessor(0, il, 8, op2.immediate, op3.immediate, ReadILOperand(il, instr, 1, registerSize)));
+ il.AddInstruction(MoveToCoprocessor(0, il, 8, op2.immediate, op3.immediate, ReadILOperand(il, instr, 1, registerSize), decomposeFlags));
break;
case MIPS_MTC0:
- il.AddInstruction(MoveToCoprocessor(0, il, 4, op2.immediate, op3.immediate, ReadILOperand(il, instr, 1, registerSize)));
+ il.AddInstruction(MoveToCoprocessor(0, il, 4, op2.immediate, op3.immediate, ReadILOperand(il, instr, 1, registerSize), decomposeFlags));
break;
case MIPS_MTC1:
- il.AddInstruction(MoveToCoprocessor(1, il, 4, op2.immediate, op3.immediate, ReadILOperand(il, instr, 1, registerSize)));
+ il.AddInstruction(MoveToCoprocessor(1, il, 4, op2.immediate, op3.immediate, ReadILOperand(il, instr, 1, registerSize), decomposeFlags));
+ break;
+ case MIPS_DMTC2:
+ il.AddInstruction(MoveToCoprocessor(2, il, 8, op2.immediate, 0, ReadILOperand(il, instr, 1, registerSize), decomposeFlags));
break;
case MIPS_MTC2:
- il.AddInstruction(MoveToCoprocessor(2, il, 4, op2.immediate, op3.immediate, ReadILOperand(il, instr, 1, registerSize)));
+ il.AddInstruction(MoveToCoprocessor(2, il, 4, op2.immediate, 0, ReadILOperand(il, instr, 1, registerSize), decomposeFlags));
break;
case MIPS_MOVE:
il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, ReadILOperand(il, instr, 2, registerSize)));
@@ -746,63 +1164,165 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
case MIPS_MULTU:
il.AddInstruction(il.SetRegisterSplit(4, REG_HI, REG_LO, il.MultDoublePrecUnsigned(8, ReadILOperand(il, instr, 1, registerSize), ReadILOperand(il, instr, 2, registerSize))));
break;
+ case MIPS_DMULT:
+ il.AddInstruction(il.SetRegisterSplit(8, REG_HI, REG_LO, il.MultDoublePrecSigned(16, ReadILOperand(il, instr, 1, registerSize), ReadILOperand(il, instr, 2, registerSize))));
+ break;
+ case MIPS_DMULTU:
+ il.AddInstruction(il.SetRegisterSplit(8, REG_HI, REG_LO, il.MultDoublePrecUnsigned(16, ReadILOperand(il, instr, 1, registerSize), ReadILOperand(il, instr, 2, registerSize))));
+ break;
case MIPS_NEG:
case MIPS_NEGU:
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
il.Neg(4, ReadILOperand(il, instr, 2, registerSize))));
break;
case MIPS_NOT:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Not(4, ReadILOperand(il, instr, 2, registerSize))));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
+ il.Not(registerSize, ReadILOperand(il, instr, 2, registerSize))));
break;
case MIPS_NOR:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Not(4, il.Or(4, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize)))));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
+ il.Not(registerSize, il.Or(registerSize, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize)))));
break;
case MIPS_OR:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Or(4, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
+ il.Or(registerSize, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
break;
case MIPS_ORI:
if (op2.reg == REG_ZERO)
- il.AddInstruction(il.SetRegister(4, op1.reg, il.Operand(1, il.Const(4, 0x0000ffff & op3.immediate))));
+ il.AddInstruction(il.SetRegister(registerSize, op1.reg, il.Operand(1, il.Const(4, 0x0000ffff & op3.immediate))));
else
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Or(4,
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
+ il.Or(registerSize,
ReadILOperand(il, instr, 2, registerSize),
il.Operand(1, il.Const(4, 0x0000ffff & op3.immediate)))));
break;
case MIPS_RDHWR:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.Unimplemented()));
+ {
+ MipsIntrinsic intrinsic;
+ switch (op2.immediate)
+ {
+ case 0: intrinsic = MIPS_INTRIN_HWR0; break;
+ case 1: intrinsic = MIPS_INTRIN_HWR1; break;
+ case 2: intrinsic = MIPS_INTRIN_HWR2; break;
+ case 3: intrinsic = MIPS_INTRIN_HWR3; break;
+ default: intrinsic = MIPS_INTRIN_HWR_UNKNOWN;
+ }
+
+ if (intrinsic != MIPS_INTRIN_HWR_UNKNOWN)
+ {
+ il.AddInstruction(
+ il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, intrinsic, {})
+ );
+ }
+ else
+ {
+ il.AddInstruction(
+ il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, MIPS_INTRIN_HWR_UNKNOWN, {il.Const(1, op2.immediate)})
+ );
+ }
break;
+ }
case MIPS_SW:
il.AddInstruction(il.Store(4, GetILOperandMemoryAddress(il, op2, addrSize), ReadILOperand(il, instr, 1, registerSize, 4)));
break;
+ case MIPS_SWL:
+ {
+ int32_t delta = endian == LittleEndian ? -3 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(LLIL_TEMP(0)) }, MIPS_INTRIN_GET_LEFT_PART32, { ReadILOperand(il, instr, 1, registerSize, 4) }));
+ il.AddInstruction(il.Store(4,
+ GetILOperandMemoryAddress(il, op2, addrSize, delta),
+ il.Register(4, LLIL_TEMP(0))
+ ));
+
+ break;
+ }
+
+ case MIPS_SDL:
+ {
+ int32_t delta = endian == LittleEndian ? -7 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(LLIL_TEMP(0)) }, MIPS_INTRIN_GET_LEFT_PART64, { ReadILOperand(il, instr, 1, registerSize, 8) }));
+ il.AddInstruction(il.Store(8,
+ GetILOperandMemoryAddress(il, op2, addrSize, delta),
+ il.Register(8, LLIL_TEMP(0))
+ ));
+
+ break;
+ }
+ case MIPS_SWR:
+ {
+ int32_t delta = endian == BigEndian ? -3 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(LLIL_TEMP(0)) }, MIPS_INTRIN_GET_RIGHT_PART32, { ReadILOperand(il, instr, 1, registerSize, 4) }));
+ il.AddInstruction(il.Store(4,
+ GetILOperandMemoryAddress(il, op2, addrSize, delta),
+ il.Register(4, LLIL_TEMP(0))
+ ));
+
+ break;
+ }
+
+ case MIPS_SDR:
+ {
+ int32_t delta = endian == BigEndian ? -7 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(LLIL_TEMP(0)) }, MIPS_INTRIN_GET_RIGHT_PART64, { ReadILOperand(il, instr, 1, registerSize, 8) }));
+ il.AddInstruction(il.Store(8,
+ GetILOperandMemoryAddress(il, op2, addrSize, delta),
+ il.Register(8, LLIL_TEMP(0))
+ ));
+
+ break;
+ }
+
+ case MIPS_SC:
+ {
+ LowLevelILLabel trueCode, falseCode, doneCode;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(LLIL_TEMP(0)) }, MIPS_INTRIN_LLBIT_CHECK, {}));
+ il.AddInstruction(il.If(il.CompareEqual(0, il.Register(0, LLIL_TEMP(0)), il.Const(0, 1)),
+ trueCode, falseCode));
+ il.MarkLabel(trueCode);
+
+ il.AddInstruction(il.Store(4, GetILOperandMemoryAddress(il, op2, addrSize), ReadILOperand(il, instr, 1, registerSize, 4)));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.Const(0, 1)));
+ il.AddInstruction(il.Goto(doneCode));
+
+ il.MarkLabel(falseCode);
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.Const(0, 0)));
+
+ il.MarkLabel(doneCode);
+ break;
+ }
case MIPS_SD:
il.AddInstruction(il.Store(8, GetILOperandMemoryAddress(il, op2, addrSize), ReadILOperand(il, instr, 1, registerSize)));
break;
+ case MIPS_SCD:
+ {
+ LowLevelILLabel trueCode, falseCode, doneCode;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(LLIL_TEMP(0)) }, MIPS_INTRIN_LLBIT_CHECK, {}));
+ il.AddInstruction(il.If(il.CompareEqual(0, il.Register(0, LLIL_TEMP(0)), il.Const(0, 1)),
+ trueCode, falseCode));
+ il.MarkLabel(trueCode);
+
+ il.AddInstruction(il.Store(8, GetILOperandMemoryAddress(il, op2, addrSize), ReadILOperand(il, instr, 1, registerSize, 4)));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.Const(0, 1)));
+ il.AddInstruction(il.Goto(doneCode));
+
+ il.MarkLabel(falseCode);
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.Const(0, 0)));
+
+ il.MarkLabel(doneCode);
+ break;
+ }
case MIPS_SWC1:
- il.AddInstruction(MoveFromCoprocessor(1, il, 4, LLIL_TEMP(0), op1.immediate, 0));
+ il.AddInstruction(MoveFromCoprocessor(1, il, 4, LLIL_TEMP(0), op1.immediate, 0, decomposeFlags));
il.AddInstruction(WriteILOperand(il, instr, 1, addrSize, il.Register(4, LLIL_TEMP(0))));
break;
case MIPS_SWC2:
- il.AddInstruction(MoveFromCoprocessor(2, il, 4, LLIL_TEMP(0), op1.immediate, 0));
+ il.AddInstruction(MoveFromCoprocessor(2, il, 4, LLIL_TEMP(0), op1.immediate, 0, decomposeFlags));
il.AddInstruction(WriteILOperand(il, instr, 1, addrSize, il.Register(4, LLIL_TEMP(0))));
break;
case MIPS_SWC3:
- il.AddInstruction(MoveFromCoprocessor(3, il, 4, LLIL_TEMP(0), op1.immediate, 0));
+ il.AddInstruction(MoveFromCoprocessor(3, il, 4, LLIL_TEMP(0), op1.immediate, 0, decomposeFlags));
il.AddInstruction(WriteILOperand(il, instr, 1, addrSize, il.Register(4, LLIL_TEMP(0))));
break;
- case MIPS_SWL:
- il.AddInstruction(il.Store(2,
- GetILOperandMemoryAddress(il, op2, addrSize),
- il.LogicalShiftRight(4, ReadILOperand(il, instr, 1, registerSize, 4), il.Const(1, 16))));
- break;
- case MIPS_SWR:
- il.AddInstruction(il.Store(2,
- il.Sub(4, GetILOperandMemoryAddress(il, op2, addrSize), il.Const(4, 1)),
- il.And(4, ReadILOperand(il, instr, 1, registerSize, 4), il.Const(4, 0xffff))));
- break;
case MIPS_SYSCALL:
il.AddInstruction(il.SystemCall());
break;
@@ -810,19 +1330,61 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
//op1 = op4.imm bits in op2.reg at bit offset op3.imm
il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
il.And(registerSize,
- il.Const(registerSize, (1<<op4.immediate)-1),
- il.ShiftLeft(registerSize, ReadILOperand(il, instr, 2, registerSize),
- il.Const(1, op3.immediate)))));
+ il.LogicalShiftRight(registerSize,
+ ReadILOperand(il, instr, 2, registerSize),
+ il.Const(1, op3.immediate)
+ ),
+ il.Const(registerSize, (1<<op4.immediate)-1)
+ )));
+ break;
+ case MIPS_DEXT:
+ case MIPS_DEXTM:
+ case MIPS_DEXTU:
+ //op1 = op4.imm bits in op2.reg at bit offset op3.imm
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.And(8,
+ il.LogicalShiftRight(8,
+ ReadILOperand(il, instr, 2, registerSize),
+ il.Const(1, op3.immediate)
+ ),
+ il.Const(8, (((uint64_t)1)<<op4.immediate)-1)
+ )));
break;
case MIPS_INS:
+ // recall: pos = op3, size = op4
il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg,
il.Or(registerSize,
il.And(registerSize,
- il.Const(registerSize, ((1<<op4.immediate)-1)<<op3.immediate),
- ReadILOperand(il, instr, 1, registerSize)),
- il.And(registerSize,
- il.Const(registerSize, (1<<op4.immediate)-1),
- ReadILOperand(il, instr, 2, registerSize)))));
+ ReadILOperand(il, instr, 1, registerSize),
+ il.Const(registerSize, ~(((1<<op4.immediate)-1)<<op3.immediate))
+ ),
+ il.ShiftLeft(registerSize,
+ il.And(registerSize,
+ ReadILOperand(il, instr, 2, registerSize),
+ il.Const(registerSize, (1<<op4.immediate)-1)
+ ),
+ il.Const(registerSize, op3.immediate)
+ )
+ )));
+ break;
+ case MIPS_DINS:
+ case MIPS_DINSM:
+ case MIPS_DINSU:
+ // recall: pos = op3, size = op4
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.Or(8,
+ il.And(8,
+ ReadILOperand(il, instr, 1, registerSize),
+ il.Const(registerSize, ~(((((uint64_t)1)<<op4.immediate)-1)<<op3.immediate))
+ ),
+ il.ShiftLeft(8,
+ il.And(8,
+ ReadILOperand(il, instr, 2, registerSize),
+ il.Const(8, (((uint64_t)1)<<op4.immediate)-1)
+ ),
+ il.Const(8, op3.immediate)
+ )
+ )));
break;
case MIPS_LUI:
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.Const(4, op2.immediate << 16)));
@@ -830,16 +1392,72 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
case MIPS_LI:
case MIPS_LW:
case MIPS_LWX:
- case MIPS_LL: // TODO: Atomic access primitives
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, ReadILOperand(il, instr, 2, registerSize, 4)));
break;
+ case MIPS_LWU:
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, il.ZeroExtend(8, ReadILOperand(il, instr, 2, registerSize, 4))));
+ break;
case MIPS_LD:
il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, ReadILOperand(il, instr, 2, registerSize)));
break;
+ case MIPS_LWL:
+ {
+ int32_t delta = endian == LittleEndian ? -3 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(op1.reg) }, MIPS_INTRIN_SET_LEFT_PART32,
+ {
+ il.Load(4, GetILOperandMemoryAddress(il, op2, addrSize, delta))
+ }
+ ));
+
+ break;
+ }
+ case MIPS_LDL:
+ {
+ int32_t delta = endian == LittleEndian ? -7 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(op1.reg) }, MIPS_INTRIN_SET_LEFT_PART64,
+ {
+ il.Load(8, GetILOperandMemoryAddress(il, op2, addrSize, delta))
+ }
+ ));
+
+ break;
+ }
+ case MIPS_LWR:
+ {
+ int32_t delta = endian == BigEndian ? -3 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(op1.reg) }, MIPS_INTRIN_SET_RIGHT_PART32,
+ {
+ il.Load(4, GetILOperandMemoryAddress(il, op2, addrSize, delta))
+ }
+ ));
+
+ break;
+ }
+ case MIPS_LDR:
+ {
+ int32_t delta = endian == BigEndian ? -7 : 0;
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(op1.reg) }, MIPS_INTRIN_SET_RIGHT_PART64,
+ {
+ il.Load(8, GetILOperandMemoryAddress(il, op2, addrSize, delta))
+ }
+ ));
+
+ break;
+ }
+ case MIPS_LL:
+ il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, ReadILOperand(il, instr, 2, registerSize, 4)));
+ il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_LLBIT_SET, {il.Const(0, 1)}));
+ break;
+ case MIPS_LLD:
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, ReadILOperand(il, instr, 2, registerSize)));
+ il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_LLBIT_SET, {il.Const(0, 1)}));
+ break;
case MIPS_SRA:
- case MIPS_SRAV:
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.ArithShiftRight(4, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
break;
+ case MIPS_SRAV:
+ il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.ArithShiftRight(4, ReadILOperand(il, instr, 2, registerSize), il.And(4, ReadILOperand(il, instr, 3, registerSize), il.Const(4, 0x1f)))));
+ break;
case MIPS_SLT:
il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.BoolToInt(registerSize,
il.CompareSignedLessThan(registerSize, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize)))));
@@ -857,25 +1475,73 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
il.CompareUnsignedLessThan(registerSize, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize)))));
break;
case MIPS_SLL:
+ // SLL is unique in that the input doesn't have to be sign extended, and the
+ // preferred way to sign extend the lower 32 bits of an register is to shift
+ // it left by 0
+ if (registerSize == 8 && op2.reg != 0 && op3.immediate == 0)
+ {
+ il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.SignExtend(8, il.LowPart(4, ReadILOperand(il, instr, 2, 8)))));
+
+ }
+ else
+ {
+ il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.ShiftLeft(4, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
+ }
+ break;
case MIPS_SLLV:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.ShiftLeft(4, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
+ il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.ShiftLeft(4, ReadILOperand(il, instr, 2, registerSize), il.And(4, ReadILOperand(il, instr, 3, registerSize), il.Const(4, 0x1f)))));
break;
case MIPS_DSLL:
case MIPS_DSLL32:
- if (registerSize != 8) {
+ if (registerSize != 8)
+ {
il.AddInstruction(il.Unimplemented());
break;
}
il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, il.ShiftLeft(8, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
break;
+ case MIPS_DSLLV:
+ if (registerSize != 8)
+ {
+ il.AddInstruction(il.Undefined());
+ break;
+ }
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, il.ShiftLeft(8, ReadILOperand(il, instr, 2, registerSize), il.And(8, ReadILOperand(il, instr, 3, registerSize), il.Const(8, 0x3f)))));
+ break;
case MIPS_DSRL:
case MIPS_DSRL32:
- if (registerSize != 8) {
+ if (registerSize != 8)
+ {
il.AddInstruction(il.Unimplemented());
break;
}
il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, il.LogicalShiftRight(8, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
break;
+ case MIPS_DSRLV:
+ if (registerSize != 8)
+ {
+ il.AddInstruction(il.Undefined());
+ break;
+ }
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, il.LogicalShiftRight(8, ReadILOperand(il, instr, 2, registerSize), il.And(8, ReadILOperand(il, instr, 3, registerSize), il.Const(8, 0x3f)))));
+ break;
+ case MIPS_DSRA:
+ case MIPS_DSRA32:
+ if (registerSize != 8)
+ {
+ il.AddInstruction(il.Unimplemented());
+ break;
+ }
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, il.ArithShiftRight(8, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
+ break;
+ case MIPS_DSRAV:
+ if (registerSize != 8)
+ {
+ il.AddInstruction(il.Undefined());
+ break;
+ }
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg, il.ArithShiftRight(8, ReadILOperand(il, instr, 2, registerSize), il.And(8, ReadILOperand(il, instr, 3, registerSize), il.Const(8, 0x3f)))));
+ break;
case MIPS_SB:
il.AddInstruction(il.Store(1, GetILOperandMemoryAddress(il, op2, addrSize), il.LowPart(1, ReadILOperand(il, instr, 1, registerSize))));
break;
@@ -912,85 +1578,74 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.SignExtend(4, ReadILOperand(il, instr, 2, registerSize, 2))));
break;
case MIPS_LHU:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.ZeroExtend(4, ReadILOperand(il, instr, 2, registerSize, 2))));
- break;
- case MIPS_LWR:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.And(4,
- il.Const(4, 0xffff0000),
- il.Register(4, op1.reg))));
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Or(4,
- ReadILOperand(il, instr, 2, registerSize, 2),
- il.Register(4, op1.reg))));
- break;
- case MIPS_LWL:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.And(4,
- il.Const(4, 0xffff),
- il.Register(4, op1.reg))));
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg,
- il.Or(4,
- il.ShiftLeft(4,
- ReadILOperand(il, instr, 2, registerSize, 2),
- il.Const(1, 16)),
- il.Register(4, op1.reg))));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.ZeroExtend(4, ReadILOperand(il, instr, 2, registerSize, 2))));
break;
case MIPS_MADD:
- il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
- il.MultDoublePrecSigned(8,
- ReadILOperand(il, instr, 1, registerSize, 4),
- ReadILOperand(il, instr, 2, registerSize, 4))));
- il.AddInstruction(il.SetRegister(4, REG_LO,
- il.Add(4,
- il.Register(4, REG_LO),
- il.LowPart(4, il.Register(8, LLIL_TEMP(0))))));
- il.AddInstruction(il.SetRegister(4, REG_HI,
- il.Add(4,
- il.Register(4, REG_HI),
- il.LogicalShiftRight(4,
- il.Register(8, LLIL_TEMP(0)),
- il.Const(1, 16)))));
+ il.AddInstruction(il.SetRegisterSplit(4, REG_HI, REG_LO,
+ il.Add(8,
+ il.RegisterSplit(4, REG_HI, REG_LO),
+ il.MultDoublePrecSigned(4,
+ ReadILOperand(il, instr, 1, registerSize, 4),
+ ReadILOperand(il, instr, 2, registerSize, 4)
+ )
+ )
+ ));
+
+ if (registerSize == 8)
+ {
+ il.AddInstruction(il.SetRegister(8, REG_HI,
+ il.SignExtend(8, il.LowPart(4, il.Register(registerSize, REG_HI)))
+ ));
+
+ il.AddInstruction(il.SetRegister(8, REG_LO,
+ il.SignExtend(8, il.LowPart(4, il.Register(registerSize, REG_LO)))
+ ));
+ }
break;
case MIPS_MADDU:
- il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
- il.MultDoublePrecUnsigned(8,
- ReadILOperand(il, instr, 1, registerSize, 4),
- ReadILOperand(il, instr, 2, registerSize, 4))));
- il.AddInstruction(il.SetRegister(4, REG_LO,
- il.Add(4,
- il.Register(4, REG_LO),
- il.LowPart(4, il.Register(8, LLIL_TEMP(0))))));
- il.AddInstruction(il.SetRegister(4, REG_HI,
- il.Add(4,
- il.Register(4, REG_HI),
- il.LogicalShiftRight(4,
- il.Register(8, LLIL_TEMP(0)),
- il.Const(1, 16)))));
+ il.AddInstruction(il.SetRegisterSplit(4, REG_HI, REG_LO,
+ il.Add(8,
+ il.RegisterSplit(4, REG_HI, REG_LO),
+ il.MultDoublePrecUnsigned(4,
+ ReadILOperand(il, instr, 1, registerSize, 4),
+ ReadILOperand(il, instr, 2, registerSize, 4)
+ )
+ )
+ ));
+
+ if (registerSize == 8)
+ {
+ il.AddInstruction(il.SetRegister(8, REG_HI,
+ il.SignExtend(8, il.LowPart(4, il.Register(registerSize, REG_HI)))
+ ));
+
+ il.AddInstruction(il.SetRegister(8, REG_LO,
+ il.SignExtend(8, il.LowPart(4, il.Register(registerSize, REG_LO)))
+ ));
+ }
break;
case MIPS_ROTR:
case MIPS_ROTRV:
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.RotateRight(4, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
break;
- case MIPS_SC:
- il.AddInstruction(il.UnimplementedMemoryRef(4, ReadILOperand(il, instr, 2, registerSize)));
- break;
case MIPS_SDBBP:
il.AddInstruction(il.Unimplemented());
break;
case MIPS_SEB:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.SignExtend(4, il.LowPart(1, ReadILOperand(il, instr, 2, registerSize)))));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.SignExtend(registerSize, il.LowPart(1, ReadILOperand(il, instr, 2, registerSize)))));
break;
case MIPS_SEH:
- il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.SignExtend(4, il.LowPart(2, ReadILOperand(il, instr, 2, registerSize)))));
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.SignExtend(registerSize, il.LowPart(2, ReadILOperand(il, instr, 2, registerSize)))));
break;
case MIPS_SH:
il.AddInstruction(il.Store(2, GetILOperandMemoryAddress(il, op2, addrSize), il.LowPart(2, ReadILOperand(il, instr, 1, registerSize))));
break;
case MIPS_SRL:
- case MIPS_SRLV:
il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.LogicalShiftRight(4, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize))));
break;
+ case MIPS_SRLV:
+ il.AddInstruction(SetRegisterOrNop(il, 4, registerSize, op1.reg, il.LogicalShiftRight(4, ReadILOperand(il, instr, 2, registerSize), il.And(4, ReadILOperand(il, instr, 3, registerSize), il.Const(4, 0x1f)))));
+ break;
case MIPS_SSNOP:
case MIPS_NOP:
il.AddInstruction(il.Nop());
@@ -998,6 +1653,12 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
case MIPS_WSBH:
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, MIPS_INTRIN_WSBH, {ReadILOperand(il, instr, 2, registerSize)}));
break;
+ case MIPS_DSBH:
+ il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, MIPS_INTRIN_DSBH, {ReadILOperand(il, instr, 2, registerSize)}));
+ break;
+ case MIPS_DSHD:
+ il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, MIPS_INTRIN_DSHD, {ReadILOperand(il, instr, 2, registerSize)}));
+ break;
case MIPS_BGEZALL:
case MIPS_BLTZALL:
break;
@@ -1166,35 +1827,315 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
il.RegisterSplit(4, op2.reg | 1, op2.reg & (~1)))));
}
break;
+
+ case MIPS_SYNC:
+ {
+ uint64_t stype = 0;
+ if (op1.operandClass != NONE)
+ {
+ stype = op1.immediate;
+ }
+
+ il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_SYNC, {il.Const(1, stype)}));
+ break;
+ }
+
+ case MIPS_DI:
+ il.AddInstruction(SimpleIntrinsic(il, MIPS_INTRIN_DI));
+ break;
+
+ case MIPS_EHB:
+ il.AddInstruction(SimpleIntrinsic(il, MIPS_INTRIN_EHB));
+ break;
+
+ case MIPS_EI:
+ il.AddInstruction(SimpleIntrinsic(il, MIPS_INTRIN_EI));
+ break;
+
+ case MIPS_WAIT:
+ il.AddInstruction(SimpleIntrinsic(il, MIPS_INTRIN_WAIT));
+ break;
+
+ case MIPS_PREF:
+ il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_PREFETCH, {il.Const(1, op1.immediate), GetILOperandMemoryAddress(il, op2, addrSize)}));
+ break;
+
+ case MIPS_CACHE:
+ il.AddInstruction(il.Intrinsic({}, MIPS_INTRIN_CACHE, {il.Const(1, op1.immediate), GetILOperandMemoryAddress(il, op2, addrSize)}));
+ break;
+
+ case CNMIPS_BADDU:
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.ZeroExtend(registerSize,
+ il.Add(1,
+ il.LowPart(1, ReadILOperand(il, instr, 2, registerSize, 8)),
+ il.LowPart(1, ReadILOperand(il, instr, 3, registerSize, 8))
+ )
+ )
+ ));
+ break;
+
+ case CNMIPS_BBIT0:
+ case CNMIPS_BBIT032:
+ case CNMIPS_BBIT1:
+ case CNMIPS_BBIT132:
+ ConditionalJump(arch, il, GetConditionForInstruction(il, instr, registerSize), addrSize, op3.immediate, addr + 8);
+ break;
+
+ case CNMIPS_CINS:
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.ShiftLeft(8,
+ il.And(8,
+ ReadILOperand(il, instr, 2, registerSize),
+ il.Const(8, (((uint64_t)1) << (op4.immediate + 1)) - 1)),
+ il.Const(8, op3.immediate)
+ )
+ ));
+ break;
+
+ case CNMIPS_CINS32:
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.ShiftLeft(8,
+ il.And(8,
+ ReadILOperand(il, instr, 2, registerSize),
+ il.Const(8, (((uint64_t)1) << (op4.immediate + 1)) - 1)),
+ il.Const(8, op3.immediate + 32)
+ )
+ ));
+ break;
+
+ case CNMIPS_DMUL:
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.Mult(8,
+ ReadILOperand(il, instr, 2, registerSize, 8),
+ ReadILOperand(il, instr, 3, registerSize, 8))));
+ break;
+
+ case CNMIPS_EXTS:
+ // recall: p = op3.immediate, lenm1 = op4.immediate
+ if (op3.immediate == 0 && op4.immediate == 7)
+ {
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.SignExtend(8, il.LowPart(1, ReadILOperand(il, instr, 2, registerSize, registerSize)))
+ ));
+ }
+ else if (op3.immediate == 0 && op4.immediate == 0xf)
+ {
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.SignExtend(8, il.LowPart(2, ReadILOperand(il, instr, 2, registerSize, registerSize)))
+ ));
+ }
+ else if (op3.immediate == 0 && op4.immediate == 0x1f)
+ {
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.SignExtend(8, il.LowPart(4, ReadILOperand(il, instr, 2, registerSize, registerSize)))
+ ));
+ }
+ else
+ {
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.ArithShiftRight(8,
+ il.ShiftLeft(8,
+ ReadILOperand(il, instr, 2, registerSize, 8),
+ il.Const(8, 63 - (op3.immediate + op4.immediate))
+ ),
+ il.Const(8, 63 - op4.immediate)
+ )
+ ));
+ }
+ break;
+
+ case CNMIPS_EXTS32:
+ // recall: p = op3.immediate, lenm1 = op4.immediate
+ if (op3.immediate + op4.immediate + 32 > 63)
+ {
+ il.AddInstruction(il.Undefined());
+ }
+ else
+ {
+ il.AddInstruction(SetRegisterOrNop(il, 8, registerSize, op1.reg,
+ il.ArithShiftRight(8,
+ il.ShiftLeft(8,
+ ReadILOperand(il, instr, 2, registerSize, 8),
+ il.Const(8, 63 - (32 + op3.immediate + op4.immediate))
+ ),
+ il.Const(8, 63 - op4.immediate)
+ )
+ ));
+ }
+ break;
+
+ case CNMIPS_POP:
+ il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, CNMIPS_INTRIN_POP, {ReadILOperand(il, instr, 2, registerSize)}));
+ break;
+ case CNMIPS_DPOP:
+ il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, CNMIPS_INTRIN_DPOP, {ReadILOperand(il, instr, 2, registerSize)}));
+ break;
+ case CNMIPS_MTM0:
+ il.AddInstruction(il.SetRegister(registerSize, CNREG_MPL0, ReadILOperand(il, instr, 1, registerSize)));
+ break;
+ case CNMIPS_MTM1:
+ il.AddInstruction(il.SetRegister(registerSize, CNREG_MPL1, ReadILOperand(il, instr, 1, registerSize)));
+ break;
+ case CNMIPS_MTM2:
+ il.AddInstruction(il.SetRegister(registerSize, CNREG_MPL2, ReadILOperand(il, instr, 1, registerSize)));
+ break;
+ case CNMIPS_MTP0:
+ il.AddInstruction(il.SetRegister(registerSize, CNREG_P0, ReadILOperand(il, instr, 1, registerSize)));
+ break;
+ case CNMIPS_MTP1:
+ il.AddInstruction(il.SetRegister(registerSize, CNREG_P1, ReadILOperand(il, instr, 1, registerSize)));
+ break;
+ case CNMIPS_MTP2:
+ il.AddInstruction(il.SetRegister(registerSize, CNREG_P2, ReadILOperand(il, instr, 1, registerSize)));
+ break;
+ case CNMIPS_RDHWR:
+ {
+ MipsIntrinsic intrinsic;
+ switch (op2.immediate)
+ {
+ case 30: intrinsic = CNMIPS_INTRIN_HWR30; break;
+ case 31: intrinsic = CNMIPS_INTRIN_HWR31; break;
+ default: intrinsic = MIPS_INTRIN_HWR_UNKNOWN;
+ }
+
+ if (intrinsic != MIPS_INTRIN_HWR_UNKNOWN)
+ {
+ il.AddInstruction(
+ il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, intrinsic, {})
+ );
+ }
+ else
+ {
+ il.AddInstruction(
+ il.Intrinsic({RegisterOrFlag::Register(op1.reg)}, MIPS_INTRIN_HWR_UNKNOWN, {il.Const(1, op2.immediate)})
+ );
+ }
+ break;
+ }
+ case CNMIPS_SAA:
+ il.AddInstruction(
+ il.Store(4,
+ GetILOperandMemoryAddress(il, op2, addrSize),
+ il.Add(4,
+ il.Load(4, GetILOperandMemoryAddress(il, op2, addrSize)),
+ ReadILOperand(il, instr, 1, registerSize, 4)
+ )
+ )
+ );
+ break;
+
+ case CNMIPS_SAAD:
+ il.AddInstruction(
+ il.Store(8,
+ GetILOperandMemoryAddress(il, op2, addrSize),
+ il.Add(8,
+ il.Load(8, GetILOperandMemoryAddress(il, op2, addrSize)),
+ ReadILOperand(il, instr, 1, registerSize, 8)
+ )
+ )
+ );
+ break;
+
+ case CNMIPS_SEQ:
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.BoolToInt(registerSize,
+ il.CompareEqual(registerSize, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize)))));
+ break;
+
+ case CNMIPS_SEQI:
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.BoolToInt(registerSize,
+ il.CompareEqual(registerSize, ReadILOperand(il, instr, 2, registerSize), il.Const(registerSize, op3.immediate)))));
+ break;
+
+ case CNMIPS_SNE:
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.BoolToInt(registerSize,
+ il.CompareNotEqual(registerSize, ReadILOperand(il, instr, 2, registerSize), ReadILOperand(il, instr, 3, registerSize)))));
+ break;
+
+ case CNMIPS_SNEI:
+ il.AddInstruction(SetRegisterOrNop(il, registerSize, registerSize, op1.reg, il.BoolToInt(registerSize,
+ il.CompareNotEqual(registerSize, ReadILOperand(il, instr, 2, registerSize), il.Const(registerSize, op3.immediate)))));
+ break;
+
+ case CNMIPS_SYNCIOBDMA:
+ il.AddInstruction(SimpleIntrinsic(il, CNMIPS_INTRIN_SYNCIOBDMA));
+ break;
+
+ case CNMIPS_SYNCS:
+ il.AddInstruction(SimpleIntrinsic(il, CNMIPS_INTRIN_SYNCS));
+ break;
+
+ case CNMIPS_SYNCW:
+ il.AddInstruction(SimpleIntrinsic(il, CNMIPS_INTRIN_SYNCW));
+ break;
+
+ case CNMIPS_SYNCWS:
+ il.AddInstruction(SimpleIntrinsic(il, CNMIPS_INTRIN_SYNCWS));
+ break;
+
+ case CNMIPS_V3MULU:
+ // description of this behemoth of an instruction:
+ //
+ // ([0:64] || P2 || P1 || P0)
+ // + ([0:192] || rt)
+ // + (rs x (MPL2 || MPL1 || MPL0))
+ // ------------------------------
+ // (P2 || P1 || P0 || rd)
+ //
+ // register splits IL operations work with 2 registers, and
+ // considering Px registers as subregisters of a massive
+ // product register would also introduce complications (for example,
+ // note that P0 is in bits 63..0 in the first summand, but then
+ // occupies bits 127..64 of the total sum), so the simplest way forward
+ // seems to be to do shifts...
+ il.AddInstruction(il.SetRegister(0x20, LLIL_TEMP(0),
+ il.Add(0x20,
+ // [0:64] || P2 || P1 || P0
+ Concat3to256(il, CNREG_P2, CNREG_P1, CNREG_P0),
+ il.Add(0x20,
+ // [0:192] || rt
+ il.ZeroExtend(0x20, ReadILOperand(il, instr, 3, 8)),
+
+ // rs x (MPL2 || MPL1 || MPL0)
+ il.Mult(0x20,
+ il.ZeroExtend(0x20, ReadILOperand(il, instr, 2, 8)),
+ Concat3to256(il, CNREG_MPL2, CNREG_MPL1, CNREG_MPL0)
+ )
+ )
+ )
+ ));
+
+ il.AddInstruction(il.SetRegister(8, CNREG_P2,
+ il.LowPart(8, il.LogicalShiftRight(0x20, il.Register(0x20, LLIL_TEMP(0)), il.Const(4, 0xc0)))
+ ));
+
+ il.AddInstruction(il.SetRegister(8, CNREG_P1,
+ il.LowPart(8, il.LogicalShiftRight(0x20, il.Register(0x20, LLIL_TEMP(0)), il.Const(4, 0x80)))
+ ));
+
+ il.AddInstruction(il.SetRegister(8, CNREG_P0,
+ il.LowPart(8, il.LogicalShiftRight(0x20, il.Register(0x20, LLIL_TEMP(0)), il.Const(4, 0x40)))
+ ));
+
+ il.AddInstruction(SetRegisterOrNop(il, 8, 8, op1.reg, il.LowPart(8, il.Register(0x20, LLIL_TEMP(0)))));
+
+ break;
+
case MIPS_ADDR:
- case MIPS_DSLLV:
- case MIPS_DSRA32:
- case MIPS_DSRA:
- case MIPS_DSRAV:
- case MIPS_DSLV:
- case MIPS_DSUB:
- case MIPS_DSUBU:
- case MIPS_LDL:
- case MIPS_LDR:
case MIPS_LDXC1:
- case MIPS_LLD:
case MIPS_LLO:
case MIPS_LUXC1:
case MIPS_LWC1:
case MIPS_LWC2:
case MIPS_LWC3:
- case MIPS_LWU:
case MIPS_LWXC1:
case MIPS_MFHC1:
case MIPS_MFHC2:
case MIPS_MOVT:
case MIPS_MULR:
- case MIPS_SCD:
case MIPS_SDC1:
case MIPS_SDC2:
case MIPS_SDC3:
- case MIPS_SDL:
- case MIPS_SDR:
case MIPS_SDXC1:
case MIPS_LDC1:
case MIPS_LDC2:
@@ -1215,25 +2156,17 @@ bool GetLowLevelILForInstruction(Architecture* arch, uint64_t addr, LowLevelILFu
case MIPS_CTC1:
case MIPS_CTC2:
case MIPS_DERET:
- case MIPS_DI:
- case MIPS_DMULT:
- case MIPS_DMULTU:
case MIPS_DRET:
- case MIPS_EHB:
- case MIPS_EI:
case MIPS_JALX: //Special instruction for switching to MIPS32/microMIPS32/MIPS16e
case MIPS_MTHC1:
case MIPS_MTHC2:
case MIPS_PAUSE:
- case MIPS_PREF:
case MIPS_PREFX:
- case MIPS_SYNC:
case MIPS_SYNCI:
case MIPS_TLBP:
case MIPS_TLBR:
case MIPS_TLBWI:
case MIPS_TLBWR:
- case MIPS_WAIT:
case MIPS_WRPGPR:
case MIPS_RDPGPR:
case MIPS_RECIP1: