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, raw_ostream &OS, 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, raw_ostream &OS, 81 SmallVectorImpl<MCFixup> &Fixups, 82 const MCSubtargetInfo &STI) const { 83 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 84 support::endian::write<uint64_t>(OS, Bits, support::little); 85 86 ++MCNumEmitted; // Keep track of the # of mi's emitted. 87 } 88 89 unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI, 90 const MCOperand &MO, 91 SmallVectorImpl<MCFixup> &Fixups, 92 const MCSubtargetInfo &STI) const { 93 if (MO.isReg()) 94 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 95 if (MO.isImm()) 96 return static_cast<unsigned>(MO.getImm()); 97 98 assert(MO.isExpr()); 99 100 const MCExpr *Expr = MO.getExpr(); 101 if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Expr)) { 102 MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); 103 Fixups.push_back(MCFixup::create(0, Expr, Kind)); 104 return 0; 105 } 106 107 int64_t Res; 108 if (Expr->evaluateAsAbsolute(Res)) 109 return Res; 110 111 llvm_unreachable("Unhandled expression!"); 112 return 0; 113 } 114 115 uint64_t 116 VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 117 SmallVectorImpl<MCFixup> &Fixups, 118 const MCSubtargetInfo &STI) const { 119 const MCOperand &MO = MI.getOperand(OpNo); 120 if (MO.isReg() || MO.isImm()) 121 return getMachineOpValue(MI, MO, Fixups, STI); 122 123 Fixups.push_back( 124 MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_srel32)); 125 return 0; 126 } 127 128 uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo, 129 SmallVectorImpl<MCFixup> &Fixups, 130 const MCSubtargetInfo &STI) const { 131 const MCOperand &MO = MI.getOperand(OpNo); 132 if (MO.isImm()) 133 return VECondCodeToVal( 134 static_cast<VECC::CondCode>(getMachineOpValue(MI, MO, Fixups, STI))); 135 return 0; 136 } 137 138 uint64_t VEMCCodeEmitter::getRDOpValue(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 VERDToVal(static_cast<VERD::RoundingMode>( 144 getMachineOpValue(MI, MO, Fixups, STI))); 145 return 0; 146 } 147 148 #include "VEGenMCCodeEmitter.inc" 149 150 MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII, 151 MCContext &Ctx) { 152 return new VEMCCodeEmitter(MCII, Ctx); 153 } 154