Commit a495dc5c authored by swift_gan's avatar swift_gan

add LDR

parent 8c61e806
......@@ -214,7 +214,7 @@ A64_TBZ_TBNZ::A64_TBZ_TBNZ(A64_TBZ_TBNZ::OP op, RegisterA64 *rt, U32 bit, ADDR o
}
ADDR A64_TBZ_TBNZ::getImmPCOffset() {
return signExtend64(14, get()->imm14) << 2;
return signExtend64(14 + 2, COMBINE(get()->imm14, 0b00, 2));
}
void A64_TBZ_TBNZ::decode(STRUCT_A64(TBZ_TBNZ) *inst) {
......@@ -236,3 +236,40 @@ void A64_TBZ_TBNZ::assembler() {
get()->b40 = static_cast<InstA64>(BITS(bit, sizeof(InstA64) - 5, sizeof(InstA64)));
get()->imm14 = TruncateToUint14(offset);
}
// LDR(literal)
A64_LDR_LIT::A64_LDR_LIT() {}
A64_LDR_LIT::A64_LDR_LIT(STRUCT_A64(LDR_LIT) *inst) : A64_INST_PC_REL(inst) {
decode(inst);
}
A64_LDR_LIT::A64_LDR_LIT(A64_LDR_LIT::OP op, RegisterA64 *rt, ADDR offset) : op(op), rt(rt),
offset(offset) {
assembler();
}
ADDR A64_LDR_LIT::getImmPCOffset() {
return signExtend64(19 + 2, COMBINE(get()->imm19, 0b00, 2));
}
void A64_LDR_LIT::decode(STRUCT_A64(LDR_LIT) *inst) {
op = OP(inst->op);
if (op == LDR_W) {
rt = WRegister::get(static_cast<U8>(inst->rt));
} else {
rt = XRegister::get(static_cast<U8>(inst->rt));
}
offset = getImmPCOffset();
}
void A64_LDR_LIT::assembler() {
SET_OPCODE(LDR_LIT);
get()->rt = rt->getCode();
get()->op = op;
get()->imm19 = TruncateToUint19(offset);
}
......@@ -46,9 +46,13 @@ namespace SandHook {
U8 size() override;
static inline U32 signExtend64(unsigned int bits, U64 value) {
U32 C = (U32) ((-1) << (bits - (U32) 1));
return static_cast<U32>((value + C) ^ C);
static inline U32 extend32(unsigned int bits, U32 value) {
return value << (32 - bits);
}
static inline U64 signExtend64(unsigned int bits, U64 value) {
U64 C = (U64) ((-1) << (bits - (U64) 1));
return static_cast<U64>((value + C) ^ C);
}
bool isPCRelAddressing() {
......@@ -65,6 +69,8 @@ namespace SandHook {
};
enum AddrMode { Offset, PreIndex, PostIndex };
template <typename Inst>
class A64_INST_PC_REL : public InstructionA64<Inst> {
......@@ -203,6 +209,8 @@ namespace SandHook {
A64_B_BL(OP op, ADDR offset);
DEFINE_IS(B_BL)
inline ADDR getOffset() {
return offset;
}
......@@ -242,6 +250,8 @@ namespace SandHook {
A64_CBZ_CBNZ(OP op, ADDR offset, RegisterA64 *rt);
DEFINE_IS(CBZ_CBNZ)
inline U32 instCode() override {
return op == CBZ ? CompareBranchOp::CBZ : CompareBranchOp::CBNZ;
}
......@@ -267,6 +277,8 @@ namespace SandHook {
A64_B_COND(Condition condition, ADDR offset);
DEFINE_IS(B_COND)
inline U32 instCode() override {
return B_cond;
}
......@@ -297,6 +309,8 @@ namespace SandHook {
A64_TBZ_TBNZ(OP op, RegisterA64 *rt, U32 bit, ADDR offset);
DEFINE_IS(TBZ_TBNZ)
inline U32 instCode() override {
return op == TBZ ? TestBranchOp::TBZ : TestBranchOp::TBNZ;
};
......@@ -314,6 +328,50 @@ namespace SandHook {
ADDR offset;
};
class INST_A64(LDR_LIT) : public A64_INST_PC_REL<STRUCT_A64(LDR_LIT)> {
public:
enum OP {
LDR_W = 0b00,
LDR_X = 0b01,
LDR_SW = 0b10,
LDR_PRFM = 0b11
};
A64_LDR_LIT();
A64_LDR_LIT(STRUCT_A64(LDR_LIT) *inst);
A64_LDR_LIT(OP op, RegisterA64 *rt, ADDR offset);
DEFINE_IS(LDR_LIT)
inline U32 instCode() override {
switch (op) {
case LDR_W:
return LoadLiteralOp::LDR_w_lit;
case LDR_X:
return LoadLiteralOp::LDR_x_lit;
case LDR_SW:
return LoadLiteralOp::LDRSW_x_lit;
case LDR_PRFM:
return LoadLiteralOp::PRFM_lit;
}
}
ADDR getImmPCOffset() override;
void decode(STRUCT_A64(LDR_LIT) *inst) override;
void assembler() override;
private:
OP op;
RegisterA64* rt;
ADDR offset;
};
}
}
......
......@@ -82,4 +82,55 @@ enum TestBranchOp {
TBNZ = TestBranchFixed | 0x01000000
};
// Load literal.
enum LoadLiteralOp {
LoadLiteralFixed = 0x18000000,
LoadLiteralFMask = 0x3B000000,
LoadLiteralMask = 0xFF000000,
LDR_w_lit = LoadLiteralFixed | 0x00000000,
LDR_x_lit = LoadLiteralFixed | 0x40000000,
LDRSW_x_lit = LoadLiteralFixed | 0x80000000,
PRFM_lit = LoadLiteralFixed | 0xC0000000,
LDR_s_lit = LoadLiteralFixed | 0x04000000,
LDR_d_lit = LoadLiteralFixed | 0x44000000,
LDR_q_lit = LoadLiteralFixed | 0x84000000
};
#define LOAD_STORE_OP_LIST(V) \
V(ST, RB, w, 0x00000000), \
V(ST, RH, w, 0x40000000), \
V(ST, R, w, 0x80000000), \
V(ST, R, x, 0xC0000000), \
V(LD, RB, w, 0x00400000), \
V(LD, RH, w, 0x40400000), \
V(LD, R, w, 0x80400000), \
V(LD, R, x, 0xC0400000), \
V(LD, RSB, x, 0x00800000), \
V(LD, RSH, x, 0x40800000), \
V(LD, RSW, x, 0x80800000), \
V(LD, RSB, w, 0x00C00000), \
V(LD, RSH, w, 0x40C00000), \
V(ST, R, b, 0x04000000), \
V(ST, R, h, 0x44000000), \
V(ST, R, s, 0x84000000), \
V(ST, R, d, 0xC4000000), \
V(ST, R, q, 0x04800000), \
V(LD, R, b, 0x04400000), \
V(LD, R, h, 0x44400000), \
V(LD, R, s, 0x84400000), \
V(LD, R, d, 0xC4400000), \
V(LD, R, q, 0x04C00000)
// Load/store (post, pre, offset and unsigned.)
enum LoadStoreOp {
LoadStoreMask = 0xC4C00000,
LoadStoreVMask = 0x04000000,
#define LOAD_STORE(A, B, C, D) \
A##B##_##C = D
LOAD_STORE_OP_LIST(LOAD_STORE),
#undef LOAD_STORE
PRFM = 0xC0800000
};
#endif //SANDHOOK_NH_INST_CODE_ARM64_H
......@@ -65,6 +65,27 @@ enum Condition {
lo = cc // C clear Unsigned lower.
};
enum Shift {
NO_SHIFT = -1,
LSL = 0x0,
LSR = 0x1,
ASR = 0x2,
ROR = 0x3,
MSL = 0x4
};
enum Extend {
NO_EXTEND = -1,
UXTB = 0,
UXTH = 1,
UXTW = 2,
UXTX = 3,
SXTB = 4,
SXTH = 5,
SXTW = 6,
SXTX = 7
};
#define IMM_LO_W 2
#define IMM_HI_W 19
DEFINE_OPCODE(ADR_ADRP, 0b10000)
......@@ -122,6 +143,27 @@ struct STRUCT_A64(TBZ_TBNZ) {
InstA64 rt:5;
};
DEFINE_OPCODE(LDR_LIT, 0b011000)
struct STRUCT_A64(LDR_LIT) {
InstA64 op:2;
InstA64 opcode:6;
InstA64 imm19:1;
InstA64 rt:5;
};
DEFINE_OPCODE(STR_IMM, 0b011)
struct STRUCT_A64(STR_IMM) {
InstA64 cond:4;
InstA64 opcode:3;
InstA64 P:1;
InstA64 unkown:1;
InstA64 W:1;
InstA64 unkown2:1;
InstA64 rn:4;
InstA64 rt:4;
InstA64 imm12:12;
};
#endif //SANDHOOK_NH_INST_AARCH64_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment