Index: lib/Target/NDS32/CMakeLists.txt =================================================================== --- lib/Target/NDS32/CMakeLists.txt +++ lib/Target/NDS32/CMakeLists.txt @@ -8,6 +8,7 @@ tablegen(LLVM NDS32GenAsmWriter.inc -gen-asm-writer) tablegen(LLVM NDS32GenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM NDS32GenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM NDS32GenDisassemblerTables.inc -gen-disassembler) add_public_tablegen_target(NDS32CommonTableGen) @@ -30,3 +31,4 @@ add_subdirectory(MCTargetDesc) add_subdirectory(InstPrinter) add_subdirectory(AsmParser) +add_subdirectory(Disassembler) Index: lib/Target/NDS32/Disassembler/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/NDS32/Disassembler/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMNDS32Disassembler + NDS32Disassembler.cpp + ) Index: lib/Target/NDS32/Disassembler/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/NDS32/Disassembler/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/NDS32/Disassembler/LLVMBuild.txt ------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = NDS32Disassembler +parent = NDS32 +required_libraries = NDS32Desc NDS32Info MCDisassembler Support +add_to_library_groups = NDS32 Index: lib/Target/NDS32/Disassembler/NDS32Disassembler.cpp =================================================================== --- /dev/null +++ lib/Target/NDS32/Disassembler/NDS32Disassembler.cpp @@ -0,0 +1,468 @@ +//===- NDS32Disassembler.cpp - Disassembler for NDS32 -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the NDS32 Disassembler. +// +//===----------------------------------------------------------------------===// + +#include "NDS32.h" +#include "NDS32RegisterInfo.h" +#include "NDS32Subtarget.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "nds32-disassembler" + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +namespace { + +class NDS32Disassembler : public MCDisassembler { + bool IsBigEndian; +public: + NDS32Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx, + bool IsBigEndian) + : MCDisassembler(STI, Ctx), + IsBigEndian(IsBigEndian) {} + + bool has16bit() const { return !STI.getFeatureBits()[NDS32::FeatureNo16Bit]; } + + DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const override; +}; + +} // end anonymous namespace + +static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodelGPRRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeJumpTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeBranchTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeBranchZeroTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeBranchTargetImm8s(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + +// Decode [Reg + Imm] addressing mode +static DecodeStatus DecodeAddrRegImm(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder, + unsigned Ra, + int32_t Imm); + +static DecodeStatus DecodeAddrWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrFPImm7uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrSPImm7uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrImm3uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrImm3uHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrImm3uByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrOffsetWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrOffsetHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeAddrOffsetByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +// Decode [Reg + Reg << Imm] addressing mode +static DecodeStatus DecodeAddrRegShift(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeImm5s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeImm11s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeImm15s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeImm20s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeRegisterList(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeLSMWModifyBase(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +#include "NDS32GenDisassemblerTables.inc" + +static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { + const NDS32Disassembler *Dis = static_cast(D); + const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo(); + return *(RegInfo->getRegClass(RC).begin() + RegNo); +} + +static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodelGPRRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeJumpTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchZeroTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTargetImm8s(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +// Decode [Reg + Imm] addressing mode +static DecodeStatus DecodeAddrRegImm(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder, + unsigned Ra, + int32_t Imm) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrImm3uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrImm3uHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrImm3uByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +// Decode [$fp + Imm7u << 2] addressing mode +static DecodeStatus DecodeAddrFPImm7uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +// Decode sp base imply [+ Imm7u << 2] addressing mode +static DecodeStatus DecodeAddrSPImm7uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrRegShift(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrOffsetWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrOffsetHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeAddrOffsetByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeImm5s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeImm11s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeImm15s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeImm20s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +static DecodeStatus DecodeRegisterList(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +// Decode mulitple load/store with base modification instructions +static DecodeStatus DecodeLSMWModifyBase(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + return MCDisassembler::Success; +} + +namespace llvm { +extern Target TheNDS32Target; +} + +static MCDisassembler *createNDS32Disassembler( + const Target &T, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new NDS32Disassembler(STI, Ctx, false); +} + +extern "C" void LLVMInitializeNDS32Disassembler() { + // Register the disassembler. + TargetRegistry::RegisterMCDisassembler(getTheNDS32Target(), + createNDS32Disassembler); +} + +/// Read two bytes from the ArrayRef and return 16 bit halfword sorted +/// according to the given endianess. +static DecodeStatus readInstruction16(ArrayRef Bytes, uint64_t Address, + uint64_t &Size, uint32_t &Insn, + bool IsBigEndian) { + // We want to read exactly 2 Bytes of data. + if (Bytes.size() < 2) { + Size = 0; + return MCDisassembler::Fail; + } + + if (IsBigEndian) { + Insn = (Bytes[0] << 8) | Bytes[1]; + } else { + Insn = (Bytes[1] << 8) | Bytes[0]; + } + + return MCDisassembler::Success; +} + +/// Read four bytes from the ArrayRef and return 32 bit word sorted +/// according to the given endianess +static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, + uint64_t &Size, uint32_t &Insn, + bool IsBigEndian) { + // We want to read exactly 4 Bytes of data. + if (Bytes.size() < 4) { + Size = 0; + return MCDisassembler::Fail; + } + + if (IsBigEndian) { + // Encoded as a big-endian 32-bit word in the stream. + Insn = + (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); + } else { + Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | + (Bytes[3] << 24); + } + + return MCDisassembler::Success; +} + +DecodeStatus NDS32Disassembler::getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const { + uint32_t Insn; + DecodeStatus Result; + + // First bit in the NDS32 instruction encoding + // indicate 32/16 bit instruction. + if (Bytes[0] & 0x80) { + Result = readInstruction16(Bytes, Address, Size, Insn, true); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + + DEBUG(dbgs() << "Trying NDS32 table (16-bit opcodes):\n"); + // Calling the auto-generated decoder function. + Result = + decodeInstruction(DecoderTable16, Instr, Insn, Address, this, STI); + + Size = 2; + } else { + Result = readInstruction32(Bytes, Address, Size, Insn, true); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + + DEBUG(dbgs() << "Trying NDS32 table (32-bit opcodes):\n"); + // Calling the auto-generated decoder function. + Result = + decodeInstruction(DecoderTable32, Instr, Insn, Address, this, STI); + + Size = 4; + } + if (Result != MCDisassembler::Fail) { + return Result; + } + + Size = 4; + return MCDisassembler::Fail; +} Index: lib/Target/NDS32/LLVMBuild.txt =================================================================== --- lib/Target/NDS32/LLVMBuild.txt +++ lib/Target/NDS32/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = TargetInfo MCTargetDesc InstPrinter AsmParser +subdirectories = TargetInfo MCTargetDesc InstPrinter AsmParser Disassembler [component_0] type = TargetGroup @@ -24,6 +24,7 @@ parent = Target has_asmprinter = 1 has_asmparser = 1 +has_disassembler = 1 [component_1] type = Library