1 //===-- SystemZMCAsmBackend.cpp - SystemZ assembler backend ---------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/SystemZMCTargetDesc.h" 11 #include "MCTargetDesc/SystemZMCFixups.h" 12 #include "llvm/MC/MCAsmBackend.h" 13 #include "llvm/MC/MCELFObjectWriter.h" 14 #include "llvm/MC/MCFixupKindInfo.h" 15 #include "llvm/MC/MCInst.h" 16 #include "llvm/MC/MCObjectWriter.h" 17 18 using namespace llvm; 19 20 // Value is a fully-resolved relocation value: Symbol + Addend [- Pivot]. 21 // Return the bits that should be installed in a relocation field for 22 // fixup kind Kind. 23 static uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value) { 24 if (Kind < FirstTargetFixupKind) 25 return Value; 26 27 switch (unsigned(Kind)) { 28 case SystemZ::FK_390_PC16DBL: 29 case SystemZ::FK_390_PC32DBL: 30 case SystemZ::FK_390_PLT16DBL: 31 case SystemZ::FK_390_PLT32DBL: 32 return (int64_t)Value / 2; 33 } 34 35 llvm_unreachable("Unknown fixup kind!"); 36 } 37 38 // If Opcode is a relaxable interprocedural reference, return the relaxed form, 39 // otherwise return 0. 40 static unsigned getRelaxedOpcode(unsigned Opcode) { 41 switch (Opcode) { 42 case SystemZ::BRAS: return SystemZ::BRASL; 43 } 44 return 0; 45 } 46 47 namespace { 48 class SystemZMCAsmBackend : public MCAsmBackend { 49 uint8_t OSABI; 50 public: 51 SystemZMCAsmBackend(uint8_t osABI) 52 : OSABI(osABI) {} 53 54 // Override MCAsmBackend 55 virtual unsigned getNumFixupKinds() const LLVM_OVERRIDE { 56 return SystemZ::NumTargetFixupKinds; 57 } 58 virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const 59 LLVM_OVERRIDE; 60 virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 61 uint64_t Value) const LLVM_OVERRIDE; 62 virtual bool mayNeedRelaxation(const MCInst &Inst) const LLVM_OVERRIDE; 63 virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, 64 uint64_t Value, 65 const MCRelaxableFragment *Fragment, 66 const MCAsmLayout &Layout) const 67 LLVM_OVERRIDE; 68 virtual void relaxInstruction(const MCInst &Inst, 69 MCInst &Res) const LLVM_OVERRIDE; 70 virtual bool writeNopData(uint64_t Count, 71 MCObjectWriter *OW) const LLVM_OVERRIDE; 72 virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const 73 LLVM_OVERRIDE { 74 return createSystemZObjectWriter(OS, OSABI); 75 } 76 virtual bool doesSectionRequireSymbols(const MCSection &Section) const 77 LLVM_OVERRIDE { 78 return false; 79 } 80 }; 81 } // end anonymous namespace 82 83 const MCFixupKindInfo & 84 SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { 85 const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = { 86 { "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 87 { "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 88 { "FK_390_PLT16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 89 { "FK_390_PLT32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel } 90 }; 91 92 if (Kind < FirstTargetFixupKind) 93 return MCAsmBackend::getFixupKindInfo(Kind); 94 95 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 96 "Invalid kind!"); 97 return Infos[Kind - FirstTargetFixupKind]; 98 } 99 100 void SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, 101 unsigned DataSize, uint64_t Value) const { 102 MCFixupKind Kind = Fixup.getKind(); 103 unsigned Offset = Fixup.getOffset(); 104 unsigned Size = (getFixupKindInfo(Kind).TargetSize + 7) / 8; 105 106 assert(Offset + Size <= DataSize && "Invalid fixup offset!"); 107 108 // Big-endian insertion of Size bytes. 109 Value = extractBitsForFixup(Kind, Value); 110 unsigned ShiftValue = (Size * 8) - 8; 111 for (unsigned I = 0; I != Size; ++I) { 112 Data[Offset + I] |= uint8_t(Value >> ShiftValue); 113 ShiftValue -= 8; 114 } 115 } 116 117 bool SystemZMCAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { 118 return getRelaxedOpcode(Inst.getOpcode()) != 0; 119 } 120 121 bool 122 SystemZMCAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 123 uint64_t Value, 124 const MCRelaxableFragment *Fragment, 125 const MCAsmLayout &Layout) const { 126 // At the moment we just need to relax 16-bit fields to wider fields. 127 Value = extractBitsForFixup(Fixup.getKind(), Value); 128 return (int16_t)Value != (int64_t)Value; 129 } 130 131 void SystemZMCAsmBackend::relaxInstruction(const MCInst &Inst, 132 MCInst &Res) const { 133 unsigned Opcode = getRelaxedOpcode(Inst.getOpcode()); 134 assert(Opcode && "Unexpected insn to relax"); 135 Res = Inst; 136 Res.setOpcode(Opcode); 137 } 138 139 bool SystemZMCAsmBackend::writeNopData(uint64_t Count, 140 MCObjectWriter *OW) const { 141 for (uint64_t I = 0; I != Count; ++I) 142 OW->Write8(7); 143 return true; 144 } 145 146 MCAsmBackend *llvm::createSystemZMCAsmBackend(const Target &T, StringRef TT, 147 StringRef CPU) { 148 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); 149 return new SystemZMCAsmBackend(OSABI); 150 } 151