1 //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch 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 LoongArchMCCodeEmitter class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/LoongArchBaseInfo.h" 14 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 15 #include "llvm/MC/MCCodeEmitter.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCInstBuilder.h" 18 #include "llvm/MC/MCInstrInfo.h" 19 #include "llvm/MC/MCRegisterInfo.h" 20 #include "llvm/Support/EndianStream.h" 21 22 using namespace llvm; 23 24 #define DEBUG_TYPE "mccodeemitter" 25 26 namespace { 27 class LoongArchMCCodeEmitter : public MCCodeEmitter { 28 LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; 29 void operator=(const LoongArchMCCodeEmitter &) = delete; 30 MCContext &Ctx; 31 MCInstrInfo const &MCII; 32 33 public: 34 LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 35 : Ctx(ctx), MCII(MCII) {} 36 37 ~LoongArchMCCodeEmitter() override {} 38 39 void encodeInstruction(const MCInst &MI, raw_ostream &OS, 40 SmallVectorImpl<MCFixup> &Fixups, 41 const MCSubtargetInfo &STI) const override; 42 43 /// TableGen'erated function for getting the binary encoding for an 44 /// instruction. 45 uint64_t getBinaryCodeForInstr(const MCInst &MI, 46 SmallVectorImpl<MCFixup> &Fixups, 47 const MCSubtargetInfo &STI) const; 48 49 /// Return binary encoding of operand. If the machine operand requires 50 /// relocation, record the relocation and return zero. 51 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 52 SmallVectorImpl<MCFixup> &Fixups, 53 const MCSubtargetInfo &STI) const; 54 55 /// Return binary encoding of an immediate operand specified by OpNo. 56 /// The value returned is the value of the immediate minus 1. 57 /// Note that this function is dedicated to specific immediate types, 58 /// e.g. uimm2_plus1. 59 unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 60 SmallVectorImpl<MCFixup> &Fixups, 61 const MCSubtargetInfo &STI) const; 62 63 /// Return binary encoding of an immediate operand specified by OpNo. 64 /// The value returned is the value of the immediate shifted right 65 // arithmetically by 2. 66 /// Note that this function is dedicated to specific immediate types, 67 /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. 68 unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, 69 SmallVectorImpl<MCFixup> &Fixups, 70 const MCSubtargetInfo &STI) const; 71 }; 72 } // end namespace 73 74 unsigned 75 LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 76 SmallVectorImpl<MCFixup> &Fixups, 77 const MCSubtargetInfo &STI) const { 78 79 if (MO.isReg()) 80 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 81 82 if (MO.isImm()) 83 return static_cast<unsigned>(MO.getImm()); 84 85 llvm_unreachable("Unhandled expression!"); 86 } 87 88 unsigned 89 LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 90 SmallVectorImpl<MCFixup> &Fixups, 91 const MCSubtargetInfo &STI) const { 92 return MI.getOperand(OpNo).getImm() - 1; 93 } 94 95 unsigned 96 LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, 97 SmallVectorImpl<MCFixup> &Fixups, 98 const MCSubtargetInfo &STI) const { 99 unsigned Res = MI.getOperand(OpNo).getImm(); 100 assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); 101 return Res >> 2; 102 } 103 104 void LoongArchMCCodeEmitter::encodeInstruction( 105 const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, 106 const MCSubtargetInfo &STI) const { 107 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 108 // Get byte count of instruction. 109 unsigned Size = Desc.getSize(); 110 111 switch (Size) { 112 default: 113 llvm_unreachable("Unhandled encodeInstruction length!"); 114 case 4: { 115 uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 116 support::endian::write(OS, Bits, support::little); 117 break; 118 } 119 } 120 } 121 122 MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, 123 MCContext &Ctx) { 124 return new LoongArchMCCodeEmitter(Ctx, MCII); 125 } 126 127 #include "LoongArchGenMCCodeEmitter.inc" 128