Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index 3dbbb29f0be6fde664abdf2b6b64b253e1f8a8fa..7fce7503e123a4a86c8796b8da71a123a8179dad 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -38,7 +38,9 @@ static constexpr IValueT B4 = 1 << 4; |
static constexpr IValueT B5 = 1 << 5; |
static constexpr IValueT B6 = 1 << 6; |
static constexpr IValueT B21 = 1 << 21; |
+static constexpr IValueT B22 = 1 << 22; |
static constexpr IValueT B24 = 1 << 24; |
+static constexpr IValueT B25 = 1 << 25; |
// Constants used for the decoding or encoding of the individual fields of |
// instructions. Based on ARM section A5.1. |
@@ -222,6 +224,32 @@ bool canEncodeBranchOffset(IOffsetT Offset) { |
namespace Ice { |
namespace ARM32 { |
+size_t MoveRelocatableFixup::emit(GlobalContext *Ctx, |
+ const Assembler &Asm) const { |
+ static constexpr const size_t FixupSize = sizeof(IValueT); |
+ if (!BuildDefs::dump()) |
+ return FixupSize; |
+ Ostream &Str = Ctx->getStrEmit(); |
+ IValueT Inst = Asm.load<IValueT>(position()); |
+ Str << "\tmov" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "w" : "t") << "\t" |
+ << RegARM32::RegNames[(Inst >> kRdShift) & 0xF] |
+ << ", #:" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "lower" : "upper") |
+ << "16:" << symbol(Ctx) << "\t@ .word " |
+ << llvm::format_hex_no_prefix(Inst, 8) << "\n"; |
+ return FixupSize; |
+} |
+ |
+MoveRelocatableFixup *AssemblerARM32::createMoveFixup(bool IsMovW, |
+ const Constant *Value) { |
+ MoveRelocatableFixup *F = |
+ new (allocate<MoveRelocatableFixup>()) MoveRelocatableFixup(); |
+ F->set_kind(IsMovW ? llvm::ELF::R_ARM_MOVW_ABS_NC |
+ : llvm::ELF::R_ARM_MOVT_ABS); |
+ F->set_value(Value); |
+ Buffer.installFixup(F); |
+ return F; |
+} |
+ |
void AssemblerARM32::bindCfgNodeLabel(const CfgNode *Node) { |
GlobalContext *Ctx = Node->getCfg()->getContext(); |
if (BuildDefs::dump() && !Ctx->getFlags().getDisableHybridAssembly()) { |
@@ -517,9 +545,8 @@ void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
// MOV (immediate) - ARM section A8.8.102, encoding A1: |
// mov{S}<c> <Rd>, #<RotatedImm8> |
// |
- // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, |
- // and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this |
- // assembler. |
+ // cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd, and |
+ // iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this assembler. |
constexpr bool SetFlags = false; |
if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags)) |
// Conditions of rule violated. |
@@ -529,6 +556,62 @@ void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, |
emitType01(Cond, kInstTypeDataImmediate, Mov, SetFlags, Rn, Rd, Src); |
} |
+void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, |
+ CondARM32::Cond Cond) { |
+ IValueT Rd; |
+ if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); |
+ if (Src == nullptr) |
Karl
2015/10/29 18:35:06
Added fallback if not relocatable constant.
|
+ return setNeedsTextFixup(); |
+ // MOV (immediate) - ARM section A8.8.102, encoding A2: |
+ // movw<c> <Rd>, #<imm16> |
+ // |
+ // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and |
+ // iiiiiiiiiiiiiiii=imm16. |
+ if (!isConditionDefined(Cond)) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
+ // Use 0 for the lower 16 bits of the relocatable, and add a fixup to |
+ // install the correct bits. |
+ constexpr bool IsMovW = true; |
+ emitFixup(createMoveFixup(IsMovW, Src)); |
+ constexpr IValueT Imm16 = 0; |
+ const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | |
+ B24 | ((Imm16 >> 12) << 16) | Rd << kRdShift | |
+ (Imm16 & 0xfff); |
+ emitInst(Encoding); |
+} |
+ |
+void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, |
+ CondARM32::Cond Cond) { |
+ IValueT Rd; |
+ if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc); |
+ if (Src == nullptr) |
Karl
2015/10/29 18:35:06
Added fallback if not relocatable constant.
|
+ return setNeedsTextFixup(); |
+ // MOVT - ARM section A8.8.102, encoding A2: |
+ // movt<c> <Rd>, #<imm16> |
+ // |
+ // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and |
+ // iiiiiiiiiiiiiiii=imm16. |
+ if (!isConditionDefined(Cond)) |
+ // Conditions of rule violated. |
+ return setNeedsTextFixup(); |
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
+ // Use 0 for the lower 16 bits of the relocatable, and add a fixup to |
+ // install the correct bits. |
+ constexpr bool IsMovW = false; |
+ emitFixup(createMoveFixup(IsMovW, Src)); |
+ constexpr IValueT Imm16 = 0; |
+ const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 | |
+ B24 | B22 | ((Imm16 >> 12) << 16) | Rd << kRdShift | |
+ (Imm16 & 0xfff); |
+ emitInst(Encoding); |
+} |
+ |
void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn, |
const Operand *OpSrc1, bool SetFlags, |
CondARM32::Cond Cond) { |