1262261Sdim//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===// 2262261Sdim// 3262261Sdim// The LLVM Compiler Infrastructure 4262261Sdim// 5262261Sdim// This file is distributed under the University of Illinois Open Source 6262261Sdim// License. See LICENSE.TXT for details. 7262261Sdim// 8262261Sdim//===----------------------------------------------------------------------===// 9262261Sdim 10262261Sdim#include "llvm/MC/MCAsmBackend.h" 11262261Sdim#include "MCTargetDesc/SparcMCTargetDesc.h" 12262261Sdim#include "MCTargetDesc/SparcFixupKinds.h" 13262261Sdim#include "llvm/MC/MCELFObjectWriter.h" 14262261Sdim#include "llvm/MC/MCFixupKindInfo.h" 15262261Sdim#include "llvm/MC/MCObjectWriter.h" 16262261Sdim#include "llvm/Support/TargetRegistry.h" 17262261Sdim 18262261Sdimusing namespace llvm; 19262261Sdim 20262261Sdimstatic unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { 21262261Sdim switch (Kind) { 22262261Sdim default: 23262261Sdim llvm_unreachable("Unknown fixup kind!"); 24262261Sdim case FK_Data_1: 25262261Sdim case FK_Data_2: 26262261Sdim case FK_Data_4: 27262261Sdim case FK_Data_8: 28262261Sdim return Value; 29262261Sdim 30262261Sdim case Sparc::fixup_sparc_wplt30: 31262261Sdim case Sparc::fixup_sparc_call30: 32262261Sdim return (Value >> 2) & 0x3fffffff; 33262261Sdim 34262261Sdim case Sparc::fixup_sparc_br22: 35262261Sdim return (Value >> 2) & 0x3fffff; 36262261Sdim 37262261Sdim case Sparc::fixup_sparc_br19: 38262261Sdim return (Value >> 2) & 0x7ffff; 39262261Sdim 40262261Sdim case Sparc::fixup_sparc_pc22: 41262261Sdim case Sparc::fixup_sparc_got22: 42262261Sdim case Sparc::fixup_sparc_tls_gd_hi22: 43262261Sdim case Sparc::fixup_sparc_tls_ldm_hi22: 44262261Sdim case Sparc::fixup_sparc_tls_ie_hi22: 45262261Sdim case Sparc::fixup_sparc_hi22: 46262261Sdim return (Value >> 10) & 0x3fffff; 47262261Sdim 48262261Sdim case Sparc::fixup_sparc_pc10: 49262261Sdim case Sparc::fixup_sparc_got10: 50262261Sdim case Sparc::fixup_sparc_tls_gd_lo10: 51262261Sdim case Sparc::fixup_sparc_tls_ldm_lo10: 52262261Sdim case Sparc::fixup_sparc_tls_ie_lo10: 53262261Sdim case Sparc::fixup_sparc_lo10: 54262261Sdim return Value & 0x3ff; 55262261Sdim 56262261Sdim case Sparc::fixup_sparc_tls_ldo_hix22: 57262261Sdim case Sparc::fixup_sparc_tls_le_hix22: 58262261Sdim return (~Value >> 10) & 0x3fffff; 59262261Sdim 60262261Sdim case Sparc::fixup_sparc_tls_ldo_lox10: 61262261Sdim case Sparc::fixup_sparc_tls_le_lox10: 62262261Sdim return (~(~Value & 0x3ff)) & 0x1fff; 63262261Sdim 64262261Sdim case Sparc::fixup_sparc_h44: 65262261Sdim return (Value >> 22) & 0x3fffff; 66262261Sdim 67262261Sdim case Sparc::fixup_sparc_m44: 68262261Sdim return (Value >> 12) & 0x3ff; 69262261Sdim 70262261Sdim case Sparc::fixup_sparc_l44: 71262261Sdim return Value & 0xfff; 72262261Sdim 73262261Sdim case Sparc::fixup_sparc_hh: 74262261Sdim return (Value >> 42) & 0x3fffff; 75262261Sdim 76262261Sdim case Sparc::fixup_sparc_hm: 77262261Sdim return (Value >> 32) & 0x3ff; 78262261Sdim 79262261Sdim case Sparc::fixup_sparc_tls_gd_add: 80262261Sdim case Sparc::fixup_sparc_tls_gd_call: 81262261Sdim case Sparc::fixup_sparc_tls_ldm_add: 82262261Sdim case Sparc::fixup_sparc_tls_ldm_call: 83262261Sdim case Sparc::fixup_sparc_tls_ldo_add: 84262261Sdim case Sparc::fixup_sparc_tls_ie_ld: 85262261Sdim case Sparc::fixup_sparc_tls_ie_ldx: 86262261Sdim case Sparc::fixup_sparc_tls_ie_add: 87262261Sdim return 0; 88262261Sdim } 89262261Sdim} 90262261Sdim 91262261Sdimnamespace { 92262261Sdim class SparcAsmBackend : public MCAsmBackend { 93262261Sdim const Target &TheTarget; 94262261Sdim public: 95262261Sdim SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {} 96262261Sdim 97262261Sdim unsigned getNumFixupKinds() const { 98262261Sdim return Sparc::NumTargetFixupKinds; 99262261Sdim } 100262261Sdim 101262261Sdim const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 102262261Sdim const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = { 103262261Sdim // name offset bits flags 104262261Sdim { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, 105262261Sdim { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, 106262261Sdim { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, 107262261Sdim { "fixup_sparc_hi22", 10, 22, 0 }, 108262261Sdim { "fixup_sparc_lo10", 22, 10, 0 }, 109262261Sdim { "fixup_sparc_h44", 10, 22, 0 }, 110262261Sdim { "fixup_sparc_m44", 22, 10, 0 }, 111262261Sdim { "fixup_sparc_l44", 20, 12, 0 }, 112262261Sdim { "fixup_sparc_hh", 10, 22, 0 }, 113262261Sdim { "fixup_sparc_hm", 22, 10, 0 }, 114262261Sdim { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, 115262261Sdim { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, 116262261Sdim { "fixup_sparc_got22", 10, 22, 0 }, 117262261Sdim { "fixup_sparc_got10", 22, 10, 0 }, 118262261Sdim { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, 119262261Sdim { "fixup_sparc_tls_gd_hi22", 10, 22, 0 }, 120262261Sdim { "fixup_sparc_tls_gd_lo10", 22, 10, 0 }, 121262261Sdim { "fixup_sparc_tls_gd_add", 0, 0, 0 }, 122262261Sdim { "fixup_sparc_tls_gd_call", 0, 0, 0 }, 123262261Sdim { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 }, 124262261Sdim { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 }, 125262261Sdim { "fixup_sparc_tls_ldm_add", 0, 0, 0 }, 126262261Sdim { "fixup_sparc_tls_ldm_call", 0, 0, 0 }, 127262261Sdim { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 }, 128262261Sdim { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 }, 129262261Sdim { "fixup_sparc_tls_ldo_add", 0, 0, 0 }, 130262261Sdim { "fixup_sparc_tls_ie_hi22", 10, 22, 0 }, 131262261Sdim { "fixup_sparc_tls_ie_lo10", 22, 10, 0 }, 132262261Sdim { "fixup_sparc_tls_ie_ld", 0, 0, 0 }, 133262261Sdim { "fixup_sparc_tls_ie_ldx", 0, 0, 0 }, 134262261Sdim { "fixup_sparc_tls_ie_add", 0, 0, 0 }, 135262261Sdim { "fixup_sparc_tls_le_hix22", 0, 0, 0 }, 136262261Sdim { "fixup_sparc_tls_le_lox10", 0, 0, 0 } 137262261Sdim }; 138262261Sdim 139262261Sdim if (Kind < FirstTargetFixupKind) 140262261Sdim return MCAsmBackend::getFixupKindInfo(Kind); 141262261Sdim 142262261Sdim assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 143262261Sdim "Invalid kind!"); 144262261Sdim return Infos[Kind - FirstTargetFixupKind]; 145262261Sdim } 146262261Sdim 147262261Sdim void processFixupValue(const MCAssembler &Asm, 148262261Sdim const MCAsmLayout &Layout, 149262261Sdim const MCFixup &Fixup, 150262261Sdim const MCFragment *DF, 151262261Sdim MCValue & Target, 152262261Sdim uint64_t &Value, 153262261Sdim bool &IsResolved) { 154262261Sdim switch ((Sparc::Fixups)Fixup.getKind()) { 155262261Sdim default: break; 156262261Sdim case Sparc::fixup_sparc_wplt30: 157262261Sdim case Sparc::fixup_sparc_tls_gd_hi22: 158262261Sdim case Sparc::fixup_sparc_tls_gd_lo10: 159262261Sdim case Sparc::fixup_sparc_tls_gd_add: 160262261Sdim case Sparc::fixup_sparc_tls_gd_call: 161262261Sdim case Sparc::fixup_sparc_tls_ldm_hi22: 162262261Sdim case Sparc::fixup_sparc_tls_ldm_lo10: 163262261Sdim case Sparc::fixup_sparc_tls_ldm_add: 164262261Sdim case Sparc::fixup_sparc_tls_ldm_call: 165262261Sdim case Sparc::fixup_sparc_tls_ldo_hix22: 166262261Sdim case Sparc::fixup_sparc_tls_ldo_lox10: 167262261Sdim case Sparc::fixup_sparc_tls_ldo_add: 168262261Sdim case Sparc::fixup_sparc_tls_ie_hi22: 169262261Sdim case Sparc::fixup_sparc_tls_ie_lo10: 170262261Sdim case Sparc::fixup_sparc_tls_ie_ld: 171262261Sdim case Sparc::fixup_sparc_tls_ie_ldx: 172262261Sdim case Sparc::fixup_sparc_tls_ie_add: 173262261Sdim case Sparc::fixup_sparc_tls_le_hix22: 174262261Sdim case Sparc::fixup_sparc_tls_le_lox10: IsResolved = false; break; 175262261Sdim } 176262261Sdim } 177262261Sdim 178262261Sdim bool mayNeedRelaxation(const MCInst &Inst) const { 179262261Sdim // FIXME. 180262261Sdim return false; 181262261Sdim } 182262261Sdim 183262261Sdim /// fixupNeedsRelaxation - Target specific predicate for whether a given 184262261Sdim /// fixup requires the associated instruction to be relaxed. 185262261Sdim bool fixupNeedsRelaxation(const MCFixup &Fixup, 186262261Sdim uint64_t Value, 187262261Sdim const MCRelaxableFragment *DF, 188262261Sdim const MCAsmLayout &Layout) const { 189262261Sdim // FIXME. 190262261Sdim assert(0 && "fixupNeedsRelaxation() unimplemented"); 191262261Sdim return false; 192262261Sdim } 193262261Sdim void relaxInstruction(const MCInst &Inst, MCInst &Res) const { 194262261Sdim // FIXME. 195262261Sdim assert(0 && "relaxInstruction() unimplemented"); 196262261Sdim } 197262261Sdim 198262261Sdim bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { 199262261Sdim // FIXME: Zero fill for now. 200262261Sdim for (uint64_t i = 0; i != Count; ++i) 201262261Sdim OW->Write8(0); 202262261Sdim return true; 203262261Sdim } 204262261Sdim 205262261Sdim bool is64Bit() const { 206262261Sdim StringRef name = TheTarget.getName(); 207262261Sdim return name == "sparcv9"; 208262261Sdim } 209262261Sdim }; 210262261Sdim 211262261Sdim class ELFSparcAsmBackend : public SparcAsmBackend { 212262261Sdim Triple::OSType OSType; 213262261Sdim public: 214262261Sdim ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) : 215262261Sdim SparcAsmBackend(T), OSType(OSType) { } 216262261Sdim 217262261Sdim void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 218262261Sdim uint64_t Value) const { 219262261Sdim 220262261Sdim Value = adjustFixupValue(Fixup.getKind(), Value); 221262261Sdim if (!Value) return; // Doesn't change encoding. 222262261Sdim 223262261Sdim unsigned Offset = Fixup.getOffset(); 224262261Sdim 225262261Sdim // For each byte of the fragment that the fixup touches, mask in the bits 226262261Sdim // from the fixup value. The Value has been "split up" into the 227262261Sdim // appropriate bitfields above. 228262261Sdim for (unsigned i = 0; i != 4; ++i) 229262261Sdim Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff); 230262261Sdim 231262261Sdim } 232262261Sdim 233262261Sdim MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 234262261Sdim uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType); 235262261Sdim return createSparcELFObjectWriter(OS, is64Bit(), OSABI); 236262261Sdim } 237262261Sdim 238262261Sdim virtual bool doesSectionRequireSymbols(const MCSection &Section) const { 239262261Sdim return false; 240262261Sdim } 241262261Sdim }; 242262261Sdim 243262261Sdim} // end anonymous namespace 244262261Sdim 245262261Sdim 246262261SdimMCAsmBackend *llvm::createSparcAsmBackend(const Target &T, 247262261Sdim const MCRegisterInfo &MRI, 248262261Sdim StringRef TT, 249262261Sdim StringRef CPU) { 250262261Sdim return new ELFSparcAsmBackend(T, Triple(TT).getOS()); 251262261Sdim} 252