17898587eSWeining Lu //===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===//
27898587eSWeining Lu //
37898587eSWeining Lu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47898587eSWeining Lu // See https://llvm.org/LICENSE.txt for license information.
57898587eSWeining Lu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67898587eSWeining Lu //
77898587eSWeining Lu //===----------------------------------------------------------------------===//
87898587eSWeining Lu //
97898587eSWeining Lu // This file implements the LoongArchDisassembler class.
107898587eSWeining Lu //
117898587eSWeining Lu //===----------------------------------------------------------------------===//
127898587eSWeining Lu
137898587eSWeining Lu #include "MCTargetDesc/LoongArchBaseInfo.h"
147898587eSWeining Lu #include "MCTargetDesc/LoongArchMCTargetDesc.h"
157898587eSWeining Lu #include "TargetInfo/LoongArchTargetInfo.h"
167898587eSWeining Lu #include "llvm/MC/MCContext.h"
17c644488aSSheng #include "llvm/MC/MCDecoderOps.h"
187898587eSWeining Lu #include "llvm/MC/MCDisassembler/MCDisassembler.h"
197898587eSWeining Lu #include "llvm/MC/MCInst.h"
207898587eSWeining Lu #include "llvm/MC/MCInstrInfo.h"
217898587eSWeining Lu #include "llvm/MC/MCRegisterInfo.h"
227898587eSWeining Lu #include "llvm/MC/MCSubtargetInfo.h"
237898587eSWeining Lu #include "llvm/MC/TargetRegistry.h"
247898587eSWeining Lu #include "llvm/Support/Endian.h"
257898587eSWeining Lu
267898587eSWeining Lu using namespace llvm;
277898587eSWeining Lu
287898587eSWeining Lu #define DEBUG_TYPE "loongarch-disassembler"
297898587eSWeining Lu
307898587eSWeining Lu typedef MCDisassembler::DecodeStatus DecodeStatus;
317898587eSWeining Lu
327898587eSWeining Lu namespace {
337898587eSWeining Lu class LoongArchDisassembler : public MCDisassembler {
347898587eSWeining Lu public:
LoongArchDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)357898587eSWeining Lu LoongArchDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
367898587eSWeining Lu : MCDisassembler(STI, Ctx) {}
377898587eSWeining Lu
387898587eSWeining Lu DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
397898587eSWeining Lu ArrayRef<uint8_t> Bytes, uint64_t Address,
407898587eSWeining Lu raw_ostream &CStream) const override;
417898587eSWeining Lu };
42*904a87acSWeining Lu } // end namespace
437898587eSWeining Lu
createLoongArchDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)447898587eSWeining Lu static MCDisassembler *createLoongArchDisassembler(const Target &T,
457898587eSWeining Lu const MCSubtargetInfo &STI,
467898587eSWeining Lu MCContext &Ctx) {
477898587eSWeining Lu return new LoongArchDisassembler(STI, Ctx);
487898587eSWeining Lu }
497898587eSWeining Lu
LLVMInitializeLoongArchDisassembler()507898587eSWeining Lu extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchDisassembler() {
517898587eSWeining Lu // Register the disassembler for each target.
527898587eSWeining Lu TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(),
537898587eSWeining Lu createLoongArchDisassembler);
547898587eSWeining Lu TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(),
557898587eSWeining Lu createLoongArchDisassembler);
567898587eSWeining Lu }
577898587eSWeining Lu
DecodeGPRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)587898587eSWeining Lu static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
597898587eSWeining Lu uint64_t Address,
604ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
617898587eSWeining Lu if (RegNo >= 32)
627898587eSWeining Lu return MCDisassembler::Fail;
637898587eSWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::R0 + RegNo));
647898587eSWeining Lu return MCDisassembler::Success;
657898587eSWeining Lu }
667898587eSWeining Lu
DecodeFPR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)673a49ad71SWeining Lu static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
683a49ad71SWeining Lu uint64_t Address,
693a49ad71SWeining Lu const MCDisassembler *Decoder) {
703a49ad71SWeining Lu if (RegNo >= 32)
713a49ad71SWeining Lu return MCDisassembler::Fail;
723a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo));
733a49ad71SWeining Lu return MCDisassembler::Success;
743a49ad71SWeining Lu }
753a49ad71SWeining Lu
DecodeFPR64RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)763a49ad71SWeining Lu static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
773a49ad71SWeining Lu uint64_t Address,
783a49ad71SWeining Lu const MCDisassembler *Decoder) {
793a49ad71SWeining Lu if (RegNo >= 32)
803a49ad71SWeining Lu return MCDisassembler::Fail;
813a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo));
823a49ad71SWeining Lu return MCDisassembler::Success;
833a49ad71SWeining Lu }
843a49ad71SWeining Lu
DecodeCFRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)853a49ad71SWeining Lu static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo,
863a49ad71SWeining Lu uint64_t Address,
873a49ad71SWeining Lu const MCDisassembler *Decoder) {
883a49ad71SWeining Lu if (RegNo >= 8)
893a49ad71SWeining Lu return MCDisassembler::Fail;
903a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo));
913a49ad71SWeining Lu return MCDisassembler::Success;
923a49ad71SWeining Lu }
933a49ad71SWeining Lu
DecodeFCSRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)943a49ad71SWeining Lu static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo,
953a49ad71SWeining Lu uint64_t Address,
963a49ad71SWeining Lu const MCDisassembler *Decoder) {
973a49ad71SWeining Lu if (RegNo >= 4)
983a49ad71SWeining Lu return MCDisassembler::Fail;
993a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo));
1003a49ad71SWeining Lu return MCDisassembler::Success;
1013a49ad71SWeining Lu }
1023a49ad71SWeining Lu
1037898587eSWeining Lu template <unsigned N, int P = 0>
decodeUImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)1047898587eSWeining Lu static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
1054ae9745aSMaksim Panchenko int64_t Address,
1064ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1077898587eSWeining Lu assert(isUInt<N>(Imm) && "Invalid immediate");
1087898587eSWeining Lu Inst.addOperand(MCOperand::createImm(Imm + P));
1097898587eSWeining Lu return MCDisassembler::Success;
1107898587eSWeining Lu }
1117898587eSWeining Lu
1127898587eSWeining Lu template <unsigned N, unsigned S = 0>
decodeSImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)1137898587eSWeining Lu static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
1144ae9745aSMaksim Panchenko int64_t Address,
1154ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1167898587eSWeining Lu assert(isUInt<N>(Imm) && "Invalid immediate");
1177898587eSWeining Lu // Sign-extend the number in the bottom <N> bits of Imm, then shift left <S>
1187898587eSWeining Lu // bits.
1197898587eSWeining Lu Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm) << S));
1207898587eSWeining Lu return MCDisassembler::Success;
1217898587eSWeining Lu }
1227898587eSWeining Lu
1237898587eSWeining Lu #include "LoongArchGenDisassemblerTables.inc"
1247898587eSWeining Lu
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const1257898587eSWeining Lu DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
1267898587eSWeining Lu ArrayRef<uint8_t> Bytes,
1277898587eSWeining Lu uint64_t Address,
1287898587eSWeining Lu raw_ostream &CS) const {
1297898587eSWeining Lu uint32_t Insn;
1307898587eSWeining Lu DecodeStatus Result;
1317898587eSWeining Lu
1327898587eSWeining Lu // We want to read exactly 4 bytes of data because all LoongArch instructions
1337898587eSWeining Lu // are fixed 32 bits.
1347898587eSWeining Lu if (Bytes.size() < 4) {
1357898587eSWeining Lu Size = 0;
1367898587eSWeining Lu return MCDisassembler::Fail;
1377898587eSWeining Lu }
1387898587eSWeining Lu
1397898587eSWeining Lu Insn = support::endian::read32le(Bytes.data());
1407898587eSWeining Lu // Calling the auto-generated decoder function.
1417898587eSWeining Lu Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
1427898587eSWeining Lu Size = 4;
1437898587eSWeining Lu
1447898587eSWeining Lu return Result;
1457898587eSWeining Lu }
146