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,645 @@ +//===- 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 DecodemGPRRegisterClass(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) { + if (RegNo > 31) + return MCDisassembler::Fail; + unsigned Reg = getReg(Decoder, NDS32::GPRRegClassID, RegNo); + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodelGPRRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 7) + return MCDisassembler::Fail; + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodemGPRRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 19 || (RegNo > 11 && RegNo < 16)) + return MCDisassembler::Fail; + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeJumpTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = (SignExtend32<24>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = (SignExtend32<14>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchZeroTarget(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = (SignExtend32<16>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTargetImm8s(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = (SignExtend32<8>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); + return MCDisassembler::Success; +} + +static bool Check(DecodeStatus &Out, DecodeStatus In) { + switch (In) { + case MCDisassembler::Success: + // Out stays the same. + return true; + case MCDisassembler::SoftFail: + Out = In; + return true; + case MCDisassembler::Fail: + Out = In; + return false; + } + llvm_unreachable("Invalid DecodeStatus!"); +} + +// Decode [Reg + Imm] addressing mode +static DecodeStatus DecodeAddrRegImm(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder, + unsigned Ra, + int32_t Imm) { + DecodeStatus S = MCDisassembler::Success; + + if (!Check(S, DecodeGPRRegisterClass(Inst, Ra, Address, Decoder))) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static DecodeStatus DecodeAddrWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Value = fieldFromInstruction(Insn, 0, 15) * 4; + int32_t Imm = SignExtend32<17>(Value); + unsigned Ra = fieldFromInstruction(Insn, 15, 5); + + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, Ra, Imm); +} + +static DecodeStatus DecodeAddrHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Value = fieldFromInstruction(Insn, 0, 15) * 2; + int32_t Imm = SignExtend32<16>(Value); + unsigned Ra = fieldFromInstruction(Insn, 15, 5); + + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, Ra, Imm); +} + +static DecodeStatus DecodeAddrByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Value = fieldFromInstruction(Insn, 0, 15); + int32_t Imm = SignExtend32<15>(Value); + unsigned Ra = fieldFromInstruction(Insn, 15, 5); + + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, Ra, Imm); +} + +static DecodeStatus DecodeAddrImm3uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Imm = fieldFromInstruction(Insn, 0, 3) * 4; + unsigned Ra = fieldFromInstruction(Insn, 3, 3); + + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, Ra, Imm); +} + +static DecodeStatus DecodeAddrImm3uHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Imm = fieldFromInstruction(Insn, 0, 3) * 2; + unsigned Ra = fieldFromInstruction(Insn, 3, 3); + + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, Ra, Imm); +} + +static DecodeStatus DecodeAddrImm3uByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Imm = fieldFromInstruction(Insn, 0, 3); + unsigned Ra = fieldFromInstruction(Insn, 3, 3); + + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, Ra, Imm); +} + +// Decode [$fp + Imm7u << 2] addressing mode +static DecodeStatus DecodeAddrFPImm7uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Imm = fieldFromInstruction(Insn, 0, 7) * 4; + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, 28, Imm); +} + +// Decode sp base imply [+ Imm7u << 2] addressing mode +static DecodeStatus DecodeAddrSPImm7uWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int32_t Imm = fieldFromInstruction(Insn, 0, 7) * 4; + return DecodeAddrRegImm(Inst, Insn, Address, Decoder, 31, Imm); +} + +static DecodeStatus DecodeAddrRegShift(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + unsigned Ra = fieldFromInstruction(Insn, 5, 5); + unsigned Rb = fieldFromInstruction(Insn, 2, 5); + unsigned sv = fieldFromInstruction(Insn, 0, 2); + + if (!Check(S, DecodeGPRRegisterClass(Inst, Ra, Address, Decoder))) + return MCDisassembler::Fail; + if (!Check(S, DecodeGPRRegisterClass(Inst, Rb, Address, Decoder))) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::createImm(sv)); + + return S; +} + +static DecodeStatus DecodeAddrOffsetWord(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Value = fieldFromInstruction(Insn, 0, 15) * 4; + int32_t Imm = SignExtend32<17>(Value); + + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static DecodeStatus DecodeAddrOffsetHalf(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Value = fieldFromInstruction(Insn, 0, 15) * 2; + int32_t Imm = SignExtend32<16>(Value); + + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static DecodeStatus DecodeAddrOffsetByte(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Value = fieldFromInstruction(Insn, 0, 15); + int32_t Imm = SignExtend32<15>(Value); + + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static DecodeStatus DecodeImm5s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Value = fieldFromInstruction(Insn, 0, 5); + int32_t Imm = SignExtend32<5>(Value); + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static DecodeStatus DecodeImm11s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Value = fieldFromInstruction(Insn, 0, 11); + int32_t Imm = SignExtend32<11>(Value); + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static DecodeStatus DecodeImm15s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Value = fieldFromInstruction(Insn, 0, 15); + int32_t Imm = SignExtend32<15>(Value); + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static DecodeStatus DecodeImm20s(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Value = fieldFromInstruction(Insn, 0, 20); + int32_t Imm = SignExtend32<20>(Value); + Inst.addOperand(MCOperand::createImm(Imm)); + + return S; +} + +static void addEnable4Regs(MCInst &Inst, + int32_t Enable4, + const void *Decoder) { + if (Enable4 & 1) + Inst.addOperand(MCOperand::createReg(NDS32::SP)); + if (Enable4 & 2) + Inst.addOperand(MCOperand::createReg(NDS32::LP)); + if (Enable4 & 4) + Inst.addOperand(MCOperand::createReg(NDS32::GP)); + if (Enable4 & 8) + Inst.addOperand(MCOperand::createReg(NDS32::FP)); +} + +static DecodeStatus DecodeRegisterList(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Enable4 = fieldFromInstruction(Insn, 0, 4); + int32_t ReEnc = fieldFromInstruction(Insn, 4, 5); + int32_t RaEnc = fieldFromInstruction(Insn, 9, 5); + int32_t RbEnc = fieldFromInstruction(Insn, 14, 5); + unsigned I, Re, Ra, Rb; + + Re = getReg(Decoder, NDS32::GPRRegClassID, ReEnc); + Ra = getReg(Decoder, NDS32::GPRRegClassID, RaEnc); + Rb = getReg(Decoder, NDS32::GPRRegClassID, RbEnc); + + // Insert base register first + Inst.addOperand(MCOperand::createReg(Ra)); + + if (Rb != Re) { + for (I = Rb; I <= Re; I++) + Inst.addOperand(MCOperand::createReg(I)); + } + + addEnable4Regs(Inst, Enable4, Decoder); + + return S; +} + +// Decode mulitple load/store with base modification instructions +static DecodeStatus DecodeLSMWModifyBase(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + DecodeStatus S = MCDisassembler::Success; + int32_t Enable4 = fieldFromInstruction(Insn, 6, 4); + int32_t ReEnc = fieldFromInstruction(Insn, 10, 5); + int32_t RaEnc = fieldFromInstruction(Insn, 15, 5); + int32_t RbEnc = fieldFromInstruction(Insn, 20, 5); + unsigned I, Re, Ra, Rb; + + Re = getReg(Decoder, NDS32::GPRRegClassID, ReEnc); + Ra = getReg(Decoder, NDS32::GPRRegClassID, RaEnc); + Rb = getReg(Decoder, NDS32::GPRRegClassID, RbEnc); + + // Insert wb, Ra register first + Inst.addOperand(MCOperand::createReg(Ra)); + Inst.addOperand(MCOperand::createReg(Ra)); + + if (Rb != Re) { + for (I = Rb; I <= Re; I++) + Inst.addOperand(MCOperand::createReg(I)); + } + + addEnable4Regs(Inst, Enable4, Decoder); + + return S; +} + +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(TheNDS32Target, + 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