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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the VEMCCodeEmitter class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/VEFixupKinds.h" 14 #include "VE.h" 15 #include "VEMCExpr.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 "llvm/Support/ErrorHandling.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <cassert> 31 #include <cstdint> 32 33 using namespace llvm; 34 35 #define DEBUG_TYPE "mccodeemitter" 36 37 STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 38 39 namespace { 40 41 class VEMCCodeEmitter : public MCCodeEmitter { 42 const MCInstrInfo &MCII; 43 MCContext &Ctx; 44 45 public: 46 VEMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) 47 : MCII(mcii), Ctx(ctx) {} 48 VEMCCodeEmitter(const VEMCCodeEmitter &) = delete; 49 VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete; 50 ~VEMCCodeEmitter() override = default; 51 52 void encodeInstruction(const MCInst &MI, raw_ostream &OS, 53 SmallVectorImpl<MCFixup> &Fixups, 54 const MCSubtargetInfo &STI) const override; 55 56 // getBinaryCodeForInstr - TableGen'erated function for getting the 57 // binary encoding for an instruction. 58 uint64_t getBinaryCodeForInstr(const MCInst &MI, 59 SmallVectorImpl<MCFixup> &Fixups, 60 const MCSubtargetInfo &STI) const; 61 62 /// getMachineOpValue - Return binary encoding of operand. If the machine 63 /// operand requires relocation, record the relocation and return zero. 64 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 65 SmallVectorImpl<MCFixup> &Fixups, 66 const MCSubtargetInfo &STI) const; 67 68 uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 69 SmallVectorImpl<MCFixup> &Fixups, 70 const MCSubtargetInfo &STI) const; 71 uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo, 72 SmallVectorImpl<MCFixup> &Fixups, 73 const MCSubtargetInfo &STI) const; 74 uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo, 75 SmallVectorImpl<MCFixup> &Fixups, 76 const MCSubtargetInfo &STI) const; 77 78 private: 79 FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const; 80 void 81 verifyInstructionPredicates(const MCInst &MI, 82 const FeatureBitset &AvailableFeatures) const; 83 }; 84 85 } // end anonymous namespace 86 87 void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 88 SmallVectorImpl<MCFixup> &Fixups, 89 const MCSubtargetInfo &STI) const { 90 verifyInstructionPredicates(MI, 91 computeAvailableFeatures(STI.getFeatureBits())); 92 93 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 94 support::endian::write<uint64_t>(OS, Bits, support::little); 95 96 ++MCNumEmitted; // Keep track of the # of mi's emitted. 97 } 98 99 unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI, 100 const MCOperand &MO, 101 SmallVectorImpl<MCFixup> &Fixups, 102 const MCSubtargetInfo &STI) const { 103 if (MO.isReg()) 104 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 105 106 if (MO.isImm()) 107 return MO.getImm(); 108 109 assert(MO.isExpr()); 110 const MCExpr *Expr = MO.getExpr(); 111 if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Expr)) { 112 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 113 Fixups.push_back(MCFixup::create(0, Expr, Kind)); 114 return 0; 115 } 116 117 int64_t Res; 118 if (Expr->evaluateAsAbsolute(Res)) 119 return Res; 120 121 llvm_unreachable("Unhandled expression!"); 122 return 0; 123 } 124 125 uint64_t 126 VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 127 SmallVectorImpl<MCFixup> &Fixups, 128 const MCSubtargetInfo &STI) const { 129 const MCOperand &MO = MI.getOperand(OpNo); 130 if (MO.isReg() || MO.isImm()) 131 return getMachineOpValue(MI, MO, Fixups, STI); 132 133 Fixups.push_back( 134 MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_pc_lo32)); 135 return 0; 136 } 137 138 uint64_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 148 uint64_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 #define ENABLE_INSTR_PREDICATE_VERIFIER 159 #include "VEGenMCCodeEmitter.inc" 160 161 MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, 162 const MCRegisterInfo &MRI, 163 MCContext &Ctx) { 164 return new VEMCCodeEmitter(MCII, Ctx); 165 } 166