xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp (revision 972a253a57b6f144b0e4a3e2080a2a0076ec55a0)
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