mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
Load/store word/byte (immediate offset)
This commit is contained in:
@@ -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<uint32_t>(bytes[0]);
|
||||
return bits;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace aarch32
|
||||
|
||||
// Decode an instruction
|
||||
bool AArch32Arch::DecodeInstruction(uint64_t address,
|
||||
|
||||
@@ -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<uint32_t>(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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <Operand::Action kMemAction, Operand::Action kRegAction,
|
||||
unsigned kMemSize>
|
||||
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<Operand::kActionWrite,
|
||||
Operand::kActionRead, 32u >,
|
||||
[0b01] = TryDecode16LoadStoreWordByteImm<Operand::kActionRead,
|
||||
Operand::kActionWrite, 32u >,
|
||||
[0b10] = TryDecode16LoadStoreWordByteImm<Operand::kActionWrite,
|
||||
Operand::kActionRead, 8u >,
|
||||
[0b11] = TryDecode16LoadStoreWordByteImm<Operand::kActionRead,
|
||||
Operand::kActionWrite, 8u >
|
||||
};
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
@@ -507,3 +507,31 @@ DEF_ISEL(STMIB) = STMDB;
|
||||
DEF_ISEL(LDMIB) = LDM;
|
||||
|
||||
// DEF_ISEL(LDMe) = LDMe;
|
||||
|
||||
// Thumb2
|
||||
namespace {
|
||||
|
||||
|
||||
template<typename M, typename T>
|
||||
DEF_SEM(STR_T2, M dst, R32 src1) {
|
||||
auto src = TruncTo<T>(Read(src1));
|
||||
WriteZExt(dst, src);
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
template<typename M>
|
||||
DEF_SEM(LDR_T2, R32W dst, M src1) {
|
||||
auto src = Read(src1);
|
||||
WriteZExt(dst, src);
|
||||
|
||||
return memory;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
DEF_ISEL(STR_T2) = STR_T2<M32W, uint32_t>;
|
||||
DEF_ISEL(LDR_T2) = LDR_T2<M32>;
|
||||
DEF_ISEL(STRB_T2) = STR_T2<M8W, uint8_t>;
|
||||
DEF_ISEL(LDRB_T2) = LDR_T2<M8>;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user