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 MCContext &Ctx; 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric public: 45753f127fSDimitry Andric VEMCCodeEmitter(const MCInstrInfo &, MCContext &ctx) 46753f127fSDimitry Andric : Ctx(ctx) {} 475ffd83dbSDimitry Andric VEMCCodeEmitter(const VEMCCodeEmitter &) = delete; 485ffd83dbSDimitry Andric VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete; 495ffd83dbSDimitry Andric ~VEMCCodeEmitter() override = default; 505ffd83dbSDimitry Andric 5106c3fb27SDimitry Andric void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 525ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 535ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const override; 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric // getBinaryCodeForInstr - TableGen'erated function for getting the 565ffd83dbSDimitry Andric // binary encoding for an instruction. 575ffd83dbSDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 585ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 595ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric /// getMachineOpValue - Return binary encoding of operand. If the machine 625ffd83dbSDimitry Andric /// operand requires relocation, record the relocation and return zero. 635ffd83dbSDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 645ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 655ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 665ffd83dbSDimitry Andric 675ffd83dbSDimitry Andric uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 685ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 695ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 705ffd83dbSDimitry Andric uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo, 715ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 725ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 735ffd83dbSDimitry Andric uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo, 745ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 755ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const; 765ffd83dbSDimitry Andric }; 775ffd83dbSDimitry Andric 785ffd83dbSDimitry Andric } // end anonymous namespace 795ffd83dbSDimitry Andric 8006c3fb27SDimitry Andric void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, 8106c3fb27SDimitry Andric SmallVectorImpl<char> &CB, 825ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 835ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 845ffd83dbSDimitry Andric uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 85*5f757f3fSDimitry Andric support::endian::write<uint64_t>(CB, Bits, llvm::endianness::little); 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric ++MCNumEmitted; // Keep track of the # of mi's emitted. 885ffd83dbSDimitry Andric } 895ffd83dbSDimitry Andric 905ffd83dbSDimitry Andric unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI, 915ffd83dbSDimitry Andric const MCOperand &MO, 925ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 935ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 945ffd83dbSDimitry Andric if (MO.isReg()) 955ffd83dbSDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 965ffd83dbSDimitry Andric if (MO.isImm()) 970eae32dcSDimitry Andric return static_cast<unsigned>(MO.getImm()); 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric assert(MO.isExpr()); 1000eae32dcSDimitry Andric 1015ffd83dbSDimitry Andric const MCExpr *Expr = MO.getExpr(); 1025ffd83dbSDimitry Andric if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Expr)) { 1035ffd83dbSDimitry Andric MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 1045ffd83dbSDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind)); 1055ffd83dbSDimitry Andric return 0; 1065ffd83dbSDimitry Andric } 1075ffd83dbSDimitry Andric 1085ffd83dbSDimitry Andric int64_t Res; 1095ffd83dbSDimitry Andric if (Expr->evaluateAsAbsolute(Res)) 1105ffd83dbSDimitry Andric return Res; 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric llvm_unreachable("Unhandled expression!"); 1135ffd83dbSDimitry Andric return 0; 1145ffd83dbSDimitry Andric } 1155ffd83dbSDimitry Andric 1165ffd83dbSDimitry Andric uint64_t 1175ffd83dbSDimitry Andric VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 1185ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1195ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 1205ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1215ffd83dbSDimitry Andric if (MO.isReg() || MO.isImm()) 1225ffd83dbSDimitry Andric return getMachineOpValue(MI, MO, Fixups, STI); 1235ffd83dbSDimitry Andric 1245ffd83dbSDimitry Andric Fixups.push_back( 1250eae32dcSDimitry Andric MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_srel32)); 1265ffd83dbSDimitry Andric return 0; 1275ffd83dbSDimitry Andric } 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo, 1305ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1315ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 1325ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1335ffd83dbSDimitry Andric if (MO.isImm()) 1345ffd83dbSDimitry Andric return VECondCodeToVal( 1355ffd83dbSDimitry Andric static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI))); 1365ffd83dbSDimitry Andric return 0; 1375ffd83dbSDimitry Andric } 1385ffd83dbSDimitry Andric 1395ffd83dbSDimitry Andric uint64_t VEMCCodeEmitter::getRDOpValue(const MCInst &MI, unsigned OpNo, 1405ffd83dbSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 1415ffd83dbSDimitry Andric const MCSubtargetInfo &STI) const { 1425ffd83dbSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo); 1435ffd83dbSDimitry Andric if (MO.isImm()) 1445ffd83dbSDimitry Andric return VERDToVal(static_cast<VERD::RoundingMode>( 1455ffd83dbSDimitry Andric getMachineOpValue(MI, MO, Fixups, STI))); 1465ffd83dbSDimitry Andric return 0; 1475ffd83dbSDimitry Andric } 1485ffd83dbSDimitry Andric 1495ffd83dbSDimitry Andric #include "VEGenMCCodeEmitter.inc" 1505ffd83dbSDimitry Andric 1515ffd83dbSDimitry Andric MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, 1525ffd83dbSDimitry Andric MCContext &Ctx) { 1535ffd83dbSDimitry Andric return new VEMCCodeEmitter(MCII, Ctx); 1545ffd83dbSDimitry Andric } 155