Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
35293 views
//===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the LoongArchDisassembler class.9//10//===----------------------------------------------------------------------===//1112#include "MCTargetDesc/LoongArchBaseInfo.h"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/MCRegisterInfo.h"21#include "llvm/MC/MCSubtargetInfo.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/Endian.h"2425using namespace llvm;2627#define DEBUG_TYPE "loongarch-disassembler"2829typedef MCDisassembler::DecodeStatus DecodeStatus;3031namespace {32class LoongArchDisassembler : public MCDisassembler {33public:34LoongArchDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)35: MCDisassembler(STI, Ctx) {}3637DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,38ArrayRef<uint8_t> Bytes, uint64_t Address,39raw_ostream &CStream) const override;40};41} // end namespace4243static MCDisassembler *createLoongArchDisassembler(const Target &T,44const MCSubtargetInfo &STI,45MCContext &Ctx) {46return new LoongArchDisassembler(STI, Ctx);47}4849extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchDisassembler() {50// Register the disassembler for each target.51TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(),52createLoongArchDisassembler);53TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(),54createLoongArchDisassembler);55}5657static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,58uint64_t Address,59const MCDisassembler *Decoder) {60if (RegNo >= 32)61return MCDisassembler::Fail;62Inst.addOperand(MCOperand::createReg(LoongArch::R0 + RegNo));63return MCDisassembler::Success;64}6566static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,67uint64_t Address,68const MCDisassembler *Decoder) {69if (RegNo >= 32)70return MCDisassembler::Fail;71Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo));72return MCDisassembler::Success;73}7475static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,76uint64_t Address,77const MCDisassembler *Decoder) {78if (RegNo >= 32)79return MCDisassembler::Fail;80Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo));81return MCDisassembler::Success;82}8384static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo,85uint64_t Address,86const MCDisassembler *Decoder) {87if (RegNo >= 8)88return MCDisassembler::Fail;89Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo));90return MCDisassembler::Success;91}9293static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo,94uint64_t Address,95const MCDisassembler *Decoder) {96if (RegNo >= 4)97return MCDisassembler::Fail;98Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo));99return MCDisassembler::Success;100}101102static DecodeStatus DecodeLSX128RegisterClass(MCInst &Inst, uint64_t RegNo,103uint64_t Address,104const MCDisassembler *Decoder) {105if (RegNo >= 32)106return MCDisassembler::Fail;107Inst.addOperand(MCOperand::createReg(LoongArch::VR0 + RegNo));108return MCDisassembler::Success;109}110111static DecodeStatus DecodeLASX256RegisterClass(MCInst &Inst, uint64_t RegNo,112uint64_t Address,113const MCDisassembler *Decoder) {114if (RegNo >= 32)115return MCDisassembler::Fail;116Inst.addOperand(MCOperand::createReg(LoongArch::XR0 + RegNo));117return MCDisassembler::Success;118}119120static DecodeStatus DecodeSCRRegisterClass(MCInst &Inst, uint64_t RegNo,121uint64_t Address,122const MCDisassembler *Decoder) {123if (RegNo >= 4)124return MCDisassembler::Fail;125Inst.addOperand(MCOperand::createReg(LoongArch::SCR0 + RegNo));126return MCDisassembler::Success;127}128129template <unsigned N, int P = 0>130static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,131int64_t Address,132const MCDisassembler *Decoder) {133assert(isUInt<N>(Imm) && "Invalid immediate");134Inst.addOperand(MCOperand::createImm(Imm + P));135return MCDisassembler::Success;136}137138template <unsigned N, unsigned S = 0>139static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,140int64_t Address,141const MCDisassembler *Decoder) {142assert(isUInt<N>(Imm) && "Invalid immediate");143// Shift left Imm <S> bits, then sign-extend the number in the bottom <N+S>144// bits.145Inst.addOperand(MCOperand::createImm(SignExtend64<N + S>(Imm << S)));146return MCDisassembler::Success;147}148149#include "LoongArchGenDisassemblerTables.inc"150151DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size,152ArrayRef<uint8_t> Bytes,153uint64_t Address,154raw_ostream &CS) const {155uint32_t Insn;156DecodeStatus Result;157158// We want to read exactly 4 bytes of data because all LoongArch instructions159// are fixed 32 bits.160if (Bytes.size() < 4) {161Size = 0;162return MCDisassembler::Fail;163}164165Insn = support::endian::read32le(Bytes.data());166// Calling the auto-generated decoder function.167Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);168Size = 4;169170return Result;171}172173174