mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[JIT] Fix more missing endian conversions (opcodes for AArch64, ARM, and Mips stub functions, and ARM target in general)
Summary: Fixed all of the missing endian conversions that Lang Hames and I identified in RuntimeDyldMachOARM.h. Fixed the opcode emission in RuntimeDyldImpl::createStubFunction() for AArch64, ARM, Mips when the host endian doesn't match the target endian. PowerPC will need changing if it's opcodes are affected by endianness but I've left this for now since I'm unsure if this is the case and it's the only path that specifies the target endian. This patch fixes MachO_ARM_PIC_relocations.s on a big-endian Mips host. This is the last of the known issues on this host. Reviewers: lhames Reviewed By: lhames Subscribers: aemerson, llvm-commits Differential Revision: http://reviews.llvm.org/D6130 llvm-svn: 221446
This commit is contained in:
parent
6037d6c977
commit
792e6a1461
@ -585,28 +585,20 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
|
||||
// This stub has to be able to access the full address space,
|
||||
// since symbol lookup won't necessarily find a handy, in-range,
|
||||
// PLT stub for functions which could be anywhere.
|
||||
uint32_t *StubAddr = (uint32_t *)Addr;
|
||||
|
||||
// Stub can use ip0 (== x16) to calculate address
|
||||
*StubAddr = 0xd2e00010; // movz ip0, #:abs_g3:<addr>
|
||||
StubAddr++;
|
||||
*StubAddr = 0xf2c00010; // movk ip0, #:abs_g2_nc:<addr>
|
||||
StubAddr++;
|
||||
*StubAddr = 0xf2a00010; // movk ip0, #:abs_g1_nc:<addr>
|
||||
StubAddr++;
|
||||
*StubAddr = 0xf2800010; // movk ip0, #:abs_g0_nc:<addr>
|
||||
StubAddr++;
|
||||
*StubAddr = 0xd61f0200; // br ip0
|
||||
writeBytesUnaligned(0xd2e00010, Addr, 4); // movz ip0, #:abs_g3:<addr>
|
||||
writeBytesUnaligned(0xf2c00010, Addr+4, 4); // movk ip0, #:abs_g2_nc:<addr>
|
||||
writeBytesUnaligned(0xf2a00010, Addr+8, 4); // movk ip0, #:abs_g1_nc:<addr>
|
||||
writeBytesUnaligned(0xf2800010, Addr+12, 4); // movk ip0, #:abs_g0_nc:<addr>
|
||||
writeBytesUnaligned(0xd61f0200, Addr+16, 4); // br ip0
|
||||
|
||||
return Addr;
|
||||
} else if (Arch == Triple::arm || Arch == Triple::armeb) {
|
||||
// TODO: There is only ARM far stub now. We should add the Thumb stub,
|
||||
// and stubs for branches Thumb - ARM and ARM - Thumb.
|
||||
uint32_t *StubAddr = (uint32_t *)Addr;
|
||||
*StubAddr = 0xe51ff004; // ldr pc,<label>
|
||||
return (uint8_t *)++StubAddr;
|
||||
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,<label>
|
||||
return Addr + 4;
|
||||
} else if (Arch == Triple::mipsel || Arch == Triple::mips) {
|
||||
uint32_t *StubAddr = (uint32_t *)Addr;
|
||||
// 0: 3c190000 lui t9,%hi(addr).
|
||||
// 4: 27390000 addiu t9,t9,%lo(addr).
|
||||
// 8: 03200008 jr t9.
|
||||
@ -614,13 +606,10 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
|
||||
const unsigned LuiT9Instr = 0x3c190000, AdduiT9Instr = 0x27390000;
|
||||
const unsigned JrT9Instr = 0x03200008, NopInstr = 0x0;
|
||||
|
||||
*StubAddr = LuiT9Instr;
|
||||
StubAddr++;
|
||||
*StubAddr = AdduiT9Instr;
|
||||
StubAddr++;
|
||||
*StubAddr = JrT9Instr;
|
||||
StubAddr++;
|
||||
*StubAddr = NopInstr;
|
||||
writeBytesUnaligned(LuiT9Instr, Addr, 4);
|
||||
writeBytesUnaligned(AdduiT9Instr, Addr+4, 4);
|
||||
writeBytesUnaligned(JrT9Instr, Addr+8, 4);
|
||||
writeBytesUnaligned(NopInstr, Addr+12, 4);
|
||||
return Addr;
|
||||
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
|
||||
// Depending on which version of the ELF ABI is in use, we need to
|
||||
|
@ -39,8 +39,7 @@ public:
|
||||
default:
|
||||
return memcpyAddend(RE);
|
||||
case MachO::ARM_RELOC_BR24: {
|
||||
uint32_t Temp;
|
||||
memcpy(&Temp, LocalAddress, 4);
|
||||
uint32_t Temp = readBytesUnaligned(LocalAddress, 4);
|
||||
Temp &= 0x00ffffff; // Mask out the opcode.
|
||||
// Now we've got the shifted immediate, shift by 2, sign extend and ret.
|
||||
return SignExtend32<26>(Temp << 2);
|
||||
@ -112,7 +111,6 @@ public:
|
||||
case MachO::ARM_RELOC_BR24: {
|
||||
// Mask the value into the target address. We know instructions are
|
||||
// 32-bit aligned, so we can do it all at once.
|
||||
uint32_t *p = (uint32_t *)LocalAddress;
|
||||
Value += RE.Addend;
|
||||
// The low two bits of the value are not encoded.
|
||||
Value >>= 2;
|
||||
@ -123,7 +121,9 @@ public:
|
||||
// instruction instead.
|
||||
|
||||
// Insert the value into the instruction.
|
||||
*p = (*p & ~0xffffff) | FinalValue;
|
||||
uint32_t Temp = readBytesUnaligned(LocalAddress, 4);
|
||||
writeBytesUnaligned((Temp & ~0xffffff) | FinalValue, LocalAddress, 4);
|
||||
|
||||
break;
|
||||
}
|
||||
case MachO::ARM_RELOC_HALF_SECTDIFF: {
|
||||
@ -136,10 +136,9 @@ public:
|
||||
Value = (Value >> 16);
|
||||
Value &= 0xffff;
|
||||
|
||||
uint32_t Insn;
|
||||
memcpy(&Insn, LocalAddress, 4);
|
||||
uint32_t Insn = readBytesUnaligned(LocalAddress, 4);
|
||||
Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff);
|
||||
memcpy(LocalAddress, &Insn, 4);
|
||||
writeBytesUnaligned(Insn, LocalAddress, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -222,8 +221,7 @@ private:
|
||||
uint64_t Offset;
|
||||
RelI->getOffset(Offset);
|
||||
uint8_t *LocalAddress = Section.Address + Offset;
|
||||
int64_t Immediate = 0;
|
||||
memcpy(&Immediate, LocalAddress, 4); // Copy the whole instruction out.
|
||||
int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out.
|
||||
Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff);
|
||||
|
||||
++RelI;
|
||||
|
Loading…
x
Reference in New Issue
Block a user