1 //===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===// 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 LoongArchDisassembler class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/LoongArchBaseInfo.h" 14 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 15 #include "TargetInfo/LoongArchTargetInfo.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCDecoderOps.h" 18 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCInstrInfo.h" 21 #include "llvm/MC/MCRegisterInfo.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 #include "llvm/MC/TargetRegistry.h" 24 #include "llvm/Support/Endian.h" 25 26 using namespace llvm; 27 28 #define DEBUG_TYPE "loongarch-disassembler" 29 30 typedef MCDisassembler::DecodeStatus DecodeStatus; 31 32 namespace { 33 class LoongArchDisassembler : public MCDisassembler { 34 public: 35 LoongArchDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) 36 : MCDisassembler(STI, Ctx) {} 37 38 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, 39 ArrayRef<uint8_t> Bytes, uint64_t Address, 40 raw_ostream &CStream) const override; 41 }; 42 } // end namespace 43 44 static MCDisassembler *createLoongArchDisassembler(const Target &T, 45 const MCSubtargetInfo &STI, 46 MCContext &Ctx) { 47 return new LoongArchDisassembler(STI, Ctx); 48 } 49 50 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchDisassembler() { 51 // Register the disassembler for each target. 52 TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(), 53 createLoongArchDisassembler); 54 TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(), 55 createLoongArchDisassembler); 56 } 57 58 static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, 59 uint64_t Address, 60 const MCDisassembler *Decoder) { 61 if (RegNo >= 32) 62 return MCDisassembler::Fail; 63 Inst.addOperand(MCOperand::createReg(LoongArch::R0 + RegNo)); 64 return MCDisassembler::Success; 65 } 66 67 static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, 68 uint64_t Address, 69 const MCDisassembler *Decoder) { 70 if (RegNo >= 32) 71 return MCDisassembler::Fail; 72 Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo)); 73 return MCDisassembler::Success; 74 } 75 76 static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, 77 uint64_t Address, 78 const MCDisassembler *Decoder) { 79 if (RegNo >= 32) 80 return MCDisassembler::Fail; 81 Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo)); 82 return MCDisassembler::Success; 83 } 84 85 static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo, 86 uint64_t Address, 87 const MCDisassembler *Decoder) { 88 if (RegNo >= 8) 89 return MCDisassembler::Fail; 90 Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo)); 91 return MCDisassembler::Success; 92 } 93 94 static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo, 95 uint64_t Address, 96 const MCDisassembler *Decoder) { 97 if (RegNo >= 4) 98 return MCDisassembler::Fail; 99 Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo)); 100 return MCDisassembler::Success; 101 } 102 103 template <unsigned N, int P = 0> 104 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, 105 int64_t Address, 106 const MCDisassembler *Decoder) { 107 assert(isUInt<N>(Imm) && "Invalid immediate"); 108 Inst.addOperand(MCOperand::createImm(Imm + P)); 109 return MCDisassembler::Success; 110 } 111 112 template <unsigned N, unsigned S = 0> 113 static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, 114 int64_t Address, 115 const MCDisassembler *Decoder) { 116 assert(isUInt<N>(Imm) && "Invalid immediate"); 117 // Sign-extend the number in the bottom <N> bits of Imm, then shift left <S> 118 // bits. 119 Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm) << S)); 120 return MCDisassembler::Success; 121 } 122 123 #include "LoongArchGenDisassemblerTables.inc" 124 125 DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 126 ArrayRef<uint8_t> Bytes, 127 uint64_t Address, 128 raw_ostream &CS) const { 129 uint32_t Insn; 130 DecodeStatus Result; 131 132 // We want to read exactly 4 bytes of data because all LoongArch instructions 133 // are fixed 32 bits. 134 if (Bytes.size() < 4) { 135 Size = 0; 136 return MCDisassembler::Fail; 137 } 138 139 Insn = support::endian::read32le(Bytes.data()); 140 // Calling the auto-generated decoder function. 141 Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); 142 Size = 4; 143 144 return Result; 145 } 146