brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.9 KiB · 84dc4b8 Raw
307 lines · cpp
1//===-- LanaiMCCodeEmitter.cpp - Convert Lanai 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 LanaiMCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "LanaiAluCode.h"14#include "MCTargetDesc/LanaiBaseInfo.h"15#include "MCTargetDesc/LanaiFixupKinds.h"16#include "MCTargetDesc/LanaiMCAsmInfo.h"17#include "llvm/ADT/SmallVector.h"18#include "llvm/ADT/Statistic.h"19#include "llvm/MC/MCCodeEmitter.h"20#include "llvm/MC/MCExpr.h"21#include "llvm/MC/MCFixup.h"22#include "llvm/MC/MCInst.h"23#include "llvm/MC/MCInstrInfo.h"24#include "llvm/MC/MCSubtargetInfo.h"25#include "llvm/Support/Casting.h"26#include "llvm/Support/EndianStream.h"27#include <cassert>28#include <cstdint>29 30#define DEBUG_TYPE "mccodeemitter"31 32STATISTIC(MCNumEmitted, "Number of MC instructions emitted");33 34namespace llvm {35 36namespace {37 38class LanaiMCCodeEmitter : public MCCodeEmitter {39public:40  LanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &C) {}41  LanaiMCCodeEmitter(const LanaiMCCodeEmitter &) = delete;42  void operator=(const LanaiMCCodeEmitter &) = delete;43  ~LanaiMCCodeEmitter() override = default;44 45  // The functions below are called by TableGen generated functions for getting46  // the binary encoding of instructions/opereands.47 48  // getBinaryCodeForInstr - TableGen'erated function for getting the49  // binary encoding for an instruction.50  uint64_t getBinaryCodeForInstr(const MCInst &Inst,51                                 SmallVectorImpl<MCFixup> &Fixups,52                                 const MCSubtargetInfo &SubtargetInfo) const;53 54  // getMachineOpValue - Return binary encoding of operand. If the machine55  // operand requires relocation, record the relocation and return zero.56  unsigned getMachineOpValue(const MCInst &Inst, const MCOperand &MCOp,57                             SmallVectorImpl<MCFixup> &Fixups,58                             const MCSubtargetInfo &SubtargetInfo) const;59 60  unsigned getRiMemoryOpValue(const MCInst &Inst, unsigned OpNo,61                              SmallVectorImpl<MCFixup> &Fixups,62                              const MCSubtargetInfo &SubtargetInfo) const;63 64  unsigned getRrMemoryOpValue(const MCInst &Inst, unsigned OpNo,65                              SmallVectorImpl<MCFixup> &Fixups,66                              const MCSubtargetInfo &SubtargetInfo) const;67 68  unsigned getSplsOpValue(const MCInst &Inst, unsigned OpNo,69                          SmallVectorImpl<MCFixup> &Fixups,70                          const MCSubtargetInfo &SubtargetInfo) const;71 72  unsigned getBranchTargetOpValue(const MCInst &Inst, unsigned OpNo,73                                  SmallVectorImpl<MCFixup> &Fixups,74                                  const MCSubtargetInfo &SubtargetInfo) const;75 76  void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB,77                         SmallVectorImpl<MCFixup> &Fixups,78                         const MCSubtargetInfo &SubtargetInfo) const override;79 80  unsigned adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,81                                const MCSubtargetInfo &STI) const;82 83  unsigned adjustPqBitsSpls(const MCInst &Inst, unsigned Value,84                            const MCSubtargetInfo &STI) const;85};86 87} // end anonymous namespace88 89static Lanai::Fixups FixupKind(const MCExpr *Expr) {90  if (isa<MCSymbolRefExpr>(Expr))91    return Lanai::FIXUP_LANAI_21;92  if (const MCSpecifierExpr *McExpr = dyn_cast<MCSpecifierExpr>(Expr)) {93    Lanai::Specifier ExprKind = McExpr->getSpecifier();94    switch (ExprKind) {95    case Lanai::S_None:96      return Lanai::FIXUP_LANAI_21;97    case Lanai::S_ABS_HI:98      return Lanai::FIXUP_LANAI_HI16;99    case Lanai::S_ABS_LO:100      return Lanai::FIXUP_LANAI_LO16;101    }102  }103  return Lanai::Fixups(0);104}105 106// getMachineOpValue - Return binary encoding of operand. If the machine107// operand requires relocation, record the relocation and return zero.108unsigned LanaiMCCodeEmitter::getMachineOpValue(109    const MCInst &Inst, const MCOperand &MCOp, SmallVectorImpl<MCFixup> &Fixups,110    const MCSubtargetInfo &SubtargetInfo) const {111  if (MCOp.isReg())112    return getLanaiRegisterNumbering(MCOp.getReg());113  if (MCOp.isImm())114    return static_cast<unsigned>(MCOp.getImm());115 116  // MCOp must be an expression117  assert(MCOp.isExpr());118  const MCExpr *Expr = MCOp.getExpr();119 120  // Extract the symbolic reference side of a binary expression.121  if (Expr->getKind() == MCExpr::Binary) {122    const MCBinaryExpr *BinaryExpr = static_cast<const MCBinaryExpr *>(Expr);123    Expr = BinaryExpr->getLHS();124  }125 126  assert(isa<MCSpecifierExpr>(Expr) || Expr->getKind() == MCExpr::SymbolRef);127  // Push fixup (all info is contained within)128  Fixups.push_back(129      MCFixup::create(0, MCOp.getExpr(), MCFixupKind(FixupKind(Expr))));130  return 0;131}132 133// Helper function to adjust P and Q bits on load and store instructions.134static unsigned adjustPqBits(const MCInst &Inst, unsigned Value,135                             unsigned PBitShift, unsigned QBitShift) {136  const MCOperand AluOp = Inst.getOperand(3);137  unsigned AluCode = AluOp.getImm();138 139  // Set the P bit to one iff the immediate is nonzero and not a post-op140  // instruction.141  const MCOperand Op2 = Inst.getOperand(2);142  Value &= ~(1 << PBitShift);143  if (!LPAC::isPostOp(AluCode) &&144      ((Op2.isImm() && Op2.getImm() != 0) ||145       (Op2.isReg() && Op2.getReg() != Lanai::R0) || (Op2.isExpr())))146    Value |= (1 << PBitShift);147 148  // Set the Q bit to one iff it is a post- or pre-op instruction.149  assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&150         "Expected register operand.");151  Value &= ~(1 << QBitShift);152  if (LPAC::modifiesOp(AluCode) && ((Op2.isImm() && Op2.getImm() != 0) ||153                                    (Op2.isReg() && Op2.getReg() != Lanai::R0)))154    Value |= (1 << QBitShift);155 156  return Value;157}158 159unsigned160LanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,161                                         const MCSubtargetInfo &STI) const {162  return adjustPqBits(Inst, Value, 17, 16);163}164 165unsigned166LanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst &Inst, unsigned Value,167                                     const MCSubtargetInfo &STI) const {168  return adjustPqBits(Inst, Value, 11, 10);169}170 171void LanaiMCCodeEmitter::encodeInstruction(172    const MCInst &Inst, SmallVectorImpl<char> &CB,173    SmallVectorImpl<MCFixup> &Fixups,174    const MCSubtargetInfo &SubtargetInfo) const {175  // Get instruction encoding and emit it176  unsigned Value = getBinaryCodeForInstr(Inst, Fixups, SubtargetInfo);177  ++MCNumEmitted; // Keep track of the number of emitted insns.178 179  support::endian::write<uint32_t>(CB, Value, llvm::endianness::big);180}181 182// Encode Lanai Memory Operand183unsigned LanaiMCCodeEmitter::getRiMemoryOpValue(184    const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,185    const MCSubtargetInfo &SubtargetInfo) const {186  unsigned Encoding;187  const MCOperand Op1 = Inst.getOperand(OpNo + 0);188  const MCOperand Op2 = Inst.getOperand(OpNo + 1);189  const MCOperand AluOp = Inst.getOperand(OpNo + 2);190 191  assert(Op1.isReg() && "First operand is not register.");192  assert((Op2.isImm() || Op2.isExpr()) &&193         "Second operand is neither an immediate nor an expression.");194  assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&195         "Register immediate only supports addition operator");196 197  Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 18);198  if (Op2.isImm()) {199    assert(isInt<16>(Op2.getImm()) &&200           "Constant value truncated (limited to 16-bit)");201 202    Encoding |= (Op2.getImm() & 0xffff);203    if (Op2.getImm() != 0) {204      if (LPAC::isPreOp(AluOp.getImm()))205        Encoding |= (0x3 << 16);206      if (LPAC::isPostOp(AluOp.getImm()))207        Encoding |= (0x1 << 16);208    }209  } else210    getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);211 212  return Encoding;213}214 215unsigned LanaiMCCodeEmitter::getRrMemoryOpValue(216    const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,217    const MCSubtargetInfo &SubtargetInfo) const {218  unsigned Encoding;219  const MCOperand Op1 = Inst.getOperand(OpNo + 0);220  const MCOperand Op2 = Inst.getOperand(OpNo + 1);221  const MCOperand AluMCOp = Inst.getOperand(OpNo + 2);222 223  assert(Op1.isReg() && "First operand is not register.");224  Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 15);225  assert(Op2.isReg() && "Second operand is not register.");226  Encoding |= (getLanaiRegisterNumbering(Op2.getReg()) << 10);227 228  assert(AluMCOp.isImm() && "Third operator is not immediate.");229  // Set BBB230  unsigned AluOp = AluMCOp.getImm();231  Encoding |= LPAC::encodeLanaiAluCode(AluOp) << 5;232  // Set P and Q233  if (LPAC::isPreOp(AluOp))234    Encoding |= (0x3 << 8);235  if (LPAC::isPostOp(AluOp))236    Encoding |= (0x1 << 8);237  // Set JJJJ238  switch (LPAC::getAluOp(AluOp)) {239  case LPAC::SHL:240  case LPAC::SRL:241    Encoding |= 0x10;242    break;243  case LPAC::SRA:244    Encoding |= 0x18;245    break;246  default:247    break;248  }249 250  return Encoding;251}252 253unsigned254LanaiMCCodeEmitter::getSplsOpValue(const MCInst &Inst, unsigned OpNo,255                                   SmallVectorImpl<MCFixup> &Fixups,256                                   const MCSubtargetInfo &SubtargetInfo) const {257  unsigned Encoding;258  const MCOperand Op1 = Inst.getOperand(OpNo + 0);259  const MCOperand Op2 = Inst.getOperand(OpNo + 1);260  const MCOperand AluOp = Inst.getOperand(OpNo + 2);261 262  assert(Op1.isReg() && "First operand is not register.");263  assert((Op2.isImm() || Op2.isExpr()) &&264         "Second operand is neither an immediate nor an expression.");265  assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&266         "Register immediate only supports addition operator");267 268  Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 12);269  if (Op2.isImm()) {270    assert(isInt<10>(Op2.getImm()) &&271           "Constant value truncated (limited to 10-bit)");272 273    Encoding |= (Op2.getImm() & 0x3ff);274    if (Op2.getImm() != 0) {275      if (LPAC::isPreOp(AluOp.getImm()))276        Encoding |= (0x3 << 10);277      if (LPAC::isPostOp(AluOp.getImm()))278        Encoding |= (0x1 << 10);279    }280  } else281    getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);282 283  return Encoding;284}285 286unsigned LanaiMCCodeEmitter::getBranchTargetOpValue(287    const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,288    const MCSubtargetInfo &SubtargetInfo) const {289  const MCOperand &MCOp = Inst.getOperand(OpNo);290  if (MCOp.isReg() || MCOp.isImm())291    return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo);292 293  Fixups.push_back(MCFixup::create(0, MCOp.getExpr(), Lanai::FIXUP_LANAI_25));294 295  return 0;296}297 298#include "LanaiGenMCCodeEmitter.inc"299 300} // end namespace llvm301 302llvm::MCCodeEmitter *303llvm::createLanaiMCCodeEmitter(const MCInstrInfo &InstrInfo,304                               MCContext &context) {305  return new LanaiMCCodeEmitter(InstrInfo, context);306}307