brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.7 KiB · cb02e33 Raw
281 lines · cpp
1//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//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 SparcMCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/SparcFixupKinds.h"14#include "SparcMCTargetDesc.h"15#include "llvm/ADT/SmallVector.h"16#include "llvm/ADT/Statistic.h"17#include "llvm/BinaryFormat/ELF.h"18#include "llvm/MC/MCAsmInfo.h"19#include "llvm/MC/MCCodeEmitter.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCExpr.h"22#include "llvm/MC/MCFixup.h"23#include "llvm/MC/MCInst.h"24#include "llvm/MC/MCInstrInfo.h"25#include "llvm/MC/MCObjectFileInfo.h"26#include "llvm/MC/MCRegisterInfo.h"27#include "llvm/MC/MCSubtargetInfo.h"28#include "llvm/MC/MCSymbol.h"29#include "llvm/Support/Casting.h"30#include "llvm/Support/EndianStream.h"31#include <cassert>32#include <cstdint>33 34using namespace llvm;35 36#define DEBUG_TYPE "mccodeemitter"37 38STATISTIC(MCNumEmitted, "Number of MC instructions emitted");39 40namespace {41 42class SparcMCCodeEmitter : public MCCodeEmitter {43  MCContext &Ctx;44 45public:46  SparcMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)47      : Ctx(ctx) {}48  SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;49  SparcMCCodeEmitter &operator=(const SparcMCCodeEmitter &) = delete;50  ~SparcMCCodeEmitter() override = default;51 52  void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,53                         SmallVectorImpl<MCFixup> &Fixups,54                         const MCSubtargetInfo &STI) const override;55 56  // getBinaryCodeForInstr - TableGen'erated function for getting the57  // binary encoding for an instruction.58  uint64_t getBinaryCodeForInstr(const MCInst &MI,59                                 SmallVectorImpl<MCFixup> &Fixups,60                                 const MCSubtargetInfo &STI) const;61 62  /// getMachineOpValue - Return binary encoding of operand. If the machine63  /// operand requires relocation, record the relocation and return zero.64  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,65                             SmallVectorImpl<MCFixup> &Fixups,66                             const MCSubtargetInfo &STI) const;67  unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,68                             SmallVectorImpl<MCFixup> &Fixups,69                             const MCSubtargetInfo &STI) const;70  unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,71                             SmallVectorImpl<MCFixup> &Fixups,72                             const MCSubtargetInfo &STI) const;73  unsigned getSImm5OpValue(const MCInst &MI, unsigned OpNo,74                           SmallVectorImpl<MCFixup> &Fixups,75                           const MCSubtargetInfo &STI) const;76  unsigned getSImm13OpValue(const MCInst &MI, unsigned OpNo,77                            SmallVectorImpl<MCFixup> &Fixups,78                            const MCSubtargetInfo &STI) const;79  unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,80                                      SmallVectorImpl<MCFixup> &Fixups,81                                      const MCSubtargetInfo &STI) const;82  unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,83                                       SmallVectorImpl<MCFixup> &Fixups,84                                       const MCSubtargetInfo &STI) const;85  unsigned getCompareAndBranchTargetOpValue(const MCInst &MI, unsigned OpNo,86                                            SmallVectorImpl<MCFixup> &Fixups,87                                            const MCSubtargetInfo &STI) const;88};89 90} // end anonymous namespace91 92static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,93                     const MCExpr *Value, uint16_t Kind) {94  bool PCRel = false;95  switch (Kind) {96  case ELF::R_SPARC_PC10:97  case ELF::R_SPARC_PC22:98  case ELF::R_SPARC_WDISP10:99  case ELF::R_SPARC_WDISP16:100  case ELF::R_SPARC_WDISP19:101  case ELF::R_SPARC_WDISP22:102  case Sparc::fixup_sparc_call30:103    PCRel = true;104  }105  Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));106}107 108void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI,109                                           SmallVectorImpl<char> &CB,110                                           SmallVectorImpl<MCFixup> &Fixups,111                                           const MCSubtargetInfo &STI) const {112  unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);113  support::endian::write(CB, Bits,114                         Ctx.getAsmInfo()->isLittleEndian()115                             ? llvm::endianness::little116                             : llvm::endianness::big);117 118  // Some instructions have phantom operands that only contribute a fixup entry.119  unsigned SymOpNo = 0;120  switch (MI.getOpcode()) {121  default: break;122  case SP::TLS_CALL:   SymOpNo = 1; break;123  case SP::GDOP_LDrr:124  case SP::GDOP_LDXrr:125  case SP::TLS_ADDrr:126  case SP::TLS_LDrr:127  case SP::TLS_LDXrr:  SymOpNo = 3; break;128  }129  if (SymOpNo != 0) {130    const MCOperand &MO = MI.getOperand(SymOpNo);131    uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);132    assert(op == 0 && "Unexpected operand value!");133    (void)op; // suppress warning.134  }135 136  ++MCNumEmitted;  // Keep track of the # of mi's emitted.137}138 139unsigned SparcMCCodeEmitter::140getMachineOpValue(const MCInst &MI, const MCOperand &MO,141                  SmallVectorImpl<MCFixup> &Fixups,142                  const MCSubtargetInfo &STI) const {143  if (MO.isReg())144    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());145 146  if (MO.isImm())147    return MO.getImm();148 149  assert(MO.isExpr());150  const MCExpr *Expr = MO.getExpr();151  if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Expr)) {152    addFixup(Fixups, 0, Expr, SExpr->getSpecifier());153    return 0;154  }155 156  int64_t Res;157  if (Expr->evaluateAsAbsolute(Res))158    return Res;159 160  llvm_unreachable("Unhandled expression!");161  return 0;162}163 164unsigned SparcMCCodeEmitter::getSImm5OpValue(const MCInst &MI, unsigned OpNo,165                                             SmallVectorImpl<MCFixup> &Fixups,166                                             const MCSubtargetInfo &STI) const {167  const MCOperand &MO = MI.getOperand(OpNo);168 169  if (MO.isImm())170    return MO.getImm();171 172  assert(MO.isExpr() &&173         "getSImm5OpValue expects only expressions or an immediate");174 175  const MCExpr *Expr = MO.getExpr();176 177  // Constant value, no fixup is needed178  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))179    return CE->getValue();180 181  if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Expr)) {182    addFixup(Fixups, 0, Expr, SExpr->getSpecifier());183    return 0;184  }185  addFixup(Fixups, 0, Expr, ELF::R_SPARC_5);186  return 0;187}188 189unsigned190SparcMCCodeEmitter::getSImm13OpValue(const MCInst &MI, unsigned OpNo,191                                     SmallVectorImpl<MCFixup> &Fixups,192                                     const MCSubtargetInfo &STI) const {193  const MCOperand &MO = MI.getOperand(OpNo);194 195  if (MO.isImm())196    return MO.getImm();197 198  assert(MO.isExpr() &&199         "getSImm13OpValue expects only expressions or an immediate");200 201  const MCExpr *Expr = MO.getExpr();202 203  // Constant value, no fixup is needed204  if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))205    return CE->getValue();206 207  if (auto *SExpr = dyn_cast<MCSpecifierExpr>(Expr)) {208    addFixup(Fixups, 0, Expr, SExpr->getSpecifier());209    return 0;210  }211  addFixup(Fixups, 0, Expr, Sparc::fixup_sparc_13);212  return 0;213}214 215unsigned SparcMCCodeEmitter::216getCallTargetOpValue(const MCInst &MI, unsigned OpNo,217                     SmallVectorImpl<MCFixup> &Fixups,218                     const MCSubtargetInfo &STI) const {219  if (MI.getOpcode() == SP::TLS_CALL) {220    // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in221    // encodeInstruction.222    return 0;223  }224 225  const MCOperand &MO = MI.getOperand(OpNo);226  addFixup(Fixups, 0, MO.getExpr(), Sparc::fixup_sparc_call30);227  return 0;228}229 230unsigned SparcMCCodeEmitter::231getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,232                  SmallVectorImpl<MCFixup> &Fixups,233                  const MCSubtargetInfo &STI) const {234  const MCOperand &MO = MI.getOperand(OpNo);235  if (MO.isReg() || MO.isImm())236    return getMachineOpValue(MI, MO, Fixups, STI);237 238  addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP22);239  return 0;240}241 242unsigned SparcMCCodeEmitter::getBranchPredTargetOpValue(243    const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,244    const MCSubtargetInfo &STI) const {245  const MCOperand &MO = MI.getOperand(OpNo);246  if (MO.isReg() || MO.isImm())247    return getMachineOpValue(MI, MO, Fixups, STI);248 249  addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP19);250  return 0;251}252 253unsigned SparcMCCodeEmitter::getBranchOnRegTargetOpValue(254    const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,255    const MCSubtargetInfo &STI) const {256  const MCOperand &MO = MI.getOperand(OpNo);257  if (MO.isReg() || MO.isImm())258    return getMachineOpValue(MI, MO, Fixups, STI);259 260  addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP16);261  return 0;262}263 264unsigned SparcMCCodeEmitter::getCompareAndBranchTargetOpValue(265    const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,266    const MCSubtargetInfo &STI) const {267  const MCOperand &MO = MI.getOperand(OpNo);268  if (MO.isImm())269    return getMachineOpValue(MI, MO, Fixups, STI);270 271  addFixup(Fixups, 0, MO.getExpr(), ELF::R_SPARC_WDISP10);272  return 0;273}274 275#include "SparcGenMCCodeEmitter.inc"276 277MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,278                                              MCContext &Ctx) {279  return new SparcMCCodeEmitter(MCII, Ctx);280}281