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 static DecodeStatus DecodeLSX128RegisterClass(MCInst &Inst, uint64_t RegNo, 104 uint64_t Address, 105 const MCDisassembler *Decoder) { 106 if (RegNo >= 32) 107 return MCDisassembler::Fail; 108 Inst.addOperand(MCOperand::createReg(LoongArch::VR0 + RegNo)); 109 return MCDisassembler::Success; 110 } 111 112 static DecodeStatus DecodeLASX256RegisterClass(MCInst &Inst, uint64_t RegNo, 113 uint64_t Address, 114 const MCDisassembler *Decoder) { 115 if (RegNo >= 32) 116 return MCDisassembler::Fail; 117 Inst.addOperand(MCOperand::createReg(LoongArch::XR0 + RegNo)); 118 return MCDisassembler::Success; 119 } 120 121 static DecodeStatus DecodeSCRRegisterClass(MCInst &Inst, uint64_t RegNo, 122 uint64_t Address, 123 const MCDisassembler *Decoder) { 124 if (RegNo >= 4) 125 return MCDisassembler::Fail; 126 Inst.addOperand(MCOperand::createReg(LoongArch::SCR0 + RegNo)); 127 return MCDisassembler::Success; 128 } 129 130 template <unsigned N, int P = 0> 131 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, 132 int64_t Address, 133 const MCDisassembler *Decoder) { 134 assert(isUInt<N>(Imm) && "Invalid immediate"); 135 Inst.addOperand(MCOperand::createImm(Imm + P)); 136 return MCDisassembler::Success; 137 } 138 139 template <unsigned N, unsigned S = 0> 140 static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, 141 int64_t Address, 142 const MCDisassembler *Decoder) { 143 assert(isUInt<N>(Imm) && "Invalid immediate"); 144 // Shift left Imm <S> bits, then sign-extend the number in the bottom <N+S> 145 // bits. 146 Inst.addOperand(MCOperand::createImm(SignExtend64<N + S>(Imm << S))); 147 return MCDisassembler::Success; 148 } 149 150 #include "LoongArchGenDisassemblerTables.inc" 151 152 DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 153 ArrayRef<uint8_t> Bytes, 154 uint64_t Address, 155 raw_ostream &CS) const { 156 uint32_t Insn; 157 DecodeStatus Result; 158 159 // We want to read exactly 4 bytes of data because all LoongArch instructions 160 // are fixed 32 bits. 161 if (Bytes.size() < 4) { 162 Size = 0; 163 return MCDisassembler::Fail; 164 } 165 166 Insn = support::endian::read32le(Bytes.data()); 167 // Calling the auto-generated decoder function. 168 Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); 169 Size = 4; 170 171 return Result; 172 } 173