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, SmallVectorImpl<char> &CB) { 61 if (Size == 4) 62 support::endian::write(CB, static_cast<uint16_t>(Bin >> 16), 63 llvm::endianness::little); 64 support::endian::write(CB, static_cast<uint16_t>(Bin), 65 llvm::endianness::little); 66 } 67 68 void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB, 69 SmallVectorImpl<MCFixup> &Fixups, 70 const MCSubtargetInfo &STI) const { 71 72 MCInst TmpInst; 73 74 uint32_t Binary; 75 76 TmpInst = 77 MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16) 78 .addOperand(MI.getOperand(0)) 79 .addImm(6); 80 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 81 writeData(Binary, 2, CB); 82 83 if (!STI.hasFeature(CSKY::Has2E3)) 84 TmpInst = MCInstBuilder(CSKY::BR32) 85 .addOperand(MI.getOperand(1)) 86 .addOperand(MI.getOperand(2)); 87 else 88 TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2)); 89 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 90 Fixups[Fixups.size() - 1].setOffset(2); 91 writeData(Binary, 4, CB); 92 } 93 94 void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB, 95 SmallVectorImpl<MCFixup> &Fixups, 96 const MCSubtargetInfo &STI) const { 97 98 MCInst TmpInst; 99 uint32_t Binary; 100 unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2; 101 102 TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16) 103 .addOperand(MI.getOperand(0)) 104 .addOperand(MI.getOperand(1)); 105 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 106 writeData(Binary, Size, CB); 107 108 TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16) 109 .addOperand(MI.getOperand(0)) 110 .addOperand(MI.getOperand(0)) 111 .addImm(1); 112 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 113 writeData(Binary, Size, CB); 114 } 115 116 void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB, 117 SmallVectorImpl<MCFixup> &Fixups, 118 const MCSubtargetInfo &STI) const { 119 120 MCInst TmpInst; 121 uint32_t Binary; 122 unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2; 123 124 TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16) 125 .addOperand(MI.getOperand(0)) 126 .addOperand(MI.getOperand(1)); 127 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 128 writeData(Binary, Size, CB); 129 130 TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16) 131 .addOperand(MI.getOperand(0)) 132 .addOperand(MI.getOperand(0)) 133 .addImm(MI.getOperand(2).getImm() + 1); 134 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 135 writeData(Binary, Size, CB); 136 } 137 138 void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, 139 SmallVectorImpl<char> &CB, 140 SmallVectorImpl<MCFixup> &Fixups, 141 const MCSubtargetInfo &STI) const { 142 const MCInstrDesc &Desc = MII.get(MI.getOpcode()); 143 unsigned Size = Desc.getSize(); 144 145 MCInst TmpInst; 146 147 switch (MI.getOpcode()) { 148 default: 149 TmpInst = MI; 150 break; 151 case CSKY::JBT_E: 152 case CSKY::JBF_E: 153 expandJBTF(MI, CB, Fixups, STI); 154 MCNumEmitted += 2; 155 return; 156 case CSKY::NEG32: 157 case CSKY::NEG16: 158 expandNEG(MI, CB, Fixups, STI); 159 MCNumEmitted += 2; 160 return; 161 case CSKY::RSUBI32: 162 case CSKY::RSUBI16: 163 expandRSUBI(MI, CB, Fixups, STI); 164 MCNumEmitted += 2; 165 return; 166 case CSKY::JBSR32: 167 TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0)); 168 break; 169 case CSKY::JBR16: 170 TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0)); 171 break; 172 case CSKY::JBR32: 173 TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0)); 174 break; 175 case CSKY::JBT16: 176 TmpInst = MCInstBuilder(CSKY::BT16) 177 .addOperand(MI.getOperand(0)) 178 .addOperand(MI.getOperand(1)); 179 break; 180 case CSKY::JBT32: 181 TmpInst = MCInstBuilder(CSKY::BT32) 182 .addOperand(MI.getOperand(0)) 183 .addOperand(MI.getOperand(1)); 184 break; 185 case CSKY::JBF16: 186 TmpInst = MCInstBuilder(CSKY::BF16) 187 .addOperand(MI.getOperand(0)) 188 .addOperand(MI.getOperand(1)); 189 break; 190 case CSKY::JBF32: 191 TmpInst = MCInstBuilder(CSKY::BF32) 192 .addOperand(MI.getOperand(0)) 193 .addOperand(MI.getOperand(1)); 194 break; 195 case CSKY::LRW32_Gen: 196 TmpInst = MCInstBuilder(CSKY::LRW32) 197 .addOperand(MI.getOperand(0)) 198 .addOperand(MI.getOperand(2)); 199 break; 200 case CSKY::LRW16_Gen: 201 TmpInst = MCInstBuilder(CSKY::LRW16) 202 .addOperand(MI.getOperand(0)) 203 .addOperand(MI.getOperand(2)); 204 break; 205 case CSKY::CMPLEI32: 206 TmpInst = MCInstBuilder(CSKY::CMPLTI32) 207 .addOperand(MI.getOperand(0)) 208 .addOperand(MI.getOperand(1)) 209 .addImm(MI.getOperand(2).getImm() + 1); 210 break; 211 case CSKY::CMPLEI16: 212 TmpInst = MCInstBuilder(CSKY::CMPLTI16) 213 .addOperand(MI.getOperand(0)) 214 .addOperand(MI.getOperand(1)) 215 .addImm(MI.getOperand(2).getImm() + 1); 216 break; 217 case CSKY::ROTRI32: 218 TmpInst = MCInstBuilder(CSKY::ROTLI32) 219 .addOperand(MI.getOperand(0)) 220 .addOperand(MI.getOperand(1)) 221 .addImm(32 - MI.getOperand(2).getImm()); 222 break; 223 case CSKY::BGENI: 224 auto V = 1 << MI.getOperand(1).getImm(); 225 TmpInst = 226 MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V); 227 break; 228 } 229 230 ++MCNumEmitted; 231 writeData(getBinaryCodeForInstr(TmpInst, Fixups, STI), Size, CB); 232 } 233 234 unsigned 235 CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 236 SmallVectorImpl<MCFixup> &Fixups, 237 const MCSubtargetInfo &STI) const { 238 if (MO.isReg()) 239 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 240 241 if (MO.isImm()) 242 return static_cast<unsigned>(MO.getImm()); 243 244 llvm_unreachable("Unhandled expression!"); 245 return 0; 246 } 247 248 unsigned 249 CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx, 250 SmallVectorImpl<MCFixup> &Fixups, 251 const MCSubtargetInfo &STI) const { 252 assert(MI.getOperand(Idx).isReg() && "Unexpected MO type."); 253 assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type."); 254 255 unsigned Ry = MI.getOperand(Idx).getReg(); 256 unsigned Rz = MI.getOperand(Idx + 1).getImm(); 257 258 unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) - 259 Ctx.getRegisterInfo()->getEncodingValue(Ry); 260 261 return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm); 262 } 263 264 unsigned 265 CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op, 266 SmallVectorImpl<MCFixup> &Fixups, 267 const MCSubtargetInfo &STI) const { 268 unsigned Reg1 = 269 Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg()); 270 unsigned Reg2 = 271 Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg()); 272 273 unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1); 274 275 return Binary; 276 } 277 278 unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx, 279 SmallVectorImpl<MCFixup> &Fixups, 280 const MCSubtargetInfo &STI) const { 281 if (MI.getOperand(Idx).getImm() == 16) 282 return 0; 283 else if (MI.getOperand(Idx).getImm() == 24) 284 return 1; 285 else if (MI.getOperand(Idx).getImm() == 32) 286 return 2; 287 else if (MI.getOperand(Idx).getImm() == 40) 288 return 3; 289 else 290 assert(0); 291 } 292 293 MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const { 294 const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Expr); 295 296 switch (CSKYExpr->getKind()) { 297 default: 298 llvm_unreachable("Unhandled fixup kind!"); 299 case CSKYMCExpr::VK_CSKY_ADDR: 300 return MCFixupKind(CSKY::fixup_csky_addr32); 301 case CSKYMCExpr::VK_CSKY_ADDR_HI16: 302 return MCFixupKind(CSKY::fixup_csky_addr_hi16); 303 case CSKYMCExpr::VK_CSKY_ADDR_LO16: 304 return MCFixupKind(CSKY::fixup_csky_addr_lo16); 305 case CSKYMCExpr::VK_CSKY_GOT: 306 return MCFixupKind(CSKY::fixup_csky_got32); 307 case CSKYMCExpr::VK_CSKY_GOTPC: 308 return MCFixupKind(CSKY::fixup_csky_gotpc); 309 case CSKYMCExpr::VK_CSKY_GOTOFF: 310 return MCFixupKind(CSKY::fixup_csky_gotoff); 311 case CSKYMCExpr::VK_CSKY_PLT: 312 return MCFixupKind(CSKY::fixup_csky_plt32); 313 case CSKYMCExpr::VK_CSKY_PLT_IMM18_BY4: 314 return MCFixupKind(CSKY::fixup_csky_plt_imm18_scale4); 315 case CSKYMCExpr::VK_CSKY_GOT_IMM18_BY4: 316 return MCFixupKind(CSKY::fixup_csky_got_imm18_scale4); 317 } 318 } 319 320 MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII, 321 MCContext &Ctx) { 322 return new CSKYMCCodeEmitter(Ctx, MCII); 323 } 324 325 #include "CSKYGenMCCodeEmitter.inc" 326