brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · bc60842 Raw
277 lines · cpp
1//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/SparcFixupKinds.h"10#include "MCTargetDesc/SparcMCTargetDesc.h"11#include "llvm/ADT/StringSwitch.h"12#include "llvm/MC/MCAsmBackend.h"13#include "llvm/MC/MCELFObjectWriter.h"14#include "llvm/MC/MCExpr.h"15#include "llvm/MC/MCObjectWriter.h"16#include "llvm/MC/MCSubtargetInfo.h"17#include "llvm/MC/MCValue.h"18#include "llvm/MC/TargetRegistry.h"19#include "llvm/Support/EndianStream.h"20 21using namespace llvm;22 23static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {24  switch (Kind) {25  default:26    assert(uint16_t(Kind) < FirstTargetFixupKind && "Unknown fixup kind!");27    return Value;28  case FK_Data_1:29  case FK_Data_2:30  case FK_Data_4:31  case FK_Data_8:32    return Value;33 34  case Sparc::fixup_sparc_call30:35    return (Value >> 2) & 0x3fffffff;36 37  case ELF::R_SPARC_WDISP22:38    return (Value >> 2) & 0x3fffff;39 40  case ELF::R_SPARC_WDISP19:41    return (Value >> 2) & 0x7ffff;42 43  case ELF::R_SPARC_WDISP16: {44    // A.3 Branch on Integer Register with Prediction (BPr)45    // Inst{21-20} = d16hi;46    // Inst{13-0}  = d16lo;47    unsigned d16hi = (Value >> 16) & 0x3;48    unsigned d16lo = (Value >> 2) & 0x3fff;49    return (d16hi << 20) | d16lo;50  }51 52  case ELF::R_SPARC_WDISP10: {53    // FIXME this really should be an error reporting check.54    assert((Value & 0x3) == 0);55 56    // 7.17 Compare and Branch57    // Inst{20-19} = d10hi;58    // Inst{12-5}  = d10lo;59    unsigned d10hi = (Value >> 10) & 0x3;60    unsigned d10lo = (Value >> 2) & 0xff;61    return (d10hi << 19) | (d10lo << 5);62  }63 64  case ELF::R_SPARC_HIX22:65    return (~Value >> 10) & 0x3fffff;66 67  case ELF::R_SPARC_PC22:68  case ELF::R_SPARC_HI22:69  case ELF::R_SPARC_LM22:70    return (Value >> 10) & 0x3fffff;71 72  case Sparc::fixup_sparc_13:73    return Value & 0x1fff;74 75  case ELF::R_SPARC_5:76    return Value & 0x1f;77 78  case ELF::R_SPARC_LOX10:79    return (Value & 0x3ff) | 0x1c00;80 81  case ELF::R_SPARC_PC10:82  case ELF::R_SPARC_LO10:83    return Value & 0x3ff;84 85  case ELF::R_SPARC_H44:86    return (Value >> 22) & 0x3fffff;87  case ELF::R_SPARC_M44:88    return (Value >> 12) & 0x3ff;89  case ELF::R_SPARC_L44:90    return Value & 0xfff;91 92  case ELF::R_SPARC_HH22:93    return (Value >> 42) & 0x3fffff;94  case ELF::R_SPARC_HM10:95    return (Value >> 32) & 0x3ff;96  }97}98 99/// getFixupKindNumBytes - The number of bytes the fixup may change.100static unsigned getFixupKindNumBytes(unsigned Kind) {101    switch (Kind) {102  default:103    return 4;104  case FK_Data_1:105    return 1;106  case FK_Data_2:107    return 2;108  case FK_Data_8:109    return 8;110  }111}112 113namespace {114class SparcAsmBackend : public MCAsmBackend {115protected:116  bool Is64Bit;117  bool IsV8Plus;118 119public:120  SparcAsmBackend(const MCSubtargetInfo &STI)121      : MCAsmBackend(STI.getTargetTriple().isLittleEndian()122                         ? llvm::endianness::little123                         : llvm::endianness::big),124        Is64Bit(STI.getTargetTriple().isArch64Bit()),125        IsV8Plus(STI.hasFeature(Sparc::FeatureV8Plus)) {}126 127  std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;128  MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;129  void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,130                  uint8_t *Data, uint64_t Value, bool IsResolved) override;131 132  bool writeNopData(raw_ostream &OS, uint64_t Count,133                    const MCSubtargetInfo *STI) const override {134 135    // If the count is not 4-byte aligned, we must be writing data into the136    // text section (otherwise we have unaligned instructions, and thus have137    // far bigger problems), so just write zeros instead.138    OS.write_zeros(Count % 4);139 140    uint64_t NumNops = Count / 4;141    for (uint64_t i = 0; i != NumNops; ++i)142      support::endian::write<uint32_t>(OS, 0x01000000, Endian);143 144    return true;145  }146};147 148class ELFSparcAsmBackend : public SparcAsmBackend {149  Triple::OSType OSType;150 151public:152  ELFSparcAsmBackend(const MCSubtargetInfo &STI, Triple::OSType OSType)153      : SparcAsmBackend(STI), OSType(OSType) {}154 155  std::unique_ptr<MCObjectTargetWriter>156  createObjectTargetWriter() const override {157    uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);158    return createSparcELFObjectWriter(Is64Bit, IsV8Plus, OSABI);159  }160};161} // end anonymous namespace162 163std::optional<MCFixupKind> SparcAsmBackend::getFixupKind(StringRef Name) const {164  unsigned Type;165  Type = llvm::StringSwitch<unsigned>(Name)166#define ELF_RELOC(X, Y) .Case(#X, Y)167#include "llvm/BinaryFormat/ELFRelocs/Sparc.def"168#undef ELF_RELOC169             .Case("BFD_RELOC_NONE", ELF::R_SPARC_NONE)170             .Case("BFD_RELOC_8", ELF::R_SPARC_8)171             .Case("BFD_RELOC_16", ELF::R_SPARC_16)172             .Case("BFD_RELOC_32", ELF::R_SPARC_32)173             .Case("BFD_RELOC_64", ELF::R_SPARC_64)174             .Default(-1u);175  if (Type == -1u)176    return std::nullopt;177  return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);178}179 180MCFixupKindInfo SparcAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {181  // clang-format off182  const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {183      // name                    offset bits flags184      {"fixup_sparc_call30",     2,     30,  0},185      {"fixup_sparc_13",        19,     13,  0},186  };187 188  const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {189      // name                    offset bits flags190      {"fixup_sparc_call30",     0,     30,  0},191      {"fixup_sparc_13",         0,     13,  0},192  };193  // clang-format on194 195  if (!mc::isRelocation(Kind)) {196    if (Kind < FirstTargetFixupKind)197      return MCAsmBackend::getFixupKindInfo(Kind);198    assert(unsigned(Kind - FirstTargetFixupKind) < Sparc::NumTargetFixupKinds &&199           "Invalid kind!");200    if (Endian == llvm::endianness::little)201      return InfosLE[Kind - FirstTargetFixupKind];202 203    return InfosBE[Kind - FirstTargetFixupKind];204  }205 206  MCFixupKindInfo Info{};207  switch (uint16_t(Kind)) {208  case ELF::R_SPARC_PC10:209    Info = {"", 22, 10, 0};210    break;211  case ELF::R_SPARC_PC22:212    Info = {"", 10, 22, 0};213    break;214  case ELF::R_SPARC_WDISP10:215    Info = {"", 0, 32, 0};216    break;217  case ELF::R_SPARC_WDISP16:218    Info = {"", 0, 32, 0};219    break;220  case ELF::R_SPARC_WDISP19:221    Info = {"", 13, 19, 0};222    break;223  case ELF::R_SPARC_WDISP22:224    Info = {"", 10, 22, 0};225    break;226 227  case ELF::R_SPARC_HI22:228    Info = {"", 10, 22, 0};229    break;230  case ELF::R_SPARC_LO10:231    Info = {"", 22, 10, 0};232    break;233  case ELF::R_SPARC_HH22:234    Info = {"", 10, 22, 0};235    break;236  case ELF::R_SPARC_HM10:237    Info = {"", 22, 10, 0};238    break;239  case ELF::R_SPARC_LM22:240    Info = {"", 10, 22, 0};241    break;242  case ELF::R_SPARC_HIX22:243    Info = {"", 10, 22, 0};244    break;245  case ELF::R_SPARC_LOX10:246    Info = {"", 19, 13, 0};247    break;248  }249  if (Endian == llvm::endianness::little)250    Info.TargetOffset = 32 - Info.TargetOffset - Info.TargetSize;251  return Info;252}253 254void SparcAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,255                                 const MCValue &Target, uint8_t *Data,256                                 uint64_t Value, bool IsResolved) {257  maybeAddReloc(F, Fixup, Target, Value, IsResolved);258  if (!IsResolved)259    return;260  Value = adjustFixupValue(Fixup.getKind(), Value);261 262  unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());263  // For each byte of the fragment that the fixup touches, mask in the264  // bits from the fixup value.265  for (unsigned i = 0; i != NumBytes; ++i) {266    unsigned Idx = Endian == llvm::endianness::little ? i : (NumBytes - 1) - i;267    Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);268  }269}270 271MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,272                                          const MCSubtargetInfo &STI,273                                          const MCRegisterInfo &MRI,274                                          const MCTargetOptions &Options) {275  return new ELFSparcAsmBackend(STI, STI.getTargetTriple().getOS());276}277