Load/store word/byte (immediate offset)

This commit is contained in:
sschriner
2022-03-07 18:56:40 -05:00
parent d5c74715b1
commit 3fed097de6
4 changed files with 98 additions and 26 deletions
+6 -10
View File
@@ -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,
+13
View File
@@ -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);
}
}
+51 -16
View File
@@ -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
+28
View File
@@ -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>;