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