summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2024-12-16 13:40:25 -0500
committerGalen Williamson <galen@vector35.com>2024-12-16 13:40:25 -0500
commit8ea98cab89afb0c14073141f30203486d1333b07 (patch)
treea749ae52d4c590c06876b0e02656ad811883b082
parentb34ddd03f71c8637a80a264a3ea757b8295d482b (diff)
[ppc] merges PR Vector35/binaryninja-api#5176 (adds support for "psq" Quantized Floating Point instructions, fixes/completes 64-bit instruction/register support)
-rw-r--r--arch/powerpc/CMakeLists.txt28
-rw-r--r--arch/powerpc/arch_ppc.cpp673
-rw-r--r--arch/powerpc/disassembler.cpp174
-rw-r--r--arch/powerpc/disassembler.h37
-rw-r--r--arch/powerpc/il.cpp1022
-rw-r--r--arch/powerpc/il.h142
-rw-r--r--arch/powerpc/test_disasm.cpp78
-rw-r--r--arch/powerpc/util.cpp13
-rw-r--r--arch/powerpc/util.h25
9 files changed, 1567 insertions, 625 deletions
diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt
index 57a68f6e..d148c690 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 545e2be3..f732b561 100644
--- a/arch/powerpc/arch_ppc.cpp
+++ b/arch/powerpc/arch_ppc.cpp
@@ -6,8 +6,8 @@
#include <binaryninjaapi.h>
#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<InstructionTextToken> &result)
+ bool PrintLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, vector<InstructionTextToken> &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<uint32_t> GetAllIntrinsics() override
+ {
+ // Highest intrinsic number currently is PPC_PS_INTRIN_END.
+ // If new extensions are added please update this code.
+ std::vector<uint32_t> 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<NameAndType> 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<NameAndType>();
+ }
+
+ virtual vector<NameAndType> 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<NameAndType>();
+ }
+
+ static vector<Confidence<Ref<Type>>> 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<Confidence<Ref<Type>>>();
+ }
+
+ virtual vector<Confidence<Ref<Type>>> 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<Confidence<Ref<Type>>>();
+ }
+
+
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<uint32_t> GetAllFlags() override
{
- MYLOG("%s()\n", __func__);
+ // MYLOG("%s()\n", __func__);
return vector<uint32_t> {
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<uint32_t> 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<uint32_t> {
@@ -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<uint32_t> {
@@ -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<uint32_t> {
@@ -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<uint32_t> {
@@ -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<uint32_t> {
@@ -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<uint32_t> {
@@ -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<uint32_t> {
@@ -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<uint32_t> {
@@ -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<uint32_t, BNLowLevelILFlagCondition> 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<uint32_t, BNLowLevelILFlagCondition> {
{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<uint32_t, BNLowLevelILFlagCondition> {
{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<uint32_t, BNLowLevelILFlagCondition> {
{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<uint32_t, BNLowLevelILFlagCondition> {
{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<uint32_t, BNLowLevelILFlagCondition> {
{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<uint32_t, BNLowLevelILFlagCondition> {
{flagClassBase , LLFC_NE},
- {flagClassBase + 1, LLFC_NE}
+ {flagClassBase + PPC_SUF_U, LLFC_NE},
+ {flagClassBase + PPC_SUF_F, LLFC_FNE}
};
default:
return map<uint32_t, BNLowLevelILFlagCondition>();
@@ -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<uint32_t> 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<uint32_t>{ 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<uint32_t>{ 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<uint32_t>{ IL_FLAG_GT };
case LLFC_NEG:
@@ -1484,7 +1545,7 @@ class PowerpcArchitecture: public Architecture
virtual vector<uint32_t> GetFullWidthRegisters() override
{
- MYLOG("%s()\n", __func__);
+ // MYLOG("%s()\n", __func__);
return vector<uint32_t>{
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<uint32_t> 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 66e40d32..2a421971 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 d586a517..d4679ae0 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 4d074aa4..43a47064 100644
--- a/arch/powerpc/il.cpp
+++ b/arch/powerpc/il.cpp
@@ -1,3 +1,4 @@
+#include "lowlevelilinstruction.h"
#include <binaryninjaapi.h>
#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 <reg>, <reg>, <rol_amt>, <mask_begin>, <mask_end>
@@ -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 68723f37..b4ca2526 100644
--- a/arch/powerpc/il.h
+++ b/arch/powerpc/il.h
@@ -15,8 +15,27 @@ eg: cmp a, b
if a<b then c=0b100 (not setting SO, setting LT)
if a>b 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_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 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_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 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_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 40
+#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 5ee7d1dd..cd70a6aa 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 <stdlib.h>
#include <time.h>
+#include <unistd.h>
+
#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
+#define BATCH 10000000
+ opterr = 0;
- powerpc_init();
+ 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;
+ }
+ }
- 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 50c3eb5b..5e37f735 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 fe2b7fda..0eb14651 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