164 lines · cpp
1//===-- VEMCCodeEmitter.cpp - Convert VE 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 VEMCCodeEmitter class.10//11//===----------------------------------------------------------------------===//12 13#include "MCTargetDesc/VEFixupKinds.h"14#include "VE.h"15#include "VEMCAsmInfo.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/MC/MCCodeEmitter.h"19#include "llvm/MC/MCContext.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/MCRegisterInfo.h"25#include "llvm/MC/MCSubtargetInfo.h"26#include "llvm/MC/MCSymbol.h"27#include "llvm/Support/EndianStream.h"28#include <cassert>29#include <cstdint>30 31using namespace llvm;32 33#define DEBUG_TYPE "mccodeemitter"34 35STATISTIC(MCNumEmitted, "Number of MC instructions emitted");36 37namespace {38 39class VEMCCodeEmitter : public MCCodeEmitter {40 MCContext &Ctx;41 42public:43 VEMCCodeEmitter(const MCInstrInfo &, MCContext &ctx)44 : Ctx(ctx) {}45 VEMCCodeEmitter(const VEMCCodeEmitter &) = delete;46 VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete;47 ~VEMCCodeEmitter() override = default;48 49 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,50 SmallVectorImpl<MCFixup> &Fixups,51 const MCSubtargetInfo &STI) const override;52 53 // getBinaryCodeForInstr - TableGen'erated function for getting the54 // binary encoding for an instruction.55 uint64_t getBinaryCodeForInstr(const MCInst &MI,56 SmallVectorImpl<MCFixup> &Fixups,57 const MCSubtargetInfo &STI) const;58 59 /// getMachineOpValue - Return binary encoding of operand. If the machine60 /// operand requires relocation, record the relocation and return zero.61 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,62 SmallVectorImpl<MCFixup> &Fixups,63 const MCSubtargetInfo &STI) const;64 65 uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,66 SmallVectorImpl<MCFixup> &Fixups,67 const MCSubtargetInfo &STI) const;68 uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo,69 SmallVectorImpl<MCFixup> &Fixups,70 const MCSubtargetInfo &STI) const;71 uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo,72 SmallVectorImpl<MCFixup> &Fixups,73 const MCSubtargetInfo &STI) const;74};75 76} // end anonymous namespace77 78static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset,79 const MCExpr *Value, uint16_t Kind) {80 bool PCRel = false;81 switch (Kind) {82 case VE::fixup_ve_srel32:83 case VE::fixup_ve_pc_hi32:84 case VE::fixup_ve_pc_lo32:85 PCRel = true;86 }87 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel));88}89 90void VEMCCodeEmitter::encodeInstruction(const MCInst &MI,91 SmallVectorImpl<char> &CB,92 SmallVectorImpl<MCFixup> &Fixups,93 const MCSubtargetInfo &STI) const {94 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);95 support::endian::write<uint64_t>(CB, Bits, llvm::endianness::little);96 97 ++MCNumEmitted; // Keep track of the # of mi's emitted.98}99 100unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI,101 const MCOperand &MO,102 SmallVectorImpl<MCFixup> &Fixups,103 const MCSubtargetInfo &STI) const {104 if (MO.isReg())105 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());106 if (MO.isImm())107 return static_cast<unsigned>(MO.getImm());108 109 assert(MO.isExpr());110 111 const MCExpr *Expr = MO.getExpr();112 if (const auto *SExpr = dyn_cast<MCSpecifierExpr>(Expr)) {113 auto Kind = VE::getFixupKind(SExpr->getSpecifier());114 addFixup(Fixups, 0, Expr, Kind);115 return 0;116 }117 118 int64_t Res;119 if (Expr->evaluateAsAbsolute(Res))120 return Res;121 122 llvm_unreachable("Unhandled expression!");123 return 0;124}125 126uint64_t127VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,128 SmallVectorImpl<MCFixup> &Fixups,129 const MCSubtargetInfo &STI) const {130 const MCOperand &MO = MI.getOperand(OpNo);131 if (MO.isReg() || MO.isImm())132 return getMachineOpValue(MI, MO, Fixups, STI);133 134 addFixup(Fixups, 0, MO.getExpr(), VE::fixup_ve_srel32);135 return 0;136}137 138uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo,139 SmallVectorImpl<MCFixup> &Fixups,140 const MCSubtargetInfo &STI) const {141 const MCOperand &MO = MI.getOperand(OpNo);142 if (MO.isImm())143 return VECondCodeToVal(144 static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI)));145 return 0;146}147 148uint64_t VEMCCodeEmitter::getRDOpValue(const MCInst &MI, unsigned OpNo,149 SmallVectorImpl<MCFixup> &Fixups,150 const MCSubtargetInfo &STI) const {151 const MCOperand &MO = MI.getOperand(OpNo);152 if (MO.isImm())153 return VERDToVal(static_cast<VERD::RoundingMode>(154 getMachineOpValue(MI, MO, Fixups, STI)));155 return 0;156}157 158#include "VEGenMCCodeEmitter.inc"159 160MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII,161 MCContext &Ctx) {162 return new VEMCCodeEmitter(MCII, Ctx);163}164