From 3c6cdd1fae2dcc4870326b8e288ebe46f48efb08 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 12 Mar 2024 13:18:38 -0400 Subject: [PATCH 01/35] added all the old stuff, need to decide on getopt for windows stuff --- arch/powerpc/CMakeLists.txt | 32 ++++++++++++++++++- arch/powerpc/arch_ppc.cpp | 48 ++++++++++++++++++++++++++--- arch/powerpc/disassembler.cpp | 18 ++++++----- arch/powerpc/disassembler.h | 7 +++-- arch/powerpc/test_asm.cpp | 4 +++ arch/powerpc/test_disasm.cpp | 58 +++++++++++++++++++++++++++++------ 6 files changed, 142 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index 57a68f6ee8..fe168576c1 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -2,8 +2,14 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) project(arch_ppc) +if((NOT BN_API_PATH) AND (NOT BN_INTERNAL_BUILD)) + set(BN_API_PATH $ENV{BN_API_PATH}) + if(NOT BN_API_PATH) + message(FATAL_ERROR "Provide path to Binary Ninja API source in BN_API_PATH") + endif() +endif() if(NOT BN_INTERNAL_BUILD) - add_subdirectory(${PROJECT_SOURCE_DIR}/../.. ${PROJECT_BINARY_DIR}/api) + add_subdirectory(${BN_API_PATH} ${PROJECT_BINARY_DIR}/api) endif() file(GLOB SOURCES @@ -47,3 +53,27 @@ 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 (${CMAKE_SYSTEM_NAME} MATCHES "Windows") + find_package(getopt_for_windows) + list(APPEND TEST_INCLUDE_LIST ${getopt_for_windows_INCLUDE_DIR}) + list(APPEND TEST_LINK_DIRECTORIES ${getopt_for_windows_LIB_DIR}) + list(APPEND TEST_LINK_LIBRARIES getopt_for_windows_static) + endif() + + add_executable(test_disasm test_disasm.cpp disassembler.cpp) + add_executable(test_asm test_asm.cpp assembler.cpp) + + 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() diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 6366db1689..4791a49d7a 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -281,6 +281,7 @@ class PowerpcArchitecture: public Architecture { private: BNEndianness endian; + int cs_mode_local; /* this can maybe be moved to the API later */ BNRegisterInfo RegisterInfo(uint32_t fullWidthReg, size_t offset, size_t size, bool zeroExtend = false) @@ -299,6 +300,14 @@ class PowerpcArchitecture: public Architecture PowerpcArchitecture(const char* name, BNEndianness endian_): Architecture(name) { endian = endian_; + cs_mode_local = 0; + } + + /* initialization list */ + PowerpcArchitecture(const char* name, BNEndianness endian_, int CS_MODE_): Architecture(name) + { + endian = endian_; + cs_mode_local = CS_MODE_; } /*************************************************************************/ @@ -360,7 +369,7 @@ class PowerpcArchitecture: public Architecture } /* decompose the instruction to get branch info */ - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) { + if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); return false; } @@ -622,7 +631,7 @@ class PowerpcArchitecture: public Architecture if (DoesQualifyForLocalDisassembly(data)) return PerformLocalDisassembly(data, addr, len, result); - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) { + if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); goto cleanup; } @@ -748,7 +757,7 @@ class PowerpcArchitecture: public Architecture goto cleanup; } - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) { + if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); il.AddInstruction(il.Undefined()); goto cleanup; @@ -922,7 +931,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 = ""; @@ -2471,6 +2480,15 @@ extern "C" Architecture* ppc = new PowerpcArchitecture("ppc", BigEndian); Architecture::Register(ppc); + Architecture* ppc_qpx = new PowerpcArchitecture("ppc_qpx", BigEndian, CS_MODE_QPX); + Architecture::Register(ppc_qpx); + + Architecture* ppc_spe = new PowerpcArchitecture("ppc_spe", BigEndian, CS_MODE_SPE); + Architecture::Register(ppc_spe); + + Architecture* ppc_ps = new PowerpcArchitecture("ppc_ps", BigEndian, CS_MODE_PS); + Architecture::Register(ppc_ps); + Architecture* ppc64 = new PowerpcArchitecture("ppc64", BigEndian); Architecture::Register(ppc64); @@ -2485,10 +2503,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); @@ -2502,9 +2529,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" @@ -2538,6 +2571,13 @@ extern "C" ppc /* the architecture */ ); + BinaryViewType::RegisterArchitecture( + "ELF", /* name of the binary view type */ + EM_PPC, /* id (key in m_arch map) */ + BigEndian, + ppc_ps /* the architecture */ + ); + BinaryViewType::RegisterArchitecture( "ELF", /* name of the binary view type */ EM_PPC64, /* id (key in m_arch map) */ diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 66a8b36dd3..24545fe053 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -19,7 +19,7 @@ thread_local csh handle_lil = 0; thread_local csh handle_big = 0; extern "C" int -powerpc_init(void) +powerpc_init(int cs_mode_arg) { int rc = -1; @@ -31,12 +31,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; } @@ -69,13 +69,13 @@ powerpc_release(void) extern "C" int powerpc_decompose(const uint8_t *data, int size, uint32_t addr, bool lil_end, - struct decomp_result *res) + struct decomp_result *res, 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 +120,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 +130,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) { @@ -174,10 +178,10 @@ powerpc_disassemble(struct decomp_result *res, char *buf, size_t len) } extern "C" const char * -powerpc_reg_to_str(uint32_t rid) +powerpc_reg_to_str(uint32_t rid, int cs_mode_arg) { 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 e1701687c9..e089244163 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -23,6 +23,7 @@ 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" //***************************************************************************** @@ -59,11 +60,11 @@ struct decomp_result //***************************************************************************** // function prototypes //***************************************************************************** -extern "C" int powerpc_init(void); +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 lil_end, struct decomp_result *result, int); 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); diff --git a/arch/powerpc/test_asm.cpp b/arch/powerpc/test_asm.cpp index 7f39179272..253b748644 100644 --- a/arch/powerpc/test_asm.cpp +++ b/arch/powerpc/test_asm.cpp @@ -23,7 +23,11 @@ using namespace std; #include #include +#if defined(_WIN32) +#include +#else #include +#endif #include "assembler.h" diff --git a/arch/powerpc/test_disasm.cpp b/arch/powerpc/test_disasm.cpp index b893d2ab9c..9c651ef181 100644 --- a/arch/powerpc/test_disasm.cpp +++ b/arch/powerpc/test_disasm.cpp @@ -15,9 +15,16 @@ g++ -std=c++11 -O0 -g -I capstone/include -L./build/capstone test_disasm.cpp dis #include #include +#if defined(_WIN32) +#include +#else +#include +#endif + #include "disassembler.h" int print_errors = 1; +int cs_mode_local = 0; int disas_instr_word(uint32_t instr_word, char *buf) { @@ -28,7 +35,7 @@ int disas_instr_word(uint32_t instr_word, char *buf) struct cs_detail *detail = &(res.detail); struct cs_ppc *ppc = &(detail->ppc); - if(powerpc_decompose((const uint8_t *)&instr_word, 4, 0, true, &res)) { + if(powerpc_decompose((const uint8_t *)&instr_word, 4, 0, true, &res, cs_mode_local)) { if(print_errors) printf("ERROR: powerpc_decompose()\n"); goto cleanup; } @@ -106,21 +113,52 @@ int disas_instr_word(uint32_t instr_word, char *buf) return rc; } +void usage() +{ + printf("send argument \"repl\" or \"speed\"\n"); +} + int main(int ac, char **av) { int rc = -1; char buf[256]; + int index; + char* disasm_cmd = 0; + int c; + +#define BATCH 10000000 + opterr = 0; + + while ((c = getopt(ac, av, "qsp")) != -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; + default: + usage(); + goto cleanup; + } + } - #define BATCH 10000000 - - powerpc_init(); - - if(ac <= 1) { - printf("send argument \"repl\" or \"speed\"\n"); + if (optind >= ac) + { + usage(); 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 +186,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 +205,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; From 767860f6ca31bc4768ff05492d9d6020932aa0b0 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 12 Mar 2024 13:26:47 -0400 Subject: [PATCH 02/35] forgot the unsubmodule changes --- arch/powerpc/CMakeLists.txt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index fe168576c1..5f90453179 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -2,14 +2,8 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) project(arch_ppc) -if((NOT BN_API_PATH) AND (NOT BN_INTERNAL_BUILD)) - set(BN_API_PATH $ENV{BN_API_PATH}) - if(NOT BN_API_PATH) - message(FATAL_ERROR "Provide path to Binary Ninja API source in BN_API_PATH") - endif() -endif() if(NOT BN_INTERNAL_BUILD) - add_subdirectory(${BN_API_PATH} ${PROJECT_BINARY_DIR}/api) + add_subdirectory(${PROJECT_SOURCE_DIR}/../.. ${PROJECT_BINARY_DIR}/api) endif() file(GLOB SOURCES From 8541410568fd41448ed3b72efb5afce017bc29fa Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 12 Mar 2024 13:41:27 -0400 Subject: [PATCH 03/35] removed windows compat stuff --- arch/powerpc/CMakeLists.txt | 27 +++++++++++---------------- arch/powerpc/test_asm.cpp | 4 ---- arch/powerpc/test_disasm.cpp | 4 ---- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index 5f90453179..95b19df983 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -53,21 +53,16 @@ if (DEFINED FORCE_TEST) set(TEST_LINK_DIRECTORIES ) set(TEST_LINK_LIBRARIES capstone) - if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") - find_package(getopt_for_windows) - list(APPEND TEST_INCLUDE_LIST ${getopt_for_windows_INCLUDE_DIR}) - list(APPEND TEST_LINK_DIRECTORIES ${getopt_for_windows_LIB_DIR}) - list(APPEND TEST_LINK_LIBRARIES getopt_for_windows_static) - endif() - - add_executable(test_disasm test_disasm.cpp disassembler.cpp) - add_executable(test_asm test_asm.cpp assembler.cpp) - - 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}) + if (${CMAKE_SYSTEM_NAME} NOT MATCHES "Windows") + add_executable(test_disasm test_disasm.cpp disassembler.cpp) + add_executable(test_asm test_asm.cpp assembler.cpp) + + 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}) + 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/test_asm.cpp b/arch/powerpc/test_asm.cpp index 253b748644..7f39179272 100644 --- a/arch/powerpc/test_asm.cpp +++ b/arch/powerpc/test_asm.cpp @@ -23,11 +23,7 @@ using namespace std; #include #include -#if defined(_WIN32) -#include -#else #include -#endif #include "assembler.h" diff --git a/arch/powerpc/test_disasm.cpp b/arch/powerpc/test_disasm.cpp index 9c651ef181..6f1615a18e 100644 --- a/arch/powerpc/test_disasm.cpp +++ b/arch/powerpc/test_disasm.cpp @@ -15,11 +15,7 @@ g++ -std=c++11 -O0 -g -I capstone/include -L./build/capstone test_disasm.cpp dis #include #include -#if defined(_WIN32) -#include -#else #include -#endif #include "disassembler.h" From 8207badb88d7bdb37f10a10713fb15830147725f Mon Sep 17 00:00:00 2001 From: David Riusech Date: Mon, 18 Mar 2024 10:04:04 -0400 Subject: [PATCH 04/35] early lifting, missing fcmpo --- arch/powerpc/il.cpp | 51 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 1de2c5c090..c5aee3064b 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1574,6 +1574,53 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(il.Trap(0)); break; + case PPC_INS_STFS: + REQUIRE2OPS + ei0 = il.Store(4, + operToIL(il, oper1), + operToIL(il, oper0) + ); + il.AddInstruction(ei0); + + break; + + case PPC_INS_STFD: + REQUIRE2OPS + ei0 = il.Store(8, + operToIL(il, oper1), + operToIL(il, oper0) + ); + 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)] + il.AddInstruction(ei0); + + 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); + + break; + + // 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; + + case PPC_INS_BCL: case PPC_INS_BCLR: case PPC_INS_BCLRL: @@ -1821,13 +1868,11 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LDU: case PPC_INS_LDUX: case PPC_INS_LDX: - 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: @@ -1899,12 +1944,10 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STDU: case PPC_INS_STDUX: case PPC_INS_STDX: - 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: From e6754f72668fd69eb531493c85fde5dc78ba07b5 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 29 Mar 2024 08:27:55 -0400 Subject: [PATCH 05/35] mac support, needed threadlocal for the disassembler.cpp --- arch/powerpc/CMakeLists.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index 95b19df983..3b3b890cdf 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -53,9 +53,23 @@ if (DEFINED FORCE_TEST) set(TEST_LINK_DIRECTORIES ) set(TEST_LINK_LIBRARIES capstone) - if (${CMAKE_SYSTEM_NAME} NOT MATCHES "Windows") + 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) + + set_target_properties(test_disasm PROPERTIES + CXX_STANDARD 17 + CXX_VISIBILITY_PRESET hidden + CXX_STANDARD_REQUIRED ON + VISIBILITY_INLINES_HIDDEN ON + POSITION_INDEPENDENT_CODE ON) + + set_target_properties(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}) From f2950ea028c89a136e80294ca53893f378c52662 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 29 Mar 2024 16:39:05 -0400 Subject: [PATCH 06/35] moved around the external routines, and added them to the il --- arch/powerpc/CMakeLists.txt | 9 +- arch/powerpc/arch_ppc.cpp | 175 ++++++++-------------------------- arch/powerpc/disassembler.cpp | 78 +++++++++++++++ arch/powerpc/disassembler.h | 16 ++++ arch/powerpc/il.cpp | 35 +++++-- arch/powerpc/test_disasm.cpp | 3 +- 6 files changed, 162 insertions(+), 154 deletions(-) diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index 3b3b890cdf..7848fe1819 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -57,14 +57,7 @@ if (DEFINED FORCE_TEST) add_executable(test_disasm test_disasm.cpp disassembler.cpp) add_executable(test_asm test_asm.cpp assembler.cpp) - set_target_properties(test_disasm PROPERTIES - CXX_STANDARD 17 - CXX_VISIBILITY_PRESET hidden - CXX_STANDARD_REQUIRED ON - VISIBILITY_INLINES_HIDDEN ON - POSITION_INDEPENDENT_CODE ON) - - set_target_properties(test_asm PROPERTIES + set_target_properties(test_disasm test_asm PROPERTIES CXX_STANDARD 17 CXX_VISIBILITY_PRESET hidden CXX_STANDARD_REQUIRED ON diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index a0f5176ade..d2fecb9f41 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -358,7 +358,7 @@ class PowerpcArchitecture: public Architecture return false; } - if (DoesQualifyForLocalDisassembly(data)) { + if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) { result.length = 4; return true; } @@ -457,149 +457,56 @@ class PowerpcArchitecture: public Architecture return true; } - bool DoesQualifyForLocalDisassembly(const uint8_t *data) - { - uint32_t insword = *(uint32_t *)data; - if(endian == BigEndian) - insword = bswap32(insword); - - // 111111xxx00xxxxxxxxxx00001000000 <- fcmpo - uint32_t tmp = insword & 0xFC6007FF; - if (tmp==0xFC000040) - return true; - // 111100xxxxxxxxxxxxxxx00111010xxx <- xxpermr - if((insword & 0xFC0007F8) == 0xF00001D0) - return true; - // 000100xxxxxxxxxxxxxxxxxxx000110x <- psq_lx - // 000100xxxxxxxxxxxxxxxxxxx000111x <- psq_stx - // 000100xxxxxxxxxxxxxxxxxxx100110x <- psq_lux - // 000100xxxxxxxxxxxxxxxxxxx100111x <- psq_stux - tmp = insword & 0xFC00007E; - if (tmp==0x1000000C || tmp==0x1000000E || tmp==0x1000004C || tmp==0x1000004E) - return true; - // 000100xxxxxxxxxx00000xxxxx011000 <- ps_muls0 - // 000100xxxxxxxxxx00000xxxxx011001 <- ps_muls0. - // 000100xxxxxxxxxx00000xxxxx011010 <- ps_muls1 - // 000100xxxxxxxxxx00000xxxxx011011 <- ps_muls1. - tmp = insword & 0xFC00F83F; - if (tmp==0x10000018 || tmp==0x10000019 || tmp==0x1000001A || tmp==0x1000001B) - return true; - - return false; - } - - bool PerformLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, vector &result) + bool PrintLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, vector &result, decomp_result* res) { (void)addr; + char buf[16]; + uint32_t local_op = PPC_INS_INVALID; - if (len < 4) return false; - uint32_t insword = *(uint32_t *)data; - if(endian == BigEndian) - insword = bswap32(insword); + struct cs_detail *detail = 0; + struct cs_ppc *ppc = 0; + struct cs_insn *insn = &(res->insn); + + detail = &(res->detail); + ppc = &(detail->ppc); + if (len < 4) + return false; len = 4; - char buf[16]; + local_op = DoesQualifyForLocalDisassembly(data, endian == BigEndian); + PerformLocalDisassembly(data, addr, len, res, endian == BigEndian); - // 111111AAA00BBBBBCCCCC00001000000 "fcmpo crA,fB,fC" - uint32_t tmp = insword & 0xFC6007FF; - if (tmp==0xFC000040) { - result.emplace_back(InstructionToken, "fcmpo"); + switch (local_op) + { + case PPC_INS_BN_FCMPO: + result.emplace_back(InstructionToken, insn->mnemonic); result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "cr%d", (insword >> 23) & 7); + snprintf(buf, sizeof(buf), "cr%d", ppc->operands[0].reg); result.emplace_back(RegisterToken, buf); result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "f%d", (insword >> 16) & 31); + snprintf(buf, sizeof(buf), "f%d", ppc->operands[1].reg); 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); + snprintf(buf, sizeof(buf), "f%d", ppc->operands[2].reg); 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); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "r%d", (insword & 0x1F0000) >> 16); - result.emplace_back(RegisterToken, buf); - result.emplace_back(OperandSeparatorToken, ", "); - snprintf(buf, sizeof(buf), "r%d", (insword & 0xF800) >> 11); - 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); 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); 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); result.emplace_back(RegisterToken, buf); - return true; + break; + default: + return false; } - - return false; + return true; } /* populate the vector result with InstructionTextToken @@ -623,9 +530,9 @@ class PowerpcArchitecture: public Architecture goto cleanup; } - if (DoesQualifyForLocalDisassembly(data)) - return PerformLocalDisassembly(data, addr, len, result); - + if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) + // PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); + return PrintLocalDisassembly(data, addr, len, result, &res); if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); goto cleanup; @@ -733,6 +640,7 @@ class PowerpcArchitecture: public Architecture 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"); @@ -743,21 +651,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, cs_mode_local)) { + else if(powerpc_decompose(data, 4, (uint32_t)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; diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 31ac753cce..4468453722 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -12,12 +12,90 @@ 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) +{ + // 111111AAA00BBBBBCCCCC00001000000 "fcmpo crA,fB,fC" + res->detail.ppc.operands[0].reg = (ppc_reg)(PPC_REG_CR0 + (insword >> 23) & 7); + res->detail.ppc.operands[0].type = PPC_OP_REG; + res->detail.ppc.operands[1].reg = (ppc_reg)(PPC_REG_F0 + (insword >> 16) & 31); + res->detail.ppc.operands[1].type = PPC_OP_REG; + res->detail.ppc.operands[2].reg = (ppc_reg)(PPC_REG_F0 + (insword >> 11) & 31); + res->detail.ppc.operands[2].type = PPC_OP_REG; + + res->insn.id = PPC_INS_BN_FCMPO; + res->detail.ppc.op_count = 3; + strncpy(res->insn.mnemonic, "fcmpo", sizeof(res->insn.mnemonic)); +} + +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 = 0; + + 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(int cs_mode_arg) { diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index 79bc9729e2..9a5d79c385 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -33,6 +33,19 @@ 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_PSQ_LX, + PPC_INS_BN_PSQ_STX, + PPC_INS_BN_PSQ_LUX, + PPC_INS_BN_PSQ_STUX, + PPC_INS_BN_PS_MULS0, + PPC_INS_BN_PS_MULS0D, + PPC_INS_BN_PS_MULS1, + PPC_INS_BN_PS_MULS1D, + PPC_INS_BN_ENDING +} ppc_insn_bn; /* operand type */ enum operand_type_t { REG, VAL, LABEL }; @@ -60,6 +73,9 @@ struct decomp_result //***************************************************************************** // function prototypes //***************************************************************************** +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, diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index ed6e29a002..8cd9b104d2 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -451,6 +451,9 @@ 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; /* bypass capstone path for *all* branching instructions; capstone * is too difficult to work with and is outright broken for some @@ -459,9 +462,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 , , , , @@ -714,11 +717,26 @@ 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; + // TODO: high level IL is sometimes assuming incorrect variables, and setting floating points to + // standard registers. + // TODO: high level IL is accidentilly adding an extra subtract operand and assigning it to no one. + // TODO: final assignment for the fcmp is whether or not the sub is 0, not greater than 0. + case PPC_INS_FCMPU: + REQUIRE3OPS + ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); + il.AddInstruction(ei0); + break; + + case PPC_INS_BN_FCMPO: + REQUIRE3OPS + ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); + il.AddInstruction(ei0); + break; + + case PPC_INS_FMR: + REQUIRE2OPS + il.AddInstruction(il.SetRegister(4, oper0->reg, operToIL(il, oper1))); + break; case PPC_INS_CRAND: case PPC_INS_CRANDC: @@ -1954,7 +1972,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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: diff --git a/arch/powerpc/test_disasm.cpp b/arch/powerpc/test_disasm.cpp index db60773e0f..ee9e7f7f0c 100644 --- a/arch/powerpc/test_disasm.cpp +++ b/arch/powerpc/test_disasm.cpp @@ -22,6 +22,7 @@ g++ -std=c++11 -O0 -g -I capstone/include -L./build/capstone test_disasm.cpp dis int print_errors = 1; int cs_mode_local = 0; size_t address_size_ = 4; +bool bigendian = true; int disas_instr_word(uint32_t instr_word, char *buf) { @@ -32,7 +33,7 @@ int disas_instr_word(uint32_t instr_word, char *buf) struct cs_detail *detail = &(res.detail); struct cs_ppc *ppc = &(detail->ppc); - if(powerpc_decompose((const uint8_t *)&instr_word, 4, 0, true, &res, address_size_, cs_mode_local)) { + if(powerpc_decompose((const uint8_t *)&instr_word, 4, 0, bigendian, &res, address_size_, cs_mode_local)) { if(print_errors) printf("ERROR: powerpc_decompose()\n"); goto cleanup; } From ae8021177c9fe3c4e70d84f5b068ff765dd170f4 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 29 Mar 2024 16:59:31 -0400 Subject: [PATCH 07/35] removed duplicate enums --- arch/powerpc/disassembler.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index 9a5d79c385..16a9a34302 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -36,14 +36,6 @@ enum ppc_status_t { typedef enum ppc_insn_bn { PPC_INS_BN_FCMPO = PPC_INS_ENDING+1, PPC_INS_BN_XXPERMR, - PPC_INS_BN_PSQ_LX, - PPC_INS_BN_PSQ_STX, - PPC_INS_BN_PSQ_LUX, - PPC_INS_BN_PSQ_STUX, - PPC_INS_BN_PS_MULS0, - PPC_INS_BN_PS_MULS0D, - PPC_INS_BN_PS_MULS1, - PPC_INS_BN_PS_MULS1D, PPC_INS_BN_ENDING } ppc_insn_bn; From 249bb518e1b61ce3c207053a59adc68799c65be8 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 7 May 2024 02:08:07 -0400 Subject: [PATCH 08/35] fixed disassembly for fp stuff --- arch/powerpc/CMakeLists.txt | 2 + arch/powerpc/arch_ppc.cpp | 14 ++++--- arch/powerpc/disassembler.cpp | 76 ++++++++++++++++++++++++++++++++--- arch/powerpc/test_disasm.cpp | 17 ++++++-- 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/CMakeLists.txt b/arch/powerpc/CMakeLists.txt index 7848fe1819..d148c690a1 100644 --- a/arch/powerpc/CMakeLists.txt +++ b/arch/powerpc/CMakeLists.txt @@ -57,6 +57,8 @@ if (DEFINED FORCE_TEST) 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 diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index d2fecb9f41..4784657889 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -482,25 +482,25 @@ class PowerpcArchitecture: public Architecture case PPC_INS_BN_FCMPO: result.emplace_back(InstructionToken, insn->mnemonic); result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "cr%d", ppc->operands[0].reg); + 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), "f%d", ppc->operands[1].reg); + 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), "f%d", ppc->operands[2].reg); + snprintf(buf, sizeof(buf), "f%d", ppc->operands[2].reg - PPC_REG_F0); result.emplace_back(RegisterToken, buf); break; case PPC_INS_BN_XXPERMR: result.emplace_back(InstructionToken, insn->mnemonic); result.emplace_back(TextToken, " "); - snprintf(buf, sizeof(buf), "vs%d", ppc->operands[0].reg); + 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), "vs%d", ppc->operands[1].reg); + 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), "vs%d", ppc->operands[2].reg); + snprintf(buf, sizeof(buf), "vs%d", ppc->operands[2].reg - PPC_REG_VS0); result.emplace_back(RegisterToken, buf); break; default: @@ -531,8 +531,10 @@ class PowerpcArchitecture: public Architecture } if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) + { // PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); return PrintLocalDisassembly(data, addr, len, result, &res); + } if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); goto cleanup; diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 4468453722..71c2f846dc 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -26,7 +26,9 @@ int DoesQualifyForLocalDisassembly(const uint8_t *data, bool bigendian) uint32_t tmp = 0; if(bigendian == true) + { insword = bswap32(insword); + } // 111111xxx00xxxxxxxxxx00001000000 <- fcmpo tmp = insword & 0xFC6007FF; @@ -41,17 +43,78 @@ int DoesQualifyForLocalDisassembly(const uint8_t *data, bool bigendian) void ppc_fcmpo(uint32_t insword, decomp_result *res) { + unsigned regtmp = 0; + // 111111AAA00BBBBBCCCCC00001000000 "fcmpo crA,fB,fC" - res->detail.ppc.operands[0].reg = (ppc_reg)(PPC_REG_CR0 + (insword >> 23) & 7); + 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; - res->detail.ppc.operands[1].reg = (ppc_reg)(PPC_REG_F0 + (insword >> 16) & 31); + + 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; - res->detail.ppc.operands[2].reg = (ppc_reg)(PPC_REG_F0 + (insword >> 11) & 31); + + 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; - strncpy(res->insn.mnemonic, "fcmpo", sizeof(res->insn.mnemonic)); } void ppc_xxpermr(uint32_t insword, decomp_result *res) @@ -76,10 +139,13 @@ void ppc_xxpermr(uint32_t insword, decomp_result *res) 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 = 0; + uint32_t insword = *(uint32_t *)data; if(bigendian == true) + { insword = bswap32(insword); + } + local_op = DoesQualifyForLocalDisassembly(data, bigendian); switch(local_op) diff --git a/arch/powerpc/test_disasm.cpp b/arch/powerpc/test_disasm.cpp index ee9e7f7f0c..00bcdab019 100644 --- a/arch/powerpc/test_disasm.cpp +++ b/arch/powerpc/test_disasm.cpp @@ -28,14 +28,25 @@ 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, bigendian, &res, address_size_, cs_mode_local)) { - if(print_errors) printf("ERROR: powerpc_decompose()\n"); - goto cleanup; + if(print_errors) + { + if (DoesQualifyForLocalDisassembly((uint8_t*)&instr_word, !bigendian) != PPC_INS_INVALID) + { + size_t instsz = 4; + PerformLocalDisassembly((uint8_t*)&instr_word, 0, instsz, &res, !bigendian); + } + else + { + printf("ERROR: powerpc_decompose()\n"); + goto cleanup; + } + } } /* MEGA DETAILS, IF YOU WANT 'EM */ From 4d6c5a7e30065de5f564bef752065330db6dc653 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Wed, 8 May 2024 18:16:20 -0400 Subject: [PATCH 09/35] adding mips tester --- arch/mips/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/mips/CMakeLists.txt b/arch/mips/CMakeLists.txt index b85248c841..8220971523 100644 --- a/arch/mips/CMakeLists.txt +++ b/arch/mips/CMakeLists.txt @@ -46,3 +46,6 @@ if(BN_INTERNAL_BUILD) LIBRARY_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR} RUNTIME_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR}) endif() + +add_executable(mipstest mips/mips.c mips/test.c) +target_link_libraries(mipstest PRIVATE arch_mips) From f6c8b412ed5b078ac68271c0688b7e21a37931ec Mon Sep 17 00:00:00 2001 From: David Riusech Date: Wed, 8 May 2024 19:19:52 -0400 Subject: [PATCH 10/35] test rework, gonna add the capstone stuff --- arch/mips/mips/test.c | 81 ++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/arch/mips/mips/test.c b/arch/mips/mips/test.c index fbe8335a61..26ba599b15 100644 --- a/arch/mips/mips/test.c +++ b/arch/mips/mips/test.c @@ -7,10 +7,11 @@ b mips_disassemble #include #include +#include #include "mips.h" -int disassemble(uint32_t insword, uint64_t address, enum MipsVersion version, char *result) +int disassemble(uint32_t insword, uint64_t address, MipsVersion version, char *result) { int rc; Instruction instr; @@ -39,42 +40,72 @@ int disassemble(uint32_t insword, uint64_t address, enum MipsVersion version, ch exit(-1); \ } +void usage(char** av) +{ + printf("usage:\n"); + printf("\t%s [instruction_words]\n", av[0]); + printf("\t%s test\n", av[0]); + printf("example:\n"); + printf("\t%s 3c028081 68435a50 24445a50 6c830007\n", av[0]); + printf("\t%s test\n", av[0]); + exit(-1); +} + int main(int ac, char **av) { char instxt[4096]; + uint32_t insword = 0; + uint64_t baseaddr = 0; + int instindex = 0; + int c = 0; - if(ac == 1) { - printf("usage:\n"); - printf("\t%s [
] \n", av[0]); - printf("\t%s \n", av[0]); - printf("\t%s test\n", av[0]); - printf("examples:\n"); - printf("\t%s 0 14E00003\n", av[0]); - printf("\t%s 00405A58 14E00003\n", av[0]); - printf("\t%s test\n", av[0]); - exit(-1); + while ((c = getopt(ac, av, "a:")) != -1) + { + switch (c) + { + case 'a': + baseaddr = strtoull(optarg, NULL, 0x10); + break; + default: + usage(av); + goto cleanup; + } } - if(ac == 2 && !strcmp(av[1], "test")) { + if (optind >= ac) + { + usage(av); + goto cleanup; + } + + instindex = optind; + + if (ac == 2 && !strcmp(av[1], "test")) + { disassemble(0x14E00003, 0, MIPS_32, instxt); ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x10")); - disassemble(0x14E00003, 0x405a58, MIPS_32, instxt); + disassemble(0x14E00003, 4, MIPS_32, instxt); ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x405a68")); exit(0); } - uint64_t address = 0; - uint32_t insword = 0; - if(ac == 2) { - address = 0; - insword = strtoul(av[1], NULL, 16); - } - else if(ac == 3) { - address = strtoul(av[1], NULL, 16); - insword = strtoul(av[2], NULL, 16); - } + while (instindex < ac) + { + insword = strtoul(av[instindex], NULL, 16); - if(0 == disassemble(insword, address, MIPS_32, instxt)) { - printf("%08llX: %08X %s\n", address, insword, instxt); + if (0 == disassemble(insword, baseaddr, MIPS_32, instxt)) + { + printf("%08llX: %08X %s\n", baseaddr, insword, instxt); + } + else + { + printf("%08llX: %08X ??\n", baseaddr, insword); + } + + baseaddr += 4; + instindex++; } + +cleanup: + return 0; } From 19fe070b0a608af66afd5f326191ffe838ea3f5d Mon Sep 17 00:00:00 2001 From: David Riusech Date: Wed, 8 May 2024 20:40:20 -0400 Subject: [PATCH 11/35] adding test updates and new architecture mips3 to disassembly --- arch/mips/arch_mips.cpp | 35 +++++++++++++++++++++++++---------- arch/mips/mips/test.c | 24 ++++++++++++++++++++---- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/arch/mips/arch_mips.cpp b/arch/mips/arch_mips.cpp index 6a3d80e4d7..8928ffae67 100644 --- a/arch/mips/arch_mips.cpp +++ b/arch/mips/arch_mips.cpp @@ -182,19 +182,24 @@ class MipsArchitecture: public Architecture size_t m_bits; BNEndianness m_endian; uint32_t m_enablePseudoOps; + MipsVersion version_overwrite; virtual bool Disassemble(const uint8_t* data, uint64_t addr, size_t maxLen, Instruction& result) { + MipsVersion version = version_overwrite; + memset(&result, 0, sizeof(result)); - if (mips_decompose((uint32_t*)data, maxLen, &result, m_bits == 64 ? MIPS_64 : MIPS_32, addr, m_endian, m_enablePseudoOps) != 0) + if (m_bits == 64) + { + version = MIPS_64; + } + + if (mips_decompose((uint32_t*)data, maxLen, &result, version, addr, m_endian, m_enablePseudoOps) != 0) return false; return true; } - virtual size_t GetAddressSize() const override - { - return m_bits / 8; - } + virtual size_t GetAddressSize() const override { return m_bits / 8; } size_t InstructionHasBranchDelay(const Instruction& instr) { @@ -383,7 +388,8 @@ class MipsArchitecture: public Architecture } public: - MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits): Architecture(name), m_bits(bits), m_endian(endian) + MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits, MipsVersion version_in): + Architecture(name), m_bits(bits), m_endian(endian), version_overwrite(version_in) { Ref settings = Settings::Instance(); m_enablePseudoOps = settings->Get("arch.mips.disassembly.pseudoOps") ? 1 : 0; @@ -2228,12 +2234,14 @@ extern "C" { InitMipsSettings(); - Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32); - Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32); - Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64); + Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32, MIPS_32); + Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32, MIPS_32); + Architecture* mips3 = new MipsArchitecture("mips3", BigEndian, 32, MIPS_3); + Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64, MIPS_64); Architecture::Register(mipsel); Architecture::Register(mipseb); + Architecture::Register(mips3); Architecture::Register(mips64eb); /* calling conventions */ @@ -2242,9 +2250,11 @@ extern "C" MipsN64CallingConvention* n64BE = new MipsN64CallingConvention(mips64eb); mipsel->RegisterCallingConvention(o32LE); - mipseb->RegisterCallingConvention(o32BE); mipsel->SetDefaultCallingConvention(o32LE); + mipseb->RegisterCallingConvention(o32BE); mipseb->SetDefaultCallingConvention(o32BE); + mips3->RegisterCallingConvention(o32BE); + mips3->SetDefaultCallingConvention(o32BE); mips64eb->RegisterCallingConvention(n64BE); mips64eb->SetDefaultCallingConvention(n64BE); @@ -2252,17 +2262,21 @@ extern "C" MipsLinuxSyscallCallingConvention* linuxSyscallBE = new MipsLinuxSyscallCallingConvention(mipseb); mipsel->RegisterCallingConvention(linuxSyscallLE); mipseb->RegisterCallingConvention(linuxSyscallBE); + mips3->RegisterCallingConvention(linuxSyscallBE); mipsel->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipsel)); mipseb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipseb)); + mips3->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips3)); mips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64eb)); /* function recognizers */ mipsel->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); mipseb->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); + mips3->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); mipsel->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mipseb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); + mips3->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); // Register the architectures with the binary format parsers so that they know when to use @@ -2278,6 +2292,7 @@ extern "C" BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS64, BigEndian, mips64eb); BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, LittleEndian, mipsel); BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, BigEndian, mipseb); + BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, BigEndian, mips3); BinaryViewType::RegisterArchitecture("PE", 0x166, LittleEndian, mipsel); return true; } diff --git a/arch/mips/mips/test.c b/arch/mips/mips/test.c index 26ba599b15..2062db6e5b 100644 --- a/arch/mips/mips/test.c +++ b/arch/mips/mips/test.c @@ -58,11 +58,27 @@ int main(int ac, char **av) uint64_t baseaddr = 0; int instindex = 0; int c = 0; + int version = MIPS_32; - while ((c = getopt(ac, av, "a:")) != -1) + while ((c = getopt(ac, av, "klmnoa:")) != -1) { switch (c) { + case 'k': + version = MIPS_64; + break; + case 'l': + version = MIPS_1; + break; + case 'm': + version = MIPS_2; + break; + case 'n': + version = MIPS_3; + break; + case 'o': + version = MIPS_4; + break; case 'a': baseaddr = strtoull(optarg, NULL, 0x10); break; @@ -82,9 +98,9 @@ int main(int ac, char **av) if (ac == 2 && !strcmp(av[1], "test")) { - disassemble(0x14E00003, 0, MIPS_32, instxt); + disassemble(0x14E00003, 0, version, instxt); ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x10")); - disassemble(0x14E00003, 4, MIPS_32, instxt); + disassemble(0x14E00003, 4, version, instxt); ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x405a68")); exit(0); } @@ -93,7 +109,7 @@ int main(int ac, char **av) { insword = strtoul(av[instindex], NULL, 16); - if (0 == disassemble(insword, baseaddr, MIPS_32, instxt)) + if (0 == disassemble(insword, baseaddr, version, instxt)) { printf("%08llX: %08X %s\n", baseaddr, insword, instxt); } From 9dcd245558cbc44e443a8773bc0a7354b870e495 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Thu, 9 May 2024 18:31:49 -0400 Subject: [PATCH 12/35] cmakelist needed patch so it could build on mac and windows for mips --- arch/mips/CMakeLists.txt | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/mips/CMakeLists.txt b/arch/mips/CMakeLists.txt index 8220971523..296a9b1a63 100644 --- a/arch/mips/CMakeLists.txt +++ b/arch/mips/CMakeLists.txt @@ -47,5 +47,21 @@ if(BN_INTERNAL_BUILD) RUNTIME_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR}) endif() -add_executable(mipstest mips/mips.c mips/test.c) -target_link_libraries(mipstest PRIVATE arch_mips) +if (DEFINED FORCE_TEST) + + if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") + add_executable(mipstest mips/mips.c mips/test.c) + + target_compile_definitions(mipstest PRIVATE FORCE_TEST=1) + + set_target_properties(mipstest PROPERTIES + CXX_STANDARD 17 + CXX_VISIBILITY_PRESET hidden + CXX_STANDARD_REQUIRED ON + VISIBILITY_INLINES_HIDDEN ON + POSITION_INDEPENDENT_CODE ON) + + target_link_libraries(mipstest PRIVATE arch_mips) + endif() +endif() + From cd28c25374ba9b34be38f973f71e3ca329a1aa57 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Sat, 18 May 2024 03:06:59 -0400 Subject: [PATCH 13/35] pull and test_disasm --- arch/powerpc/test_disasm.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/test_disasm.cpp b/arch/powerpc/test_disasm.cpp index 00bcdab019..bae7f10823 100644 --- a/arch/powerpc/test_disasm.cpp +++ b/arch/powerpc/test_disasm.cpp @@ -22,7 +22,8 @@ g++ -std=c++11 -O0 -g -I capstone/include -L./build/capstone test_disasm.cpp dis int print_errors = 1; int cs_mode_local = 0; size_t address_size_ = 4; -bool bigendian = true; +// data in default with strtoul is little endian +bool littleendian = true; int disas_instr_word(uint32_t instr_word, char *buf) { @@ -33,13 +34,13 @@ int disas_instr_word(uint32_t instr_word, char *buf) struct cs_detail *detail = &(res.detail); struct cs_ppc *ppc = &(detail->ppc); - if(powerpc_decompose((const uint8_t *)&instr_word, 4, 0, bigendian, &res, address_size_, cs_mode_local)) { + 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, !bigendian) != PPC_INS_INVALID) + if (DoesQualifyForLocalDisassembly((uint8_t*)&instr_word, !littleendian) != PPC_INS_INVALID) { size_t instsz = 4; - PerformLocalDisassembly((uint8_t*)&instr_word, 0, instsz, &res, !bigendian); + PerformLocalDisassembly((uint8_t*)&instr_word, 0, instsz, &res, !littleendian); } else { From a194ba6d1a47237a932d7f527daf39910e4ce9aa Mon Sep 17 00:00:00 2001 From: David Riusech Date: Sat, 19 Oct 2024 15:16:29 -0400 Subject: [PATCH 14/35] stashed the mips changes --- arch/mips/CMakeLists.txt | 19 -------- arch/mips/arch_mips.cpp | 42 ++++++----------- arch/mips/mips/test.c | 99 +++++++++++----------------------------- 3 files changed, 40 insertions(+), 120 deletions(-) diff --git a/arch/mips/CMakeLists.txt b/arch/mips/CMakeLists.txt index 296a9b1a63..b85248c841 100644 --- a/arch/mips/CMakeLists.txt +++ b/arch/mips/CMakeLists.txt @@ -46,22 +46,3 @@ if(BN_INTERNAL_BUILD) LIBRARY_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR} RUNTIME_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR}) endif() - -if (DEFINED FORCE_TEST) - - if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") - add_executable(mipstest mips/mips.c mips/test.c) - - target_compile_definitions(mipstest PRIVATE FORCE_TEST=1) - - set_target_properties(mipstest PROPERTIES - CXX_STANDARD 17 - CXX_VISIBILITY_PRESET hidden - CXX_STANDARD_REQUIRED ON - VISIBILITY_INLINES_HIDDEN ON - POSITION_INDEPENDENT_CODE ON) - - target_link_libraries(mipstest PRIVATE arch_mips) - endif() -endif() - diff --git a/arch/mips/arch_mips.cpp b/arch/mips/arch_mips.cpp index e4b4b0d995..938facde07 100644 --- a/arch/mips/arch_mips.cpp +++ b/arch/mips/arch_mips.cpp @@ -181,25 +181,20 @@ class MipsArchitecture: public Architecture protected: size_t m_bits; BNEndianness m_endian; - MipsVersion version_overwrite; uint32_t m_decomposeFlags; virtual bool Disassemble(const uint8_t* data, uint64_t addr, size_t maxLen, Instruction& result) { - MipsVersion version = version_overwrite; - memset(&result, 0, sizeof(result)); - if (m_bits == 64) - { - version = MIPS_64; - } - - if (mips_decompose((uint32_t*)data, maxLen, &result, version, addr, m_endian, m_decomposeFlags) != 0) + if (mips_decompose((uint32_t*)data, maxLen, &result, m_bits == 64 ? MIPS_64 : MIPS_32, addr, m_endian, m_decomposeFlags) != 0) return false; return true; } - virtual size_t GetAddressSize() const override { return m_bits / 8; } + virtual size_t GetAddressSize() const override + { + return m_bits / 8; + } size_t InstructionHasBranchDelay(const Instruction& instr) { @@ -407,8 +402,8 @@ class MipsArchitecture: public Architecture } public: - MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits, MipsVersion version_in, uint32_t decomposeFlags = 0) - : Architecture(name), m_bits(bits), m_endian(endian), version_overwrite(version_in), m_decomposeFlags(decomposeFlags) + MipsArchitecture(const std::string& name, BNEndianness endian, size_t bits, uint32_t decomposeFlags = 0) + : Architecture(name), m_bits(bits), m_endian(endian), m_decomposeFlags(decomposeFlags) { Ref settings = Settings::Instance(); uint32_t flag_pseudo_ops = settings->Get("arch.mips.disassembly.pseudoOps") ? DECOMPOSE_FLAGS_PSEUDO_OP : 0; @@ -3243,20 +3238,18 @@ extern "C" { InitMipsSettings(); - Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32, MIPS_32); - Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32, MIPS_32); - Architecture* mips3 = new MipsArchitecture("mips3", BigEndian, 32, MIPS_3); - Architecture* mips64el = new MipsArchitecture("mipsel64", LittleEndian, 64, MIPS_64); - Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64, MIPS_64); - Architecture* cnmips64eb = new MipsArchitecture("cavium-mips64", BigEndian, 64, MIPS_64, DECOMPOSE_FLAGS_CAVIUM); + Architecture* mipsel = new MipsArchitecture("mipsel32", LittleEndian, 32); + Architecture* mipseb = new MipsArchitecture("mips32", BigEndian, 32); + Architecture* mips64el = new MipsArchitecture("mipsel64", LittleEndian, 64); + Architecture* mips64eb = new MipsArchitecture("mips64", BigEndian, 64); + Architecture* cnmips64eb = new MipsArchitecture("cavium-mips64", BigEndian, 64, DECOMPOSE_FLAGS_CAVIUM); Architecture::Register(mipsel); Architecture::Register(mipseb); - Architecture::Register(mips3); Architecture::Register(mips64el); Architecture::Register(mips64eb); Architecture::Register(cnmips64eb); - + /* calling conventions */ MipsO32CallingConvention* o32LE = new MipsO32CallingConvention(mipsel); MipsO32CallingConvention* o32BE = new MipsO32CallingConvention(mipseb); @@ -3265,11 +3258,9 @@ extern "C" MipsN64CallingConvention* n64BEc = new MipsN64CallingConvention(cnmips64eb); mipsel->RegisterCallingConvention(o32LE); - mipsel->SetDefaultCallingConvention(o32LE); mipseb->RegisterCallingConvention(o32BE); + mipsel->SetDefaultCallingConvention(o32LE); mipseb->SetDefaultCallingConvention(o32BE); - mips3->RegisterCallingConvention(o32BE); - mips3->SetDefaultCallingConvention(o32BE); mips64el->RegisterCallingConvention(n64LE); mips64el->SetDefaultCallingConvention(n64LE); mips64eb->RegisterCallingConvention(n64BE); @@ -3281,11 +3272,9 @@ extern "C" MipsLinuxSyscallCallingConvention* linuxSyscallBE = new MipsLinuxSyscallCallingConvention(mipseb); mipsel->RegisterCallingConvention(linuxSyscallLE); mipseb->RegisterCallingConvention(linuxSyscallBE); - mips3->RegisterCallingConvention(linuxSyscallBE); mipsel->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipsel)); mipseb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mipseb)); - mips3->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips3)); mips64el->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64el)); mips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(mips64eb)); cnmips64eb->RegisterCallingConvention(new MipsLinuxRtlResolveCallingConvention(cnmips64eb)); @@ -3293,11 +3282,9 @@ extern "C" /* function recognizers */ mipsel->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); mipseb->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); - mips3->RegisterFunctionRecognizer(new MipsImportedFunctionRecognizer()); mipsel->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mipseb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); - mips3->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mips64el->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); mips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); cnmips64eb->RegisterRelocationHandler("ELF", new MipsElfRelocationHandler()); @@ -3316,7 +3303,6 @@ extern "C" BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS64, BigEndian, mips64eb); BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, LittleEndian, mipsel); BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, BigEndian, mipseb); - BinaryViewType::RegisterArchitecture("ELF", ARCH_ID_MIPS32, BigEndian, mips3); Ref elf = BinaryViewType::GetByName("ELF"); if (elf) diff --git a/arch/mips/mips/test.c b/arch/mips/mips/test.c index 3d17a22111..c2bf633319 100644 --- a/arch/mips/mips/test.c +++ b/arch/mips/mips/test.c @@ -7,12 +7,11 @@ b mips_disassemble #include #include -#include #include #include "mips.h" -int disassemble(uint32_t insword, uint64_t address, MipsVersion version, char *result) +int disassemble(uint32_t insword, uint64_t address, enum MipsVersion version, char *result) { int rc; Instruction instr; @@ -41,88 +40,42 @@ int disassemble(uint32_t insword, uint64_t address, MipsVersion version, char *r exit(-1); \ } -void usage(char** av) -{ - printf("usage:\n"); - printf("\t%s [instruction_words]\n", av[0]); - printf("\t%s test\n", av[0]); - printf("example:\n"); - printf("\t%s 3c028081 68435a50 24445a50 6c830007\n", av[0]); - printf("\t%s test\n", av[0]); - exit(-1); -} - int main(int ac, char **av) { char instxt[4096]; - uint32_t insword = 0; - uint64_t baseaddr = 0; - int instindex = 0; - int c = 0; - int version = MIPS_32; - while ((c = getopt(ac, av, "klmnoa:")) != -1) - { - switch (c) - { - case 'k': - version = MIPS_64; - break; - case 'l': - version = MIPS_1; - break; - case 'm': - version = MIPS_2; - break; - case 'n': - version = MIPS_3; - break; - case 'o': - version = MIPS_4; - break; - case 'a': - baseaddr = strtoull(optarg, NULL, 0x10); - break; - default: - usage(av); - goto cleanup; - } + if(ac == 1) { + printf("usage:\n"); + printf("\t%s [
] \n", av[0]); + printf("\t%s \n", av[0]); + printf("\t%s test\n", av[0]); + printf("examples:\n"); + printf("\t%s 0 14E00003\n", av[0]); + printf("\t%s 00405A58 14E00003\n", av[0]); + printf("\t%s test\n", av[0]); + exit(-1); } - if (optind >= ac) - { - usage(av); - goto cleanup; - } - - instindex = optind; - - if (ac == 2 && !strcmp(av[1], "test")) - { - disassemble(0x14E00003, 0, version, instxt); + if(ac == 2 && !strcmp(av[1], "test")) { + disassemble(0x14E00003, 0, MIPS_32, instxt); ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x10")); - disassemble(0x14E00003, 4, version, instxt); + disassemble(0x14E00003, 0x405a58, MIPS_32, instxt); ASSERT(!strcmp(instxt, "bne\t$a3, $zero, 0x405a68")); exit(0); } - while (instindex < ac) - { - insword = strtoul(av[instindex], NULL, 16); - - if (0 == disassemble(insword, baseaddr, version, instxt)) - { - printf("%08llX: %08X %s\n", baseaddr, insword, instxt); - } - else - { - printf("%08llX: %08X ??\n", baseaddr, insword); - } - - baseaddr += 4; - instindex++; + uint64_t address = 0; + uint32_t insword = 0; + if(ac == 2) { + address = 0; + insword = strtoul(av[1], NULL, 16); + } + else if(ac == 3) { + address = strtoul(av[1], NULL, 16); + insword = strtoul(av[2], NULL, 16); } -cleanup: - return 0; + if(0 == disassemble(insword, address, MIPS_32, instxt)) { + printf("%08" PRIX64 ": %08X %s\n", address, insword, instxt); + } } From 5783c86ce4d125f21fa40764d6c76090276af1b4 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Mon, 11 Nov 2024 00:41:08 -0500 Subject: [PATCH 15/35] temporarily have something for fcmpo and psq_st type stuff, trying to make it a bit better --- arch/powerpc/disassembler.h | 12 ++++ arch/powerpc/il.cpp | 108 ++++++++++++++++++++++++++++++++--- arch/powerpc/test_disasm.cpp | 16 ++++-- binaryninjaapi.h | 28 +++++++++ lowlevelilinstruction.cpp | 5 ++ 5 files changed, 157 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index 81ccfd8a13..cecaa57e62 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -39,6 +39,18 @@ typedef enum ppc_insn_bn { 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 }; diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index dfbc87a957..3483b8aac2 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -21,7 +21,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) { @@ -455,6 +455,10 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, struct cs_detail *detail = 0; struct cs_ppc *ppc = 0; + // for ppc_ps + ppc_reg_bn gqr_l = (ppc_reg_bn)0; + int w_l = 0; + /* bypass capstone path for *all* branching instructions; capstone * is too difficult to work with and is outright broken for some * branch instructions (bdnz, etc.) @@ -1703,19 +1707,113 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // 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_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; + + // pull paired single + ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); + ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); + + // convert gqr to a register + gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); + oper3->type = PPC_OP_REG; + oper3->imm = 0; + oper3->reg = (ppc_reg)gqr_l; + + // // first thing is first, quantize! + ei2 = il.Quantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + + // Then store the quantized value + ei2 = il.Store(8, + operToIL(il, oper1, OTI_GPR0_ZERO), + // temporary measure to allow it to resemble the instruction, just oper2il oper0 + // operToIL(il, oper0) + ei2 + ); + il.AddInstruction(ei2); + + break; + + case PPC_INS_PSQ_L: + REQUIRE4OPS + w_l = oper2->imm; + + // pull paired single + ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); + ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); + + // // convert gqr to a register + gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); + oper3->type = PPC_OP_REG; + oper3->imm = 0; + oper3->reg = (ppc_reg)gqr_l; + + // // first thing is first, dequantize! + ei2 = il.DeQuantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + + // Then store the quantized value + ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + ei0 = il.Load(8, ei0); // [d(rA)] + ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] + il.AddInstruction(ei0); + + break; + + case PPC_INS_FADD: + case PPC_INS_FADDS: + REQUIRE2OPS + ei0 = il.FloatAdd( + 4, + operToIL(il, oper1), + operToIL(il, oper2) + ); + ei0 = il.SetRegister(4, oper0->reg, ei0, + (ppc->update_cr0) ? IL_FLAGWRITE_CR0_S : 0 + ); + il.AddInstruction(ei0); + break; + + case PPC_INS_FSUB: + case PPC_INS_FSUBS: + REQUIRE2OPS + ei0 = il.FloatSub( + 4, + operToIL(il, oper1), + operToIL(il, oper2) + ); + ei0 = il.SetRegister(4, oper0->reg, ei0, + (ppc->update_cr0) ? IL_FLAGWRITE_CR0_S : 0 + ); + il.AddInstruction(ei0); + break; + // TODO: high level IL is sometimes assuming incorrect variables, and setting floating points to // standard registers. // TODO: high level IL is accidentilly adding an extra subtract operand and assigning it to no one. // TODO: final assignment for the fcmp is whether or not the sub is 0, not greater than 0. case PPC_INS_FCMPU: REQUIRE3OPS - ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); + ei0 = il.FloatCompareUnordered(4, operToIL(il, oper1), operToIL(il, oper2)); + // ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); il.AddInstruction(ei0); break; case PPC_INS_BN_FCMPO: REQUIRE3OPS - ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); + ei0 = il.FloatCompareOrdered(4, operToIL(il, oper1), operToIL(il, oper2)); + // ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); il.AddInstruction(ei0); break; @@ -1957,8 +2055,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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: @@ -1996,8 +2092,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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: diff --git a/arch/powerpc/test_disasm.cpp b/arch/powerpc/test_disasm.cpp index bae7f10823..cd70a6aae8 100644 --- a/arch/powerpc/test_disasm.cpp +++ b/arch/powerpc/test_disasm.cpp @@ -96,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), @@ -123,8 +123,11 @@ int disas_instr_word(uint32_t instr_word, char *buf) return rc; } -void usage() +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"); } @@ -139,7 +142,7 @@ int main(int ac, char **av) #define BATCH 10000000 opterr = 0; - while ((c = getopt(ac, av, "qsp")) != -1) + while ((c = getopt(ac, av, "qspb")) != -1) { switch (c) { @@ -152,15 +155,18 @@ int main(int ac, char **av) case 'p': cs_mode_local = CS_MODE_PS; break; + case 'b': + littleendian = false; + break; default: - usage(); + usage(av[0]); goto cleanup; } } if (optind >= ac) { - usage(); + usage(av[0]); goto cleanup; } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 2de2aa6313..2ea9f72d58 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -11908,6 +11908,34 @@ namespace BinaryNinja { ExprId ExternPointer( size_t size, uint64_t val, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); + /*! + retrieve a paired single + \param size The size of the reg in bytes, likely 8? + \param s the floating point register to use + \param index the floating point param, either a 0 or a 1 + */ + ExprId PairedSingle(size_t size, ExprId s, uint32_t index, const ILSourceLocation& loc = ILSourceLocation()); + + /*! + quantize a paired single + \param size The size of the reg in bytes, likely 8? + \param a the first floating point register to use + \param b the second floating point register to use + \param q quantize register to use + \param w paired single control + */ + ExprId Quantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc = ILSourceLocation()); + + /*! + dequantize a paired single + \param size The size of the reg in bytes, likely 8? + \param a the first floating point register to use + \param b the second floating point register to use + \param q quantize register to use + \param w paired single control + */ + ExprId DeQuantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc = ILSourceLocation()); + /*! Returns an expression for the constant raw binary floating point value \c value with size \c size diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 173686624e..ce71ba7ff1 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -3045,6 +3045,11 @@ ExprId LowLevelILFunction::ExternPointer(size_t size, uint64_t val, uint64_t off return AddExprWithLocation(LLIL_EXTERN_PTR, loc, size, 0, val, offset); } +// ExprId LowLevelILFunction::PairedSingle(size_t size, ExprId s, uint32_t index, const ILSourceLocation& loc) +// { +// return ; +// } + ExprId LowLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc) { From 31b08dbc4d6ea91ddc76e4fd20aeedabf4c479b0 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 12 Nov 2024 08:42:34 -0500 Subject: [PATCH 16/35] may be removing paired single stuff, but floating point conditionals are working --- arch/powerpc/arch_ppc.cpp | 159 +++++++++++++++++++++--------------- arch/powerpc/disassembler.h | 3 + arch/powerpc/il.cpp | 132 ++++++++++++++++++++---------- arch/powerpc/il.h | 137 +++++++++++++++++++------------ lowlevelilinstruction.cpp | 17 +++- 5 files changed, 281 insertions(+), 167 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 479a723ef9..49a3705df3 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -6,8 +6,8 @@ #include #define MYLOG(...) while(0); -//#define MYLOG BinaryNinja::LogDebug -//#define MYLOG printf +// #define MYLOG BinaryNinja::LogWarn +// #define MYLOG printf #include "lowlevelilinstruction.h" using namespace BinaryNinja; // for ::LogDebug, etc. @@ -673,24 +673,15 @@ 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__); - + MYLOG("%s(), op:%d, flagwritetype:%d, flag:%d\n", __func__, op, flagWriteType, flag); bool signedWrite = true; 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: @@ -775,10 +766,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: @@ -790,10 +783,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: @@ -804,7 +799,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)); @@ -814,6 +812,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) @@ -854,7 +853,7 @@ class PowerpcArchitecture: public Architecture */ virtual vector GetAllFlags() override { - MYLOG("%s()\n", __func__); + // MYLOG("%s()\n", __func__); return vector { IL_FLAG_LT, IL_FLAG_GT, IL_FLAG_EQ, IL_FLAG_SO, IL_FLAG_LT_1, IL_FLAG_GT_1, IL_FLAG_EQ_1, IL_FLAG_SO_1, @@ -870,7 +869,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"; @@ -928,6 +927,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, @@ -942,7 +944,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) { @@ -980,6 +982,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: @@ -1032,12 +1051,13 @@ class PowerpcArchitecture: public Architecture virtual vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override { - MYLOG("%s(%d)\n", __func__, writeType); + MYLOG("%s() writeType:%d\n", __func__, writeType); switch (writeType) { case IL_FLAGWRITE_CR0_S: case IL_FLAGWRITE_CR0_U: + case IL_FLAGWRITE_CR0_F: case IL_FLAGWRITE_MTCR0: case IL_FLAGWRITE_INVL0: return vector { @@ -1046,6 +1066,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 { @@ -1054,6 +1075,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 { @@ -1062,6 +1084,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 { @@ -1070,6 +1093,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 { @@ -1078,6 +1102,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 { @@ -1086,6 +1111,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 { @@ -1094,6 +1120,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 { @@ -1124,27 +1151,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; } /* @@ -1160,6 +1179,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, }; } @@ -1225,7 +1247,9 @@ class PowerpcArchitecture: public Architecture virtual std::map GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override { - uint32_t flagClassBase = IL_FLAGCLASS_CR0_S + ((semGroup / 10) * 2); + MYLOG("%s() semgroup:%d", __func__, semGroup); + + uint32_t flagClassBase = IL_FLAGCLASS_CR0_S + ((semGroup / 10) * PPC_SUF_SZ); uint32_t groupType = semGroup % 10; switch (groupType) @@ -1233,32 +1257,38 @@ class PowerpcArchitecture: public Architecture case IL_FLAGGROUP_CR0_LT: return map { {flagClassBase , LLFC_SLT}, - {flagClassBase + 1, LLFC_ULT} + {flagClassBase + PPC_SUF_U, LLFC_ULT}, + {flagClassBase + PPC_SUF_F, LLFC_FLT}, }; case IL_FLAGGROUP_CR0_LE: return map { {flagClassBase , LLFC_SLE}, - {flagClassBase + 1, LLFC_ULE} + {flagClassBase + PPC_SUF_U, LLFC_ULE}, + {flagClassBase + PPC_SUF_F, LLFC_FLE} }; case IL_FLAGGROUP_CR0_GT: return map { {flagClassBase , LLFC_SGT}, - {flagClassBase + 1, LLFC_UGT} + {flagClassBase + PPC_SUF_U, LLFC_UGT}, + {flagClassBase + PPC_SUF_F, LLFC_FGT} }; case IL_FLAGGROUP_CR0_GE: return map { {flagClassBase , LLFC_SGE}, - {flagClassBase + 1, LLFC_UGE} + {flagClassBase + PPC_SUF_U, LLFC_UGE}, + {flagClassBase + PPC_SUF_F, LLFC_FGE} }; case IL_FLAGGROUP_CR0_EQ: return map { {flagClassBase , LLFC_E}, - {flagClassBase + 1, LLFC_E} + {flagClassBase + PPC_SUF_U, LLFC_E}, + {flagClassBase + PPC_SUF_F, LLFC_FE} }; case IL_FLAGGROUP_CR0_NE: return map { {flagClassBase , LLFC_NE}, - {flagClassBase + 1, LLFC_NE} + {flagClassBase + PPC_SUF_U, LLFC_NE}, + {flagClassBase + PPC_SUF_F, LLFC_FNE} }; default: return map(); @@ -1271,22 +1301,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) { @@ -1298,7 +1317,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: @@ -1341,24 +1360,30 @@ class PowerpcArchitecture: public Architecture */ virtual vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t) override { - MYLOG("%s(%d)\n", __func__, cond); + MYLOG("%s() cond:%d\n", __func__, cond); switch (cond) { case LLFC_E: /* equal */ case LLFC_NE: /* not equal */ + case LLFC_FE: + case LLFC_FNE: return vector{ IL_FLAG_EQ }; case LLFC_ULT: /* (unsigned) less than == LT */ case LLFC_SLT: /* (signed) less than == LT */ case LLFC_SGE: /* (signed) greater-or-equal == !LT */ case LLFC_UGE: /* (unsigned) greater-or-equal == !LT */ + case LLFC_FLT: + case LLFC_FGE: return vector{ IL_FLAG_LT }; case LLFC_SGT: /* (signed) greater-than == GT */ case LLFC_UGT: /* (unsigned) greater-than == GT */ case LLFC_ULE: /* (unsigned) less-or-equal == !GT */ case LLFC_SLE: /* (signed) lesser-or-equal == !GT */ + case LLFC_FGT: + case LLFC_FLE: return vector{ IL_FLAG_GT }; case LLFC_NEG: @@ -1391,7 +1416,7 @@ class PowerpcArchitecture: public Architecture virtual vector GetFullWidthRegisters() override { - MYLOG("%s()\n", __func__); + // MYLOG("%s()\n", __func__); return vector{ PPC_REG_R0, PPC_REG_R1, PPC_REG_R2, PPC_REG_R3, PPC_REG_R4, PPC_REG_R5, PPC_REG_R6, PPC_REG_R7, diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index cecaa57e62..93d7d423b3 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -26,6 +26,9 @@ Then some helpers if you need them: #include "capstone/cs_priv.h" #include "capstone/ppc.h" +#define PPC_CRX_REG_MASK 0x1ff +#define PPC_CRX_FLOAT_MASK 0x200 + //***************************************************************************** // structs and types //***************************************************************************** diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 3483b8aac2..0af6c3ebef 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -131,33 +131,42 @@ static ExprId operToIL(LowLevelILFunction &il, struct cs_ppc_op *op, /* 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) @@ -230,6 +239,7 @@ static bool LiftConditionalBranch(LowLevelILFunction& il, uint8_t bo, uint8_t bi 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; if (!le) @@ -239,7 +249,7 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 switch (insn >> 26) { - case 18: /* b (b, ba, bl, bla) */ + case PPC_INS_BCA: /* b (b, ba, bl, bla) */ { uint32_t target = insn & 0x03fffffc; @@ -275,7 +285,7 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 break; } - case 16: /* bc */ + case PPC_INS_BA: /* bc */ { uint32_t target = insn & 0xfffc; uint8_t bo = (insn >> 21) & 0x1f; @@ -329,7 +339,7 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 break; } - case 19: /* bcctr, bclr */ + case PPC_INS_BCCTR: /* bcctr, bclr */ { uint8_t bo = (insn >> 21) & 0x1f; uint8_t bi = (insn >> 16) & 0x1f; @@ -444,6 +454,30 @@ static void ByteReversedStore(LowLevelILFunction &il, struct cs_ppc* ppc, size_t 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 */ + ) +{ + ExprId tmp; + const int addrsz = 4; + // assume single + if (!load_store_sz) + load_store_sz = 4; + + // operand1.reg = [operand2.reg + operand2.imm] + 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)); + } + + il.AddInstruction(il.SetRegister(load_store_sz, operand1->reg, (il.Operand(1, il.Load(load_store_sz, tmp))))); +} + /* returns TRUE - if this IL continues FALSE - if this IL terminates a block */ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, @@ -1739,8 +1773,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, ei2 = il.Store(8, operToIL(il, oper1, OTI_GPR0_ZERO), // temporary measure to allow it to resemble the instruction, just oper2il oper0 - // operToIL(il, oper0) - ei2 + operToIL(il, oper0) + // ei2 ); il.AddInstruction(ei2); @@ -1780,7 +1814,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, operToIL(il, oper2) ); ei0 = il.SetRegister(4, oper0->reg, ei0, - (ppc->update_cr0) ? IL_FLAGWRITE_CR0_S : 0 + (ppc->update_cr0) ? (IL_FLAGWRITE_CR0_S | PPC_CRX_FLOAT_MASK) : 0 ); il.AddInstruction(ei0); break; @@ -1794,27 +1828,28 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, operToIL(il, oper2) ); ei0 = il.SetRegister(4, oper0->reg, ei0, - (ppc->update_cr0) ? IL_FLAGWRITE_CR0_S : 0 + (ppc->update_cr0) ? (IL_FLAGWRITE_CR0_S | PPC_CRX_FLOAT_MASK) : 0 ); il.AddInstruction(ei0); break; - // TODO: high level IL is sometimes assuming incorrect variables, and setting floating points to - // standard registers. - // TODO: high level IL is accidentilly adding an extra subtract operand and assigning it to no one. - // TODO: final assignment for the fcmp is whether or not the sub is 0, not greater than 0. + #define RZF 4 case PPC_INS_FCMPU: REQUIRE3OPS - ei0 = il.FloatCompareUnordered(4, operToIL(il, oper1), operToIL(il, oper2)); - // ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); - il.AddInstruction(ei0); + 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.FloatCompareOrdered(4, operToIL(il, oper1), operToIL(il, oper2)); - // ei0 = il.FloatSub(4, operToIL(il, oper1), operToIL(il, oper2), crxToFlagWriteType(oper0->reg)); - il.AddInstruction(ei0); + 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: @@ -1842,18 +1877,25 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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)] - il.AddInstruction(ei0); + // 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_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); + // 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; // ===================================== diff --git a/arch/powerpc/il.h b/arch/powerpc/il.h index 68723f3754..c3512ae417 100644 --- a/arch/powerpc/il.h +++ b/arch/powerpc/il.h @@ -15,8 +15,27 @@ eg: cmp a, b if ab then c=0b010 (not setting SO, setting GT) if a==b then c=0b001 (not setting SO, setting EQ) + +FOR FLOATING POINT +if ((frA) is a NaN or (frB) is a NaN) then c=0b0001 +else if (frA)< (frB) then c=0b1000 +else if (frA)> (frB) then c=0b0100 +else if (frA)==(frB) then c=0b0010 */ +typedef enum +{ + PPC_SUF_S=0, + PPC_SUF_U=1, + PPC_SUF_F=2, + PPC_SUF_SZ=3 +} ppc_suf; + +#define IL_FLOAT_FLAG_NAN (1 << 8) +#define IL_FLOAT_FLAG_LT (8 << 8) +#define IL_FLOAT_FLAG_GT (4 << 8) +#define IL_FLOAT_FLAG_EQ (2 << 8) + #define IL_FLAG_LT 0 #define IL_FLAG_GT 1 #define IL_FLAG_EQ 2 @@ -59,62 +78,78 @@ if a==b then c=0b001 (not setting SO, setting EQ) #define IL_FLAGWRITE_NONE 0 #define IL_FLAGWRITE_CR0_S 1 #define IL_FLAGWRITE_CR0_U 2 -#define IL_FLAGWRITE_CR1_S 3 -#define IL_FLAGWRITE_CR1_U 4 -#define IL_FLAGWRITE_CR2_S 5 -#define IL_FLAGWRITE_CR2_U 6 -#define IL_FLAGWRITE_CR3_S 7 -#define IL_FLAGWRITE_CR3_U 8 -#define IL_FLAGWRITE_CR4_S 9 -#define IL_FLAGWRITE_CR4_U 10 -#define IL_FLAGWRITE_CR5_S 11 -#define IL_FLAGWRITE_CR5_U 12 -#define IL_FLAGWRITE_CR6_S 13 -#define IL_FLAGWRITE_CR6_U 14 -#define IL_FLAGWRITE_CR7_S 15 -#define IL_FLAGWRITE_CR7_U 16 -#define IL_FLAGWRITE_XER 17 -#define IL_FLAGWRITE_XER_CA 18 -#define IL_FLAGWRITE_XER_OV_SO 19 - -#define IL_FLAGWRITE_MTCR0 20 -#define IL_FLAGWRITE_MTCR1 21 -#define IL_FLAGWRITE_MTCR2 22 -#define IL_FLAGWRITE_MTCR3 23 -#define IL_FLAGWRITE_MTCR4 24 -#define IL_FLAGWRITE_MTCR5 25 -#define IL_FLAGWRITE_MTCR6 26 -#define IL_FLAGWRITE_MTCR7 27 - -#define IL_FLAGWRITE_INVL0 30 -#define IL_FLAGWRITE_INVL1 31 -#define IL_FLAGWRITE_INVL2 32 -#define IL_FLAGWRITE_INVL3 33 -#define IL_FLAGWRITE_INVL4 34 -#define IL_FLAGWRITE_INVL5 35 -#define IL_FLAGWRITE_INVL6 36 -#define IL_FLAGWRITE_INVL7 37 - -#define IL_FLAGWRITE_INVALL 40 +#define IL_FLAGWRITE_CR0_F 3 +#define IL_FLAGWRITE_CR1_S 4 +#define IL_FLAGWRITE_CR1_U 5 +#define IL_FLAGWRITE_CR1_F 6 +#define IL_FLAGWRITE_CR2_S 7 +#define IL_FLAGWRITE_CR2_U 8 +#define IL_FLAGWRITE_CR2_F 9 +#define IL_FLAGWRITE_CR3_S 10 +#define IL_FLAGWRITE_CR3_U 11 +#define IL_FLAGWRITE_CR3_F 12 +#define IL_FLAGWRITE_CR4_S 13 +#define IL_FLAGWRITE_CR4_U 14 +#define IL_FLAGWRITE_CR4_F 15 +#define IL_FLAGWRITE_CR5_S 16 +#define IL_FLAGWRITE_CR5_U 17 +#define IL_FLAGWRITE_CR5_F 18 +#define IL_FLAGWRITE_CR6_S 19 +#define IL_FLAGWRITE_CR6_U 20 +#define IL_FLAGWRITE_CR6_F 21 +#define IL_FLAGWRITE_CR7_S 22 +#define IL_FLAGWRITE_CR7_U 23 +#define IL_FLAGWRITE_CR7_F 24 +#define IL_FLAGWRITE_XER 25 +#define IL_FLAGWRITE_XER_CA 26 +#define IL_FLAGWRITE_XER_OV_SO 27 + +#define IL_FLAGWRITE_MTCR0 28 +#define IL_FLAGWRITE_MTCR1 29 +#define IL_FLAGWRITE_MTCR2 30 +#define IL_FLAGWRITE_MTCR3 31 +#define IL_FLAGWRITE_MTCR4 32 +#define IL_FLAGWRITE_MTCR5 33 +#define IL_FLAGWRITE_MTCR6 34 +#define IL_FLAGWRITE_MTCR7 35 + +#define IL_FLAGWRITE_INVL0 38 +#define IL_FLAGWRITE_INVL1 39 +#define IL_FLAGWRITE_INVL2 40 +#define IL_FLAGWRITE_INVL3 41 +#define IL_FLAGWRITE_INVL4 42 +#define IL_FLAGWRITE_INVL5 43 +#define IL_FLAGWRITE_INVL6 44 +#define IL_FLAGWRITE_INVL7 45 + +#define IL_FLAGWRITE_INVALL 48 /* the different classes of writes to each cr */ #define IL_FLAGCLASS_NONE 0 #define IL_FLAGCLASS_CR0_S 1 #define IL_FLAGCLASS_CR0_U 2 -#define IL_FLAGCLASS_CR1_S 3 -#define IL_FLAGCLASS_CR1_U 4 -#define IL_FLAGCLASS_CR2_S 5 -#define IL_FLAGCLASS_CR2_U 6 -#define IL_FLAGCLASS_CR3_S 7 -#define IL_FLAGCLASS_CR3_U 8 -#define IL_FLAGCLASS_CR4_S 9 -#define IL_FLAGCLASS_CR4_U 10 -#define IL_FLAGCLASS_CR5_S 11 -#define IL_FLAGCLASS_CR5_U 12 -#define IL_FLAGCLASS_CR6_S 13 -#define IL_FLAGCLASS_CR6_U 14 -#define IL_FLAGCLASS_CR7_S 15 -#define IL_FLAGCLASS_CR7_U 16 +#define IL_FLAGCLASS_CR0_F 3 +#define IL_FLAGCLASS_CR1_S 4 +#define IL_FLAGCLASS_CR1_U 5 +#define IL_FLAGCLASS_CR1_F 6 +#define IL_FLAGCLASS_CR2_S 7 +#define IL_FLAGCLASS_CR2_U 8 +#define IL_FLAGCLASS_CR2_F 9 +#define IL_FLAGCLASS_CR3_S 10 +#define IL_FLAGCLASS_CR3_U 11 +#define IL_FLAGCLASS_CR3_F 12 +#define IL_FLAGCLASS_CR4_S 13 +#define IL_FLAGCLASS_CR4_U 14 +#define IL_FLAGCLASS_CR4_F 15 +#define IL_FLAGCLASS_CR5_S 16 +#define IL_FLAGCLASS_CR5_U 17 +#define IL_FLAGCLASS_CR5_F 18 +#define IL_FLAGCLASS_CR6_S 19 +#define IL_FLAGCLASS_CR6_U 20 +#define IL_FLAGCLASS_CR6_F 21 +#define IL_FLAGCLASS_CR7_S 22 +#define IL_FLAGCLASS_CR7_U 23 +#define IL_FLAGCLASS_CR7_F 24 #define IL_FLAGGROUP_CR0_LT (0 + 0) #define IL_FLAGGROUP_CR0_LE (0 + 1) diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index ce71ba7ff1..c0c22bb551 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -3045,11 +3045,20 @@ ExprId LowLevelILFunction::ExternPointer(size_t size, uint64_t val, uint64_t off return AddExprWithLocation(LLIL_EXTERN_PTR, loc, size, 0, val, offset); } -// ExprId LowLevelILFunction::PairedSingle(size_t size, ExprId s, uint32_t index, const ILSourceLocation& loc) -// { -// return ; -// } +ExprId LowLevelILFunction::PairedSingle(size_t size, ExprId s, uint32_t index, const ILSourceLocation& loc) +{ + return 0; +} +ExprId LowLevelILFunction::Quantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc) +{ + return 0; +} + +ExprId LowLevelILFunction::DeQuantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc) +{ + return 0; +} ExprId LowLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc) { From 3f9fd3a49779e12befa91ab252233686d3b158e7 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 12 Nov 2024 08:56:26 -0500 Subject: [PATCH 17/35] forgot that set needs to differentiate s vs f --- arch/powerpc/il.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 0af6c3ebef..0210a53b2b 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1814,7 +1814,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, operToIL(il, oper2) ); ei0 = il.SetRegister(4, oper0->reg, ei0, - (ppc->update_cr0) ? (IL_FLAGWRITE_CR0_S | PPC_CRX_FLOAT_MASK) : 0 + (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0 ); il.AddInstruction(ei0); break; @@ -1828,7 +1828,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, operToIL(il, oper2) ); ei0 = il.SetRegister(4, oper0->reg, ei0, - (ppc->update_cr0) ? (IL_FLAGWRITE_CR0_S | PPC_CRX_FLOAT_MASK) : 0 + (ppc->update_cr0) ? IL_FLAGWRITE_CR0_F : 0 ); il.AddInstruction(ei0); break; From 0a7efb04e6d87ea29265dd1c28b50b5058a48238 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 12 Nov 2024 11:25:02 -0500 Subject: [PATCH 18/35] lfs casting is working, still need stfs, but confident it won't be hard --- arch/powerpc/il.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 0210a53b2b..af39b27914 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -475,7 +475,7 @@ static void loadstoreppcfs(LowLevelILFunction& il, int load_store_sz, tmp = il.Add(addrsz, il.Register(addrsz, operand2->mem.base), il.Const(addrsz, operand2->mem.disp)); } - il.AddInstruction(il.SetRegister(load_store_sz, operand1->reg, (il.Operand(1, il.Load(load_store_sz, tmp))))); + il.AddInstruction(il.SetRegister(load_store_sz, operand1->reg, il.FloatConvert(load_store_sz, il.Operand(1, il.Load(load_store_sz, tmp))))); } /* returns TRUE - if this IL continues From 91be7248b1b8011c5092d1eaf68fb098339bf6ed Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 12 Nov 2024 17:04:42 -0500 Subject: [PATCH 19/35] working ish, at least is casting the left side though it may not be 100% kosher --- arch/powerpc/il.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index af39b27914..2336f1a1c2 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1863,6 +1863,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, operToIL(il, oper1), operToIL(il, oper0) ); + ei0 = il.FloatConvert(4, ei0); il.AddInstruction(ei0); break; @@ -1872,6 +1873,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, operToIL(il, oper1), operToIL(il, oper0) ); + ei0 = il.FloatConvert(8, ei0); il.AddInstruction(ei0); break; From 6757717c02bfdce784e2b49ba25bb5e0b6508343 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Thu, 14 Nov 2024 23:33:52 -0500 Subject: [PATCH 20/35] now ppc_ps isn't default, but will be dope --- arch/powerpc/arch_ppc.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 49a3705df3..fff12cd41b 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -2498,13 +2498,6 @@ extern "C" ppc /* the architecture */ ); - BinaryViewType::RegisterArchitecture( - "ELF", /* name of the binary view type */ - EM_PPC, /* id (key in m_arch map) */ - BigEndian, - ppc_ps /* the architecture */ - ); - BinaryViewType::RegisterArchitecture( "ELF", /* name of the binary view type */ EM_PPC64, /* id (key in m_arch map) */ From f504c02f81a08eacd3d0f1d2399dafc2d05233b7 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Tue, 19 Nov 2024 14:19:47 -0500 Subject: [PATCH 21/35] fixed stfs so that no more left side casting --- arch/powerpc/il.cpp | 129 +++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 2336f1a1c2..f8688dae32 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1748,63 +1748,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // had it not had the quantization, we could probably get away with // a cast and then store. - 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; - - // pull paired single - ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); - ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); - - // convert gqr to a register - gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); - oper3->type = PPC_OP_REG; - oper3->imm = 0; - oper3->reg = (ppc_reg)gqr_l; - - // // first thing is first, quantize! - ei2 = il.Quantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); - - // Then store the quantized value - ei2 = il.Store(8, - operToIL(il, oper1, OTI_GPR0_ZERO), - // temporary measure to allow it to resemble the instruction, just oper2il oper0 - operToIL(il, oper0) - // ei2 - ); - il.AddInstruction(ei2); - - break; - - case PPC_INS_PSQ_L: - REQUIRE4OPS - w_l = oper2->imm; - - // pull paired single - ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); - ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); - - // // convert gqr to a register - gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); - oper3->type = PPC_OP_REG; - oper3->imm = 0; - oper3->reg = (ppc_reg)gqr_l; - - // // first thing is first, dequantize! - ei2 = il.DeQuantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); - - // Then store the quantized value - ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 - ei0 = il.Load(8, ei0); // [d(rA)] - ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] - il.AddInstruction(ei0); - - break; - case PPC_INS_FADD: case PPC_INS_FADDS: REQUIRE2OPS @@ -1861,9 +1804,9 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, REQUIRE2OPS ei0 = il.Store(4, operToIL(il, oper1), - operToIL(il, oper0) + il.FloatConvert(4, operToIL(il, oper0)) ); - ei0 = il.FloatConvert(4, ei0); + // ei0 = il.FloatConvert(4, ei0); il.AddInstruction(ei0); break; @@ -1871,9 +1814,9 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, REQUIRE2OPS ei0 = il.Store(8, operToIL(il, oper1), - operToIL(il, oper0) + il.FloatConvert(8, operToIL(il, oper0)) ); - ei0 = il.FloatConvert(8, ei0); + // ei0 = il.FloatConvert(8, ei0); il.AddInstruction(ei0); break; @@ -1900,6 +1843,69 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, loadstoreppcfs(il, 8, oper0, oper1); break; + case PPC_INS_CNTLZW: + // il.AddInstruction(il.Intrinsic( + // {RegisterOrFlag::Register((operand1).reg[0])}, ARM64_INTRIN_CLZ, {ExtractRegister(il, operand2, 0, get_register_size((operand2).reg[0]), false, get_register_size((operand2).reg[0])) + // })); + // 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; + + // // pull paired single + // ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); + // ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); + + // // convert gqr to a register + // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); + // oper3->type = PPC_OP_REG; + // oper3->imm = 0; + // oper3->reg = (ppc_reg)gqr_l; + + // // // first thing is first, quantize! + // ei2 = il.Quantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + + // // Then store the quantized value + // ei2 = il.Store(8, + // operToIL(il, oper1, OTI_GPR0_ZERO), + // // temporary measure to allow it to resemble the instruction, just oper2il oper0 + // operToIL(il, oper0) + // // ei2 + // ); + // il.AddInstruction(ei2); + + // break; + + case PPC_INS_PSQ_L: + // REQUIRE4OPS + // w_l = oper2->imm; + + // // pull paired single + // ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); + // ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); + + // // // convert gqr to a register + // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); + // oper3->type = PPC_OP_REG; + // oper3->imm = 0; + // oper3->reg = (ppc_reg)gqr_l; + + // // // first thing is first, dequantize! + // ei2 = il.DeQuantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + + // // Then store the quantized value + // ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + // ei0 = il.Load(8, ei0); // [d(rA)] + // ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] + // il.AddInstruction(ei0); + + // break; + + // ===================================== // =====TO BE DEFINED INSTRUCTIONS====== // ===================================== @@ -1908,7 +1914,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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: From 51bb72d93b6aad801e147535dd2c53b1c0215688 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Thu, 21 Nov 2024 05:10:56 -0500 Subject: [PATCH 22/35] psq is sorta working, still need to do frsp --- arch/powerpc/arch_ppc.cpp | 73 +++++++ arch/powerpc/il.cpp | 433 +++++++++++++++++++++++++++----------- arch/powerpc/il.h | 9 + 3 files changed, 391 insertions(+), 124 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index fff12cd41b..2389954937 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -639,6 +639,79 @@ class PowerpcArchitecture: public Architecture return rc; } + virtual string GetIntrinsicName(uint32_t intrinsic) override + { + switch (intrinsic) + { + case PPC_INTRIN_QUANTIZE: + return "quantize"; + case PPC_INTRIN_DEQUANTIZE: + return "dequantize"; + case PPC_INTRIN_CNTLZW: + return "__builtin_clz"; + default: + break; + } + + return ""; + } + + + virtual std::vector GetAllIntrinsics() override + { + // Highest intrinsic number currently is ARM64_INTRIN_NEON_END. + // If new extensions are added please update this code. + std::vector result{PPC_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_QUANTIZE == 0, + "Invalid first PPCIntrinsic value. Please add your intrinsic further in the enum."); + + // Normal intrinsics. + for (uint32_t id = PPC_INTRIN_QUANTIZE; id < PPCIntrinsic::PPC_INTRIN_END; id++) { + result.push_back(id); + } + + // consider populating with separate architecture stuff, like ppc_ps stuff or something + return result; + } + + + virtual vector GetIntrinsicInputs(uint32_t intrinsic) override + { + switch (intrinsic) + { + case PPC_INTRIN_CNTLZW: // rs + return {NameAndType(Type::IntegerType(4, false))}; + case PPC_INTRIN_QUANTIZE: + case PPC_INTRIN_DEQUANTIZE: + return {NameAndType(Type::IntegerType(8, false))}; + default: + break; + } + + return vector(); + } + + + virtual vector>> GetIntrinsicOutputs(uint32_t intrinsic) override + { + switch (intrinsic) + { + case PPC_INTRIN_CNTLZW: // ra + return {Type::IntegerType(4, false)}; + case PPC_INTRIN_QUANTIZE: + case PPC_INTRIN_DEQUANTIZE: + return {Type::IntegerType(8, false)}; + default: + break; + } + + return vector>>(); + } + + virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override { bool rc = false; diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index f8688dae32..7cb68cddd7 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1,3 +1,4 @@ +#include "lowlevelilinstruction.h" #include #include "disassembler.h" @@ -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: @@ -1733,56 +1738,57 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // ===================================== // =====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. + // 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: - REQUIRE2OPS - 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 - ); + 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: - REQUIRE2OPS - 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 - ); + 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; - #define RZF 4 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)); + ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg | PPC_CRX_FLOAT_MASK)); il.AddInstruction(ei2); break; @@ -1790,32 +1796,27 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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)); + ei2 = il.FloatSub(RZF, ei0, ei1, crxToFlagWriteType(oper0->reg | PPC_CRX_FLOAT_MASK)); il.AddInstruction(ei2); break; case PPC_INS_FMR: REQUIRE2OPS - il.AddInstruction(il.SetRegister(4, oper0->reg, operToIL(il, oper1))); + 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.Store(4, - operToIL(il, oper1), - il.FloatConvert(4, operToIL(il, oper0)) - ); + ei0 = il.Store(4, operToIL(il, oper1), il.FloatConvert(4, operToIL(il, oper0))); // 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)) - ); + 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; @@ -1823,10 +1824,10 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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); + // 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); @@ -1835,80 +1836,283 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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); + // 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: - // il.AddInstruction(il.Intrinsic( - // {RegisterOrFlag::Register((operand1).reg[0])}, ARM64_INTRIN_CLZ, {ExtractRegister(il, operand2, 0, get_register_size((operand2).reg[0]), false, get_register_size((operand2).reg[0])) - // })); - // break; + 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); - + 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; + // if (w_l == 0) + // { + + // } + // else if (w_l == 1) + // { + // ei0 = operToIL(il, oper0); + // ei0 = il.Intrinsic(); + + // // Then store the quantized value + // ei2 = il.Store(8, operToIL(il, oper1, OTI_GPR0_ZERO), + // // temporary measure to allow it to resemble the instruction, just oper2il oper0 + // operToIL(il, oper0) + // // ei2 + // ); + // il.AddInstruction(ei2); + // } // // pull paired single // ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); // ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); // // convert gqr to a register - // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); - // oper3->type = PPC_OP_REG; - // oper3->imm = 0; - // oper3->reg = (ppc_reg)gqr_l; + // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); + // oper3->type = PPC_OP_REG; + // oper3->imm = 0; + // oper3->reg = (ppc_reg)gqr_l; + + // // // first thing is first, quantize! + // ei2 = il.Quantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + + ei0 = il.Intrinsic( + {RegisterOrFlag::Register(oper0->reg)}, + // {}, + PPC_INTRIN_QUANTIZE, + {operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)} + ); - // // // first thing is first, quantize! - // ei2 = il.Quantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + il.AddInstruction(ei0); - // // Then store the quantized value - // ei2 = il.Store(8, - // operToIL(il, oper1, OTI_GPR0_ZERO), - // // temporary measure to allow it to resemble the instruction, just oper2il oper0 - // operToIL(il, oper0) - // // ei2 - // ); - // il.AddInstruction(ei2); + // ei0 = il.SetRegister(8, oper0->reg, 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, 8) + // ei2 + ); + il.AddInstruction(ei0); - // break; + break; case PPC_INS_PSQ_L: - // REQUIRE4OPS - // w_l = oper2->imm; + REQUIRE4OPS + // w_l = oper2->imm; // // pull paired single - // ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); - // ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); + // ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); + // ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); // // // convert gqr to a register - // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); - // oper3->type = PPC_OP_REG; - // oper3->imm = 0; - // oper3->reg = (ppc_reg)gqr_l; + // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); + // oper3->type = PPC_OP_REG; + // oper3->imm = 0; + // oper3->reg = (ppc_reg)gqr_l; - // // // first thing is first, dequantize! - // ei2 = il.DeQuantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + // // // first thing is first, dequantize! + // ei2 = il.DeQuantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); // // Then store the quantized value - // ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 - // ei0 = il.Load(8, ei0); // [d(rA)] - // ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] - // il.AddInstruction(ei0); + // ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 + // ei0 = il.Load(8, ei0); // [d(rA)] + // ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] + // il.AddInstruction(ei0); + + ei0 = il.Load(8, operToIL(il, oper1)); // [d(rA)] + ei0 = il.Intrinsic( + {RegisterOrFlag::Register(oper0->reg)}, + // {}, + PPC_INTRIN_DEQUANTIZE, + {ei0} + ); - // break; + // ei0 = il.SetRegister(8, oper0->reg, il.Operand(8, ei0)); // rD = [d(rA)] + il.AddInstruction(ei0); -// ===================================== -// =====TO BE DEFINED INSTRUCTIONS====== -// ===================================== + // il.AddInstruction(ei0); + break; + + case PPC_INS_FRSP: + + + // ===================================== + // =====TO BE DEFINED INSTRUCTIONS====== + // ===================================== case PPC_INS_BCL: case PPC_INS_BCLR: @@ -2103,7 +2307,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_FCFID: case PPC_INS_FCFIDS: case PPC_INS_FCFIDU: @@ -2114,30 +2317,12 @@ 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_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: diff --git a/arch/powerpc/il.h b/arch/powerpc/il.h index c3512ae417..2b6bc1eb9d 100644 --- a/arch/powerpc/il.h +++ b/arch/powerpc/il.h @@ -207,5 +207,14 @@ typedef enum #define IL_FLAGGROUP_CR7_EQ (70 + 4) #define IL_FLAGGROUP_CR7_NE (70 + 5) +enum PPCIntrinsic : uint32_t +{ + PPC_INTRIN_QUANTIZE, + PPC_INTRIN_DEQUANTIZE, + PPC_INTRIN_CNTLZW, + PPC_INTRIN_END, + PPC_INTRIN_INVALID = 0xFFFFFFFF, +}; + bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction& il, const uint8_t *data, uint64_t addr, decomp_result *res, bool le); From f23c7b915d015d7a5d7f05c730f3b48155ab745e Mon Sep 17 00:00:00 2001 From: David Riusech Date: Thu, 21 Nov 2024 12:07:46 -0500 Subject: [PATCH 23/35] dequanize and quantize at least look a bit better now --- arch/powerpc/arch_ppc.cpp | 13 ++++++++++++- arch/powerpc/il.cpp | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 2389954937..142e470c4e 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -1533,7 +1533,10 @@ 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, + + 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 }; return result; @@ -1730,6 +1733,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)); diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 7cb68cddd7..b33e3ea561 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -2051,7 +2051,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, {RegisterOrFlag::Register(oper0->reg)}, // {}, PPC_INTRIN_QUANTIZE, - {operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8)} + {operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), il.Const(4, oper3->imm)} ); il.AddInstruction(ei0); @@ -2097,7 +2097,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, {RegisterOrFlag::Register(oper0->reg)}, // {}, PPC_INTRIN_DEQUANTIZE, - {ei0} + {ei0, operToIL(il, oper0), il.Const(4, oper3->imm)} ); // ei0 = il.SetRegister(8, oper0->reg, il.Operand(8, ei0)); // rD = [d(rA)] From ce3c8c151f24464a40b37b418f9524c493c5a9b3 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 22 Nov 2024 14:09:35 -0500 Subject: [PATCH 24/35] frsp is added, not perfect but assuming it has to do with some macro in the first place. quantize and dequantize are in a good state --- arch/powerpc/arch_ppc.cpp | 10 ++++++++-- arch/powerpc/il.cpp | 24 ++++++++++++++++++------ arch/powerpc/il.h | 1 + 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 142e470c4e..4d4370f843 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -649,6 +649,8 @@ class PowerpcArchitecture: public Architecture return "dequantize"; case PPC_INTRIN_CNTLZW: return "__builtin_clz"; + case PPC_INTRIN_FRSP: + return "float_round"; default: break; } @@ -684,9 +686,11 @@ class PowerpcArchitecture: public Architecture { case PPC_INTRIN_CNTLZW: // rs return {NameAndType(Type::IntegerType(4, false))}; + // for now, quantize is operating on the float in, and the gqr that holds the scale case PPC_INTRIN_QUANTIZE: + return {NameAndType(Type::FloatType(4)), NameAndType(Type::IntegerType(4, false))}; case PPC_INTRIN_DEQUANTIZE: - return {NameAndType(Type::IntegerType(8, false))}; + return {NameAndType(Type::IntegerType(4, false)), NameAndType(Type::FloatType(8)), NameAndType(Type::IntegerType(4, false))}; default: break; } @@ -702,8 +706,10 @@ class PowerpcArchitecture: public Architecture case PPC_INTRIN_CNTLZW: // ra return {Type::IntegerType(4, false)}; case PPC_INTRIN_QUANTIZE: + // quantize returns the quantized float + return {Type::FloatType(4)}; case PPC_INTRIN_DEQUANTIZE: - return {Type::IntegerType(8, false)}; + return {Type::FloatType(4)}; default: break; } diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index b33e3ea561..cc125bfe4f 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -2047,11 +2047,15 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // // // first thing is first, quantize! // ei2 = il.Quantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); + // The intrinsic used to perform the quantize operation. + // optional, use output {} for empty. ei0 = il.Intrinsic( {RegisterOrFlag::Register(oper0->reg)}, - // {}, PPC_INTRIN_QUANTIZE, - {operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 8), il.Const(4, oper3->imm)} + { + operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 4), + il.Const(4, oper3->imm) + } ); il.AddInstruction(ei0); @@ -2062,7 +2066,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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, 8) + operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 4) // ei2 ); il.AddInstruction(ei0); @@ -2095,9 +2099,12 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, ei0 = il.Load(8, operToIL(il, oper1)); // [d(rA)] ei0 = il.Intrinsic( {RegisterOrFlag::Register(oper0->reg)}, - // {}, PPC_INTRIN_DEQUANTIZE, - {ei0, operToIL(il, oper0), il.Const(4, oper3->imm)} + { + ei0, + operToIL(il, oper0), + il.Const(4, oper3->imm) + } ); // ei0 = il.SetRegister(8, oper0->reg, il.Operand(8, ei0)); // rD = [d(rA)] @@ -2108,7 +2115,12 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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====== diff --git a/arch/powerpc/il.h b/arch/powerpc/il.h index 2b6bc1eb9d..fb2cdfcc23 100644 --- a/arch/powerpc/il.h +++ b/arch/powerpc/il.h @@ -212,6 +212,7 @@ enum PPCIntrinsic : uint32_t PPC_INTRIN_QUANTIZE, PPC_INTRIN_DEQUANTIZE, PPC_INTRIN_CNTLZW, + PPC_INTRIN_FRSP, PPC_INTRIN_END, PPC_INTRIN_INVALID = 0xFFFFFFFF, }; From 7e53b41cf4567edc4b0dd623b329855c591aca12 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 22 Nov 2024 15:28:13 -0500 Subject: [PATCH 25/35] removed attempt to make quantization an instruction for il --- binaryninjaapi.h | 28 ---------------------------- lowlevelilinstruction.cpp | 14 -------------- 2 files changed, 42 deletions(-) diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 15a8e22d81..762cd27548 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -11908,34 +11908,6 @@ namespace BinaryNinja { ExprId ExternPointer( size_t size, uint64_t val, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation()); - /*! - retrieve a paired single - \param size The size of the reg in bytes, likely 8? - \param s the floating point register to use - \param index the floating point param, either a 0 or a 1 - */ - ExprId PairedSingle(size_t size, ExprId s, uint32_t index, const ILSourceLocation& loc = ILSourceLocation()); - - /*! - quantize a paired single - \param size The size of the reg in bytes, likely 8? - \param a the first floating point register to use - \param b the second floating point register to use - \param q quantize register to use - \param w paired single control - */ - ExprId Quantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc = ILSourceLocation()); - - /*! - dequantize a paired single - \param size The size of the reg in bytes, likely 8? - \param a the first floating point register to use - \param b the second floating point register to use - \param q quantize register to use - \param w paired single control - */ - ExprId DeQuantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc = ILSourceLocation()); - /*! Returns an expression for the constant raw binary floating point value \c value with size \c size diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index c0c22bb551..173686624e 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -3045,20 +3045,6 @@ ExprId LowLevelILFunction::ExternPointer(size_t size, uint64_t val, uint64_t off return AddExprWithLocation(LLIL_EXTERN_PTR, loc, size, 0, val, offset); } -ExprId LowLevelILFunction::PairedSingle(size_t size, ExprId s, uint32_t index, const ILSourceLocation& loc) -{ - return 0; -} - -ExprId LowLevelILFunction::Quantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc) -{ - return 0; -} - -ExprId LowLevelILFunction::DeQuantize(size_t size, ExprId a, ExprId b, ExprId q, ExprId w, const ILSourceLocation& loc) -{ - return 0; -} ExprId LowLevelILFunction::FloatConstRaw(size_t size, uint64_t val, const ILSourceLocation& loc) { From 7880c25939eee33e46060f888d2d54f75d69dc45 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Sat, 23 Nov 2024 20:39:10 -0500 Subject: [PATCH 26/35] better instruction filtering, and a few more instructions --- arch/powerpc/arch_ppc.cpp | 83 ++++++++++++++++++++++++++-------- arch/powerpc/il.cpp | 94 +++++++++++++++------------------------ arch/powerpc/il.h | 5 ++- 3 files changed, 103 insertions(+), 79 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 4d4370f843..6880581c5b 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -639,39 +639,57 @@ class PowerpcArchitecture: public Architecture return rc; } - virtual string GetIntrinsicName(uint32_t intrinsic) override + static string GetIntrinsicName_ppc_ps(uint32_t intrinsic) { switch (intrinsic) { - case PPC_INTRIN_QUANTIZE: + case PPC_PS_INTRIN_QUANTIZE: return "quantize"; - case PPC_INTRIN_DEQUANTIZE: + case PPC_PS_INTRIN_DEQUANTIZE: return "dequantize"; + default: + break; + } + return ""; + } + + virtual string GetIntrinsicName(uint32_t intrinsic) override + { + switch (intrinsic) + { case PPC_INTRIN_CNTLZW: return "__builtin_clz"; case PPC_INTRIN_FRSP: return "float_round"; default: + if (cs_mode_local == CS_MODE_PS) + { + return GetIntrinsicName_ppc_ps(intrinsic); + } break; } - return ""; } virtual std::vector GetAllIntrinsics() override { - // Highest intrinsic number currently is ARM64_INTRIN_NEON_END. + // Highest intrinsic number currently is PPC_PS_INTRIN_END. // If new extensions are added please update this code. - std::vector result{PPC_INTRIN_END}; + std::vector result{PPC_PS_INTRIN_END}; // Double check someone didn't insert a new intrinsic at the beginning of our enum since we rely // on it to fill the next array. - static_assert(PPCIntrinsic::PPC_INTRIN_QUANTIZE == 0, + 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_QUANTIZE; id < PPCIntrinsic::PPC_INTRIN_END; id++) { + 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); } @@ -679,6 +697,20 @@ class PowerpcArchitecture: public Architecture return result; } + static vector GetIntrinsicInputs_ppc_ps(uint32_t intrinsic) + { + switch (intrinsic) + { + // for now, quantize is operating on the float in, and the gqr that holds the scale + case PPC_PS_INTRIN_QUANTIZE: + return {NameAndType(Type::FloatType(4)), NameAndType(Type::IntegerType(4, false))}; + case PPC_PS_INTRIN_DEQUANTIZE: + return {NameAndType(Type::IntegerType(4, false)), NameAndType(Type::FloatType(8)), NameAndType(Type::IntegerType(4, false))}; + default: + break; + } + return vector(); + } virtual vector GetIntrinsicInputs(uint32_t intrinsic) override { @@ -686,18 +718,33 @@ class PowerpcArchitecture: public Architecture { 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 - case PPC_INTRIN_QUANTIZE: - return {NameAndType(Type::FloatType(4)), NameAndType(Type::IntegerType(4, false))}; - case PPC_INTRIN_DEQUANTIZE: - return {NameAndType(Type::IntegerType(4, false)), NameAndType(Type::FloatType(8)), NameAndType(Type::IntegerType(4, false))}; default: + if (cs_mode_local == CS_MODE_PS) + { + return GetIntrinsicInputs_ppc_ps(intrinsic); + } break; } - return vector(); } + static vector>> GetIntrinsicOutputs_ppc_ps(uint32_t intrinsic) + { + switch(intrinsic) + { + case PPC_PS_INTRIN_QUANTIZE: + // quantize returns the quantized float + return {Type::FloatType(4)}; + case PPC_PS_INTRIN_DEQUANTIZE: + return {Type::FloatType(4)}; + default: + break; + } + return vector>>(); + } virtual vector>> GetIntrinsicOutputs(uint32_t intrinsic) override { @@ -705,15 +752,15 @@ class PowerpcArchitecture: public Architecture { case PPC_INTRIN_CNTLZW: // ra return {Type::IntegerType(4, false)}; - case PPC_INTRIN_QUANTIZE: - // quantize returns the quantized float - return {Type::FloatType(4)}; - case PPC_INTRIN_DEQUANTIZE: + case PPC_INTRIN_FRSP: return {Type::FloatType(4)}; default: + if (cs_mode_local == CS_MODE_PS) + { + return GetIntrinsicOutputs_ppc_ps(intrinsic); + } break; } - return vector>>(); } diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index cc125bfe4f..f86ef81ce6 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -1808,7 +1808,17 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STFS: REQUIRE2OPS - ei0 = il.Store(4, operToIL(il, oper1), il.FloatConvert(4, operToIL(il, oper0))); + 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; @@ -1833,6 +1843,17 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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); + break; + case PPC_INS_LFD: REQUIRE2OPS // ei0 = operToIL(il, oper1); // d(rA) or 0 @@ -2017,41 +2038,11 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, // w_l = oper2->imm; - // if (w_l == 0) - // { - - // } - // else if (w_l == 1) - // { - // ei0 = operToIL(il, oper0); - // ei0 = il.Intrinsic(); - - // // Then store the quantized value - // ei2 = il.Store(8, operToIL(il, oper1, OTI_GPR0_ZERO), - // // temporary measure to allow it to resemble the instruction, just oper2il oper0 - // operToIL(il, oper0) - // // ei2 - // ); - // il.AddInstruction(ei2); - // } - // // pull paired single - // ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); - // ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); - - // // convert gqr to a register - // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); - // oper3->type = PPC_OP_REG; - // oper3->imm = 0; - // oper3->reg = (ppc_reg)gqr_l; - - // // // first thing is first, quantize! - // ei2 = il.Quantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); - // The intrinsic used to perform the quantize operation. // optional, use output {} for empty. ei0 = il.Intrinsic( {RegisterOrFlag::Register(oper0->reg)}, - PPC_INTRIN_QUANTIZE, + PPC_PS_INTRIN_QUANTIZE, { operToIL(il, oper0, PPC_IL_OPTIONS_DEFAULT, PPC_IL_EXTRA_DEFAULT, 4), il.Const(4, oper3->imm) @@ -2060,8 +2051,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, il.AddInstruction(ei0); - // ei0 = il.SetRegister(8, oper0->reg, 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 @@ -2071,35 +2060,21 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, ); 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; - // // pull paired single - // ei0 = il.PairedSingle(8, operToIL(il, oper0), 0); - // ei1 = il.PairedSingle(8, operToIL(il, oper0), 1); - - // // // convert gqr to a register - // gqr_l = (ppc_reg_bn)(oper3->imm + PPC_REG_BN_GQR0); - // oper3->type = PPC_OP_REG; - // oper3->imm = 0; - // oper3->reg = (ppc_reg)gqr_l; - - // // // first thing is first, dequantize! - // ei2 = il.DeQuantize(8, ei0, ei1, operToIL(il, oper3), operToIL(il, oper2)); - - // // Then store the quantized value - // ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0 - // ei0 = il.Load(8, ei0); // [d(rA)] - // ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)] - // il.AddInstruction(ei0); - ei0 = il.Load(8, operToIL(il, oper1)); // [d(rA)] ei0 = il.Intrinsic( {RegisterOrFlag::Register(oper0->reg)}, - PPC_INTRIN_DEQUANTIZE, + PPC_PS_INTRIN_DEQUANTIZE, { ei0, operToIL(il, oper0), @@ -2107,11 +2082,14 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, } ); - // ei0 = il.SetRegister(8, oper0->reg, il.Operand(8, ei0)); // rD = [d(rA)] - il.AddInstruction(ei0); - // il.AddInstruction(ei0); + // again, if w=0 qdequantize ps1 + // if (w_l == 0) + // { + + // } + break; case PPC_INS_FRSP: @@ -2350,7 +2328,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LFIWZX: case PPC_INS_LFSU: case PPC_INS_LFSUX: - case PPC_INS_LFSX: case PPC_INS_LSWI: case PPC_INS_LVEBX: case PPC_INS_LVEHX: @@ -2417,7 +2394,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_STFIWX: case PPC_INS_STFSU: case PPC_INS_STFSUX: - case PPC_INS_STFSX: case PPC_INS_STSWI: case PPC_INS_STVEBX: case PPC_INS_STVEHX: diff --git a/arch/powerpc/il.h b/arch/powerpc/il.h index fb2cdfcc23..b4ca2526cd 100644 --- a/arch/powerpc/il.h +++ b/arch/powerpc/il.h @@ -209,11 +209,12 @@ typedef enum enum PPCIntrinsic : uint32_t { - PPC_INTRIN_QUANTIZE, - PPC_INTRIN_DEQUANTIZE, 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, }; From ae824e680e2c4158b2ae17a82858bba98f7b51c9 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Mon, 25 Nov 2024 12:06:01 -0500 Subject: [PATCH 27/35] added sux stuff, may have to do stux stuff --- arch/powerpc/il.cpp | 60 +++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index f86ef81ce6..699fc6a762 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -461,7 +461,9 @@ static void ByteReversedStore(LowLevelILFunction &il, struct cs_ppc* ppc, size_t 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* operand2, /* location the read/write occurs */ + cs_ppc_op* operand3=0, + bool update=false ) { ExprId tmp; @@ -471,16 +473,32 @@ static void loadstoreppcfs(LowLevelILFunction& il, int load_store_sz, load_store_sz = 4; // operand1.reg = [operand2.reg + operand2.imm] - if (operand2->mem.disp == 0) + if (operand2->type == PPC_OP_MEM) { - tmp = il.Register(4, operand2->mem.base); + 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 + else if(operand2->type == PPC_OP_REG) { - tmp = il.Add(addrsz, il.Register(addrsz, operand2->mem.base), il.Const(addrsz, operand2->mem.disp)); + 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 @@ -1720,7 +1738,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(4, oper0->reg, operToIL(il, oper1), + ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0); + il.AddInstruction(ei0); break; case PPC_INS_SC: @@ -1845,13 +1865,25 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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); + // 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: @@ -2326,8 +2358,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_LFDX: case PPC_INS_LFIWAX: case PPC_INS_LFIWZX: - case PPC_INS_LFSU: - case PPC_INS_LFSUX: case PPC_INS_LSWI: case PPC_INS_LVEBX: case PPC_INS_LVEHX: From 70a4cf502f8ece12b3b923682e5dfe71b8e37bfe Mon Sep 17 00:00:00 2001 From: David Riusech Date: Thu, 28 Nov 2024 06:02:47 -0500 Subject: [PATCH 28/35] xori and some mylog --- arch/powerpc/arch_ppc.cpp | 18 +++++++++--------- arch/powerpc/disassembler.h | 5 +++++ arch/powerpc/il.cpp | 11 +++++++---- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 6880581c5b..dcd3651f7a 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -799,7 +799,7 @@ 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(), op:%d, flagwritetype:%d, flag:%d\n", __func__, op, flagWriteType, flag); + // MYLOG("%s(), op:%d, flagwritetype:%d, flag:%d\n", __func__, op, flagWriteType, flag); bool signedWrite = true; ExprId left, right; ppc_suf suf = (ppc_suf)0; @@ -938,7 +938,7 @@ class PowerpcArchitecture: public Architecture virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) override { - MYLOG("%s() semgroup:%d\n", __func__, semGroup); + // MYLOG("%s() semgroup:%d\n", __func__, semGroup); uint32_t flagBase = (semGroup / 10) * 4; // get to flags from the right cr switch (semGroup % 10) @@ -995,7 +995,7 @@ class PowerpcArchitecture: public Architecture virtual string GetFlagName(uint32_t flag) override { - MYLOG("%s() flag:%d\n", __func__, flag); + // MYLOG("%s() flag:%d\n", __func__, flag); switch(powerpc_crx_to_reg(flag)) { case IL_FLAG_LT: return "lt"; @@ -1070,7 +1070,7 @@ class PowerpcArchitecture: public Architecture virtual string GetFlagWriteTypeName(uint32_t writeType) override { - MYLOG("%s() writeType:%d\n", __func__, writeType); + // MYLOG("%s() writeType:%d\n", __func__, writeType); switch (writeType) { @@ -1177,7 +1177,7 @@ class PowerpcArchitecture: public Architecture virtual vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override { - MYLOG("%s() writeType:%d\n", __func__, writeType); + // MYLOG("%s() writeType:%d\n", __func__, writeType); switch (writeType) { @@ -1277,7 +1277,7 @@ class PowerpcArchitecture: public Architecture } virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType) override { - MYLOG("%s() writetype:%d", __func__, writeType); + // MYLOG("%s() writetype:%d", __func__, writeType); uint32_t flag_out = 0; if ((writeType < IL_FLAGWRITE_CR0_S) || (writeType > IL_FLAGWRITE_CR7_F)) @@ -1373,7 +1373,7 @@ class PowerpcArchitecture: public Architecture virtual std::map GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override { - MYLOG("%s() semgroup:%d", __func__, semGroup); + // MYLOG("%s() semgroup:%d", __func__, semGroup); uint32_t flagClassBase = IL_FLAGCLASS_CR0_S + ((semGroup / 10) * PPC_SUF_SZ); uint32_t groupType = semGroup % 10; @@ -1427,7 +1427,7 @@ class PowerpcArchitecture: public Architecture virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass) override { - MYLOG("%s() flag:%d, semclass:%d\n", __func__, flag, semClass); + // MYLOG("%s() flag:%d, semclass:%d\n", __func__, flag, semClass); ppc_suf suf = (ppc_suf)0; @@ -1486,7 +1486,7 @@ class PowerpcArchitecture: public Architecture */ virtual vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t) override { - MYLOG("%s() cond:%d\n", __func__, cond); + // MYLOG("%s() cond:%d\n", __func__, cond); switch (cond) { diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index 93d7d423b3..b5668adcd3 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -29,6 +29,11 @@ Then some helpers if you need them: #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 //***************************************************************************** diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index 699fc6a762..b3a1524e0e 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -136,7 +136,7 @@ static ExprId operToIL(LowLevelILFunction &il, struct cs_ppc_op *op, /* map PPC_REG_CRX to an IL flagwrite type (a named set of written flags */ int crxToFlagWriteType(int crx, bool signedComparison = true) { - MYLOG("%s() crx:%d", __func__, crx); + // MYLOG("%s() crx:%d", __func__, crx); int flag_out = 0; int crx_local = 0; int crx_type = 0; @@ -171,7 +171,7 @@ int crxToFlagWriteType(int crx, bool signedComparison = true) static ExprId ExtractConditionClause(LowLevelILFunction& il, uint8_t crBit, bool negate = false) { - MYLOG("%s() crbit:%x", __func__, crBit); + // MYLOG("%s() crbit:%x", __func__, crBit); uint32_t flagBase = (crBit / 4) * 10; switch (crBit & 3) @@ -244,7 +244,7 @@ static bool LiftConditionalBranch(LowLevelILFunction& il, uint8_t bo, uint8_t bi static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8_t* data, uint64_t addr, bool le) { - MYLOG("%s() addr:0x%08llx\n", __func__, addr); + // MYLOG("%s() addr:0x%08llx\n", __func__, addr); uint32_t insn = *(const uint32_t *) data; if (!le) @@ -1241,6 +1241,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, break; case PPC_INS_XORI: + case PPC_BN_INS_XORI: case PPC_INS_XORIS: REQUIRE3OPS if (insn->id == PPC_INS_XORIS) @@ -2834,7 +2835,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: From 47820dd11b92eea78cd117ae5a67d91507ff58be Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 13 Dec 2024 15:22:50 -0500 Subject: [PATCH 29/35] gqr strings --- arch/powerpc/disassembler.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 942396a1c2..88f0246668 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -321,9 +321,19 @@ powerpc_disassemble(struct decomp_result *res, char *buf, size_t len) return rc; } +const char* const gqr_array[] = {"gqr0", "gqr1", "gqr2", "gqr3", "gqr4", "gqr5", "gqr6", "gqr7"}; + extern "C" const char * 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(cs_mode_arg); } From 11e4dd5621d4857082ff53275905d227ebfbd9dc Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 13 Dec 2024 15:34:21 -0500 Subject: [PATCH 30/35] gqr's ar in arch --- arch/powerpc/arch_ppc.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index dcd3651f7a..1af73844bb 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -1587,11 +1587,18 @@ class PowerpcArchitecture: public Architecture 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_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 }; + vector gqrarray = { + PPC_REG_BN_GQR0, PPC_REG_BN_GQR1, PPC_REG_BN_GQR2, PPC_REG_BN_GQR3, + PPC_REG_BN_GQR4, PPC_REG_BN_GQR5, PPC_REG_BN_GQR6, PPC_REG_BN_GQR7}; + + + if ((cs_mode_local & CS_MODE_PS) != 0) + { + result.insert(result.end(), gqrarray.begin(), gqrarray.end()); + } + return result; } From ee9f945df287aab331fbbac0fa9436e418202548 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 13 Dec 2024 15:39:21 -0500 Subject: [PATCH 31/35] static qualifier and unused var --- arch/powerpc/arch_ppc.cpp | 3 +-- arch/powerpc/disassembler.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index 1af73844bb..b1acbdd949 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -788,7 +788,7 @@ class PowerpcArchitecture: public Architecture goto cleanup; } -getil: +// getil: rc = GetLowLevelILForPPCInstruction(this, il, data, addr, &res, endian == LittleEndian); len = 4; @@ -800,7 +800,6 @@ class PowerpcArchitecture: public Architecture uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override { // MYLOG("%s(), op:%d, flagwritetype:%d, flag:%d\n", __func__, op, flagWriteType, flag); - bool signedWrite = true; ExprId left, right; ppc_suf suf = (ppc_suf)0; diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 88f0246668..8590394def 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -321,7 +321,7 @@ powerpc_disassemble(struct decomp_result *res, char *buf, size_t len) return rc; } -const char* const gqr_array[] = {"gqr0", "gqr1", "gqr2", "gqr3", "gqr4", "gqr5", "gqr6", "gqr7"}; +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, int cs_mode_arg) From daf63792647bc2c81f06362807d498655de28b06 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Fri, 13 Dec 2024 15:49:02 -0500 Subject: [PATCH 32/35] xed is same commit --- arch/x86/xed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/xed b/arch/x86/xed index afbb851b5f..6d87b5481a 160000 --- a/arch/x86/xed +++ b/arch/x86/xed @@ -1 +1 @@ -Subproject commit afbb851b5f2f2ac6cdb6e6d9bebbaf2d4e77286d +Subproject commit 6d87b5481aa53b5ab1fc2b5a5622759c46746bf9 From 830ab1c70dc8c8aa63e405e269b2ed79b20a4198 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Sat, 14 Dec 2024 17:34:46 -0500 Subject: [PATCH 33/35] added 64 bit updates --- arch/powerpc/arch_ppc.cpp | 160 ++++++------ arch/powerpc/disassembler.cpp | 2 +- arch/powerpc/disassembler.h | 2 +- arch/powerpc/il.cpp | 456 ++++++++++++++++++++-------------- arch/powerpc/util.cpp | 13 + arch/powerpc/util.h | 25 ++ 6 files changed, 387 insertions(+), 271 deletions(-) diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp index b1acbdd949..f732b561ba 100644 --- a/arch/powerpc/arch_ppc.cpp +++ b/arch/powerpc/arch_ppc.cpp @@ -322,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 @@ -364,7 +364,7 @@ class PowerpcArchitecture: public Architecture } /* decompose the instruction to get branch info */ - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { + if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); return false; } @@ -378,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); @@ -397,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) { @@ -535,7 +539,7 @@ class PowerpcArchitecture: public Architecture // PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); return PrintLocalDisassembly(data, addr, len, result, &res); } - if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { + if(powerpc_decompose(data, 4, addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { MYLOG("ERROR: powerpc_decompose()\n"); goto cleanup; } @@ -782,7 +786,7 @@ class PowerpcArchitecture: public Architecture if (DoesQualifyForLocalDisassembly(data, endian == BigEndian)) { PerformLocalDisassembly(data, addr, len, &res, endian == BigEndian); } - else if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8, cs_mode_local)) { + 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; @@ -1629,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); diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp index 8590394def..2a421971da 100644 --- a/arch/powerpc/disassembler.cpp +++ b/arch/powerpc/disassembler.cpp @@ -212,7 +212,7 @@ powerpc_release(void) } extern "C" int -powerpc_decompose(const uint8_t *data, int size, uint32_t addr, bool lil_end, +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; diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h index b5668adcd3..d4679ae0c8 100644 --- a/arch/powerpc/disassembler.h +++ b/arch/powerpc/disassembler.h @@ -90,7 +90,7 @@ bool PerformLocalDisassembly(const uint8_t *data, uint64_t addr, size_t &len, de 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, +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); diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index b3a1524e0e..fd5877c71e 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -132,6 +132,7 @@ 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) @@ -196,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); @@ -207,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) { @@ -241,32 +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 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)))) { @@ -274,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)); } @@ -292,23 +300,27 @@ static bool LiftBranches(Architecture* arch, LowLevelILFunction &il, const uint8 } 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; @@ -320,27 +332,35 @@ 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; } @@ -354,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; @@ -374,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); @@ -435,31 +455,34 @@ 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, +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, @@ -511,11 +534,21 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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 * branch instructions (bdnz, etc.) @@ -590,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); @@ -603,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); @@ -619,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); @@ -639,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); @@ -654,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; @@ -679,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); @@ -702,47 +735,49 @@ 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 */ 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; @@ -891,13 +926,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); @@ -962,7 +1001,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) ) ); @@ -977,15 +1016,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); } @@ -997,15 +1036,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); } @@ -1019,18 +1058,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); } @@ -1044,18 +1083,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); } @@ -1067,14 +1106,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); } @@ -1086,14 +1130,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); } @@ -1139,48 +1188,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; @@ -1191,8 +1240,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; @@ -1201,13 +1250,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); @@ -1217,24 +1266,24 @@ 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); @@ -1245,14 +1294,14 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, 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 ) ); @@ -1264,12 +1313,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); @@ -1278,13 +1327,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); @@ -1294,17 +1343,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); @@ -1314,7 +1363,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, @@ -1330,14 +1379,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); } @@ -1348,15 +1397,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); } @@ -1368,14 +1420,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); } @@ -1386,15 +1438,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); } @@ -1405,15 +1460,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); } @@ -1423,16 +1486,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); } @@ -1444,14 +1518,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); } @@ -1462,7 +1536,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); @@ -1470,7 +1544,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); } @@ -1739,7 +1813,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_MR: /* move register */ REQUIRE2OPS - ei0 = 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; diff --git a/arch/powerpc/util.cpp b/arch/powerpc/util.cpp index 50c3eb5b14..5e37f735c2 100644 --- a/arch/powerpc/util.cpp +++ b/arch/powerpc/util.cpp @@ -85,4 +85,17 @@ void printInstructionVerbose(decomp_result *res) } } +uint64_t sign_extend(size_t addressSize_local, uint64_t target, int signBit) +{ + if ((target >> signBit) & 1) + { + target = target | (~((1 << signBit) - 1)); + } + + if (addressSize_local == 4) + { + target = target & 0xffffffff; + } + return target; +} diff --git a/arch/powerpc/util.h b/arch/powerpc/util.h index fe2b7fdaad..0eb146515d 100644 --- a/arch/powerpc/util.h +++ b/arch/powerpc/util.h @@ -6,6 +6,30 @@ #define FALL_THROUGH #endif +#define ADDRMASK(addressSize, target) \ + if (addressSize == 4) \ + { \ + target &= 0xffffffff; \ + } + +#define EXTOPT(rawInsn, addressSize, extend, TYPE) \ + { \ + int L_tmp = ((rawInsn >> 10) & 1); \ + if ((L_tmp == 1) && (addressSize == 8)) \ + { \ + extend = OTI_ ## TYPE ## EXT64_IMMS; \ + } \ + else \ + { \ + extend = OTI_ ## TYPE ## EXT32_IMMS; \ + } \ + } + +#define EXTOPTZ(data, addressSize, extend) EXTOPT(data, addressSize, extend, Z) +#define EXTOPTS(data, addressSize, extend) EXTOPT(data, addressSize, extend, S) + +#define ADDRNEG1(addressSize) (addressSize == 4) ? ((uint32_t)-1) : ((uint64_t)-1) + inline uint32_t bswap32(uint32_t x) { return ((x&0xFF)<<24) | @@ -16,3 +40,4 @@ inline uint32_t bswap32(uint32_t x) void printOperandVerbose(decomp_result *res, cs_ppc_op *opers); void printInstructionVerbose(decomp_result *res); +uint64_t sign_extend(size_t addressSize_local, uint64_t target, int signBit); \ No newline at end of file From 1e6a68861b27f85073f14ac1cfe1aa03405febb8 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Sat, 14 Dec 2024 17:46:32 -0500 Subject: [PATCH 34/35] cmpdi is just an alias --- arch/powerpc/il.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp index fd5877c71e..43a4706463 100644 --- a/arch/powerpc/il.cpp +++ b/arch/powerpc/il.cpp @@ -763,6 +763,7 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il, case PPC_INS_CMPI: case PPC_INS_CMPWI: /* compare (signed) word(32-bit) immediate */ + case PPC_INS_CMPDI: REQUIRE2OPS EXTOPTS(rawInsn, addressSize_l, extend_l); ei0 = operToIL_a(il, oper2 ? oper1 : oper0, addressSize_l); From 6679c2a10126bc68a5587c66230b56c16d60b8a1 Mon Sep 17 00:00:00 2001 From: David Riusech Date: Mon, 16 Dec 2024 11:57:33 -0500 Subject: [PATCH 35/35] because they said so --- arch/powerpc/capstone | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/capstone b/arch/powerpc/capstone index 650e85dcf2..5cca00533d 160000 --- a/arch/powerpc/capstone +++ b/arch/powerpc/capstone @@ -1 +1 @@ -Subproject commit 650e85dcf23b3a3bff69144511533b7339436238 +Subproject commit 5cca00533dadfe53181f1de3525f859769f69b65