diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index b8a69515c6f..099ad390d2a 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/lib/Target/XCore/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_TARGET_DEFINITIONS XCore.td) tablegen(LLVM XCoreGenRegisterInfo.inc -gen-register-info) tablegen(LLVM XCoreGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM XCoreGenDisassemblerTables.inc -gen-disassembler) tablegen(LLVM XCoreGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM XCoreGenDAGISel.inc -gen-dag-isel) tablegen(LLVM XCoreGenCallingConv.inc -gen-callingconv) diff --git a/lib/Target/XCore/Disassembler/Makefile b/lib/Target/XCore/Disassembler/Makefile index 2b28d39dcb9..4caffdd1da6 100644 --- a/lib/Target/XCore/Disassembler/Makefile +++ b/lib/Target/XCore/Disassembler/Makefile @@ -10,4 +10,7 @@ LEVEL = ../../../.. LIBRARYNAME = LLVMXCoreDisassembler +# Hack: we need to include 'main' XCore target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + include $(LEVEL)/Makefile.common diff --git a/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp b/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp index 16b3c208a74..d0a98d13615 100644 --- a/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp +++ b/lib/Target/XCore/Disassembler/XCoreDisassembler.cpp @@ -11,8 +11,11 @@ // //===----------------------------------------------------------------------===// +#include "XCore.h" +#include "XCoreRegisterInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" @@ -25,11 +28,12 @@ namespace { /// XCoreDisassembler - a disasembler class for XCore. class XCoreDisassembler : public MCDisassembler { + const MCRegisterInfo *RegInfo; public: /// Constructor - Initializes the disassembler. /// - XCoreDisassembler(const MCSubtargetInfo &STI) : - MCDisassembler(STI) {} + XCoreDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) : + MCDisassembler(STI), RegInfo(Info) {} /// getInstruction - See MCDisassembler. virtual DecodeStatus getInstruction(MCInst &instr, @@ -38,8 +42,50 @@ public: uint64_t address, raw_ostream &vStream, raw_ostream &cStream) const; -}; + const MCRegisterInfo *getRegInfo() const { return RegInfo; } +}; +} + +static bool readInstruction16(const MemoryObject ®ion, + uint64_t address, + uint64_t &size, + uint16_t &insn) { + uint8_t Bytes[4]; + + // We want to read exactly 2 Bytes of data. + if (region.readBytes(address, 2, Bytes, NULL) == -1) { + size = 0; + return false; + } + // Encoded as a little-endian 16-bit word in the stream. + insn = (Bytes[0] << 0) | (Bytes[1] << 8); + return true; +} + +static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { + const XCoreDisassembler *Dis = static_cast(D); + return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo); +} + + +static DecodeStatus DecodeGRRegsRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + +#include "XCoreGenDisassemblerTables.inc" + +static DecodeStatus DecodeGRRegsRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) +{ + if (RegNo > 11) + return MCDisassembler::Fail; + unsigned Reg = getReg(Decoder, XCore::GRRegsRegClassID, RegNo); + Inst.addOperand(MCOperand::CreateReg(Reg)); + return MCDisassembler::Success; } MCDisassembler::DecodeStatus @@ -49,6 +95,20 @@ XCoreDisassembler::getInstruction(MCInst &instr, uint64_t Address, raw_ostream &vStream, raw_ostream &cStream) const { + uint16_t low; + + if (!readInstruction16(Region, Address, Size, low)) { + return Fail; + } + + // Calling the auto-generated decoder function. + DecodeStatus Result = decodeInstruction(DecoderTable16, instr, low, Address, + this, STI); + if (Result != Fail) { + Size = 2; + return Result; + } + return Fail; } @@ -58,7 +118,7 @@ namespace llvm { static MCDisassembler *createXCoreDisassembler(const Target &T, const MCSubtargetInfo &STI) { - return new XCoreDisassembler(STI); + return new XCoreDisassembler(STI, T.createMCRegInfo("")); } extern "C" void LLVMInitializeXCoreDisassembler() { diff --git a/lib/Target/XCore/Makefile b/lib/Target/XCore/Makefile index 2b01ad41454..92ddc886087 100644 --- a/lib/Target/XCore/Makefile +++ b/lib/Target/XCore/Makefile @@ -14,8 +14,8 @@ TARGET = XCore # Make sure that tblgen is run, first thing. BUILT_SOURCES = XCoreGenRegisterInfo.inc XCoreGenInstrInfo.inc \ XCoreGenAsmWriter.inc \ - XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ - XCoreGenSubtargetInfo.inc + XCoreGenDAGISel.inc XCoreGenCallingConv.inc \ + XCoreGenDisassemblerTables.inc XCoreGenSubtargetInfo.inc DIRS = Disassembler InstPrinter TargetInfo MCTargetDesc diff --git a/lib/Target/XCore/XCoreInstrFormats.td b/lib/Target/XCore/XCoreInstrFormats.td index d905a5c6edf..f7fa673db81 100644 --- a/lib/Target/XCore/XCoreInstrFormats.td +++ b/lib/Target/XCore/XCoreInstrFormats.td @@ -20,6 +20,7 @@ class InstXCore pattern> let AsmString = asmstr; let Pattern = pattern; let Size = sz; + field bits<32> SoftFail = 0; } // XCore pseudo instructions format @@ -84,8 +85,14 @@ class _FL2R pattern> : InstXCore<4, outs, ins, asmstr, pattern> { } -class _F1R pattern> +class _F1R opc, dag outs, dag ins, string asmstr, list pattern> : InstXCore<2, outs, ins, asmstr, pattern> { + bits<4> a; + + let Inst{15-11} = opc{5-1}; + let Inst{10-5} = 0b111111; + let Inst{4} = opc{0}; + let Inst{3-0} = a; } class _F0R pattern> diff --git a/lib/Target/XCore/XCoreInstrInfo.td b/lib/Target/XCore/XCoreInstrInfo.td index 9b7758d8274..e41c6d934ee 100644 --- a/lib/Target/XCore/XCoreInstrInfo.td +++ b/lib/Target/XCore/XCoreInstrInfo.td @@ -946,17 +946,17 @@ def ENDIN_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src), // TODO edu, eeu, waitet, waitef, tstart, clrtp // setdp, setcp, setev, kcall // dgetreg -def MSYNC_1r : _F1R<(outs), (ins GRRegs:$i), - "msync res[$i]", - [(int_xcore_msync GRRegs:$i)]>; -def MJOIN_1r : _F1R<(outs), (ins GRRegs:$i), - "mjoin res[$i]", - [(int_xcore_mjoin GRRegs:$i)]>; +def MSYNC_1r : _F1R<0b000111, (outs), (ins GRRegs:$a), + "msync res[$a]", + [(int_xcore_msync GRRegs:$a)]>; +def MJOIN_1r : _F1R<0b000101, (outs), (ins GRRegs:$a), + "mjoin res[$a]", + [(int_xcore_mjoin GRRegs:$a)]>; let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in -def BAU_1r : _F1R<(outs), (ins GRRegs:$addr), - "bau $addr", - [(brind GRRegs:$addr)]>; +def BAU_1r : _F1R<0b001001, (outs), (ins GRRegs:$a), + "bau $a", + [(brind GRRegs:$a)]>; let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in def BR_JT : PseudoInstXCore<(outs), (ins InlineJT:$t, GRRegs:$i), @@ -969,49 +969,49 @@ def BR_JT32 : PseudoInstXCore<(outs), (ins InlineJT32:$t, GRRegs:$i), [(XCoreBR_JT32 tjumptable:$t, GRRegs:$i)]>; let Defs=[SP], neverHasSideEffects=1 in -def SETSP_1r : _F1R<(outs), (ins GRRegs:$src), - "set sp, $src", +def SETSP_1r : _F1R<0b001011, (outs), (ins GRRegs:$a), + "set sp, $a", []>; let hasCtrlDep = 1 in -def ECALLT_1r : _F1R<(outs), (ins GRRegs:$src), - "ecallt $src", +def ECALLT_1r : _F1R<0b010011, (outs), (ins GRRegs:$a), + "ecallt $a", []>; let hasCtrlDep = 1 in -def ECALLF_1r : _F1R<(outs), (ins GRRegs:$src), - "ecallf $src", +def ECALLF_1r : _F1R<0b010010, (outs), (ins GRRegs:$a), + "ecallf $a", []>; let isCall=1, // All calls clobber the link register and the non-callee-saved registers: Defs = [R0, R1, R2, R3, R11, LR], Uses = [SP] in { -def BLA_1r : _F1R<(outs), (ins GRRegs:$addr), - "bla $addr", - [(XCoreBranchLink GRRegs:$addr)]>; +def BLA_1r : _F1R<0b001000, (outs), (ins GRRegs:$a), + "bla $a", + [(XCoreBranchLink GRRegs:$a)]>; } -def SYNCR_1r : _F1R<(outs), (ins GRRegs:$r), - "syncr res[$r]", - [(int_xcore_syncr GRRegs:$r)]>; +def SYNCR_1r : _F1R<0b100001, (outs), (ins GRRegs:$a), + "syncr res[$a]", + [(int_xcore_syncr GRRegs:$a)]>; -def FREER_1r : _F1R<(outs), (ins GRRegs:$r), - "freer res[$r]", - [(int_xcore_freer GRRegs:$r)]>; +def FREER_1r : _F1R<0b000100, (outs), (ins GRRegs:$a), + "freer res[$a]", + [(int_xcore_freer GRRegs:$a)]>; let Uses=[R11] in { -def SETV_1r : _F1R<(outs), (ins GRRegs:$r), - "setv res[$r], r11", - [(int_xcore_setv GRRegs:$r, R11)]>; +def SETV_1r : _F1R<0b010001, (outs), (ins GRRegs:$a), + "setv res[$a], r11", + [(int_xcore_setv GRRegs:$a, R11)]>; -def SETEV_1r : _F1R<(outs), (ins GRRegs:$r), - "setev res[$r], r11", - [(int_xcore_setev GRRegs:$r, R11)]>; +def SETEV_1r : _F1R<0b001111, (outs), (ins GRRegs:$a), + "setev res[$a], r11", + [(int_xcore_setev GRRegs:$a, R11)]>; } -def EEU_1r : _F1R<(outs), (ins GRRegs:$r), - "eeu res[$r]", - [(int_xcore_eeu GRRegs:$r)]>; +def EEU_1r : _F1R<0b000001, (outs), (ins GRRegs:$a), + "eeu res[$a]", + [(int_xcore_eeu GRRegs:$a)]>; // Zero operand short // TODO freet, ldspc, stspc, ldssr, stssr, ldsed, stsed, diff --git a/lib/Target/XCore/XCoreRegisterInfo.td b/lib/Target/XCore/XCoreRegisterInfo.td index 9edfda1f500..4c771e97006 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.td +++ b/lib/Target/XCore/XCoreRegisterInfo.td @@ -45,10 +45,10 @@ def LR : Ri<15, "lr">, DwarfRegNum<[15]>; def GRRegs : RegisterClass<"XCore", [i32], 32, // Return values and arguments (add R0, R1, R2, R3, - // Not preserved across procedure calls - R11, // Callee save - R4, R5, R6, R7, R8, R9, R10)>; + R4, R5, R6, R7, R8, R9, R10, + // Not preserved across procedure calls + R11)>; // Reserved def RRegs : RegisterClass<"XCore", [i32], 32, (add CP, DP, SP, LR)> {