181ad6265SDimitry Andric //=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // This file implements the LoongArchMCCodeEmitter class. 1081ad6265SDimitry Andric // 1181ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h" 1481ad6265SDimitry Andric #include "MCTargetDesc/LoongArchMCTargetDesc.h" 1581ad6265SDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 1681ad6265SDimitry Andric #include "llvm/MC/MCContext.h" 1781ad6265SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 1881ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h" 1981ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 2081ad6265SDimitry Andric #include "llvm/Support/EndianStream.h" 2181ad6265SDimitry Andric 2281ad6265SDimitry Andric using namespace llvm; 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric #define DEBUG_TYPE "mccodeemitter" 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric namespace { 2781ad6265SDimitry Andric class LoongArchMCCodeEmitter : public MCCodeEmitter { 2881ad6265SDimitry Andric LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete; 2981ad6265SDimitry Andric void operator=(const LoongArchMCCodeEmitter &) = delete; 3081ad6265SDimitry Andric MCContext &Ctx; 3181ad6265SDimitry Andric MCInstrInfo const &MCII; 3281ad6265SDimitry Andric 3381ad6265SDimitry Andric public: 3481ad6265SDimitry Andric LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) 3581ad6265SDimitry Andric : Ctx(ctx), MCII(MCII) {} 3681ad6265SDimitry Andric 3781ad6265SDimitry Andric ~LoongArchMCCodeEmitter() override {} 3881ad6265SDimitry Andric 3981ad6265SDimitry Andric void encodeInstruction(const MCInst &MI, raw_ostream &OS, 4081ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4181ad6265SDimitry Andric const MCSubtargetInfo &STI) const override; 4281ad6265SDimitry Andric 4381ad6265SDimitry Andric /// TableGen'erated function for getting the binary encoding for an 4481ad6265SDimitry Andric /// instruction. 4581ad6265SDimitry Andric uint64_t getBinaryCodeForInstr(const MCInst &MI, 4681ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 4781ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric /// Return binary encoding of operand. If the machine operand requires 5081ad6265SDimitry Andric /// relocation, record the relocation and return zero. 5181ad6265SDimitry Andric unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, 5281ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 5381ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric /// Return binary encoding of an immediate operand specified by OpNo. 5681ad6265SDimitry Andric /// The value returned is the value of the immediate minus 1. 5781ad6265SDimitry Andric /// Note that this function is dedicated to specific immediate types, 5881ad6265SDimitry Andric /// e.g. uimm2_plus1. 5981ad6265SDimitry Andric unsigned getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 6081ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 6181ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 6281ad6265SDimitry Andric 6381ad6265SDimitry Andric /// Return binary encoding of an immediate operand specified by OpNo. 6481ad6265SDimitry Andric /// The value returned is the value of the immediate shifted right 6581ad6265SDimitry Andric // arithmetically by 2. 6681ad6265SDimitry Andric /// Note that this function is dedicated to specific immediate types, 6781ad6265SDimitry Andric /// e.g. simm14_lsl2, simm16_lsl2, simm21_lsl2 and simm26_lsl2. 6881ad6265SDimitry Andric unsigned getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, 6981ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7081ad6265SDimitry Andric const MCSubtargetInfo &STI) const; 7181ad6265SDimitry Andric }; 72*972a253aSDimitry Andric } // end namespace 7381ad6265SDimitry Andric 7481ad6265SDimitry Andric unsigned 7581ad6265SDimitry Andric LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, 7681ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 7781ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 7881ad6265SDimitry Andric 7981ad6265SDimitry Andric if (MO.isReg()) 8081ad6265SDimitry Andric return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 8181ad6265SDimitry Andric 8281ad6265SDimitry Andric if (MO.isImm()) 8381ad6265SDimitry Andric return static_cast<unsigned>(MO.getImm()); 8481ad6265SDimitry Andric 8581ad6265SDimitry Andric llvm_unreachable("Unhandled expression!"); 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric 8881ad6265SDimitry Andric unsigned 8981ad6265SDimitry Andric LoongArchMCCodeEmitter::getImmOpValueSub1(const MCInst &MI, unsigned OpNo, 9081ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9181ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 9281ad6265SDimitry Andric return MI.getOperand(OpNo).getImm() - 1; 9381ad6265SDimitry Andric } 9481ad6265SDimitry Andric 9581ad6265SDimitry Andric unsigned 9681ad6265SDimitry Andric LoongArchMCCodeEmitter::getImmOpValueAsr2(const MCInst &MI, unsigned OpNo, 9781ad6265SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, 9881ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 9981ad6265SDimitry Andric unsigned Res = MI.getOperand(OpNo).getImm(); 10081ad6265SDimitry Andric assert((Res & 3) == 0 && "lowest 2 bits are non-zero"); 10181ad6265SDimitry Andric return Res >> 2; 10281ad6265SDimitry Andric } 10381ad6265SDimitry Andric 10481ad6265SDimitry Andric void LoongArchMCCodeEmitter::encodeInstruction( 10581ad6265SDimitry Andric const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, 10681ad6265SDimitry Andric const MCSubtargetInfo &STI) const { 10781ad6265SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 10881ad6265SDimitry Andric // Get byte count of instruction. 10981ad6265SDimitry Andric unsigned Size = Desc.getSize(); 11081ad6265SDimitry Andric 11181ad6265SDimitry Andric switch (Size) { 11281ad6265SDimitry Andric default: 11381ad6265SDimitry Andric llvm_unreachable("Unhandled encodeInstruction length!"); 11481ad6265SDimitry Andric case 4: { 11581ad6265SDimitry Andric uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 11681ad6265SDimitry Andric support::endian::write(OS, Bits, support::little); 11781ad6265SDimitry Andric break; 11881ad6265SDimitry Andric } 11981ad6265SDimitry Andric } 12081ad6265SDimitry Andric } 12181ad6265SDimitry Andric 12281ad6265SDimitry Andric MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII, 12381ad6265SDimitry Andric MCContext &Ctx) { 12481ad6265SDimitry Andric return new LoongArchMCCodeEmitter(Ctx, MCII); 12581ad6265SDimitry Andric } 12681ad6265SDimitry Andric 12781ad6265SDimitry Andric #include "LoongArchGenMCCodeEmitter.inc" 128