aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM/ARMJITInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/ARM/ARMJITInfo.cpp')
-rw-r--r--lib/Target/ARM/ARMJITInfo.cpp27
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: {