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