1 //===-- CSKYMCCodeEmitter.cpp - CSKY Code Emitter interface ---------------===// 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 CSKYMCCodeEmitter class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CSKYMCCodeEmitter.h" 14 #include "CSKYMCExpr.h" 15 #include "MCTargetDesc/CSKYMCTargetDesc.h" 16 #include "llvm/ADT/Statistic.h" 17 #include "llvm/MC/MCInstBuilder.h" 18 #include "llvm/MC/MCInstrInfo.h" 19 #include "llvm/MC/MCRegisterInfo.h" 20 #include "llvm/MC/MCSubtargetInfo.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/EndianStream.h" 23 24 using namespace llvm; 25 26 #define DEBUG_TYPE "csky-mccode-emitter" 27 28 STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 29 30 unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx, 31 SmallVectorImpl<MCFixup> &Fixups, 32 const MCSubtargetInfo &STI) const { 33 const MCOperand &MO = MI.getOperand(Idx); 34 assert(MO.isImm() && "Unexpected MO type."); 35 return MO.getImm() - 1; 36 } 37 38 unsigned 39 CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx, 40 SmallVectorImpl<MCFixup> &Fixups, 41 const MCSubtargetInfo &STI) const { 42 const MCOperand &MO = MI.getOperand(Idx); 43 assert(MO.isImm() && "Unexpected MO type."); 44 45 auto V = (MO.getImm() <= 3) ? 4 : MO.getImm(); 46 return V - 1; 47 } 48 49 unsigned 50 CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx, 51 SmallVectorImpl<MCFixup> &Fixups, 52 const MCSubtargetInfo &STI) const { 53 const MCOperand &MSB = MI.getOperand(Idx); 54 const MCOperand &LSB = MI.getOperand(Idx + 1); 55 assert(MSB.isImm() && LSB.isImm() && "Unexpected MO type."); 56 57 return MSB.getImm() - LSB.getImm(); 58 } 59 60 static void writeData(uint32_t Bin, unsigned Size, raw_ostream &OS) { 61 uint16_t LO16 = static_cast<uint16_t>(Bin); 62 uint16_t HI16 = static_cast<uint16_t>(Bin >> 16); 63 64 if (Size == 4) 65 support::endian::write<uint16_t>(OS, HI16, support::little); 66 67 support::endian::write<uint16_t>(OS, LO16, support::little); 68 } 69 70 void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, 71 SmallVectorImpl<MCFixup> &Fixups, 72 const MCSubtargetInfo &STI) const { 73 const MCInstrDesc &Desc = MII.get(MI.getOpcode()); 74 unsigned Size = Desc.getSize(); 75 76 ++MCNumEmitted; 77 78 uint32_t Bin = getBinaryCodeForInstr(MI, Fixups, STI); 79 80 uint16_t LO16 = static_cast<uint16_t>(Bin); 81 uint16_t HI16 = static_cast<uint16_t>(Bin >> 16); 82 83 if (Size == 4) 84 support::endian::write<uint16_t>(OS, HI16, support::little); 85 86 support::endian::write<uint16_t>(OS, LO16, support::little); 87 } 88 89 unsigned 90 CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 91 SmallVectorImpl<MCFixup> &Fixups, 92 const MCSubtargetInfo &STI) const { 93 if (MO.isReg()) 94 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 95 96 if (MO.isImm()) 97 return static_cast<unsigned>(MO.getImm()); 98 99 llvm_unreachable("Unhandled expression!"); 100 return 0; 101 } 102 103 unsigned 104 CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx, 105 SmallVectorImpl<MCFixup> &Fixups, 106 const MCSubtargetInfo &STI) const { 107 assert(MI.getOperand(Idx).isReg() && "Unexpected MO type."); 108 assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type."); 109 110 unsigned Ry = MI.getOperand(Idx).getReg(); 111 unsigned Rz = MI.getOperand(Idx + 1).getImm(); 112 113 unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) - 114 Ctx.getRegisterInfo()->getEncodingValue(Ry); 115 116 return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm); 117 } 118 119 unsigned 120 CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op, 121 SmallVectorImpl<MCFixup> &Fixups, 122 const MCSubtargetInfo &STI) const { 123 unsigned Reg1 = 124 Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg()); 125 unsigned Reg2 = 126 Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg()); 127 128 unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1); 129 130 return Binary; 131 } 132 133 unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx, 134 SmallVectorImpl<MCFixup> &Fixups, 135 const MCSubtargetInfo &STI) const { 136 if (MI.getOperand(Idx).getImm() == 16) 137 return 0; 138 else if (MI.getOperand(Idx).getImm() == 24) 139 return 1; 140 else if (MI.getOperand(Idx).getImm() == 32) 141 return 2; 142 else if (MI.getOperand(Idx).getImm() == 40) 143 return 3; 144 else 145 assert(0); 146 } 147 148 MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const { 149 const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr); 150 151 switch (CSKYExpr->getKind()) { 152 default: 153 llvm_unreachable("Unhandled fixup kind!"); 154 case CSKYMCExpr::VK_CSKY_ADDR: 155 return MCFixupKind(CSKY::fixup_csky_addr32); 156 case CSKYMCExpr::VK_CSKY_ADDR_HI16: 157 return MCFixupKind(CSKY::fixup_csky_addr_hi16); 158 case CSKYMCExpr::VK_CSKY_ADDR_LO16: 159 return MCFixupKind(CSKY::fixup_csky_addr_lo16); 160 case CSKYMCExpr::VK_CSKY_GOT: 161 return MCFixupKind(CSKY::fixup_csky_got32); 162 case CSKYMCExpr::VK_CSKY_GOTPC: 163 return MCFixupKind(CSKY::fixup_csky_gotpc); 164 case CSKYMCExpr::VK_CSKY_GOTOFF: 165 return MCFixupKind(CSKY::fixup_csky_gotoff); 166 case CSKYMCExpr::VK_CSKY_PLT: 167 return MCFixupKind(CSKY::fixup_csky_plt32); 168 case CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4: 169 return MCFixupKind(CSKY::fixup_csky_plt_imm18_scale4); 170 case CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4: 171 return MCFixupKind(CSKY::fixup_csky_got_imm18_scale4); 172 } 173 } 174 175 MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII, 176 MCContext &Ctx) { 177 return new CSKYMCCodeEmitter(Ctx, MCII); 178 } 179 180 #include "CSKYGenMCCodeEmitter.inc" 181