diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index 57a68f6ee8..d148c690a1 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -47,3 +47,31 @@ if(BN_INTERNAL_BUILD) LIBRARY_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR} RUNTIME_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR}) endif() + +if (DEFINED FORCE_TEST) + set(TEST_INLCUDE_LIST ) + set(TEST_LINK_DIRECTORIES ) + set(TEST_LINK_LIBRARIES capstone) + + if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") + add_executable(test_disasm test_disasm.cpp disassembler.cpp) + add_executable(test_asm test_asm.cpp assembler.cpp) + + target_compile_definitions(test_disasm PRIVATE FORCE_TEST=1) + + set_target_properties(test_disasm test_asm PROPERTIES + CXX_STANDARD 17 + CXX_VISIBILITY_PRESET hidden + CXX_STANDARD_REQUIRED ON + VISIBILITY_INLINES_HIDDEN ON + POSITION_INDEPENDENT_CODE ON) + + target_include_directories(test_disasm PRIVATE ${TEST_INCLUDE_LIST}) + target_link_directories(test_disasm PRIVATE ${TEST_LINK_DIRECTORIES}) + target_link_libraries(test_disasm PRIVATE ${TEST_LINK_LIBRARIES}) + + target_include_directories(test_asm PRIVATE ${TEST_INCLUDE_LIST}) + target_link_directories(test_asm PRIVATE ${TEST_LINK_DIRECTORIES}) + target_link_libraries(test_asm PRIVATE ${TEST_LINK_LIBRARIES}) + endif() +endif() diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 545e2be370..f732b561ba 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -6,8 +6,8 @@ #include #define MYLOG(...) while(0); -//#define MYLOG BinaryNinja::LogDebug -//#define MYLOG printf +// #define MYLOG BinaryNinja::LogWarn +// #define MYLOG printf #include "lowlevelilinstruction.h" using namespace BinaryNinja; // for ::LogDebug, etc. @@ -281,6 +281,7 @@ class PowerpcArchitecture: public Architecture { private: BNEndianness endian; + int cs_mode_local; size_t addressSize; /* this can maybe be moved to the API later */ @@ -297,10 +298,11 @@ class PowerpcArchitecture: public Architecture public: /* initialization list */ - PowerpcArchitecture(const char* name, BNEndianness endian_, size_t addressSize_=4): Architecture(name) + PowerpcArchitecture(const char* name, BNEndianness endian_, size_t addressSize_=4, int cs_mode_=0): Architecture(name) { endian = endian_; addressSize = addressSize_; + cs_mode_local = cs_mode_; } /*************************************************************************/ @@ -320,7 +322,7 @@ class PowerpcArchitecture: public Architecture virtual size_t GetDefaultIntegerSize() const override { MYLOG("%s()\n", __func__); - return 4; + return addressSize; } virtual size_t GetInstructionAlignment() const override @@ -356,13 +358,13 @@ class PowerpcArchitecture: public Architecture return false; } - if (DoesQualifyForLocalDisassembly(data)) { + if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) { result.length = 4; return true; } /* decompose the instruction to get branch info */ - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) { + if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); return false; } @@ -376,15 +378,17 @@ class PowerpcArchitecture: public Architecture { case 18: /* b (b, ba, bl, bla) */ { - uint32_t target = raw_insn & 0x03fffffc; + uint64_t target = raw_insn & 0x03fffffc; /* sign extend target */ - if ((target >> 25) & 1) - target |= 0xfc000000; + target = sign_extend(addressSize, target, 25); /* account for absolute addressing */ if (!(raw_insn & 2)) - target += (uint32_t) addr; + { + target += addr; + ADDRMASK(addressSize, target); + } if (raw_insn & 1) result.AddBranch(CallDestination, target); @@ -395,17 +399,19 @@ class PowerpcArchitecture: public Architecture } case 16: /* bc */ { - uint32_t target = raw_insn & 0xfffc; + uint64_t target = raw_insn & 0xfffc; uint8_t bo = (raw_insn >> 21) & 0x1f; bool lk = raw_insn & 1; /* sign extend target */ - if ((target >> 15) & 1) - target |= 0xffff0000; + target = sign_extend(addressSize, target, 15); /* account for absolute addressing */ if (!(raw_insn & 2)) - target += (uint32_t) addr; + { + target += addr; + ADDRMASK(addressSize, target); + } if (target != addr + 4) { @@ -455,149 +461,56 @@ class PowerpcArchitecture: public Architecture return true; } - bool DoesQualifyForLocalDisassembly(const uint8_t *data) - { - uint32_t insword = *(uint32_t *)data; - if(endian == BigEndian) - insword = bswap32(insword); - - // 111111xxx00xxxxxxxxxx00001000000 <- fcmpo - uint32_t tmp = insword & 0xFC6007FF; - if (tmp==0xFC000040) - return true; - // 111100xxxxxxxxxxxxxxx00111010xxx <- xxpermr - if((insword & 0xFC0007F8) == 0xF00001D0) - return true; - // 000100xxxxxxxxxxxxxxxxxxx000110x <- psq_lx - // 000100xxxxxxxxxxxxxxxxxxx000111x <- psq_stx - // 000100xxxxxxxxxxxxxxxxxxx100110x <- psq_lux - // 000100xxxxxxxxxxxxxxxxxxx100111x <- psq_stux - tmp = insword & 0xFC00007E; - if (tmp==0x1000000C || tmp==0x1000000E || tmp==0x1000004C || tmp==0x1000004E) - return true; - // 000100xxxxxxxxxx00000xxxxx011000 <- ps_muls0 - // 000100xxxxxxxxxx00000xxxxx011001 <- ps_muls0. - // 000100xxxxxxxxxx00000xxxxx011010 <- ps_muls1 - // 000100xxxxxxxxxx00000xxxxx011011 <- ps_muls1. - tmp = insword & 0xFC00F83F; - if (tmp==0x10000018 || tmp==0x10000019 || tmp==0x1000001A || tmp==0x1000001B) - return true; - - return false; - } - - bool PerformLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, vector &result) + bool PrintLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, vector &result, decomp_result* res) { (void)addr; + char buf[16]; + uint32_t local_op = PPC_INS_INVALID; - if (len < 4) return false; - uint32_t insword = *(uint32_t *)data; - if(endian == BigEndian) - insword = bswap32(insword); + struct cs_detail *detail = 0; + struct cs_ppc *ppc = 0; + struct cs_insn *insn = &(res->insn); + detail = &(res->detail); + ppc = &(detail->ppc); + + if (len < 4) + return false; len = 4; - char buf[16]; + local_op = DoesQualifyForLocalDisassembly(data, endian == BigEndian); + PerformLocalDisassembly(data, addr, len, res, endian == BigEndian); - // 111111AAA00BBBBBCCCCC00001000000 "fcmpo crA,fB,fC" - uint32_t tmp = insword & 0xFC6007FF; - if (tmp==0xFC000040) { - result.emplace_back(InstructionToken, "fcmpo"); + switch (local_op) + { + case PPC_INS_BN_FCMPO: + result.emplace_back(InstructionToken, insn->mnemonic); result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "cr%d", (insword >> 23) & 7); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "f%d", (insword >> 16) & 31); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "f%d", (insword >> 11) & 31); - result.emplace_back(RegisterToken, buf); - return true; - } - - // 111100AAAAABBBBBCCCCC00011010BCA "xxpermr vsA,vsB,vsC" - if ((insword & 0xFC0007F8)==0xF00001D0) { - int a = ((insword & 0x3E00000)>>21)|((insword & 0x1)<<5); - int b = ((insword & 0x1F0000)>>16)|((insword & 0x4)<<3); - int c = ((insword & 0xF800)>>11)|((insword & 0x2)<<4); - result.emplace_back(InstructionToken, "xxpermr"); - result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "vs%d", a); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "vs%d", b); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "vs%d", c); - result.emplace_back(RegisterToken, buf); - return true; - } - - // 000100AAAAABBBBBCCCCCDEEE000110x psq_lx FREG,GPR,GPR,NUM,NUM - // 000100AAAAABBBBBCCCCCDEEE000111x psq_stx FREG,GPR,GPR,NUM,NUM - // 000100AAAAABBBBBCCCCCDEEE100110x psq_lux FREG,GPR,GPR,NUM,NUM - // 000100AAAAABBBBBCCCCCDEEE100111x psq_stux FREG,GPR,GPR,NUM,NUM - tmp = insword & 0xFC00007E; - if (tmp==0x1000000C || tmp==0x1000000E || tmp==0x1000004C || tmp==0x1000004E) { - switch(tmp) { - case 0x1000000C: - result.emplace_back(InstructionToken, "psq_lx"); - result.emplace_back(TextToken, " "); - break; - case 0x1000000E: result.emplace_back(InstructionToken, "psq_stx"); - result.emplace_back(TextToken, " "); - break; - case 0x1000004C: result.emplace_back(InstructionToken, "psq_lux"); - result.emplace_back(TextToken, " "); - break; - case 0x1000004E: result.emplace_back(InstructionToken, "psq_stux"); - result.emplace_back(TextToken, " "); - break; - } - snprintf(buf, sizeof(buf), "f%d", (insword & 0x3E00000) >> 21); + snprintf(buf, sizeof(buf), "cr%d", ppc->operands[0].reg - PPC_REG_CR0); result.emplace_back(RegisterToken, buf); result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "r%d", (insword & 0x1F0000) >> 16); + snprintf(buf, sizeof(buf), "f%d", ppc->operands[1].reg - PPC_REG_F0); result.emplace_back(RegisterToken, buf); result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "r%d", (insword & 0xF800) >> 11); + snprintf(buf, sizeof(buf), "f%d", ppc->operands[2].reg - PPC_REG_F0); result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - tmp = (insword & 0x400)>>10; - snprintf(buf, sizeof(buf), "%d", tmp); - result.emplace_back(IntegerToken, buf, tmp, 1); - result.emplace_back(OperandSeparatorToken, ", "); - tmp = (insword & 0x380)>>7; - snprintf(buf, sizeof(buf), "%d", tmp); - result.emplace_back(IntegerToken, buf, tmp, 1); - return true; - } - - // 000100AAAAABBBBB00000CCCCC011000 ps_muls0 FREG,FREG,FREG - // 000100AAAAABBBBB00000CCCCC011001 ps_muls0. FREG,FREG,FREG - // 000100AAAAABBBBB00000CCCCC011010 ps_muls1 FREG,FREG,FREG - // 000100AAAAABBBBB00000CCCCC011011 ps_muls1. FREG,FREG,FREG - tmp = insword & 0xFC00F83F; - if (tmp==0x10000018 || tmp==0x10000019 || tmp==0x1000001A || tmp==0x1000001B) { - switch(tmp) { - case 0x10000018: result.emplace_back(InstructionToken, "ps_muls0"); break; - case 0x10000019: result.emplace_back(InstructionToken, "ps_muls0."); break; - case 0x1000001A: result.emplace_back(InstructionToken, "ps_muls1"); break; - case 0x1000001B: result.emplace_back(InstructionToken, "ps_muls1."); break; - } + break; + case PPC_INS_BN_XXPERMR: + result.emplace_back(InstructionToken, insn->mnemonic); result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "f%d", (insword & 0x3E00000) >> 21); + snprintf(buf, sizeof(buf), "vs%d", ppc->operands[0].reg - PPC_REG_VS0); result.emplace_back(RegisterToken, buf); result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "f%d", (insword & 0x1F0000) >> 16); + snprintf(buf, sizeof(buf), "vs%d", ppc->operands[1].reg - PPC_REG_VS0); result.emplace_back(RegisterToken, buf); result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "f%d", (insword & 0x7C0) >> 6); + snprintf(buf, sizeof(buf), "vs%d", ppc->operands[2].reg - PPC_REG_VS0); result.emplace_back(RegisterToken, buf); - return true; + break; + default: + return false; } - - return false; + return true; } /* populate the vector result with InstructionTextToken @@ -621,10 +534,12 @@ class PowerpcArchitecture: public Architecture goto cleanup; } - if (DoesQualifyForLocalDisassembly(data)) - return PerformLocalDisassembly(data, addr, len, result); - - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) { + if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) + { + // PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); + return PrintLocalDisassembly(data, addr, len, result, &res); + } + if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); goto cleanup; } @@ -728,9 +643,136 @@ class PowerpcArchitecture: public Architecture return rc; } + static string GetIntrinsicName_ppc_ps(uint32_t intrinsic) + { + switch (intrinsic) + { + case PPC_PS_INTRIN_QUANTIZE: + return "quantize"; + case PPC_PS_INTRIN_DEQUANTIZE: + return "dequantize"; + default: + break; + } + return ""; + } + + virtual string GetIntrinsicName(uint32_t intrinsic) override + { + switch (intrinsic) + { + case PPC_INTRIN_CNTLZW: + return "__builtin_clz"; + case PPC_INTRIN_FRSP: + return "float_round"; + default: + if (cs_mode_local == CS_MODE_PS) + { + return GetIntrinsicName_ppc_ps(intrinsic); + } + break; + } + return ""; + } + + + virtual std::vector GetAllIntrinsics() override + { + // Highest intrinsic number currently is PPC_PS_INTRIN_END. + // If new extensions are added please update this code. + std::vector result{PPC_PS_INTRIN_END}; + + // Double check someone didn't insert a new intrinsic at the beginning of our enum since we rely + // on it to fill the next array. + static_assert(PPCIntrinsic::PPC_INTRIN_CNTLZW == 0, + "Invalid first PPCIntrinsic value. Please add your intrinsic further in the enum."); + + // Normal intrinsics. + for (uint32_t id = PPC_INTRIN_CNTLZW; id < PPCIntrinsic::PPC_INTRIN_END; id++) { + result.push_back(id); + } + + // PPC_PS intrinsics. + for (uint32_t id = PPC_PS_INTRIN_QUANTIZE; id < PPCIntrinsic::PPC_PS_INTRIN_END; id++) { + result.push_back(id); + } + + // consider populating with separate architecture stuff, like ppc_ps stuff or something + return result; + } + + static vector GetIntrinsicInputs_ppc_ps(uint32_t intrinsic) + { + switch (intrinsic) + { + // for now, quantize is operating on the float in, and the gqr that holds the scale + case PPC_PS_INTRIN_QUANTIZE: + return {NameAndType(Type::FloatType(4)), NameAndType(Type::IntegerType(4, false))}; + case PPC_PS_INTRIN_DEQUANTIZE: + return {NameAndType(Type::IntegerType(4, false)), NameAndType(Type::FloatType(8)), NameAndType(Type::IntegerType(4, false))}; + default: + break; + } + return vector(); + } + + virtual vector GetIntrinsicInputs(uint32_t intrinsic) override + { + switch (intrinsic) + { + case PPC_INTRIN_CNTLZW: // rs + return {NameAndType(Type::IntegerType(4, false))}; + case PPC_INTRIN_FRSP: + return {NameAndType(Type::FloatType(4))}; + // for now, quantize is operating on the float in, and the gqr that holds the scale + default: + if (cs_mode_local == CS_MODE_PS) + { + return GetIntrinsicInputs_ppc_ps(intrinsic); + } + break; + } + return vector(); + } + + static vector>> GetIntrinsicOutputs_ppc_ps(uint32_t intrinsic) + { + switch(intrinsic) + { + case PPC_PS_INTRIN_QUANTIZE: + // quantize returns the quantized float + return {Type::FloatType(4)}; + case PPC_PS_INTRIN_DEQUANTIZE: + return {Type::FloatType(4)}; + default: + break; + } + return vector>>(); + } + + virtual vector>> GetIntrinsicOutputs(uint32_t intrinsic) override + { + switch (intrinsic) + { + case PPC_INTRIN_CNTLZW: // ra + return {Type::IntegerType(4, false)}; + case PPC_INTRIN_FRSP: + return {Type::FloatType(4)}; + default: + if (cs_mode_local == CS_MODE_PS) + { + return GetIntrinsicOutputs_ppc_ps(intrinsic); + } + break; + } + return vector>>(); + } + + virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override { bool rc = false; + struct decomp_result res = {0}; if (len < 4) { MYLOG("ERROR: need at least 4 bytes\n"); @@ -741,21 +783,16 @@ class PowerpcArchitecture: public Architecture // MYLOG("%s(data, 0x%llX, 0x%zX, il)\n", __func__, addr, len); //} - struct decomp_result res; - - if (DoesQualifyForLocalDisassembly(data)) { - il.AddInstruction(il.Unimplemented()); - rc = true; - len = 4; - goto cleanup; + if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) { + PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); } - - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) { + else if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); il.AddInstruction(il.Undefined()); goto cleanup; } +// getil: rc = GetLowLevelILForPPCInstruction(this, il, data, addr, &res, endian == LittleEndian); len = 4; @@ -766,24 +803,14 @@ class PowerpcArchitecture: public Architecture virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override { - MYLOG("%s()\n", __func__); - - bool signedWrite = true; + // MYLOG("%s(), op:%d, flagwritetype:%d, flag:%d\n", __func__, op, flagWriteType, flag); ExprId left, right; + ppc_suf suf = (ppc_suf)0; + + suf = (ppc_suf)((flagWriteType - 1) % PPC_SUF_SZ); switch (flagWriteType) { - case IL_FLAGWRITE_CR0_U: - case IL_FLAGWRITE_CR1_U: - case IL_FLAGWRITE_CR2_U: - case IL_FLAGWRITE_CR3_U: - case IL_FLAGWRITE_CR4_U: - case IL_FLAGWRITE_CR5_U: - case IL_FLAGWRITE_CR6_U: - case IL_FLAGWRITE_CR7_U: - signedWrite = false; - break; - case IL_FLAGWRITE_MTCR0: case IL_FLAGWRITE_MTCR1: case IL_FLAGWRITE_MTCR2: @@ -807,7 +834,7 @@ class PowerpcArchitecture: public Architecture } auto liftOps = [&]() { - if (op == LLIL_SUB) + if ((op == LLIL_SUB) || (op == LLIL_FSUB)) { left = il.GetExprForRegisterOrConstant(operands[0], size); right = il.GetExprForRegisterOrConstant(operands[1], size); @@ -868,10 +895,12 @@ class PowerpcArchitecture: public Architecture case IL_FLAG_LT_7: liftOps(); - if (signedWrite) + if (suf == PPC_SUF_S) return il.CompareSignedLessThan(size, left, right); - else + else if (suf == PPC_SUF_U) return il.CompareUnsignedLessThan(size, left, right); + else if (suf == PPC_SUF_F) + return il.FloatCompareLessThan(size, left, right); case IL_FLAG_GT: case IL_FLAG_GT_1: @@ -883,10 +912,12 @@ class PowerpcArchitecture: public Architecture case IL_FLAG_GT_7: liftOps(); - if (signedWrite) + if (suf == PPC_SUF_S) return il.CompareSignedGreaterThan(size, left, right); - else + else if (suf == PPC_SUF_U) return il.CompareUnsignedGreaterThan(size, left, right); + else if (suf == PPC_SUF_F) + return il.FloatCompareGreaterThan(size, left, right); case IL_FLAG_EQ: case IL_FLAG_EQ_1: @@ -897,7 +928,10 @@ class PowerpcArchitecture: public Architecture case IL_FLAG_EQ_6: case IL_FLAG_EQ_7: liftOps(); - return il.CompareEqual(size, left, right); + if (suf == PPC_SUF_F) + return il.FloatCompareEqual(size, left, right); + else + return il.CompareEqual(size, left, right); } BNFlagRole role = GetFlagRole(flag, GetSemanticClassForFlagWriteType(flagWriteType)); @@ -907,6 +941,7 @@ class PowerpcArchitecture: public Architecture virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) override { + // MYLOG("%s() semgroup:%d\n", __func__, semGroup); uint32_t flagBase = (semGroup / 10) * 4; // get to flags from the right cr switch (semGroup % 10) @@ -924,7 +959,7 @@ class PowerpcArchitecture: public Architecture virtual string GetRegisterName(uint32_t regId) override { - const char *result = powerpc_reg_to_str(regId); + const char *result = powerpc_reg_to_str(regId, cs_mode_local); if(result == NULL) result = ""; @@ -947,7 +982,7 @@ class PowerpcArchitecture: public Architecture */ virtual vector GetAllFlags() override { - MYLOG("%s()\n", __func__); + // MYLOG("%s()\n", __func__); return vector { IL_FLAG_LT, IL_FLAG_GT, IL_FLAG_EQ, IL_FLAG_SO, IL_FLAG_LT_1, IL_FLAG_GT_1, IL_FLAG_EQ_1, IL_FLAG_SO_1, @@ -963,7 +998,7 @@ class PowerpcArchitecture: public Architecture virtual string GetFlagName(uint32_t flag) override { - MYLOG("%s(%d)\n", __func__, flag); + // MYLOG("%s() flag:%d\n", __func__, flag); switch(powerpc_crx_to_reg(flag)) { case IL_FLAG_LT: return "lt"; @@ -1021,6 +1056,9 @@ class PowerpcArchitecture: public Architecture IL_FLAGWRITE_CR0_U, IL_FLAGWRITE_CR1_U, IL_FLAGWRITE_CR2_U, IL_FLAGWRITE_CR3_U, IL_FLAGWRITE_CR4_U, IL_FLAGWRITE_CR5_U, IL_FLAGWRITE_CR6_U, IL_FLAGWRITE_CR7_U, + IL_FLAGWRITE_CR0_F, IL_FLAGWRITE_CR1_F, IL_FLAGWRITE_CR2_F, IL_FLAGWRITE_CR3_F, + IL_FLAGWRITE_CR4_F, IL_FLAGWRITE_CR5_F, IL_FLAGWRITE_CR6_F, IL_FLAGWRITE_CR7_F, + IL_FLAGWRITE_XER, IL_FLAGWRITE_XER_CA, IL_FLAGWRITE_XER_OV_SO, IL_FLAGWRITE_MTCR0, IL_FLAGWRITE_MTCR1, IL_FLAGWRITE_MTCR2, IL_FLAGWRITE_MTCR3, @@ -1035,7 +1073,7 @@ class PowerpcArchitecture: public Architecture virtual string GetFlagWriteTypeName(uint32_t writeType) override { - MYLOG("%s(%d)\n", __func__, writeType); + // MYLOG("%s() writeType:%d\n", __func__, writeType); switch (writeType) { @@ -1073,6 +1111,23 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR7_U: return "cr7_unsigned"; + case IL_FLAGWRITE_CR0_F: + return "cr0_float"; + case IL_FLAGWRITE_CR1_F: + return "cr1_float"; + case IL_FLAGWRITE_CR2_F: + return "cr2_float"; + case IL_FLAGWRITE_CR3_F: + return "cr3_floatt"; + case IL_FLAGWRITE_CR4_F: + return "cr4_float"; + case IL_FLAGWRITE_CR5_F: + return "cr5_float"; + case IL_FLAGWRITE_CR6_F: + return "cr6_float"; + case IL_FLAGWRITE_CR7_F: + return "cr7_float"; + case IL_FLAGWRITE_XER: return "xer"; case IL_FLAGWRITE_XER_CA: @@ -1125,12 +1180,13 @@ class PowerpcArchitecture: public Architecture virtual vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override { - MYLOG("%s(%d)\n", __func__, writeType); + // MYLOG("%s() writeType:%d\n", __func__, writeType); switch (writeType) { case IL_FLAGWRITE_CR0_S: case IL_FLAGWRITE_CR0_U: + case IL_FLAGWRITE_CR0_F: case IL_FLAGWRITE_MTCR0: case IL_FLAGWRITE_INVL0: return vector { @@ -1139,6 +1195,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR1_S: case IL_FLAGWRITE_CR1_U: + case IL_FLAGWRITE_CR1_F: case IL_FLAGWRITE_MTCR1: case IL_FLAGWRITE_INVL1: return vector { @@ -1147,6 +1204,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR2_S: case IL_FLAGWRITE_CR2_U: + case IL_FLAGWRITE_CR2_F: case IL_FLAGWRITE_MTCR2: case IL_FLAGWRITE_INVL2: return vector { @@ -1155,6 +1213,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR3_S: case IL_FLAGWRITE_CR3_U: + case IL_FLAGWRITE_CR3_F: case IL_FLAGWRITE_MTCR3: case IL_FLAGWRITE_INVL3: return vector { @@ -1163,6 +1222,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR4_S: case IL_FLAGWRITE_CR4_U: + case IL_FLAGWRITE_CR4_F: case IL_FLAGWRITE_MTCR4: case IL_FLAGWRITE_INVL4: return vector { @@ -1171,6 +1231,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR5_S: case IL_FLAGWRITE_CR5_U: + case IL_FLAGWRITE_CR5_F: case IL_FLAGWRITE_MTCR5: case IL_FLAGWRITE_INVL5: return vector { @@ -1179,6 +1240,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR6_S: case IL_FLAGWRITE_CR6_U: + case IL_FLAGWRITE_CR6_F: case IL_FLAGWRITE_MTCR6: case IL_FLAGWRITE_INVL6: return vector { @@ -1187,6 +1249,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAGWRITE_CR7_S: case IL_FLAGWRITE_CR7_U: + case IL_FLAGWRITE_CR7_F: case IL_FLAGWRITE_MTCR7: case IL_FLAGWRITE_INVL7: return vector { @@ -1217,27 +1280,19 @@ class PowerpcArchitecture: public Architecture } virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType) override { - switch (writeType) + // MYLOG("%s() writetype:%d", __func__, writeType); + uint32_t flag_out = 0; + + if ((writeType < IL_FLAGWRITE_CR0_S) || (writeType > IL_FLAGWRITE_CR7_F)) { - case IL_FLAGWRITE_CR0_S: return IL_FLAGCLASS_CR0_S; - case IL_FLAGWRITE_CR0_U: return IL_FLAGCLASS_CR0_U; - case IL_FLAGWRITE_CR1_S: return IL_FLAGCLASS_CR1_S; - case IL_FLAGWRITE_CR1_U: return IL_FLAGCLASS_CR1_U; - case IL_FLAGWRITE_CR2_S: return IL_FLAGCLASS_CR2_S; - case IL_FLAGWRITE_CR2_U: return IL_FLAGCLASS_CR2_U; - case IL_FLAGWRITE_CR3_S: return IL_FLAGCLASS_CR3_S; - case IL_FLAGWRITE_CR3_U: return IL_FLAGCLASS_CR3_U; - case IL_FLAGWRITE_CR4_S: return IL_FLAGCLASS_CR4_S; - case IL_FLAGWRITE_CR4_U: return IL_FLAGCLASS_CR4_U; - case IL_FLAGWRITE_CR5_S: return IL_FLAGCLASS_CR5_S; - case IL_FLAGWRITE_CR5_U: return IL_FLAGCLASS_CR5_U; - case IL_FLAGWRITE_CR6_S: return IL_FLAGCLASS_CR6_S; - case IL_FLAGWRITE_CR6_U: return IL_FLAGCLASS_CR6_U; - case IL_FLAGWRITE_CR7_S: return IL_FLAGCLASS_CR7_S; - case IL_FLAGWRITE_CR7_U: return IL_FLAGCLASS_CR7_U; + flag_out = IL_FLAGCLASS_NONE; } - - return IL_FLAGCLASS_NONE; + else + { + flag_out = IL_FLAGCLASS_CR0_S + (writeType - IL_FLAGWRITE_CR0_S); + } + + return flag_out; } /* @@ -1253,6 +1308,9 @@ class PowerpcArchitecture: public Architecture IL_FLAGCLASS_CR0_U, IL_FLAGCLASS_CR1_U, IL_FLAGCLASS_CR2_U, IL_FLAGCLASS_CR3_U, IL_FLAGCLASS_CR4_U, IL_FLAGCLASS_CR5_U, IL_FLAGCLASS_CR6_U, IL_FLAGCLASS_CR7_U, + + IL_FLAGCLASS_CR0_F, IL_FLAGCLASS_CR1_F, IL_FLAGCLASS_CR2_F, IL_FLAGCLASS_CR3_F, + IL_FLAGCLASS_CR4_F, IL_FLAGCLASS_CR5_F, IL_FLAGCLASS_CR6_F, IL_FLAGCLASS_CR7_F, }; } @@ -1318,7 +1376,9 @@ class PowerpcArchitecture: public Architecture virtual std::map GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override { - uint32_t flagClassBase = IL_FLAGCLASS_CR0_S + ((semGroup / 10) * 2); + // MYLOG("%s() semgroup:%d", __func__, semGroup); + + uint32_t flagClassBase = IL_FLAGCLASS_CR0_S + ((semGroup / 10) * PPC_SUF_SZ); uint32_t groupType = semGroup % 10; switch (groupType) @@ -1326,32 +1386,38 @@ class PowerpcArchitecture: public Architecture case IL_FLAGGROUP_CR0_LT: return map { {flagClassBase , LLFC_SLT}, - {flagClassBase + 1, LLFC_ULT} + {flagClassBase + PPC_SUF_U, LLFC_ULT}, + {flagClassBase + PPC_SUF_F, LLFC_FLT}, }; case IL_FLAGGROUP_CR0_LE: return map { {flagClassBase , LLFC_SLE}, - {flagClassBase + 1, LLFC_ULE} + {flagClassBase + PPC_SUF_U, LLFC_ULE}, + {flagClassBase + PPC_SUF_F, LLFC_FLE} }; case IL_FLAGGROUP_CR0_GT: return map { {flagClassBase , LLFC_SGT}, - {flagClassBase + 1, LLFC_UGT} + {flagClassBase + PPC_SUF_U, LLFC_UGT}, + {flagClassBase + PPC_SUF_F, LLFC_FGT} }; case IL_FLAGGROUP_CR0_GE: return map { {flagClassBase , LLFC_SGE}, - {flagClassBase + 1, LLFC_UGE} + {flagClassBase + PPC_SUF_U, LLFC_UGE}, + {flagClassBase + PPC_SUF_F, LLFC_FGE} }; case IL_FLAGGROUP_CR0_EQ: return map { {flagClassBase , LLFC_E}, - {flagClassBase + 1, LLFC_E} + {flagClassBase + PPC_SUF_U, LLFC_E}, + {flagClassBase + PPC_SUF_F, LLFC_FE} }; case IL_FLAGGROUP_CR0_NE: return map { {flagClassBase , LLFC_NE}, - {flagClassBase + 1, LLFC_NE} + {flagClassBase + PPC_SUF_U, LLFC_NE}, + {flagClassBase + PPC_SUF_F, LLFC_FNE} }; default: return map(); @@ -1364,22 +1430,11 @@ class PowerpcArchitecture: public Architecture virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass) override { - MYLOG("%s(%d)\n", __func__, flag); + // MYLOG("%s() flag:%d, semclass:%d\n", __func__, flag, semClass); - bool signedClass = true; + ppc_suf suf = (ppc_suf)0; - switch (semClass) - { - case IL_FLAGCLASS_CR0_U: - case IL_FLAGCLASS_CR1_U: - case IL_FLAGCLASS_CR2_U: - case IL_FLAGCLASS_CR3_U: - case IL_FLAGCLASS_CR4_U: - case IL_FLAGCLASS_CR5_U: - case IL_FLAGCLASS_CR6_U: - case IL_FLAGCLASS_CR7_U: - signedClass = false; - } + suf = (ppc_suf)((semClass - 1) % PPC_SUF_SZ); switch (flag) { @@ -1391,7 +1446,7 @@ class PowerpcArchitecture: public Architecture case IL_FLAG_LT_5: case IL_FLAG_LT_6: case IL_FLAG_LT_7: - return signedClass ? NegativeSignFlagRole : SpecialFlagRole; + return (suf == PPC_SUF_S) ? NegativeSignFlagRole : SpecialFlagRole; case IL_FLAG_GT: case IL_FLAG_GT_1: case IL_FLAG_GT_2: @@ -1434,24 +1489,30 @@ class PowerpcArchitecture: public Architecture */ virtual vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t) override { - MYLOG("%s(%d)\n", __func__, cond); + // MYLOG("%s() cond:%d\n", __func__, cond); switch (cond) { case LLFC_E: /* equal */ case LLFC_NE: /* not equal */ + case LLFC_FE: + case LLFC_FNE: return vector{ IL_FLAG_EQ }; case LLFC_ULT: /* (unsigned) less than == LT */ case LLFC_SLT: /* (signed) less than == LT */ case LLFC_SGE: /* (signed) greater-or-equal == !LT */ case LLFC_UGE: /* (unsigned) greater-or-equal == !LT */ + case LLFC_FLT: + case LLFC_FGE: return vector{ IL_FLAG_LT }; case LLFC_SGT: /* (signed) greater-than == GT */ case LLFC_UGT: /* (unsigned) greater-than == GT */ case LLFC_ULE: /* (unsigned) less-or-equal == !GT */ case LLFC_SLE: /* (signed) lesser-or-equal == !GT */ + case LLFC_FGT: + case LLFC_FLE: return vector{ IL_FLAG_GT }; case LLFC_NEG: @@ -1484,7 +1545,7 @@ class PowerpcArchitecture: public Architecture virtual vector GetFullWidthRegisters() override { - MYLOG("%s()\n", __func__); + // MYLOG("%s()\n", __func__); return vector{ PPC_REG_R0, PPC_REG_R1, PPC_REG_R2, PPC_REG_R3, PPC_REG_R4, PPC_REG_R5, PPC_REG_R6, PPC_REG_R7, @@ -1528,9 +1589,19 @@ class PowerpcArchitecture: public Architecture PPC_REG_VS32, PPC_REG_VS33, PPC_REG_VS34, PPC_REG_VS35, PPC_REG_VS36, PPC_REG_VS37, PPC_REG_VS38, PPC_REG_VS39, PPC_REG_VS40, PPC_REG_VS41, PPC_REG_VS42, PPC_REG_VS43, PPC_REG_VS44, PPC_REG_VS45, PPC_REG_VS46, PPC_REG_VS47, PPC_REG_VS48, PPC_REG_VS49, PPC_REG_VS50, PPC_REG_VS51, PPC_REG_VS52, PPC_REG_VS53, PPC_REG_VS54, PPC_REG_VS55, - PPC_REG_VS56, PPC_REG_VS57, PPC_REG_VS58, PPC_REG_VS59, PPC_REG_VS60, PPC_REG_VS61, PPC_REG_VS62, PPC_REG_VS63 + PPC_REG_VS56, PPC_REG_VS57, PPC_REG_VS58, PPC_REG_VS59, PPC_REG_VS60, PPC_REG_VS61, PPC_REG_VS62, PPC_REG_VS63, }; + vector gqrarray = { + PPC_REG_BN_GQR0, PPC_REG_BN_GQR1, PPC_REG_BN_GQR2, PPC_REG_BN_GQR3, + PPC_REG_BN_GQR4, PPC_REG_BN_GQR5, PPC_REG_BN_GQR6, PPC_REG_BN_GQR7}; + + + if ((cs_mode_local & CS_MODE_PS) != 0) + { + result.insert(result.end(), gqrarray.begin(), gqrarray.end()); + } + return result; } @@ -1562,72 +1633,72 @@ class PowerpcArchitecture: public Architecture case PPC_REG_CR5: return RegisterInfo(PPC_REG_CR5, 0, 4); case PPC_REG_CR6: return RegisterInfo(PPC_REG_CR6, 0, 4); case PPC_REG_CR7: return RegisterInfo(PPC_REG_CR7, 0, 4); - case PPC_REG_CTR: return RegisterInfo(PPC_REG_CTR, 0, 4); - case PPC_REG_F0: return RegisterInfo(PPC_REG_F0, 0, 4); - case PPC_REG_F1: return RegisterInfo(PPC_REG_F1, 0, 4); - case PPC_REG_F2: return RegisterInfo(PPC_REG_F2, 0, 4); - case PPC_REG_F3: return RegisterInfo(PPC_REG_F3, 0, 4); - case PPC_REG_F4: return RegisterInfo(PPC_REG_F4, 0, 4); - case PPC_REG_F5: return RegisterInfo(PPC_REG_F5, 0, 4); - case PPC_REG_F6: return RegisterInfo(PPC_REG_F6, 0, 4); - case PPC_REG_F7: return RegisterInfo(PPC_REG_F7, 0, 4); - case PPC_REG_F8: return RegisterInfo(PPC_REG_F8, 0, 4); - case PPC_REG_F9: return RegisterInfo(PPC_REG_F9, 0, 4); - case PPC_REG_F10: return RegisterInfo(PPC_REG_F10, 0, 4); - case PPC_REG_F11: return RegisterInfo(PPC_REG_F11, 0, 4); - case PPC_REG_F12: return RegisterInfo(PPC_REG_F12, 0, 4); - case PPC_REG_F13: return RegisterInfo(PPC_REG_F13, 0, 4); - case PPC_REG_F14: return RegisterInfo(PPC_REG_F14, 0, 4); - case PPC_REG_F15: return RegisterInfo(PPC_REG_F15, 0, 4); - case PPC_REG_F16: return RegisterInfo(PPC_REG_F16, 0, 4); - case PPC_REG_F17: return RegisterInfo(PPC_REG_F17, 0, 4); - case PPC_REG_F18: return RegisterInfo(PPC_REG_F18, 0, 4); - case PPC_REG_F19: return RegisterInfo(PPC_REG_F19, 0, 4); - case PPC_REG_F20: return RegisterInfo(PPC_REG_F20, 0, 4); - case PPC_REG_F21: return RegisterInfo(PPC_REG_F21, 0, 4); - case PPC_REG_F22: return RegisterInfo(PPC_REG_F22, 0, 4); - case PPC_REG_F23: return RegisterInfo(PPC_REG_F23, 0, 4); - case PPC_REG_F24: return RegisterInfo(PPC_REG_F24, 0, 4); - case PPC_REG_F25: return RegisterInfo(PPC_REG_F25, 0, 4); - case PPC_REG_F26: return RegisterInfo(PPC_REG_F26, 0, 4); - case PPC_REG_F27: return RegisterInfo(PPC_REG_F27, 0, 4); - case PPC_REG_F28: return RegisterInfo(PPC_REG_F28, 0, 4); - case PPC_REG_F29: return RegisterInfo(PPC_REG_F29, 0, 4); - case PPC_REG_F30: return RegisterInfo(PPC_REG_F30, 0, 4); - case PPC_REG_F31: return RegisterInfo(PPC_REG_F31, 0, 4); - case PPC_REG_LR: return RegisterInfo(PPC_REG_LR, 0, 4); - case PPC_REG_R0: return RegisterInfo(PPC_REG_R0, 0, 4); - case PPC_REG_R1: return RegisterInfo(PPC_REG_R1, 0, 4); - case PPC_REG_R2: return RegisterInfo(PPC_REG_R2, 0, 4); - case PPC_REG_R3: return RegisterInfo(PPC_REG_R3, 0, 4); - case PPC_REG_R4: return RegisterInfo(PPC_REG_R4, 0, 4); - case PPC_REG_R5: return RegisterInfo(PPC_REG_R5, 0, 4); - case PPC_REG_R6: return RegisterInfo(PPC_REG_R6, 0, 4); - case PPC_REG_R7: return RegisterInfo(PPC_REG_R7, 0, 4); - case PPC_REG_R8: return RegisterInfo(PPC_REG_R8, 0, 4); - case PPC_REG_R9: return RegisterInfo(PPC_REG_R9, 0, 4); - case PPC_REG_R10: return RegisterInfo(PPC_REG_R10, 0, 4); - case PPC_REG_R11: return RegisterInfo(PPC_REG_R11, 0, 4); - case PPC_REG_R12: return RegisterInfo(PPC_REG_R12, 0, 4); - case PPC_REG_R13: return RegisterInfo(PPC_REG_R13, 0, 4); - case PPC_REG_R14: return RegisterInfo(PPC_REG_R14, 0, 4); - case PPC_REG_R15: return RegisterInfo(PPC_REG_R15, 0, 4); - case PPC_REG_R16: return RegisterInfo(PPC_REG_R16, 0, 4); - case PPC_REG_R17: return RegisterInfo(PPC_REG_R17, 0, 4); - case PPC_REG_R18: return RegisterInfo(PPC_REG_R18, 0, 4); - case PPC_REG_R19: return RegisterInfo(PPC_REG_R19, 0, 4); - case PPC_REG_R20: return RegisterInfo(PPC_REG_R20, 0, 4); - case PPC_REG_R21: return RegisterInfo(PPC_REG_R21, 0, 4); - case PPC_REG_R22: return RegisterInfo(PPC_REG_R22, 0, 4); - case PPC_REG_R23: return RegisterInfo(PPC_REG_R23, 0, 4); - case PPC_REG_R24: return RegisterInfo(PPC_REG_R24, 0, 4); - case PPC_REG_R25: return RegisterInfo(PPC_REG_R25, 0, 4); - case PPC_REG_R26: return RegisterInfo(PPC_REG_R26, 0, 4); - case PPC_REG_R27: return RegisterInfo(PPC_REG_R27, 0, 4); - case PPC_REG_R28: return RegisterInfo(PPC_REG_R28, 0, 4); - case PPC_REG_R29: return RegisterInfo(PPC_REG_R29, 0, 4); - case PPC_REG_R30: return RegisterInfo(PPC_REG_R30, 0, 4); - case PPC_REG_R31: return RegisterInfo(PPC_REG_R31, 0, 4); + case PPC_REG_CTR: return RegisterInfo(PPC_REG_CTR, 0, addressSize); + case PPC_REG_F0: return RegisterInfo(PPC_REG_F0, 0, 8); + case PPC_REG_F1: return RegisterInfo(PPC_REG_F1, 0, 8); + case PPC_REG_F2: return RegisterInfo(PPC_REG_F2, 0, 8); + case PPC_REG_F3: return RegisterInfo(PPC_REG_F3, 0, 8); + case PPC_REG_F4: return RegisterInfo(PPC_REG_F4, 0, 8); + case PPC_REG_F5: return RegisterInfo(PPC_REG_F5, 0, 8); + case PPC_REG_F6: return RegisterInfo(PPC_REG_F6, 0, 8); + case PPC_REG_F7: return RegisterInfo(PPC_REG_F7, 0, 8); + case PPC_REG_F8: return RegisterInfo(PPC_REG_F8, 0, 8); + case PPC_REG_F9: return RegisterInfo(PPC_REG_F9, 0, 8); + case PPC_REG_F10: return RegisterInfo(PPC_REG_F10, 0, 8); + case PPC_REG_F11: return RegisterInfo(PPC_REG_F11, 0, 8); + case PPC_REG_F12: return RegisterInfo(PPC_REG_F12, 0, 8); + case PPC_REG_F13: return RegisterInfo(PPC_REG_F13, 0, 8); + case PPC_REG_F14: return RegisterInfo(PPC_REG_F14, 0, 8); + case PPC_REG_F15: return RegisterInfo(PPC_REG_F15, 0, 8); + case PPC_REG_F16: return RegisterInfo(PPC_REG_F16, 0, 8); + case PPC_REG_F17: return RegisterInfo(PPC_REG_F17, 0, 8); + case PPC_REG_F18: return RegisterInfo(PPC_REG_F18, 0, 8); + case PPC_REG_F19: return RegisterInfo(PPC_REG_F19, 0, 8); + case PPC_REG_F20: return RegisterInfo(PPC_REG_F20, 0, 8); + case PPC_REG_F21: return RegisterInfo(PPC_REG_F21, 0, 8); + case PPC_REG_F22: return RegisterInfo(PPC_REG_F22, 0, 8); + case PPC_REG_F23: return RegisterInfo(PPC_REG_F23, 0, 8); + case PPC_REG_F24: return RegisterInfo(PPC_REG_F24, 0, 8); + case PPC_REG_F25: return RegisterInfo(PPC_REG_F25, 0, 8); + case PPC_REG_F26: return RegisterInfo(PPC_REG_F26, 0, 8); + case PPC_REG_F27: return RegisterInfo(PPC_REG_F27, 0, 8); + case PPC_REG_F28: return RegisterInfo(PPC_REG_F28, 0, 8); + case PPC_REG_F29: return RegisterInfo(PPC_REG_F29, 0, 8); + case PPC_REG_F30: return RegisterInfo(PPC_REG_F30, 0, 8); + case PPC_REG_F31: return RegisterInfo(PPC_REG_F31, 0, 8); + case PPC_REG_LR: return RegisterInfo(PPC_REG_LR, 0, addressSize); + case PPC_REG_R0: return RegisterInfo(PPC_REG_R0, 0, addressSize); + case PPC_REG_R1: return RegisterInfo(PPC_REG_R1, 0, addressSize); + case PPC_REG_R2: return RegisterInfo(PPC_REG_R2, 0, addressSize); + case PPC_REG_R3: return RegisterInfo(PPC_REG_R3, 0, addressSize); + case PPC_REG_R4: return RegisterInfo(PPC_REG_R4, 0, addressSize); + case PPC_REG_R5: return RegisterInfo(PPC_REG_R5, 0, addressSize); + case PPC_REG_R6: return RegisterInfo(PPC_REG_R6, 0, addressSize); + case PPC_REG_R7: return RegisterInfo(PPC_REG_R7, 0, addressSize); + case PPC_REG_R8: return RegisterInfo(PPC_REG_R8, 0, addressSize); + case PPC_REG_R9: return RegisterInfo(PPC_REG_R9, 0, addressSize); + case PPC_REG_R10: return RegisterInfo(PPC_REG_R10, 0, addressSize); + case PPC_REG_R11: return RegisterInfo(PPC_REG_R11, 0, addressSize); + case PPC_REG_R12: return RegisterInfo(PPC_REG_R12, 0, addressSize); + case PPC_REG_R13: return RegisterInfo(PPC_REG_R13, 0, addressSize); + case PPC_REG_R14: return RegisterInfo(PPC_REG_R14, 0, addressSize); + case PPC_REG_R15: return RegisterInfo(PPC_REG_R15, 0, addressSize); + case PPC_REG_R16: return RegisterInfo(PPC_REG_R16, 0, addressSize); + case PPC_REG_R17: return RegisterInfo(PPC_REG_R17, 0, addressSize); + case PPC_REG_R18: return RegisterInfo(PPC_REG_R18, 0, addressSize); + case PPC_REG_R19: return RegisterInfo(PPC_REG_R19, 0, addressSize); + case PPC_REG_R20: return RegisterInfo(PPC_REG_R20, 0, addressSize); + case PPC_REG_R21: return RegisterInfo(PPC_REG_R21, 0, addressSize); + case PPC_REG_R22: return RegisterInfo(PPC_REG_R22, 0, addressSize); + case PPC_REG_R23: return RegisterInfo(PPC_REG_R23, 0, addressSize); + case PPC_REG_R24: return RegisterInfo(PPC_REG_R24, 0, addressSize); + case PPC_REG_R25: return RegisterInfo(PPC_REG_R25, 0, addressSize); + case PPC_REG_R26: return RegisterInfo(PPC_REG_R26, 0, addressSize); + case PPC_REG_R27: return RegisterInfo(PPC_REG_R27, 0, addressSize); + case PPC_REG_R28: return RegisterInfo(PPC_REG_R28, 0, addressSize); + case PPC_REG_R29: return RegisterInfo(PPC_REG_R29, 0, addressSize); + case PPC_REG_R30: return RegisterInfo(PPC_REG_R30, 0, addressSize); + case PPC_REG_R31: return RegisterInfo(PPC_REG_R31, 0, addressSize); case PPC_REG_V0: return RegisterInfo(PPC_REG_V0, 0, 4); case PPC_REG_V1: return RegisterInfo(PPC_REG_V1, 0, 4); case PPC_REG_V2: return RegisterInfo(PPC_REG_V2, 0, 4); @@ -1725,6 +1796,14 @@ class PowerpcArchitecture: public Architecture case PPC_REG_VS61: return RegisterInfo(PPC_REG_VS61, 0, 4); case PPC_REG_VS62: return RegisterInfo(PPC_REG_VS62, 0, 4); case PPC_REG_VS63: return RegisterInfo(PPC_REG_VS63, 0, 4); + case PPC_REG_BN_GQR0: return RegisterInfo(PPC_REG_BN_GQR0, 0, 4); + case PPC_REG_BN_GQR1: return RegisterInfo(PPC_REG_BN_GQR1, 0, 4); + case PPC_REG_BN_GQR2: return RegisterInfo(PPC_REG_BN_GQR2, 0, 4); + case PPC_REG_BN_GQR3: return RegisterInfo(PPC_REG_BN_GQR3, 0, 4); + case PPC_REG_BN_GQR4: return RegisterInfo(PPC_REG_BN_GQR4, 0, 4); + case PPC_REG_BN_GQR5: return RegisterInfo(PPC_REG_BN_GQR5, 0, 4); + case PPC_REG_BN_GQR6: return RegisterInfo(PPC_REG_BN_GQR6, 0, 4); + case PPC_REG_BN_GQR7: return RegisterInfo(PPC_REG_BN_GQR7, 0, 4); default: //LogError("%s(%d == \"%s\") invalid argument", __func__, // regId, powerpc_reg_to_str(regId)); @@ -2475,6 +2554,15 @@ extern "C" Architecture* ppc = new PowerpcArchitecture("ppc", BigEndian); Architecture::Register(ppc); + Architecture* ppc_qpx = new PowerpcArchitecture("ppc_qpx", BigEndian, 4, CS_MODE_QPX); + Architecture::Register(ppc_qpx); + + Architecture* ppc_spe = new PowerpcArchitecture("ppc_spe", BigEndian, 4, CS_MODE_SPE); + Architecture::Register(ppc_spe); + + Architecture* ppc_ps = new PowerpcArchitecture("ppc_ps", BigEndian, 4, CS_MODE_PS); + Architecture::Register(ppc_ps); + Architecture* ppc64 = new PowerpcArchitecture("ppc64", BigEndian, 8); Architecture::Register(ppc64); @@ -2489,10 +2577,19 @@ extern "C" conv = new PpcSvr4CallingConvention(ppc); ppc->RegisterCallingConvention(conv); ppc->SetDefaultCallingConvention(conv); + ppc_qpx->RegisterCallingConvention(conv); + ppc_qpx->SetDefaultCallingConvention(conv); + ppc_spe->RegisterCallingConvention(conv); + ppc_spe->SetDefaultCallingConvention(conv); + ppc_ps->RegisterCallingConvention(conv); + ppc_ps->SetDefaultCallingConvention(conv); ppc64->RegisterCallingConvention(conv); ppc64->SetDefaultCallingConvention(conv); conv = new PpcLinuxSyscallCallingConvention(ppc); ppc->RegisterCallingConvention(conv); + ppc_qpx->RegisterCallingConvention(conv); + ppc_spe->RegisterCallingConvention(conv); + ppc_ps->RegisterCallingConvention(conv); ppc64->RegisterCallingConvention(conv); conv = new PpcSvr4CallingConvention(ppc_le); @@ -2506,9 +2603,15 @@ extern "C" /* function recognizer */ ppc->RegisterFunctionRecognizer(new PpcImportedFunctionRecognizer()); + ppc_qpx->RegisterFunctionRecognizer(new PpcImportedFunctionRecognizer()); + ppc_spe->RegisterFunctionRecognizer(new PpcImportedFunctionRecognizer()); + ppc_ps->RegisterFunctionRecognizer(new PpcImportedFunctionRecognizer()); ppc_le->RegisterFunctionRecognizer(new PpcImportedFunctionRecognizer()); ppc->RegisterRelocationHandler("ELF", new PpcElfRelocationHandler()); + ppc_qpx->RegisterRelocationHandler("ELF", new PpcElfRelocationHandler()); + ppc_spe->RegisterRelocationHandler("ELF", new PpcElfRelocationHandler()); + ppc_ps->RegisterRelocationHandler("ELF", new PpcElfRelocationHandler()); ppc_le->RegisterRelocationHandler("ELF", new PpcElfRelocationHandler()); ppc_le->RegisterRelocationHandler("Mach-O", new PpcMachoRelocationHandler()); /* call the STATIC RegisterArchitecture with "Mach-O" diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 66e40d32f4..2a421971da 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -12,14 +12,158 @@ architecture plugin picture. //#define MYLOG BinaryNinja::LogDebug #include "disassembler.h" +#include "util.h" /* have to do this... while options can be toggled after initialization (thru cs_option(), the modes cannot, and endianness is considered a mode) */ thread_local csh handle_lil = 0; thread_local csh handle_big = 0; +int DoesQualifyForLocalDisassembly(const uint8_t *data, bool bigendian) +{ + uint32_t insword = *(uint32_t *)data; + int result = PPC_INS_INVALID; + uint32_t tmp = 0; + + if(bigendian == true) + { + insword = bswap32(insword); + } + + // 111111xxx00xxxxxxxxxx00001000000 <- fcmpo + tmp = insword & 0xFC6007FF; + if (tmp==0xFC000040) + result = PPC_INS_BN_FCMPO; + // 111100xxxxxxxxxxxxxxx00111010xxx <- xxpermr + if((insword & 0xFC0007F8) == 0xF00001D0) + result = PPC_INS_BN_XXPERMR; + + return result; +} + +void ppc_fcmpo(uint32_t insword, decomp_result *res) +{ + unsigned regtmp = 0; + + // 111111AAA00BBBBBCCCCC00001000000 "fcmpo crA,fB,fC" + regtmp = PPC_REG_CR0 + ((insword >> 23) & 7); + res->detail.ppc.operands[0].reg = (ppc_reg)(regtmp); + res->detail.ppc.operands[0].type = PPC_OP_REG; + + regtmp = PPC_REG_F0 + ((insword >> 16) & 31); + res->detail.ppc.operands[1].reg = (ppc_reg)(regtmp); + res->detail.ppc.operands[1].type = PPC_OP_REG; + + regtmp = PPC_REG_F0 + ((insword >> 11) & 31); + res->detail.ppc.operands[2].reg = (ppc_reg)(regtmp); + res->detail.ppc.operands[2].type = PPC_OP_REG; + + +#ifdef FORCE_TEST + SStream ss; + struct cs_struct* handle = 0; + struct MCInst tempmc = {0}; + char* first_space = 0; + + // SStream_Init(&ss); + ss.index = 0; + ss.buffer[0] = '\0'; + regtmp = PPC_REG_CR0 + ((insword >> 23) & 7); + tempmc.Operands[0].MachineOperandType = MCOperand::kRegister; + tempmc.Operands[0].Kind = 1; + tempmc.Operands[0].RegVal = regtmp; + regtmp = PPC_REG_F0 + ((insword >> 16) & 31); + tempmc.Operands[1].MachineOperandType = MCOperand::kRegister; + tempmc.Operands[1].Kind = 1; + tempmc.Operands[1].RegVal = regtmp; + regtmp = PPC_REG_F0 + ((insword >> 11) & 31); + tempmc.Operands[2].Kind = 1; + tempmc.Operands[2].MachineOperandType = MCOperand::kRegister; + tempmc.Operands[2].RegVal = regtmp; + + // temporarily set this so that print processing succeeds + res->insn.id = PPC_INS_FCMPU; + + if (handle_big != 0) + { + handle = (struct cs_struct*)handle_big; + } + else if (handle_lil != 0) + { + handle = (struct cs_struct*)handle_lil; + } + +#define PPC_FCMPUS 804 + + tempmc.csh = handle; + tempmc.Opcode = PPC_FCMPUS; + tempmc.flat_insn = &res->insn; + tempmc.flat_insn->detail = &res->detail; + + if (handle != 0) + { + handle->printer(&tempmc, &ss, handle->printer_info); + } + + // replace the 'fcmpu' with 'fcmpo' + first_space = strchr(ss.buffer, ' '); + strncpy(res->insn.op_str, first_space + 1, sizeof(res->insn.op_str)); +#endif + + strncpy(res->insn.mnemonic, "fcmpo", sizeof(res->insn.mnemonic)); + + // reset this to the target value + res->insn.id = PPC_INS_BN_FCMPO; + res->detail.ppc.op_count = 3; +} + +void ppc_xxpermr(uint32_t insword, decomp_result *res) +{ + // 111100AAAAABBBBBCCCCC00011010BCA "xxpermr vsA,vsB,vsC" + int a = ((insword & 0x3E00000)>>21)|((insword & 0x1)<<5); + int b = ((insword & 0x1F0000)>>16)|((insword & 0x4)<<3); + int c = ((insword & 0xF800)>>11)|((insword & 0x2)<<4); + + res->detail.ppc.operands[0].reg = (ppc_reg)(PPC_REG_VS0 + a); + res->detail.ppc.operands[0].type = PPC_OP_REG; + res->detail.ppc.operands[1].reg = (ppc_reg)(PPC_REG_VS0 + b); + res->detail.ppc.operands[1].type = PPC_OP_REG; + res->detail.ppc.operands[2].reg = (ppc_reg)(PPC_REG_VS0 + c); + res->detail.ppc.operands[2].type = PPC_OP_REG; + + res->insn.id = PPC_INS_BN_XXPERMR; + res->detail.ppc.op_count = 3; + strncpy(res->insn.mnemonic, "xxpermr", sizeof(res->insn.mnemonic)); +} + +bool PerformLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, decomp_result* res, bool bigendian) +{ + uint32_t local_op = 0; + uint32_t insword = *(uint32_t *)data; + + if(bigendian == true) + { + insword = bswap32(insword); + } + + local_op = DoesQualifyForLocalDisassembly(data, bigendian); + + switch(local_op) + { + case PPC_INS_BN_FCMPO: + ppc_fcmpo(insword, res); + break; + case PPC_INS_BN_XXPERMR: + ppc_xxpermr(insword, res); + break; + default: + return false; + } + return true; +} + extern "C" int -powerpc_init(void) +powerpc_init(int cs_mode_arg) { int rc = -1; @@ -31,12 +175,12 @@ powerpc_init(void) } /* initialize capstone handle */ - if(cs_open(CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, &handle_big) != CS_ERR_OK) { + if(cs_open(CS_ARCH_PPC, (cs_mode)((int)CS_MODE_BIG_ENDIAN | cs_mode_arg), &handle_big) != CS_ERR_OK) { MYLOG("ERROR: cs_open()\n"); goto cleanup; } - if(cs_open(CS_ARCH_PPC, CS_MODE_LITTLE_ENDIAN, &handle_lil) != CS_ERR_OK) { + if(cs_open(CS_ARCH_PPC, (cs_mode)((int)CS_MODE_LITTLE_ENDIAN | cs_mode_arg), &handle_lil) != CS_ERR_OK) { MYLOG("ERROR: cs_open()\n"); goto cleanup; } @@ -68,14 +212,14 @@ powerpc_release(void) } extern "C" int -powerpc_decompose(const uint8_t *data, int size, uint32_t addr, bool lil_end, - struct decomp_result *res, bool is_64bit) +powerpc_decompose(const uint8_t *data, int size, uint64_t addr, bool lil_end, + struct decomp_result *res, bool is_64bit, int cs_mode_arg) { int rc = -1; res->status = STATUS_ERROR_UNSPEC; if(!handle_lil) { - powerpc_init(); + powerpc_init(cs_mode_arg); } //typedef struct cs_insn { @@ -120,6 +264,7 @@ powerpc_decompose(const uint8_t *data, int size, uint32_t addr, bool lil_end, // } cs_ppc_op; csh handle; + struct cs_struct *hand_tmp = 0; cs_insn *insn = 0; /* instruction information cs_disasm() will allocate array of cs_insn here */ @@ -129,6 +274,9 @@ powerpc_decompose(const uint8_t *data, int size, uint32_t addr, bool lil_end, if(lil_end) handle = handle_lil; res->handle = handle; + hand_tmp = (struct cs_struct *)handle; + hand_tmp->mode = (cs_mode)((int)hand_tmp->mode | cs_mode_arg); + /* call */ size_t n = cs_disasm(handle, data, size, addr, 1, &insn); if(n != 1) { @@ -173,11 +321,21 @@ powerpc_disassemble(struct decomp_result *res, char *buf, size_t len) return rc; } +static const char* const gqr_array[] = {"gqr0", "gqr1", "gqr2", "gqr3", "gqr4", "gqr5", "gqr6", "gqr7"}; + extern "C" const char * -powerpc_reg_to_str(uint32_t rid) +powerpc_reg_to_str(uint32_t rid, int cs_mode_arg) { + if ((cs_mode_arg & CS_MODE_PS) != 0) + { + if ((rid >= PPC_REG_BN_GQR0) && (rid < PPC_REG_BN_ENDING)) + { + return gqr_array[rid - PPC_REG_BN_GQR0]; + } + } + if(!handle_lil) { - powerpc_init(); + powerpc_init(cs_mode_arg); } return cs_reg_name(handle_lil, rid); diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index d586a51709..d4679ae0c8 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -23,8 +23,17 @@ Then some helpers if you need them: /* capstone stuff /usr/local/include/capstone */ #include "capstone/capstone.h" +#include "capstone/cs_priv.h" #include "capstone/ppc.h" +#define PPC_CRX_REG_MASK 0x1ff +#define PPC_CRX_FLOAT_MASK 0x200 + +// TODO this is some sorta capstone baddy, where xori is showing as xnop's +// opcode. Maybe pulling capstone will fix, need for xori to correctly +// lift. Capstone is posting that XORI is 1452, though that is XNOP +#define PPC_BN_INS_XORI PPC_INS_XNOP + //***************************************************************************** // structs and types //***************************************************************************** @@ -32,6 +41,23 @@ enum ppc_status_t { STATUS_ERROR_UNSPEC=-1, STATUS_SUCCESS=0, STATUS_UNDEF_INSTR }; +typedef enum ppc_insn_bn { + PPC_INS_BN_FCMPO = PPC_INS_ENDING+1, + PPC_INS_BN_XXPERMR, + PPC_INS_BN_ENDING +} ppc_insn_bn; + +typedef enum ppc_reg_bn { + PPC_REG_BN_GQR0 = PPC_REG_ENDING+1, + PPC_REG_BN_GQR1, + PPC_REG_BN_GQR2, + PPC_REG_BN_GQR3, + PPC_REG_BN_GQR4, + PPC_REG_BN_GQR5, + PPC_REG_BN_GQR6, + PPC_REG_BN_GQR7, + PPC_REG_BN_ENDING +} ppc_reg_bn; /* operand type */ enum operand_type_t { REG, VAL, LABEL }; @@ -59,11 +85,14 @@ struct decomp_result //***************************************************************************** // function prototypes //***************************************************************************** -extern "C" int powerpc_init(void); +int DoesQualifyForLocalDisassembly(const uint8_t *data, bool bigendian); +bool PerformLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, decomp_result* res, bool bigendian); + +extern "C" int powerpc_init(int); extern "C" void powerpc_release(void); -extern "C" int powerpc_decompose(const uint8_t *data, int size, uint32_t addr, - bool lil_end, struct decomp_result *result, bool is_64bit); +extern "C" int powerpc_decompose(const uint8_t *data, int size, uint64_t addr, + bool lil_end, struct decomp_result *result, bool is_64bit, int cs_mode); extern "C" int powerpc_disassemble(struct decomp_result *, char *buf, size_t len); -extern "C" const char *powerpc_reg_to_str(uint32_t rid); +extern "C" const char *powerpc_reg_to_str(uint32_t rid, int cs_mode_arg); extern "C" const uint32_t powerpc_crx_to_reg(uint32_t rid); diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 4d074aa4f2..43a4706463 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1,3 +1,4 @@ +#include "lowlevelilinstruction.h" #include #include "disassembler.h" @@ -21,7 +22,7 @@ using namespace BinaryNinja; #define OTI_GPR0_ZERO 2048 #define MYLOG(...) while(0); -//#define MYLOG BinaryNinja::LogDebug +// #define MYLOG BinaryNinja::LogWarn static uint32_t genMask(uint32_t mb, uint32_t me) { @@ -31,8 +32,12 @@ static uint32_t genMask(uint32_t mb, uint32_t me) return (mb <= me) ? (maskBegin & maskEnd) : (maskBegin | maskEnd); } +#define PPC_IL_OPTIONS_DEFAULT 0 +#define PPC_IL_EXTRA_DEFAULT 0 +#define RZF 4 + static ExprId operToIL(LowLevelILFunction &il, struct cs_ppc_op *op, - int options=0, uint64_t extra=0) + int options=PPC_IL_OPTIONS_DEFAULT, uint64_t extra=PPC_IL_EXTRA_DEFAULT, size_t regsz=4) { ExprId res; @@ -45,26 +50,26 @@ static ExprId operToIL(LowLevelILFunction &il, struct cs_ppc_op *op, case PPC_OP_REG: //MYLOG("case PPC_OP_REG returning reg %d\n", op->reg); if (options & OTI_GPR0_ZERO && op->reg == PPC_REG_R0) - res = il.Const(4, 0); + res = il.Const(regsz, 0); else - res = il.Register(4, op->reg); + res = il.Register(regsz, op->reg); break; case PPC_OP_IMM: /* the immediate is a constant pointer (eg: absolute address) */ if(options & OTI_IMM_CPTR) { - res = il.ConstPointer(4, op->imm); + res = il.ConstPointer(regsz, op->imm); } /* the immediate is a displacement (eg: relative addressing) */ else if(options & OTI_IMM_REL_CPTR) { - res = il.ConstPointer(4, op->imm + extra); + res = il.ConstPointer(regsz, op->imm + extra); } /* the immediate should be biased with given value */ else if(options & OTI_IMM_BIAS) { - res = il.Const(4, op->imm + extra); + res = il.Const(regsz, op->imm + extra); } /* the immediate is just a plain boring immediate */ else { - res = il.Const(4, op->imm); + res = il.Const(regsz, op->imm); } break; @@ -72,14 +77,14 @@ static ExprId operToIL(LowLevelILFunction &il, struct cs_ppc_op *op, //MYLOG("case PPC_OP_MEM returning regs (%d,%d)\n", op->mem.base, op->mem.disp); if (options & OTI_GPR0_ZERO && op->mem.base == PPC_REG_R0) - res = il.Const(4, 0); + res = il.Const(regsz, 0); else - res = il.Register(4, op->mem.base); + res = il.Register(regsz, op->mem.base); if(options & OTI_IMM_BIAS) - res = il.Add(4, res, il.Const(4, op->mem.disp + extra)); + res = il.Add(regsz, res, il.Const(4, op->mem.disp + extra)); else - res = il.Add(4, res, il.Const(4, op->mem.disp)); + res = il.Add(regsz, res, il.Const(4, op->mem.disp)); break; case PPC_OP_CRX: @@ -127,37 +132,47 @@ static ExprId operToIL(LowLevelILFunction &il, struct cs_ppc_op *op, return res; } +#define operToIL_a(il, op, regSz) operToIL(il, op, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, regSz) /* map PPC_REG_CRX to an IL flagwrite type (a named set of written flags */ int crxToFlagWriteType(int crx, bool signedComparison = true) { - /* when we have more flags... */ - switch(crx) + // MYLOG("%s() crx:%d", __func__, crx); + int flag_out = 0; + int crx_local = 0; + int crx_type = 0; + int crx_index = 0; + int suf = 0; + + crx_local = crx & PPC_CRX_REG_MASK; + crx_type = crx & PPC_CRX_FLOAT_MASK; + if ((crx_local < PPC_REG_CR0) || (crx_local > PPC_REG_CR7)) { - case PPC_REG_CR0: - return signedComparison ? IL_FLAGWRITE_CR0_S : IL_FLAGWRITE_CR0_U; - case PPC_REG_CR1: - return signedComparison ? IL_FLAGWRITE_CR1_S : IL_FLAGWRITE_CR1_U; - case PPC_REG_CR2: - return signedComparison ? IL_FLAGWRITE_CR2_S : IL_FLAGWRITE_CR2_U; - case PPC_REG_CR3: - return signedComparison ? IL_FLAGWRITE_CR3_S : IL_FLAGWRITE_CR3_U; - case PPC_REG_CR4: - return signedComparison ? IL_FLAGWRITE_CR4_S : IL_FLAGWRITE_CR4_U; - case PPC_REG_CR5: - return signedComparison ? IL_FLAGWRITE_CR5_S : IL_FLAGWRITE_CR5_U; - case PPC_REG_CR6: - return signedComparison ? IL_FLAGWRITE_CR6_S : IL_FLAGWRITE_CR6_U; - case PPC_REG_CR7: - return signedComparison ? IL_FLAGWRITE_CR7_S : IL_FLAGWRITE_CR7_U; - default: - return 0; + goto fail; + } + + crx_index = crx_local - PPC_REG_CR0; + + if (crx_type != 0) + { + suf = PPC_SUF_F; } + else if (signedComparison == false) + { + suf = PPC_SUF_U; + } + + /* when we have more flags... */ + flag_out = (crx_index * PPC_SUF_SZ) + IL_FLAGWRITE_CR0_S + suf; + +fail: + return flag_out; } static ExprId ExtractConditionClause(LowLevelILFunction& il, uint8_t crBit, bool negate = false) { + // MYLOG("%s() crbit:%x", __func__, crBit); uint32_t flagBase = (crBit / 4) * 10; switch (crBit & 3) @@ -182,7 +197,7 @@ static ExprId ExtractConditionClause(LowLevelILFunction& il, uint8_t crBit, bool } -static bool LiftConditionalBranch(LowLevelILFunction& il, uint8_t bo, uint8_t bi, BNLowLevelILLabel& takenLabel, BNLowLevelILLabel& falseLabel) +static bool LiftConditionalBranch(LowLevelILFunction& il, uint8_t bo, uint8_t bi, BNLowLevelILLabel& takenLabel, BNLowLevelILLabel& falseLabel, size_t addressSize_a=4) { bool testsCtr = !(bo & 4); bool testsCrBit = !(bo & 0x10); @@ -193,18 +208,18 @@ static bool LiftConditionalBranch(LowLevelILFunction& il, uint8_t bo, uint8_t bi ExprId cond, left, right; il.AddInstruction( - il.SetRegister(4, PPC_REG_CTR, - il.Sub(4, - il.Register(4, PPC_REG_CTR), - il.Const(4, 1)))); + il.SetRegister(addressSize_a, PPC_REG_CTR, + il.Sub(addressSize_a, + il.Register(addressSize_a, PPC_REG_CTR), + il.Const(addressSize_a, 1)))); - left = il.Register(4, PPC_REG_CTR); - right = il.Const(4, 0); + left = il.Register(addressSize_a, PPC_REG_CTR); + right = il.Const(addressSize_a, 0); if (bo & 2) - cond = il.CompareEqual(4, left, right); + cond = il.CompareEqual(addressSize_a, left, right); else - cond = il.CompareNotEqual(4, left, right); + cond = il.CompareNotEqual(addressSize_a, left, right); if (!testsCrBit) { @@ -227,31 +242,37 @@ static bool LiftConditionalBranch(LowLevelILFunction& il, uint8_t bo, uint8_t bi return isConditional; } - static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8_t* data, uint64_t addr, bool le) { + // MYLOG("%s() addr:0x%08llx\n", __func__, addr); uint32_t insn = *(const uint32_t *) data; + bool lk; + size_t addressSize_l = arch->GetAddressSize(); if (!le) + { insn = bswap32(insn); + } - bool lk = insn & 1; + lk = insn & 1; switch (insn >> 26) { - case 18: /* b (b, ba, bl, bla) */ + case PPC_INS_BCA: /* b (b, ba, bl, bla) */ { - uint32_t target = insn & 0x03fffffc; + uint64_t target = insn & 0x03fffffc; /* sign extend target */ - if ((target >> 25) & 1) - target |= 0xfc000000; + target = sign_extend(addressSize_l, target, 25); /* account for absolute addressing */ if (!(insn & 2)) - target += (uint32_t) addr; + { + target += addr; + ADDRMASK(addressSize_l, target); + } - BNLowLevelILLabel *label = il.GetLabelForAddress(arch, target); + BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target); if (label && !(lk && (target != (addr+4)))) { @@ -259,7 +280,9 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 * 'lk' bit behavior into account, but don't emit as a call */ if (lk) - il.AddInstruction(il.SetRegister(4, PPC_REG_LR, il.ConstPointer(4, addr + 4))); + { + il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_LR, il.ConstPointer(addressSize_l, addr + 4))); + } il.AddInstruction(il.Goto(*label)); } @@ -275,25 +298,29 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 break; } - case 16: /* bc */ + case PPC_INS_BA: /* bc */ { - uint32_t target = insn & 0xfffc; + uint64_t target = insn & 0xfffc; uint8_t bo = (insn >> 21) & 0x1f; uint8_t bi = (insn >> 16) & 0x1f; /* sign extend target */ - if ((target >> 15) & 1) - target |= 0xffff0000; + target = sign_extend(addressSize_l, target, 15); /* account for absolute addressing */ if (!(insn & 2)) - target += (uint32_t) addr; + { + target += addr; + ADDRMASK(addressSize_l, target); + } BNLowLevelILLabel *existingTakenLabel = il.GetLabelForAddress(arch, target); BNLowLevelILLabel *existingFalseLabel = il.GetLabelForAddress(arch, addr + 4); if (lk) - il.AddInstruction(il.SetRegister(4, PPC_REG_LR, il.ConstPointer(4, addr + 4))); + { + il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_LR, il.ConstPointer(addressSize_l, addr + 4))); + } LowLevelILLabel takenLabelManual, falseLabelManual; BNLowLevelILLabel* takenLabel = existingTakenLabel; @@ -305,31 +332,39 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 if (!falseLabel) falseLabel = &falseLabelManual; - bool wasConditionalBranch = LiftConditionalBranch(il, bo, bi, *takenLabel, *falseLabel); + bool wasConditionalBranch = LiftConditionalBranch(il, bo, bi, *takenLabel, *falseLabel, addressSize_l); if (wasConditionalBranch && !existingTakenLabel) + { il.MarkLabel(*takenLabel); + } if (!wasConditionalBranch && existingTakenLabel) + { il.AddInstruction(il.Goto(*takenLabel)); + } else if (target != addr + 4) { if (lk) { - il.AddInstruction(il.Call(il.ConstPointer(4, target))); + il.AddInstruction(il.Call(il.ConstPointer(addressSize_l, target))); if (wasConditionalBranch) + { il.AddInstruction(il.Goto(*falseLabel)); + } } else - il.AddInstruction(il.Jump(il.ConstPointer(4, target))); + il.AddInstruction(il.Jump(il.ConstPointer(addressSize_l, target))); } if (wasConditionalBranch && !existingFalseLabel) + { il.MarkLabel(*falseLabel); + } break; } - case 19: /* bcctr, bclr */ + case PPC_INS_BCCTR: /* bcctr, bclr */ { uint8_t bo = (insn >> 21) & 0x1f; uint8_t bi = (insn >> 16) & 0x1f; @@ -339,13 +374,13 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 switch ((insn >> 1) & 0x3ff) { case 16: - expr = il.Register(4, PPC_REG_LR); + expr = il.Register(addressSize_l, PPC_REG_LR); blr = true; break; case 528: if (!(bo & 4)) return false; - expr = il.Register(4, PPC_REG_CTR); + expr = il.Register(addressSize_l, PPC_REG_CTR); break; default: return false; @@ -359,7 +394,7 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 if (!falseLabel) falseLabel = &falseLabelManual; - bool wasConditionalBranch = LiftConditionalBranch(il, bo, bi, takenLabel, *falseLabel); + bool wasConditionalBranch = LiftConditionalBranch(il, bo, bi, takenLabel, *falseLabel, addressSize_l); if (wasConditionalBranch) il.MarkLabel(takenLabel); @@ -420,30 +455,75 @@ static ExprId ByteReverseRegister(LowLevelILFunction &il, uint32_t reg, size_t s } -static void ByteReversedLoad(LowLevelILFunction &il, struct cs_ppc* ppc, size_t size) +static void ByteReversedLoad(LowLevelILFunction &il, struct cs_ppc* ppc, size_t size, size_t addressSize_a=4) { - ExprId addr = operToIL(il, &ppc->operands[1], OTI_GPR0_ZERO); // (rA|0) - ExprId val = il.Load(size, il.Add(4, addr, operToIL(il, &ppc->operands[2]))); // [(rA|0) + (rB)] + ExprId addr = operToIL(il, &ppc->operands[1], OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_a); // (rA|0) + ExprId val = il.Load(size, il.Add(addressSize_a, addr, operToIL_a(il, &ppc->operands[2], addressSize_a))); // [(rA|0) + (rB)] - if (size < 4) - val = il.ZeroExtend(4, val); + if (size < addressSize_a) + { + val = il.ZeroExtend(addressSize_a, val); + } /* set reg immediately; this will cause xrefs to be sized correctly, * we'll use this as the scratch while we calculate the swapped value */ - il.AddInstruction(il.SetRegister(4, ppc->operands[0].reg, val)); // rD = [(rA|0) + (rB)] + il.AddInstruction(il.SetRegister(addressSize_a, ppc->operands[0].reg, val)); // rD = [(rA|0) + (rB)] ExprId swap = ByteReverseRegister(il, ppc->operands[0].reg, size); - il.AddInstruction(il.SetRegister(4, ppc->operands[0].reg, swap)); // rD = swap([(rA|0) + (rB)]) + il.AddInstruction(il.SetRegister(addressSize_a, ppc->operands[0].reg, swap)); // rD = swap([(rA|0) + (rB)]) } -static void ByteReversedStore(LowLevelILFunction &il, struct cs_ppc* ppc, size_t size) +static void ByteReversedStore(LowLevelILFunction &il, struct cs_ppc* ppc, size_t size, size_t addressSize_a=4) { - ExprId addr = operToIL(il, &ppc->operands[1], OTI_GPR0_ZERO); // (rA|0) - addr = il.Add(4, addr, operToIL(il, &ppc->operands[2])); // (rA|0) + (rB) + ExprId addr = operToIL(il, &ppc->operands[1], OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_a); // (rA|0) + addr = il.Add(addressSize_a, addr, operToIL_a(il, &ppc->operands[2], addressSize_a)); // (rA|0) + (rB) ExprId val = ByteReverseRegister(il, ppc->operands[0].reg, size); // rS = swap(rS) il.AddInstruction(il.Store(size, addr, val)); // [(rA|0) + (rB)] = swap(rS) } +static void loadstoreppcfs(LowLevelILFunction& il, + int load_store_sz, + cs_ppc_op* operand1, /* register that gets read/written */ + cs_ppc_op* operand2, /* location the read/write occurs */ + cs_ppc_op* operand3=0, + bool update=false + ) +{ + ExprId tmp; + const int addrsz = 4; + // assume single + if (!load_store_sz) + load_store_sz = 4; + + // operand1.reg = [operand2.reg + operand2.imm] + if (operand2->type == PPC_OP_MEM) + { + if (operand2->mem.disp == 0) + { + tmp = il.Register(4, operand2->mem.base); + } + else + { + tmp = il.Add(addrsz, il.Register(addrsz, operand2->mem.base), il.Const(addrsz, operand2->mem.disp)); + } + } + else if(operand2->type == PPC_OP_REG) + { + if ((operand3 != 0) && (operand3->type == PPC_OP_REG)) + { + tmp = il.Add(4, il.Register(addrsz, operand2->reg), il.Register(addrsz, operand3->reg)); + } + } + + il.AddInstruction(il.SetRegister(load_store_sz, operand1->reg, il.FloatConvert(load_store_sz, il.Operand(1, il.Load(load_store_sz, tmp))))); + + if (update == true) + { + tmp = il.SetRegister(4, operand2->reg, tmp); + il.AddInstruction(tmp); + } +} + /* returns TRUE - if this IL continues FALSE - if this IL terminates a block */ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, @@ -451,6 +531,23 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, { int i; bool rc = true; + struct cs_insn *insn = 0; + struct cs_detail *detail = 0; + struct cs_ppc *ppc = 0; + size_t addressSize_l = 0; + int extend_l = 0; + uint32_t rawInsn = *(const uint32_t *) data; + + // for ppc_ps + ppc_reg_bn gqr_l = (ppc_reg_bn)0; + int w_l = 0; + + addressSize_l = arch->GetAddressSize(); + if (!le) + { + rawInsn = bswap32(rawInsn); + } + /* bypass capstone path for *all* branching instructions; capstone * is too difficult to work with and is outright broken for some @@ -459,9 +556,9 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, if (LiftBranches(arch, il, data, addr, le)) return true; - struct cs_insn *insn = &(res->insn); - struct cs_detail *detail = &(res->detail); - struct cs_ppc *ppc = &(detail->ppc); + insn = &(res->insn); + detail = &(res->detail); + ppc = &(detail->ppc); /* There is a simplifying reduction available for: * rlwinm , , , , @@ -526,11 +623,11 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ADD: /* add */ REQUIRE2OPS ei0 = il.Add( - 4, - operToIL(il, oper1), - operToIL(il, oper2) + addressSize_l, + operToIL_a(il, oper1, addressSize_l), + operToIL_a(il, oper2, addressSize_l) ); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, (insn->id == PPC_INS_ADD && ppc->update_cr0) ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -539,13 +636,13 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ADDE: /* add, extended (+ carry flag) */ REQUIRE3OPS ei0 = il.AddCarry( - 4, - operToIL(il, oper1), - operToIL(il, oper2), + addressSize_l, + operToIL_a(il, oper1, addressSize_l), + operToIL_a(il, oper2, addressSize_l), il.Flag(IL_FLAG_XER_CA), IL_FLAGWRITE_XER_CA ); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -555,17 +652,17 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ADDZE: REQUIRE2OPS if (insn->id == PPC_INS_ADDME) - ei0 = il.Const(4, 0xffffffff); + ei0 = il.Const(addressSize_l, ADDRNEG1(addressSize_l)); else - ei0 = il.Const(4, 0); + ei0 = il.Const(addressSize_l, 0); ei0 = il.AddCarry( - 4, - operToIL(il, oper1), + addressSize_l, + operToIL_a(il, oper1, addressSize_l), ei0, il.Flag(IL_FLAG_XER_CA), IL_FLAGWRITE_XER_CA ); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -575,12 +672,12 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ADDIC: /* add immediate, carrying */ REQUIRE3OPS ei0 = il.Add( - 4, - operToIL(il, oper1), - operToIL(il, oper2), + addressSize_l, + operToIL_a(il, oper1, addressSize_l), + operToIL_a(il, oper2, addressSize_l), IL_FLAGWRITE_XER_CA ); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -590,24 +687,24 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ADDIS: /* add immediate, shifted */ REQUIRE2OPS if (insn->id == PPC_INS_ADDIS) - ei0 = il.Const(4, oper2->imm << 16); + ei0 = il.Const(addressSize_l, oper2->imm << 16); else - ei0 = il.Const(4, oper2->imm); + ei0 = il.Const(addressSize_l, oper2->imm); ei0 = il.Add( - 4, - operToIL(il, oper1, OTI_GPR0_ZERO), + addressSize_l, + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), ei0 ); - ei0 = il.SetRegister(4, oper0->reg, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); il.AddInstruction(ei0); break; case PPC_INS_LIS: /* load immediate, shifted */ REQUIRE2OPS ei0 = il.SetRegister( - 4, + addressSize_l, oper0->reg, - il.ConstPointer(4, oper1->imm << 16) + il.ConstPointer(addressSize_l, oper1->imm << 16) ); il.AddInstruction(ei0); break; @@ -615,20 +712,20 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LI: /* load immediate */ case PPC_INS_LA: /* load displacement */ REQUIRE2OPS - il.AddInstruction(il.SetRegister(4, oper0->reg, operToIL(il, oper1))); + il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, operToIL_a(il, oper1, addressSize_l))); break; case PPC_INS_AND: case PPC_INS_ANDC: // and [with complement] case PPC_INS_NAND: REQUIRE3OPS - ei0 = operToIL(il, oper2); + ei0 = operToIL_a(il, oper2, addressSize_l); if (insn->id == PPC_INS_ANDC) - ei0 = il.Not(4, ei0); - ei0 = il.And(4, operToIL(il, oper1), ei0); + ei0 = il.Not(addressSize_l, ei0); + ei0 = il.And(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); if (insn->id == PPC_INS_NAND) - ei0 = il.Not(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.Not(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -638,47 +735,50 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ANDI: REQUIRE3OPS if (insn->id == PPC_INS_ANDIS) - ei0 = il.Const(4, oper2->imm << 16); + ei0 = il.Const(addressSize_l, oper2->imm << 16); else - ei0 = il.Const(4, oper2->imm); - ei0 = il.And(4, operToIL(il, oper1), ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0, IL_FLAGWRITE_CR0_S); + ei0 = il.Const(addressSize_l, oper2->imm); + ei0 = il.And(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, IL_FLAGWRITE_CR0_S); il.AddInstruction(ei0); break; case PPC_INS_CMP: case PPC_INS_CMPW: /* compare (signed) word(32-bit) */ REQUIRE2OPS - ei0 = operToIL(il, oper2 ? oper1 : oper0); - ei1 = operToIL(il, oper2 ? oper2 : oper1); - ei2 = il.Sub(4, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); + ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); + ei1 = operToIL_a(il, oper2 ? oper2 : oper1, addressSize_l); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); il.AddInstruction(ei2); break; case PPC_INS_CMPL: case PPC_INS_CMPLW: /* compare logical(unsigned) word(32-bit) */ REQUIRE2OPS - ei0 = operToIL(il, oper2 ? oper1 : oper0); - ei1 = operToIL(il, oper2 ? oper2 : oper1); - ei2 = il.Sub(4, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0, false)); + ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); + ei1 = operToIL_a(il, oper2 ? oper2 : oper1, addressSize_l); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0, false)); il.AddInstruction(ei2); break; case PPC_INS_CMPI: case PPC_INS_CMPWI: /* compare (signed) word(32-bit) immediate */ + case PPC_INS_CMPDI: REQUIRE2OPS - ei0 = operToIL(il, oper2 ? oper1 : oper0); - ei1 = operToIL(il, oper2 ? oper2 : oper1, OTI_SEXT32_IMMS); - ei2 = il.Sub(4, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); + EXTOPTS(rawInsn, addressSize_l, extend_l); + ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); + ei1 = operToIL(il, oper2 ? oper2 : oper1, extend_l, PPC_IL_EXTRA_DEFAULT, addressSize_l); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); il.AddInstruction(ei2); break; case PPC_INS_CMPLI: case PPC_INS_CMPLWI: /* compare logical(unsigned) word(32-bit) immediate */ REQUIRE2OPS - ei0 = operToIL(il, oper2 ? oper1 : oper0); - ei1 = operToIL(il, oper2 ? oper2 : oper1, OTI_ZEXT32_IMMS); - ei2 = il.Sub(4, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0, false)); + EXTOPTZ(rawInsn, addressSize_l, extend_l); + ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); + ei1 = operToIL(il, oper2 ? oper2 : oper1, extend_l, PPC_IL_EXTRA_DEFAULT, addressSize_l); + ei2 = il.Sub(addressSize_l, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0, false)); il.AddInstruction(ei2); break; @@ -714,12 +814,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // il.AddInstruction(ei2); // break; - // case PPC_INS_FCMPU: - // REQUIRE3OPS - // ei0 = il.FloatSub(4, il.Unimplemented(), il.Unimplemented(), (oper0->reg - PPC_REG_CR0) + IL_FLAGWRITE_INVL0); - // il.AddInstruction(ei0); - // break; - case PPC_INS_CRAND: case PPC_INS_CRANDC: case PPC_INS_CRNAND: @@ -833,13 +927,17 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_EXTSB: case PPC_INS_EXTSH: REQUIRE2OPS - ei0 = il.Register(4, oper1->reg); + ei0 = il.Register(addressSize_l, oper1->reg); if (insn->id == PPC_INS_EXTSB) + { ei0 = il.LowPart(1, ei0); + } else + { ei0 = il.LowPart(2, ei0); - ei0 = il.SignExtend(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0, + } + ei0 = il.SignExtend(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -904,7 +1002,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, ei0 = il.SetRegister(4, i, // dest il.Load(4, // source - operToIL(il, oper1, OTI_IMM_BIAS, (i-(oper0->reg))*4) + operToIL(il, oper1, OTI_IMM_BIAS, (i-(oper0->reg))*4, addressSize_l) ) ); @@ -919,15 +1017,15 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LBZ: case PPC_INS_LBZU: REQUIRE2OPS - ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(1, ei0); // [d(rA)] - ei0 = il.ZeroExtend(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0); // rD = [d(rA)] + ei0 = il.ZeroExtend(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); // rD = [d(rA)] il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) if(insn->id == PPC_INS_LBZU) { - ei0 = il.SetRegister(4, oper1->mem.base, operToIL(il, oper1)); + ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -939,15 +1037,15 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LBZX: case PPC_INS_LBZUX: REQUIRE3OPS - ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 - ei0 = il.Load(1, il.Add(4, ei0, operToIL(il, oper2))); // [d(rA) + d(rB)] - ei0 = il.ZeroExtend(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0); // rD = [d(rA)] + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 + ei0 = il.Load(1, il.Add(addressSize_l, ei0, operToIL_a(il, oper2, addressSize_l))); // [d(rA) + d(rB)] + ei0 = il.ZeroExtend(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); // rD = [d(rA)] il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) if(insn->id == PPC_INS_LBZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) { - ei0 = il.SetRegister(4, oper1->reg, operToIL(il, oper1)); + ei0 = il.SetRegister(addressSize_l, oper1->reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -961,18 +1059,18 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LHA: case PPC_INS_LHAU: REQUIRE2OPS - ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(2, ei0); // [d(rA)] if(insn->id == PPC_INS_LHZ || insn->id == PPC_INS_LHZU) - ei0 = il.ZeroExtend(4, ei0); + ei0 = il.ZeroExtend(addressSize_l, ei0); else - ei0 = il.SignExtend(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0); // rD = [d(rA)] + ei0 = il.SignExtend(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); // rD = [d(rA)] il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) if(insn->id == PPC_INS_LHZU || insn->id == PPC_INS_LHAU) { - ei0 = il.SetRegister(4, oper1->mem.base, operToIL(il, oper1)); + ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -986,18 +1084,18 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LHAX: case PPC_INS_LHAUX: REQUIRE3OPS - ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 - ei0 = il.Load(2, il.Add(4, ei0, operToIL(il, oper2))); // [d(rA) + d(rB)] + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 + ei0 = il.Load(2, il.Add(addressSize_l, ei0, operToIL_a(il, oper2, addressSize_l))); // [d(rA) + d(rB)] if(insn->id == PPC_INS_LHZX || insn->id == PPC_INS_LHZUX) - ei0 = il.ZeroExtend(4, ei0); + ei0 = il.ZeroExtend(addressSize_l, ei0); else - ei0 = il.SignExtend(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0); // rD = [d(rA)] + ei0 = il.SignExtend(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); // rD = [d(rA)] il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) if((insn->id == PPC_INS_LHZUX || insn->id == PPC_INS_LHAUX) && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) { - ei0 = il.SetRegister(4, oper1->reg, operToIL(il, oper1)); + ei0 = il.SetRegister(addressSize_l, oper1->reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1009,14 +1107,19 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LWZ: case PPC_INS_LWZU: REQUIRE2OPS - ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 ei0 = il.Load(4, ei0); // [d(rA)] - ei0 = il.SetRegister(4, oper0->reg, ei0); // rD = [d(rA)] + if(addressSize_l == 8) + { + ei0 = il.ZeroExtend(addressSize_l, ei0); + } + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); // rD = [d(rA)] il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LWZU) { - ei0 = il.SetRegister(4, oper1->mem.base, operToIL(il, oper1)); + if(insn->id == PPC_INS_LWZU) + { + ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1028,14 +1131,19 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LWZX: case PPC_INS_LWZUX: REQUIRE3OPS - ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 - ei0 = il.Load(4, il.Add(4, ei0, operToIL(il, oper2))); // [d(rA) + d(rB)] - ei0 = il.SetRegister(4, oper0->reg, ei0); // rD = [d(rA)] + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l); // d(rA) or 0 + ei0 = il.Load(4, il.Add(addressSize_l, ei0, operToIL_a(il, oper2, addressSize_l))); // [d(rA) + d(rB)] + if(addressSize_l == 8) + { + ei0 = il.ZeroExtend(addressSize_l, ei0); + } + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); // rD = [d(rA)] il.AddInstruction(ei0); // if update, rA is set to effective address (d(rA)) - if(insn->id == PPC_INS_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) { - ei0 = il.SetRegister(4, oper1->reg, operToIL(il, oper1)); + if(insn->id == PPC_INS_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) + { + ei0 = il.SetRegister(addressSize_l, oper1->reg, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1081,48 +1189,48 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LHBRX: REQUIRE3OPS - ByteReversedLoad(il, ppc, 2); + ByteReversedLoad(il, ppc, 2, addressSize_l); break; case PPC_INS_LWBRX: REQUIRE3OPS - ByteReversedLoad(il, ppc, 4); + ByteReversedLoad(il, ppc, 4, addressSize_l); break; case PPC_INS_STHBRX: REQUIRE3OPS - ByteReversedStore(il, ppc, 2); + ByteReversedStore(il, ppc, 2, addressSize_l); break; case PPC_INS_STWBRX: REQUIRE3OPS - ByteReversedStore(il, ppc, 4); + ByteReversedStore(il, ppc, 4, addressSize_l); break; case PPC_INS_MFCTR: // move from ctr REQUIRE1OP - il.AddInstruction(il.SetRegister(4, oper0->reg, il.Register(4, PPC_REG_CTR))); + il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, il.Register(addressSize_l, PPC_REG_CTR))); break; case PPC_INS_MFLR: // move from link register REQUIRE1OP - il.AddInstruction(il.SetRegister(4, oper0->reg, il.Register(4, PPC_REG_LR))); + il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, il.Register(addressSize_l, PPC_REG_LR))); break; case PPC_INS_MTCTR: // move to ctr REQUIRE1OP - il.AddInstruction(il.SetRegister(4, PPC_REG_CTR, operToIL(il, oper0))); + il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_CTR, operToIL_a(il, oper0, addressSize_l))); break; case PPC_INS_MTLR: // move to link register REQUIRE1OP - il.AddInstruction(il.SetRegister(4, PPC_REG_LR, operToIL(il, oper0))); + il.AddInstruction(il.SetRegister(addressSize_l, PPC_REG_LR, operToIL_a(il, oper0, addressSize_l))); break; case PPC_INS_NEG: REQUIRE2OPS - ei0 = il.Neg(4, operToIL(il, oper1)); - il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, + ei0 = il.Neg(addressSize_l, operToIL_a(il, oper1, addressSize_l)); + il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 )); break; @@ -1133,8 +1241,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_NOT: REQUIRE2OPS - ei0 = il.Not(4, operToIL(il, oper1)); - il.AddInstruction(il.SetRegister(4, oper0->reg, ei0, + ei0 = il.Not(addressSize_l, operToIL_a(il, oper1, addressSize_l)); + il.AddInstruction(il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 )); break; @@ -1143,13 +1251,13 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ORC: case PPC_INS_NOR: REQUIRE3OPS - ei0 = operToIL(il, oper2); + ei0 = operToIL_a(il, oper2, addressSize_l); if (insn->id == PPC_INS_ORC) - ei0 = il.Not(4, ei0); - ei0 = il.Or(4, operToIL(il, oper1), ei0); + ei0 = il.Not(addressSize_l, ei0); + ei0 = il.Or(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); if (insn->id == PPC_INS_NOR) - ei0 = il.Not(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.Not(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -1159,41 +1267,42 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_ORIS: REQUIRE3OPS if (insn->id == PPC_INS_ORIS) - ei0 = il.Const(4, oper2->imm << 16); + ei0 = il.Const(addressSize_l, oper2->imm << 16); else - ei0 = il.Const(4, oper2->imm); - ei0 = il.Or(4, operToIL(il, oper1), ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0); + ei0 = il.Const(addressSize_l, oper2->imm); + ei0 = il.Or(addressSize_l, operToIL_a(il, oper1, addressSize_l), ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0); il.AddInstruction(ei0); break; case PPC_INS_XOR: case PPC_INS_EQV: REQUIRE3OPS - ei0 = il.Xor(4, - operToIL(il, oper1), - operToIL(il, oper2) + ei0 = il.Xor(addressSize_l, + operToIL_a(il, oper1, addressSize_l), + operToIL_a(il, oper2, addressSize_l) ); if (insn->id == PPC_INS_EQV) - ei0 = il.Not(4, ei0); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.Not(addressSize_l, ei0); + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); break; case PPC_INS_XORI: + case PPC_BN_INS_XORI: case PPC_INS_XORIS: REQUIRE3OPS if (insn->id == PPC_INS_XORIS) - ei0 = il.Const(4, oper2->imm << 16); + ei0 = il.Const(addressSize_l, oper2->imm << 16); else - ei0 = il.Const(4, oper2->imm); + ei0 = il.Const(addressSize_l, oper2->imm); ei0 = il.SetRegister( - 4, + addressSize_l, oper0->reg, - il.Xor(4, - operToIL(il, oper1), + il.Xor(addressSize_l, + operToIL_a(il, oper1, addressSize_l), ei0 ) ); @@ -1205,12 +1314,12 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_SUBFIC: REQUIRE3OPS ei0 = il.Sub( - 4, - operToIL(il, oper2), - operToIL(il, oper1), + addressSize_l, + operToIL_a(il, oper2, addressSize_l), + operToIL_a(il, oper1, addressSize_l), (insn->id != PPC_INS_SUBF) ? IL_FLAGWRITE_XER_CA : 0 ); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -1219,13 +1328,13 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_SUBFE: REQUIRE3OPS ei0 = il.SubBorrow( - 4, - operToIL(il, oper2), - operToIL(il, oper1), + addressSize_l, + operToIL_a(il, oper2, addressSize_l), + operToIL_a(il, oper1, addressSize_l), il.Flag(IL_FLAG_XER_CA), IL_FLAGWRITE_XER_CA ); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -1235,17 +1344,17 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_SUBFZE: REQUIRE2OPS if (insn->id == PPC_INS_SUBFME) - ei0 = il.Const(4, 0xffffffff); + ei0 = il.Const(addressSize_l, ADDRNEG1(addressSize_l)); else - ei0 = il.Const(4, 0); + ei0 = il.Const(addressSize_l, 0); ei0 = il.AddCarry( - 4, + addressSize_l, ei0, - operToIL(il, oper1), + operToIL_a(il, oper1, addressSize_l), il.Flag(IL_FLAG_XER_CA), IL_FLAGWRITE_XER_CA ); - ei0 = il.SetRegister(4, oper0->reg, ei0, + ei0 = il.SetRegister(addressSize_l, oper0->reg, ei0, ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0 ); il.AddInstruction(ei0); @@ -1255,7 +1364,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, REQUIRE2OPS for(i=oper0->reg; i<=PPC_REG_R31; ++i) { ei0 = il.Register(4, i); // source - ei1 = operToIL(il, oper1, OTI_IMM_BIAS, (i-(oper0->reg))*4); + ei1 = operToIL(il, oper1, OTI_IMM_BIAS, (i-(oper0->reg))*4, addressSize_l); il.AddInstruction( il.Store(4, ei1, @@ -1271,14 +1380,14 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STBU: /* store(size, addr, val) */ REQUIRE2OPS ei0 = il.Store(1, - operToIL(il, oper1, OTI_GPR0_ZERO), - il.LowPart(1, operToIL(il, oper0)) + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), + il.LowPart(1, operToIL_a(il, oper0, addressSize_l)) ); il.AddInstruction(ei0); // if update, then rA gets updated address if(insn->id == PPC_INS_STBU) { - ei0 = il.SetRegister(4, oper1->mem.base, operToIL(il, oper1)); + ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1289,15 +1398,18 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STBUX: /* store(size, addr, val) */ REQUIRE3OPS ei0 = il.Store(1, - il.Add(4, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL(il, oper2)), - il.LowPart(1, operToIL(il, oper0)) + il.Add( + addressSize_l, + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), + operToIL_a(il, oper2, addressSize_l)), + il.LowPart(1, operToIL_a(il, oper0, addressSize_l)) ); il.AddInstruction(ei0); // if update, then rA gets updated address if(insn->id == PPC_INS_STBUX) { - ei0 = il.SetRegister(4, oper1->reg, - il.Add(4, operToIL(il, oper1), operToIL(il, oper2)) + ei0 = il.SetRegister(addressSize_l, oper1->reg, + il.Add(addressSize_l, operToIL_a(il, oper1, addressSize_l), operToIL_a(il, oper2, addressSize_l)) ); il.AddInstruction(ei0); } @@ -1309,14 +1421,14 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STHU: /* store(size, addr, val) */ REQUIRE2OPS ei0 = il.Store(2, - operToIL(il, oper1, OTI_GPR0_ZERO), - il.LowPart(2, operToIL(il, oper0)) + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), + il.LowPart(2, operToIL_a(il, oper0, addressSize_l)) ); il.AddInstruction(ei0); // if update, then rA gets updated address if(insn->id == PPC_INS_STHU) { - ei0 = il.SetRegister(4, oper1->mem.base, operToIL(il, oper1)); + ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1327,15 +1439,18 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STHUX: /* store(size, addr, val) */ REQUIRE3OPS ei0 = il.Store(2, - il.Add(4, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL(il, oper2)), - il.LowPart(2, operToIL(il, oper0)) + il.Add( + addressSize_l, + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), + operToIL_a(il, oper2, addressSize_l)), + il.LowPart(2, operToIL_a(il, oper0, addressSize_l)) ); il.AddInstruction(ei0); // if update, then rA gets updated address if(insn->id == PPC_INS_STHUX) { - ei0 = il.SetRegister(4, oper1->reg, - il.Add(4, operToIL(il, oper1), operToIL(il, oper2)) + ei0 = il.SetRegister(addressSize_l, oper1->reg, + il.Add(addressSize_l, operToIL_a(il, oper1, addressSize_l), operToIL_a(il, oper2, addressSize_l)) ); il.AddInstruction(ei0); } @@ -1346,15 +1461,23 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STW: case PPC_INS_STWU: /* store(size, addr, val) */ REQUIRE2OPS + if (addressSize_l == 8) + { + ei0 = il.LowPart(4, operToIL_a(il, oper0, addressSize_l)); + } + else if (addressSize_l == 4) + { + ei0 = operToIL(il, oper0); + } ei0 = il.Store(4, - operToIL(il, oper1, OTI_GPR0_ZERO), - operToIL(il, oper0) + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), + ei0 ); il.AddInstruction(ei0); // if update, then rA gets updated address if(insn->id == PPC_INS_STWU) { - ei0 = il.SetRegister(4, oper1->mem.base, operToIL(il, oper1)); + ei0 = il.SetRegister(addressSize_l, oper1->mem.base, operToIL_a(il, oper1, addressSize_l)); il.AddInstruction(ei0); } @@ -1364,16 +1487,27 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STWX: case PPC_INS_STWUX: /* store(size, addr, val) */ REQUIRE3OPS + if (addressSize_l == 8) + { + ei0 = il.LowPart(4, operToIL_a(il, oper0, addressSize_l)); + } + else if (addressSize_l == 4) + { + ei0 = operToIL(il, oper0); + } ei0 = il.Store(4, - il.Add(4, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL(il, oper2)), - operToIL(il, oper0) + il.Add( + addressSize_l, + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_EXTRA_DEFAULT, addressSize_l), + operToIL_a(il, oper2, addressSize_l)), + ei0 ); il.AddInstruction(ei0); // if update, then rA gets updated address if(insn->id == PPC_INS_STWUX) { - ei0 = il.SetRegister(4, oper1->reg, - il.Add(4, operToIL(il, oper1), operToIL(il, oper2)) + ei0 = il.SetRegister(addressSize_l, oper1->reg, + il.Add(addressSize_l, operToIL_a(il, oper1, addressSize_l), operToIL_a(il, oper2, addressSize_l)) ); il.AddInstruction(ei0); } @@ -1385,14 +1519,14 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STDU: /* store(size, addr, val) */ REQUIRE2OPS ei0 = il.Store(8, - operToIL(il, oper1, OTI_GPR0_ZERO), - operToIL(il, oper0) + operToIL(il, oper1, OTI_GPR0_ZERO, PPC_IL_OPTIONS_DEFAULT, addressSize_l), + operToIL_a(il, oper0, addressSize_l) ); il.AddInstruction(ei0); // if update, then rA gets updated address - if(insn->id == PPC_INS_STWU) { - ei0 = il.SetRegister(8, oper1->mem.base, operToIL(il, oper1)); + if(insn->id == PPC_INS_STDU) { + ei0 = il.SetRegister(8, oper1->mem.base, operToIL_a(il, oper1, 8)); il.AddInstruction(ei0); } @@ -1403,7 +1537,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STDUX: /* store(size, addr, val) */ REQUIRE3OPS ei0 = il.Store(8, - il.Add(8, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL(il, oper2)), + il.Add(8, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL_a(il, oper2, addressSize_l)), operToIL(il, oper0) ); il.AddInstruction(ei0); @@ -1411,7 +1545,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // if update, then rA gets updated address if(insn->id == PPC_INS_STDUX) { ei0 = il.SetRegister(8, oper1->reg, - il.Add(8, operToIL(il, oper1), operToIL(il, oper2)) + il.Add(8, operToIL_a(il, oper1, 8), operToIL_a(il, oper2, 8)) ); il.AddInstruction(ei0); } @@ -1680,7 +1814,9 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_MR: /* move register */ REQUIRE2OPS - il.AddInstruction(il.SetRegister(4, oper0->reg, operToIL(il, oper1))); + ei0 = il.SetRegister(addressSize_l, oper0->reg, operToIL_a(il, oper1, addressSize_l), + ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0); + il.AddInstruction(ei0); break; case PPC_INS_SC: @@ -1695,11 +1831,391 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(il.Trap(0)); break; +// ===================================== +// =====FLOATING POINT INSTRUCTIONS===== +// ===================================== + + // case PPC_INS_FCMPO: /* compare (signed) word(32-bit) */ + // REQUIRE2OPS + // ei0 = operToIL(il, oper2 ? oper1 : oper0); + // ei1 = operToIL(il, oper2 ? oper2 : oper1); + // ei2 = il.Sub(4, ei0, ei1, crxToFlagWriteType(oper2 ? oper0->reg : PPC_REG_CR0)); + // il.AddInstruction(ei2); + // break; + + // for this one, i guess the easiest thing to do is to summarize it by + // the end result. For this instuction to happen, the end result is: + // register Fn is stored at Rn. + // how do we achieve this result in IL? + // had it not had the quantization, we could probably get away with + // a cast and then store. + + case PPC_INS_FADD: + REQUIRE3OPS + ei0 = il.FloatAdd(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei0); + break; + + case PPC_INS_FADDS: + REQUIRE3OPS + ei0 = il.FloatAdd(4, operToIL(il, oper1), operToIL(il, oper2)); + ei0 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei0); + break; + + case PPC_INS_FSUB: + REQUIRE3OPS + ei0 = il.FloatSub(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei0); + break; + + case PPC_INS_FSUBS: + REQUIRE3OPS + ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2)); + ei0 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei0); + break; + + case PPC_INS_FCMPU: + REQUIRE3OPS + ei0 = il.Register(RZF, oper1->reg); + ei1 = il.Register(RZF, oper2->reg); + ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg | PPC_CRX_FLOAT_MASK)); + il.AddInstruction(ei2); + break; + + case PPC_INS_BN_FCMPO: + REQUIRE3OPS + ei0 = il.Register(RZF, oper1->reg); + ei1 = il.Register(RZF, oper2->reg); + ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg | PPC_CRX_FLOAT_MASK)); + il.AddInstruction(ei2); + break; + + case PPC_INS_FMR: + REQUIRE2OPS + ei0 = il.SetRegister(8, oper0->reg, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + il.AddInstruction(ei0); + break; + + case PPC_INS_STFS: + REQUIRE2OPS + ei0 = il.FloatConvert(4, operToIL(il, oper0)); + ei0 = il.Store(4, operToIL(il, oper1), ei0); + // ei0 = il.FloatConvert(4, ei0); + il.AddInstruction(ei0); + break; + + case PPC_INS_STFSX: + REQUIRE3OPS + ei0 = il.FloatConvert(4, operToIL(il, oper0)); + ei1 = il.Add(4, operToIL(il, oper1), operToIL(il, oper2)); + ei0 = il.Store(4, ei1, ei0); + // ei0 = il.FloatConvert(4, ei0); + il.AddInstruction(ei0); + break; + + case PPC_INS_STFD: + REQUIRE2OPS + ei0 = il.Store(8, operToIL(il, oper1), + il.FloatConvert(8, operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8))); + // ei0 = il.FloatConvert(8, ei0); + il.AddInstruction(ei0); + break; + + case PPC_INS_LFS: + REQUIRE2OPS + // ei0 = operToIL(il, oper1); // d(rA) or 0 + // ei0 = il.Load(4, ei0); // [d(rA)] + // ei0 = il.SetRegister(4, oper0->reg, ei0); // rD = [d(rA)] + // // ei1 = il.IntToFloat(4, ei0); + // il.AddInstruction(ei1); + + // alternatively, do it the way arm64 does it + loadstoreppcfs(il, 4, oper0, oper1); + break; + + case PPC_INS_LFSX: + REQUIRE3OPS + // ei0 = il.Add(4, operToIL(il, oper1), operToIL(il, oper2)); + // ei0 = il.Load(4, ei0); + // ei0 = il.Operand(1, ei0); + // ei0 = il.FloatConvert(4, ei0); + // ei0 = il.SetRegister(4, oper0->reg, ei0); + // // alternatively, do it the way arm64 does it + // il.AddInstruction(ei0); + + loadstoreppcfs(il, 4, oper0, oper1, oper2); + break; + + case PPC_INS_LFSU: + REQUIRE2OPS + loadstoreppcfs(il, 4, oper0, oper1, 0, true); + break; + + case PPC_INS_LFSUX: + REQUIRE3OPS + loadstoreppcfs(il, 4, oper0, oper1, oper2, true); + break; + + case PPC_INS_LFD: + REQUIRE2OPS + // ei0 = operToIL(il, oper1); // d(rA) or 0 + // ei0 = il.Load(8, ei0); // [d(rA)] + // ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] + // il.AddInstruction(ei0); + + // same as lfs + loadstoreppcfs(il, 8, oper0, oper1); + break; + + case PPC_INS_FMUL: + REQUIRE3OPS + ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FMULS: + REQUIRE3OPS + ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper2)); + ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FDIV: + REQUIRE3OPS + ei0 = il.DivDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FDIVS: + REQUIRE3OPS + ei0 = il.FloatDiv(4, operToIL(il, oper1), operToIL(il, oper2)); + ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FMADD: + REQUIRE4OPS + ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.FloatAdd(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FMADDS: + REQUIRE4OPS + ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.FloatAdd(4, ei0, operToIL(il, oper2), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei1 = il.SetRegister(4, oper0->reg, ei0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FMSUB: + REQUIRE4OPS + ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.FloatSub(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FMSUBS: + REQUIRE4OPS + ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3)); + ei0 = il.FloatSub(4, ei0, operToIL(il, oper2)); + ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + // this is a weird one, its described as round a float to an int towards 0, then set + // bits 32-63 of a double reg to that result, ignoring the lower 32 bits 0-31. + // TODO: needs further testing to verify that this is functional, and verify that the + // method used was correct, as well as the registers afffected, like FPSCR. + case PPC_INS_FCTIWZ: + REQUIRE2OPS + ei0 = il.FloatTrunc(RZF, operToIL(il, oper1)); + ei1 = il.Const(4, 32); + ei2 = il.ShiftLeft(8, ei0, ei1); + ei0 = il.SetRegister(8, oper0->reg, ei2, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei0); + break; + + case PPC_INS_FNEG: + REQUIRE2OPS + ei0 = il.FloatNeg(4, operToIL(il, oper1)); + ei0 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei0); + break; + + case PPC_INS_FNMADD: + REQUIRE4OPS + ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.FloatAdd(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.FloatNeg(8, ei0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FNMADDS: + REQUIRE4OPS + ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.FloatAdd(4, ei0, operToIL(il, oper2), (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + ei0 = il.FloatNeg(4, ei0); + ei1 = il.SetRegister(4, oper0->reg, ei0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FNMSUB: + REQUIRE4OPS + ei0 = il.MultDoublePrecSigned(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), + operToIL(il, oper3, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.FloatSub(8, ei0, operToIL(il, oper2, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei0 = il.FloatNeg(8, ei0); + ei1 = il.SetRegister(8, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FNMSUBS: + REQUIRE4OPS + ei0 = il.FloatMult(4, operToIL(il, oper1), operToIL(il, oper3)); + ei0 = il.FloatSub(4, ei0, operToIL(il, oper2)); + ei0 = il.FloatNeg(4, ei0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FABS: + REQUIRE2OPS + ei0 = il.FloatAbs(4, operToIL(il, oper1)); + ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FNABS: + REQUIRE2OPS + ei0 = il.FloatAbs(4, operToIL(il, oper1)); + ei0 = il.FloatNeg(4, ei0); + ei1 = il.SetRegister(4, oper0->reg, ei0, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + // TODO: needs more testing to make sure that stuff is good. the decompilation is a + // little rough, seems to be making the const double 1 into an int by default, + // gonna have to figure out how if its right and FPSCR is correct. + case PPC_INS_FRSQRTE: + REQUIRE2OPS + ei0 = il.FloatConstDouble(1); + ei1 = il.FloatSqrt(8, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei1 = il.DivDoublePrecSigned(8, ei0, ei1); + ei1 = il.SetRegister(8, oper0->reg, ei1, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_FRSQRTES: + REQUIRE2OPS + ei0 = il.FloatConstSingle(1); + ei1 = il.FloatSqrt(4, operToIL(il, oper1, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)); + ei1 = il.FloatDiv(4, ei0, ei1); + ei1 = il.SetRegister(4, oper0->reg, ei1, (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0); + il.AddInstruction(ei1); + break; + + case PPC_INS_CNTLZW: + ei0 = il.Intrinsic({RegisterOrFlag::Register(oper1->reg)}, PPC_INTRIN_CNTLZW, + {operToIL(il, oper0)}); + il.AddInstruction(ei0); + break; + + case PPC_INS_PSQ_ST: + REQUIRE4OPS + MYLOG("0x%08x psq_st args f%d r%d[%d] w:%lldd gcqr:%lld\n", + (uint32_t)addr, oper0->reg - PPC_REG_F0, oper1->mem.base - PPC_REG_R0, oper1->mem.disp, oper2->imm, + oper3->imm); + MYLOG("opcount %d insn pnem %s\n", ppc->op_count, insn->op_str); + + // w_l = oper2->imm; + + // The intrinsic used to perform the quantize operation. + // optional, use output {} for empty. + ei0 = il.Intrinsic( + {RegisterOrFlag::Register(oper0->reg)}, + PPC_PS_INTRIN_QUANTIZE, + { + operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 4), + il.Const(4, oper3->imm) + } + ); + + il.AddInstruction(ei0); + + // Then store the quantized value + ei0 = il.Store(8, operToIL(il, oper1), + // temporary measure to allow it to resemble the instruction, just oper2il oper0 + // ei0 + operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 4) + // ei2 + ); + il.AddInstruction(ei0); + + // we are supposed to quantize the upper 32 bits as well, ps1 if w=0 + // if (w_l == 0) + // { + + // } + break; + + case PPC_INS_PSQ_L: + REQUIRE4OPS + // w_l = oper2->imm; + + ei0 = il.Load(8, operToIL(il, oper1)); // [d(rA)] + ei0 = il.Intrinsic( + {RegisterOrFlag::Register(oper0->reg)}, + PPC_PS_INTRIN_DEQUANTIZE, + { + ei0, + operToIL(il, oper0), + il.Const(4, oper3->imm) + } + ); + + il.AddInstruction(ei0); + + // again, if w=0 qdequantize ps1 + // if (w_l == 0) + // { + + // } + + break; + + case PPC_INS_FRSP: + ei0 = il.Intrinsic( + {RegisterOrFlag::Register(oper0->reg)}, + PPC_INTRIN_FRSP, + {operToIL(il, oper1)}); + il.AddInstruction(ei0); + break; + + // ===================================== + // =====TO BE DEFINED INSTRUCTIONS====== + // ===================================== + case PPC_INS_BCL: case PPC_INS_BCLR: case PPC_INS_BCLRL: case PPC_INS_CNTLZD: - case PPC_INS_CNTLZW: case PPC_INS_DCBA: case PPC_INS_DCBF: case PPC_INS_DCBI: @@ -1889,9 +2405,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_EVSUBFW: case PPC_INS_EVSUBIFW: case PPC_INS_EVXOR: - case PPC_INS_FABS: - case PPC_INS_FADD: - case PPC_INS_FADDS: case PPC_INS_FCFID: case PPC_INS_FCFIDS: case PPC_INS_FCFIDU: @@ -1902,51 +2415,25 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_FCTIDZ: case PPC_INS_FCTIW: case PPC_INS_FCTIWUZ: - case PPC_INS_FCTIWZ: - case PPC_INS_FDIV: - case PPC_INS_FDIVS: - case PPC_INS_FMADD: - case PPC_INS_FMADDS: - case PPC_INS_FMR: - case PPC_INS_FMSUB: - case PPC_INS_FMSUBS: - case PPC_INS_FMUL: - case PPC_INS_FMULS: - case PPC_INS_FNABS: - case PPC_INS_FNEG: - case PPC_INS_FNMADD: - case PPC_INS_FNMADDS: - case PPC_INS_FNMSUB: - case PPC_INS_FNMSUBS: case PPC_INS_FRE: case PPC_INS_FRES: case PPC_INS_FRIM: case PPC_INS_FRIN: case PPC_INS_FRIP: case PPC_INS_FRIZ: - case PPC_INS_FRSP: - case PPC_INS_FRSQRTE: - case PPC_INS_FRSQRTES: case PPC_INS_FSEL: case PPC_INS_FSQRT: case PPC_INS_FSQRTS: - case PPC_INS_FSUB: - case PPC_INS_FSUBS: case PPC_INS_ICBI: case PPC_INS_ICCCI: case PPC_INS_ISYNC: case PPC_INS_LDARX: case PPC_INS_LDBRX: - case PPC_INS_LFD: case PPC_INS_LFDU: case PPC_INS_LFDUX: case PPC_INS_LFDX: case PPC_INS_LFIWAX: case PPC_INS_LFIWZX: - case PPC_INS_LFS: - case PPC_INS_LFSU: - case PPC_INS_LFSUX: - case PPC_INS_LFSX: case PPC_INS_LSWI: case PPC_INS_LVEBX: case PPC_INS_LVEHX: @@ -2007,15 +2494,12 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_SLBMTE: case PPC_INS_STDBRX: case PPC_INS_STDCX: - case PPC_INS_STFD: case PPC_INS_STFDU: case PPC_INS_STFDUX: case PPC_INS_STFDX: case PPC_INS_STFIWX: - case PPC_INS_STFS: case PPC_INS_STFSU: case PPC_INS_STFSUX: - case PPC_INS_STFSX: case PPC_INS_STSWI: case PPC_INS_STVEBX: case PPC_INS_STVEHX: @@ -2426,7 +2910,9 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_TWUI: case PPC_INS_WAITRSV: case PPC_INS_WAITIMPL: - case PPC_INS_XNOP: + // TODO not technically implemented but capstone misinterprettation + // where it is posting that XORI is 1452, though that is XNOP + // case PPC_INS_XNOP: case PPC_INS_XVMOVDP: case PPC_INS_XVMOVSP: case PPC_INS_XXSPLTD: diff --git a/arch/powerpc/il.h b/arch/powerpc/il.h index 68723f3754..b4ca2526cd 100644 --- a/arch/powerpc/il.h +++ b/arch/powerpc/il.h @@ -15,8 +15,27 @@ eg: cmp a, b if ab then c=0b010 (not setting SO, setting GT) if a==b then c=0b001 (not setting SO, setting EQ) + +FOR FLOATING POINT +if ((frA) is a NaN or (frB) is a NaN) then c=0b0001 +else if (frA)< (frB) then c=0b1000 +else if (frA)> (frB) then c=0b0100 +else if (frA)==(frB) then c=0b0010 */ +typedef enum +{ + PPC_SUF_S=0, + PPC_SUF_U=1, + PPC_SUF_F=2, + PPC_SUF_SZ=3 +} ppc_suf; + +#define IL_FLOAT_FLAG_NAN (1 << 8) +#define IL_FLOAT_FLAG_LT (8 << 8) +#define IL_FLOAT_FLAG_GT (4 << 8) +#define IL_FLOAT_FLAG_EQ (2 << 8) + #define IL_FLAG_LT 0 #define IL_FLAG_GT 1 #define IL_FLAG_EQ 2 @@ -59,62 +78,78 @@ if a==b then c=0b001 (not setting SO, setting EQ) #define IL_FLAGWRITE_NONE 0 #define IL_FLAGWRITE_CR0_S 1 #define IL_FLAGWRITE_CR0_U 2 -#define IL_FLAGWRITE_CR1_S 3 -#define IL_FLAGWRITE_CR1_U 4 -#define IL_FLAGWRITE_CR2_S 5 -#define IL_FLAGWRITE_CR2_U 6 -#define IL_FLAGWRITE_CR3_S 7 -#define IL_FLAGWRITE_CR3_U 8 -#define IL_FLAGWRITE_CR4_S 9 -#define IL_FLAGWRITE_CR4_U 10 -#define IL_FLAGWRITE_CR5_S 11 -#define IL_FLAGWRITE_CR5_U 12 -#define IL_FLAGWRITE_CR6_S 13 -#define IL_FLAGWRITE_CR6_U 14 -#define IL_FLAGWRITE_CR7_S 15 -#define IL_FLAGWRITE_CR7_U 16 -#define IL_FLAGWRITE_XER 17 -#define IL_FLAGWRITE_XER_CA 18 -#define IL_FLAGWRITE_XER_OV_SO 19 - -#define IL_FLAGWRITE_MTCR0 20 -#define IL_FLAGWRITE_MTCR1 21 -#define IL_FLAGWRITE_MTCR2 22 -#define IL_FLAGWRITE_MTCR3 23 -#define IL_FLAGWRITE_MTCR4 24 -#define IL_FLAGWRITE_MTCR5 25 -#define IL_FLAGWRITE_MTCR6 26 -#define IL_FLAGWRITE_MTCR7 27 - -#define IL_FLAGWRITE_INVL0 30 -#define IL_FLAGWRITE_INVL1 31 -#define IL_FLAGWRITE_INVL2 32 -#define IL_FLAGWRITE_INVL3 33 -#define IL_FLAGWRITE_INVL4 34 -#define IL_FLAGWRITE_INVL5 35 -#define IL_FLAGWRITE_INVL6 36 -#define IL_FLAGWRITE_INVL7 37 - -#define IL_FLAGWRITE_INVALL 40 +#define IL_FLAGWRITE_CR0_F 3 +#define IL_FLAGWRITE_CR1_S 4 +#define IL_FLAGWRITE_CR1_U 5 +#define IL_FLAGWRITE_CR1_F 6 +#define IL_FLAGWRITE_CR2_S 7 +#define IL_FLAGWRITE_CR2_U 8 +#define IL_FLAGWRITE_CR2_F 9 +#define IL_FLAGWRITE_CR3_S 10 +#define IL_FLAGWRITE_CR3_U 11 +#define IL_FLAGWRITE_CR3_F 12 +#define IL_FLAGWRITE_CR4_S 13 +#define IL_FLAGWRITE_CR4_U 14 +#define IL_FLAGWRITE_CR4_F 15 +#define IL_FLAGWRITE_CR5_S 16 +#define IL_FLAGWRITE_CR5_U 17 +#define IL_FLAGWRITE_CR5_F 18 +#define IL_FLAGWRITE_CR6_S 19 +#define IL_FLAGWRITE_CR6_U 20 +#define IL_FLAGWRITE_CR6_F 21 +#define IL_FLAGWRITE_CR7_S 22 +#define IL_FLAGWRITE_CR7_U 23 +#define IL_FLAGWRITE_CR7_F 24 +#define IL_FLAGWRITE_XER 25 +#define IL_FLAGWRITE_XER_CA 26 +#define IL_FLAGWRITE_XER_OV_SO 27 + +#define IL_FLAGWRITE_MTCR0 28 +#define IL_FLAGWRITE_MTCR1 29 +#define IL_FLAGWRITE_MTCR2 30 +#define IL_FLAGWRITE_MTCR3 31 +#define IL_FLAGWRITE_MTCR4 32 +#define IL_FLAGWRITE_MTCR5 33 +#define IL_FLAGWRITE_MTCR6 34 +#define IL_FLAGWRITE_MTCR7 35 + +#define IL_FLAGWRITE_INVL0 38 +#define IL_FLAGWRITE_INVL1 39 +#define IL_FLAGWRITE_INVL2 40 +#define IL_FLAGWRITE_INVL3 41 +#define IL_FLAGWRITE_INVL4 42 +#define IL_FLAGWRITE_INVL5 43 +#define IL_FLAGWRITE_INVL6 44 +#define IL_FLAGWRITE_INVL7 45 + +#define IL_FLAGWRITE_INVALL 48 /* the different classes of writes to each cr */ #define IL_FLAGCLASS_NONE 0 #define IL_FLAGCLASS_CR0_S 1 #define IL_FLAGCLASS_CR0_U 2 -#define IL_FLAGCLASS_CR1_S 3 -#define IL_FLAGCLASS_CR1_U 4 -#define IL_FLAGCLASS_CR2_S 5 -#define IL_FLAGCLASS_CR2_U 6 -#define IL_FLAGCLASS_CR3_S 7 -#define IL_FLAGCLASS_CR3_U 8 -#define IL_FLAGCLASS_CR4_S 9 -#define IL_FLAGCLASS_CR4_U 10 -#define IL_FLAGCLASS_CR5_S 11 -#define IL_FLAGCLASS_CR5_U 12 -#define IL_FLAGCLASS_CR6_S 13 -#define IL_FLAGCLASS_CR6_U 14 -#define IL_FLAGCLASS_CR7_S 15 -#define IL_FLAGCLASS_CR7_U 16 +#define IL_FLAGCLASS_CR0_F 3 +#define IL_FLAGCLASS_CR1_S 4 +#define IL_FLAGCLASS_CR1_U 5 +#define IL_FLAGCLASS_CR1_F 6 +#define IL_FLAGCLASS_CR2_S 7 +#define IL_FLAGCLASS_CR2_U 8 +#define IL_FLAGCLASS_CR2_F 9 +#define IL_FLAGCLASS_CR3_S 10 +#define IL_FLAGCLASS_CR3_U 11 +#define IL_FLAGCLASS_CR3_F 12 +#define IL_FLAGCLASS_CR4_S 13 +#define IL_FLAGCLASS_CR4_U 14 +#define IL_FLAGCLASS_CR4_F 15 +#define IL_FLAGCLASS_CR5_S 16 +#define IL_FLAGCLASS_CR5_U 17 +#define IL_FLAGCLASS_CR5_F 18 +#define IL_FLAGCLASS_CR6_S 19 +#define IL_FLAGCLASS_CR6_U 20 +#define IL_FLAGCLASS_CR6_F 21 +#define IL_FLAGCLASS_CR7_S 22 +#define IL_FLAGCLASS_CR7_U 23 +#define IL_FLAGCLASS_CR7_F 24 #define IL_FLAGGROUP_CR0_LT (0 + 0) #define IL_FLAGGROUP_CR0_LE (0 + 1) @@ -172,5 +207,16 @@ if a==b then c=0b001 (not setting SO, setting EQ) #define IL_FLAGGROUP_CR7_EQ (70 + 4) #define IL_FLAGGROUP_CR7_NE (70 + 5) +enum PPCIntrinsic : uint32_t +{ + PPC_INTRIN_CNTLZW, + PPC_INTRIN_FRSP, + PPC_INTRIN_END, + PPC_PS_INTRIN_QUANTIZE, + PPC_PS_INTRIN_DEQUANTIZE, + PPC_PS_INTRIN_END, + PPC_INTRIN_INVALID = 0xFFFFFFFF, +}; + bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction& il, const uint8_t *data, uint64_t addr, decomp_result *res, bool le); diff --git a/arch/powerpc/test_disasm.cpp b/arch/powerpc/test_disasm.cpp index 5ee7d1dd6c..cd70a6aae8 100644 --- a/arch/powerpc/test_disasm.cpp +++ b/arch/powerpc/test_disasm.cpp @@ -15,22 +15,39 @@ g++ -std=c++11 -O0 -g -I capstone/include -L./build/capstone test_disasm.cpp dis #include #include +#include + #include "disassembler.h" int print_errors = 1; +int cs_mode_local = 0; +size_t address_size_ = 4; +// data in default with strtoul is little endian +bool littleendian = true; int disas_instr_word(uint32_t instr_word, char *buf) { int rc = -1; - struct decomp_result res; + struct decomp_result res = {0}; struct cs_insn *insn = &(res.insn); struct cs_detail *detail = &(res.detail); struct cs_ppc *ppc = &(detail->ppc); - if(powerpc_decompose((const uint8_t *)&instr_word, 4, 0, true, &res, false)) { - if(print_errors) printf("ERROR: powerpc_decompose()\n"); - goto cleanup; + if(powerpc_decompose((const uint8_t *)&instr_word, 4, 0, littleendian, &res, address_size_, cs_mode_local)) { + if(print_errors) + { + if (DoesQualifyForLocalDisassembly((uint8_t*)&instr_word, !littleendian) != PPC_INS_INVALID) + { + size_t instsz = 4; + PerformLocalDisassembly((uint8_t*)&instr_word, 0, instsz, &res, !littleendian); + } + else + { + printf("ERROR: powerpc_decompose()\n"); + goto cleanup; + } + } } /* MEGA DETAILS, IF YOU WANT 'EM */ @@ -79,7 +96,7 @@ int disas_instr_word(uint32_t instr_word, char *buf) printf("reg: %s\n", cs_reg_name(res.handle, op.reg)); break; case PPC_OP_IMM: - printf("imm: 0x%X\n", op.imm); + printf("imm: 0x%llx\n", op.imm); break; case PPC_OP_MEM: printf("mem (%s + %d)\n", cs_reg_name(res.handle, op.mem.base), @@ -106,21 +123,58 @@ int disas_instr_word(uint32_t instr_word, char *buf) return rc; } +void usage(const char* av0) +{ + printf("usage: %s [-p] [-q] [-s] [-b] repl/send\n", av0); + printf("p for ppc_ps, q for ppc_qpx, s for ppc_spe\n"); + printf("b for big endian interprettation\n"); + printf("send argument \"repl\" or \"speed\"\n"); +} + int main(int ac, char **av) { int rc = -1; char buf[256]; + int index; + char* disasm_cmd = 0; + int c; + +#define BATCH 10000000 + opterr = 0; + + while ((c = getopt(ac, av, "qspb")) != -1) + { + switch (c) + { + case 'q': + cs_mode_local = CS_MODE_QPX; + break; + case 's': + cs_mode_local = CS_MODE_SPE; + break; + case 'p': + cs_mode_local = CS_MODE_PS; + break; + case 'b': + littleendian = false; + break; + default: + usage(av[0]); + goto cleanup; + } + } - #define BATCH 10000000 - - powerpc_init(); - - if(ac <= 1) { - printf("send argument \"repl\" or \"speed\"\n"); + if (optind >= ac) + { + usage(av[0]); goto cleanup; } - if(!strcasecmp(av[1], "repl")) { + disasm_cmd = av[optind]; + + powerpc_init(cs_mode_local); + + if(!strcasecmp(disasm_cmd, "repl")) { printf("REPL mode!\n"); printf("example inputs (write the words as if after endian fetch):\n"); printf("93e1fffc\n"); @@ -148,7 +202,7 @@ int main(int ac, char **av) printf("%s\n", buf); } } - else if(!strcasecmp(av[1], "speed")) { + else if(!strcasecmp(disasm_cmd, "speed")) { printf("SPEED TEST THAT COUNTS QUICK RETURNS FROM BAD INSTRUCTIONS AS DISASSEMBLED\n"); print_errors = 0; uint32_t instr_word = 0x780b3f7c; @@ -167,7 +221,7 @@ int main(int ac, char **av) printf("current rate: %f instructions per second\n", (float)BATCH/ellapsed); } } - else if(!strcasecmp(av[1], "speed2")) { + else if(!strcasecmp(disasm_cmd, "speed2")) { printf("SPEED TEST THAT IS GIVEN NO CREDIT FOR QUICK RETURNS FROM BAD INSTRUCTIONS\n"); print_errors = 0; uint32_t instr_word = 0x780b3f7c; diff --git a/arch/powerpc/util.cpp b/arch/powerpc/util.cpp index 50c3eb5b14..5e37f735c2 100644 --- a/arch/powerpc/util.cpp +++ b/arch/powerpc/util.cpp @@ -85,4 +85,17 @@ void printInstructionVerbose(decomp_result *res) } } +uint64_t sign_extend(size_t addressSize_local, uint64_t target, int signBit) +{ + if ((target >> signBit) & 1) + { + target = target | (~((1 << signBit) - 1)); + } + + if (addressSize_local == 4) + { + target = target & 0xffffffff; + } + return target; +} diff --git a/arch/powerpc/util.h b/arch/powerpc/util.h index fe2b7fdaad..0eb146515d 100644 --- a/arch/powerpc/util.h +++ b/arch/powerpc/util.h @@ -6,6 +6,30 @@ #define FALL_THROUGH #endif +#define ADDRMASK(addressSize, target) \ + if (addressSize == 4) \ + { \ + target &= 0xffffffff; \ + } + +#define EXTOPT(rawInsn, addressSize, extend, TYPE) \ + { \ + int L_tmp = ((rawInsn >> 10) & 1); \ + if ((L_tmp == 1) && (addressSize == 8)) \ + { \ + extend = OTI_ ## TYPE ## EXT64_IMMS; \ + } \ + else \ + { \ + extend = OTI_ ## TYPE ## EXT32_IMMS; \ + } \ + } + +#define EXTOPTZ(data, addressSize, extend) EXTOPT(data, addressSize, extend, Z) +#define EXTOPTS(data, addressSize, extend) EXTOPT(data, addressSize, extend, S) + +#define ADDRNEG1(addressSize) (addressSize == 4) ? ((uint32_t)-1) : ((uint64_t)-1) + inline uint32_t bswap32(uint32_t x) { return ((x&0xFF)<<24) | @@ -16,3 +40,4 @@ inline uint32_t bswap32(uint32_t x) void printOperandVerbose(decomp_result *res, cs_ppc_op *opers); void printInstructionVerbose(decomp_result *res); +uint64_t sign_extend(size_t addressSize_local, uint64_t target, int signBit); \ No newline at end of file