510 lines · cpp
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-exception6//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 27using namespace llvm;28 29#define DEBUG_TYPE "csky-mccode-emitter"30 31STATISTIC(MCNumEmitted, "Number of MC instructions emitted");32 33static 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 50namespace {51class CSKYMCCodeEmitter : public MCCodeEmitter {52 MCContext &Ctx;53 const MCInstrInfo &MII;54 55public: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} // namespace212 213unsigned 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 221unsigned222CSKYMCCodeEmitter::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 232unsigned233CSKYMCCodeEmitter::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 243static 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 251void 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 else271 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 277void 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 299void 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 321void 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 417unsigned418CSKYMCCodeEmitter::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 431unsigned432CSKYMCCodeEmitter::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 447unsigned448CSKYMCCodeEmitter::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 461unsigned 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 478MCFixupKind 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 504MCCodeEmitter *llvm::createCSKYMCCodeEmitter(const MCInstrInfo &MCII,505 MCContext &Ctx) {506 return new CSKYMCCodeEmitter(Ctx, MCII);507}508 509#include "CSKYGenMCCodeEmitter.inc"510