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