Skip to content

Commit

Permalink
ArmV8: Preserve SIMD registers
Browse files Browse the repository at this point in the history
  • Loading branch information
kynex7510 committed Jan 1, 2024
1 parent 159e1c1 commit 85e54ea
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 9 deletions.
23 changes: 16 additions & 7 deletions src/assembler/ArmV8Assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@ void ArmV8Assembler::updateLabels() {

using enum ArmV8Register;

static uint32_t val(ArmV8Register reg) { return static_cast<uint32_t>(reg); }
static bool is_simd(ArmV8Register reg) { return static_cast<uint32_t>(reg) >= 0x40; }

static uint32_t val(ArmV8Register reg) {
auto x = static_cast<uint32_t>(reg);
if (is_simd(reg))
x -= 0x40;
return x;
}

void ArmV8Assembler::mov(ArmV8Register dst, ArmV8Register src) {
const auto srcShifted = val(src) << 16;
Expand All @@ -34,16 +41,17 @@ void ArmV8Assembler::ldp(ArmV8Register reg1, ArmV8Register reg2, ArmV8Register r
using enum ArmV8IndexKind;

uint32_t opc = 0;
const auto use_simd = is_simd(reg1) && is_simd(reg2);

switch (kind) {
case PreIndex:
opc = 0x2A7 << 22;
opc = (use_simd ? 0x1B7 : 0x2A7) << 22;
break;
case PostIndex:
opc = 0x2A3 << 22;
opc = (use_simd ? 0x1B3 : 0x2A3) << 22;
break;
case SignedOffset:
opc = 0x2A5 << 22;
opc = (use_simd ? 0x1B5 : 0x2A5) << 22;
break;
}

Expand All @@ -58,16 +66,17 @@ void ArmV8Assembler::stp(ArmV8Register reg1, ArmV8Register reg2, ArmV8Register r
using enum ArmV8IndexKind;

uint32_t opc = 0;
const auto use_simd = is_simd(reg1) && is_simd(reg2);

switch (kind) {
case PreIndex:
opc = (0x2A6 << 22);
opc = (use_simd ? 0x1B6 : 0x2A6) << 22;
break;
case PostIndex:
opc = (0x2A2 << 22);
opc = (use_simd ? 0x1B2 : 0x2A2) << 22;
break;
case SignedOffset:
opc = (0x2A4 << 22);
opc = (use_simd ? 0x1B4 : 0x2A4) << 22;
break;
}

Expand Down
32 changes: 32 additions & 0 deletions src/assembler/ArmV8Assembler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,38 @@ namespace tulip::hook {
X30,
SP,
PC,
D0 = 0x40,
D1,
D2,
D3,
D4,
D5,
D6,
D7,
D8,
D9,
D10,
D11,
D12,
D13,
D14,
D15,
D16,
D17,
D18,
D19,
D20,
D21,
D22,
D23,
D24,
D25,
D26,
D27,
D28,
D29,
D30,
D31,
};

enum class ArmV8IndexKind : uint8_t {
Expand Down
9 changes: 7 additions & 2 deletions src/generator/ArmV8Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ std::vector<uint8_t> ArmV8HandlerGenerator::handlerBytes(uint64_t address) {

// preserve registers
a.push({X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15});
// TODO: fp
a.push({D0, D1, D2, D3, D4, D5, D6, D7});
// v8-15 are callee saved.
a.push({D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31});

// set the parameters
a.ldr(X0, "content");
Expand All @@ -64,14 +66,16 @@ std::vector<uint8_t> ArmV8HandlerGenerator::handlerBytes(uint64_t address) {
a.mov(X30, X0);

// recover registers
// TODO: fp
a.pop({D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31});
a.pop({D0, D1, D2, D3, D4, D5, D6, D7});
a.pop({X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15});

// call the func
a.blr(X30);

// preserve the return values
a.push({X0, X1, X2, X3, X4, X5, X6, X7});
a.push({D0, D1, D2, D3, D4, D5, D6, D7});

// call the post handler, decrementing
a.ldr(X0, "handlerPost");
Expand All @@ -81,6 +85,7 @@ std::vector<uint8_t> ArmV8HandlerGenerator::handlerBytes(uint64_t address) {
a.mov(X30, X0);

// recover the return values
a.pop({D0, D1, D2, D3, D4, D5, D6, D7});
a.pop({X0, X1, X2, X3, X4, X5, X6, X7});

// done!
Expand Down

0 comments on commit 85e54ea

Please sign in to comment.