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 MCContext &Ctx; 43 44 public: 45 VEMCCodeEmitter(const MCInstrInfo &, MCContext &ctx) 46 : Ctx(ctx) {} 47 VEMCCodeEmitter(const VEMCCodeEmitter &) = delete; 48 VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete; 49 ~VEMCCodeEmitter() override = default; 50 51 void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB, 52 SmallVectorImpl<MCFixup> &Fixups, 53 const MCSubtargetInfo &STI) const override; 54 55 // getBinaryCodeForInstr - TableGen'erated function for getting the 56 // binary encoding for an instruction. 57 uint64_t getBinaryCodeForInstr(const MCInst &MI, 58 SmallVectorImpl<MCFixup> &Fixups, 59 const MCSubtargetInfo &STI) const; 60 61 /// getMachineOpValue - Return binary encoding of operand. If the machine 62 /// operand requires relocation, record the relocation and return zero. 63 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 64 SmallVectorImpl<MCFixup> &Fixups, 65 const MCSubtargetInfo &STI) const; 66 67 uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 68 SmallVectorImpl<MCFixup> &Fixups, 69 const MCSubtargetInfo &STI) const; 70 uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo, 71 SmallVectorImpl<MCFixup> &Fixups, 72 const MCSubtargetInfo &STI) const; 73 uint64_t getRDOpValue(const MCInst &MI, unsigned OpNo, 74 SmallVectorImpl<MCFixup> &Fixups, 75 const MCSubtargetInfo &STI) const; 76 }; 77 78 } // end anonymous namespace 79 80 void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, 81 SmallVectorImpl<char> &CB, 82 SmallVectorImpl<MCFixup> &Fixups, 83 const MCSubtargetInfo &STI) const { 84 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 85 support::endian::write<uint64_t>(CB, Bits, llvm::endianness::little); 86 87 ++MCNumEmitted; // Keep track of the # of mi's emitted. 88 } 89 90 unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI, 91 const MCOperand &MO, 92 SmallVectorImpl<MCFixup> &Fixups, 93 const MCSubtargetInfo &STI) const { 94 if (MO.isReg()) 95 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 96 if (MO.isImm()) 97 return static_cast<unsigned>(MO.getImm()); 98 99 assert(MO.isExpr()); 100 101 const MCExpr *Expr = MO.getExpr(); 102 if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Expr)) { 103 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 104 Fixups.push_back(MCFixup::create(0, Expr, Kind)); 105 return 0; 106 } 107 108 int64_t Res; 109 if (Expr->evaluateAsAbsolute(Res)) 110 return Res; 111 112 llvm_unreachable("Unhandled expression!"); 113 return 0; 114 } 115 116 uint64_t 117 VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 118 SmallVectorImpl<MCFixup> &Fixups, 119 const MCSubtargetInfo &STI) const { 120 const MCOperand &MO = MI.getOperand(OpNo); 121 if (MO.isReg() || MO.isImm()) 122 return getMachineOpValue(MI, MO, Fixups, STI); 123 124 Fixups.push_back( 125 MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_srel32)); 126 return 0; 127 } 128 129 uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo, 130 SmallVectorImpl<MCFixup> &Fixups, 131 const MCSubtargetInfo &STI) const { 132 const MCOperand &MO = MI.getOperand(OpNo); 133 if (MO.isImm()) 134 return VECondCodeToVal( 135 static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI))); 136 return 0; 137 } 138 139 uint64_t VEMCCodeEmitter::getRDOpValue(const MCInst &MI, unsigned OpNo, 140 SmallVectorImpl<MCFixup> &Fixups, 141 const MCSubtargetInfo &STI) const { 142 const MCOperand &MO = MI.getOperand(OpNo); 143 if (MO.isImm()) 144 return VERDToVal(static_cast<VERD::RoundingMode>( 145 getMachineOpValue(MI, MO, Fixups, STI))); 146 return 0; 147 } 148 149 #include "VEGenMCCodeEmitter.inc" 150 151 MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, 152 MCContext &Ctx) { 153 return new VEMCCodeEmitter(MCII, Ctx); 154 } 155