brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · d4058fa Raw
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