xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
1 //===-- RISCVMCCodeEmitter.cpp - Convert RISC-V code to machine code ------===//
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 RISCVMCCodeEmitter class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MCTargetDesc/RISCVBaseInfo.h"
14 #include "MCTargetDesc/RISCVFixupKinds.h"
15 #include "MCTargetDesc/RISCVMCExpr.h"
16 #include "MCTargetDesc/RISCVMCTargetDesc.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCCodeEmitter.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstBuilder.h"
24 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCRegisterInfo.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/EndianStream.h"
30 #include "llvm/Support/raw_ostream.h"
31 
32 using namespace llvm;
33 
34 #define DEBUG_TYPE "mccodeemitter"
35 
36 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
37 STATISTIC(MCNumFixups, "Number of MC fixups created");
38 
39 namespace {
40 class RISCVMCCodeEmitter : public MCCodeEmitter {
41   RISCVMCCodeEmitter(const RISCVMCCodeEmitter &) = delete;
42   void operator=(const RISCVMCCodeEmitter &) = delete;
43   MCContext &Ctx;
44   MCInstrInfo const &MCII;
45 
46 public:
47   RISCVMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
48       : Ctx(ctx), MCII(MCII) {}
49 
50   ~RISCVMCCodeEmitter() override = default;
51 
52   void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
53                          SmallVectorImpl<MCFixup> &Fixups,
54                          const MCSubtargetInfo &STI) const override;
55 
56   void expandFunctionCall(const MCInst &MI, SmallVectorImpl<char> &CB,
57                           SmallVectorImpl<MCFixup> &Fixups,
58                           const MCSubtargetInfo &STI) const;
59 
60   void expandAddTPRel(const MCInst &MI, SmallVectorImpl<char> &CB,
61                       SmallVectorImpl<MCFixup> &Fixups,
62                       const MCSubtargetInfo &STI) const;
63 
64   void expandLongCondBr(const MCInst &MI, SmallVectorImpl<char> &CB,
65                         SmallVectorImpl<MCFixup> &Fixups,
66                         const MCSubtargetInfo &STI) const;
67 
68   /// TableGen'erated function for getting the binary encoding for an
69   /// instruction.
70   uint64_t getBinaryCodeForInstr(const MCInst &MI,
71                                  SmallVectorImpl<MCFixup> &Fixups,
72                                  const MCSubtargetInfo &STI) const;
73 
74   /// Return binary encoding of operand. If the machine operand requires
75   /// relocation, record the relocation and return zero.
76   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
77                              SmallVectorImpl<MCFixup> &Fixups,
78                              const MCSubtargetInfo &STI) const;
79 
80   unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
81                              SmallVectorImpl<MCFixup> &Fixups,
82                              const MCSubtargetInfo &STI) const;
83 
84   unsigned getImmOpValue(const MCInst &MI, unsigned OpNo,
85                          SmallVectorImpl<MCFixup> &Fixups,
86                          const MCSubtargetInfo &STI) const;
87 
88   unsigned getVMaskReg(const MCInst &MI, unsigned OpNo,
89                        SmallVectorImpl<MCFixup> &Fixups,
90                        const MCSubtargetInfo &STI) const;
91 
92   unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo,
93                            SmallVectorImpl<MCFixup> &Fixups,
94                            const MCSubtargetInfo &STI) const;
95 
96   unsigned getRegReg(const MCInst &MI, unsigned OpNo,
97                      SmallVectorImpl<MCFixup> &Fixups,
98                      const MCSubtargetInfo &STI) const;
99 };
100 } // end anonymous namespace
101 
102 MCCodeEmitter *llvm::createRISCVMCCodeEmitter(const MCInstrInfo &MCII,
103                                               MCContext &Ctx) {
104   return new RISCVMCCodeEmitter(Ctx, MCII);
105 }
106 
107 // Expand PseudoCALL(Reg), PseudoTAIL and PseudoJump to AUIPC and JALR with
108 // relocation types. We expand those pseudo-instructions while encoding them,
109 // meaning AUIPC and JALR won't go through RISC-V MC to MC compressed
110 // instruction transformation. This is acceptable because AUIPC has no 16-bit
111 // form and C_JALR has no immediate operand field.  We let linker relaxation
112 // deal with it. When linker relaxation is enabled, AUIPC and JALR have a
113 // chance to relax to JAL.
114 // If the C extension is enabled, JAL has a chance relax to C_JAL.
115 void RISCVMCCodeEmitter::expandFunctionCall(const MCInst &MI,
116                                             SmallVectorImpl<char> &CB,
117                                             SmallVectorImpl<MCFixup> &Fixups,
118                                             const MCSubtargetInfo &STI) const {
119   MCInst TmpInst;
120   MCOperand Func;
121   MCRegister Ra;
122   if (MI.getOpcode() == RISCV::PseudoTAIL) {
123     Func = MI.getOperand(0);
124     Ra = RISCV::X6;
125   } else if (MI.getOpcode() == RISCV::PseudoCALLReg) {
126     Func = MI.getOperand(1);
127     Ra = MI.getOperand(0).getReg();
128   } else if (MI.getOpcode() == RISCV::PseudoCALL) {
129     Func = MI.getOperand(0);
130     Ra = RISCV::X1;
131   } else if (MI.getOpcode() == RISCV::PseudoJump) {
132     Func = MI.getOperand(1);
133     Ra = MI.getOperand(0).getReg();
134   }
135   uint32_t Binary;
136 
137   assert(Func.isExpr() && "Expected expression");
138 
139   const MCExpr *CallExpr = Func.getExpr();
140 
141   // Emit AUIPC Ra, Func with R_RISCV_CALL relocation type.
142   TmpInst = MCInstBuilder(RISCV::AUIPC).addReg(Ra).addExpr(CallExpr);
143   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
144   support::endian::write(CB, Binary, llvm::endianness::little);
145 
146   if (MI.getOpcode() == RISCV::PseudoTAIL ||
147       MI.getOpcode() == RISCV::PseudoJump)
148     // Emit JALR X0, Ra, 0
149     TmpInst = MCInstBuilder(RISCV::JALR).addReg(RISCV::X0).addReg(Ra).addImm(0);
150   else
151     // Emit JALR Ra, Ra, 0
152     TmpInst = MCInstBuilder(RISCV::JALR).addReg(Ra).addReg(Ra).addImm(0);
153   Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
154   support::endian::write(CB, Binary, llvm::endianness::little);
155 }
156 
157 // Expand PseudoAddTPRel to a simple ADD with the correct relocation.
158 void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI,
159                                         SmallVectorImpl<char> &CB,
160                                         SmallVectorImpl<MCFixup> &Fixups,
161                                         const MCSubtargetInfo &STI) const {
162   MCOperand DestReg = MI.getOperand(0);
163   MCOperand SrcReg = MI.getOperand(1);
164   MCOperand TPReg = MI.getOperand(2);
165   assert(TPReg.isReg() && TPReg.getReg() == RISCV::X4 &&
166          "Expected thread pointer as second input to TP-relative add");
167 
168   MCOperand SrcSymbol = MI.getOperand(3);
169   assert(SrcSymbol.isExpr() &&
170          "Expected expression as third input to TP-relative add");
171 
172   const RISCVMCExpr *Expr = dyn_cast<RISCVMCExpr>(SrcSymbol.getExpr());
173   assert(Expr && Expr->getKind() == RISCVMCExpr::VK_RISCV_TPREL_ADD &&
174          "Expected tprel_add relocation on TP-relative symbol");
175 
176   // Emit the correct tprel_add relocation for the symbol.
177   Fixups.push_back(MCFixup::create(
178       0, Expr, MCFixupKind(RISCV::fixup_riscv_tprel_add), MI.getLoc()));
179 
180   // Emit fixup_riscv_relax for tprel_add where the relax feature is enabled.
181   if (STI.hasFeature(RISCV::FeatureRelax)) {
182     const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
183     Fixups.push_back(MCFixup::create(
184         0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax), MI.getLoc()));
185   }
186 
187   // Emit a normal ADD instruction with the given operands.
188   MCInst TmpInst = MCInstBuilder(RISCV::ADD)
189                        .addOperand(DestReg)
190                        .addOperand(SrcReg)
191                        .addOperand(TPReg);
192   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
193   support::endian::write(CB, Binary, llvm::endianness::little);
194 }
195 
196 static unsigned getInvertedBranchOp(unsigned BrOp) {
197   switch (BrOp) {
198   default:
199     llvm_unreachable("Unexpected branch opcode!");
200   case RISCV::PseudoLongBEQ:
201     return RISCV::BNE;
202   case RISCV::PseudoLongBNE:
203     return RISCV::BEQ;
204   case RISCV::PseudoLongBLT:
205     return RISCV::BGE;
206   case RISCV::PseudoLongBGE:
207     return RISCV::BLT;
208   case RISCV::PseudoLongBLTU:
209     return RISCV::BGEU;
210   case RISCV::PseudoLongBGEU:
211     return RISCV::BLTU;
212   }
213 }
214 
215 // Expand PseudoLongBxx to an inverted conditional branch and an unconditional
216 // jump.
217 void RISCVMCCodeEmitter::expandLongCondBr(const MCInst &MI,
218                                           SmallVectorImpl<char> &CB,
219                                           SmallVectorImpl<MCFixup> &Fixups,
220                                           const MCSubtargetInfo &STI) const {
221   MCRegister SrcReg1 = MI.getOperand(0).getReg();
222   MCRegister SrcReg2 = MI.getOperand(1).getReg();
223   MCOperand SrcSymbol = MI.getOperand(2);
224   unsigned Opcode = MI.getOpcode();
225   bool IsEqTest =
226       Opcode == RISCV::PseudoLongBNE || Opcode == RISCV::PseudoLongBEQ;
227 
228   bool UseCompressedBr = false;
229   if (IsEqTest && (STI.hasFeature(RISCV::FeatureStdExtC) ||
230                    STI.hasFeature(RISCV::FeatureStdExtZca))) {
231     if (RISCV::X8 <= SrcReg1.id() && SrcReg1.id() <= RISCV::X15 &&
232         SrcReg2.id() == RISCV::X0) {
233       UseCompressedBr = true;
234     } else if (RISCV::X8 <= SrcReg2.id() && SrcReg2.id() <= RISCV::X15 &&
235                SrcReg1.id() == RISCV::X0) {
236       std::swap(SrcReg1, SrcReg2);
237       UseCompressedBr = true;
238     }
239   }
240 
241   uint32_t Offset;
242   if (UseCompressedBr) {
243     unsigned InvOpc =
244         Opcode == RISCV::PseudoLongBNE ? RISCV::C_BEQZ : RISCV::C_BNEZ;
245     MCInst TmpInst = MCInstBuilder(InvOpc).addReg(SrcReg1).addImm(6);
246     uint16_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
247     support::endian::write<uint16_t>(CB, Binary, llvm::endianness::little);
248     Offset = 2;
249   } else {
250     unsigned InvOpc = getInvertedBranchOp(Opcode);
251     MCInst TmpInst =
252         MCInstBuilder(InvOpc).addReg(SrcReg1).addReg(SrcReg2).addImm(8);
253     uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
254     support::endian::write(CB, Binary, llvm::endianness::little);
255     Offset = 4;
256   }
257 
258   // Emit an unconditional jump to the destination.
259   MCInst TmpInst =
260       MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addOperand(SrcSymbol);
261   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
262   support::endian::write(CB, Binary, llvm::endianness::little);
263 
264   Fixups.clear();
265   if (SrcSymbol.isExpr()) {
266     Fixups.push_back(MCFixup::create(Offset, SrcSymbol.getExpr(),
267                                      MCFixupKind(RISCV::fixup_riscv_jal),
268                                      MI.getLoc()));
269   }
270 }
271 
272 void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
273                                            SmallVectorImpl<char> &CB,
274                                            SmallVectorImpl<MCFixup> &Fixups,
275                                            const MCSubtargetInfo &STI) const {
276   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
277   // Get byte count of instruction.
278   unsigned Size = Desc.getSize();
279 
280   // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the
281   // expanded instructions for each pseudo is correct in the Size field of the
282   // tablegen definition for the pseudo.
283   switch (MI.getOpcode()) {
284   default:
285     break;
286   case RISCV::PseudoCALLReg:
287   case RISCV::PseudoCALL:
288   case RISCV::PseudoTAIL:
289   case RISCV::PseudoJump:
290     expandFunctionCall(MI, CB, Fixups, STI);
291     MCNumEmitted += 2;
292     return;
293   case RISCV::PseudoAddTPRel:
294     expandAddTPRel(MI, CB, Fixups, STI);
295     MCNumEmitted += 1;
296     return;
297   case RISCV::PseudoLongBEQ:
298   case RISCV::PseudoLongBNE:
299   case RISCV::PseudoLongBLT:
300   case RISCV::PseudoLongBGE:
301   case RISCV::PseudoLongBLTU:
302   case RISCV::PseudoLongBGEU:
303     expandLongCondBr(MI, CB, Fixups, STI);
304     MCNumEmitted += 2;
305     return;
306   }
307 
308   switch (Size) {
309   default:
310     llvm_unreachable("Unhandled encodeInstruction length!");
311   case 2: {
312     uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
313     support::endian::write<uint16_t>(CB, Bits, llvm::endianness::little);
314     break;
315   }
316   case 4: {
317     uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
318     support::endian::write(CB, Bits, llvm::endianness::little);
319     break;
320   }
321   }
322 
323   ++MCNumEmitted; // Keep track of the # of mi's emitted.
324 }
325 
326 unsigned
327 RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
328                                       SmallVectorImpl<MCFixup> &Fixups,
329                                       const MCSubtargetInfo &STI) const {
330 
331   if (MO.isReg())
332     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
333 
334   if (MO.isImm())
335     return static_cast<unsigned>(MO.getImm());
336 
337   llvm_unreachable("Unhandled expression!");
338   return 0;
339 }
340 
341 unsigned
342 RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
343                                       SmallVectorImpl<MCFixup> &Fixups,
344                                       const MCSubtargetInfo &STI) const {
345   const MCOperand &MO = MI.getOperand(OpNo);
346 
347   if (MO.isImm()) {
348     unsigned Res = MO.getImm();
349     assert((Res & 1) == 0 && "LSB is non-zero");
350     return Res >> 1;
351   }
352 
353   return getImmOpValue(MI, OpNo, Fixups, STI);
354 }
355 
356 unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
357                                            SmallVectorImpl<MCFixup> &Fixups,
358                                            const MCSubtargetInfo &STI) const {
359   bool EnableRelax = STI.hasFeature(RISCV::FeatureRelax);
360   const MCOperand &MO = MI.getOperand(OpNo);
361 
362   MCInstrDesc const &Desc = MCII.get(MI.getOpcode());
363   unsigned MIFrm = RISCVII::getFormat(Desc.TSFlags);
364 
365   // If the destination is an immediate, there is nothing to do.
366   if (MO.isImm())
367     return MO.getImm();
368 
369   assert(MO.isExpr() &&
370          "getImmOpValue expects only expressions or immediates");
371   const MCExpr *Expr = MO.getExpr();
372   MCExpr::ExprKind Kind = Expr->getKind();
373   RISCV::Fixups FixupKind = RISCV::fixup_riscv_invalid;
374   bool RelaxCandidate = false;
375   if (Kind == MCExpr::Target) {
376     const RISCVMCExpr *RVExpr = cast<RISCVMCExpr>(Expr);
377 
378     switch (RVExpr->getKind()) {
379     case RISCVMCExpr::VK_RISCV_None:
380     case RISCVMCExpr::VK_RISCV_Invalid:
381     case RISCVMCExpr::VK_RISCV_32_PCREL:
382       llvm_unreachable("Unhandled fixup kind!");
383     case RISCVMCExpr::VK_RISCV_TPREL_ADD:
384       // tprel_add is only used to indicate that a relocation should be emitted
385       // for an add instruction used in TP-relative addressing. It should not be
386       // expanded as if representing an actual instruction operand and so to
387       // encounter it here is an error.
388       llvm_unreachable(
389           "VK_RISCV_TPREL_ADD should not represent an instruction operand");
390     case RISCVMCExpr::VK_RISCV_LO:
391       if (MIFrm == RISCVII::InstFormatI)
392         FixupKind = RISCV::fixup_riscv_lo12_i;
393       else if (MIFrm == RISCVII::InstFormatS)
394         FixupKind = RISCV::fixup_riscv_lo12_s;
395       else
396         llvm_unreachable("VK_RISCV_LO used with unexpected instruction format");
397       RelaxCandidate = true;
398       break;
399     case RISCVMCExpr::VK_RISCV_HI:
400       FixupKind = RISCV::fixup_riscv_hi20;
401       RelaxCandidate = true;
402       break;
403     case RISCVMCExpr::VK_RISCV_PCREL_LO:
404       if (MIFrm == RISCVII::InstFormatI)
405         FixupKind = RISCV::fixup_riscv_pcrel_lo12_i;
406       else if (MIFrm == RISCVII::InstFormatS)
407         FixupKind = RISCV::fixup_riscv_pcrel_lo12_s;
408       else
409         llvm_unreachable(
410             "VK_RISCV_PCREL_LO used with unexpected instruction format");
411       RelaxCandidate = true;
412       break;
413     case RISCVMCExpr::VK_RISCV_PCREL_HI:
414       FixupKind = RISCV::fixup_riscv_pcrel_hi20;
415       RelaxCandidate = true;
416       break;
417     case RISCVMCExpr::VK_RISCV_GOT_HI:
418       FixupKind = RISCV::fixup_riscv_got_hi20;
419       break;
420     case RISCVMCExpr::VK_RISCV_TPREL_LO:
421       if (MIFrm == RISCVII::InstFormatI)
422         FixupKind = RISCV::fixup_riscv_tprel_lo12_i;
423       else if (MIFrm == RISCVII::InstFormatS)
424         FixupKind = RISCV::fixup_riscv_tprel_lo12_s;
425       else
426         llvm_unreachable(
427             "VK_RISCV_TPREL_LO used with unexpected instruction format");
428       RelaxCandidate = true;
429       break;
430     case RISCVMCExpr::VK_RISCV_TPREL_HI:
431       FixupKind = RISCV::fixup_riscv_tprel_hi20;
432       RelaxCandidate = true;
433       break;
434     case RISCVMCExpr::VK_RISCV_TLS_GOT_HI:
435       FixupKind = RISCV::fixup_riscv_tls_got_hi20;
436       break;
437     case RISCVMCExpr::VK_RISCV_TLS_GD_HI:
438       FixupKind = RISCV::fixup_riscv_tls_gd_hi20;
439       break;
440     case RISCVMCExpr::VK_RISCV_CALL:
441       FixupKind = RISCV::fixup_riscv_call;
442       RelaxCandidate = true;
443       break;
444     case RISCVMCExpr::VK_RISCV_CALL_PLT:
445       FixupKind = RISCV::fixup_riscv_call_plt;
446       RelaxCandidate = true;
447       break;
448     }
449   } else if ((Kind == MCExpr::SymbolRef &&
450                  cast<MCSymbolRefExpr>(Expr)->getKind() ==
451                      MCSymbolRefExpr::VK_None) ||
452              Kind == MCExpr::Binary) {
453     // FIXME: Sub kind binary exprs have chance of underflow.
454     if (MIFrm == RISCVII::InstFormatJ) {
455       FixupKind = RISCV::fixup_riscv_jal;
456     } else if (MIFrm == RISCVII::InstFormatB) {
457       FixupKind = RISCV::fixup_riscv_branch;
458     } else if (MIFrm == RISCVII::InstFormatCJ) {
459       FixupKind = RISCV::fixup_riscv_rvc_jump;
460     } else if (MIFrm == RISCVII::InstFormatCB) {
461       FixupKind = RISCV::fixup_riscv_rvc_branch;
462     } else if (MIFrm == RISCVII::InstFormatI) {
463       FixupKind = RISCV::fixup_riscv_12_i;
464     }
465   }
466 
467   assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!");
468 
469   Fixups.push_back(
470       MCFixup::create(0, Expr, MCFixupKind(FixupKind), MI.getLoc()));
471   ++MCNumFixups;
472 
473   // Ensure an R_RISCV_RELAX relocation will be emitted if linker relaxation is
474   // enabled and the current fixup will result in a relocation that may be
475   // relaxed.
476   if (EnableRelax && RelaxCandidate) {
477     const MCConstantExpr *Dummy = MCConstantExpr::create(0, Ctx);
478     Fixups.push_back(
479     MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_relax),
480                     MI.getLoc()));
481     ++MCNumFixups;
482   }
483 
484   return 0;
485 }
486 
487 unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo,
488                                          SmallVectorImpl<MCFixup> &Fixups,
489                                          const MCSubtargetInfo &STI) const {
490   MCOperand MO = MI.getOperand(OpNo);
491   assert(MO.isReg() && "Expected a register.");
492 
493   switch (MO.getReg()) {
494   default:
495     llvm_unreachable("Invalid mask register.");
496   case RISCV::V0:
497     return 0;
498   case RISCV::NoRegister:
499     return 1;
500   }
501 }
502 
503 unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,
504                                              SmallVectorImpl<MCFixup> &Fixups,
505                                              const MCSubtargetInfo &STI) const {
506   const MCOperand &MO = MI.getOperand(OpNo);
507   assert(MO.isImm() && "Rlist operand must be immediate");
508   auto Imm = MO.getImm();
509   assert(Imm >= 4 && "EABI is currently not implemented");
510   return Imm;
511 }
512 
513 unsigned RISCVMCCodeEmitter::getRegReg(const MCInst &MI, unsigned OpNo,
514                                        SmallVectorImpl<MCFixup> &Fixups,
515                                        const MCSubtargetInfo &STI) const {
516   const MCOperand &MO = MI.getOperand(OpNo);
517   const MCOperand &MO1 = MI.getOperand(OpNo + 1);
518   assert(MO.isReg() && MO1.isReg() && "Expected registers.");
519 
520   unsigned Op = Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
521   unsigned Op1 = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());
522 
523   return Op | Op1 << 5;
524 }
525 
526 #include "RISCVGenMCCodeEmitter.inc"
527