summaryrefslogtreecommitdiff
path: root/arch/mips
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
parentc3040ecfc43983af6f05da13cf2242d085b1e230 (diff)
Add Cavium Octeon MIPS Instructions and more general MIPS fixes
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/arch_mips.cpp1024
-rw-r--r--arch/mips/il.cpp1305
-rw-r--r--arch/mips/il.h58
-rw-r--r--arch/mips/mips/mips.c704
-rw-r--r--arch/mips/mips/mips.h249
5 files changed, 2982 insertions, 358 deletions
diff --git a/arch/mips/arch_mips.cpp b/arch/mips/arch_mips.cpp
index 7f4501ba..25ce265d 100644
--- a/arch/mips/arch_mips.cpp
+++ b/arch/mips/arch_mips.cpp
@@ -181,12 +181,12 @@ class MipsArchitecture: public Architecture
protected:
size_t m_bits;
BNEndianness m_endian;
- uint32_t m_enablePseudoOps;
+ uint32_t m_decomposeFlags;
virtual bool Disassemble(const uint8_t* data, uint64_t addr, size_t maxLen, Instruction& result)
{
memset(&result, 0, sizeof(result));
- if (mips_decompose((uint32_t*)data, maxLen, &result, m_bits == 64 ? MIPS_64 : MIPS_32, addr, m_endian, m_enablePseudoOps) != 0)
+ if (mips_decompose((uint32_t*)data, maxLen, &result, m_bits == 64 ? MIPS_64 : MIPS_32, addr, m_endian, m_decomposeFlags) != 0)
return false;
return true;
}
@@ -219,6 +219,7 @@ protected:
case MIPS_BLTZL:
case MIPS_BNE:
case MIPS_BNEL:
+ case MIPS_BNEZ:
case MIPS_JR:
case MIPS_JR_HB:
case MIPS_J:
@@ -233,6 +234,10 @@ protected:
case MIPS_BC2TL:
case MIPS_BC2F:
case MIPS_BC2T:
+ case CNMIPS_BBIT0:
+ case CNMIPS_BBIT032:
+ case CNMIPS_BBIT1:
+ case CNMIPS_BBIT132:
return 1;
default:
return 0;
@@ -244,8 +249,12 @@ protected:
{
switch (instr.operation)
{
+ case MIPS_LDL:
+ case MIPS_LDR:
case MIPS_LWL:
case MIPS_LWR:
+ case MIPS_SDL:
+ case MIPS_SDR:
case MIPS_SWL:
case MIPS_SWR:
return true;
@@ -270,6 +279,7 @@ protected:
case MIPS_BLTZL:
case MIPS_BEQ:
case MIPS_BNE:
+ case MIPS_BNEZ:
case MIPS_BEQL:
case MIPS_BNEL:
case MIPS_BC1F:
@@ -280,6 +290,10 @@ protected:
case MIPS_BC2TL:
case MIPS_BC2F:
case MIPS_BC2T:
+ case CNMIPS_BBIT0:
+ case CNMIPS_BBIT032:
+ case CNMIPS_BBIT1:
+ case CNMIPS_BBIT132:
return true;
default:
return false;
@@ -333,6 +347,7 @@ protected:
case MIPS_BGTZ:
case MIPS_BLEZ:
case MIPS_BLTZ:
+ case MIPS_BNEZ:
case MIPS_BGEZL:
case MIPS_BGTZL:
case MIPS_BLEZL:
@@ -346,6 +361,10 @@ protected:
case MIPS_BNE:
case MIPS_BEQL:
case MIPS_BNEL:
+ case CNMIPS_BBIT0:
+ case CNMIPS_BBIT032:
+ case CNMIPS_BBIT1:
+ case CNMIPS_BBIT132:
result.AddBranch(TrueBranch, instr.operands[2].immediate, nullptr, hasBranchDelay);
//need to jump over the branch delay slot and current instruction
result.AddBranch(FalseBranch, addr + 8, nullptr, hasBranchDelay);
@@ -383,10 +402,13 @@ protected:
}
public:
- MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits): Architecture(name), m_bits(bits), m_endian(endian)
+ MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits, uint32_t decomposeFlags = 0)
+ : Architecture(name), m_bits(bits), m_endian(endian), m_decomposeFlags(decomposeFlags)
{
Ref<Settings> settings = Settings::Instance();
- m_enablePseudoOps = settings->Get<bool>("arch.mips.disassembly.pseudoOps") ? 1 : 0;
+ uint32_t flag_pseudo_ops = settings->Get<bool>("arch.mips.disassembly.pseudoOps") ? DECOMPOSE_FLAGS_PSEUDO_OP : 0;
+
+ m_decomposeFlags |= flag_pseudo_ops;
}
virtual BNEndianness GetEndianness() const override
@@ -501,7 +523,7 @@ public:
il.AddInstruction(il.If(GetConditionForInstruction(il, instr, GetAddressSize()), trueCode, falseCode));
il.MarkLabel(trueCode);
il.SetCurrentAddress(this, addr + instr.size);
- GetLowLevelILForInstruction(this, addr + instr.size, il, secondInstr, GetAddressSize());
+ GetLowLevelILForInstruction(this, addr + instr.size, il, secondInstr, GetAddressSize(), m_decomposeFlags);
for (size_t i = 0; i < instrInfo.branchCount; i++)
{
if (instrInfo.branchType[i] == TrueBranch)
@@ -527,7 +549,7 @@ public:
nop = il.Nop();
il.AddInstruction(nop);
- GetLowLevelILForInstruction(this, addr + instr.size, il, secondInstr, GetAddressSize());
+ GetLowLevelILForInstruction(this, addr + instr.size, il, secondInstr, GetAddressSize(), m_decomposeFlags);
LowLevelILInstruction delayed;
uint32_t clobbered = BN_INVALID_REGISTER;
@@ -554,7 +576,7 @@ public:
}
else
{
- status = GetLowLevelILForInstruction(this, addr, il, instr, GetAddressSize());
+ status = GetLowLevelILForInstruction(this, addr, il, instr, GetAddressSize(), m_decomposeFlags);
}
if (clobbered != BN_INVALID_REGISTER)
@@ -603,45 +625,110 @@ public:
Instruction* base;
uint32_t addrToUse;
bool store = false;
- bool proceed = true;
+ bool proceed = false;
+ bool is32bit = false;
switch (instr.operation)
{
- case MIPS_SWL:
- store = true;
- // fall through
- case MIPS_LWL:
- proceed = (secondInstr.operation == (store ? MIPS_SWR : MIPS_LWR));
- left = &instr;
- right = &secondInstr;
- break;
+ case MIPS_LDL: proceed = secondInstr.operation == MIPS_LDR; break;
+ case MIPS_LDR: proceed = secondInstr.operation == MIPS_LDL; break;
+ case MIPS_LWL: proceed = secondInstr.operation == MIPS_LWR; break;
+ case MIPS_LWR: proceed = secondInstr.operation == MIPS_LWL; break;
- case MIPS_SWR:
- store = true;
- // fall through
- case MIPS_LWR:
- proceed = (secondInstr.operation == (store ? MIPS_SWL : MIPS_LWL));
- left = &secondInstr;
- right = &instr;
- break;
+ case MIPS_SDL: proceed = secondInstr.operation == MIPS_SDR; break;
+ case MIPS_SDR: proceed = secondInstr.operation == MIPS_SDL; break;
+ case MIPS_SWL: proceed = secondInstr.operation == MIPS_SWR; break;
+ case MIPS_SWR: proceed = secondInstr.operation == MIPS_SWL; break;
- default:
- proceed = false;
- break;
+ default: proceed = false;
+ }
+
+ switch (instr.operation)
+ {
+ case MIPS_SDL:
+ case MIPS_SDR:
+ case MIPS_SWL:
+ case MIPS_SWR:
+ store = true;
+ break;
+ case MIPS_LDL:
+ case MIPS_LDR:
+ case MIPS_LWL:
+ case MIPS_LWR:
+ store = false;
+ break;
+
+ default: proceed = false;
+ }
+
+ switch (instr.operation)
+ {
+ case MIPS_LDL:
+ case MIPS_LWL:
+ case MIPS_SDL:
+ case MIPS_SWL:
+ left = &instr;
+ right = &secondInstr;
+ break;
+
+ case MIPS_LDR:
+ case MIPS_LWR:
+ case MIPS_SDR:
+ case MIPS_SWR:
+ left = &secondInstr;
+ right = &instr;
+ break;
+
+ default: proceed = false;
+ }
+
+ switch (instr.operation)
+ {
+ case MIPS_LWL:
+ case MIPS_LWR:
+ case MIPS_SWL:
+ case MIPS_SWR:
+ is32bit = true;
+ break;
+
+ case MIPS_LDL:
+ case MIPS_LDR:
+ case MIPS_SDL:
+ case MIPS_SDR:
+ is32bit = false;
+ break;
+
+ default: proceed = false;
}
proceed = proceed && (instr.operands[0].reg == secondInstr.operands[0].reg);
if (m_endian == BigEndian)
{
- proceed = proceed && ((left->operands[1].immediate + 3) == right->operands[1].immediate);
- addrToUse = (uint32_t)addr + ((&instr == left) ? 0 : 4);
+ if (is32bit)
+ {
+ proceed = proceed && ((left->operands[1].immediate + 3) == right->operands[1].immediate);
+ addrToUse = (uint32_t)addr + ((&instr == left) ? 0 : 4);
+ }
+ else
+ {
+ proceed = proceed && ((left->operands[1].immediate + 7) == right->operands[1].immediate);
+ addrToUse = (uint32_t)addr + ((&instr == left) ? 0 : 8);
+ }
base = left;
}
else
{
- proceed = proceed && (left->operands[1].immediate == (right->operands[1].immediate + 3));
- addrToUse = (uint32_t)addr + ((&instr == right) ? 0 : 4);
+ if (is32bit)
+ {
+ proceed = proceed && (left->operands[1].immediate == (right->operands[1].immediate + 3));
+ addrToUse = (uint32_t)addr + ((&instr == right) ? 0 : 4);
+ }
+ else
+ {
+ proceed = proceed && (left->operands[1].immediate == (right->operands[1].immediate + 7));
+ addrToUse = (uint32_t)addr + ((&instr == right) ? 0 : 8);
+ }
base = right;
}
@@ -649,13 +736,17 @@ public:
{
len = 8;
il.SetCurrentAddress(this, addrToUse);
- base->operation = store ? MIPS_SW : MIPS_LW;
- return GetLowLevelILForInstruction(this, addrToUse, il, *base, GetAddressSize());
+ if (store)
+ base->operation = is32bit ? MIPS_SW : MIPS_SD;
+ else
+ base->operation = is32bit ? MIPS_LW : MIPS_LD;
+
+ return GetLowLevelILForInstruction(this, addrToUse, il, *base, GetAddressSize(), m_decomposeFlags);
}
}
len = instr.size;
- return GetLowLevelILForInstruction(this, addr, il, instr, GetAddressSize());
+ return GetLowLevelILForInstruction(this, addr, il, instr, GetAddressSize(), m_decomposeFlags);
}
virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override
@@ -702,6 +793,8 @@ public:
return true;
int32_t imm = instr.operands[i].immediate;
+ uint64_t label_imm = instr.operands[i].immediate;
+
if (i != 0)
result.emplace_back(OperandSeparatorToken, ", ");
@@ -720,7 +813,7 @@ public:
result.emplace_back(IntegerToken, operand, imm);
break;
case LABEL:
- snprintf(operand, sizeof(operand), "%#x", imm);
+ snprintf(operand, sizeof(operand), "%#" PRIx64, label_imm);
result.emplace_back(PossibleAddressToken, operand, imm);
break;
case REG:
@@ -800,22 +893,97 @@ public:
{
case MIPS_INTRIN_WSBH:
return "__wsbh";
+ case MIPS_INTRIN_DSBH:
+ return "_dsbh";
+ case MIPS_INTRIN_DSHD:
+ return "_dshd";
case MIPS_INTRIN_MFC0:
- return "moveFromCoprocessor";
+ return "moveFromCoprocessor0";
+ case MIPS_INTRIN_MFC2:
+ return "moveFromCoprocessor2";
case MIPS_INTRIN_MFC_UNIMPLEMENTED:
return "moveFromCoprocessorUnimplemented";
case MIPS_INTRIN_MTC0:
- return "moveToCoprocessor";
+ return "moveToCoprocessor0";
+ case MIPS_INTRIN_MTC2:
+ return "moveToCoprocessor2";
case MIPS_INTRIN_MTC_UNIMPLEMENTED:
return "moveToCoprocessorUnimplemented";
case MIPS_INTRIN_DMFC0:
- return "moveDwordFromCoprocessor";
+ return "moveDwordFromCoprocessor0";
+ case MIPS_INTRIN_DMFC2:
+ return "moveDwordFromCoprocessor2";
case MIPS_INTRIN_DMFC_UNIMPLEMENTED:
return "moveDwordFromCoprocessorUnimplemented";
case MIPS_INTRIN_DMTC0:
- return "moveDwordToCoprocessor";
+ return "moveDwordToCoprocessor0";
+ case MIPS_INTRIN_DMTC2:
+ return "moveDwordToCoprocessor2";
case MIPS_INTRIN_DMTC_UNIMPLEMENTED:
return "moveDwordToCoprocessorUnimplemented";
+ case MIPS_INTRIN_SYNC:
+ return "_sync";
+ case MIPS_INTRIN_EI:
+ return "_enableInterrupts";
+ case MIPS_INTRIN_DI:
+ return "_disableInterrupts";
+ case MIPS_INTRIN_EHB:
+ return "_clearExecutionHazards";
+ case MIPS_INTRIN_WAIT:
+ return "_enterLowPowerMode";
+ case MIPS_INTRIN_HWR0:
+ return "_cpuNum";
+ case MIPS_INTRIN_HWR1:
+ return "_synciStep";
+ case MIPS_INTRIN_HWR2:
+ return "_cycleCounter";
+ case MIPS_INTRIN_HWR3:
+ return "_cycleCounterResolution";
+ case MIPS_INTRIN_HWR29:
+ return "_userLocalRegister";
+ case MIPS_INTRIN_HWR_UNKNOWN:
+ return "_hardwareRegister";
+ case MIPS_INTRIN_LLBIT_SET:
+ return "_setLLBit";
+ case MIPS_INTRIN_LLBIT_CHECK:
+ return "_checkLLBit";
+ case MIPS_INTRIN_PREFETCH:
+ return "_prefetch";
+ case MIPS_INTRIN_CACHE:
+ return "_cache";
+ case MIPS_INTRIN_GET_LEFT_PART32:
+ return "_getLeftPart32";
+ case MIPS_INTRIN_GET_RIGHT_PART32:
+ return "_getRightPart32";
+ case MIPS_INTRIN_SET_LEFT_PART32:
+ return "_setLeftPart32";
+ case MIPS_INTRIN_SET_RIGHT_PART32:
+ return "_setRightPart32";
+ case MIPS_INTRIN_GET_LEFT_PART64:
+ return "_getLeftPart64";
+ case MIPS_INTRIN_GET_RIGHT_PART64:
+ return "_getRightPart64";
+ case MIPS_INTRIN_SET_LEFT_PART64:
+ return "_setLeftPart64";
+ case MIPS_INTRIN_SET_RIGHT_PART64:
+ return "_setRightPart64";
+
+ case CNMIPS_INTRIN_SYNCIOBDMA:
+ return "_synciobdma";
+ case CNMIPS_INTRIN_SYNCS:
+ return "_syncs";
+ case CNMIPS_INTRIN_SYNCW:
+ return "_syncw";
+ case CNMIPS_INTRIN_SYNCWS:
+ return "_syncws";
+ case CNMIPS_INTRIN_HWR30:
+ return "_chOrd";
+ case CNMIPS_INTRIN_HWR31:
+ return "_cvmCount";
+ case CNMIPS_INTRIN_POP:
+ return "_countOnes32";
+ case CNMIPS_INTRIN_DPOP:
+ return "_countOnes64";
default:
return "";
}
@@ -825,6 +993,8 @@ public:
{
return vector<uint32_t>{
MIPS_INTRIN_WSBH,
+ MIPS_INTRIN_DSBH,
+ MIPS_INTRIN_DSHD,
MIPS_INTRIN_MFC0,
MIPS_INTRIN_MFC_UNIMPLEMENTED,
MIPS_INTRIN_MTC0,
@@ -833,6 +1003,38 @@ public:
MIPS_INTRIN_DMFC_UNIMPLEMENTED,
MIPS_INTRIN_DMTC0,
MIPS_INTRIN_DMTC_UNIMPLEMENTED,
+ MIPS_INTRIN_SYNC,
+ MIPS_INTRIN_DI,
+ MIPS_INTRIN_EHB,
+ MIPS_INTRIN_EI,
+ MIPS_INTRIN_WAIT,
+ MIPS_INTRIN_HWR0,
+ MIPS_INTRIN_HWR1,
+ MIPS_INTRIN_HWR2,
+ MIPS_INTRIN_HWR3,
+ MIPS_INTRIN_HWR29,
+ MIPS_INTRIN_HWR_UNKNOWN,
+ MIPS_INTRIN_LLBIT_SET,
+ MIPS_INTRIN_LLBIT_CHECK,
+ MIPS_INTRIN_PREFETCH,
+ MIPS_INTRIN_CACHE,
+ MIPS_INTRIN_GET_LEFT_PART32,
+ MIPS_INTRIN_GET_RIGHT_PART32,
+ MIPS_INTRIN_SET_LEFT_PART32,
+ MIPS_INTRIN_SET_RIGHT_PART32,
+ MIPS_INTRIN_GET_LEFT_PART64,
+ MIPS_INTRIN_GET_RIGHT_PART64,
+ MIPS_INTRIN_SET_LEFT_PART64,
+ MIPS_INTRIN_SET_RIGHT_PART64,
+
+ CNMIPS_INTRIN_SYNCIOBDMA,
+ CNMIPS_INTRIN_SYNCS,
+ CNMIPS_INTRIN_SYNCW,
+ CNMIPS_INTRIN_SYNCWS,
+ CNMIPS_INTRIN_HWR30,
+ CNMIPS_INTRIN_HWR31,
+ CNMIPS_INTRIN_POP,
+ CNMIPS_INTRIN_DPOP,
};
}
@@ -842,6 +1044,9 @@ public:
{
case MIPS_INTRIN_WSBH:
return {NameAndType(Type::IntegerType(4, false))};
+ case MIPS_INTRIN_DSBH:
+ case MIPS_INTRIN_DSHD:
+ return {NameAndType(Type::IntegerType(8, false))};
case MIPS_INTRIN_MFC0:
return {
NameAndType("register", Type::IntegerType(4, false)),
@@ -886,6 +1091,71 @@ public:
NameAndType("selector", Type::IntegerType(4, false)),
NameAndType("value", Type::IntegerType(8, false)),
};
+ case MIPS_INTRIN_SYNC:
+ return {
+ NameAndType("stype", Type::IntegerType(4, false)),
+ };
+ case MIPS_INTRIN_HWR_UNKNOWN:
+ return {
+ NameAndType("hwreg", Type::IntegerType(4, false)),
+ };
+ case MIPS_INTRIN_LLBIT_SET:
+ return {
+ NameAndType("value", Type::IntegerType(4, false)),
+ };
+ case MIPS_INTRIN_PREFETCH:
+ case MIPS_INTRIN_CACHE:
+ return {
+ NameAndType("op", Type::IntegerType(1, false)),
+ NameAndType("address", Type::IntegerType(m_bits == 64 ? 8 : 4, false)),
+ };
+
+ // NOTE: SET_x_PARTx could potentially benefit from
+ // including the old value as an input (since each
+ // only sets part of the register and keeps the
+ // other the same), but this can lead to registers
+ // unnecessarily treated as function arguments
+ //
+ // NOTE: PARTx intrinsics could benefit from some kind
+ // of "size" input indicating how many bytes to
+ // get/set, but that value would be taking the
+ // low bits of a pointer with unknown value, which
+ // isn't exactly useful
+ //
+ // PLUS, the majority of the SWL/SWR/etc.
+ // instructions that get lifted by themselves
+ // actually *are* members of a pair that just
+ // aren't immediately next to each other, so they
+ // go through the code checking for those pairs...
+ // so for each "rX = setLeftXX([address])" we also
+ // expect to see a "rY = setRightXX([address])",
+ // which is a little more follow-able
+ case MIPS_INTRIN_GET_LEFT_PART32:
+ case MIPS_INTRIN_GET_RIGHT_PART32:
+ return {
+ NameAndType("value", Type::IntegerType(4, false)),
+ };
+ case MIPS_INTRIN_SET_LEFT_PART32:
+ return {
+ NameAndType("leftpart", Type::IntegerType(4, false))
+ };
+ case MIPS_INTRIN_SET_RIGHT_PART32:
+ return {
+ NameAndType("rightpart", Type::IntegerType(4, false))
+ };
+ case MIPS_INTRIN_GET_LEFT_PART64:
+ case MIPS_INTRIN_GET_RIGHT_PART64:
+ return {
+ NameAndType("value", Type::IntegerType(8, false)),
+ };
+ case MIPS_INTRIN_SET_LEFT_PART64:
+ return {
+ NameAndType("leftpart", Type::IntegerType(8, false))
+ };
+ case MIPS_INTRIN_SET_RIGHT_PART64:
+ return {
+ NameAndType("rightpart", Type::IntegerType(8, false))
+ };
default:
return vector<NameAndType>();
}
@@ -896,13 +1166,39 @@ public:
switch (intrinsic)
{
case MIPS_INTRIN_WSBH:
+ case CNMIPS_INTRIN_POP:
return {Type::IntegerType(4, false)};
+ case MIPS_INTRIN_DSBH:
+ case MIPS_INTRIN_DSHD:
+ case CNMIPS_INTRIN_DPOP:
+ return {Type::IntegerType(8, false)};
case MIPS_INTRIN_MFC0:
case MIPS_INTRIN_MFC_UNIMPLEMENTED:
return {Type::IntegerType(4, false)};
case MIPS_INTRIN_DMFC0:
case MIPS_INTRIN_DMFC_UNIMPLEMENTED:
return {Type::IntegerType(8, false)};
+ case MIPS_INTRIN_HWR0:
+ case MIPS_INTRIN_HWR1:
+ case MIPS_INTRIN_HWR2:
+ case MIPS_INTRIN_HWR3:
+ case MIPS_INTRIN_HWR29:
+ case MIPS_INTRIN_HWR_UNKNOWN:
+ case CNMIPS_INTRIN_HWR30:
+ case CNMIPS_INTRIN_HWR31:
+ return {Type::IntegerType(4, false)};
+ case MIPS_INTRIN_LLBIT_CHECK:
+ return {Type::IntegerType(0, false)};
+ case MIPS_INTRIN_GET_LEFT_PART32:
+ case MIPS_INTRIN_GET_RIGHT_PART32:
+ case MIPS_INTRIN_SET_LEFT_PART32:
+ case MIPS_INTRIN_SET_RIGHT_PART32:
+ return {Type::IntegerType(4, false)};
+ case MIPS_INTRIN_GET_LEFT_PART64:
+ case MIPS_INTRIN_GET_RIGHT_PART64:
+ case MIPS_INTRIN_SET_LEFT_PART64:
+ case MIPS_INTRIN_SET_RIGHT_PART64:
+ return {Type::IntegerType(8, false)};
default:
return vector<Confidence<Ref<Type>>>();
}
@@ -995,7 +1291,7 @@ public:
if (GetEndianness() == LittleEndian)
instValue = bswap32(instValue);
- uint32_t op = instValue >> 25;
+ uint32_t op = instValue >> 26;
switch (op)
{
case 1: //REGIMM
@@ -1074,7 +1370,7 @@ public:
virtual vector<uint32_t> GetFullWidthRegisters() override
{
- return vector<uint32_t>{
+ vector<uint32_t> registers = vector<uint32_t>{
REG_ZERO, REG_AT, REG_V0, REG_V1, REG_A0, REG_A1, REG_A2, REG_A3,
REG_T0, REG_T1, REG_T2, REG_T3, REG_T4, REG_T5, REG_T6, REG_T7,
REG_S0, REG_S1, REG_S2, REG_S3, REG_S4, REG_S5, REG_S6, REG_S7,
@@ -1190,11 +1486,210 @@ public:
// Coprocessor 0 register 31
REG_DESAVE,
};
+
+ if ((m_decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ uint32_t cavium_registers[] =
+ {
+ CNREG_MPL0,
+ CNREG_MPL1,
+ CNREG_MPL2,
+ CNREG_P0,
+ CNREG_P1,
+ CNREG_P2,
+
+ CNREG0_CVM_COUNT,
+ CNREG0_CVM_CTL,
+ CNREG0_POWTHROTTLE,
+ CNREG0_CVM_MEM_CTL,
+ CNREG0_MULTICORE_DBG,
+
+ CNREG2_0040_HSH_DAT0,
+ CNREG2_0041_HSH_DAT1,
+ CNREG2_0042_HSH_DAT2,
+ CNREG2_0043_HSH_DAT3,
+ CNREG2_0044_HSH_DAT4,
+ CNREG2_0045_HSH_DAT5,
+ CNREG2_0046_HSH_DAT6,
+
+ CNREG2_0048_HSH_IV0,
+ CNREG2_0049_HSH_IV1,
+ CNREG2_004A_HSH_IV2,
+ CNREG2_004B_HSH_IV3,
+
+ CNREG2_0050_SHA3_DAT24,
+ CNREG2_0051_SHA3_DAT15_RD,
+
+ CNREG2_0058_GFM_MUL_REFLECT0,
+ CNREG2_0059_GFM_MUL_REFLECT1,
+ CNREG2_005A_GFM_RESINP_REFLECT0,
+ CNREG2_005B_GFM_RESINP_REFLECT1,
+ CNREG2_005C_GFM_XOR0_REFLECT,
+
+ // also KASUMI
+ CNREG2_0080_3DES_KEY0,
+ CNREG2_0081_3DES_KEY1,
+ CNREG2_0082_3DES_KEY2,
+
+ CNREG2_0084_3DES_IV,
+ CNREG2_0088_3DES_RESULT_RD,
+ CNREG2_0098_3DES_RESULT_WR,
+
+ // also SMS4 RESINP
+ CNREG2_0100_AES_RESULT0,
+ CNREG2_0101_AES_RESULT1,
+
+ // also SMS4 IV
+ CNREG2_0102_AES_IV0,
+ CNREG2_0103_AES_IV1,
+
+ // also SMS4 KEY
+ CNREG2_0104_AES_KEY0,
+ CNREG2_0105_AES_KEY1,
+ CNREG2_0106_AES_KEY2,
+ CNREG2_0107_AES_KEY3,
+
+ // also SMS4_x
+ CNREG2_0108_AES_ENC_CBC0,
+ CNREG2_010A_AES_ENC0,
+ CNREG2_010C_AES_DEC_CBC0,
+ CNREG2_010E_AES_DEC0,
+
+ CNREG2_0110_AES_KEYLENGTH,
+ CNREG2_0111_AES_DAT0,
+
+ CNREG2_0115_CAMELLIA_FL,
+ CNREG2_0116_CAMELLIA_FLINV,
+
+ CNREG2_0200_CRC_POLYNOMIAL,
+ CNREG2_0201_CRC_IV,
+ CNREG2_0202_CRC_LEN,
+ CNREG2_0203_CRC_IV_REFLECT_RD,
+ CNREG2_0204_CRC_BYTE,
+ CNREG2_0205_CRC_HALF,
+ CNREG2_0206_CRC_WORD,
+ CNREG2_0211_CRC_IV_REFLECT_WR,
+ CNREG2_0214_CRC_BYTE_REFLECT,
+ CNREG2_0215_CRC_HALF_REFLECT,
+ CNREG2_0216_CRC_WORD_REFLECT,
+
+ // also SNOW3G_LFSR, SHA3DAT0..=14
+ CNREG2_0240_HSH_DATW0,
+ CNREG2_0241_HSH_DATW1,
+ CNREG2_0242_HSH_DATW2,
+ CNREG2_0243_HSH_DATW3,
+ CNREG2_0244_HSH_DATW4,
+ CNREG2_0245_HSH_DATW5,
+ CNREG2_0246_HSH_DATW6,
+ CNREG2_0247_HSH_DATW7,
+ CNREG2_0248_HSH_DATW8,
+ CNREG2_0249_HSH_DATW9,
+ CNREG2_024A_HSH_DATW10,
+ CNREG2_024B_HSH_DATW11,
+ CNREG2_024C_HSH_DATW12,
+ CNREG2_024D_HSH_DATW13,
+ CNREG2_024E_HSH_DATW14,
+
+ CNREG2_024F_SHA3_DAT15_RD,
+
+ // also SNOW3G_RESULT (0x250), SNOW3G_SFM (0x251, 0x252, 0x253)
+ CNREG2_0250_HSH_IVW0,
+ CNREG2_0251_HSH_IVW1,
+ CNREG2_0252_HSH_IVW2,
+ CNREG2_0253_HSH_IVW3,
+ CNREG2_0254_HSH_IVW4,
+ CNREG2_0255_HSH_IVW5,
+ CNREG2_0256_HSH_IVW6,
+ CNREG2_0257_HSH_IVW7,
+
+ CNREG2_0258_GFM_MUL0,
+ CNREG2_0259_GFM_MUL1,
+ CNREG2_025A_GFM_RESINP0,
+ CNREG2_025B_GFM_RESINP1,
+ CNREG2_025C_GFM_XOR0,
+ CNREG2_025E_GFM_POLY,
+
+ CNREG2_02C0_SHA3_XORDAT0,
+ CNREG2_02C1_SHA3_XORDAT1,
+ CNREG2_02C2_SHA3_XORDAT2,
+ CNREG2_02C3_SHA3_XORDAT3,
+ CNREG2_02C4_SHA3_XORDAT4,
+ CNREG2_02C5_SHA3_XORDAT5,
+ CNREG2_02C6_SHA3_XORDAT6,
+ CNREG2_02C7_SHA3_XORDAT7,
+ CNREG2_02C8_SHA3_XORDAT8,
+ CNREG2_02C9_SHA3_XORDAT9,
+ CNREG2_02CA_SHA3_XORDAT10,
+ CNREG2_02CB_SHA3_XORDAT11,
+ CNREG2_02CC_SHA3_XORDAT12,
+ CNREG2_02CD_SHA3_XORDAT13,
+ CNREG2_02CE_SHA3_XORDAT14,
+ CNREG2_02CF_SHA3_XORDAT15,
+ CNREG2_02D0_SHA3_XORDAT16,
+ CNREG2_02D1_SHA3_XORDAT17,
+
+ CNREG2_0400_LLM_READ_ADDR0,
+ CNREG2_0401_LLM_WRITE_ADDR_INTERNAL0,
+ CNREG2_0402_LLM_DATA0,
+ CNREG2_0404_LLM_READ64_ADDR0,
+ CNREG2_0405_LLM_WRITE64_ADDR_INTERNAL0,
+ CNREG2_0408_LLM_READ_ADDR1,
+ CNREG2_0409_LLM_WRITE_ADDR_INTERNAL1,
+ CNREG2_040a_LLM_DATA1,
+ CNREG2_040c_LLM_READ64_ADDR1,
+ CNREG2_040d_LLM_WRITE64_ADDR_INTERNAL1,
+
+ CNREG2_1202_CRC_LEN,
+ CNREG2_1207_CRC_DWORD,
+ CNREG2_1208_CRC_VAR,
+ CNREG2_1217_CRC_DWORD_REFLECT,
+ CNREG2_1218_CRC_VAR_REFLECT,
+
+ CNREG2_3109_AES_ENC_CBC1,
+ CNREG2_310B_AES_ENC1,
+ CNREG2_310D_AES_DEC_CBC1,
+ CNREG2_310F_AES_DEC1,
+
+ CNREG2_3114_CAMELLIA_ROUND,
+
+ CNREG2_3119_SMS4_ENC_CBC1,
+ CNREG2_311B_SMS4_ENC1,
+ CNREG2_311D_SMS4_DEC_CBC1,
+ CNREG2_311F_SMS4_DEC1,
+
+ CNREG2_4052_SHA3_STARTOP,
+ CNREG2_4047_HSH_STARTMD5,
+ CNREG2_404D_SNOW3G_START,
+ CNREG2_4055_ZUC_START,
+ CNREG2_4056_ZUC_MORE,
+ CNREG2_405D_GFM_XORMUL1_REFLECT,
+ CNREG2_404E_SNOW3G_MORE,
+ CNREG2_404F_HSH_STARTSHA256,
+ CNREG2_4057_HSH_STARTSHA,
+ CNREG2_4088_3DES_ENC_CBC,
+ CNREG2_4089_KAS_ENC_CBC,
+ CNREG2_408A_3DES_ENC,
+ CNREG2_408B_KAS_ENC,
+ CNREG2_408C_3DES_DEC_CBC,
+ CNREG2_408E_3DES_DEC,
+
+ CNREG2_4200_CRC_POLYNOMIAL_WR,
+ CNREG2_4210_CRC_POLYNOMIAL_REFLECT,
+
+ CNREG2_424F_HSH_STARTSHA512,
+ CNREG2_425D_GFM_XORMUL1,
+
+ };
+
+ registers.insert(registers.end(), std::begin(cavium_registers), std::end(cavium_registers));
+ }
+
+ return registers;
}
virtual vector<uint32_t> GetAllRegisters() override
{
- return vector<uint32_t>{
+ vector<uint32_t> registers = vector<uint32_t>{
REG_ZERO, REG_AT, REG_V0, REG_V1, REG_A0, REG_A1, REG_A2, REG_A3,
REG_T0, REG_T1, REG_T2, REG_T3, REG_T4, REG_T5, REG_T6, REG_T7,
REG_S0, REG_S1, REG_S2, REG_S3, REG_S4, REG_S5, REG_S6, REG_S7,
@@ -1309,6 +1804,205 @@ public:
// Coprocessor 0 register 31
REG_DESAVE,
};
+
+ if ((m_decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ uint32_t cavium_registers[] =
+ {
+ CNREG_MPL0,
+ CNREG_MPL1,
+ CNREG_MPL2,
+ CNREG_P0,
+ CNREG_P1,
+ CNREG_P2,
+
+ CNREG0_CVM_COUNT,
+ CNREG0_CVM_CTL,
+ CNREG0_POWTHROTTLE,
+ CNREG0_CVM_MEM_CTL,
+ CNREG0_MULTICORE_DBG,
+
+ CNREG2_0040_HSH_DAT0,
+ CNREG2_0041_HSH_DAT1,
+ CNREG2_0042_HSH_DAT2,
+ CNREG2_0043_HSH_DAT3,
+ CNREG2_0044_HSH_DAT4,
+ CNREG2_0045_HSH_DAT5,
+ CNREG2_0046_HSH_DAT6,
+
+ CNREG2_0048_HSH_IV0,
+ CNREG2_0049_HSH_IV1,
+ CNREG2_004A_HSH_IV2,
+ CNREG2_004B_HSH_IV3,
+
+ CNREG2_0050_SHA3_DAT24,
+ CNREG2_0051_SHA3_DAT15_RD,
+
+ CNREG2_0058_GFM_MUL_REFLECT0,
+ CNREG2_0059_GFM_MUL_REFLECT1,
+ CNREG2_005A_GFM_RESINP_REFLECT0,
+ CNREG2_005B_GFM_RESINP_REFLECT1,
+ CNREG2_005C_GFM_XOR0_REFLECT,
+
+ // also KASUMI
+ CNREG2_0080_3DES_KEY0,
+ CNREG2_0081_3DES_KEY1,
+ CNREG2_0082_3DES_KEY2,
+
+ CNREG2_0084_3DES_IV,
+ CNREG2_0088_3DES_RESULT_RD,
+ CNREG2_0098_3DES_RESULT_WR,
+
+ // also SMS4 RESINP
+ CNREG2_0100_AES_RESULT0,
+ CNREG2_0101_AES_RESULT1,
+
+ // also SMS4 IV
+ CNREG2_0102_AES_IV0,
+ CNREG2_0103_AES_IV1,
+
+ // also SMS4 KEY
+ CNREG2_0104_AES_KEY0,
+ CNREG2_0105_AES_KEY1,
+ CNREG2_0106_AES_KEY2,
+ CNREG2_0107_AES_KEY3,
+
+ // also SMS4_x
+ CNREG2_0108_AES_ENC_CBC0,
+ CNREG2_010A_AES_ENC0,
+ CNREG2_010C_AES_DEC_CBC0,
+ CNREG2_010E_AES_DEC0,
+
+ CNREG2_0110_AES_KEYLENGTH,
+ CNREG2_0111_AES_DAT0,
+
+ CNREG2_0115_CAMELLIA_FL,
+ CNREG2_0116_CAMELLIA_FLINV,
+
+ CNREG2_0200_CRC_POLYNOMIAL,
+ CNREG2_0201_CRC_IV,
+ CNREG2_0202_CRC_LEN,
+ CNREG2_0203_CRC_IV_REFLECT_RD,
+ CNREG2_0204_CRC_BYTE,
+ CNREG2_0205_CRC_HALF,
+ CNREG2_0206_CRC_WORD,
+ CNREG2_0211_CRC_IV_REFLECT_WR,
+ CNREG2_0214_CRC_BYTE_REFLECT,
+ CNREG2_0215_CRC_HALF_REFLECT,
+ CNREG2_0216_CRC_WORD_REFLECT,
+
+ // also SNOW3G_LFSR, SHA3DAT0..=14
+ CNREG2_0240_HSH_DATW0,
+ CNREG2_0241_HSH_DATW1,
+ CNREG2_0242_HSH_DATW2,
+ CNREG2_0243_HSH_DATW3,
+ CNREG2_0244_HSH_DATW4,
+ CNREG2_0245_HSH_DATW5,
+ CNREG2_0246_HSH_DATW6,
+ CNREG2_0247_HSH_DATW7,
+ CNREG2_0248_HSH_DATW8,
+ CNREG2_0249_HSH_DATW9,
+ CNREG2_024A_HSH_DATW10,
+ CNREG2_024B_HSH_DATW11,
+ CNREG2_024C_HSH_DATW12,
+ CNREG2_024D_HSH_DATW13,
+ CNREG2_024E_HSH_DATW14,
+
+ CNREG2_024F_SHA3_DAT15_RD,
+
+ // also SNOW3G_RESULT (0x250), SNOW3G_SFM (0x251, 0x252, 0x253)
+ CNREG2_0250_HSH_IVW0,
+ CNREG2_0251_HSH_IVW1,
+ CNREG2_0252_HSH_IVW2,
+ CNREG2_0253_HSH_IVW3,
+ CNREG2_0254_HSH_IVW4,
+ CNREG2_0255_HSH_IVW5,
+ CNREG2_0256_HSH_IVW6,
+ CNREG2_0257_HSH_IVW7,
+
+ CNREG2_0258_GFM_MUL0,
+ CNREG2_0259_GFM_MUL1,
+ CNREG2_025A_GFM_RESINP0,
+ CNREG2_025B_GFM_RESINP1,
+ CNREG2_025C_GFM_XOR0,
+ CNREG2_025E_GFM_POLY,
+
+ CNREG2_02C0_SHA3_XORDAT0,
+ CNREG2_02C1_SHA3_XORDAT1,
+ CNREG2_02C2_SHA3_XORDAT2,
+ CNREG2_02C3_SHA3_XORDAT3,
+ CNREG2_02C4_SHA3_XORDAT4,
+ CNREG2_02C5_SHA3_XORDAT5,
+ CNREG2_02C6_SHA3_XORDAT6,
+ CNREG2_02C7_SHA3_XORDAT7,
+ CNREG2_02C8_SHA3_XORDAT8,
+ CNREG2_02C9_SHA3_XORDAT9,
+ CNREG2_02CA_SHA3_XORDAT10,
+ CNREG2_02CB_SHA3_XORDAT11,
+ CNREG2_02CC_SHA3_XORDAT12,
+ CNREG2_02CD_SHA3_XORDAT13,
+ CNREG2_02CE_SHA3_XORDAT14,
+ CNREG2_02CF_SHA3_XORDAT15,
+ CNREG2_02D0_SHA3_XORDAT16,
+ CNREG2_02D1_SHA3_XORDAT17,
+
+ CNREG2_0400_LLM_READ_ADDR0,
+ CNREG2_0401_LLM_WRITE_ADDR_INTERNAL0,
+ CNREG2_0402_LLM_DATA0,
+ CNREG2_0404_LLM_READ64_ADDR0,
+ CNREG2_0405_LLM_WRITE64_ADDR_INTERNAL0,
+ CNREG2_0408_LLM_READ_ADDR1,
+ CNREG2_0409_LLM_WRITE_ADDR_INTERNAL1,
+ CNREG2_040a_LLM_DATA1,
+ CNREG2_040c_LLM_READ64_ADDR1,
+ CNREG2_040d_LLM_WRITE64_ADDR_INTERNAL1,
+
+ CNREG2_1202_CRC_LEN,
+ CNREG2_1207_CRC_DWORD,
+ CNREG2_1208_CRC_VAR,
+ CNREG2_1217_CRC_DWORD_REFLECT,
+ CNREG2_1218_CRC_VAR_REFLECT,
+
+ CNREG2_3109_AES_ENC_CBC1,
+ CNREG2_310B_AES_ENC1,
+ CNREG2_310D_AES_DEC_CBC1,
+ CNREG2_310F_AES_DEC1,
+
+ CNREG2_3114_CAMELLIA_ROUND,
+
+ CNREG2_3119_SMS4_ENC_CBC1,
+ CNREG2_311B_SMS4_ENC1,
+ CNREG2_311D_SMS4_DEC_CBC1,
+ CNREG2_311F_SMS4_DEC1,
+
+ CNREG2_4052_SHA3_STARTOP,
+ CNREG2_4047_HSH_STARTMD5,
+ CNREG2_404D_SNOW3G_START,
+ CNREG2_4055_ZUC_START,
+ CNREG2_4056_ZUC_MORE,
+ CNREG2_405D_GFM_XORMUL1_REFLECT,
+ CNREG2_404E_SNOW3G_MORE,
+ CNREG2_404F_HSH_STARTSHA256,
+ CNREG2_4057_HSH_STARTSHA,
+ CNREG2_4088_3DES_ENC_CBC,
+ CNREG2_4089_KAS_ENC_CBC,
+ CNREG2_408A_3DES_ENC,
+ CNREG2_408B_KAS_ENC,
+ CNREG2_408C_3DES_DEC_CBC,
+ CNREG2_408E_3DES_DEC,
+
+ CNREG2_4200_CRC_POLYNOMIAL_WR,
+ CNREG2_4210_CRC_POLYNOMIAL_REFLECT,
+
+ CNREG2_424F_HSH_STARTSHA512,
+ CNREG2_425D_GFM_XORMUL1,
+
+ };
+
+ registers.insert(registers.end(), std::begin(cavium_registers), std::end(cavium_registers));
+ }
+
+ return registers;
}
virtual vector<uint32_t> GetAllFlags() override
@@ -1336,7 +2030,7 @@ public:
virtual vector<uint32_t> GetSystemRegisters() override
{
- return vector< uint32_t> {
+ vector<uint32_t> registers = vector<uint32_t>{
// Coprocessor 0 register 0
REG_INDEX,
REG_MVP_CONTROL,
@@ -1437,7 +2131,207 @@ public:
REG_ERROR_EPC,
// Coprocessor 0 register 31
REG_DESAVE,
+
};
+
+ if ((m_decomposeFlags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ uint32_t cavium_registers[] =
+ {
+ CNREG_MPL0,
+ CNREG_MPL1,
+ CNREG_MPL2,
+ CNREG_P0,
+ CNREG_P1,
+ CNREG_P2,
+
+ CNREG0_CVM_COUNT,
+ CNREG0_CVM_CTL,
+ CNREG0_POWTHROTTLE,
+ CNREG0_CVM_MEM_CTL,
+ CNREG0_MULTICORE_DBG,
+
+ CNREG2_0040_HSH_DAT0,
+ CNREG2_0041_HSH_DAT1,
+ CNREG2_0042_HSH_DAT2,
+ CNREG2_0043_HSH_DAT3,
+ CNREG2_0044_HSH_DAT4,
+ CNREG2_0045_HSH_DAT5,
+ CNREG2_0046_HSH_DAT6,
+
+ CNREG2_0048_HSH_IV0,
+ CNREG2_0049_HSH_IV1,
+ CNREG2_004A_HSH_IV2,
+ CNREG2_004B_HSH_IV3,
+
+ CNREG2_0050_SHA3_DAT24,
+ CNREG2_0051_SHA3_DAT15_RD,
+
+ CNREG2_0058_GFM_MUL_REFLECT0,
+ CNREG2_0059_GFM_MUL_REFLECT1,
+ CNREG2_005A_GFM_RESINP_REFLECT0,
+ CNREG2_005B_GFM_RESINP_REFLECT1,
+ CNREG2_005C_GFM_XOR0_REFLECT,
+
+ // also KASUMI
+ CNREG2_0080_3DES_KEY0,
+ CNREG2_0081_3DES_KEY1,
+ CNREG2_0082_3DES_KEY2,
+
+ CNREG2_0084_3DES_IV,
+ CNREG2_0088_3DES_RESULT_RD,
+ CNREG2_0098_3DES_RESULT_WR,
+
+ // also SMS4 RESINP
+ CNREG2_0100_AES_RESULT0,
+ CNREG2_0101_AES_RESULT1,
+
+ // also SMS4 IV
+ CNREG2_0102_AES_IV0,
+ CNREG2_0103_AES_IV1,
+
+ // also SMS4 KEY
+ CNREG2_0104_AES_KEY0,
+ CNREG2_0105_AES_KEY1,
+ CNREG2_0106_AES_KEY2,
+ CNREG2_0107_AES_KEY3,
+
+ // also SMS4_x
+ CNREG2_0108_AES_ENC_CBC0,
+ CNREG2_010A_AES_ENC0,
+ CNREG2_010C_AES_DEC_CBC0,
+ CNREG2_010E_AES_DEC0,
+
+ CNREG2_0110_AES_KEYLENGTH,
+ CNREG2_0111_AES_DAT0,
+
+ CNREG2_0115_CAMELLIA_FL,
+ CNREG2_0116_CAMELLIA_FLINV,
+
+ CNREG2_0200_CRC_POLYNOMIAL,
+ CNREG2_0201_CRC_IV,
+ CNREG2_0202_CRC_LEN,
+ CNREG2_0203_CRC_IV_REFLECT_RD,
+ CNREG2_0204_CRC_BYTE,
+ CNREG2_0205_CRC_HALF,
+ CNREG2_0206_CRC_WORD,
+ CNREG2_0211_CRC_IV_REFLECT_WR,
+ CNREG2_0214_CRC_BYTE_REFLECT,
+ CNREG2_0215_CRC_HALF_REFLECT,
+ CNREG2_0216_CRC_WORD_REFLECT,
+
+ // also SNOW3G_LFSR, SHA3DAT0..=14
+ CNREG2_0240_HSH_DATW0,
+ CNREG2_0241_HSH_DATW1,
+ CNREG2_0242_HSH_DATW2,
+ CNREG2_0243_HSH_DATW3,
+ CNREG2_0244_HSH_DATW4,
+ CNREG2_0245_HSH_DATW5,
+ CNREG2_0246_HSH_DATW6,
+ CNREG2_0247_HSH_DATW7,
+ CNREG2_0248_HSH_DATW8,
+ CNREG2_0249_HSH_DATW9,
+ CNREG2_024A_HSH_DATW10,
+ CNREG2_024B_HSH_DATW11,
+ CNREG2_024C_HSH_DATW12,
+ CNREG2_024D_HSH_DATW13,
+ CNREG2_024E_HSH_DATW14,
+
+ CNREG2_024F_SHA3_DAT15_RD,
+
+ // also SNOW3G_RESULT (0x250), SNOW3G_SFM (0x251, 0x252, 0x253)
+ CNREG2_0250_HSH_IVW0,
+ CNREG2_0251_HSH_IVW1,
+ CNREG2_0252_HSH_IVW2,
+ CNREG2_0253_HSH_IVW3,
+ CNREG2_0254_HSH_IVW4,
+ CNREG2_0255_HSH_IVW5,
+ CNREG2_0256_HSH_IVW6,
+ CNREG2_0257_HSH_IVW7,
+
+ CNREG2_0258_GFM_MUL0,
+ CNREG2_0259_GFM_MUL1,
+ CNREG2_025A_GFM_RESINP0,
+ CNREG2_025B_GFM_RESINP1,
+ CNREG2_025C_GFM_XOR0,
+ CNREG2_025E_GFM_POLY,
+
+ CNREG2_02C0_SHA3_XORDAT0,
+ CNREG2_02C1_SHA3_XORDAT1,
+ CNREG2_02C2_SHA3_XORDAT2,
+ CNREG2_02C3_SHA3_XORDAT3,
+ CNREG2_02C4_SHA3_XORDAT4,
+ CNREG2_02C5_SHA3_XORDAT5,
+ CNREG2_02C6_SHA3_XORDAT6,
+ CNREG2_02C7_SHA3_XORDAT7,
+ CNREG2_02C8_SHA3_XORDAT8,
+ CNREG2_02C9_SHA3_XORDAT9,
+ CNREG2_02CA_SHA3_XORDAT10,
+ CNREG2_02CB_SHA3_XORDAT11,
+ CNREG2_02CC_SHA3_XORDAT12,
+ CNREG2_02CD_SHA3_XORDAT13,
+ CNREG2_02CE_SHA3_XORDAT14,
+ CNREG2_02CF_SHA3_XORDAT15,
+ CNREG2_02D0_SHA3_XORDAT16,
+ CNREG2_02D1_SHA3_XORDAT17,
+
+ CNREG2_0400_LLM_READ_ADDR0,
+ CNREG2_0401_LLM_WRITE_ADDR_INTERNAL0,
+ CNREG2_0402_LLM_DATA0,
+ CNREG2_0404_LLM_READ64_ADDR0,
+ CNREG2_0405_LLM_WRITE64_ADDR_INTERNAL0,
+ CNREG2_0408_LLM_READ_ADDR1,
+ CNREG2_0409_LLM_WRITE_ADDR_INTERNAL1,
+ CNREG2_040a_LLM_DATA1,
+ CNREG2_040c_LLM_READ64_ADDR1,
+ CNREG2_040d_LLM_WRITE64_ADDR_INTERNAL1,
+
+ CNREG2_1202_CRC_LEN,
+ CNREG2_1207_CRC_DWORD,
+ CNREG2_1208_CRC_VAR,
+ CNREG2_1217_CRC_DWORD_REFLECT,
+ CNREG2_1218_CRC_VAR_REFLECT,
+
+ CNREG2_3109_AES_ENC_CBC1,
+ CNREG2_310B_AES_ENC1,
+ CNREG2_310D_AES_DEC_CBC1,
+ CNREG2_310F_AES_DEC1,
+
+ CNREG2_3114_CAMELLIA_ROUND,
+
+ CNREG2_3119_SMS4_ENC_CBC1,
+ CNREG2_311B_SMS4_ENC1,
+ CNREG2_311D_SMS4_DEC_CBC1,
+ CNREG2_311F_SMS4_DEC1,
+
+ CNREG2_4052_SHA3_STARTOP,
+ CNREG2_4047_HSH_STARTMD5,
+ CNREG2_404D_SNOW3G_START,
+ CNREG2_4055_ZUC_START,
+ CNREG2_4056_ZUC_MORE,
+ CNREG2_405D_GFM_XORMUL1_REFLECT,
+ CNREG2_404E_SNOW3G_MORE,
+ CNREG2_404F_HSH_STARTSHA256,
+ CNREG2_4057_HSH_STARTSHA,
+ CNREG2_4088_3DES_ENC_CBC,
+ CNREG2_4089_KAS_ENC_CBC,
+ CNREG2_408A_3DES_ENC,
+ CNREG2_408B_KAS_ENC,
+ CNREG2_408C_3DES_DEC_CBC,
+ CNREG2_408E_3DES_DEC,
+
+ CNREG2_4200_CRC_POLYNOMIAL_WR,
+ CNREG2_4210_CRC_POLYNOMIAL_REFLECT,
+
+ CNREG2_424F_HSH_STARTSHA512,
+ CNREG2_425D_GFM_XORMUL1,
+
+ };
+
+ registers.insert(registers.end(), std::begin(cavium_registers), std::end(cavium_registers));
+ }
+
+ return registers;
}
};
@@ -2035,7 +2929,7 @@ public:
uint32_t inst2 = *(uint32_t*)(cur->relocationDataCache);
Instruction instruction;
memset(&instruction, 0, sizeof(instruction));
- if (mips_decompose(&inst2, sizeof(uint32_t), &instruction, MIPS_32, cur->address, arch->GetEndianness(), 1))
+ if (mips_decompose(&inst2, sizeof(uint32_t), &instruction, MIPS_32, cur->address, arch->GetEndianness(), DECOMPOSE_FLAGS_PSEUDO_OP))
break;
int32_t immediate = swap(inst2) & 0xffff;
@@ -2226,6 +3120,36 @@ static void InitMipsSettings()
})");
}
+
+static Ref<Platform> ElfFlagsRecognize(BinaryView* view, Metadata* metadata)
+{
+ Ref<Metadata> abiMetadata = metadata->Get("EI_OSABI");
+ if (!abiMetadata || !abiMetadata->IsUnsignedInteger())
+ return nullptr;
+
+ uint64_t abi = abiMetadata->GetUnsignedInteger();
+ if (abi != 0 && abi != 3)
+ return nullptr;
+
+ Ref<Metadata> flagsMetadata = metadata->Get("e_flags");
+ if (!flagsMetadata || !flagsMetadata->IsUnsignedInteger())
+ return nullptr;
+
+ uint64_t flagsValue = flagsMetadata->GetUnsignedInteger();
+ uint8_t machineVariant = (flagsValue >> 16) & 0xff;
+
+ switch (machineVariant)
+ {
+ case 0x8b: // EF_MIPS_MACH_OCTEON
+ case 0x8d: // EF_MIPS_MACH_OCTEON2
+ case 0x8e: // EF_MIPS_MACH_OCTEON3
+ LogInfo("ELF flags 0x%08" PRIx64 " machine variant 0x%02x: using cavium architecture", flagsValue, machineVariant);
+ return Platform::GetByName("linux-cnmips64");
+ default:
+ return nullptr;
+ }
+}
+
extern "C"
{
BN_DECLARE_CORE_ABI_VERSION
@@ -2245,15 +3169,18 @@ extern "C"
Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32);
Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32);
Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64);
+ Architecture* cnmips64eb = new MipsArchitecture("cavium-mips64", BigEndian, 64, DECOMPOSE_FLAGS_CAVIUM);
Architecture::Register(mipsel);
Architecture::Register(mipseb);
Architecture::Register(mips64eb);
+ Architecture::Register(cnmips64eb);
/* calling conventions */
MipsO32CallingConvention* o32LE = new MipsO32CallingConvention(mipsel);
MipsO32CallingConvention* o32BE = new MipsO32CallingConvention(mipseb);
MipsN64CallingConvention* n64BE = new MipsN64CallingConvention(mips64eb);
+ MipsN64CallingConvention* n64BEc = new MipsN64CallingConvention(cnmips64eb);
mipsel->RegisterCallingConvention(o32LE);
mipseb->RegisterCallingConvention(o32BE);
@@ -2261,6 +3188,8 @@ extern "C"
mipseb->SetDefaultCallingConvention(o32BE);
mips64eb->RegisterCallingConvention(n64BE);
mips64eb->SetDefaultCallingConvention(n64BE);
+ cnmips64eb->RegisterCallingConvention(n64BEc);
+ cnmips64eb->SetDefaultCallingConvention(n64BEc);
MipsLinuxSyscallCallingConvention* linuxSyscallLE = new MipsLinuxSyscallCallingConvention(mipsel);
MipsLinuxSyscallCallingConvention* linuxSyscallBE = new MipsLinuxSyscallCallingConvention(mipseb);
@@ -2270,6 +3199,7 @@ extern "C"
mipsel->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipsel));
mipseb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipseb));
mips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64eb));
+ cnmips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(cnmips64eb));
/* function recognizers */
mipsel->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer());
@@ -2278,6 +3208,7 @@ extern "C"
mipsel->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
mipseb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
mips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
+ cnmips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler());
// Register the architectures with the binary format parsers so that they know when to use
// these architectures for disassembling an executable file
@@ -2292,6 +3223,11 @@ extern "C"
BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS64, BigEndian, mips64eb);
BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, LittleEndian, mipsel);
BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, BigEndian, mipseb);
+
+ Ref<BinaryViewType> elf = BinaryViewType::GetByName("ELF");
+ if (elf)
+ elf->RegisterPlatformRecognizer(ARCH_ID_MIPS64, BigEndian, ElfFlagsRecognize);
+
BinaryViewType::RegisterArchitecture("PE", 0x166, LittleEndian, mipsel);
return true;
}
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:
diff --git a/arch/mips/il.h b/arch/mips/il.h
index 5c03f82b..abb3d939 100644
--- a/arch/mips/il.h
+++ b/arch/mips/il.h
@@ -7,14 +7,69 @@
enum MipsIntrinsic : uint32_t
{
MIPS_INTRIN_WSBH,
+ MIPS_INTRIN_DSBH,
+ MIPS_INTRIN_DSHD,
MIPS_INTRIN_MFC0,
+ MIPS_INTRIN_MFC2,
MIPS_INTRIN_MFC_UNIMPLEMENTED,
MIPS_INTRIN_MTC0,
+ MIPS_INTRIN_MTC2,
MIPS_INTRIN_MTC_UNIMPLEMENTED,
MIPS_INTRIN_DMFC0,
+ MIPS_INTRIN_DMFC2,
MIPS_INTRIN_DMFC_UNIMPLEMENTED,
MIPS_INTRIN_DMTC0,
+ MIPS_INTRIN_DMTC2,
MIPS_INTRIN_DMTC_UNIMPLEMENTED,
+ MIPS_INTRIN_SYNC,
+ MIPS_INTRIN_DI,
+ MIPS_INTRIN_EHB,
+ MIPS_INTRIN_EI,
+ MIPS_INTRIN_WAIT,
+ MIPS_INTRIN_HWR0,
+ MIPS_INTRIN_HWR1,
+ MIPS_INTRIN_HWR2,
+ MIPS_INTRIN_HWR3,
+ MIPS_INTRIN_HWR29,
+ MIPS_INTRIN_HWR_UNKNOWN,
+ MIPS_INTRIN_LLBIT_SET,
+ MIPS_INTRIN_LLBIT_CHECK,
+ MIPS_INTRIN_PREFETCH,
+ MIPS_INTRIN_CACHE,
+
+ // there's no clean way to lift LWL/LWR, SWL/SWR, etc when not
+ // a pair of adjacent instructions, since the number and position
+ // of the bytes written to/read from depends on the alignment of
+ // the address
+ //
+ // consider writing a register to an unaligned address with
+ // SWL rX, 0(rY)/SWR rX, 3(rY); this could write either 1, 2, 3,
+ // or 4 bytes in each instruction, and then later in the function
+ // to load the value of rX back, the number of bytes read by
+ // LWL rX, 0(rY)/LWR rX, 3(rY) is again variable...the number of
+ // bytes, shifts, and bitmasks all depend on (rY & 3)
+ //
+ // lifting these instructions faithfully, even when the analysis
+ // engine is able to follow this, would be a total mess to read,
+ // so it might as well be an intrinsic-like black box anyways, to
+ // help data cross-references work
+ MIPS_INTRIN_GET_LEFT_PART32,
+ MIPS_INTRIN_GET_RIGHT_PART32,
+ MIPS_INTRIN_SET_LEFT_PART32,
+ MIPS_INTRIN_SET_RIGHT_PART32,
+ MIPS_INTRIN_GET_LEFT_PART64,
+ MIPS_INTRIN_GET_RIGHT_PART64,
+ MIPS_INTRIN_SET_LEFT_PART64,
+ MIPS_INTRIN_SET_RIGHT_PART64,
+
+ CNMIPS_INTRIN_SYNCIOBDMA,
+ CNMIPS_INTRIN_SYNCS,
+ CNMIPS_INTRIN_SYNCW,
+ CNMIPS_INTRIN_SYNCWS,
+ CNMIPS_INTRIN_HWR30,
+ CNMIPS_INTRIN_HWR31,
+ CNMIPS_INTRIN_POP,
+ CNMIPS_INTRIN_DPOP,
MIPS_INTRIN_INVALID=0xFFFFFFFF,
};
@@ -23,6 +78,7 @@ bool GetLowLevelILForInstruction(
uint64_t addr,
BinaryNinja::LowLevelILFunction& il,
mips::Instruction& instr,
- size_t addrSize);
+ size_t addrSize,
+ uint32_t decomposeFlags);
BinaryNinja::ExprId GetConditionForInstruction(BinaryNinja::LowLevelILFunction& il, mips::Instruction& instr, size_t registerSize);
diff --git a/arch/mips/mips/mips.c b/arch/mips/mips/mips.c
index 42bb0311..a108c8f3 100644
--- a/arch/mips/mips/mips.c
+++ b/arch/mips/mips/mips.c
@@ -54,153 +54,171 @@ using namespace mips;
} while (0);
+static Operation cavium_mips_base_table[8][8] = {
+ {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
+ {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
+ {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP1X, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
+ {MIPS_DADDI, MIPS_DADDIU, MIPS_LDL, MIPS_LDR, MIPS_INVALID, MIPS_JALX, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
+ {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR, MIPS_CACHE},
+ {MIPS_LL, MIPS_LWC1, CNMIPS_BBIT0, MIPS_PREF, MIPS_LLD, MIPS_LDC1, CNMIPS_BBIT032, MIPS_LD},
+ {MIPS_SC, MIPS_SWC1, CNMIPS_BBIT1, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, CNMIPS_BBIT132, MIPS_SD}
+};
+
//Fields are: [Version][opcode_high][opcode_low]
static Operation mips_base_table[6][8][8] = {
{ //MIPS version 1
- {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
- {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
- {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP3},
- {MIPS_LLO, MIPS_LHI, MIPS_TRAP},
- {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR},
- {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_INVALID, MIPS_INVALID, MIPS_SWR},
- {MIPS_INVALID, MIPS_LWC1, MIPS_LWC2, MIPS_LWC3},
- {MIPS_INVALID, MIPS_SWC1, MIPS_SWC2, MIPS_SWC3}
+ {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
+ {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
+ {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP3, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LLO, MIPS_LHI, MIPS_TRAP, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_INVALID},
+ {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_INVALID, MIPS_INVALID, MIPS_SWR, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_LWC1, MIPS_LWC2, MIPS_LWC3, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_SWC1, MIPS_SWC2, MIPS_SWC3, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID}
},{ //MIPS version 2
- {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
- {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
- {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP3, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
- {MIPS_INVALID},
- {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR},
- {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_INVALID, MIPS_INVALID, MIPS_SWR},
- {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_LWC3, MIPS_INVALID, MIPS_LDC1, MIPS_LDC2, MIPS_LDC3},
- {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_SWC3, MIPS_INVALID, MIPS_SDC1, MIPS_SDC2, MIPS_SDC3}
+ {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
+ {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
+ {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP3, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_INVALID},
+ {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_INVALID, MIPS_INVALID, MIPS_SWR, MIPS_INVALID},
+ {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_LWC3, MIPS_INVALID, MIPS_LDC1, MIPS_LDC2, MIPS_LDC3},
+ {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_SWC3, MIPS_INVALID, MIPS_SDC1, MIPS_SDC2, MIPS_SDC3}
},{ //MIPS version 3
- {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
- {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
- {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_INVALID, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
- {MIPS_DADDI, MIPS_DADDIU, MIPS_LDL, MIPS_LDR},
- {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
- {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR},
- {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_INVALID, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
- {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
+ {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
+ {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
+ {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_INVALID, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
+ {MIPS_DADDI, MIPS_DADDIU, MIPS_LDL, MIPS_LDR, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
+ {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR, MIPS_INVALID},
+ {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_INVALID, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
+ {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
},{ //MIPS version 4
- {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
- {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
- {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP1X, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
- {MIPS_DADDI, MIPS_DADDIU, MIPS_LDL, MIPS_LDR},
- {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
- {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR},
- {MIPS_INVALID, MIPS_LWC1, MIPS_LWC2, MIPS_PREF, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
- {MIPS_INVALID, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
+ {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
+ {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
+ {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP1X, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
+ {MIPS_DADDI, MIPS_DADDIU, MIPS_LDL, MIPS_LDR, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
+ {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_LWC1, MIPS_LWC2, MIPS_PREF, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
+ {MIPS_INVALID, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
},{ //MIPS version 5 (MIPS32)
- {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
- {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
- {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP1X, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
- {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_JALX, MIPS_INVALID, MIPS_INVALID},
- {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
- {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR, MIPS_CACHE},
- {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_PREF, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
- {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
+ {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
+ {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
+ {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP1X, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_JALX, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
+ {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR, MIPS_CACHE},
+ {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_PREF, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
+ {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
},{ //MIPS version 6 (MIPS64)
- {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
- {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
- {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP1X, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
- {MIPS_DADDI, MIPS_DADDIU, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_JALX, MIPS_INVALID, MIPS_INVALID},
- {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
- {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR, MIPS_CACHE},
- {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_PREF, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
- {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
+ {MIPS_INVALID, MIPS_INVALID, MIPS_J, MIPS_JAL, MIPS_BEQ, MIPS_BNE, MIPS_BLEZ, MIPS_BGTZ},
+ {MIPS_ADDI, MIPS_ADDIU, MIPS_SLTI, MIPS_SLTIU, MIPS_ANDI, MIPS_ORI, MIPS_XORI, MIPS_LUI},
+ {MIPS_COP0, MIPS_COP1, MIPS_COP2, MIPS_COP1X, MIPS_BEQL, MIPS_BNEL, MIPS_BLEZL, MIPS_BGTZL},
+ {MIPS_DADDI, MIPS_DADDIU, MIPS_LDL, MIPS_LDR, MIPS_INVALID, MIPS_JALX, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_LB, MIPS_LH, MIPS_LWL, MIPS_LW, MIPS_LBU, MIPS_LHU, MIPS_LWR, MIPS_LWU},
+ {MIPS_SB, MIPS_SH, MIPS_SWL, MIPS_SW, MIPS_SDL, MIPS_SDR, MIPS_SWR, MIPS_CACHE},
+ {MIPS_LL, MIPS_LWC1, MIPS_LWC2, MIPS_PREF, MIPS_LLD, MIPS_LDC1, MIPS_LDC2, MIPS_LD},
+ {MIPS_SC, MIPS_SWC1, MIPS_SWC2, MIPS_INVALID, MIPS_SCD, MIPS_SDC1, MIPS_SDC2, MIPS_SD}
}
};
//Fields are: [Version][function_high][function_low]
static Operation mips_special_table[6][8][8] = {
{ //MIPS version 1
- {MIPS_SLL, MIPS_INVALID, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
- {MIPS_JR, MIPS_JALR, MIPS_INVALID, MIPS_INVALID, MIPS_SYSCALL, MIPS_BREAK},
- {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO},
- {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU},
- {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
- {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU}
+ {MIPS_SLL, MIPS_INVALID, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
+ {MIPS_JR, MIPS_JALR, MIPS_INVALID, MIPS_INVALID, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID}
},{ //MIPS version 2
- {MIPS_SLL, MIPS_INVALID, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
- {MIPS_JR, MIPS_JALR, MIPS_INVALID, MIPS_INVALID, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
- {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO},
- {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU},
- {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
- {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU},
- {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE}
+ {MIPS_SLL, MIPS_INVALID, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
+ {MIPS_JR, MIPS_JALR, MIPS_INVALID, MIPS_INVALID, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
+ {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID}
},{ //MIPS version 3
- {MIPS_SLL, MIPS_INVALID, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
- {MIPS_JR, MIPS_JALR, MIPS_INVALID, MIPS_INVALID, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
- {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_DSLLV, MIPS_INVALID, MIPS_DSLV, MIPS_DSRAV},
- {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_DMULT, MIPS_DMULTU, MIPS_DDIV, MIPS_DDIVU},
- {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
- {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
- {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE},
- {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
+ {MIPS_SLL, MIPS_INVALID, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
+ {MIPS_JR, MIPS_JALR, MIPS_INVALID, MIPS_INVALID, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
+ {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_DSLLV, MIPS_INVALID, MIPS_DSRLV, MIPS_DSRAV},
+ {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_DMULT, MIPS_DMULTU, MIPS_DDIV, MIPS_DDIVU},
+ {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
+ {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE, MIPS_INVALID},
+ {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
},{ //MIPS version 4
- {MIPS_SLL, MIPS_MOVCI, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
- {MIPS_JR, MIPS_JALR, MIPS_MOVZ, MIPS_MOVN, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
- {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_DSLLV, MIPS_INVALID, MIPS_DSLV, MIPS_DSRAV},
- {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_DMULT, MIPS_DMULTU, MIPS_DDIV, MIPS_DDIVU},
- {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
- {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
- {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE},
- {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
+ {MIPS_SLL, MIPS_MOVCI, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
+ {MIPS_JR, MIPS_JALR, MIPS_MOVZ, MIPS_MOVN, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
+ {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_DSLLV, MIPS_INVALID, MIPS_DSRLV, MIPS_DSRAV},
+ {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_DMULT, MIPS_DMULTU, MIPS_DDIV, MIPS_DDIVU},
+ {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
+ {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE, MIPS_INVALID},
+ {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
},{ //MIPS version 5
- {MIPS_SLL, MIPS_MOVCI, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
- {MIPS_JR, MIPS_JALR, MIPS_MOVZ, MIPS_MOVN, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
- {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO},
- {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU},
- {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
- {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
- {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE},
- {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
+ {MIPS_SLL, MIPS_MOVCI, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
+ {MIPS_JR, MIPS_JALR, MIPS_MOVZ, MIPS_MOVN, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
+ {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_DSLLV, MIPS_INVALID, MIPS_DSRLV, MIPS_DSRAV},
+ {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_DMULT, MIPS_DMULTU, MIPS_DDIV, MIPS_DDIVU},
+ {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
+ {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE, MIPS_INVALID},
+ {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
},{ //MIPS version 6
- {MIPS_SLL, MIPS_MOVCI, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
- {MIPS_JR, MIPS_JALR, MIPS_MOVZ, MIPS_MOVN, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
- {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO},
- {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU},
- {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
- {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
- {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE},
- {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
+ {MIPS_SLL, MIPS_MOVCI, MIPS_SRL, MIPS_SRA, MIPS_SLLV, MIPS_INVALID, MIPS_SRLV, MIPS_SRAV},
+ {MIPS_JR, MIPS_JALR, MIPS_MOVZ, MIPS_MOVN, MIPS_SYSCALL, MIPS_BREAK, MIPS_INVALID, MIPS_SYNC},
+ {MIPS_MFHI, MIPS_MTHI, MIPS_MFLO, MIPS_MTLO, MIPS_DSLLV, MIPS_INVALID, MIPS_DSRLV, MIPS_DSRAV},
+ {MIPS_MULT, MIPS_MULTU, MIPS_DIV, MIPS_DIVU, MIPS_DMULT, MIPS_DMULTU, MIPS_DDIV, MIPS_DDIVU},
+ {MIPS_ADD, MIPS_ADDU, MIPS_SUB, MIPS_SUBU, MIPS_AND, MIPS_OR, MIPS_XOR, MIPS_NOR},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_SLT, MIPS_SLTU, MIPS_DADD, MIPS_DADDU, MIPS_DSUB, MIPS_DSUBU},
+ {MIPS_TGE, MIPS_TGEU, MIPS_TLT, MIPS_TLTU, MIPS_TEQ, MIPS_INVALID, MIPS_TNE, MIPS_INVALID},
+ {MIPS_DSLL, MIPS_INVALID, MIPS_DSRL, MIPS_DSRA, MIPS_DSLL32, MIPS_INVALID, MIPS_DSRL32, MIPS_DSRA32}
}
};
static Operation mips_regimm_table[6][4][8] = {
{ //MIPS version 1
- {MIPS_BLTZ, MIPS_BGEZ},
- {MIPS_INVALID},
- {MIPS_BLTZAL, MIPS_BGEZAL},
+ {MIPS_BLTZ, MIPS_BGEZ, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
},{ //MIPS version 2
- {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL},
- {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI},
- {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL},
+ {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI, MIPS_INVALID},
+ {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
},{ //MIPS version 3
- {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL},
- {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI},
- {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL},
+ {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI, MIPS_INVALID},
+ {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
},{ //MIPS version 4
- {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL},
- {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI},
- {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL},
+ {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI, MIPS_INVALID},
+ {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
},{ //MIPS version 5
- {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL},
- {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI},
- {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL},
+ {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI, MIPS_INVALID},
+ {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_SYNCI}
},{ //MIPS version 6
- {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL},
- {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI},
- {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL},
+ {MIPS_BLTZ, MIPS_BGEZ, MIPS_BLTZL, MIPS_BGEZL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_TGEI, MIPS_TGEIU, MIPS_TLTI, MIPS_TLTIU, MIPS_TEQI, MIPS_INVALID, MIPS_TNEI, MIPS_INVALID},
+ {MIPS_BLTZAL, MIPS_BGEZAL, MIPS_BLTZALL, MIPS_BGEZALL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_SYNCI}
}
};
-static Operation mips_special2_table[8][8] = {
- {MIPS_MADD, MIPS_MADDU, MIPS_MUL, MIPS_INVALID, MIPS_MSUB, MIPS_MSUBU},
+static Operation mips32_special2_table[8][8] = {
+ {MIPS_MADD, MIPS_MADDU, MIPS_MUL, MIPS_INVALID, MIPS_MSUB, MIPS_MSUBU, MIPS_INVALID, MIPS_INVALID},
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
@@ -210,7 +228,29 @@ static Operation mips_special2_table[8][8] = {
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_SDBBP}
};
-static Operation mips_special3_table[8][8] = {
+static Operation mips64_special2_table[8][8] = {
+ {MIPS_MADD, MIPS_MADDU, MIPS_MUL, MIPS_INVALID, MIPS_MSUB, MIPS_MSUBU, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_CLZ, MIPS_CLO, MIPS_INVALID, MIPS_INVALID, MIPS_DCLZ, MIPS_DCLO, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_SDBBP}
+};
+
+static Operation cavium_mips64_special2_table[8][8] = {
+ {MIPS_MADD, MIPS_MADDU, MIPS_MUL, CNMIPS_DMUL, MIPS_MSUB, MIPS_MSUBU, MIPS_INVALID, MIPS_INVALID},
+ {CNMIPS_MTM0, CNMIPS_MTP0, CNMIPS_MTP1, CNMIPS_MTP2, CNMIPS_MTM1, CNMIPS_MTM2, MIPS_INVALID, CNMIPS_VMULU},
+ {CNMIPS_VMM0, CNMIPS_V3MULU, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {CNMIPS_SAA, CNMIPS_SAAD, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, CNMIPS_CVM},
+ {MIPS_CLZ, MIPS_CLO, MIPS_INVALID, MIPS_INVALID, MIPS_DCLZ, MIPS_DCLO, MIPS_INVALID, MIPS_INVALID},
+ {CNMIPS_BADDU, MIPS_INVALID, CNMIPS_SEQ, CNMIPS_SNE, CNMIPS_POP, CNMIPS_DPOP, CNMIPS_SEQI, CNMIPS_SNEI},
+ {MIPS_INVALID, MIPS_INVALID, CNMIPS_CINS, CNMIPS_CINS32, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, CNMIPS_EXTS, CNMIPS_EXTS32, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_SDBBP}
+};
+
+static Operation mips32_special3_table[8][8] = {
{MIPS_EXT, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INS, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
{MIPS_INVALID, MIPS_INVALID, MIPS_LX, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
@@ -221,6 +261,17 @@ static Operation mips_special3_table[8][8] = {
{MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_RDHWR, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
};
+static Operation mips64_special3_table[8][8] = {
+ {MIPS_EXT, MIPS_DEXTM, MIPS_DEXTU, MIPS_DEXT, MIPS_INS, MIPS_DINSM, MIPS_DINSU, MIPS_DINS},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_LX, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_BSHFL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_DBSHFL, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+ {MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_RDHWR, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID, MIPS_INVALID},
+};
+
static Operation mips_v5_cop1_S_table[8][8] = {
{MIPS_ADD_S, MIPS_SUB_S, MIPS_MUL_S, MIPS_DIV_S, MIPS_SQRT_S, MIPS_ABS_S, MIPS_MOV_S, MIPS_NEG_S},
{MIPS_ROUND_L_S, MIPS_TRUNC_L_S, MIPS_CEIL_L_S, MIPS_FLOOR_L_S, MIPS_ROUND_W_S, MIPS_TRUNC_W_S, MIPS_CEIL_W_S, MIPS_FLOOR_W_S},
@@ -326,6 +377,7 @@ static const char* const OperationStrings[] = {
"bltzl",
"bne",
"bnel",
+ "bnez",
"bnz.b",
"bnz.d",
"bnz.h",
@@ -446,10 +498,19 @@ static const char* const OperationStrings[] = {
"daddi",
"daddiu",
"daddu",
+ "dbshfl",
+ "dclo",
+ "dclz",
"ddiv",
"ddivu",
"deret",
+ "dext",
+ "dextm",
+ "dextu",
"di",
+ "dins",
+ "dinsm",
+ "dinsu",
"div.d",
"div.ps",
"div.s",
@@ -464,15 +525,20 @@ static const char* const OperationStrings[] = {
"dmtc1",
"dmtc2",
"dret",
+ "drotr",
+ "drotr32",
+ "drotrv",
+ "dsbh",
+ "dshd",
"dsll",
"dsll32",
"dsllv",
- "dslv",
"dsra",
"dsra32",
"dsrav",
"dsrl",
"dsrl32",
+ "dsrlv",
"dsub",
"dsubu",
"ehb",
@@ -699,6 +765,44 @@ static const char* const OperationStrings[] = {
"wsbh",
"xor",
"xori",
+
+ // cavium instructions
+ "baddu",
+ "bbit0",
+ "bbit032",
+ "bbit1",
+ "bbit132",
+ "cins",
+ "cins32",
+ "cvm",
+ "dmul",
+ "dpop",
+ "exts",
+ "exts32",
+ "mtm0",
+ "mtm1",
+ "mtm2",
+ "mtp0",
+ "mtp1",
+ "mtp2",
+ "pop",
+ "rdhwr",
+ "saa",
+ "saad",
+ "seq",
+ "seqi",
+ "sne",
+ "snei",
+ "synciobdma",
+ "syncs",
+ "syncw",
+ "syncws",
+ "v3mulu",
+ "vmm0",
+ "vmulu",
+ "zcb",
+ "zcbt",
+
};
static const char * const RegisterStrings[] = {
@@ -870,6 +974,183 @@ static const char * const RegisterStrings[] = {
"cop0_DataHi",
"cop0_ErrorEPC",
"cop0_DESAVE",
+
+ // cavium-specific multiplication registers
+ "cvm_mpl0",
+ "cvm_mpl1",
+ "cvm_mpl2",
+ "cvm_p0",
+ "cvm_p1",
+ "cvm_p2",
+
+ // cavium-specific implementation defined
+ "cop0_CvmCount",
+ "cop0_CvmCtl",
+ "cop0_PowerThrottle",
+ "cop0_CvmMemCtl",
+ "cop0_MulticoreDbg",
+
+ "CVMX_HSH_DAT0",
+ "CVMX_HSH_DAT1",
+ "CVMX_HSH_DAT2",
+ "CVMX_HSH_DAT3",
+ "CVMX_HSH_DAT4",
+ "CVMX_HSH_DAT5",
+ "CVMX_HSH_DAT6",
+ "CVMX_HSH_IV0",
+ "CVMX_HSH_IV1",
+ "CVMX_HSH_IV2",
+ "CVMX_HSH_IV3",
+ "CVMX_SHA3_DAT24",
+ "CVMX_SHA3_DAT15_RD",
+ "CVMX_GFM_MUL_REFLECT0",
+ "CVMX_GFM_MUL_REFLECT1",
+ "CVMX_GFM_RESINP_REFLECT0",
+ "CVMX_GFM_RESINP_REFLECT1",
+ "CVMX_GFM_XOR0_REFLECT",
+
+ "CVMX_3DES/KASUMI_KEY0",
+ "CVMX_3DES/KASUMI_KEY1",
+ "CVMX_3DES/KASUMI_KEY2",
+ "CVMX_3DES_IV",
+ "CVMX_3DES_RESULT_RD",
+ "CVMX_3DES_RESULT_WR",
+
+ "CVMX_AES/SMS4_RESULT0",
+ "CVMX_AES/SMS4_RESULT1",
+ "CVMX_AES/SMS4_IV0",
+ "CVMX_AES/SMS4_IV1",
+ "CVMX_AES/SMS4_KEY0",
+ "CVMX_AES/SMS4_KEY1",
+ "CVMX_AES/SMS4_KEY2",
+ "CVMX_AES/SMS4_KEY3",
+
+ "CVMX_AES/SMS4_ENC_CBC0",
+ "CVMX_AES/SMS4_ENC0",
+ "CVMX_AES/SMS4_DEC_CBC0",
+ "CVMX_AES/SMS4_DEC0",
+
+ "CVMX_AES_KEYLENGTH",
+ "CVMX_AES_DAT0",
+
+ "CVMX_CAMELLIA_FL",
+ "CVMX_CAMELLIA_FLINV",
+
+ "CVMX_CRC_POLYNOMIAL",
+ "CVMX_CRC_IV",
+ "CVMX_CRC_LEN",
+ "CVMX_CRC_IV_REFLECT_RD",
+ "CVMX_CRC_BYTE",
+ "CVMX_CRC_HALF",
+ "CVMX_CRC_WORD",
+ "CVMX_CRC_IV_REFLECT_WR",
+ "CVMX_CRC_BYTE_REFLECT",
+ "CVMX_CRC_HALF_REFLECT",
+ "CVMX_CRC_WORD_REFLECT",
+
+ "CVMX_HSH_DATW0",
+ "CVMX_HSH_DATW1",
+ "CVMX_HSH_DATW2",
+ "CVMX_HSH_DATW3",
+ "CVMX_HSH_DATW4",
+ "CVMX_HSH_DATW5",
+ "CVMX_HSH_DATW6",
+ "CVMX_HSH_DATW7",
+ "CVMX_HSH_DATW8",
+ "CVMX_HSH_DATW9",
+ "CVMX_HSH_DATW10",
+ "CVMX_HSH_DATW11",
+ "CVMX_HSH_DATW12",
+ "CVMX_HSH_DATW13",
+ "CVMX_HSH_DATW14",
+
+ "CVMX_SHA3_DAT15_RD",
+
+ "CVMX_HSH_IVW0",
+ "CVMX_HSH_IVW1",
+ "CVMX_HSH_IVW2",
+ "CVMX_HSH_IVW3",
+ "CVMX_HSH_IVW4",
+ "CVMX_HSH_IVW5",
+ "CVMX_HSH_IVW6",
+ "CVMX_HSH_IVW7",
+
+ "CVMX_GFM_MUL0",
+ "CVMX_GFM_MUL1",
+ "CVMX_GFM_RESINP0",
+ "CVMX_GFM_RESINP1",
+ "CVMX_GFM_XOR0",
+ "CVMX_GFM_POLY",
+
+ "CVMX_SHA3_XORDAT0",
+ "CVMX_SHA3_XORDAT1",
+ "CVMX_SHA3_XORDAT2",
+ "CVMX_SHA3_XORDAT3",
+ "CVMX_SHA3_XORDAT4",
+ "CVMX_SHA3_XORDAT5",
+ "CVMX_SHA3_XORDAT6",
+ "CVMX_SHA3_XORDAT7",
+ "CVMX_SHA3_XORDAT8",
+ "CVMX_SHA3_XORDAT9",
+ "CVMX_SHA3_XORDAT10",
+ "CVMX_SHA3_XORDAT11",
+ "CVMX_SHA3_XORDAT12",
+ "CVMX_SHA3_XORDAT13",
+ "CVMX_SHA3_XORDAT14",
+ "CVMX_SHA3_XORDAT15",
+ "CVMX_SHA3_XORDAT16",
+ "CVMX_SHA3_XORDAT17",
+
+ "CVMX_LLM_READ_ADDR0",
+ "CVMX_LLM_WRITE_ADDR_INTERNAL0",
+ "CVMX_LLM_DATA0",
+ "CVMX_LLM_READ64_ADDR0",
+ "CVMX_LLM_WRITE64_ADDR_INTERNAL0",
+ "CVMX_LLM_READ_ADDR1",
+ "CVMX_LLM_WRITE_ADDR_INTERNAL1",
+ "CVMX_LLM_DATA1",
+ "CVMX_LLM_READ64_ADDR1",
+ "CVMX_LLM_WRITE64_ADDR_INTERNAL1",
+
+ "CVMX_CRC_LEN",
+ "CVMX_CRC_DWORD",
+ "CVMX_CRC_VAR",
+ "CVMX_CRC_DWORD_REFLECT",
+ "CVMX_CRC_VAR_REFLECT",
+
+ "CVMX_AES_ENC_CBC1",
+ "CVMX_AES_ENC1",
+ "CVMX_AES_DEC_CBC1",
+ "CVMX_AES_DEC1",
+
+ "CVMX_CAMELLIA_ROUND",
+
+ "CVMX_SMS4_ENC_CBC1",
+ "CVMX_SMS4_ENC1",
+ "CVMX_SMS4_DEC_CBC1",
+ "CVMX_SMS4_DEC1",
+
+ "CVMX_SHA3_STARTOP",
+ "CVMX_HSH_STARTMD5",
+ "CVMX_SNOW3G_START",
+ "CVMX_ZUC_START",
+ "CVMX_ZUC_MORE",
+ "CVMX_GFM_XORMUL1_REFLECT",
+ "CVMX_SNOW3G_MORE",
+ "CVMX_HSH_STARTSHA256",
+ "CVMX_HSH_STARTSHA",
+ "CVMX_3DES_ENC_CBC",
+ "CVMX_KAS_ENC_CBC",
+ "CVMX_3DES_ENC",
+ "CVMX_KAS_ENC",
+ "CVMX_3DES_DEC_CBC",
+ "CVMX_3DES_DEC",
+
+ "CVMX_CRC_POLYNOMIAL_WR",
+ "CVMX_CRC_POLYNOMIAL_REFLECT",
+
+ "CVMX_HSH_STARTSHA512",
+ "CVMX_GFM_XORMUL1",
};
static const char * const FlagStrings[] = {
@@ -959,7 +1240,8 @@ uint32_t mips_decompose_instruction(
combined ins,
Instruction* restrict instruction,
uint32_t version,
- uint64_t address)
+ uint64_t address,
+ uint32_t flags)
{
uint64_t registerMask;
@@ -986,14 +1268,40 @@ uint32_t mips_decompose_instruction(
break;
case 0x1c:
if (version == MIPS_32)
- instruction->operation = mips_special2_table[ins.decode.func_hi][ins.decode.func_lo];
+ instruction->operation = mips32_special2_table[ins.decode.func_hi][ins.decode.func_lo];
+ else if (version == MIPS_64)
+ {
+ if ((flags & DECOMPOSE_FLAGS_CAVIUM) == 0)
+ instruction->operation = mips64_special2_table[ins.decode.func_hi][ins.decode.func_lo];
+ else
+ {
+ instruction->operation = cavium_mips64_special2_table[ins.decode.func_hi][ins.decode.func_lo];
+ if (instruction->operation == CNMIPS_CVM)
+ {
+ switch (ins.r.sa)
+ {
+ // note that CN50xx docs don't include these instructions, but they are
+ // listed in the SDK (bootloader/u-boot/mips/include/asm/inst.h)
+ case 0x1c: instruction->operation = CNMIPS_ZCB; break;
+ case 0x1d: instruction->operation = CNMIPS_ZCBT; break;
+ default: return 1;
+ }
+ }
+ }
+
+ }
break;
case 0x1f:
if (version == MIPS_32)
- instruction->operation = mips_special3_table[ins.decode.func_hi][ins.decode.func_lo];
+ instruction->operation = mips32_special3_table[ins.decode.func_hi][ins.decode.func_lo];
+ else if (version == MIPS_64)
+ instruction->operation = mips64_special3_table[ins.decode.func_hi][ins.decode.func_lo];
break;
default:
- instruction->operation = mips_base_table[version-1][ins.decode.op_hi][ins.decode.op_lo];
+ if ((flags & DECOMPOSE_FLAGS_CAVIUM) == 0)
+ instruction->operation = mips_base_table[version-1][ins.decode.op_hi][ins.decode.op_lo];
+ else
+ instruction->operation = cavium_mips_base_table[ins.decode.op_hi][ins.decode.op_lo];
}
//Now deal with aliases and stage 2 decoding
@@ -1029,14 +1337,35 @@ uint32_t mips_decompose_instruction(
return 1;
}
break;
+ case MIPS_DBSHFL:
+ switch (ins.r.sa)
+ {
+ case 0x02: instruction->operation = MIPS_DSBH; break;
+ case 0x05: instruction->operation = MIPS_DSHD; break;
+ default:
+ return 1;
+ }
+ break;
case MIPS_SRL:
if (ins.bits.bit21 == 1)
instruction->operation = MIPS_ROTR;
break;
+ case MIPS_DSRL:
+ if (ins.bits.bit21 == 1)
+ instruction->operation = MIPS_DROTR;
+ break;
+ case MIPS_DSRL32:
+ if (ins.bits.bit21 == 1)
+ instruction->operation = MIPS_DROTR32;
+ break;
case MIPS_SRLV:
if (ins.bits.bit6 == 1)
instruction->operation = MIPS_ROTRV;
break;
+ case MIPS_DSRLV:
+ if (ins.bits.bit6 == 1)
+ instruction->operation = MIPS_DROTRV;
+ break;
case MIPS_COP0:
switch (ins.r.rs)
{
@@ -1289,9 +1618,36 @@ uint32_t mips_decompose_instruction(
instruction->operation = MIPS_BEQZ;
}
break;
+ case MIPS_BNE:
+ if (ins.r.rt == 0)
+ instruction->operation = MIPS_BNEZ;
+
+ break;
case MIPS_BGEZAL:
if (ins.r.rs == 0)
instruction->operation = MIPS_BAL;
+ case MIPS_SYNC:
+ if ((flags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ switch (ins.r.sa)
+ {
+ case 2: instruction->operation = CNMIPS_SYNCIOBDMA; break;
+ case 4: instruction->operation = CNMIPS_SYNCW; break;
+ case 5: instruction->operation = CNMIPS_SYNCWS; break;
+ case 6: instruction->operation = CNMIPS_SYNCS; break;
+ }
+ }
+ break;
+ case MIPS_RDHWR:
+ if ((flags & DECOMPOSE_FLAGS_CAVIUM) != 0)
+ {
+ switch (ins.r.rd)
+ {
+ case 30: instruction->operation = CNMIPS_RDHWR; break;
+ case 31: instruction->operation = CNMIPS_RDHWR; break;
+ }
+ }
+ break;
default:
break;
}
@@ -1355,7 +1711,7 @@ uint32_t mips_decompose_instruction(
break;
case MIPS_J:
case MIPS_JAL:
- INS_1(LABEL, (address & 0xf0000000) + (((uint32_t)ins.j.immediate)<<2))
+ INS_1(LABEL, (address & 0xfffffffff0000000) + (((uint32_t)ins.j.immediate)<<2))
break;
case MIPS_JR:
INS_1(REG, ins.r.rs)
@@ -1406,10 +1762,12 @@ uint32_t mips_decompose_instruction(
case MIPS_CLZ:
case MIPS_NOT:
case MIPS_MOVE:
+ case MIPS_DCLO:
+ case MIPS_DCLZ:
INS_2(REG, ins.r.rd, REG, ins.r.rs)
break;
case MIPS_RDHWR:
- INS_2(REG, ins.r.rt, REG, (CPREG_0 + ins.r.rd));
+ INS_2(REG, ins.r.rt, IMM, ins.r.rd);
break;
case MIPS_TRUNC_W_S:
case MIPS_TRUNC_W_D:
@@ -1479,6 +1837,7 @@ uint32_t mips_decompose_instruction(
case MIPS_BLTZALL:
case MIPS_BLTZL:
case MIPS_BEQZ:
+ case MIPS_BNEZ:
INS_2(REG, ins.i.rs, LABEL, (4 + address + (ins.i.immediate<<2)) & registerMask)
break;
case MIPS_BGTZ:
@@ -1543,6 +1902,8 @@ uint32_t mips_decompose_instruction(
case MIPS_NEG:
case MIPS_NEGU:
case MIPS_BITSWAP:
+ case MIPS_DSBH:
+ case MIPS_DSHD:
INS_2(REG, ins.r.rd, REG, ins.r.rt)
break;
case MIPS_CFC0:
@@ -1827,6 +2188,8 @@ uint32_t mips_decompose_instruction(
INS_3(REG, ins.i.rs, REG, ins.i.rt, LABEL, (4 + address + (ins.i.immediate<<2)) & registerMask)
break;
case MIPS_ROTR:
+ case MIPS_DROTR:
+ case MIPS_DROTR32:
INS_3(REG, ins.r.rd, REG, ins.r.rt, IMM, ins.r.sa)
if (ins.r.rs != 1)
return 1;
@@ -1849,6 +2212,7 @@ uint32_t mips_decompose_instruction(
return 1;
break;
case MIPS_ROTRV:
+ case MIPS_DROTRV:
INS_3(REG, ins.r.rd, REG, ins.r.rt, REG, ins.r.rs)
if (ins.r.sa != 1)
return 1;
@@ -1856,7 +2220,7 @@ uint32_t mips_decompose_instruction(
case MIPS_SRLV:
case MIPS_DSLLV:
case MIPS_DSRAV:
- case MIPS_DSLV:
+ case MIPS_DSRLV:
case MIPS_SLLV:
case MIPS_SRAV:
INS_3(REG, ins.r.rd, REG, ins.r.rt, REG, ins.r.rs)
@@ -1887,14 +2251,101 @@ uint32_t mips_decompose_instruction(
REG, ins.f.ft + FPREG_F0);
break;
case MIPS_INS:
+ case MIPS_DINS:
INS_4(REG, ins.r.rt, REG, ins.r.rs, IMM, ins.r.sa, IMM, ((int32_t)ins.r.rd + 1) - ins.r.sa);
break;
+ case MIPS_DINSM:
+ INS_4(REG, ins.r.rt, REG, ins.r.rs, IMM, ins.r.sa, IMM, ((int32_t)ins.r.rd + 33) - ins.r.sa);
+ break;
+ case MIPS_DINSU:
+ INS_4(REG, ins.r.rt, REG, ins.r.rs, IMM, ins.r.sa + 32, IMM, ((int32_t)ins.r.rd + 1) - ins.r.sa);
+ break;
case MIPS_EXT:
+ case MIPS_DEXT:
INS_4(REG, ins.r.rt, REG, ins.r.rs, IMM, ins.r.sa, IMM, ins.r.rd + 1);
break;
+ case MIPS_DEXTM:
+ INS_4(REG, ins.r.rt, REG, ins.r.rs, IMM, ins.r.sa, IMM, ins.r.rd + 33);
+ break;
+ case MIPS_DEXTU:
+ INS_4(REG, ins.r.rt, REG, ins.r.rs, IMM, ins.r.sa + 32, IMM, ins.r.rd + 1);
+ break;
case MIPS_ALIGN:
INS_4(REG, ins.r.rd, REG, ins.r.rs, REG, ins.r.rt, IMM, (ins.r.sa & 3));
break;
+
+ case CNMIPS_BADDU:
+ case CNMIPS_DMUL:
+ case CNMIPS_SEQ:
+ case CNMIPS_SNE:
+ case CNMIPS_V3MULU:
+ case CNMIPS_VMM0:
+ case CNMIPS_VMULU:
+ INS_3(REG, ins.r.rd, REG, ins.r.rs, REG, ins.r.rt)
+ if (ins.r.sa != 0)
+ return 1;
+ break;
+ case CNMIPS_BBIT0:
+ case CNMIPS_BBIT032:
+ case CNMIPS_BBIT1:
+ case CNMIPS_BBIT132:
+ INS_3(REG, ins.i.rs, IMM, ins.i.rt, LABEL, (4 + address + (ins.i.immediate<<2)) & registerMask)
+ break;
+ case CNMIPS_CINS:
+ case CNMIPS_CINS32:
+ case CNMIPS_EXTS:
+ case CNMIPS_EXTS32:
+ INS_4(REG, ins.r.rt, REG, ins.r.rs, IMM, ins.r.sa, IMM, ins.r.rd)
+ break;
+ case CNMIPS_MTM0:
+ case CNMIPS_MTM1:
+ case CNMIPS_MTM2:
+ case CNMIPS_MTP0:
+ case CNMIPS_MTP1:
+ case CNMIPS_MTP2:
+ INS_1(REG, ins.r.rs)
+ break;
+ case CNMIPS_SAA:
+ case CNMIPS_SAAD:
+ instruction->operands[0].operandClass = REG;
+ instruction->operands[1].operandClass = MEM_IMM;
+ instruction->operands[0].reg = ins.i.rt;
+ instruction->operands[1].reg = ins.i.rs;
+ instruction->operands[1].immediate = 0;
+ break;
+ case CNMIPS_SEQI:
+ case CNMIPS_SNEI:
+ {
+ uint32_t uimm = ins.decode.group1;
+
+ uint32_t mask = 1u << (10 - 1);
+ int32_t simm = (uimm ^ mask) - mask;
+
+ INS_3(REG, ins.r.rt, REG, ins.r.rs, IMM, simm)
+ break;
+ }
+ case CNMIPS_DPOP:
+ case CNMIPS_POP:
+ INS_2(REG, ins.r.rd, REG, ins.r.rs);
+ break;
+
+ case CNMIPS_RDHWR:
+ INS_2(REG, ins.r.rt, IMM, ins.r.rd);
+ break;
+
+ case CNMIPS_SYNCIOBDMA:
+ case CNMIPS_SYNCS:
+ case CNMIPS_SYNCW:
+ case CNMIPS_SYNCWS:
+ break;
+
+ case CNMIPS_ZCB:
+ case CNMIPS_ZCBT:
+ instruction->operands[0].operandClass = MEM_IMM;
+ instruction->operands[0].reg = ins.i.rs;
+ instruction->operands[0].immediate = 0;
+ break;
+
default:
return 1;
}
@@ -1976,6 +2427,7 @@ uint32_t mips_disassemble(
}
+// flags: see DECOMPOSE_FLAGS_*
uint32_t mips_decompose(
const uint32_t* instructionValue,
size_t size,
@@ -1983,7 +2435,7 @@ uint32_t mips_decompose(
uint32_t version,
uint64_t address,
uint32_t endianBig,
- uint32_t enablePseudoOps)
+ uint32_t flags)
{
combined ins;
if (instructionValue == NULL)
@@ -1994,12 +2446,12 @@ uint32_t mips_decompose(
else
ins.value = instructionValue[0];
- uint32_t result = mips_decompose_instruction(ins, instruction, version, address);
+ uint32_t result = mips_decompose_instruction(ins, instruction, version, address, flags);
if (result != 0)
return result;
instruction->size = 4;
//look for peudoinstructions by disassembling the next instruction too
- if (enablePseudoOps != 0 && size >= 8)
+ if ((flags & DECOMPOSE_FLAGS_PSEUDO_OP != 0) && size >= 8)
{
if (endianBig == 1)
ins.value = bswap32(instructionValue[1]);
@@ -2008,7 +2460,7 @@ uint32_t mips_decompose(
Instruction instruction2;
if (instruction->operation == MIPS_LUI)
{
- result = mips_decompose_instruction(ins, &instruction2, version, address+4);
+ result = mips_decompose_instruction(ins, &instruction2, version, address+4, flags);
if (result != 0)
{
return result;
diff --git a/arch/mips/mips/mips.h b/arch/mips/mips/mips.h
index 14c5f2d8..48b68712 100644
--- a/arch/mips/mips/mips.h
+++ b/arch/mips/mips/mips.h
@@ -30,6 +30,9 @@
namespace mips
{
#endif
+ static const uint32_t DECOMPOSE_FLAGS_PSEUDO_OP = 0x1;
+ static const uint32_t DECOMPOSE_FLAGS_CAVIUM = 0x2;
+
enum Operation {
MIPS_INVALID,
MIPS_ABS_D,
@@ -82,6 +85,7 @@ namespace mips
MIPS_BLTZL,
MIPS_BNE,
MIPS_BNEL,
+ MIPS_BNEZ,
MIPS_BNZ_B,
MIPS_BNZ_D,
MIPS_BNZ_H,
@@ -202,10 +206,19 @@ namespace mips
MIPS_DADDI,
MIPS_DADDIU,
MIPS_DADDU,
+ MIPS_DBSHFL,
+ MIPS_DCLO,
+ MIPS_DCLZ,
MIPS_DDIV,
MIPS_DDIVU,
MIPS_DERET,
+ MIPS_DEXT,
+ MIPS_DEXTM,
+ MIPS_DEXTU,
MIPS_DI,
+ MIPS_DINS,
+ MIPS_DINSM,
+ MIPS_DINSU,
MIPS_DIV_D,
MIPS_DIV_PS,
MIPS_DIV_S,
@@ -220,15 +233,20 @@ namespace mips
MIPS_DMTC1,
MIPS_DMTC2,
MIPS_DRET,
+ MIPS_DROTR,
+ MIPS_DROTR32,
+ MIPS_DROTRV,
+ MIPS_DSBH,
+ MIPS_DSHD,
MIPS_DSLL,
MIPS_DSLL32,
MIPS_DSLLV,
- MIPS_DSLV,
MIPS_DSRA,
MIPS_DSRA32,
MIPS_DSRAV,
MIPS_DSRL,
MIPS_DSRL32,
+ MIPS_DSRLV,
MIPS_DSUB,
MIPS_DSUBU,
MIPS_EHB,
@@ -455,6 +473,44 @@ namespace mips
MIPS_WSBH,
MIPS_XOR,
MIPS_XORI,
+
+ // cavium instructions
+ CNMIPS_BADDU,
+ CNMIPS_BBIT0,
+ CNMIPS_BBIT032,
+ CNMIPS_BBIT1,
+ CNMIPS_BBIT132,
+ CNMIPS_CINS,
+ CNMIPS_CINS32,
+ CNMIPS_CVM,
+ CNMIPS_DMUL,
+ CNMIPS_DPOP,
+ CNMIPS_EXTS,
+ CNMIPS_EXTS32,
+ CNMIPS_MTM0,
+ CNMIPS_MTM1,
+ CNMIPS_MTM2,
+ CNMIPS_MTP0,
+ CNMIPS_MTP1,
+ CNMIPS_MTP2,
+ CNMIPS_POP,
+ CNMIPS_RDHWR,
+ CNMIPS_SAA,
+ CNMIPS_SAAD,
+ CNMIPS_SEQ,
+ CNMIPS_SEQI,
+ CNMIPS_SNE,
+ CNMIPS_SNEI,
+ CNMIPS_SYNCIOBDMA,
+ CNMIPS_SYNCS,
+ CNMIPS_SYNCW,
+ CNMIPS_SYNCWS,
+ CNMIPS_V3MULU,
+ CNMIPS_VMM0,
+ CNMIPS_VMULU,
+ CNMIPS_ZCB,
+ CNMIPS_ZCBT,
+
MIPS_OPERATION_END
};
@@ -667,6 +723,197 @@ namespace mips
// Coprocessor 0 register 31
REG_DESAVE, // 0
+ // cavium multiplication registers
+ CNREG_MPL0,
+ CNREG_MPL1,
+ CNREG_MPL2,
+ CNREG_P0,
+ CNREG_P1,
+ CNREG_P2,
+
+ // cavium cop0 registers: see `COP0_xx` macros in cvmx-asm.h in SDK
+ CNREG0_CVM_COUNT, // implementation-defined 9, 6
+ CNREG0_CVM_CTL, // implementation-defined 9, 7
+ CNREG0_POWTHROTTLE, // implementation-defined 11, 6
+ CNREG0_CVM_MEM_CTL, // implementation-defined 11, 7
+ CNREG0_MULTICORE_DBG, // implementation-defined 22, 0
+
+ // cavium cop2 registers
+ CNREG2_0040_HSH_DAT0,
+ CNREG2_0041_HSH_DAT1,
+ CNREG2_0042_HSH_DAT2,
+ CNREG2_0043_HSH_DAT3,
+ CNREG2_0044_HSH_DAT4,
+ CNREG2_0045_HSH_DAT5,
+ CNREG2_0046_HSH_DAT6,
+
+ CNREG2_0048_HSH_IV0,
+ CNREG2_0049_HSH_IV1,
+ CNREG2_004A_HSH_IV2,
+ CNREG2_004B_HSH_IV3,
+
+ CNREG2_0050_SHA3_DAT24,
+ CNREG2_0051_SHA3_DAT15_RD,
+
+ CNREG2_0058_GFM_MUL_REFLECT0,
+ CNREG2_0059_GFM_MUL_REFLECT1,
+ CNREG2_005A_GFM_RESINP_REFLECT0,
+ CNREG2_005B_GFM_RESINP_REFLECT1,
+ CNREG2_005C_GFM_XOR0_REFLECT,
+
+ // also KASUMI
+ CNREG2_0080_3DES_KEY0,
+ CNREG2_0081_3DES_KEY1,
+ CNREG2_0082_3DES_KEY2,
+
+ CNREG2_0084_3DES_IV,
+ CNREG2_0088_3DES_RESULT_RD,
+ CNREG2_0098_3DES_RESULT_WR,
+
+ // also SMS4 RESINP
+ CNREG2_0100_AES_RESULT0,
+ CNREG2_0101_AES_RESULT1,
+
+ // also SMS4 IV
+ CNREG2_0102_AES_IV0,
+ CNREG2_0103_AES_IV1,
+
+ // also SMS4 KEY
+ CNREG2_0104_AES_KEY0,
+ CNREG2_0105_AES_KEY1,
+ CNREG2_0106_AES_KEY2,
+ CNREG2_0107_AES_KEY3,
+
+ // also SMS4_x
+ CNREG2_0108_AES_ENC_CBC0,
+ CNREG2_010A_AES_ENC0,
+ CNREG2_010C_AES_DEC_CBC0,
+ CNREG2_010E_AES_DEC0,
+
+ CNREG2_0110_AES_KEYLENGTH,
+ CNREG2_0111_AES_DAT0,
+
+ CNREG2_0115_CAMELLIA_FL,
+ CNREG2_0116_CAMELLIA_FLINV,
+
+ CNREG2_0200_CRC_POLYNOMIAL,
+ CNREG2_0201_CRC_IV,
+ CNREG2_0202_CRC_LEN,
+ CNREG2_0203_CRC_IV_REFLECT_RD,
+ CNREG2_0204_CRC_BYTE,
+ CNREG2_0205_CRC_HALF,
+ CNREG2_0206_CRC_WORD,
+ CNREG2_0211_CRC_IV_REFLECT_WR,
+ CNREG2_0214_CRC_BYTE_REFLECT,
+ CNREG2_0215_CRC_HALF_REFLECT,
+ CNREG2_0216_CRC_WORD_REFLECT,
+
+ // also SNOW3G_LFSR, SHA3DAT0..=14
+ CNREG2_0240_HSH_DATW0,
+ CNREG2_0241_HSH_DATW1,
+ CNREG2_0242_HSH_DATW2,
+ CNREG2_0243_HSH_DATW3,
+ CNREG2_0244_HSH_DATW4,
+ CNREG2_0245_HSH_DATW5,
+ CNREG2_0246_HSH_DATW6,
+ CNREG2_0247_HSH_DATW7,
+ CNREG2_0248_HSH_DATW8,
+ CNREG2_0249_HSH_DATW9,
+ CNREG2_024A_HSH_DATW10,
+ CNREG2_024B_HSH_DATW11,
+ CNREG2_024C_HSH_DATW12,
+ CNREG2_024D_HSH_DATW13,
+ CNREG2_024E_HSH_DATW14,
+
+ CNREG2_024F_SHA3_DAT15_RD,
+
+ // also SNOW3G_RESULT (0x250), SNOW3G_SFM (0x251, 0x252, 0x253)
+ CNREG2_0250_HSH_IVW0,
+ CNREG2_0251_HSH_IVW1,
+ CNREG2_0252_HSH_IVW2,
+ CNREG2_0253_HSH_IVW3,
+ CNREG2_0254_HSH_IVW4,
+ CNREG2_0255_HSH_IVW5,
+ CNREG2_0256_HSH_IVW6,
+ CNREG2_0257_HSH_IVW7,
+
+ CNREG2_0258_GFM_MUL0,
+ CNREG2_0259_GFM_MUL1,
+ CNREG2_025A_GFM_RESINP0,
+ CNREG2_025B_GFM_RESINP1,
+ CNREG2_025C_GFM_XOR0,
+ CNREG2_025E_GFM_POLY,
+
+ CNREG2_02C0_SHA3_XORDAT0,
+ CNREG2_02C1_SHA3_XORDAT1,
+ CNREG2_02C2_SHA3_XORDAT2,
+ CNREG2_02C3_SHA3_XORDAT3,
+ CNREG2_02C4_SHA3_XORDAT4,
+ CNREG2_02C5_SHA3_XORDAT5,
+ CNREG2_02C6_SHA3_XORDAT6,
+ CNREG2_02C7_SHA3_XORDAT7,
+ CNREG2_02C8_SHA3_XORDAT8,
+ CNREG2_02C9_SHA3_XORDAT9,
+ CNREG2_02CA_SHA3_XORDAT10,
+ CNREG2_02CB_SHA3_XORDAT11,
+ CNREG2_02CC_SHA3_XORDAT12,
+ CNREG2_02CD_SHA3_XORDAT13,
+ CNREG2_02CE_SHA3_XORDAT14,
+ CNREG2_02CF_SHA3_XORDAT15,
+ CNREG2_02D0_SHA3_XORDAT16,
+ CNREG2_02D1_SHA3_XORDAT17,
+
+ CNREG2_0400_LLM_READ_ADDR0,
+ CNREG2_0401_LLM_WRITE_ADDR_INTERNAL0,
+ CNREG2_0402_LLM_DATA0,
+ CNREG2_0404_LLM_READ64_ADDR0,
+ CNREG2_0405_LLM_WRITE64_ADDR_INTERNAL0,
+ CNREG2_0408_LLM_READ_ADDR1,
+ CNREG2_0409_LLM_WRITE_ADDR_INTERNAL1,
+ CNREG2_040a_LLM_DATA1,
+ CNREG2_040c_LLM_READ64_ADDR1,
+ CNREG2_040d_LLM_WRITE64_ADDR_INTERNAL1,
+
+ CNREG2_1202_CRC_LEN,
+ CNREG2_1207_CRC_DWORD,
+ CNREG2_1208_CRC_VAR,
+ CNREG2_1217_CRC_DWORD_REFLECT,
+ CNREG2_1218_CRC_VAR_REFLECT,
+
+ CNREG2_3109_AES_ENC_CBC1,
+ CNREG2_310B_AES_ENC1,
+ CNREG2_310D_AES_DEC_CBC1,
+ CNREG2_310F_AES_DEC1,
+
+ CNREG2_3114_CAMELLIA_ROUND,
+
+ CNREG2_3119_SMS4_ENC_CBC1,
+ CNREG2_311B_SMS4_ENC1,
+ CNREG2_311D_SMS4_DEC_CBC1,
+ CNREG2_311F_SMS4_DEC1,
+
+ CNREG2_4052_SHA3_STARTOP,
+ CNREG2_4047_HSH_STARTMD5,
+ CNREG2_404D_SNOW3G_START,
+ CNREG2_4055_ZUC_START,
+ CNREG2_4056_ZUC_MORE,
+ CNREG2_405D_GFM_XORMUL1_REFLECT,
+ CNREG2_404E_SNOW3G_MORE,
+ CNREG2_404F_HSH_STARTSHA256,
+ CNREG2_4057_HSH_STARTSHA,
+ CNREG2_4088_3DES_ENC_CBC,
+ CNREG2_4089_KAS_ENC_CBC,
+ CNREG2_408A_3DES_ENC,
+ CNREG2_408B_KAS_ENC,
+ CNREG2_408C_3DES_DEC_CBC,
+ CNREG2_408E_3DES_DEC,
+
+ CNREG2_4200_CRC_POLYNOMIAL_WR,
+ CNREG2_4210_CRC_POLYNOMIAL_REFLECT,
+
+ CNREG2_424F_HSH_STARTSHA512,
+ CNREG2_425D_GFM_XORMUL1,
+
// Last valid register
END_REG
};