From 837caa9313e1f9480721f232f89f5c7b1b9c9d09 Mon Sep 17 00:00:00 2001 From: Jason W Kim Date: Thu, 18 Nov 2010 23:37:15 +0000 Subject: [PATCH] Fix .o emission of ARM movt/movw. MCSymbolRefExpr::VK_ARM_(HI||LO)16 for the .o path now works for ARM. Note: lo16AllZero remains in ARMInstrInfo.td - It can be factored out when Thumb movt is repaired. Existing tests cover this update. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119760 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMCodeEmitter.cpp | 5 +++++ lib/Target/ARM/ARMELFWriterInfo.cpp | 18 +++++++++++++++-- lib/Target/ARM/ARMFixupKinds.h | 6 ++++++ lib/Target/ARM/ARMInstrInfo.td | 13 +++++++++--- lib/Target/ARM/ARMMCCodeEmitter.cpp | 31 +++++++++++++++++++++++++++++ utils/TableGen/EDEmitter.cpp | 1 + 6 files changed, 69 insertions(+), 5 deletions(-) diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 14b0acc037f..8888420d2af 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -214,6 +214,11 @@ namespace { Binary |= (Reg << 13); return Binary; } + + unsigned getMovtImmOpValue(const MachineInstr &MI, unsigned Op) const { + return 0; + } + uint32_t getAddrMode2OpValue(const MachineInstr &MI, unsigned OpIdx) const { return 0;} uint32_t getAddrMode2OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) diff --git a/lib/Target/ARM/ARMELFWriterInfo.cpp b/lib/Target/ARM/ARMELFWriterInfo.cpp index 85b690fd7aa..776727500db 100644 --- a/lib/Target/ARM/ARMELFWriterInfo.cpp +++ b/lib/Target/ARM/ARMELFWriterInfo.cpp @@ -27,13 +27,27 @@ using namespace llvm; ARMELFWriterInfo::ARMELFWriterInfo(TargetMachine &TM) : TargetELFWriterInfo(TM.getTargetData()->getPointerSizeInBits() == 64, TM.getTargetData()->isLittleEndian()) { - // silently OK construction } ARMELFWriterInfo::~ARMELFWriterInfo() {} unsigned ARMELFWriterInfo::getRelocationType(unsigned MachineRelTy) const { - assert(0 && "ARMELFWriterInfo::getRelocationType() not implemented"); + switch (MachineRelTy) { + case ARM::reloc_arm_absolute: + case ARM::reloc_arm_relative: + case ARM::reloc_arm_cp_entry: + case ARM::reloc_arm_vfp_cp_entry: + case ARM::reloc_arm_machine_cp_entry: + case ARM::reloc_arm_jt_base: + case ARM::reloc_arm_pic_jt: + assert(0 && "unsupported ARM relocation type"); break; + + case ARM::reloc_arm_branch: return R_ARM_CALL; break; + case ARM::reloc_arm_movt: return R_ARM_MOVT_ABS; break; + case ARM::reloc_arm_movw: return R_ARM_MOVW_ABS_NC; break; + default: + llvm_unreachable("unknown ARM relocation type"); break; + } return 0; } diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h index 8d26f213e6d..2da0619955c 100644 --- a/lib/Target/ARM/ARMFixupKinds.h +++ b/lib/Target/ARM/ARMFixupKinds.h @@ -25,6 +25,12 @@ enum Fixups { // instructions. fixup_arm_branch, + // The next two are for the movt/movw pair + // the 16bit imm field are split into imm{15-12} and imm{11-0} + // Fixme: We need new ones for Thumb. + fixup_arm_movt_hi16, // :upper16: + fixup_arm_movw_lo16, // :lower16: + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 0ef1e3c653c..fc542ea0601 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -442,6 +442,13 @@ def imm0_31_m1 : Operand, PatLeaf<(imm), [{ let EncoderMethod = "getImmMinusOneOpValue"; } +// For movt/movw - sets the MC Encoder method. +// The imm is split into imm{15-12}, imm{11-0} +// +def movt_imm : Operand { + let EncoderMethod = "getMovtImmOpValue"; +} + // Define ARM specific addressing modes. @@ -1970,7 +1977,7 @@ def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi, } let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in -def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm:$imm), +def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins movt_imm:$imm), DPFrm, IIC_iMOVi, "movw", "\t$Rd, $imm", [(set GPR:$Rd, imm0_65535:$imm)]>, @@ -1985,7 +1992,7 @@ def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm:$imm), } let Constraints = "$src = $Rd" in -def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm:$imm), +def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, movt_imm:$imm), DPFrm, IIC_iMOVi, "movt", "\t$Rd, $imm", [(set GPR:$Rd, @@ -3056,7 +3063,7 @@ def MOVCCs : AI1<0b1101, (outs GPR:$Rd), } let isMoveImm = 1 in -def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm:$imm), +def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, movt_imm:$imm), DPFrm, IIC_iMOVi, "movw", "\t$Rd, $imm", []>, diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index cbb41021ddb..6592dcfebe8 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -70,6 +70,10 @@ public: unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, SmallVectorImpl &Fixups) const; + /// getMovtImmOpValue - Return the encoding for the movw/movt pair + uint32_t getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const; + bool EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg, unsigned &Imm, SmallVectorImpl &Fixups) const; @@ -395,6 +399,33 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, return Binary; } +uint32_t ARMMCCodeEmitter:: +getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const { + // {20-16} = imm{15-12} + // {11-0} = imm{11-0} + const MCOperand &MO = MI.getOperand(OpIdx); + if (MO.isImm()) { + return static_cast(MO.getImm()); + } else if (const MCSymbolRefExpr *Expr = + dyn_cast(MO.getExpr())) { + MCFixupKind Kind; + switch (Expr->getKind()) { + case MCSymbolRefExpr::VK_ARM_HI16: + Kind = MCFixupKind(ARM::fixup_arm_movt_hi16); + break; + case MCSymbolRefExpr::VK_ARM_LO16: + Kind = MCFixupKind(ARM::fixup_arm_movw_lo16); + break; + default: assert(0 && "Unsupported ARMFixup"); break; + } + Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + return 0; + }; + llvm_unreachable(0 && "Unsupported MCExpr type in MCOperand"); + return 0; +} + uint32_t ARMMCCodeEmitter:: getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const { diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index dd09174c207..ab52e8bd267 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -563,6 +563,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, REG("QQQQPR"); IMM("i32imm"); + IMM("movt_imm"); IMM("bf_inv_mask_imm"); IMM("jtblock_operand"); IMM("nohash_imm");