brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.7 KiB · 5f9f55e Raw
510 lines · cpp
1//===-- CSKYMCCodeEmitter.cpp - CSKY Code Emitter interface ---------------===//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// This file implements the CSKYMCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "CSKYMCAsmInfo.h"14#include "MCTargetDesc/CSKYFixupKinds.h"15#include "MCTargetDesc/CSKYMCAsmInfo.h"16#include "MCTargetDesc/CSKYMCTargetDesc.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/MC/MCCodeEmitter.h"19#include "llvm/MC/MCContext.h"20#include "llvm/MC/MCInstBuilder.h"21#include "llvm/MC/MCInstrInfo.h"22#include "llvm/MC/MCRegisterInfo.h"23#include "llvm/MC/MCSubtargetInfo.h"24#include "llvm/Support/Casting.h"25#include "llvm/Support/EndianStream.h"26 27using namespace llvm;28 29#define DEBUG_TYPE "csky-mccode-emitter"30 31STATISTIC(MCNumEmitted, "Number of MC instructions emitted");32 33static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,34                     const MCExpr *Value, uint16_t Kind) {35  bool PCRel = false;36  switch (Kind) {37  case CSKY::Fixups::fixup_csky_pcrel_imm16_scale2:38  case CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4:39  case CSKY::Fixups::fixup_csky_pcrel_imm26_scale2:40  case CSKY::Fixups::fixup_csky_pcrel_imm18_scale2:41  case CSKY::Fixups::fixup_csky_gotpc:42  case CSKY::Fixups::fixup_csky_pcrel_imm10_scale2:43  case CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4:44  case CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4:45    PCRel = true;46  }47  Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));48}49 50namespace {51class CSKYMCCodeEmitter : public MCCodeEmitter {52  MCContext &Ctx;53  const MCInstrInfo &MII;54 55public:56  CSKYMCCodeEmitter(MCContext &Ctx, const MCInstrInfo &MII)57      : Ctx(Ctx), MII(MII) {}58 59  ~CSKYMCCodeEmitter() {}60 61  void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB,62                         SmallVectorImpl<MCFixup> &Fixups,63                         const MCSubtargetInfo &STI) const override;64 65  // Generated by tablegen.66  uint64_t getBinaryCodeForInstr(const MCInst &MI,67                                 SmallVectorImpl<MCFixup> &Fixups,68                                 const MCSubtargetInfo &STI) const;69 70  // Default encoding method used by tablegen.71  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,72                             SmallVectorImpl<MCFixup> &Fixups,73                             const MCSubtargetInfo &STI) const;74 75  template <int shift = 0>76  unsigned getImmOpValue(const MCInst &MI, unsigned Idx,77                         SmallVectorImpl<MCFixup> &Fixups,78                         const MCSubtargetInfo &STI) const {79    const MCOperand &MO = MI.getOperand(Idx);80    if (MO.isImm())81      return (MO.getImm() >> shift);82 83    assert(MO.isExpr() && "Unexpected MO type.");84 85    MCFixupKind Kind = getTargetFixup(MO.getExpr());86    addFixup(Fixups, 0, MO.getExpr(), Kind);87    return 0;88  }89 90  unsigned getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,91                               SmallVectorImpl<MCFixup> &Fixups,92                               const MCSubtargetInfo &STI) const;93 94  unsigned getRegisterSeqOpValue(const MCInst &MI, unsigned Op,95                                 SmallVectorImpl<MCFixup> &Fixups,96                                 const MCSubtargetInfo &STI) const;97 98  unsigned getOImmOpValue(const MCInst &MI, unsigned Idx,99                          SmallVectorImpl<MCFixup> &Fixups,100                          const MCSubtargetInfo &STI) const;101 102  unsigned getImmOpValueIDLY(const MCInst &MI, unsigned Idx,103                             SmallVectorImpl<MCFixup> &Fixups,104                             const MCSubtargetInfo &STI) const;105 106  unsigned getImmJMPIX(const MCInst &MI, unsigned Idx,107                       SmallVectorImpl<MCFixup> &Fixups,108                       const MCSubtargetInfo &STI) const;109 110  unsigned getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,111                                SmallVectorImpl<MCFixup> &Fixups,112                                const MCSubtargetInfo &STI) const;113 114  unsigned getImmShiftOpValue(const MCInst &MI, unsigned Idx,115                              SmallVectorImpl<MCFixup> &Fixups,116                              const MCSubtargetInfo &STI) const {117    const MCOperand &MO = MI.getOperand(Idx);118    assert(MO.isImm() && "Unexpected MO type.");119    return 1 << MO.getImm();120  }121 122  MCFixupKind getTargetFixup(const MCExpr *Expr) const;123 124  template <llvm::CSKY::Fixups FIXUP>125  unsigned getBranchSymbolOpValue(const MCInst &MI, unsigned Idx,126                                  SmallVectorImpl<MCFixup> &Fixups,127                                  const MCSubtargetInfo &STI) const {128    const MCOperand &MO = MI.getOperand(Idx);129 130    if (MO.isImm())131      return MO.getImm() >> 1;132 133    assert(MO.isExpr() && "Unexpected MO type.");134 135    MCFixupKind Kind = MCFixupKind(FIXUP);136    if (MO.getExpr()->getKind() == MCExpr::Specifier)137      Kind = getTargetFixup(MO.getExpr());138 139    addFixup(Fixups, 0, MO.getExpr(), Kind);140    return 0;141  }142 143  template <llvm::CSKY::Fixups FIXUP>144  unsigned getConstpoolSymbolOpValue(const MCInst &MI, unsigned Idx,145                                     SmallVectorImpl<MCFixup> &Fixups,146                                     const MCSubtargetInfo &STI) const {147    const MCOperand &MO = MI.getOperand(Idx);148    assert(MO.isExpr() && "Unexpected MO type.");149 150    MCFixupKind Kind = MCFixupKind(FIXUP);151    if (MO.getExpr()->getKind() == MCExpr::Specifier)152      Kind = getTargetFixup(MO.getExpr());153 154    addFixup(Fixups, 0, MO.getExpr(), Kind);155    return 0;156  }157 158  template <llvm::CSKY::Fixups FIXUP>159  unsigned getDataSymbolOpValue(const MCInst &MI, unsigned Idx,160                                SmallVectorImpl<MCFixup> &Fixups,161                                const MCSubtargetInfo &STI) const {162    const MCOperand &MO = MI.getOperand(Idx);163    assert(MO.isExpr() && "Unexpected MO type.");164 165    MCFixupKind Kind = MCFixupKind(FIXUP);166    if (MO.getExpr()->getKind() == MCExpr::Specifier)167      Kind = getTargetFixup(MO.getExpr());168 169    addFixup(Fixups, 0, MO.getExpr(), Kind);170    return 0;171  }172 173  unsigned getCallSymbolOpValue(const MCInst &MI, unsigned Idx,174                                SmallVectorImpl<MCFixup> &Fixups,175                                const MCSubtargetInfo &STI) const {176    const MCOperand &MO = MI.getOperand(Idx);177    assert(MO.isExpr() && "Unexpected MO type.");178 179    MCFixupKind Kind = CSKY::fixup_csky_pcrel_imm26_scale2;180    if (MO.getExpr()->getKind() == MCExpr::Specifier)181      Kind = getTargetFixup(MO.getExpr());182 183    addFixup(Fixups, 0, MO.getExpr(), Kind);184    return 0;185  }186 187  unsigned getBareSymbolOpValue(const MCInst &MI, unsigned Idx,188                                SmallVectorImpl<MCFixup> &Fixups,189                                const MCSubtargetInfo &STI) const {190    const MCOperand &MO = MI.getOperand(Idx);191    assert(MO.isExpr() && "Unexpected MO type.");192 193    MCFixupKind Kind = CSKY::fixup_csky_pcrel_imm18_scale2;194    if (MO.getExpr()->getKind() == MCExpr::Specifier)195      Kind = getTargetFixup(MO.getExpr());196 197    addFixup(Fixups, 0, MO.getExpr(), Kind);198    return 0;199  }200 201  void expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB,202                  SmallVectorImpl<MCFixup> &Fixups,203                  const MCSubtargetInfo &STI) const;204  void expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB,205                 SmallVectorImpl<MCFixup> &Fixups,206                 const MCSubtargetInfo &STI) const;207  void expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB,208                   SmallVectorImpl<MCFixup> &Fixups,209                   const MCSubtargetInfo &STI) const;210};211} // namespace212 213unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx,214                                           SmallVectorImpl<MCFixup> &Fixups,215                                           const MCSubtargetInfo &STI) const {216  const MCOperand &MO = MI.getOperand(Idx);217  assert(MO.isImm() && "Unexpected MO type.");218  return MO.getImm() - 1;219}220 221unsigned222CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx,223                                     SmallVectorImpl<MCFixup> &Fixups,224                                     const MCSubtargetInfo &STI) const {225  const MCOperand &MO = MI.getOperand(Idx);226  assert(MO.isImm() && "Unexpected MO type.");227 228  auto V = (MO.getImm() <= 3) ? 4 : MO.getImm();229  return V - 1;230}231 232unsigned233CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx,234                                        SmallVectorImpl<MCFixup> &Fixups,235                                        const MCSubtargetInfo &STI) const {236  const MCOperand &MSB = MI.getOperand(Idx);237  const MCOperand &LSB = MI.getOperand(Idx + 1);238  assert(MSB.isImm() && LSB.isImm() && "Unexpected MO type.");239 240  return MSB.getImm() - LSB.getImm();241}242 243static void writeData(uint32_t Bin, unsigned Size, SmallVectorImpl<char> &CB) {244  if (Size == 4)245    support::endian::write(CB, static_cast<uint16_t>(Bin >> 16),246                           llvm::endianness::little);247  support::endian::write(CB, static_cast<uint16_t>(Bin),248                         llvm::endianness::little);249}250 251void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB,252                                   SmallVectorImpl<MCFixup> &Fixups,253                                   const MCSubtargetInfo &STI) const {254 255  MCInst TmpInst;256 257  uint32_t Binary;258 259  TmpInst =260      MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16)261          .addOperand(MI.getOperand(0))262          .addImm(6);263  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);264  writeData(Binary, 2, CB);265 266  if (!STI.hasFeature(CSKY::Has2E3))267    TmpInst = MCInstBuilder(CSKY::BR32)268                  .addOperand(MI.getOperand(1))269                  .addOperand(MI.getOperand(2));270  else271    TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2));272  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);273  Fixups[Fixups.size() - 1].setOffset(2);274  writeData(Binary, 4, CB);275}276 277void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB,278                                  SmallVectorImpl<MCFixup> &Fixups,279                                  const MCSubtargetInfo &STI) const {280 281  MCInst TmpInst;282  uint32_t Binary;283  unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2;284 285  TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)286                .addOperand(MI.getOperand(0))287                .addOperand(MI.getOperand(1));288  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);289  writeData(Binary, Size, CB);290 291  TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)292                .addOperand(MI.getOperand(0))293                .addOperand(MI.getOperand(0))294                .addImm(1);295  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);296  writeData(Binary, Size, CB);297}298 299void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB,300                                    SmallVectorImpl<MCFixup> &Fixups,301                                    const MCSubtargetInfo &STI) const {302 303  MCInst TmpInst;304  uint32_t Binary;305  unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2;306 307  TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16)308                .addOperand(MI.getOperand(0))309                .addOperand(MI.getOperand(1));310  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);311  writeData(Binary, Size, CB);312 313  TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16)314                .addOperand(MI.getOperand(0))315                .addOperand(MI.getOperand(0))316                .addImm(MI.getOperand(2).getImm() + 1);317  Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);318  writeData(Binary, Size, CB);319}320 321void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI,322                                          SmallVectorImpl<char> &CB,323                                          SmallVectorImpl<MCFixup> &Fixups,324                                          const MCSubtargetInfo &STI) const {325  const MCInstrDesc &Desc = MII.get(MI.getOpcode());326  unsigned Size = Desc.getSize();327 328  MCInst TmpInst;329 330  switch (MI.getOpcode()) {331  default:332    TmpInst = MI;333    break;334  case CSKY::JBT_E:335  case CSKY::JBF_E:336    expandJBTF(MI, CB, Fixups, STI);337    MCNumEmitted += 2;338    return;339  case CSKY::NEG32:340  case CSKY::NEG16:341    expandNEG(MI, CB, Fixups, STI);342    MCNumEmitted += 2;343    return;344  case CSKY::RSUBI32:345  case CSKY::RSUBI16:346    expandRSUBI(MI, CB, Fixups, STI);347    MCNumEmitted += 2;348    return;349  case CSKY::JBSR32:350    TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0));351    break;352  case CSKY::JBR16:353    TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0));354    break;355  case CSKY::JBR32:356    TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0));357    break;358  case CSKY::JBT16:359    TmpInst = MCInstBuilder(CSKY::BT16)360                  .addOperand(MI.getOperand(0))361                  .addOperand(MI.getOperand(1));362    break;363  case CSKY::JBT32:364    TmpInst = MCInstBuilder(CSKY::BT32)365                  .addOperand(MI.getOperand(0))366                  .addOperand(MI.getOperand(1));367    break;368  case CSKY::JBF16:369    TmpInst = MCInstBuilder(CSKY::BF16)370                  .addOperand(MI.getOperand(0))371                  .addOperand(MI.getOperand(1));372    break;373  case CSKY::JBF32:374    TmpInst = MCInstBuilder(CSKY::BF32)375                  .addOperand(MI.getOperand(0))376                  .addOperand(MI.getOperand(1));377    break;378  case CSKY::LRW32_Gen:379    TmpInst = MCInstBuilder(CSKY::LRW32)380                  .addOperand(MI.getOperand(0))381                  .addOperand(MI.getOperand(2));382    break;383  case CSKY::LRW16_Gen:384    TmpInst = MCInstBuilder(CSKY::LRW16)385                  .addOperand(MI.getOperand(0))386                  .addOperand(MI.getOperand(2));387    break;388  case CSKY::CMPLEI32:389    TmpInst = MCInstBuilder(CSKY::CMPLTI32)390                  .addOperand(MI.getOperand(0))391                  .addOperand(MI.getOperand(1))392                  .addImm(MI.getOperand(2).getImm() + 1);393    break;394  case CSKY::CMPLEI16:395    TmpInst = MCInstBuilder(CSKY::CMPLTI16)396                  .addOperand(MI.getOperand(0))397                  .addOperand(MI.getOperand(1))398                  .addImm(MI.getOperand(2).getImm() + 1);399    break;400  case CSKY::ROTRI32:401    TmpInst = MCInstBuilder(CSKY::ROTLI32)402                  .addOperand(MI.getOperand(0))403                  .addOperand(MI.getOperand(1))404                  .addImm(32 - MI.getOperand(2).getImm());405    break;406  case CSKY::BGENI:407    auto V = 1 << MI.getOperand(1).getImm();408    TmpInst =409        MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V);410    break;411  }412 413  ++MCNumEmitted;414  writeData(getBinaryCodeForInstr(TmpInst, Fixups, STI), Size, CB);415}416 417unsigned418CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,419                                     SmallVectorImpl<MCFixup> &Fixups,420                                     const MCSubtargetInfo &STI) const {421  if (MO.isReg())422    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());423 424  if (MO.isImm())425    return static_cast<unsigned>(MO.getImm());426 427  llvm_unreachable("Unhandled expression!");428  return 0;429}430 431unsigned432CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx,433                                       SmallVectorImpl<MCFixup> &Fixups,434                                       const MCSubtargetInfo &STI) const {435  assert(MI.getOperand(Idx).isReg() && "Unexpected MO type.");436  assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type.");437 438  unsigned Ry = MI.getOperand(Idx).getReg();439  unsigned Rz = MI.getOperand(Idx + 1).getImm();440 441  unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) -442                 Ctx.getRegisterInfo()->getEncodingValue(Ry);443 444  return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm);445}446 447unsigned448CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op,449                                         SmallVectorImpl<MCFixup> &Fixups,450                                         const MCSubtargetInfo &STI) const {451  unsigned Reg1 =452      Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg());453  unsigned Reg2 =454      Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg());455 456  unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1);457 458  return Binary;459}460 461unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx,462                                        SmallVectorImpl<MCFixup> &Fixups,463                                        const MCSubtargetInfo &STI) const {464  switch (MI.getOperand(Idx).getImm()) {465  default:466    llvm_unreachable("Unhandled jmpix imm!");467  case 16:468    return 0;469  case 24:470    return 1;471  case 32:472    return 2;473  case 40:474    return 3;475  }476}477 478MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const {479  const auto *CSKYExpr = cast<MCSpecifierExpr>(Expr);480  switch (CSKYExpr->getSpecifier()) {481  default:482    llvm_unreachable("Unhandled fixup kind!");483  case CSKY::S_ADDR:484    return CSKY::fixup_csky_addr32;485  case CSKY::S_ADDR_HI16:486    return CSKY::fixup_csky_addr_hi16;487  case CSKY::S_ADDR_LO16:488    return CSKY::fixup_csky_addr_lo16;489  case CSKY::S_GOT:490    return CSKY::fixup_csky_got32;491  case CSKY::S_GOTPC:492    return CSKY::fixup_csky_gotpc;493  case CSKY::S_GOTOFF:494    return CSKY::fixup_csky_gotoff;495  case CSKY::S_PLT:496    return CSKY::fixup_csky_plt32;497  case CSKY::S_PLT_IMM18_BY4:498    return CSKY::fixup_csky_plt_imm18_scale4;499  case CSKY::S_GOT_IMM18_BY4:500    return CSKY::fixup_csky_got_imm18_scale4;501  }502}503 504MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,505                                             MCContext &Ctx) {506  return new CSKYMCCodeEmitter(Ctx, MCII);507}508 509#include "CSKYGenMCCodeEmitter.inc"510