diff --git a/lib/Arch/AArch32/Decode.cpp b/lib/Arch/AArch32/Decode.cpp index cd55843a..95d77507 100644 --- a/lib/Arch/AArch32/Decode.cpp +++ b/lib/Arch/AArch32/Decode.cpp @@ -565,10 +565,6 @@ static_assert(sizeof(SpecialRegsAndHints) == 4, " "); static constexpr auto kAddressSize = 32u; -static const char *const kIntRegName[] = { - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"}; - void AddIntRegOp(Instruction &inst, unsigned index, unsigned size, Operand::Action action) { Operand::Register reg; @@ -608,9 +604,9 @@ void AddImmOp(Instruction &inst, uint64_t value, unsigned size, op.size = size; } -static void AddAddrRegOp(Instruction &inst, const char *reg_name, - unsigned mem_size, Operand::Action mem_action, - unsigned disp, unsigned scale = 0) { +void AddAddrRegOp(Instruction &inst, const char *reg_name, unsigned mem_size, + Operand::Action mem_action, + unsigned disp, unsigned scale) { Operand::Address addr; addr.address_size = 32; addr.base_reg.name = reg_name; @@ -907,7 +903,7 @@ static void AddShiftImmCarryOperand(Instruction &inst, uint32_t reg_num, // (shift_t, shift_n) = DecodeImmShift(type, imm5); // (shifted, carry) = Shift_C(R[m], shift_t, shift_n, PSTATE.C); // See an instruction in Integer Data Processing (three register, immediate shift) set for an example -static void AddShiftRegImmOperand(Instruction &inst, uint32_t reg_num, +void AddShiftRegImmOperand(Instruction &inst, uint32_t reg_num, uint32_t shift_type, uint32_t shift_size, bool carry_out, bool can_shift_right_by_32) { auto is_rrx = false; @@ -1190,7 +1186,7 @@ static bool EvalPCDest(Instruction &inst, const bool s, const unsigned int rd, auto src2 = EvalOperand(inst, inst.operands[4], uses_linkreg); AddAddrRegOp(inst, kNextPCVariableName.data(), kAddressSize, - Operand::kActionWrite, 0); + Operand::kActionWrite, 0u); if (uses_linkreg) { @@ -3625,7 +3621,7 @@ static uint32_t BytesToBits(const uint8_t *bytes) { bits = (bits << 8) | static_cast(bytes[0]); return bits; } -} // namespace +} // namespace aarch32 // Decode an instruction bool AArch32Arch::DecodeInstruction(uint64_t address, diff --git a/lib/Arch/AArch32/Decode.h b/lib/Arch/AArch32/Decode.h index d21189ef..082b6eab 100644 --- a/lib/Arch/AArch32/Decode.h +++ b/lib/Arch/AArch32/Decode.h @@ -24,6 +24,10 @@ static constexpr auto kPCRegNum = 15u; static constexpr auto kLRRegNum = 14u; static constexpr auto kSPRegNum = 13u; +static const char *const kIntRegName[] = { + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"}; + typedef std::optional(InstEval)(uint32_t, uint32_t); //bool DecodeCondition(Instruction &inst, uint32_t cond); @@ -34,9 +38,18 @@ void AddIntRegOp(Instruction &inst, unsigned index, unsigned size, void AddIntRegOp(Instruction &inst, const char *reg_name, unsigned size, Operand::Action action); +void AddAddrRegOp(Instruction &inst, const char *reg_name, unsigned mem_size, + Operand::Action mem_action, + unsigned disp, unsigned scale = 0); + void AddImmOp(Instruction &inst, uint64_t value, unsigned size = 32, bool is_signed = false); +void AddShiftRegImmOperand(Instruction &inst, uint32_t reg_num, + uint32_t shift_type, uint32_t shift_size, + bool carry_out, bool can_shift_right_by_32); + + } } diff --git a/lib/Arch/AArch32/DecodeThumb2.cpp b/lib/Arch/AArch32/DecodeThumb2.cpp index d7784d4e..4117b568 100644 --- a/lib/Arch/AArch32/DecodeThumb2.cpp +++ b/lib/Arch/AArch32/DecodeThumb2.cpp @@ -21,6 +21,7 @@ #include "Arch.h" #include "Decode.h" #include "remill/BC/ABI.h" +#include "remill/Arch/Name.h" namespace remill { @@ -319,7 +320,7 @@ static const char *const kIdpAddSubComp1LowRegImm[] = { // 01 CMP (immediate) // 10 ADD, ADDS (immediate) // 11 SUB, SUBS (immediate) -// Add, subtract, compare, move (one low register and immediate) TODO(sonya) +// Add, subtract, compare, move (one low register and immediate) static bool TryDecode16AddSubComp1LowRegImm(Instruction &inst, uint16_t bits) { // TODO(sonya): setflags = !InITBlock() @@ -339,37 +340,68 @@ static bool TryDecode16AddSubComp1LowRegImm(Instruction &inst, uint16_t bits) { } -// MOV, MOVS (register) — T2 TODO(sonya) +// MOV, MOVS (register) — T2 static bool TryDecode16MOVrT2(Instruction &inst, uint16_t bits) { - inst.category = Instruction::kCategoryError; - return false; -// const MOVrT2_16 enc = {bits}; -// inst.category = Instruction::kCategoryNormal; -// inst.function = "MOVL_T2"; -// -// return true; + const MOVrT2_16 enc = {bits}; + inst.category = Instruction::kCategoryNormal; + inst.function = "MOVL_T2"; + + // TODO(sonya): setflags = !InITBlock() + // if op == '00' && imm5 == '00000' && InITBlock() then UNPREDICTABLE; + + AddIntRegOp(inst, uint32_t(enc.Rd), 32u, Operand::kActionWrite); + + // (shift_t, shift_n) = DecodeImmShift(op, imm5); + AddShiftRegImmOperand(inst, uint32_t(enc.Rm), uint32_t(enc.op), + uint32_t(enc.imm5), false, false); + + return true; } +static const char *const kIdpLoadStoreWordByte[] = { + [0b00] = "STR_T2", [0b01] = "LDR_T2", + [0b10] = "STRB_T2", [0b11] = "LDRB_T2" +}; + // B L // 0 0 STR (immediate) // 0 1 LDR (immediate) // 1 0 STRB (immediate) // 1 1 LDRB (immediate) -// Load/store word/byte (immediate offset) TODO(sonya) +// Load/store word/byte (immediate offset) +template static bool TryDecode16LoadStoreWordByteImm(Instruction &inst, uint16_t bits) { - inst.category = Instruction::kCategoryError; - return false; -// const LoadStoreWordByteImm16 enc = {bits}; + inst.category = Instruction::kCategoryNormal; + const LoadStoreWordByteImm16 enc = {bits}; + inst.function = kIdpLoadStoreWordByte[(enc.B << 1) | enc.L]; + + AddAddrRegOp(inst, kIntRegName[enc.Rt], 32u, kRegAction, 0u); + AddAddrRegOp(inst, kIntRegName[enc.Rn], 32u, kMemAction, enc.imm5 << 2); + + return true; } +static TryDecode16 *kDecode16LoadStoreWordByteImm[] = { + [0b00] = TryDecode16LoadStoreWordByteImm, + [0b01] = TryDecode16LoadStoreWordByteImm, + [0b10] = TryDecode16LoadStoreWordByteImm, + [0b11] = TryDecode16LoadStoreWordByteImm +}; + // L // 0 STR (immediate) // 1 LDR (immediate) // Load/store (SP-relative) TODO(sonya) static bool TryDecode16LoadStoreSPRelative(Instruction &inst, uint16_t bits) { inst.category = Instruction::kCategoryError; + return false; // const LoadStoreSPRelative16 enc = {bits}; } @@ -377,7 +409,7 @@ static bool TryDecode16LoadStoreSPRelative(Instruction &inst, uint16_t bits) { // SP // 0 ADR // 1 ADD, ADDS (SP plus immediate) -// Add PC/SP (immediate) TODO(sonya) +// Add PC/SP (immediate) static bool TryDecode16AddPCSP(Instruction &inst, uint16_t bits) { const AddPCSPImm16 enc = {bits}; @@ -556,7 +588,7 @@ static TryDecode16 *Try16bit(uint16_t bits) { // 011xxx Load/store word/byte (immediate offset) } else if ((op0 >> 3) == 0b011) { - return TryDecode16LoadStoreWordByteImm; + return kDecode16LoadStoreWordByteImm[(op0 >> 1) & 0b11]; // 1001xx Load/store (SP-relative) } else if ((op0 >> 2) == 0b1001) { @@ -587,6 +619,8 @@ static TryDecode16 *Try16bit(uint16_t bits) { return nullptr; } + + // op0 op1 op2 op3 op4 op5 // 0 1110 0x 0x0 0 MSR (register) // 0 1110 0x 0x0 1 MSR (Banked register) @@ -705,7 +739,8 @@ bool DecodeThumb2Instruction(Instruction &inst, uint32_t bits) { LOG(ERROR) << inst.Serialize(); return ret; } -} // namespace + +} // namespace aarch32 } // namespace remill diff --git a/lib/Arch/AArch32/Semantics/MEM.cpp b/lib/Arch/AArch32/Semantics/MEM.cpp index bfa1a446..00436889 100644 --- a/lib/Arch/AArch32/Semantics/MEM.cpp +++ b/lib/Arch/AArch32/Semantics/MEM.cpp @@ -507,3 +507,31 @@ DEF_ISEL(STMIB) = STMDB; DEF_ISEL(LDMIB) = LDM; // DEF_ISEL(LDMe) = LDMe; + +// Thumb2 +namespace { + + +template +DEF_SEM(STR_T2, M dst, R32 src1) { + auto src = TruncTo(Read(src1)); + WriteZExt(dst, src); + + return memory; +} + +template +DEF_SEM(LDR_T2, R32W dst, M src1) { + auto src = Read(src1); + WriteZExt(dst, src); + + return memory; +} +} // namespace + +DEF_ISEL(STR_T2) = STR_T2; +DEF_ISEL(LDR_T2) = LDR_T2; +DEF_ISEL(STRB_T2) = STR_T2; +DEF_ISEL(LDRB_T2) = LDR_T2; + +