17898587eSWeining Lu //===-- LoongArchDisassembler.cpp - Disassembler for LoongArch ------------===// 27898587eSWeining Lu // 37898587eSWeining Lu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47898587eSWeining Lu // See https://llvm.org/LICENSE.txt for license information. 57898587eSWeining Lu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67898587eSWeining Lu // 77898587eSWeining Lu //===----------------------------------------------------------------------===// 87898587eSWeining Lu // 97898587eSWeining Lu // This file implements the LoongArchDisassembler class. 107898587eSWeining Lu // 117898587eSWeining Lu //===----------------------------------------------------------------------===// 127898587eSWeining Lu 137898587eSWeining Lu #include "MCTargetDesc/LoongArchMCTargetDesc.h" 147898587eSWeining Lu #include "TargetInfo/LoongArchTargetInfo.h" 157898587eSWeining Lu #include "llvm/MC/MCContext.h" 16c644488aSSheng #include "llvm/MC/MCDecoderOps.h" 177898587eSWeining Lu #include "llvm/MC/MCDisassembler/MCDisassembler.h" 187898587eSWeining Lu #include "llvm/MC/MCInst.h" 197898587eSWeining Lu #include "llvm/MC/MCInstrInfo.h" 207898587eSWeining Lu #include "llvm/MC/MCSubtargetInfo.h" 217898587eSWeining Lu #include "llvm/MC/TargetRegistry.h" 227898587eSWeining Lu #include "llvm/Support/Endian.h" 237898587eSWeining Lu 247898587eSWeining Lu using namespace llvm; 257898587eSWeining Lu 267898587eSWeining Lu #define DEBUG_TYPE "loongarch-disassembler" 277898587eSWeining Lu 287898587eSWeining Lu typedef MCDisassembler::DecodeStatus DecodeStatus; 297898587eSWeining Lu 307898587eSWeining Lu namespace { 317898587eSWeining Lu class LoongArchDisassembler : public MCDisassembler { 327898587eSWeining Lu public: 337898587eSWeining Lu LoongArchDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) 347898587eSWeining Lu : MCDisassembler(STI, Ctx) {} 357898587eSWeining Lu 367898587eSWeining Lu DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, 377898587eSWeining Lu ArrayRef<uint8_t> Bytes, uint64_t Address, 387898587eSWeining Lu raw_ostream &CStream) const override; 397898587eSWeining Lu }; 40904a87acSWeining Lu } // end namespace 417898587eSWeining Lu 427898587eSWeining Lu static MCDisassembler *createLoongArchDisassembler(const Target &T, 437898587eSWeining Lu const MCSubtargetInfo &STI, 447898587eSWeining Lu MCContext &Ctx) { 457898587eSWeining Lu return new LoongArchDisassembler(STI, Ctx); 467898587eSWeining Lu } 477898587eSWeining Lu 487898587eSWeining Lu extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchDisassembler() { 497898587eSWeining Lu // Register the disassembler for each target. 507898587eSWeining Lu TargetRegistry::RegisterMCDisassembler(getTheLoongArch32Target(), 517898587eSWeining Lu createLoongArchDisassembler); 527898587eSWeining Lu TargetRegistry::RegisterMCDisassembler(getTheLoongArch64Target(), 537898587eSWeining Lu createLoongArchDisassembler); 547898587eSWeining Lu } 557898587eSWeining Lu 567898587eSWeining Lu static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, 577898587eSWeining Lu uint64_t Address, 584ae9745aSMaksim Panchenko const MCDisassembler *Decoder) { 597898587eSWeining Lu if (RegNo >= 32) 607898587eSWeining Lu return MCDisassembler::Fail; 617898587eSWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::R0 + RegNo)); 627898587eSWeining Lu return MCDisassembler::Success; 637898587eSWeining Lu } 647898587eSWeining Lu 653a49ad71SWeining Lu static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo, 663a49ad71SWeining Lu uint64_t Address, 673a49ad71SWeining Lu const MCDisassembler *Decoder) { 683a49ad71SWeining Lu if (RegNo >= 32) 693a49ad71SWeining Lu return MCDisassembler::Fail; 703a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo)); 713a49ad71SWeining Lu return MCDisassembler::Success; 723a49ad71SWeining Lu } 733a49ad71SWeining Lu 743a49ad71SWeining Lu static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo, 753a49ad71SWeining Lu uint64_t Address, 763a49ad71SWeining Lu const MCDisassembler *Decoder) { 773a49ad71SWeining Lu if (RegNo >= 32) 783a49ad71SWeining Lu return MCDisassembler::Fail; 793a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo)); 803a49ad71SWeining Lu return MCDisassembler::Success; 813a49ad71SWeining Lu } 823a49ad71SWeining Lu 833a49ad71SWeining Lu static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo, 843a49ad71SWeining Lu uint64_t Address, 853a49ad71SWeining Lu const MCDisassembler *Decoder) { 863a49ad71SWeining Lu if (RegNo >= 8) 873a49ad71SWeining Lu return MCDisassembler::Fail; 883a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo)); 893a49ad71SWeining Lu return MCDisassembler::Success; 903a49ad71SWeining Lu } 913a49ad71SWeining Lu 923a49ad71SWeining Lu static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo, 933a49ad71SWeining Lu uint64_t Address, 943a49ad71SWeining Lu const MCDisassembler *Decoder) { 953a49ad71SWeining Lu if (RegNo >= 4) 963a49ad71SWeining Lu return MCDisassembler::Fail; 973a49ad71SWeining Lu Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo)); 983a49ad71SWeining Lu return MCDisassembler::Success; 993a49ad71SWeining Lu } 1003a49ad71SWeining Lu 1011aa3b64eSwanglei static DecodeStatus DecodeLSX128RegisterClass(MCInst &Inst, uint64_t RegNo, 1021aa3b64eSwanglei uint64_t Address, 1031aa3b64eSwanglei const MCDisassembler *Decoder) { 1041aa3b64eSwanglei if (RegNo >= 32) 1051aa3b64eSwanglei return MCDisassembler::Fail; 1061aa3b64eSwanglei Inst.addOperand(MCOperand::createReg(LoongArch::VR0 + RegNo)); 1071aa3b64eSwanglei return MCDisassembler::Success; 1081aa3b64eSwanglei } 1091aa3b64eSwanglei 110f3d18b9dSwanglei static DecodeStatus DecodeLASX256RegisterClass(MCInst &Inst, uint64_t RegNo, 111f3d18b9dSwanglei uint64_t Address, 112f3d18b9dSwanglei const MCDisassembler *Decoder) { 113f3d18b9dSwanglei if (RegNo >= 32) 114f3d18b9dSwanglei return MCDisassembler::Fail; 115f3d18b9dSwanglei Inst.addOperand(MCOperand::createReg(LoongArch::XR0 + RegNo)); 116f3d18b9dSwanglei return MCDisassembler::Success; 117f3d18b9dSwanglei } 118f3d18b9dSwanglei 119*d6675b6aSwanglei static DecodeStatus DecodeSCRRegisterClass(MCInst &Inst, uint64_t RegNo, 120*d6675b6aSwanglei uint64_t Address, 121*d6675b6aSwanglei const MCDisassembler *Decoder) { 122*d6675b6aSwanglei if (RegNo >= 4) 123*d6675b6aSwanglei return MCDisassembler::Fail; 124*d6675b6aSwanglei Inst.addOperand(MCOperand::createReg(LoongArch::SCR0 + RegNo)); 125*d6675b6aSwanglei return MCDisassembler::Success; 126*d6675b6aSwanglei } 127*d6675b6aSwanglei 1287898587eSWeining Lu template <unsigned N, int P = 0> 1297898587eSWeining Lu static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, 1304ae9745aSMaksim Panchenko int64_t Address, 1314ae9745aSMaksim Panchenko const MCDisassembler *Decoder) { 1327898587eSWeining Lu assert(isUInt<N>(Imm) && "Invalid immediate"); 1337898587eSWeining Lu Inst.addOperand(MCOperand::createImm(Imm + P)); 1347898587eSWeining Lu return MCDisassembler::Success; 1357898587eSWeining Lu } 1367898587eSWeining Lu 1377898587eSWeining Lu template <unsigned N, unsigned S = 0> 1387898587eSWeining Lu static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, 1394ae9745aSMaksim Panchenko int64_t Address, 1404ae9745aSMaksim Panchenko const MCDisassembler *Decoder) { 1417898587eSWeining Lu assert(isUInt<N>(Imm) && "Invalid immediate"); 142f292d53cSwanglei // Shift left Imm <S> bits, then sign-extend the number in the bottom <N+S> 1437898587eSWeining Lu // bits. 144f292d53cSwanglei Inst.addOperand(MCOperand::createImm(SignExtend64<N + S>(Imm << S))); 1457898587eSWeining Lu return MCDisassembler::Success; 1467898587eSWeining Lu } 1477898587eSWeining Lu 1487898587eSWeining Lu #include "LoongArchGenDisassemblerTables.inc" 1497898587eSWeining Lu 1507898587eSWeining Lu DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 1517898587eSWeining Lu ArrayRef<uint8_t> Bytes, 1527898587eSWeining Lu uint64_t Address, 1537898587eSWeining Lu raw_ostream &CS) const { 1547898587eSWeining Lu uint32_t Insn; 1557898587eSWeining Lu DecodeStatus Result; 1567898587eSWeining Lu 1577898587eSWeining Lu // We want to read exactly 4 bytes of data because all LoongArch instructions 1587898587eSWeining Lu // are fixed 32 bits. 1597898587eSWeining Lu if (Bytes.size() < 4) { 1607898587eSWeining Lu Size = 0; 1617898587eSWeining Lu return MCDisassembler::Fail; 1627898587eSWeining Lu } 1637898587eSWeining Lu 1647898587eSWeining Lu Insn = support::endian::read32le(Bytes.data()); 1657898587eSWeining Lu // Calling the auto-generated decoder function. 1667898587eSWeining Lu Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); 1677898587eSWeining Lu Size = 4; 1687898587eSWeining Lu 1697898587eSWeining Lu return Result; 1707898587eSWeining Lu } 171