Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
35294 views
//===-- RISCVMCCodeEmitter.cpp - Convert RISC-V code to machine code ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the RISCVMCCodeEmitter class.9//10//===----------------------------------------------------------------------===//1112#include "MCTargetDesc/RISCVBaseInfo.h"13#include "MCTargetDesc/RISCVFixupKinds.h"14#include "MCTargetDesc/RISCVMCExpr.h"15#include "MCTargetDesc/RISCVMCTargetDesc.h"16#include "llvm/ADT/Statistic.h"17#include "llvm/MC/MCAsmInfo.h"18#include "llvm/MC/MCCodeEmitter.h"19#include "llvm/MC/MCContext.h"20#include "llvm/MC/MCExpr.h"21#include "llvm/MC/MCInst.h"22#include "llvm/MC/MCInstBuilder.h"23#include "llvm/MC/MCInstrInfo.h"24#include "llvm/MC/MCRegisterInfo.h"25#include "llvm/MC/MCSubtargetInfo.h"26#include "llvm/MC/MCSymbol.h"27#include "llvm/Support/Casting.h"28#include "llvm/Support/EndianStream.h"29#include "llvm/Support/raw_ostream.h"3031using namespace llvm;3233#define DEBUG_TYPE "mccodeemitter"3435STATISTIC(MCNumEmitted, "Number of MC instructions emitted");36STATISTIC(MCNumFixups, "Number of MC fixups created");3738namespace {39class RISCVMCCodeEmitter : public MCCodeEmitter {40RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete;41void operator=(const RISCVMCCodeEmitter &) = delete;42MCContext &Ctx;43MCInstrInfo const &MCII;4445public:46RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)47: Ctx(ctx), MCII(MCII) {}4849~RISCVMCCodeEmitter() override = default;5051void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,52SmallVectorImpl<MCFixup> &Fixups,53const MCSubtargetInfo &STI) const override;5455void expandFunctionCall(const MCInst &MI, SmallVectorImpl<char> &CB,56SmallVectorImpl<MCFixup> &Fixups,57const MCSubtargetInfo &STI) const;5859void expandTLSDESCCall(const MCInst &MI, SmallVectorImpl<char> &CB,60SmallVectorImpl<MCFixup> &Fixups,61const MCSubtargetInfo &STI) const;6263void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,64SmallVectorImpl<MCFixup> &Fixups,65const MCSubtargetInfo &STI) const;6667void expandLongCondBr(const MCInst &MI, SmallVectorImpl<char> &CB,68SmallVectorImpl<MCFixup> &Fixups,69const MCSubtargetInfo &STI) const;7071/// TableGen'erated function for getting the binary encoding for an72/// instruction.73uint64_t getBinaryCodeForInstr(const MCInst &MI,74SmallVectorImpl<MCFixup> &Fixups,75const MCSubtargetInfo &STI) const;7677/// Return binary encoding of operand. If the machine operand requires78/// relocation, record the relocation and return zero.79unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,80SmallVectorImpl<MCFixup> &Fixups,81const MCSubtargetInfo &STI) const;8283unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,84SmallVectorImpl<MCFixup> &Fixups,85const MCSubtargetInfo &STI) const;8687unsigned getImmOpValue(const MCInst &MI, unsigned OpNo,88SmallVectorImpl<MCFixup> &Fixups,89const MCSubtargetInfo &STI) const;9091unsigned getVMaskReg(const MCInst &MI, unsigned OpNo,92SmallVectorImpl<MCFixup> &Fixups,93const MCSubtargetInfo &STI) const;9495unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo,96SmallVectorImpl<MCFixup> &Fixups,97const MCSubtargetInfo &STI) const;9899unsigned getRegReg(const MCInst &MI, unsigned OpNo,100SmallVectorImpl<MCFixup> &Fixups,101const MCSubtargetInfo &STI) const;102};103} // end anonymous namespace104105MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,106MCContext &Ctx) {107return new RISCVMCCodeEmitter(Ctx, MCII);108}109110// Expand PseudoCALL(Reg), PseudoTAIL and PseudoJump to AUIPC and JALR with111// relocation types. We expand those pseudo-instructions while encoding them,112// meaning AUIPC and JALR won't go through RISC-V MC to MC compressed113// instruction transformation. This is acceptable because AUIPC has no 16-bit114// form and C_JALR has no immediate operand field. We let linker relaxation115// deal with it. When linker relaxation is enabled, AUIPC and JALR have a116// chance to relax to JAL.117// If the C extension is enabled, JAL has a chance relax to C_JAL.118void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI,119SmallVectorImpl<char> &CB,120SmallVectorImpl<MCFixup> &Fixups,121const MCSubtargetInfo &STI) const {122MCInst TmpInst;123MCOperand Func;124MCRegister Ra;125if (MI.getOpcode() == RISCV::PseudoTAIL) {126Func = MI.getOperand(0);127Ra = RISCV::X6;128// For Zicfilp, PseudoTAIL should be expanded to a software guarded branch.129// It means to use t2(x7) as rs1 of JALR to expand PseudoTAIL.130if (STI.hasFeature(RISCV::FeatureStdExtZicfilp))131Ra = RISCV::X7;132} else if (MI.getOpcode() == RISCV::PseudoCALLReg) {133Func = MI.getOperand(1);134Ra = MI.getOperand(0).getReg();135} else if (MI.getOpcode() == RISCV::PseudoCALL) {136Func = MI.getOperand(0);137Ra = RISCV::X1;138} else if (MI.getOpcode() == RISCV::PseudoJump) {139Func = MI.getOperand(1);140Ra = MI.getOperand(0).getReg();141}142uint32_t Binary;143144assert(Func.isExpr() && "Expected expression");145146const MCExpr *CallExpr = Func.getExpr();147148// Emit AUIPC Ra, Func with R_RISCV_CALL relocation type.149TmpInst = MCInstBuilder(RISCV::AUIPC).addReg(Ra).addExpr(CallExpr);150Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);151support::endian::write(CB, Binary, llvm::endianness::little);152153if (MI.getOpcode() == RISCV::PseudoTAIL ||154MI.getOpcode() == RISCV::PseudoJump)155// Emit JALR X0, Ra, 0156TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0);157else158// Emit JALR Ra, Ra, 0159TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0);160Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);161support::endian::write(CB, Binary, llvm::endianness::little);162}163164void RISCVMCCodeEmitter::expandTLSDESCCall(const MCInst &MI,165SmallVectorImpl<char> &CB,166SmallVectorImpl<MCFixup> &Fixups,167const MCSubtargetInfo &STI) const {168MCOperand SrcSymbol = MI.getOperand(3);169assert(SrcSymbol.isExpr() &&170"Expected expression as first input to TLSDESCCALL");171const RISCVMCExpr *Expr = dyn_cast<RISCVMCExpr>(SrcSymbol.getExpr());172MCRegister Link = MI.getOperand(0).getReg();173MCRegister Dest = MI.getOperand(1).getReg();174MCRegister Imm = MI.getOperand(2).getImm();175Fixups.push_back(MCFixup::create(1760, Expr, MCFixupKind(RISCV::fixup_riscv_tlsdesc_call), MI.getLoc()));177MCInst Call =178MCInstBuilder(RISCV::JALR).addReg(Link).addReg(Dest).addImm(Imm);179180uint32_t Binary = getBinaryCodeForInstr(Call, Fixups, STI);181support::endian::write(CB, Binary, llvm::endianness::little);182}183184// Expand PseudoAddTPRel to a simple ADD with the correct relocation.185void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI,186SmallVectorImpl<char> &CB,187SmallVectorImpl<MCFixup> &Fixups,188const MCSubtargetInfo &STI) const {189MCOperand DestReg = MI.getOperand(0);190MCOperand SrcReg = MI.getOperand(1);191MCOperand TPReg = MI.getOperand(2);192assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 &&193"Expected thread pointer as second input to TP-relative add");194195MCOperand SrcSymbol = MI.getOperand(3);196assert(SrcSymbol.isExpr() &&197"Expected expression as third input to TP-relative add");198199const RISCVMCExpr *Expr = dyn_cast<RISCVMCExpr>(SrcSymbol.getExpr());200assert(Expr && Expr->getKind() == RISCVMCExpr::VK_RISCV_TPREL_ADD &&201"Expected tprel_add relocation on TP-relative symbol");202203// Emit the correct tprel_add relocation for the symbol.204Fixups.push_back(MCFixup::create(2050, Expr, MCFixupKind(RISCV::fixup_riscv_tprel_add), MI.getLoc()));206207// Emit fixup_riscv_relax for tprel_add where the relax feature is enabled.208if (STI.hasFeature(RISCV::FeatureRelax)) {209const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);210Fixups.push_back(MCFixup::create(2110, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), MI.getLoc()));212}213214// Emit a normal ADD instruction with the given operands.215MCInst TmpInst = MCInstBuilder(RISCV::ADD)216.addOperand(DestReg)217.addOperand(SrcReg)218.addOperand(TPReg);219uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);220support::endian::write(CB, Binary, llvm::endianness::little);221}222223static unsigned getInvertedBranchOp(unsigned BrOp) {224switch (BrOp) {225default:226llvm_unreachable("Unexpected branch opcode!");227case RISCV::PseudoLongBEQ:228return RISCV::BNE;229case RISCV::PseudoLongBNE:230return RISCV::BEQ;231case RISCV::PseudoLongBLT:232return RISCV::BGE;233case RISCV::PseudoLongBGE:234return RISCV::BLT;235case RISCV::PseudoLongBLTU:236return RISCV::BGEU;237case RISCV::PseudoLongBGEU:238return RISCV::BLTU;239}240}241242// Expand PseudoLongBxx to an inverted conditional branch and an unconditional243// jump.244void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,245SmallVectorImpl<char> &CB,246SmallVectorImpl<MCFixup> &Fixups,247const MCSubtargetInfo &STI) const {248MCRegister SrcReg1 = MI.getOperand(0).getReg();249MCRegister SrcReg2 = MI.getOperand(1).getReg();250MCOperand SrcSymbol = MI.getOperand(2);251unsigned Opcode = MI.getOpcode();252bool IsEqTest =253Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;254255bool UseCompressedBr = false;256if (IsEqTest && (STI.hasFeature(RISCV::FeatureStdExtC) ||257STI.hasFeature(RISCV::FeatureStdExtZca))) {258if (RISCV::X8 <= SrcReg1.id() && SrcReg1.id() <= RISCV::X15 &&259SrcReg2.id() == RISCV::X0) {260UseCompressedBr = true;261} else if (RISCV::X8 <= SrcReg2.id() && SrcReg2.id() <= RISCV::X15 &&262SrcReg1.id() == RISCV::X0) {263std::swap(SrcReg1, SrcReg2);264UseCompressedBr = true;265}266}267268uint32_t Offset;269if (UseCompressedBr) {270unsigned InvOpc =271Opcode == RISCV::PseudoLongBNE ? RISCV::C_BEQZ : RISCV::C_BNEZ;272MCInst TmpInst = MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(6);273uint16_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);274support::endian::write<uint16_t>(CB, Binary, llvm::endianness::little);275Offset = 2;276} else {277unsigned InvOpc = getInvertedBranchOp(Opcode);278MCInst TmpInst =279MCInstBuilder(InvOpc).addReg(SrcReg1).addReg(SrcReg2).addImm(8);280uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);281support::endian::write(CB, Binary, llvm::endianness::little);282Offset = 4;283}284285// Save the number fixups.286size_t FixupStartIndex = Fixups.size();287288// Emit an unconditional jump to the destination.289MCInst TmpInst =290MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);291uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);292support::endian::write(CB, Binary, llvm::endianness::little);293294// Drop any fixup added so we can add the correct one.295Fixups.resize(FixupStartIndex);296297if (SrcSymbol.isExpr()) {298Fixups.push_back(MCFixup::create(Offset, SrcSymbol.getExpr(),299MCFixupKind(RISCV::fixup_riscv_jal),300MI.getLoc()));301}302}303304void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,305SmallVectorImpl<char> &CB,306SmallVectorImpl<MCFixup> &Fixups,307const MCSubtargetInfo &STI) const {308const MCInstrDesc &Desc = MCII.get(MI.getOpcode());309// Get byte count of instruction.310unsigned Size = Desc.getSize();311312// RISCVInstrInfo::getInstSizeInBytes expects that the total size of the313// expanded instructions for each pseudo is correct in the Size field of the314// tablegen definition for the pseudo.315switch (MI.getOpcode()) {316default:317break;318case RISCV::PseudoCALLReg:319case RISCV::PseudoCALL:320case RISCV::PseudoTAIL:321case RISCV::PseudoJump:322expandFunctionCall(MI, CB, Fixups, STI);323MCNumEmitted += 2;324return;325case RISCV::PseudoAddTPRel:326expandAddTPRel(MI, CB, Fixups, STI);327MCNumEmitted += 1;328return;329case RISCV::PseudoLongBEQ:330case RISCV::PseudoLongBNE:331case RISCV::PseudoLongBLT:332case RISCV::PseudoLongBGE:333case RISCV::PseudoLongBLTU:334case RISCV::PseudoLongBGEU:335expandLongCondBr(MI, CB, Fixups, STI);336MCNumEmitted += 2;337return;338case RISCV::PseudoTLSDESCCall:339expandTLSDESCCall(MI, CB, Fixups, STI);340MCNumEmitted += 1;341return;342}343344switch (Size) {345default:346llvm_unreachable("Unhandled encodeInstruction length!");347case 2: {348uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);349support::endian::write<uint16_t>(CB, Bits, llvm::endianness::little);350break;351}352case 4: {353uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);354support::endian::write(CB, Bits, llvm::endianness::little);355break;356}357}358359++MCNumEmitted; // Keep track of the # of mi's emitted.360}361362unsigned363RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,364SmallVectorImpl<MCFixup> &Fixups,365const MCSubtargetInfo &STI) const {366367if (MO.isReg())368return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());369370if (MO.isImm())371return static_cast<unsigned>(MO.getImm());372373llvm_unreachable("Unhandled expression!");374return 0;375}376377unsigned378RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,379SmallVectorImpl<MCFixup> &Fixups,380const MCSubtargetInfo &STI) const {381const MCOperand &MO = MI.getOperand(OpNo);382383if (MO.isImm()) {384unsigned Res = MO.getImm();385assert((Res & 1) == 0 && "LSB is non-zero");386return Res >> 1;387}388389return getImmOpValue(MI, OpNo, Fixups, STI);390}391392unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,393SmallVectorImpl<MCFixup> &Fixups,394const MCSubtargetInfo &STI) const {395bool EnableRelax = STI.hasFeature(RISCV::FeatureRelax);396const MCOperand &MO = MI.getOperand(OpNo);397398MCInstrDesc const &Desc = MCII.get(MI.getOpcode());399unsigned MIFrm = RISCVII::getFormat(Desc.TSFlags);400401// If the destination is an immediate, there is nothing to do.402if (MO.isImm())403return MO.getImm();404405assert(MO.isExpr() &&406"getImmOpValue expects only expressions or immediates");407const MCExpr *Expr = MO.getExpr();408MCExpr::ExprKind Kind = Expr->getKind();409RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid;410bool RelaxCandidate = false;411if (Kind == MCExpr::Target) {412const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr);413414switch (RVExpr->getKind()) {415case RISCVMCExpr::VK_RISCV_None:416case RISCVMCExpr::VK_RISCV_Invalid:417case RISCVMCExpr::VK_RISCV_32_PCREL:418llvm_unreachable("Unhandled fixup kind!");419case RISCVMCExpr::VK_RISCV_TPREL_ADD:420// tprel_add is only used to indicate that a relocation should be emitted421// for an add instruction used in TP-relative addressing. It should not be422// expanded as if representing an actual instruction operand and so to423// encounter it here is an error.424llvm_unreachable(425"VK_RISCV_TPREL_ADD should not represent an instruction operand");426case RISCVMCExpr::VK_RISCV_LO:427if (MIFrm == RISCVII::InstFormatI)428FixupKind = RISCV::fixup_riscv_lo12_i;429else if (MIFrm == RISCVII::InstFormatS)430FixupKind = RISCV::fixup_riscv_lo12_s;431else432llvm_unreachable("VK_RISCV_LO used with unexpected instruction format");433RelaxCandidate = true;434break;435case RISCVMCExpr::VK_RISCV_HI:436FixupKind = RISCV::fixup_riscv_hi20;437RelaxCandidate = true;438break;439case RISCVMCExpr::VK_RISCV_PCREL_LO:440if (MIFrm == RISCVII::InstFormatI)441FixupKind = RISCV::fixup_riscv_pcrel_lo12_i;442else if (MIFrm == RISCVII::InstFormatS)443FixupKind = RISCV::fixup_riscv_pcrel_lo12_s;444else445llvm_unreachable(446"VK_RISCV_PCREL_LO used with unexpected instruction format");447RelaxCandidate = true;448break;449case RISCVMCExpr::VK_RISCV_PCREL_HI:450FixupKind = RISCV::fixup_riscv_pcrel_hi20;451RelaxCandidate = true;452break;453case RISCVMCExpr::VK_RISCV_GOT_HI:454FixupKind = RISCV::fixup_riscv_got_hi20;455break;456case RISCVMCExpr::VK_RISCV_TPREL_LO:457if (MIFrm == RISCVII::InstFormatI)458FixupKind = RISCV::fixup_riscv_tprel_lo12_i;459else if (MIFrm == RISCVII::InstFormatS)460FixupKind = RISCV::fixup_riscv_tprel_lo12_s;461else462llvm_unreachable(463"VK_RISCV_TPREL_LO used with unexpected instruction format");464RelaxCandidate = true;465break;466case RISCVMCExpr::VK_RISCV_TPREL_HI:467FixupKind = RISCV::fixup_riscv_tprel_hi20;468RelaxCandidate = true;469break;470case RISCVMCExpr::VK_RISCV_TLS_GOT_HI:471FixupKind = RISCV::fixup_riscv_tls_got_hi20;472break;473case RISCVMCExpr::VK_RISCV_TLS_GD_HI:474FixupKind = RISCV::fixup_riscv_tls_gd_hi20;475break;476case RISCVMCExpr::VK_RISCV_CALL:477FixupKind = RISCV::fixup_riscv_call;478RelaxCandidate = true;479break;480case RISCVMCExpr::VK_RISCV_CALL_PLT:481FixupKind = RISCV::fixup_riscv_call_plt;482RelaxCandidate = true;483break;484case RISCVMCExpr::VK_RISCV_TLSDESC_HI:485FixupKind = RISCV::fixup_riscv_tlsdesc_hi20;486break;487case RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO:488FixupKind = RISCV::fixup_riscv_tlsdesc_load_lo12;489break;490case RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO:491FixupKind = RISCV::fixup_riscv_tlsdesc_add_lo12;492break;493case RISCVMCExpr::VK_RISCV_TLSDESC_CALL:494FixupKind = RISCV::fixup_riscv_tlsdesc_call;495break;496}497} else if ((Kind == MCExpr::SymbolRef &&498cast<MCSymbolRefExpr>(Expr)->getKind() ==499MCSymbolRefExpr::VK_None) ||500Kind == MCExpr::Binary) {501// FIXME: Sub kind binary exprs have chance of underflow.502if (MIFrm == RISCVII::InstFormatJ) {503FixupKind = RISCV::fixup_riscv_jal;504} else if (MIFrm == RISCVII::InstFormatB) {505FixupKind = RISCV::fixup_riscv_branch;506} else if (MIFrm == RISCVII::InstFormatCJ) {507FixupKind = RISCV::fixup_riscv_rvc_jump;508} else if (MIFrm == RISCVII::InstFormatCB) {509FixupKind = RISCV::fixup_riscv_rvc_branch;510} else if (MIFrm == RISCVII::InstFormatI) {511FixupKind = RISCV::fixup_riscv_12_i;512}513}514515assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!");516517Fixups.push_back(518MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));519++MCNumFixups;520521// Ensure an R_RISCV_RELAX relocation will be emitted if linker relaxation is522// enabled and the current fixup will result in a relocation that may be523// relaxed.524if (EnableRelax && RelaxCandidate) {525const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);526Fixups.push_back(527MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax),528MI.getLoc()));529++MCNumFixups;530}531532return 0;533}534535unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo,536SmallVectorImpl<MCFixup> &Fixups,537const MCSubtargetInfo &STI) const {538MCOperand MO = MI.getOperand(OpNo);539assert(MO.isReg() && "Expected a register.");540541switch (MO.getReg()) {542default:543llvm_unreachable("Invalid mask register.");544case RISCV::V0:545return 0;546case RISCV::NoRegister:547return 1;548}549}550551unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,552SmallVectorImpl<MCFixup> &Fixups,553const MCSubtargetInfo &STI) const {554const MCOperand &MO = MI.getOperand(OpNo);555assert(MO.isImm() && "Rlist operand must be immediate");556auto Imm = MO.getImm();557assert(Imm >= 4 && "EABI is currently not implemented");558return Imm;559}560561unsigned RISCVMCCodeEmitter::getRegReg(const MCInst &MI, unsigned OpNo,562SmallVectorImpl<MCFixup> &Fixups,563const MCSubtargetInfo &STI) const {564const MCOperand &MO = MI.getOperand(OpNo);565const MCOperand &MO1 = MI.getOperand(OpNo + 1);566assert(MO.isReg() && MO1.isReg() && "Expected registers.");567568unsigned Op = Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());569unsigned Op1 = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());570571return Op | Op1 << 5;572}573574#include "RISCVGenMCCodeEmitter.inc"575576577