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 ...@@ -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() { 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) { void A64_TBZ_TBNZ::decode(STRUCT_A64(TBZ_TBNZ) *inst) {
...@@ -236,3 +236,40 @@ void A64_TBZ_TBNZ::assembler() { ...@@ -236,3 +236,40 @@ void A64_TBZ_TBNZ::assembler() {
get()->b40 = static_cast<InstA64>(BITS(bit, sizeof(InstA64) - 5, sizeof(InstA64))); get()->b40 = static_cast<InstA64>(BITS(bit, sizeof(InstA64) - 5, sizeof(InstA64)));
get()->imm14 = TruncateToUint14(offset); 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 { ...@@ -46,9 +46,13 @@ namespace SandHook {
U8 size() override; U8 size() override;
static inline U32 signExtend64(unsigned int bits, U64 value) { static inline U32 extend32(unsigned int bits, U32 value) {
U32 C = (U32) ((-1) << (bits - (U32) 1)); return value << (32 - bits);
return static_cast<U32>((value + C) ^ C); }
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() { bool isPCRelAddressing() {
...@@ -65,6 +69,8 @@ namespace SandHook { ...@@ -65,6 +69,8 @@ namespace SandHook {
}; };
enum AddrMode { Offset, PreIndex, PostIndex };
template <typename Inst> template <typename Inst>
class A64_INST_PC_REL : public InstructionA64<Inst> { class A64_INST_PC_REL : public InstructionA64<Inst> {
...@@ -203,6 +209,8 @@ namespace SandHook { ...@@ -203,6 +209,8 @@ namespace SandHook {
A64_B_BL(OP op, ADDR offset); A64_B_BL(OP op, ADDR offset);
DEFINE_IS(B_BL)
inline ADDR getOffset() { inline ADDR getOffset() {
return offset; return offset;
} }
...@@ -242,6 +250,8 @@ namespace SandHook { ...@@ -242,6 +250,8 @@ namespace SandHook {
A64_CBZ_CBNZ(OP op, ADDR offset, RegisterA64 *rt); A64_CBZ_CBNZ(OP op, ADDR offset, RegisterA64 *rt);
DEFINE_IS(CBZ_CBNZ)
inline U32 instCode() override { inline U32 instCode() override {
return op == CBZ ? CompareBranchOp::CBZ : CompareBranchOp::CBNZ; return op == CBZ ? CompareBranchOp::CBZ : CompareBranchOp::CBNZ;
} }
...@@ -267,6 +277,8 @@ namespace SandHook { ...@@ -267,6 +277,8 @@ namespace SandHook {
A64_B_COND(Condition condition, ADDR offset); A64_B_COND(Condition condition, ADDR offset);
DEFINE_IS(B_COND)
inline U32 instCode() override { inline U32 instCode() override {
return B_cond; return B_cond;
} }
...@@ -297,6 +309,8 @@ namespace SandHook { ...@@ -297,6 +309,8 @@ namespace SandHook {
A64_TBZ_TBNZ(OP op, RegisterA64 *rt, U32 bit, ADDR offset); A64_TBZ_TBNZ(OP op, RegisterA64 *rt, U32 bit, ADDR offset);
DEFINE_IS(TBZ_TBNZ)
inline U32 instCode() override { inline U32 instCode() override {
return op == TBZ ? TestBranchOp::TBZ : TestBranchOp::TBNZ; return op == TBZ ? TestBranchOp::TBZ : TestBranchOp::TBNZ;
}; };
...@@ -314,6 +328,50 @@ namespace SandHook { ...@@ -314,6 +328,50 @@ namespace SandHook {
ADDR offset; 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 { ...@@ -82,4 +82,55 @@ enum TestBranchOp {
TBNZ = TestBranchFixed | 0x01000000 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 #endif //SANDHOOK_NH_INST_CODE_ARM64_H
...@@ -65,6 +65,27 @@ enum Condition { ...@@ -65,6 +65,27 @@ enum Condition {
lo = cc // C clear Unsigned lower. 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_LO_W 2
#define IMM_HI_W 19 #define IMM_HI_W 19
DEFINE_OPCODE(ADR_ADRP, 0b10000) DEFINE_OPCODE(ADR_ADRP, 0b10000)
...@@ -122,6 +143,27 @@ struct STRUCT_A64(TBZ_TBNZ) { ...@@ -122,6 +143,27 @@ struct STRUCT_A64(TBZ_TBNZ) {
InstA64 rt:5; 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 #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