1251607Sdim//===-- SystemZMCAsmBackend.cpp - SystemZ assembler backend ---------------===// 2251607Sdim// 3251607Sdim// The LLVM Compiler Infrastructure 4251607Sdim// 5251607Sdim// This file is distributed under the University of Illinois Open Source 6251607Sdim// License. See LICENSE.TXT for details. 7251607Sdim// 8251607Sdim//===----------------------------------------------------------------------===// 9251607Sdim 10251607Sdim#include "MCTargetDesc/SystemZMCTargetDesc.h" 11251607Sdim#include "MCTargetDesc/SystemZMCFixups.h" 12251607Sdim#include "llvm/MC/MCAsmBackend.h" 13251607Sdim#include "llvm/MC/MCELFObjectWriter.h" 14251607Sdim#include "llvm/MC/MCFixupKindInfo.h" 15251607Sdim#include "llvm/MC/MCInst.h" 16251607Sdim#include "llvm/MC/MCObjectWriter.h" 17251607Sdim 18251607Sdimusing namespace llvm; 19251607Sdim 20251607Sdim// Value is a fully-resolved relocation value: Symbol + Addend [- Pivot]. 21251607Sdim// Return the bits that should be installed in a relocation field for 22251607Sdim// fixup kind Kind. 23251607Sdimstatic uint64_t extractBitsForFixup(MCFixupKind Kind, uint64_t Value) { 24251607Sdim if (Kind < FirstTargetFixupKind) 25251607Sdim return Value; 26251607Sdim 27251607Sdim switch (unsigned(Kind)) { 28251607Sdim case SystemZ::FK_390_PC16DBL: 29251607Sdim case SystemZ::FK_390_PC32DBL: 30251607Sdim case SystemZ::FK_390_PLT16DBL: 31251607Sdim case SystemZ::FK_390_PLT32DBL: 32251607Sdim return (int64_t)Value / 2; 33251607Sdim } 34251607Sdim 35251607Sdim llvm_unreachable("Unknown fixup kind!"); 36251607Sdim} 37251607Sdim 38251607Sdimnamespace { 39251607Sdimclass SystemZMCAsmBackend : public MCAsmBackend { 40251607Sdim uint8_t OSABI; 41251607Sdimpublic: 42251607Sdim SystemZMCAsmBackend(uint8_t osABI) 43251607Sdim : OSABI(osABI) {} 44251607Sdim 45251607Sdim // Override MCAsmBackend 46251607Sdim virtual unsigned getNumFixupKinds() const LLVM_OVERRIDE { 47251607Sdim return SystemZ::NumTargetFixupKinds; 48251607Sdim } 49251607Sdim virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const 50251607Sdim LLVM_OVERRIDE; 51251607Sdim virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 52251607Sdim uint64_t Value) const LLVM_OVERRIDE; 53263508Sdim virtual bool mayNeedRelaxation(const MCInst &Inst) const LLVM_OVERRIDE { 54263508Sdim return false; 55263508Sdim } 56251607Sdim virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, 57251607Sdim uint64_t Value, 58251607Sdim const MCRelaxableFragment *Fragment, 59251607Sdim const MCAsmLayout &Layout) const 60263508Sdim LLVM_OVERRIDE { 61263508Sdim return false; 62263508Sdim } 63251607Sdim virtual void relaxInstruction(const MCInst &Inst, 64263508Sdim MCInst &Res) const LLVM_OVERRIDE { 65263508Sdim llvm_unreachable("SystemZ does do not have assembler relaxation"); 66263508Sdim } 67251607Sdim virtual bool writeNopData(uint64_t Count, 68251607Sdim MCObjectWriter *OW) const LLVM_OVERRIDE; 69251607Sdim virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const 70251607Sdim LLVM_OVERRIDE { 71251607Sdim return createSystemZObjectWriter(OS, OSABI); 72251607Sdim } 73251607Sdim virtual bool doesSectionRequireSymbols(const MCSection &Section) const 74251607Sdim LLVM_OVERRIDE { 75251607Sdim return false; 76251607Sdim } 77251607Sdim}; 78251607Sdim} // end anonymous namespace 79251607Sdim 80251607Sdimconst MCFixupKindInfo & 81251607SdimSystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { 82251607Sdim const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = { 83251607Sdim { "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 84251607Sdim { "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, 85251607Sdim { "FK_390_PLT16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 86251607Sdim { "FK_390_PLT32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel } 87251607Sdim }; 88251607Sdim 89251607Sdim if (Kind < FirstTargetFixupKind) 90251607Sdim return MCAsmBackend::getFixupKindInfo(Kind); 91251607Sdim 92251607Sdim assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 93251607Sdim "Invalid kind!"); 94251607Sdim return Infos[Kind - FirstTargetFixupKind]; 95251607Sdim} 96251607Sdim 97251607Sdimvoid SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, 98251607Sdim unsigned DataSize, uint64_t Value) const { 99251607Sdim MCFixupKind Kind = Fixup.getKind(); 100251607Sdim unsigned Offset = Fixup.getOffset(); 101251607Sdim unsigned Size = (getFixupKindInfo(Kind).TargetSize + 7) / 8; 102251607Sdim 103251607Sdim assert(Offset + Size <= DataSize && "Invalid fixup offset!"); 104251607Sdim 105251607Sdim // Big-endian insertion of Size bytes. 106251607Sdim Value = extractBitsForFixup(Kind, Value); 107251607Sdim unsigned ShiftValue = (Size * 8) - 8; 108251607Sdim for (unsigned I = 0; I != Size; ++I) { 109251607Sdim Data[Offset + I] |= uint8_t(Value >> ShiftValue); 110251607Sdim ShiftValue -= 8; 111251607Sdim } 112251607Sdim} 113251607Sdim 114251607Sdimbool SystemZMCAsmBackend::writeNopData(uint64_t Count, 115251607Sdim MCObjectWriter *OW) const { 116251607Sdim for (uint64_t I = 0; I != Count; ++I) 117251607Sdim OW->Write8(7); 118251607Sdim return true; 119251607Sdim} 120251607Sdim 121263508SdimMCAsmBackend *llvm::createSystemZMCAsmBackend(const Target &T, 122263508Sdim const MCRegisterInfo &MRI, 123263508Sdim StringRef TT, StringRef CPU) { 124251607Sdim uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); 125251607Sdim return new SystemZMCAsmBackend(OSABI); 126251607Sdim} 127