xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
181ad6265SDimitry Andric //===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===//
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 LoongArchDisassembler class.
1081ad6265SDimitry Andric //
1181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1281ad6265SDimitry Andric 
1381ad6265SDimitry Andric #include "MCTargetDesc/LoongArchBaseInfo.h"
1481ad6265SDimitry Andric #include "MCTargetDesc/LoongArchMCTargetDesc.h"
1581ad6265SDimitry Andric #include "TargetInfo/LoongArchTargetInfo.h"
1681ad6265SDimitry Andric #include "llvm/MC/MCContext.h"
1781ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
1881ad6265SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
1981ad6265SDimitry Andric #include "llvm/MC/MCInst.h"
2081ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
2181ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
2281ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
2381ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h"
2481ad6265SDimitry Andric #include "llvm/Support/Endian.h"
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric using namespace llvm;
2781ad6265SDimitry Andric 
2881ad6265SDimitry Andric #define DEBUG_TYPE "loongarch-disassembler"
2981ad6265SDimitry Andric 
3081ad6265SDimitry Andric typedef MCDisassembler::DecodeStatus DecodeStatus;
3181ad6265SDimitry Andric 
3281ad6265SDimitry Andric namespace {
3381ad6265SDimitry Andric class LoongArchDisassembler : public MCDisassembler {
3481ad6265SDimitry Andric public:
LoongArchDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)3581ad6265SDimitry Andric   LoongArchDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
3681ad6265SDimitry Andric       : MCDisassembler(STI, Ctx) {}
3781ad6265SDimitry Andric 
3881ad6265SDimitry Andric   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
3981ad6265SDimitry Andric                               ArrayRef<uint8_t> Bytes, uint64_t Address,
4081ad6265SDimitry Andric                               raw_ostream &CStream) const override;
4181ad6265SDimitry Andric };
42972a253aSDimitry Andric } // end namespace
4381ad6265SDimitry Andric 
createLoongArchDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)4481ad6265SDimitry Andric static MCDisassembler *createLoongArchDisassembler(const Target &T,
4581ad6265SDimitry Andric                                                    const MCSubtargetInfo &STI,
4681ad6265SDimitry Andric                                                    MCContext &Ctx) {
4781ad6265SDimitry Andric   return new LoongArchDisassembler(STI, Ctx);
4881ad6265SDimitry Andric }
4981ad6265SDimitry Andric 
LLVMInitializeLoongArchDisassembler()5081ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchDisassembler() {
5181ad6265SDimitry Andric   // Register the disassembler for each target.
5281ad6265SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(),
5381ad6265SDimitry Andric                                          createLoongArchDisassembler);
5481ad6265SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(),
5581ad6265SDimitry Andric                                          createLoongArchDisassembler);
5681ad6265SDimitry Andric }
5781ad6265SDimitry Andric 
DecodeGPRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)5881ad6265SDimitry Andric static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
5981ad6265SDimitry Andric                                            uint64_t Address,
6081ad6265SDimitry Andric                                            const MCDisassembler *Decoder) {
6181ad6265SDimitry Andric   if (RegNo >= 32)
6281ad6265SDimitry Andric     return MCDisassembler::Fail;
6381ad6265SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::R0 + RegNo));
6481ad6265SDimitry Andric   return MCDisassembler::Success;
6581ad6265SDimitry Andric }
6681ad6265SDimitry Andric 
DecodeFPR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)6781ad6265SDimitry Andric static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
6881ad6265SDimitry Andric                                              uint64_t Address,
6981ad6265SDimitry Andric                                              const MCDisassembler *Decoder) {
7081ad6265SDimitry Andric   if (RegNo >= 32)
7181ad6265SDimitry Andric     return MCDisassembler::Fail;
7281ad6265SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo));
7381ad6265SDimitry Andric   return MCDisassembler::Success;
7481ad6265SDimitry Andric }
7581ad6265SDimitry Andric 
DecodeFPR64RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)7681ad6265SDimitry Andric static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
7781ad6265SDimitry Andric                                              uint64_t Address,
7881ad6265SDimitry Andric                                              const MCDisassembler *Decoder) {
7981ad6265SDimitry Andric   if (RegNo >= 32)
8081ad6265SDimitry Andric     return MCDisassembler::Fail;
8181ad6265SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo));
8281ad6265SDimitry Andric   return MCDisassembler::Success;
8381ad6265SDimitry Andric }
8481ad6265SDimitry Andric 
DecodeCFRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)8581ad6265SDimitry Andric static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo,
8681ad6265SDimitry Andric                                            uint64_t Address,
8781ad6265SDimitry Andric                                            const MCDisassembler *Decoder) {
8881ad6265SDimitry Andric   if (RegNo >= 8)
8981ad6265SDimitry Andric     return MCDisassembler::Fail;
9081ad6265SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo));
9181ad6265SDimitry Andric   return MCDisassembler::Success;
9281ad6265SDimitry Andric }
9381ad6265SDimitry Andric 
DecodeFCSRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)9481ad6265SDimitry Andric static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo,
9581ad6265SDimitry Andric                                             uint64_t Address,
9681ad6265SDimitry Andric                                             const MCDisassembler *Decoder) {
9781ad6265SDimitry Andric   if (RegNo >= 4)
9881ad6265SDimitry Andric     return MCDisassembler::Fail;
9981ad6265SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo));
10081ad6265SDimitry Andric   return MCDisassembler::Success;
10181ad6265SDimitry Andric }
10281ad6265SDimitry Andric 
DecodeLSX128RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)103*06c3fb27SDimitry Andric static DecodeStatus DecodeLSX128RegisterClass(MCInst &Inst, uint64_t RegNo,
104*06c3fb27SDimitry Andric                                               uint64_t Address,
105*06c3fb27SDimitry Andric                                               const MCDisassembler *Decoder) {
106*06c3fb27SDimitry Andric   if (RegNo >= 32)
107*06c3fb27SDimitry Andric     return MCDisassembler::Fail;
108*06c3fb27SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::VR0 + RegNo));
109*06c3fb27SDimitry Andric   return MCDisassembler::Success;
110*06c3fb27SDimitry Andric }
111*06c3fb27SDimitry Andric 
DecodeLASX256RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)112*06c3fb27SDimitry Andric static DecodeStatus DecodeLASX256RegisterClass(MCInst &Inst, uint64_t RegNo,
113*06c3fb27SDimitry Andric                                                uint64_t Address,
114*06c3fb27SDimitry Andric                                                const MCDisassembler *Decoder) {
115*06c3fb27SDimitry Andric   if (RegNo >= 32)
116*06c3fb27SDimitry Andric     return MCDisassembler::Fail;
117*06c3fb27SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::XR0 + RegNo));
118*06c3fb27SDimitry Andric   return MCDisassembler::Success;
119*06c3fb27SDimitry Andric }
120*06c3fb27SDimitry Andric 
DecodeSCRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)121*06c3fb27SDimitry Andric static DecodeStatus DecodeSCRRegisterClass(MCInst &Inst, uint64_t RegNo,
122*06c3fb27SDimitry Andric                                            uint64_t Address,
123*06c3fb27SDimitry Andric                                            const MCDisassembler *Decoder) {
124*06c3fb27SDimitry Andric   if (RegNo >= 4)
125*06c3fb27SDimitry Andric     return MCDisassembler::Fail;
126*06c3fb27SDimitry Andric   Inst.addOperand(MCOperand::createReg(LoongArch::SCR0 + RegNo));
127*06c3fb27SDimitry Andric   return MCDisassembler::Success;
128*06c3fb27SDimitry Andric }
129*06c3fb27SDimitry Andric 
13081ad6265SDimitry Andric template <unsigned N, int P = 0>
decodeUImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)13181ad6265SDimitry Andric static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
13281ad6265SDimitry Andric                                       int64_t Address,
13381ad6265SDimitry Andric                                       const MCDisassembler *Decoder) {
13481ad6265SDimitry Andric   assert(isUInt<N>(Imm) && "Invalid immediate");
13581ad6265SDimitry Andric   Inst.addOperand(MCOperand::createImm(Imm + P));
13681ad6265SDimitry Andric   return MCDisassembler::Success;
13781ad6265SDimitry Andric }
13881ad6265SDimitry Andric 
13981ad6265SDimitry Andric template <unsigned N, unsigned S = 0>
decodeSImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)14081ad6265SDimitry Andric static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
14181ad6265SDimitry Andric                                       int64_t Address,
14281ad6265SDimitry Andric                                       const MCDisassembler *Decoder) {
14381ad6265SDimitry Andric   assert(isUInt<N>(Imm) && "Invalid immediate");
144bdd1243dSDimitry Andric   // Shift left Imm <S> bits, then sign-extend the number in the bottom <N+S>
14581ad6265SDimitry Andric   // bits.
146bdd1243dSDimitry Andric   Inst.addOperand(MCOperand::createImm(SignExtend64<N + S>(Imm << S)));
14781ad6265SDimitry Andric   return MCDisassembler::Success;
14881ad6265SDimitry Andric }
14981ad6265SDimitry Andric 
15081ad6265SDimitry Andric #include "LoongArchGenDisassemblerTables.inc"
15181ad6265SDimitry Andric 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const15281ad6265SDimitry Andric DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
15381ad6265SDimitry Andric                                                    ArrayRef<uint8_t> Bytes,
15481ad6265SDimitry Andric                                                    uint64_t Address,
15581ad6265SDimitry Andric                                                    raw_ostream &CS) const {
15681ad6265SDimitry Andric   uint32_t Insn;
15781ad6265SDimitry Andric   DecodeStatus Result;
15881ad6265SDimitry Andric 
15981ad6265SDimitry Andric   // We want to read exactly 4 bytes of data because all LoongArch instructions
16081ad6265SDimitry Andric   // are fixed 32 bits.
16181ad6265SDimitry Andric   if (Bytes.size() < 4) {
16281ad6265SDimitry Andric     Size = 0;
16381ad6265SDimitry Andric     return MCDisassembler::Fail;
16481ad6265SDimitry Andric   }
16581ad6265SDimitry Andric 
16681ad6265SDimitry Andric   Insn = support::endian::read32le(Bytes.data());
16781ad6265SDimitry Andric   // Calling the auto-generated decoder function.
16881ad6265SDimitry Andric   Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
16981ad6265SDimitry Andric   Size = 4;
17081ad6265SDimitry Andric 
17181ad6265SDimitry Andric   return Result;
17281ad6265SDimitry Andric }
173