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