15ffd83dbSDimitry Andric //===-- VEMCCodeEmitter.cpp - Convert VE code to machine code -------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // This file implements the VEMCCodeEmitter class. 105ffd83dbSDimitry Andric // 115ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 125ffd83dbSDimitry Andric 135ffd83dbSDimitry Andric #include "MCTargetDesc/VEFixupKinds.h" 145ffd83dbSDimitry Andric #include "VE.h" 155ffd83dbSDimitry Andric #include "VEMCExpr.h" 165ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/Statistic.h" 185ffd83dbSDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 195ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 205ffd83dbSDimitry Andric #include "llvm/MC/MCExpr.h" 215ffd83dbSDimitry Andric #include "llvm/MC/MCFixup.h" 225ffd83dbSDimitry Andric #include "llvm/MC/MCInst.h" 235ffd83dbSDimitry Andric #include "llvm/MC/MCInstrInfo.h" 245ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 255ffd83dbSDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 265ffd83dbSDimitry Andric #include "llvm/MC/MCSymbol.h" 275ffd83dbSDimitry Andric #include "llvm/Support/EndianStream.h" 285ffd83dbSDimitry Andric #include "llvm/Support/ErrorHandling.h" 295ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h" 305ffd83dbSDimitry Andric #include <cassert> 315ffd83dbSDimitry Andric #include <cstdint> 325ffd83dbSDimitry Andric 335ffd83dbSDimitry Andric using namespace llvm; 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric #define DEBUG_TYPE "mccodeemitter" 365ffd83dbSDimitry Andric 375ffd83dbSDimitry Andric STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 385ffd83dbSDimitry Andric 395ffd83dbSDimitry Andric namespace { 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric class VEMCCodeEmitter : public MCCodeEmitter { 425ffd83dbSDimitry Andric const MCInstrInfo &MCII; 435ffd83dbSDimitry Andric MCContext &Ctx; 445ffd83dbSDimitry Andric 455ffd83dbSDimitry Andric public: 465ffd83dbSDimitry Andric VEMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) 475ffd83dbSDimitry Andric : MCII(mcii), Ctx(ctx) {} 485ffd83dbSDimitry Andric VEMCCodeEmitter(const VEMCCodeEmitter &) = delete; 495ffd83dbSDimitry Andric VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete; 505ffd83dbSDimitry Andric ~VEMCCodeEmitter() override = default; 515ffd83dbSDimitry Andric 525ffd83dbSDimitry Andric void encodeInstruction(const MCInst &MI, raw_ostream &OS, 535ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 545ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const override; 555ffd83dbSDimitry Andric 565ffd83dbSDimitry Andric // getBinaryCodeForInstr - TableGen'erated function for getting the 575ffd83dbSDimitry Andric // binary encoding for an instruction. 585ffd83dbSDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 595ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 605ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 615ffd83dbSDimitry Andric 625ffd83dbSDimitry Andric /// getMachineOpValue - Return binary encoding of operand. If the machine 635ffd83dbSDimitry Andric /// operand requires relocation, record the relocation and return zero. 645ffd83dbSDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 655ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 665ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 675ffd83dbSDimitry Andric 685ffd83dbSDimitry Andric uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 695ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 705ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 715ffd83dbSDimitry Andric uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo, 725ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 735ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 745ffd83dbSDimitry Andric uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo, 755ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 765ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 775ffd83dbSDimitry Andric 785ffd83dbSDimitry Andric private: 795ffd83dbSDimitry Andric FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; 805ffd83dbSDimitry Andric void 815ffd83dbSDimitry Andric verifyInstructionPredicates(const MCInst &MI, 825ffd83dbSDimitry Andric const FeatureBitset &AvailableFeatures) const; 835ffd83dbSDimitry Andric }; 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric } // end anonymous namespace 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 885ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 895ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 905ffd83dbSDimitry Andric verifyInstructionPredicates(MI, 915ffd83dbSDimitry Andric computeAvailableFeatures(STI.getFeatureBits())); 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 945ffd83dbSDimitry Andric support::endian::write<uint64_t>(OS, Bits, support::little); 955ffd83dbSDimitry Andric 965ffd83dbSDimitry Andric ++MCNumEmitted; // Keep track of the # of mi's emitted. 975ffd83dbSDimitry Andric } 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI, 1005ffd83dbSDimitry Andric const MCOperand &MO, 1015ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1025ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 1035ffd83dbSDimitry Andric if (MO.isReg()) 1045ffd83dbSDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 1055ffd83dbSDimitry Andric if (MO.isImm()) 106*0eae32dcSDimitry Andric return static_cast<unsigned>(MO.getImm()); 1075ffd83dbSDimitry Andric 1085ffd83dbSDimitry Andric assert(MO.isExpr()); 109*0eae32dcSDimitry Andric 1105ffd83dbSDimitry Andric const MCExpr *Expr = MO.getExpr(); 1115ffd83dbSDimitry Andric if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Expr)) { 1125ffd83dbSDimitry Andric MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 1135ffd83dbSDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind)); 1145ffd83dbSDimitry Andric return 0; 1155ffd83dbSDimitry Andric } 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric int64_t Res; 1185ffd83dbSDimitry Andric if (Expr->evaluateAsAbsolute(Res)) 1195ffd83dbSDimitry Andric return Res; 1205ffd83dbSDimitry Andric 1215ffd83dbSDimitry Andric llvm_unreachable("Unhandled expression!"); 1225ffd83dbSDimitry Andric return 0; 1235ffd83dbSDimitry Andric } 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric uint64_t 1265ffd83dbSDimitry Andric VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 1275ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1285ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 1295ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1305ffd83dbSDimitry Andric if (MO.isReg() || MO.isImm()) 1315ffd83dbSDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI); 1325ffd83dbSDimitry Andric 1335ffd83dbSDimitry Andric Fixups.push_back( 134*0eae32dcSDimitry Andric MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_srel32)); 1355ffd83dbSDimitry Andric return 0; 1365ffd83dbSDimitry Andric } 1375ffd83dbSDimitry Andric 1385ffd83dbSDimitry Andric uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo, 1395ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1405ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 1415ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1425ffd83dbSDimitry Andric if (MO.isImm()) 1435ffd83dbSDimitry Andric return VECondCodeToVal( 1445ffd83dbSDimitry Andric static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI))); 1455ffd83dbSDimitry Andric return 0; 1465ffd83dbSDimitry Andric } 1475ffd83dbSDimitry Andric 1485ffd83dbSDimitry Andric uint64_t VEMCCodeEmitter::getRDOpValue(const MCInst &MI, unsigned OpNo, 1495ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1505ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 1515ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1525ffd83dbSDimitry Andric if (MO.isImm()) 1535ffd83dbSDimitry Andric return VERDToVal(static_cast<VERD::RoundingMode>( 1545ffd83dbSDimitry Andric getMachineOpValue(MI, MO, Fixups, STI))); 1555ffd83dbSDimitry Andric return 0; 1565ffd83dbSDimitry Andric } 1575ffd83dbSDimitry Andric 1585ffd83dbSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER 1595ffd83dbSDimitry Andric #include "VEGenMCCodeEmitter.inc" 1605ffd83dbSDimitry Andric 1615ffd83dbSDimitry Andric MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, 1625ffd83dbSDimitry Andric const MCRegisterInfo &MRI, 1635ffd83dbSDimitry Andric MCContext &Ctx) { 1645ffd83dbSDimitry Andric return new VEMCCodeEmitter(MCII, Ctx); 1655ffd83dbSDimitry Andric } 166