From d77ffa8e2124611cc05d8397a373f7602d16b380 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 13 Apr 2008 11:16:27 -0600 Subject: [PATCH] convert relative calls to absolute indirect calls on x86_64, in case we need to jump further than a 32-bit displacement will allow --- src/compiler.cpp | 62 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 56c7567bc8..ec7514292d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1131,13 +1131,19 @@ argumentFootprint(unsigned count) } void -rex(Context* c) +rex(Context* c, uint8_t mask, Register r) { if (BytesPerWord == 8) { - c->code.append(0x48); + c->code.append(mask | ((r & 8) >> 3)); } } +void +rex(Context* c) +{ + rex(c, 0x48, rax); +} + void encode(Context* c, uint8_t* instruction, unsigned length, int a, Register b, int32_t displacement, int index, unsigned scale) @@ -1203,8 +1209,9 @@ RegisterOperand::apply(Context* c, Operation op) { switch (op) { case call: { + if (value(c) & 8) rex(c, 0x40, value(c)); c->code.append(0xff); - c->code.append(0xd0 | value(c)); + c->code.append(0xd0 | (value(c) & 7)); } break; case jmp: @@ -1410,8 +1417,8 @@ RegisterOperand::accept(Context* c, Operation op, case mov8: { assert(c, BytesPerWord == 8 or op == mov4); // todo - rex(c); - c->code.append(0xb8 | value(c)); + rex(c, 0x48, value(c)); + c->code.append(0xb8 | (value(c) & 7)); c->code.appendAddress(operand->value); } break; @@ -1620,14 +1627,27 @@ AddressOperand::apply(Context* c, Operation op) { switch (op) { case alignedCall: { - while ((c->code.length() + 1) % 4) { - c->code.append(0x90); + if (BytesPerWord == 8) { + while ((c->code.length() + 2) % 8) { + c->code.append(0x90); + } + } else { + while ((c->code.length() + 1) % 4) { + c->code.append(0x90); + } } apply(c, call); } break; case call: { - unconditional(c, 0xe8, this); + if (BytesPerWord == 8) { + RegisterOperand* t = temporary(c, r10); + t->accept(c, mov, this); + t->apply(c, call); + t->release(c); + } else { + unconditional(c, 0xe8, this); + } } break; case jmp: @@ -1650,7 +1670,6 @@ AddressOperand::apply(Context* c, Operation op) conditional(c, 0x8d, this); break; - case jl: conditional(c, 0x8c, this); break; @@ -2836,13 +2855,26 @@ class MyCompiler: public Compiler { } virtual void updateCall(void* returnAddress, void* newTarget) { - uint8_t* instruction = static_cast(returnAddress) - 5; - assert(&c, *instruction == 0xE8); - assert(&c, reinterpret_cast(instruction + 1) % 4 == 0); + if (BytesPerWord == 8) { + uint8_t* instruction = static_cast(returnAddress) - 13; + assert(&c, instruction[0] == 0x49); + assert(&c, instruction[1] == 0xba); + assert(&c, instruction[10] == 0x41); + assert(&c, instruction[11] == 0xff); + assert(&c, instruction[12] == 0xd2); + assert(&c, reinterpret_cast(instruction + 2) % 8 == 0); - int32_t v = static_cast(newTarget) - - static_cast(returnAddress); - memcpy(instruction + 1, &v, 4); + intptr_t v = reinterpret_cast(newTarget); + memcpy(instruction + 2, &v, 8); + } else { + uint8_t* instruction = static_cast(returnAddress) - 5; + assert(&c, *instruction == 0xE8); + assert(&c, reinterpret_cast(instruction + 1) % 4 == 0); + + int32_t v = static_cast(newTarget) + - static_cast(returnAddress); + memcpy(instruction + 1, &v, 4); + } } virtual void dispose() {