1*5ffd83dbSDimitry Andric //===-- VEMCCodeEmitter.cpp - Convert VE code to machine code -------------===// 2*5ffd83dbSDimitry Andric // 3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5ffd83dbSDimitry Andric // 7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 8*5ffd83dbSDimitry Andric // 9*5ffd83dbSDimitry Andric // This file implements the VEMCCodeEmitter class. 10*5ffd83dbSDimitry Andric // 11*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 12*5ffd83dbSDimitry Andric 13*5ffd83dbSDimitry Andric #include "MCTargetDesc/VEFixupKinds.h" 14*5ffd83dbSDimitry Andric #include "VE.h" 15*5ffd83dbSDimitry Andric #include "VEMCExpr.h" 16*5ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h" 17*5ffd83dbSDimitry Andric #include "llvm/ADT/Statistic.h" 18*5ffd83dbSDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 19*5ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 20*5ffd83dbSDimitry Andric #include "llvm/MC/MCExpr.h" 21*5ffd83dbSDimitry Andric #include "llvm/MC/MCFixup.h" 22*5ffd83dbSDimitry Andric #include "llvm/MC/MCInst.h" 23*5ffd83dbSDimitry Andric #include "llvm/MC/MCInstrInfo.h" 24*5ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 25*5ffd83dbSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 26*5ffd83dbSDimitry Andric #include "llvm/MC/MCSymbol.h" 27*5ffd83dbSDimitry Andric #include "llvm/Support/EndianStream.h" 28*5ffd83dbSDimitry Andric #include "llvm/Support/ErrorHandling.h" 29*5ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h" 30*5ffd83dbSDimitry Andric #include <cassert> 31*5ffd83dbSDimitry Andric #include <cstdint> 32*5ffd83dbSDimitry Andric 33*5ffd83dbSDimitry Andric using namespace llvm; 34*5ffd83dbSDimitry Andric 35*5ffd83dbSDimitry Andric #define DEBUG_TYPE "mccodeemitter" 36*5ffd83dbSDimitry Andric 37*5ffd83dbSDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 38*5ffd83dbSDimitry Andric 39*5ffd83dbSDimitry Andric namespace { 40*5ffd83dbSDimitry Andric 41*5ffd83dbSDimitry Andric class VEMCCodeEmitter : public MCCodeEmitter { 42*5ffd83dbSDimitry Andric const MCInstrInfo &MCII; 43*5ffd83dbSDimitry Andric MCContext &Ctx; 44*5ffd83dbSDimitry Andric 45*5ffd83dbSDimitry Andric public: 46*5ffd83dbSDimitry Andric VEMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) 47*5ffd83dbSDimitry Andric : MCII(mcii), Ctx(ctx) {} 48*5ffd83dbSDimitry Andric VEMCCodeEmitter(const VEMCCodeEmitter &) = delete; 49*5ffd83dbSDimitry Andric VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete; 50*5ffd83dbSDimitry Andric ~VEMCCodeEmitter() override = default; 51*5ffd83dbSDimitry Andric 52*5ffd83dbSDimitry Andric void encodeInstruction(const MCInst &MI, raw_ostream &OS, 53*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 54*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const override; 55*5ffd83dbSDimitry Andric 56*5ffd83dbSDimitry Andric // getBinaryCodeForInstr - TableGen'erated function for getting the 57*5ffd83dbSDimitry Andric // binary encoding for an instruction. 58*5ffd83dbSDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 59*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 60*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 61*5ffd83dbSDimitry Andric 62*5ffd83dbSDimitry Andric /// getMachineOpValue - Return binary encoding of operand. If the machine 63*5ffd83dbSDimitry Andric /// operand requires relocation, record the relocation and return zero. 64*5ffd83dbSDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 65*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 66*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 67*5ffd83dbSDimitry Andric 68*5ffd83dbSDimitry Andric uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 69*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 70*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 71*5ffd83dbSDimitry Andric uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo, 72*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 73*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 74*5ffd83dbSDimitry Andric uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo, 75*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 76*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 77*5ffd83dbSDimitry Andric 78*5ffd83dbSDimitry Andric private: 79*5ffd83dbSDimitry Andric FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; 80*5ffd83dbSDimitry Andric void 81*5ffd83dbSDimitry Andric verifyInstructionPredicates(const MCInst &MI, 82*5ffd83dbSDimitry Andric const FeatureBitset &AvailableFeatures) const; 83*5ffd83dbSDimitry Andric }; 84*5ffd83dbSDimitry Andric 85*5ffd83dbSDimitry Andric } // end anonymous namespace 86*5ffd83dbSDimitry Andric 87*5ffd83dbSDimitry Andric void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 88*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 89*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 90*5ffd83dbSDimitry Andric verifyInstructionPredicates(MI, 91*5ffd83dbSDimitry Andric computeAvailableFeatures(STI.getFeatureBits())); 92*5ffd83dbSDimitry Andric 93*5ffd83dbSDimitry Andric uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 94*5ffd83dbSDimitry Andric support::endian::write<uint64_t>(OS, Bits, support::little); 95*5ffd83dbSDimitry Andric 96*5ffd83dbSDimitry Andric ++MCNumEmitted; // Keep track of the # of mi's emitted. 97*5ffd83dbSDimitry Andric } 98*5ffd83dbSDimitry Andric 99*5ffd83dbSDimitry Andric unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI, 100*5ffd83dbSDimitry Andric const MCOperand &MO, 101*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 102*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 103*5ffd83dbSDimitry Andric if (MO.isReg()) 104*5ffd83dbSDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 105*5ffd83dbSDimitry Andric 106*5ffd83dbSDimitry Andric if (MO.isImm()) 107*5ffd83dbSDimitry Andric return MO.getImm(); 108*5ffd83dbSDimitry Andric 109*5ffd83dbSDimitry Andric assert(MO.isExpr()); 110*5ffd83dbSDimitry Andric const MCExpr *Expr = MO.getExpr(); 111*5ffd83dbSDimitry Andric if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Expr)) { 112*5ffd83dbSDimitry Andric MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 113*5ffd83dbSDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind)); 114*5ffd83dbSDimitry Andric return 0; 115*5ffd83dbSDimitry Andric } 116*5ffd83dbSDimitry Andric 117*5ffd83dbSDimitry Andric int64_t Res; 118*5ffd83dbSDimitry Andric if (Expr->evaluateAsAbsolute(Res)) 119*5ffd83dbSDimitry Andric return Res; 120*5ffd83dbSDimitry Andric 121*5ffd83dbSDimitry Andric llvm_unreachable("Unhandled expression!"); 122*5ffd83dbSDimitry Andric return 0; 123*5ffd83dbSDimitry Andric } 124*5ffd83dbSDimitry Andric 125*5ffd83dbSDimitry Andric uint64_t 126*5ffd83dbSDimitry Andric VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 127*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 128*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 129*5ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 130*5ffd83dbSDimitry Andric if (MO.isReg() || MO.isImm()) 131*5ffd83dbSDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI); 132*5ffd83dbSDimitry Andric 133*5ffd83dbSDimitry Andric Fixups.push_back( 134*5ffd83dbSDimitry Andric MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_pc_lo32)); 135*5ffd83dbSDimitry Andric return 0; 136*5ffd83dbSDimitry Andric } 137*5ffd83dbSDimitry Andric 138*5ffd83dbSDimitry Andric uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo, 139*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 140*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 141*5ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 142*5ffd83dbSDimitry Andric if (MO.isImm()) 143*5ffd83dbSDimitry Andric return VECondCodeToVal( 144*5ffd83dbSDimitry Andric static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI))); 145*5ffd83dbSDimitry Andric return 0; 146*5ffd83dbSDimitry Andric } 147*5ffd83dbSDimitry Andric 148*5ffd83dbSDimitry Andric uint64_t VEMCCodeEmitter::getRDOpValue(const MCInst &MI, unsigned OpNo, 149*5ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 150*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 151*5ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 152*5ffd83dbSDimitry Andric if (MO.isImm()) 153*5ffd83dbSDimitry Andric return VERDToVal(static_cast<VERD::RoundingMode>( 154*5ffd83dbSDimitry Andric getMachineOpValue(MI, MO, Fixups, STI))); 155*5ffd83dbSDimitry Andric return 0; 156*5ffd83dbSDimitry Andric } 157*5ffd83dbSDimitry Andric 158*5ffd83dbSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER 159*5ffd83dbSDimitry Andric #include "VEGenMCCodeEmitter.inc" 160*5ffd83dbSDimitry Andric 161*5ffd83dbSDimitry Andric MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, 162*5ffd83dbSDimitry Andric const MCRegisterInfo &MRI, 163*5ffd83dbSDimitry Andric MCContext &Ctx) { 164*5ffd83dbSDimitry Andric return new VEMCCodeEmitter(MCII, Ctx); 165*5ffd83dbSDimitry Andric } 166