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 "CSKYMCAsmInfo.h" 14 #include "MCTargetDesc/CSKYFixupKinds.h" 15 #include "MCTargetDesc/CSKYMCAsmInfo.h" 16 #include "MCTargetDesc/CSKYMCTargetDesc.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/MC/MCCodeEmitter.h" 19 #include "llvm/MC/MCContext.h" 20 #include "llvm/MC/MCInstBuilder.h" 21 #include "llvm/MC/MCInstrInfo.h" 22 #include "llvm/MC/MCRegisterInfo.h" 23 #include "llvm/MC/MCSubtargetInfo.h" 24 #include "llvm/Support/Casting.h" 25 #include "llvm/Support/EndianStream.h" 26 27 using namespace llvm; 28 29 #define DEBUG_TYPE "csky-mccode-emitter" 30 31 STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); 32 33 static void addFixup(SmallVectorImpl<MCFixup> &Fixups, uint32_t Offset, 34 const MCExpr *Value, uint16_t Kind) { 35 bool PCRel = false; 36 switch (Kind) { 37 case CSKY::Fixups::fixup_csky_pcrel_imm16_scale2: 38 case CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4: 39 case CSKY::Fixups::fixup_csky_pcrel_imm26_scale2: 40 case CSKY::Fixups::fixup_csky_pcrel_imm18_scale2: 41 case CSKY::Fixups::fixup_csky_gotpc: 42 case CSKY::Fixups::fixup_csky_pcrel_imm10_scale2: 43 case CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4: 44 case CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4: 45 PCRel = true; 46 } 47 Fixups.push_back(MCFixup::create(Offset, Value, Kind, PCRel)); 48 } 49 50 namespace { 51 class CSKYMCCodeEmitter : public MCCodeEmitter { 52 MCContext &Ctx; 53 const MCInstrInfo &MII; 54 55 public: 56 CSKYMCCodeEmitter(MCContext &Ctx, const MCInstrInfo &MII) 57 : Ctx(Ctx), MII(MII) {} 58 59 ~CSKYMCCodeEmitter() {} 60 61 void encodeInstruction(const MCInst &Inst, SmallVectorImpl<char> &CB, 62 SmallVectorImpl<MCFixup> &Fixups, 63 const MCSubtargetInfo &STI) const override; 64 65 // Generated by tablegen. 66 uint64_t getBinaryCodeForInstr(const MCInst &MI, 67 SmallVectorImpl<MCFixup> &Fixups, 68 const MCSubtargetInfo &STI) const; 69 70 // Default encoding method used by tablegen. 71 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 72 SmallVectorImpl<MCFixup> &Fixups, 73 const MCSubtargetInfo &STI) const; 74 75 template <int shift = 0> 76 unsigned getImmOpValue(const MCInst &MI, unsigned Idx, 77 SmallVectorImpl<MCFixup> &Fixups, 78 const MCSubtargetInfo &STI) const { 79 const MCOperand &MO = MI.getOperand(Idx); 80 if (MO.isImm()) 81 return (MO.getImm() >> shift); 82 83 assert(MO.isExpr() && "Unexpected MO type."); 84 85 MCFixupKind Kind = getTargetFixup(MO.getExpr()); 86 addFixup(Fixups, 0, MO.getExpr(), Kind); 87 return 0; 88 } 89 90 unsigned getRegSeqImmOpValue(const MCInst &MI, unsigned Idx, 91 SmallVectorImpl<MCFixup> &Fixups, 92 const MCSubtargetInfo &STI) const; 93 94 unsigned getRegisterSeqOpValue(const MCInst &MI, unsigned Op, 95 SmallVectorImpl<MCFixup> &Fixups, 96 const MCSubtargetInfo &STI) const; 97 98 unsigned getOImmOpValue(const MCInst &MI, unsigned Idx, 99 SmallVectorImpl<MCFixup> &Fixups, 100 const MCSubtargetInfo &STI) const; 101 102 unsigned getImmOpValueIDLY(const MCInst &MI, unsigned Idx, 103 SmallVectorImpl<MCFixup> &Fixups, 104 const MCSubtargetInfo &STI) const; 105 106 unsigned getImmJMPIX(const MCInst &MI, unsigned Idx, 107 SmallVectorImpl<MCFixup> &Fixups, 108 const MCSubtargetInfo &STI) const; 109 110 unsigned getImmOpValueMSBSize(const MCInst &MI, unsigned Idx, 111 SmallVectorImpl<MCFixup> &Fixups, 112 const MCSubtargetInfo &STI) const; 113 114 unsigned getImmShiftOpValue(const MCInst &MI, unsigned Idx, 115 SmallVectorImpl<MCFixup> &Fixups, 116 const MCSubtargetInfo &STI) const { 117 const MCOperand &MO = MI.getOperand(Idx); 118 assert(MO.isImm() && "Unexpected MO type."); 119 return 1 << MO.getImm(); 120 } 121 122 MCFixupKind getTargetFixup(const MCExpr *Expr) const; 123 124 template <llvm::CSKY::Fixups FIXUP> 125 unsigned getBranchSymbolOpValue(const MCInst &MI, unsigned Idx, 126 SmallVectorImpl<MCFixup> &Fixups, 127 const MCSubtargetInfo &STI) const { 128 const MCOperand &MO = MI.getOperand(Idx); 129 130 if (MO.isImm()) 131 return MO.getImm() >> 1; 132 133 assert(MO.isExpr() && "Unexpected MO type."); 134 135 MCFixupKind Kind = MCFixupKind(FIXUP); 136 if (MO.getExpr()->getKind() == MCExpr::Specifier) 137 Kind = getTargetFixup(MO.getExpr()); 138 139 addFixup(Fixups, 0, MO.getExpr(), Kind); 140 return 0; 141 } 142 143 template <llvm::CSKY::Fixups FIXUP> 144 unsigned getConstpoolSymbolOpValue(const MCInst &MI, unsigned Idx, 145 SmallVectorImpl<MCFixup> &Fixups, 146 const MCSubtargetInfo &STI) const { 147 const MCOperand &MO = MI.getOperand(Idx); 148 assert(MO.isExpr() && "Unexpected MO type."); 149 150 MCFixupKind Kind = MCFixupKind(FIXUP); 151 if (MO.getExpr()->getKind() == MCExpr::Specifier) 152 Kind = getTargetFixup(MO.getExpr()); 153 154 addFixup(Fixups, 0, MO.getExpr(), Kind); 155 return 0; 156 } 157 158 template <llvm::CSKY::Fixups FIXUP> 159 unsigned getDataSymbolOpValue(const MCInst &MI, unsigned Idx, 160 SmallVectorImpl<MCFixup> &Fixups, 161 const MCSubtargetInfo &STI) const { 162 const MCOperand &MO = MI.getOperand(Idx); 163 assert(MO.isExpr() && "Unexpected MO type."); 164 165 MCFixupKind Kind = MCFixupKind(FIXUP); 166 if (MO.getExpr()->getKind() == MCExpr::Specifier) 167 Kind = getTargetFixup(MO.getExpr()); 168 169 addFixup(Fixups, 0, MO.getExpr(), Kind); 170 return 0; 171 } 172 173 unsigned getCallSymbolOpValue(const MCInst &MI, unsigned Idx, 174 SmallVectorImpl<MCFixup> &Fixups, 175 const MCSubtargetInfo &STI) const { 176 const MCOperand &MO = MI.getOperand(Idx); 177 assert(MO.isExpr() && "Unexpected MO type."); 178 179 MCFixupKind Kind = CSKY::fixup_csky_pcrel_imm26_scale2; 180 if (MO.getExpr()->getKind() == MCExpr::Specifier) 181 Kind = getTargetFixup(MO.getExpr()); 182 183 addFixup(Fixups, 0, MO.getExpr(), Kind); 184 return 0; 185 } 186 187 unsigned getBareSymbolOpValue(const MCInst &MI, unsigned Idx, 188 SmallVectorImpl<MCFixup> &Fixups, 189 const MCSubtargetInfo &STI) const { 190 const MCOperand &MO = MI.getOperand(Idx); 191 assert(MO.isExpr() && "Unexpected MO type."); 192 193 MCFixupKind Kind = CSKY::fixup_csky_pcrel_imm18_scale2; 194 if (MO.getExpr()->getKind() == MCExpr::Specifier) 195 Kind = getTargetFixup(MO.getExpr()); 196 197 addFixup(Fixups, 0, MO.getExpr(), Kind); 198 return 0; 199 } 200 201 void expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB, 202 SmallVectorImpl<MCFixup> &Fixups, 203 const MCSubtargetInfo &STI) const; 204 void expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB, 205 SmallVectorImpl<MCFixup> &Fixups, 206 const MCSubtargetInfo &STI) const; 207 void expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB, 208 SmallVectorImpl<MCFixup> &Fixups, 209 const MCSubtargetInfo &STI) const; 210 }; 211 } // namespace 212 213 unsigned CSKYMCCodeEmitter::getOImmOpValue(const MCInst &MI, unsigned Idx, 214 SmallVectorImpl<MCFixup> &Fixups, 215 const MCSubtargetInfo &STI) const { 216 const MCOperand &MO = MI.getOperand(Idx); 217 assert(MO.isImm() && "Unexpected MO type."); 218 return MO.getImm() - 1; 219 } 220 221 unsigned 222 CSKYMCCodeEmitter::getImmOpValueIDLY(const MCInst &MI, unsigned Idx, 223 SmallVectorImpl<MCFixup> &Fixups, 224 const MCSubtargetInfo &STI) const { 225 const MCOperand &MO = MI.getOperand(Idx); 226 assert(MO.isImm() && "Unexpected MO type."); 227 228 auto V = (MO.getImm() <= 3) ? 4 : MO.getImm(); 229 return V - 1; 230 } 231 232 unsigned 233 CSKYMCCodeEmitter::getImmOpValueMSBSize(const MCInst &MI, unsigned Idx, 234 SmallVectorImpl<MCFixup> &Fixups, 235 const MCSubtargetInfo &STI) const { 236 const MCOperand &MSB = MI.getOperand(Idx); 237 const MCOperand &LSB = MI.getOperand(Idx + 1); 238 assert(MSB.isImm() && LSB.isImm() && "Unexpected MO type."); 239 240 return MSB.getImm() - LSB.getImm(); 241 } 242 243 static void writeData(uint32_t Bin, unsigned Size, SmallVectorImpl<char> &CB) { 244 if (Size == 4) 245 support::endian::write(CB, static_cast<uint16_t>(Bin >> 16), 246 llvm::endianness::little); 247 support::endian::write(CB, static_cast<uint16_t>(Bin), 248 llvm::endianness::little); 249 } 250 251 void CSKYMCCodeEmitter::expandJBTF(const MCInst &MI, SmallVectorImpl<char> &CB, 252 SmallVectorImpl<MCFixup> &Fixups, 253 const MCSubtargetInfo &STI) const { 254 255 MCInst TmpInst; 256 257 uint32_t Binary; 258 259 TmpInst = 260 MCInstBuilder(MI.getOpcode() == CSKY::JBT_E ? CSKY::BF16 : CSKY::BT16) 261 .addOperand(MI.getOperand(0)) 262 .addImm(6); 263 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 264 writeData(Binary, 2, CB); 265 266 if (!STI.hasFeature(CSKY::Has2E3)) 267 TmpInst = MCInstBuilder(CSKY::BR32) 268 .addOperand(MI.getOperand(1)) 269 .addOperand(MI.getOperand(2)); 270 else 271 TmpInst = MCInstBuilder(CSKY::JMPI32).addOperand(MI.getOperand(2)); 272 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 273 Fixups[Fixups.size() - 1].setOffset(2); 274 writeData(Binary, 4, CB); 275 } 276 277 void CSKYMCCodeEmitter::expandNEG(const MCInst &MI, SmallVectorImpl<char> &CB, 278 SmallVectorImpl<MCFixup> &Fixups, 279 const MCSubtargetInfo &STI) const { 280 281 MCInst TmpInst; 282 uint32_t Binary; 283 unsigned Size = MI.getOpcode() == CSKY::NEG32 ? 4 : 2; 284 285 TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16) 286 .addOperand(MI.getOperand(0)) 287 .addOperand(MI.getOperand(1)); 288 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 289 writeData(Binary, Size, CB); 290 291 TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16) 292 .addOperand(MI.getOperand(0)) 293 .addOperand(MI.getOperand(0)) 294 .addImm(1); 295 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 296 writeData(Binary, Size, CB); 297 } 298 299 void CSKYMCCodeEmitter::expandRSUBI(const MCInst &MI, SmallVectorImpl<char> &CB, 300 SmallVectorImpl<MCFixup> &Fixups, 301 const MCSubtargetInfo &STI) const { 302 303 MCInst TmpInst; 304 uint32_t Binary; 305 unsigned Size = MI.getOpcode() == CSKY::RSUBI32 ? 4 : 2; 306 307 TmpInst = MCInstBuilder(Size == 4 ? CSKY::NOT32 : CSKY::NOT16) 308 .addOperand(MI.getOperand(0)) 309 .addOperand(MI.getOperand(1)); 310 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 311 writeData(Binary, Size, CB); 312 313 TmpInst = MCInstBuilder(Size == 4 ? CSKY::ADDI32 : CSKY::ADDI16) 314 .addOperand(MI.getOperand(0)) 315 .addOperand(MI.getOperand(0)) 316 .addImm(MI.getOperand(2).getImm() + 1); 317 Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); 318 writeData(Binary, Size, CB); 319 } 320 321 void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, 322 SmallVectorImpl<char> &CB, 323 SmallVectorImpl<MCFixup> &Fixups, 324 const MCSubtargetInfo &STI) const { 325 const MCInstrDesc &Desc = MII.get(MI.getOpcode()); 326 unsigned Size = Desc.getSize(); 327 328 MCInst TmpInst; 329 330 switch (MI.getOpcode()) { 331 default: 332 TmpInst = MI; 333 break; 334 case CSKY::JBT_E: 335 case CSKY::JBF_E: 336 expandJBTF(MI, CB, Fixups, STI); 337 MCNumEmitted += 2; 338 return; 339 case CSKY::NEG32: 340 case CSKY::NEG16: 341 expandNEG(MI, CB, Fixups, STI); 342 MCNumEmitted += 2; 343 return; 344 case CSKY::RSUBI32: 345 case CSKY::RSUBI16: 346 expandRSUBI(MI, CB, Fixups, STI); 347 MCNumEmitted += 2; 348 return; 349 case CSKY::JBSR32: 350 TmpInst = MCInstBuilder(CSKY::BSR32).addOperand(MI.getOperand(0)); 351 break; 352 case CSKY::JBR16: 353 TmpInst = MCInstBuilder(CSKY::BR16).addOperand(MI.getOperand(0)); 354 break; 355 case CSKY::JBR32: 356 TmpInst = MCInstBuilder(CSKY::BR32).addOperand(MI.getOperand(0)); 357 break; 358 case CSKY::JBT16: 359 TmpInst = MCInstBuilder(CSKY::BT16) 360 .addOperand(MI.getOperand(0)) 361 .addOperand(MI.getOperand(1)); 362 break; 363 case CSKY::JBT32: 364 TmpInst = MCInstBuilder(CSKY::BT32) 365 .addOperand(MI.getOperand(0)) 366 .addOperand(MI.getOperand(1)); 367 break; 368 case CSKY::JBF16: 369 TmpInst = MCInstBuilder(CSKY::BF16) 370 .addOperand(MI.getOperand(0)) 371 .addOperand(MI.getOperand(1)); 372 break; 373 case CSKY::JBF32: 374 TmpInst = MCInstBuilder(CSKY::BF32) 375 .addOperand(MI.getOperand(0)) 376 .addOperand(MI.getOperand(1)); 377 break; 378 case CSKY::LRW32_Gen: 379 TmpInst = MCInstBuilder(CSKY::LRW32) 380 .addOperand(MI.getOperand(0)) 381 .addOperand(MI.getOperand(2)); 382 break; 383 case CSKY::LRW16_Gen: 384 TmpInst = MCInstBuilder(CSKY::LRW16) 385 .addOperand(MI.getOperand(0)) 386 .addOperand(MI.getOperand(2)); 387 break; 388 case CSKY::CMPLEI32: 389 TmpInst = MCInstBuilder(CSKY::CMPLTI32) 390 .addOperand(MI.getOperand(0)) 391 .addOperand(MI.getOperand(1)) 392 .addImm(MI.getOperand(2).getImm() + 1); 393 break; 394 case CSKY::CMPLEI16: 395 TmpInst = MCInstBuilder(CSKY::CMPLTI16) 396 .addOperand(MI.getOperand(0)) 397 .addOperand(MI.getOperand(1)) 398 .addImm(MI.getOperand(2).getImm() + 1); 399 break; 400 case CSKY::ROTRI32: 401 TmpInst = MCInstBuilder(CSKY::ROTLI32) 402 .addOperand(MI.getOperand(0)) 403 .addOperand(MI.getOperand(1)) 404 .addImm(32 - MI.getOperand(2).getImm()); 405 break; 406 case CSKY::BGENI: 407 auto V = 1 << MI.getOperand(1).getImm(); 408 TmpInst = 409 MCInstBuilder(CSKY::MOVI32).addOperand(MI.getOperand(0)).addImm(V); 410 break; 411 } 412 413 ++MCNumEmitted; 414 writeData(getBinaryCodeForInstr(TmpInst, Fixups, STI), Size, CB); 415 } 416 417 unsigned 418 CSKYMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 419 SmallVectorImpl<MCFixup> &Fixups, 420 const MCSubtargetInfo &STI) const { 421 if (MO.isReg()) 422 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 423 424 if (MO.isImm()) 425 return static_cast<unsigned>(MO.getImm()); 426 427 llvm_unreachable("Unhandled expression!"); 428 return 0; 429 } 430 431 unsigned 432 CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx, 433 SmallVectorImpl<MCFixup> &Fixups, 434 const MCSubtargetInfo &STI) const { 435 assert(MI.getOperand(Idx).isReg() && "Unexpected MO type."); 436 assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type."); 437 438 unsigned Ry = MI.getOperand(Idx).getReg(); 439 unsigned Rz = MI.getOperand(Idx + 1).getImm(); 440 441 unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) - 442 Ctx.getRegisterInfo()->getEncodingValue(Ry); 443 444 return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm); 445 } 446 447 unsigned 448 CSKYMCCodeEmitter::getRegisterSeqOpValue(const MCInst &MI, unsigned Op, 449 SmallVectorImpl<MCFixup> &Fixups, 450 const MCSubtargetInfo &STI) const { 451 unsigned Reg1 = 452 Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op).getReg()); 453 unsigned Reg2 = 454 Ctx.getRegisterInfo()->getEncodingValue(MI.getOperand(Op + 1).getReg()); 455 456 unsigned Binary = ((Reg1 & 0x1f) << 5) | (Reg2 - Reg1); 457 458 return Binary; 459 } 460 461 unsigned CSKYMCCodeEmitter::getImmJMPIX(const MCInst &MI, unsigned Idx, 462 SmallVectorImpl<MCFixup> &Fixups, 463 const MCSubtargetInfo &STI) const { 464 switch (MI.getOperand(Idx).getImm()) { 465 default: 466 llvm_unreachable("Unhandled jmpix imm!"); 467 case 16: 468 return 0; 469 case 24: 470 return 1; 471 case 32: 472 return 2; 473 case 40: 474 return 3; 475 } 476 } 477 478 MCFixupKind CSKYMCCodeEmitter::getTargetFixup(const MCExpr *Expr) const { 479 const auto *CSKYExpr = cast<MCSpecifierExpr>(Expr); 480 switch (CSKYExpr->getSpecifier()) { 481 default: 482 llvm_unreachable("Unhandled fixup kind!"); 483 case CSKY::S_ADDR: 484 return CSKY::fixup_csky_addr32; 485 case CSKY::S_ADDR_HI16: 486 return CSKY::fixup_csky_addr_hi16; 487 case CSKY::S_ADDR_LO16: 488 return CSKY::fixup_csky_addr_lo16; 489 case CSKY::S_GOT: 490 return CSKY::fixup_csky_got32; 491 case CSKY::S_GOTPC: 492 return CSKY::fixup_csky_gotpc; 493 case CSKY::S_GOTOFF: 494 return CSKY::fixup_csky_gotoff; 495 case CSKY::S_PLT: 496 return CSKY::fixup_csky_plt32; 497 case CSKY::S_PLT_IMM18_BY4: 498 return CSKY::fixup_csky_plt_imm18_scale4; 499 case CSKY::S_GOT_IMM18_BY4: 500 return CSKY::fixup_csky_got_imm18_scale4; 501 } 502 } 503 504 MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII, 505 MCContext &Ctx) { 506 return new CSKYMCCodeEmitter(Ctx, MCII); 507 } 508 509 #include "CSKYGenMCCodeEmitter.inc" 510