Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions src/ffi/platforms/ppc64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,21 @@ extern "C" bool node_ffi_create_fast_trampoline(
}

// Load the target address from the literal pool into r12, then branch through
// CTR. ELFv2 functions can use r12 to establish their TOC on global entry.
Emit32(&cursor, Bl(1)); // bl .+4
Emit32(&cursor, Mfspr(12, 8)); // mflr r12
Emit32(&cursor, Ld(12, 12, 20)); // ld r12, literal-mflr(r12)
Emit32(&cursor, Mtspr(9, 12)); // mtctr r12
Emit32(&cursor, 0x4e800420); // bctr
Emit32(&cursor, 0x60000000); // nop; align literal to 8 bytes
// CTR. Save the caller's link register before using `bl` to obtain the
// trampoline's address, and restore it before the tail branch so the native
// target returns to V8 rather than back into the trampoline. ELFv2 functions
// can use r12 to establish their TOC on global entry.
Emit32(&cursor, Mfspr(0, 8)); // mflr r0
Emit32(&cursor, Bl(1)); // bl .+4
Emit32(&cursor, Mfspr(12, 8)); // mflr r12
Emit32(&cursor, Mtspr(8, 0)); // mtlr r0
const unsigned literal_offset = gp_count % 2 == 0 ? 24 : 20;
Emit32(&cursor, Ld(12, 12, literal_offset));
Emit32(&cursor, Mtspr(9, 12)); // mtctr r12
Emit32(&cursor, 0x4e800420); // bctr
if (gp_count % 2 == 0) {
Emit32(&cursor, 0x60000000); // nop; align literal to 8 bytes
}
Emit64(&cursor, reinterpret_cast<uintptr_t>(target));

const size_t written = reinterpret_cast<uint8_t*>(cursor) -
Expand Down
Loading