brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.0 KiB · 6964998 Raw
351 lines · cpp
1//===-- CSKYAsmBackend.cpp - CSKY 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 "CSKYAsmBackend.h"10#include "MCTargetDesc/CSKYMCTargetDesc.h"11#include "llvm/ADT/DenseMap.h"12#include "llvm/MC/MCAssembler.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCObjectWriter.h"15#include "llvm/MC/MCValue.h"16#include "llvm/Support/Debug.h"17 18#define DEBUG_TYPE "csky-asmbackend"19 20using namespace llvm;21 22std::unique_ptr<MCObjectTargetWriter>23CSKYAsmBackend::createObjectTargetWriter() const {24  return createCSKYELFObjectWriter();25}26 27MCFixupKindInfo CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {28 29  static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = {30      {CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},31      {CSKY::Fixups::fixup_csky_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}},32      {CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 0, 32, 0}},33      {CSKY::Fixups::fixup_csky_pcrel_imm16_scale2,34       {"fixup_csky_pcrel_imm16_scale2", 0, 32, 0}},35      {CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4,36       {"fixup_csky_pcrel_uimm16_scale4", 0, 32, 0}},37      {CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4,38       {"fixup_csky_pcrel_uimm8_scale4", 0, 32, 0}},39      {CSKY::Fixups::fixup_csky_pcrel_imm26_scale2,40       {"fixup_csky_pcrel_imm26_scale2", 0, 32, 0}},41      {CSKY::Fixups::fixup_csky_pcrel_imm18_scale2,42       {"fixup_csky_pcrel_imm18_scale2", 0, 32, 0}},43      {CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}},44      {CSKY::Fixups::fixup_csky_got_imm18_scale4,45       {"fixup_csky_got_imm18_scale4", 0, 32, 0}},46      {CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}},47      {CSKY::Fixups::fixup_csky_gotpc, {"fixup_csky_gotpc", 0, 32, 0}},48      {CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}},49      {CSKY::Fixups::fixup_csky_plt_imm18_scale4,50       {"fixup_csky_plt_imm18_scale4", 0, 32, 0}},51      {CSKY::Fixups::fixup_csky_pcrel_imm10_scale2,52       {"fixup_csky_pcrel_imm10_scale2", 0, 16, 0}},53      {CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4,54       {"fixup_csky_pcrel_uimm7_scale4", 0, 16, 0}},55      {CSKY::Fixups::fixup_csky_doffset_imm18,56       {"fixup_csky_doffset_imm18", 0, 18, 0}},57      {CSKY::Fixups::fixup_csky_doffset_imm18_scale2,58       {"fixup_csky_doffset_imm18_scale2", 0, 18, 0}},59      {CSKY::Fixups::fixup_csky_doffset_imm18_scale4,60       {"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}};61 62  assert(Infos.size() == CSKY::NumTargetFixupKinds &&63         "Not all fixup kinds added to Infos array");64 65  if (mc::isRelocation(Kind))66    return {};67  if (Kind < FirstTargetFixupKind)68    return MCAsmBackend::getFixupKindInfo(Kind);69  return Infos[Kind];70}71 72static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,73                                 MCContext &Ctx) {74  switch (Fixup.getKind()) {75  default:76    llvm_unreachable("Unknown fixup kind!");77  case CSKY::fixup_csky_got32:78  case CSKY::fixup_csky_got_imm18_scale4:79  case CSKY::fixup_csky_gotoff:80  case CSKY::fixup_csky_gotpc:81  case CSKY::fixup_csky_plt32:82  case CSKY::fixup_csky_plt_imm18_scale4:83    llvm_unreachable("Relocation should be unconditionally forced\n");84  case FK_Data_1:85  case FK_Data_2:86  case FK_Data_4:87  case FK_Data_8:88    return Value;89  case CSKY::fixup_csky_addr32:90    return Value & 0xffffffff;91  case CSKY::fixup_csky_pcrel_imm16_scale2:92    if (!isIntN(17, Value))93      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");94    if (Value & 0x1)95      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");96 97    return (Value >> 1) & 0xffff;98  case CSKY::fixup_csky_pcrel_uimm16_scale4:99    if (!isUIntN(18, Value))100      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");101    if (Value & 0x3)102      Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");103 104    return (Value >> 2) & 0xffff;105  case CSKY::fixup_csky_pcrel_imm26_scale2:106    if (!isIntN(27, Value))107      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");108    if (Value & 0x1)109      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");110 111    return (Value >> 1) & 0x3ffffff;112  case CSKY::fixup_csky_pcrel_imm18_scale2:113    if (!isIntN(19, Value))114      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");115    if (Value & 0x1)116      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");117 118    return (Value >> 1) & 0x3ffff;119  case CSKY::fixup_csky_pcrel_uimm8_scale4: {120    if (!isUIntN(10, Value))121      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");122    if (Value & 0x3)123      Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");124 125    unsigned IMM4L = (Value >> 2) & 0xf;126    unsigned IMM4H = (Value >> 6) & 0xf;127 128    Value = (IMM4H << 21) | (IMM4L << 4);129    return Value;130  }131  case CSKY::fixup_csky_pcrel_imm10_scale2:132    if (!isIntN(11, Value))133      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");134    if (Value & 0x1)135      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");136 137    return (Value >> 1) & 0x3ff;138  case CSKY::fixup_csky_pcrel_uimm7_scale4:139    if ((Value >> 2) > 0xfe)140      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");141    if (Value & 0x3)142      Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");143 144    if ((Value >> 2) <= 0x7f) {145      unsigned IMM5L = (Value >> 2) & 0x1f;146      unsigned IMM2H = (Value >> 7) & 0x3;147 148      Value = (1 << 12) | (IMM2H << 8) | IMM5L;149    } else {150      unsigned IMM5L = (~Value >> 2) & 0x1f;151      unsigned IMM2H = (~Value >> 7) & 0x3;152 153      Value = (IMM2H << 8) | IMM5L;154    }155 156    return Value;157  }158}159 160bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &,161                                                  const MCFixup &Fixup,162                                                  const MCValue &,163                                                  uint64_t Value,164                                                  bool Resolved) const {165  // Return true if the symbol is unresolved.166  if (!Resolved)167    return true;168 169  int64_t Offset = int64_t(Value);170  switch (Fixup.getKind()) {171  default:172    return false;173  case CSKY::fixup_csky_pcrel_imm10_scale2:174    return !isShiftedInt<10, 1>(Offset);175  case CSKY::fixup_csky_pcrel_imm16_scale2:176    return !isShiftedInt<16, 1>(Offset);177  case CSKY::fixup_csky_pcrel_imm26_scale2:178    return !isShiftedInt<26, 1>(Offset);179  case CSKY::fixup_csky_pcrel_uimm7_scale4:180    return ((Value >> 2) > 0xfe) || (Value & 0x3);181  }182}183 184std::optional<bool> CSKYAsmBackend::evaluateFixup(const MCFragment &F,185                                                  MCFixup &Fixup, MCValue &,186                                                  uint64_t &Value) {187  // For a few PC-relative fixups, offsets need to be aligned down. We188  // compensate here because the default handler's `Value` decrement doesn't189  // account for this alignment.190  switch (Fixup.getKind()) {191  case CSKY::fixup_csky_pcrel_uimm16_scale4:192  case CSKY::fixup_csky_pcrel_uimm8_scale4:193  case CSKY::fixup_csky_pcrel_uimm7_scale4:194    Value = (Asm->getFragmentOffset(F) + Fixup.getOffset()) % 4;195  }196  return {};197}198 199void CSKYAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,200                                const MCValue &Target, uint8_t *Data,201                                uint64_t Value, bool IsResolved) {202  if (IsResolved && shouldForceRelocation(Fixup, Target))203    IsResolved = false;204  maybeAddReloc(F, Fixup, Target, Value, IsResolved);205 206  MCFixupKind Kind = Fixup.getKind();207  if (mc::isRelocation(Kind))208    return;209  MCContext &Ctx = getContext();210  MCFixupKindInfo Info = getFixupKindInfo(Kind);211  if (!Value)212    return; // Doesn't change encoding.213  // Apply any target-specific value adjustments.214  Value = adjustFixupValue(Fixup, Value, Ctx);215 216  // Shift the value into position.217  Value <<= Info.TargetOffset;218 219  unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;220 221  assert(Fixup.getOffset() + NumBytes <= F.getSize() &&222         "Invalid fixup offset!");223 224  // For each byte of the fragment that the fixup touches, mask in the225  // bits from the fixup value.226  bool IsLittleEndian = (Endian == llvm::endianness::little);227  bool IsInstFixup = (Kind >= FirstTargetFixupKind);228 229  if (IsLittleEndian && IsInstFixup && (NumBytes == 4)) {230    Data[0] |= uint8_t((Value >> 16) & 0xff);231    Data[1] |= uint8_t((Value >> 24) & 0xff);232    Data[2] |= uint8_t(Value & 0xff);233    Data[3] |= uint8_t((Value >> 8) & 0xff);234  } else {235    for (unsigned I = 0; I != NumBytes; I++) {236      unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);237      Data[Idx] |= uint8_t((Value >> (I * 8)) & 0xff);238    }239  }240}241 242bool CSKYAsmBackend::mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand>,243                                       const MCSubtargetInfo &STI) const {244  switch (Opcode) {245  default:246    return false;247  case CSKY::JBR32:248  case CSKY::JBT32:249  case CSKY::JBF32:250  case CSKY::JBSR32:251    if (!STI.hasFeature(CSKY::Has2E3))252      return false;253    return true;254  case CSKY::JBR16:255  case CSKY::JBT16:256  case CSKY::JBF16:257  case CSKY::LRW16:258  case CSKY::BR16:259    return true;260  }261}262 263bool CSKYAsmBackend::shouldForceRelocation(const MCFixup &Fixup,264                                           const MCValue &Target /*STI*/) {265  if (Target.getSpecifier())266    return true;267  switch (Fixup.getKind()) {268  default:269    break;270  case CSKY::fixup_csky_doffset_imm18:271  case CSKY::fixup_csky_doffset_imm18_scale2:272  case CSKY::fixup_csky_doffset_imm18_scale4:273    return true;274  }275 276  return false;277}278 279bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,280                                          uint64_t Value) const {281  return false;282}283 284void CSKYAsmBackend::relaxInstruction(MCInst &Inst,285                                      const MCSubtargetInfo &STI) const {286  MCInst Res;287 288  switch (Inst.getOpcode()) {289  default:290    LLVM_DEBUG(Inst.dump());291    llvm_unreachable("Opcode not expected!");292  case CSKY::LRW16:293    Res.setOpcode(CSKY::LRW32);294    Res.addOperand(Inst.getOperand(0));295    Res.addOperand(Inst.getOperand(1));296    break;297  case CSKY::BR16:298    Res.setOpcode(CSKY::BR32);299    Res.addOperand(Inst.getOperand(0));300    break;301  case CSKY::JBSR32:302    Res.setOpcode(CSKY::JSRI32);303    Res.addOperand(Inst.getOperand(1));304    break;305  case CSKY::JBR32:306    Res.setOpcode(CSKY::JMPI32);307    Res.addOperand(Inst.getOperand(1));308    break;309  case CSKY::JBT32:310  case CSKY::JBF32:311    Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E);312    Res.addOperand(Inst.getOperand(0));313    Res.addOperand(Inst.getOperand(1));314    Res.addOperand(Inst.getOperand(2));315    break;316  case CSKY::JBR16:317    Res.setOpcode(CSKY::JBR32);318    Res.addOperand(Inst.getOperand(0));319    Res.addOperand(Inst.getOperand(1));320    break;321  case CSKY::JBT16:322  case CSKY::JBF16:323    // ck801324    unsigned opcode;325    if (STI.hasFeature(CSKY::HasE2))326      opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32;327    else328      opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E;329 330    Res.setOpcode(opcode);331    Res.addOperand(Inst.getOperand(0));332    Res.addOperand(Inst.getOperand(1));333    Res.addOperand(Inst.getOperand(2));334    break;335  }336  Inst = std::move(Res);337}338 339bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,340                                  const MCSubtargetInfo *STI) const {341  OS.write_zeros(Count);342  return true;343}344 345MCAsmBackend *llvm::createCSKYAsmBackend(const Target &T,346                                         const MCSubtargetInfo &STI,347                                         const MCRegisterInfo &MRI,348                                         const MCTargetOptions &Options) {349  return new CSKYAsmBackend(STI, Options);350}351