Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index 2044050216fcfb223d3093e5e07d897c6af17d3c..3abf0f675fe3f92471006486de50fca723b1aa3e 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -506,6 +506,20 @@ bool canEncodeBranchOffset(IOffsetT Offset) { |
Utils::IsInt(kBranchOffsetBits, Offset >> 2); |
} |
+IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) { |
+ // Adjust offset to the way ARM CPUs read PC. |
+ Offset -= kPCReadOffset; |
+ |
+ bool IsGoodOffset = canEncodeBranchOffset(Offset); |
+ assert(IsGoodOffset); |
+ (void)IsGoodOffset; |
+ |
+ // Properly preserve only the bits supported in the instruction. |
+ Offset >>= 2; |
+ Offset &= kBranchOffsetMask; |
+ return (Inst & ~kBranchOffsetMask) | Offset; |
+} |
+ |
IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet, |
const char *RegName, const char *InstName) { |
IValueT Reg = 0; |
@@ -595,6 +609,18 @@ size_t MoveRelocatableFixup::emit(GlobalContext *Ctx, |
return InstARM32::InstSize; |
} |
+// This fixup points to an ARM32 instruction with the following format: |
+void MoveRelocatableFixup::emitOffset(Assembler *Asm) const { |
+ // cccc00110T00iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, |
+ // iiiiiiiiiiiiiiii = Imm16, and T=1 for movt. |
+ |
+ const IValueT Inst = Asm->load<IValueT>(position()); |
+ constexpr IValueT Imm16Mask = 0x000F0FFF; |
+ const IValueT Imm16 = |
+ offset() >> (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? 0 : 16) & 0xffff; |
+ Asm->store(position(), |
+ (Inst & ~Imm16Mask) | ((Imm16 >> 12) << 16) | (Imm16 & 0xfff)); |
+} |
Karl
2016/02/03 21:03:05
Add blank line?
John
2016/02/03 21:25:20
Done.
|
MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, |
const Constant *Value) { |
MoveRelocatableFixup *F = |
@@ -618,6 +644,15 @@ size_t BlRelocatableFixup::emit(GlobalContext *Ctx, |
return InstARM32::InstSize; |
} |
+void BlRelocatableFixup::emitOffset(Assembler *Asm) const { |
+ // cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and |
+ // iiiiiiiiiiiiiiiiiiiiiiii= |
+ // EncodedBranchOffset(cccc101l000000000000000000000000, Offset); |
+ const IValueT Inst = Asm->load<IValueT>(position()); |
+ constexpr IValueT OffsetMask = 0x00FFFFFF; |
+ Asm->store(position(), encodeBranchOffset(offset(), Inst & ~OffsetMask)); |
+} |
+ |
void AssemblerARM32::padWithNop(intptr_t Padding) { |
constexpr intptr_t InstWidth = sizeof(IValueT); |
assert(Padding % InstWidth == 0 && |
@@ -667,20 +702,6 @@ Label *AssemblerARM32::getOrCreateLabel(SizeT Number, LabelVector &Labels) { |
return L; |
} |
-IValueT AssemblerARM32::encodeBranchOffset(IOffsetT Offset, IValueT Inst) { |
- // Adjust offset to the way ARM CPUs read PC. |
- Offset -= kPCReadOffset; |
- |
- bool IsGoodOffset = canEncodeBranchOffset(Offset); |
- assert(IsGoodOffset); |
- (void)IsGoodOffset; |
- |
- // Properly preserve only the bits supported in the instruction. |
- Offset >>= 2; |
- Offset &= kBranchOffsetMask; |
- return (Inst & ~kBranchOffsetMask) | Offset; |
-} |
- |
// Pull out offset from branch Inst. |
IOffsetT AssemblerARM32::decodeBranchOffset(IValueT Inst) { |
// Sign-extend, left-shift by 2, and adjust to the way ARM CPUs read PC. |