Chromium Code Reviews| 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. |