diff options
Diffstat (limited to 'lib/Target/ARM/ARMJITInfo.cpp')
-rw-r--r-- | lib/Target/ARM/ARMJITInfo.cpp | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/lib/Target/ARM/ARMJITInfo.cpp b/lib/Target/ARM/ARMJITInfo.cpp index 45b7e48..afbe0e4 100644 --- a/lib/Target/ARM/ARMJITInfo.cpp +++ b/lib/Target/ARM/ARMJITInfo.cpp @@ -17,6 +17,7 @@ #include "ARMConstantPoolValue.h" #include "ARMRelocations.h" #include "ARMSubtarget.h" +#include "MCTargetDesc/ARMAddressingModes.h" #include "llvm/Function.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/Support/Debug.h" @@ -48,7 +49,7 @@ static TargetJITInfo::JITCompilerFn JITCompilerFunction; // write our own wrapper, which does things our way, so we have complete // control over register saving and restoring. extern "C" { -#if defined(__arm__) +#if defined(__arm__) && !defined(ANDROID) void ARMCompilationCallback(); asm( ".text\n" @@ -248,6 +249,7 @@ intptr_t ARMJITInfo::resolveRelocDestAddr(MachineRelocation *MR) const { return getJumpTableBaseAddr(MR->getJumpTableIndex()); case ARM::reloc_arm_cp_entry: case ARM::reloc_arm_vfp_cp_entry: + case ARM::reloc_arm_so_imm_cp_entry: // Constant pool entry address. return getConstantPoolEntryAddr(MR->getConstantPoolIndex()); case ARM::reloc_arm_machine_cp_entry: { @@ -294,6 +296,29 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR, getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift; break; } + case ARM::reloc_arm_so_imm_cp_entry: { + ResultPtr = ResultPtr - (intptr_t)RelocPos - 8; + // If the result is positive, set bit U(23) to 1. + if (ResultPtr >= 0) + *((intptr_t*)RelocPos) |= 1 << ARMII::U_BitShift; + else { + // Otherwise, obtain the absolute value and set bit U(23) to 0. + *((intptr_t*)RelocPos) &= ~(1 << ARMII::U_BitShift); + // FIXME: Also set bit 22 to 1 since 'sub' instruction is going to be used. + *((intptr_t*)RelocPos) |= 1 << 22; + ResultPtr = - ResultPtr; + } + + int SoImmVal = ARM_AM::getSOImmVal(ResultPtr); + assert(SoImmVal != -1 && "Not a valid so_imm value!"); + *((intptr_t*)RelocPos) |= (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1) + << ARMII::SoRotImmShift; + *((intptr_t*)RelocPos) |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); + // Set register Rn to PC. + *((intptr_t*)RelocPos) |= + getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift; + break; + } case ARM::reloc_arm_pic_jt: case ARM::reloc_arm_machine_cp_entry: case ARM::reloc_arm_absolute: { |