remove namespace

This commit is contained in:
Lysann Tranvouez 2025-10-01 21:19:29 +02:00
parent 82e6abc1ee
commit a63de06aa9

View file

@ -36,291 +36,279 @@
// TBZ z0110110 bbbbbiii iiiiiiii iiittttt & 0x7f000000 == 0x36000000 (z = size, b = bitnum, i = SignExtend(imm14:00, 64), t = Rt) // TBZ z0110110 bbbbbiii iiiiiiii iiittttt & 0x7f000000 == 0x36000000 (z = size, b = bitnum, i = SignExtend(imm14:00, 64), t = Rt)
// //
namespace detour_arm64_disasm union detour_arm64_disasm_add_imm12
{ {
union add_imm12 uint32_t assembled;
struct
{ {
uint32_t assembled; uint32_t rd : 5; // Destination register
struct uint32_t rn : 5; // Source register
{ uint32_t imm12 : 12; // 12-bit immediate
uint32_t rd : 5; // Destination register uint32_t shift : 2; // shift (must be 0 or 1)
uint32_t rn : 5; // Source register uint32_t opcode1 : 7; // Must be 0010001 == 0x11
uint32_t imm12 : 12; // 12-bit immediate uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
uint32_t shift : 2; // shift (must be 0 or 1) } s;
uint32_t opcode1 : 7; // Must be 0010001 == 0x11 static uint32_t assemble(uint32_t size, uint32_t rd, uint32_t rn, uint32_t imm, uint32_t shift)
uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
} s;
static uint32_t assemble(uint32_t size, uint32_t rd, uint32_t rn, uint32_t imm, uint32_t shift)
{
add_imm12 temp;
temp.s.rd = rd;
temp.s.rn = rn;
temp.s.imm12 = imm & 0xfff;
temp.s.shift = shift;
temp.s.opcode1 = 0x11;
temp.s.size = size;
return temp.assembled;
}
static uint32_t assemble_add_32(const uint32_t rd, const uint32_t rn, const uint32_t imm, const uint32_t shift) { return assemble(0, rd, rn, imm, shift); }
static uint32_t assemble_add_64(const uint32_t rd, const uint32_t rn, const uint32_t imm, const uint32_t shift) { return assemble(1, rd, rn, imm, shift); }
};
union adr19
{ {
uint32_t assembled; detour_arm64_disasm_add_imm12 temp;
struct temp.s.rd = rd;
{ temp.s.rn = rn;
uint32_t rd : 5; // Destination register temp.s.imm12 = imm & 0xfff;
uint32_t imm19 : 19; // 19-bit upper immediate temp.s.shift = shift;
uint32_t opcode1 : 5; // Must be 10000 == 0x10 temp.s.opcode1 = 0x11;
uint32_t imm2 : 2; // 2-bit lower immediate temp.s.size = size;
uint32_t type : 1; // 0 = ADR, 1 = ADRP return temp.assembled;
} s;
inline int32_t imm() const { uint32_t Imm = (s.imm19 << 2) | s.imm2; return (int32_t)(Imm << 11) >> 11; }
static uint32_t assemble(uint32_t type, uint32_t rd, int32_t delta)
{
adr19 temp;
temp.s.rd = rd;
temp.s.imm19 = (delta >> 2) & 0x7ffff;
temp.s.opcode1 = 0x10;
temp.s.imm2 = delta & 3;
temp.s.type = type;
return temp.assembled;
}
static uint32_t assemble_adr(uint32_t rd, int32_t delta) { return assemble(0, rd, delta); }
static uint32_t assemble_adrp(uint32_t rd, int32_t delta) { return assemble(1, rd, delta); }
};
union bcc19
{
uint32_t assembled;
struct
{
uint32_t condition : 4; // Condition
uint32_t opcode1 : 1; // Must be 0
uint32_t imm19 : 19; // 19-bit immediate
uint32_t opcode2 : 8; // Must be 01010100 == 0x54
} s;
inline int32_t imm() const { return (int32_t)(s.imm19 << 13) >> 11; }
static uint32_t assemble_bcc(uint32_t condition, int32_t delta)
{
bcc19 temp;
temp.s.condition = condition;
temp.s.opcode1 = 0;
temp.s.imm19 = delta >> 2;
temp.s.opcode2 = 0x54;
return temp.assembled;
}
};
union branch26
{
uint32_t assembled;
struct
{
uint32_t imm26 : 26; // 26-bit immediate
uint32_t opcode1 : 5; // Must be 00101 == 0x5
uint32_t link : 1; // 0 = B, 1 = BL
} s;
inline int32_t imm() const { return (int32_t)(s.imm26 << 6) >> 4; }
static uint32_t assemble(uint32_t link, int32_t delta)
{
branch26 temp;
temp.s.imm26 = delta >> 2;
temp.s.opcode1 = 0x5;
temp.s.link = link;
return temp.assembled;
}
static uint32_t assemble_b(int32_t delta) { return assemble(0, delta); }
static uint32_t assemble_bl(int32_t delta) { return assemble(1, delta); }
};
union br
{
uint32_t assembled;
struct
{
uint32_t opcode1 : 5; // Must be 00000 == 0
uint32_t rn : 5; // Register number
uint32_t opcode2 : 22; // Must be 1101011000011111000000 == 0x3587c0 for Br
// 0x358fc0 for Brl
} s;
static uint32_t assemble(uint32_t rn, bool link)
{
br temp;
temp.s.opcode1 = 0;
temp.s.rn = rn;
temp.s.opcode2 = 0x3587c0;
if (link)
temp.assembled |= 0x00200000;
return temp.assembled;
}
static uint32_t assemble_br(uint32_t rn)
{
return assemble(rn, false);
}
static uint32_t assemble_brl(uint32_t rn)
{
return assemble(rn, true);
}
};
union cbz19
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Register to test
uint32_t imm19 : 19; // 19-bit immediate
uint32_t nz : 1; // 0 = CBZ, 1 = CBNZ
uint32_t opcode1 : 6; // Must be 011010 == 0x1a
uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
} s;
inline int32_t imm() const { return (int32_t)(s.imm19 << 13) >> 11; }
static uint32_t assemble(uint32_t size, uint32_t nz, uint32_t rt, int32_t delta)
{
cbz19 temp;
temp.s.rt = rt;
temp.s.imm19 = delta >> 2;
temp.s.nz = nz;
temp.s.opcode1 = 0x1a;
temp.s.size = size;
return temp.assembled;
}
};
union ldr_lit19
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Destination register
uint32_t imm19 : 19; // 19-bit immediate
uint32_t opcode1 : 2; // Must be 0
uint32_t fp_neon : 1; // 0 = LDR Wt/LDR Xt/LDRSW/PRFM, 1 = LDR St/LDR Dt/LDR Qt
uint32_t opcode2 : 3; // Must be 011 = 3
uint32_t size : 2; // 00 = LDR Wt/LDR St, 01 = LDR Xt/LDR Dt, 10 = LDRSW/LDR Qt, 11 = PRFM/invalid
} s;
inline int32_t imm() const { return (int32_t)(s.imm19 << 13) >> 11; }
static uint32_t assemble(uint32_t size, uint32_t fpneon, uint32_t rt, int32_t delta)
{
ldr_lit19 temp;
temp.s.rt = rt;
temp.s.imm19 = delta >> 2;
temp.s.opcode1 = 0;
temp.s.fp_neon = fpneon;
temp.s.opcode2 = 3;
temp.s.size = size;
return temp.assembled;
}
};
union ldr_fp_neon_imm9
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Destination register
uint32_t rn : 5; // Base register
uint32_t imm12 : 12; // 12-bit immediate
uint32_t opcode1 : 1; // Must be 1 == 1
uint32_t opc : 1; // Part of size
uint32_t opcode2 : 6; // Must be 111101 == 0x3d
uint32_t size : 2; // Size (0=8-bit, 1=16-bit, 2=32-bit, 3=64-bit, 4=128-bit)
} s;
static uint32_t assemble(uint32_t size, uint32_t rt, uint32_t rn, uint32_t imm)
{
ldr_fp_neon_imm9 temp;
temp.s.rt = rt;
temp.s.rn = rn;
temp.s.imm12 = imm;
temp.s.opcode1 = 1;
temp.s.opc = size >> 2;
temp.s.opcode2 = 0x3d;
temp.s.size = size & 3;
return temp.assembled;
}
};
union mov16
{
uint32_t assembled;
struct
{
uint32_t rd : 5; // Destination register
uint32_t imm16 : 16; // Immediate
uint32_t shift : 2; // Shift amount (0=0, 1=16, 2=32, 3=48)
uint32_t opcode : 6; // Must be 100101 == 0x25
uint32_t type : 2; // 0 = MOVN, 1 = reserved, 2 = MOVZ, 3 = MOVK
uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
} s;
static uint32_t assemble(uint32_t size, uint32_t type, uint32_t rd, uint32_t imm, uint32_t shift)
{
mov16 temp;
temp.s.rd = rd;
temp.s.imm16 = imm;
temp.s.shift = shift;
temp.s.opcode = 0x25;
temp.s.type = type;
temp.s.size = size;
return temp.assembled;
}
static uint32_t assemble_movn32(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(0, 0, rd, imm, shift); }
static uint32_t assemble_movn64(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(1, 0, rd, imm, shift); }
static uint32_t assemble_movz32(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(0, 2, rd, imm, shift); }
static uint32_t assemble_movz64(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(1, 2, rd, imm, shift); }
static uint32_t assemble_movk32(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(0, 3, rd, imm, shift); }
static uint32_t assemble_movk64(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(1, 3, rd, imm, shift); }
};
union tbz14
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Register to test
uint32_t imm14 : 14; // 14-bit immediate
uint32_t bit : 5; // 5-bit index
uint32_t nz : 1; // 0 = TBZ, 1 = TBNZ
uint32_t opcode1 : 6; // Must be 011011 == 0x1b
uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
} s;
inline int32_t imm() const { return (int32_t)(s.imm14 << 18) >> 16; }
static uint32_t assemble(uint32_t size, uint32_t nz, uint32_t rt, uint32_t bit, int32_t delta)
{
tbz14 temp;
temp.s.rt = rt;
temp.s.imm14 = delta >> 2;
temp.s.bit = bit;
temp.s.nz = nz;
temp.s.opcode1 = 0x1b;
temp.s.size = size;
return temp.assembled;
}
};
static uint8_t pure_copy32(uint8_t* source, uint8_t* dest);
static uint8_t emit_mov_immediate(uint32_t*& dst_inst, uint8_t rd, uint64_t immediate);
static uint8_t copy_adr(uint8_t* source, uint8_t* dest, uint32_t instruction) ;
static uint8_t copy_bcc(uint8_t* source, uint8_t* dest, uint32_t instruction);
static uint8_t copy_b_or_bl(uint8_t* source, uint8_t* dest, uint32_t instruction, bool link);
static uint8_t copy_cbz(uint8_t* source, uint8_t* dest, uint32_t instruction);
static uint8_t copy_tbz(uint8_t* source, uint8_t* dest, uint32_t instruction);
static uint8_t copy_ldr_literal(uint8_t* source, uint8_t* dest, uint32_t instruction);
static uint32_t get_instruction(uint8_t* source)
{
return ((uint32_t*)source)[0];
} }
static uint32_t assemble_add_32(const uint32_t rd, const uint32_t rn, const uint32_t imm, const uint32_t shift) { return assemble(0, rd, rn, imm, shift); }
static uint32_t assemble_add_64(const uint32_t rd, const uint32_t rn, const uint32_t imm, const uint32_t shift) { return assemble(1, rd, rn, imm, shift); }
};
static uint8_t emit_instruction(uint32_t*& dst_inst, uint32_t instruction) union detour_arm64_disasm_adr19
{
uint32_t assembled;
struct
{ {
*dst_inst++ = instruction; uint32_t rd : 5; // Destination register
return sizeof(uint32_t); uint32_t imm19 : 19; // 19-bit upper immediate
uint32_t opcode1 : 5; // Must be 10000 == 0x10
uint32_t imm2 : 2; // 2-bit lower immediate
uint32_t type : 1; // 0 = ADR, 1 = ADRP
} s;
inline int32_t imm() const { uint32_t Imm = (s.imm19 << 2) | s.imm2; return (int32_t)(Imm << 11) >> 11; }
static uint32_t assemble(uint32_t type, uint32_t rd, int32_t delta)
{
detour_arm64_disasm_adr19 temp;
temp.s.rd = rd;
temp.s.imm19 = (delta >> 2) & 0x7ffff;
temp.s.opcode1 = 0x10;
temp.s.imm2 = delta & 3;
temp.s.type = type;
return temp.assembled;
}
static uint32_t assemble_adr(uint32_t rd, int32_t delta) { return assemble(0, rd, delta); }
static uint32_t assemble_adrp(uint32_t rd, int32_t delta) { return assemble(1, rd, delta); }
};
union detour_arm64_disasm_bcc19
{
uint32_t assembled;
struct
{
uint32_t condition : 4; // Condition
uint32_t opcode1 : 1; // Must be 0
uint32_t imm19 : 19; // 19-bit immediate
uint32_t opcode2 : 8; // Must be 01010100 == 0x54
} s;
inline int32_t imm() const { return (int32_t)(s.imm19 << 13) >> 11; }
static uint32_t assemble_bcc(uint32_t condition, int32_t delta)
{
detour_arm64_disasm_bcc19 temp;
temp.s.condition = condition;
temp.s.opcode1 = 0;
temp.s.imm19 = delta >> 2;
temp.s.opcode2 = 0x54;
return temp.assembled;
} }
}; };
uint8_t detour_arm64_disasm::pure_copy32(uint8_t* source, uint8_t* dest) union detour_arm64_disasm_branch26
{
uint32_t assembled;
struct
{
uint32_t imm26 : 26; // 26-bit immediate
uint32_t opcode1 : 5; // Must be 00101 == 0x5
uint32_t link : 1; // 0 = B, 1 = BL
} s;
inline int32_t imm() const { return (int32_t)(s.imm26 << 6) >> 4; }
static uint32_t assemble(uint32_t link, int32_t delta)
{
detour_arm64_disasm_branch26 temp;
temp.s.imm26 = delta >> 2;
temp.s.opcode1 = 0x5;
temp.s.link = link;
return temp.assembled;
}
static uint32_t assemble_b(int32_t delta) { return assemble(0, delta); }
static uint32_t assemble_bl(int32_t delta) { return assemble(1, delta); }
};
union detour_arm64_disasm_br
{
uint32_t assembled;
struct
{
uint32_t opcode1 : 5; // Must be 00000 == 0
uint32_t rn : 5; // Register number
uint32_t opcode2 : 22; // Must be 1101011000011111000000 == 0x3587c0 for Br
// 0x358fc0 for Brl
} s;
static uint32_t assemble(uint32_t rn, bool link)
{
detour_arm64_disasm_br temp;
temp.s.opcode1 = 0;
temp.s.rn = rn;
temp.s.opcode2 = 0x3587c0;
if (link)
temp.assembled |= 0x00200000;
return temp.assembled;
}
static uint32_t assemble_br(uint32_t rn)
{
return assemble(rn, false);
}
static uint32_t assemble_brl(uint32_t rn)
{
return assemble(rn, true);
}
};
union detour_arm64_disasm_cbz19
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Register to test
uint32_t imm19 : 19; // 19-bit immediate
uint32_t nz : 1; // 0 = CBZ, 1 = CBNZ
uint32_t opcode1 : 6; // Must be 011010 == 0x1a
uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
} s;
inline int32_t imm() const { return (int32_t)(s.imm19 << 13) >> 11; }
static uint32_t assemble(uint32_t size, uint32_t nz, uint32_t rt, int32_t delta)
{
detour_arm64_disasm_cbz19 temp;
temp.s.rt = rt;
temp.s.imm19 = delta >> 2;
temp.s.nz = nz;
temp.s.opcode1 = 0x1a;
temp.s.size = size;
return temp.assembled;
}
};
union detour_arm64_disasm_ldr_lit19
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Destination register
uint32_t imm19 : 19; // 19-bit immediate
uint32_t opcode1 : 2; // Must be 0
uint32_t fp_neon : 1; // 0 = LDR Wt/LDR Xt/LDRSW/PRFM, 1 = LDR St/LDR Dt/LDR Qt
uint32_t opcode2 : 3; // Must be 011 = 3
uint32_t size : 2; // 00 = LDR Wt/LDR St, 01 = LDR Xt/LDR Dt, 10 = LDRSW/LDR Qt, 11 = PRFM/invalid
} s;
inline int32_t imm() const { return (int32_t)(s.imm19 << 13) >> 11; }
static uint32_t assemble(uint32_t size, uint32_t fpneon, uint32_t rt, int32_t delta)
{
detour_arm64_disasm_ldr_lit19 temp;
temp.s.rt = rt;
temp.s.imm19 = delta >> 2;
temp.s.opcode1 = 0;
temp.s.fp_neon = fpneon;
temp.s.opcode2 = 3;
temp.s.size = size;
return temp.assembled;
}
};
union detour_arm64_disasm_ldr_fp_neon_imm9
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Destination register
uint32_t rn : 5; // Base register
uint32_t imm12 : 12; // 12-bit immediate
uint32_t opcode1 : 1; // Must be 1 == 1
uint32_t opc : 1; // Part of size
uint32_t opcode2 : 6; // Must be 111101 == 0x3d
uint32_t size : 2; // Size (0=8-bit, 1=16-bit, 2=32-bit, 3=64-bit, 4=128-bit)
} s;
static uint32_t assemble(uint32_t size, uint32_t rt, uint32_t rn, uint32_t imm)
{
detour_arm64_disasm_ldr_fp_neon_imm9 temp;
temp.s.rt = rt;
temp.s.rn = rn;
temp.s.imm12 = imm;
temp.s.opcode1 = 1;
temp.s.opc = size >> 2;
temp.s.opcode2 = 0x3d;
temp.s.size = size & 3;
return temp.assembled;
}
};
union detour_arm64_disasm_mov16
{
uint32_t assembled;
struct
{
uint32_t rd : 5; // Destination register
uint32_t imm16 : 16; // Immediate
uint32_t shift : 2; // Shift amount (0=0, 1=16, 2=32, 3=48)
uint32_t opcode : 6; // Must be 100101 == 0x25
uint32_t type : 2; // 0 = MOVN, 1 = reserved, 2 = MOVZ, 3 = MOVK
uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
} s;
static uint32_t assemble(uint32_t size, uint32_t type, uint32_t rd, uint32_t imm, uint32_t shift)
{
detour_arm64_disasm_mov16 temp;
temp.s.rd = rd;
temp.s.imm16 = imm;
temp.s.shift = shift;
temp.s.opcode = 0x25;
temp.s.type = type;
temp.s.size = size;
return temp.assembled;
}
static uint32_t assemble_movn32(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(0, 0, rd, imm, shift); }
static uint32_t assemble_movn64(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(1, 0, rd, imm, shift); }
static uint32_t assemble_movz32(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(0, 2, rd, imm, shift); }
static uint32_t assemble_movz64(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(1, 2, rd, imm, shift); }
static uint32_t assemble_movk32(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(0, 3, rd, imm, shift); }
static uint32_t assemble_movk64(uint32_t rd, uint32_t imm, uint32_t shift) { return assemble(1, 3, rd, imm, shift); }
};
union detour_arm64_disasm_tbz14
{
uint32_t assembled;
struct
{
uint32_t rt : 5; // Register to test
uint32_t imm14 : 14; // 14-bit immediate
uint32_t bit : 5; // 5-bit index
uint32_t nz : 1; // 0 = TBZ, 1 = TBNZ
uint32_t opcode1 : 6; // Must be 011011 == 0x1b
uint32_t size : 1; // 0 = 32-bit, 1 = 64-bit
} s;
inline int32_t imm() const { return (int32_t)(s.imm14 << 18) >> 16; }
static uint32_t assemble(uint32_t size, uint32_t nz, uint32_t rt, uint32_t bit, int32_t delta)
{
detour_arm64_disasm_tbz14 temp;
temp.s.rt = rt;
temp.s.imm14 = delta >> 2;
temp.s.bit = bit;
temp.s.nz = nz;
temp.s.opcode1 = 0x1b;
temp.s.size = size;
return temp.assembled;
}
};
static uint32_t get_instruction(uint8_t* source)
{
return ((uint32_t*)source)[0];
}
static uint8_t emit_instruction(uint32_t*& dst_inst, uint32_t instruction)
{
*dst_inst++ = instruction;
return sizeof(uint32_t);
};
uint8_t pure_copy32(uint8_t* source, uint8_t* dest)
{ {
*(uint32_t *)dest = *(uint32_t*)source; *(uint32_t *)dest = *(uint32_t*)source;
return sizeof(uint32_t); return sizeof(uint32_t);
@ -329,7 +317,7 @@ uint8_t detour_arm64_disasm::pure_copy32(uint8_t* source, uint8_t* dest)
/////////////////////////////////////////////////////////// Disassembler Code. /////////////////////////////////////////////////////////// Disassembler Code.
// //
uint8_t detour_arm64_disasm::emit_mov_immediate(uint32_t*& dst_inst, uint8_t rd, uint64_t immediate) uint8_t emit_mov_immediate(uint32_t*& dst_inst, uint8_t rd, uint64_t immediate)
{ {
uint32_t piece[4]; uint32_t piece[4];
piece[3] = (uint32_t)((immediate >> 48) & 0xffff); piece[3] = (uint32_t)((immediate >> 48) & 0xffff);
@ -341,7 +329,7 @@ uint8_t detour_arm64_disasm::emit_mov_immediate(uint32_t*& dst_inst, uint8_t rd,
// special case: MOVN with 32-bit dest // special case: MOVN with 32-bit dest
if (piece[3] == 0 && piece[2] == 0 && piece[1] == 0xffff) if (piece[3] == 0 && piece[2] == 0 && piece[1] == 0xffff)
{ {
emit_instruction(dst_inst, mov16::assemble_movn32(rd, piece[0] ^ 0xffff, 0)); emit_instruction(dst_inst, detour_arm64_disasm_mov16::assemble_movn32(rd, piece[0] ^ 0xffff, 0));
count++; count++;
} }
@ -362,17 +350,17 @@ uint8_t detour_arm64_disasm::emit_mov_immediate(uint32_t*& dst_inst, uint8_t rd,
{ {
if (default_piece == 0xffff) if (default_piece == 0xffff)
{ {
emit_instruction(dst_inst, mov16::assemble_movn64(rd, cur_piece ^ 0xffff, piece_num)); emit_instruction(dst_inst, detour_arm64_disasm_mov16::assemble_movn64(rd, cur_piece ^ 0xffff, piece_num));
} }
else else
{ {
emit_instruction(dst_inst, mov16::assemble_movz64(rd, cur_piece, piece_num)); emit_instruction(dst_inst, detour_arm64_disasm_mov16::assemble_movz64(rd, cur_piece, piece_num));
} }
first = false; first = false;
} }
else else
{ {
emit_instruction(dst_inst, mov16::assemble_movk64(rd, cur_piece, piece_num)); emit_instruction(dst_inst, detour_arm64_disasm_mov16::assemble_movk64(rd, cur_piece, piece_num));
} }
} }
} }
@ -380,9 +368,9 @@ uint8_t detour_arm64_disasm::emit_mov_immediate(uint32_t*& dst_inst, uint8_t rd,
return (uint8_t)(count * sizeof(uint32_t)); return (uint8_t)(count * sizeof(uint32_t));
} }
uint8_t detour_arm64_disasm::copy_adr(uint8_t* source, uint8_t* dest, uint32_t instruction) uint8_t copy_adr(uint8_t* source, uint8_t* dest, uint32_t instruction)
{ {
adr19& decoded = (adr19&)(instruction); detour_arm64_disasm_adr19& decoded = (detour_arm64_disasm_adr19&)(instruction);
uint32_t* dst_inst = (uint32_t*)(dest); uint32_t* dst_inst = (uint32_t*)(dest);
// ADR case // ADR case
@ -395,14 +383,14 @@ uint8_t detour_arm64_disasm::copy_adr(uint8_t* source, uint8_t* dest, uint32_t i
// output as ADR // output as ADR
if (delta >= -(1 << 20) && delta < (1 << 20)) if (delta >= -(1 << 20) && delta < (1 << 20))
{ {
emit_instruction(dst_inst, adr19::assemble_adr(decoded.s.rd, (int32_t)delta)); emit_instruction(dst_inst, detour_arm64_disasm_adr19::assemble_adr(decoded.s.rd, (int32_t)delta));
} }
// output as ADRP; ADD // output as ADRP; ADD
else if (delta_page >= -(1 << 20) && (delta_page < (1 << 20))) else if (delta_page >= -(1 << 20) && (delta_page < (1 << 20)))
{ {
emit_instruction(dst_inst, adr19::assemble_adrp(decoded.s.rd, (int32_t)delta_page)); emit_instruction(dst_inst, detour_arm64_disasm_adr19::assemble_adrp(decoded.s.rd, (int32_t)delta_page));
emit_instruction(dst_inst, add_imm12::assemble_add_32(decoded.s.rd, decoded.s.rd, ((std::ptrdiff_t)target) & 0xfff, 0)); emit_instruction(dst_inst, detour_arm64_disasm_add_imm12::assemble_add_32(decoded.s.rd, decoded.s.rd, ((std::ptrdiff_t)target) & 0xfff, 0));
} }
// output as immediate move // output as immediate move
@ -421,7 +409,7 @@ uint8_t detour_arm64_disasm::copy_adr(uint8_t* source, uint8_t* dest, uint32_t i
// output as ADRP // output as ADRP
if (delta_page >= -(1 << 20) && (delta_page < (1 << 20))) if (delta_page >= -(1 << 20) && (delta_page < (1 << 20)))
{ {
emit_instruction(dst_inst, adr19::assemble_adrp(decoded.s.rd, (int32_t)delta_page)); emit_instruction(dst_inst, detour_arm64_disasm_adr19::assemble_adrp(decoded.s.rd, (int32_t)delta_page));
} }
// output as immediate move // output as immediate move
@ -434,9 +422,9 @@ uint8_t detour_arm64_disasm::copy_adr(uint8_t* source, uint8_t* dest, uint32_t i
return (uint8_t)((uint8_t*)dst_inst - dest); return (uint8_t)((uint8_t*)dst_inst - dest);
} }
uint8_t detour_arm64_disasm::copy_bcc(uint8_t* source, uint8_t* dest, uint32_t instruction) uint8_t copy_bcc(uint8_t* source, uint8_t* dest, uint32_t instruction)
{ {
bcc19& decoded = (bcc19&)(instruction); detour_arm64_disasm_bcc19& decoded = (detour_arm64_disasm_bcc19&)(instruction);
uint32_t* dst_inst = (uint32_t*)(dest); uint32_t* dst_inst = (uint32_t*)(dest);
uint8_t* target = source + decoded.imm(); uint8_t* target = source + decoded.imm();
@ -446,30 +434,30 @@ uint8_t detour_arm64_disasm::copy_bcc(uint8_t* source, uint8_t* dest, uint32_t i
// output as BCC // output as BCC
if (delta >= -(1 << 20) && delta < (1 << 20)) if (delta >= -(1 << 20) && delta < (1 << 20))
{ {
emit_instruction(dst_inst, bcc19::assemble_bcc(decoded.s.condition, (int32_t)delta)); emit_instruction(dst_inst, detour_arm64_disasm_bcc19::assemble_bcc(decoded.s.condition, (int32_t)delta));
} }
// output as BCC <skip>; B // output as BCC <skip>; B
else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27))) else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27)))
{ {
emit_instruction(dst_inst, bcc19::assemble_bcc(decoded.s.condition ^ 1, 8)); emit_instruction(dst_inst, detour_arm64_disasm_bcc19::assemble_bcc(decoded.s.condition ^ 1, 8));
emit_instruction(dst_inst, branch26::assemble_b((int32_t)delta4)); emit_instruction(dst_inst, detour_arm64_disasm_branch26::assemble_b((int32_t)delta4));
} }
// output as MOV x17, Target; BCC <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!) // output as MOV x17, Target; BCC <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!)
else else
{ {
emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target); emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target);
emit_instruction(dst_inst, bcc19::assemble_bcc(decoded.s.condition ^ 1, 8)); emit_instruction(dst_inst, detour_arm64_disasm_bcc19::assemble_bcc(decoded.s.condition ^ 1, 8));
emit_instruction(dst_inst, br::assemble_br(17)); emit_instruction(dst_inst, detour_arm64_disasm_br::assemble_br(17));
} }
return (uint8_t)((uint8_t*)dst_inst - dest); return (uint8_t)((uint8_t*)dst_inst - dest);
} }
uint8_t detour_arm64_disasm::copy_b_or_bl(uint8_t* source, uint8_t* dest, uint32_t instruction, bool link) uint8_t copy_b_or_bl(uint8_t* source, uint8_t* dest, uint32_t instruction, bool link)
{ {
branch26& decoded = (branch26&)(instruction); detour_arm64_disasm_branch26& decoded = (detour_arm64_disasm_branch26&)(instruction);
uint32_t* dst_inst = (uint32_t*)(dest); uint32_t* dst_inst = (uint32_t*)(dest);
uint8_t* target = source + decoded.imm(); uint8_t* target = source + decoded.imm();
@ -478,22 +466,22 @@ uint8_t detour_arm64_disasm::copy_b_or_bl(uint8_t* source, uint8_t* dest, uint32
// output as B or BRL // output as B or BRL
if (delta >= -(1 << 27) && (delta < (1 << 27))) if (delta >= -(1 << 27) && (delta < (1 << 27)))
{ {
emit_instruction(dst_inst, branch26::assemble(link, (int32_t)delta)); emit_instruction(dst_inst, detour_arm64_disasm_branch26::assemble(link, (int32_t)delta));
} }
// output as MOV x17, Target; BR or BRL x17 (BIG assumption that x17 isn't being used for anything!!) // output as MOV x17, Target; BR or BRL x17 (BIG assumption that x17 isn't being used for anything!!)
else else
{ {
emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target); emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target);
emit_instruction(dst_inst, br::assemble(17, link)); emit_instruction(dst_inst, detour_arm64_disasm_br::assemble(17, link));
} }
return (uint8_t)((uint8_t*)dst_inst - dest); return (uint8_t)((uint8_t*)dst_inst - dest);
} }
uint8_t detour_arm64_disasm::copy_cbz(uint8_t* source, uint8_t* dest, uint32_t instruction) uint8_t copy_cbz(uint8_t* source, uint8_t* dest, uint32_t instruction)
{ {
cbz19& decoded = (cbz19&)(instruction); detour_arm64_disasm_cbz19& decoded = (detour_arm64_disasm_cbz19&)(instruction);
uint32_t* dst_inst = (uint32_t*)(dest); uint32_t* dst_inst = (uint32_t*)(dest);
uint8_t* target = source + decoded.imm(); uint8_t* target = source + decoded.imm();
@ -503,30 +491,30 @@ uint8_t detour_arm64_disasm::copy_cbz(uint8_t* source, uint8_t* dest, uint32_t i
// output as CBZ/NZ // output as CBZ/NZ
if (delta >= -(1 << 20) && delta < (1 << 20)) if (delta >= -(1 << 20) && delta < (1 << 20))
{ {
emit_instruction(dst_inst, cbz19::assemble(decoded.s.size, decoded.s.nz, decoded.s.rt, (int32_t)delta)); emit_instruction(dst_inst, detour_arm64_disasm_cbz19::assemble(decoded.s.size, decoded.s.nz, decoded.s.rt, (int32_t)delta));
} }
// output as CBNZ/Z <skip>; B // output as CBNZ/Z <skip>; B
else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27))) else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27)))
{ {
emit_instruction(dst_inst, cbz19::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, 8)); emit_instruction(dst_inst, detour_arm64_disasm_cbz19::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, 8));
emit_instruction(dst_inst, branch26::assemble_b((int32_t)delta4)); emit_instruction(dst_inst, detour_arm64_disasm_branch26::assemble_b((int32_t)delta4));
} }
// output as MOV x17, Target; CBNZ/Z <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!) // output as MOV x17, Target; CBNZ/Z <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!)
else else
{ {
emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target); emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target);
emit_instruction(dst_inst, cbz19::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, 8)); emit_instruction(dst_inst, detour_arm64_disasm_cbz19::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, 8));
emit_instruction(dst_inst, br::assemble_br(17)); emit_instruction(dst_inst, detour_arm64_disasm_br::assemble_br(17));
} }
return (uint8_t)((uint8_t*)dst_inst - dest); return (uint8_t)((uint8_t*)dst_inst - dest);
} }
uint8_t detour_arm64_disasm::copy_tbz(uint8_t* source, uint8_t* dest, uint32_t instruction) uint8_t copy_tbz(uint8_t* source, uint8_t* dest, uint32_t instruction)
{ {
tbz14& decoded = (tbz14&)(instruction); detour_arm64_disasm_tbz14& decoded = (detour_arm64_disasm_tbz14&)(instruction);
uint32_t* dst_inst = (uint32_t*)(dest); uint32_t* dst_inst = (uint32_t*)(dest);
uint8_t* target = source + decoded.imm(); uint8_t* target = source + decoded.imm();
@ -536,30 +524,30 @@ uint8_t detour_arm64_disasm::copy_tbz(uint8_t* source, uint8_t* dest, uint32_t i
// output as TBZ/NZ // output as TBZ/NZ
if (delta >= -(1 << 13) && delta < (1 << 13)) if (delta >= -(1 << 13) && delta < (1 << 13))
{ {
emit_instruction(dst_inst, tbz14::assemble(decoded.s.size, decoded.s.nz, decoded.s.rt, decoded.s.bit, (int32_t)delta)); emit_instruction(dst_inst, detour_arm64_disasm_tbz14::assemble(decoded.s.size, decoded.s.nz, decoded.s.rt, decoded.s.bit, (int32_t)delta));
} }
// output as TBNZ/Z <skip>; B // output as TBNZ/Z <skip>; B
else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27))) else if (delta4 >= -(1 << 27) && (delta4 < (1 << 27)))
{ {
emit_instruction(dst_inst, tbz14::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, decoded.s.bit, 8)); emit_instruction(dst_inst, detour_arm64_disasm_tbz14::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, decoded.s.bit, 8));
emit_instruction(dst_inst, branch26::assemble_b((int32_t)delta4)); emit_instruction(dst_inst, detour_arm64_disasm_branch26::assemble_b((int32_t)delta4));
} }
// output as MOV x17, Target; TBNZ/Z <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!) // output as MOV x17, Target; TBNZ/Z <skip>; BR x17 (BIG assumption that x17 isn't being used for anything!!)
else else
{ {
emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target); emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target);
emit_instruction(dst_inst, tbz14::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, decoded.s.bit, 8)); emit_instruction(dst_inst, detour_arm64_disasm_tbz14::assemble(decoded.s.size, decoded.s.nz ^ 1, decoded.s.rt, decoded.s.bit, 8));
emit_instruction(dst_inst, br::assemble_br(17)); emit_instruction(dst_inst, detour_arm64_disasm_br::assemble_br(17));
} }
return (uint8_t)((uint8_t*)dst_inst - dest); return (uint8_t)((uint8_t*)dst_inst - dest);
} }
uint8_t detour_arm64_disasm::copy_ldr_literal(uint8_t* source, uint8_t* dest, uint32_t instruction) uint8_t copy_ldr_literal(uint8_t* source, uint8_t* dest, uint32_t instruction)
{ {
ldr_lit19& decoded = (ldr_lit19&)(instruction); detour_arm64_disasm_ldr_lit19& decoded = (detour_arm64_disasm_ldr_lit19&)(instruction);
uint32_t* dst_inst = (uint32_t*)(dest); uint32_t* dst_inst = (uint32_t*)(dest);
uint8_t* target = source + decoded.imm(); uint8_t* target = source + decoded.imm();
@ -568,7 +556,7 @@ uint8_t detour_arm64_disasm::copy_ldr_literal(uint8_t* source, uint8_t* dest, ui
// output as LDR // output as LDR
if (delta >= -(1 << 21) && delta < (1 << 21)) if (delta >= -(1 << 21) && delta < (1 << 21))
{ {
emit_instruction(dst_inst, ldr_lit19::assemble(decoded.s.size, decoded.s.fp_neon, decoded.s.rt, (int32_t)delta)); emit_instruction(dst_inst, detour_arm64_disasm_ldr_lit19::assemble(decoded.s.size, decoded.s.fp_neon, decoded.s.rt, (int32_t)delta));
} }
// output as move immediate // output as move immediate
@ -588,7 +576,7 @@ uint8_t detour_arm64_disasm::copy_ldr_literal(uint8_t* source, uint8_t* dest, ui
else else
{ {
emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target); emit_mov_immediate(dst_inst, 17, (std::ptrdiff_t)target);
emit_instruction(dst_inst, ldr_fp_neon_imm9::assemble(2 + decoded.s.size, decoded.s.rt, 17, 0)); emit_instruction(dst_inst, detour_arm64_disasm_ldr_fp_neon_imm9::assemble(2 + decoded.s.size, decoded.s.rt, 17, 0));
} }
return (uint8_t)((uint8_t*)dst_inst - dest); return (uint8_t)((uint8_t*)dst_inst - dest);
@ -596,8 +584,6 @@ uint8_t detour_arm64_disasm::copy_ldr_literal(uint8_t* source, uint8_t* dest, ui
uint8_t* internal_detour_copy_instruction(uint8_t* dst, uint8_t* src, uint32_t* out_extra_len) uint8_t* internal_detour_copy_instruction(uint8_t* dst, uint8_t* src, uint32_t* out_extra_len)
{ {
using namespace detour_arm64_disasm;
const uint32_t instruction = get_instruction(src); const uint32_t instruction = get_instruction(src);
uint32_t copied_size; uint32_t copied_size;