diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index 952a45684a9..9335b183dbd 100644 --- a/lib/Target/PowerPC/PPCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -63,7 +63,11 @@ namespace { unsigned get_crbitm_encoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getDirectBrEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getCondBrEncoding(const MachineInstr &MI, unsigned OpNo) const; - + + unsigned getHA16Encoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getLO16Encoding(const MachineInstr &MI, unsigned OpNo) const; + unsigned getLO14Encoding(const MachineInstr &MI, unsigned OpNo) const; + const char *getPassName() const { return "PowerPC Machine Code Emitter"; } /// runOnMachineFunction - emits the given MachineFunction to memory @@ -140,16 +144,27 @@ unsigned PPCCodeEmitter::get_crbitm_encoding(const MachineInstr &MI, MachineRelocation PPCCodeEmitter::GetRelocation(const MachineOperand &MO, unsigned RelocID) const { + // If in PIC mode, we need to encode the negated address of the + // 'movepctolr' into the unrelocated field. After relocation, we'll have + // &gv-&movepctolr-4 in the imm field. Once &movepctolr is added to the imm + // field, we get &gv. This doesn't happen for branch relocations, which are + // always implicitly pc relative. + intptr_t Cst = 0; + if (TM.getRelocationModel() == Reloc::PIC_) { + assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); + Cst = -(intptr_t)MovePCtoLROffset - 4; + } + if (MO.isGlobal()) return MachineRelocation::getGV(MCE.getCurrentPCOffset(), RelocID, - const_cast(MO.getGlobal()),0, - isa(MO.getGlobal())); + const_cast(MO.getGlobal()), + Cst, isa(MO.getGlobal())); if (MO.isSymbol()) return MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), - RelocID, MO.getSymbolName(), 0); + RelocID, MO.getSymbolName(), Cst); if (MO.isCPI()) return MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), - RelocID, MO.getIndex(), 0); + RelocID, MO.getIndex(), Cst); if (MO.isMBB()) MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), @@ -157,7 +172,7 @@ MachineRelocation PPCCodeEmitter::GetRelocation(const MachineOperand &MO, assert(MO.isJTI()); return MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), - RelocID, MO.getIndex(), 0); + RelocID, MO.getIndex(), Cst); } unsigned PPCCodeEmitter::getDirectBrEncoding(const MachineInstr &MI, @@ -176,6 +191,33 @@ unsigned PPCCodeEmitter::getCondBrEncoding(const MachineInstr &MI, return 0; } +unsigned PPCCodeEmitter::getHA16Encoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO); + + MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_high)); + return 0; +} + +unsigned PPCCodeEmitter::getLO16Encoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO); + + MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_low)); + return 0; +} + +unsigned PPCCodeEmitter::getLO14Encoding(const MachineInstr &MI, + unsigned OpNo) const { + const MachineOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO); + + MCE.addRelocation(GetRelocation(MO, PPC::reloc_absolute_low_ix)); + return 0; +} + unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO) const { @@ -194,15 +236,6 @@ unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, "MovePCtoLR not seen yet?"); switch (MI.getOpcode()) { default: MI.dump(); llvm_unreachable("Unknown instruction for relocation!"); - case PPC::LIS: - case PPC::LIS8: - case PPC::ADDIS: - case PPC::ADDIS8: - Reloc = PPC::reloc_absolute_high; // Pointer to symbol - break; - case PPC::LI: - case PPC::LI8: - case PPC::LA: // Loads. case PPC::LBZ: case PPC::LBZ8: @@ -235,18 +268,7 @@ unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, break; } - MachineRelocation R = GetRelocation(MO, Reloc); - - // If in PIC mode, we need to encode the negated address of the - // 'movepctolr' into the unrelocated field. After relocation, we'll have - // &gv-&movepctolr-4 in the imm field. Once &movepctolr is added to the imm - // field, we get &gv. This doesn't happen for branch relocations, which are - // always implicitly pc relative. - if (TM.getRelocationModel() == Reloc::PIC_) { - assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); - R.setConstantVal(-(intptr_t)MovePCtoLROffset - 4); - } - MCE.addRelocation(R); + MCE.addRelocation(GetRelocation(MO, Reloc)); } else { #ifndef NDEBUG errs() << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; diff --git a/lib/Target/PowerPC/PPCFixupKinds.h b/lib/Target/PowerPC/PPCFixupKinds.h index fcf3dbaa6cd..b3c889e3f8d 100644 --- a/lib/Target/PowerPC/PPCFixupKinds.h +++ b/lib/Target/PowerPC/PPCFixupKinds.h @@ -23,6 +23,18 @@ enum Fixups { /// branches. fixup_ppc_brcond14, + /// fixup_ppc_lo16 - A 16-bit fixup corresponding to lo16(_foo) for instrs + /// like 'li'. + fixup_ppc_lo16, + + /// fixup_ppc_ha16 - A 16-bit fixup corresponding to ha16(_foo) for instrs + /// like 'lis'. + fixup_ppc_ha16, + + /// fixup_ppc_lo14 - A 14-bit fixup corresponding to lo16(_foo) for instrs + /// like 'std'. + fixup_ppc_lo14, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index 53db7336564..0b96bcd6357 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -23,9 +23,11 @@ def u16imm64 : Operand { } def symbolHi64 : Operand { let PrintMethod = "printSymbolHi"; + let EncoderMethod = "getHA16Encoding"; } def symbolLo64 : Operand { let PrintMethod = "printSymbolLo"; + let EncoderMethod = "getLO16Encoding"; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 269f371bdaf..11f84d0d84c 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -302,9 +302,11 @@ def aaddr : Operand { def piclabel: Operand {} def symbolHi: Operand { let PrintMethod = "printSymbolHi"; + let EncoderMethod = "getHA16Encoding"; } def symbolLo: Operand { let PrintMethod = "printSymbolLo"; + let EncoderMethod = "getLO16Encoding"; } def crbitm: Operand { let PrintMethod = "printcrbitm"; diff --git a/lib/Target/PowerPC/PPCMCCodeEmitter.cpp b/lib/Target/PowerPC/PPCMCCodeEmitter.cpp index 53183127c27..644f46f21d8 100644 --- a/lib/Target/PowerPC/PPCMCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCMCCodeEmitter.cpp @@ -44,7 +44,10 @@ public: const static MCFixupKindInfo Infos[] = { // name offset bits flags { "fixup_ppc_br24", 6, 24, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel } + { "fixup_ppc_brcond14", 16, 14, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_ppc_lo16", 16, 16, 0 }, + { "fixup_ppc_ha16", 16, 16, 0 }, + { "fixup_ppc_lo14", 16, 14, 0 } }; if (Kind < FirstTargetFixupKind) @@ -57,10 +60,14 @@ public: unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups) const; - unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups) const; - + unsigned getHA16Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const; + unsigned getLO16Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const; + unsigned getLO14Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const; unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups) const; @@ -118,6 +125,39 @@ unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo, return 0; } +unsigned PPCMCCodeEmitter::getHA16Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups); + + // Add a fixup for the branch target. + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_ha16)); + return 0; +} + +unsigned PPCMCCodeEmitter::getLO16Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups); + + // Add a fixup for the branch target. + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_lo16)); + return 0; +} + +unsigned PPCMCCodeEmitter::getLO14Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups); + + // Add a fixup for the branch target. + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), + (MCFixupKind)PPC::fixup_ppc_lo14)); + return 0; +} + unsigned PPCMCCodeEmitter:: get_crbitm_encoding(const MCInst &MI, unsigned OpNo,