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