a426b286c8
patch for r263619, and unify all the URLs to point to svnweb.
763 lines
27 KiB
Diff
763 lines
27 KiB
Diff
Pull in r198591 from upstream llvm trunk (by Venkatraman Govindaraju):
|
|
|
|
[Sparc] Add initial implementation of disassembler for sparc
|
|
|
|
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
|
|
|
Index: lib/Target/Sparc/SparcInstrFormats.td
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcInstrFormats.td
|
|
+++ lib/Target/Sparc/SparcInstrFormats.td
|
|
@@ -12,6 +12,7 @@ class InstSP<dag outs, dag ins, string asmstr, lis
|
|
field bits<32> Inst;
|
|
|
|
let Namespace = "SP";
|
|
+ let Size = 4;
|
|
|
|
bits<2> op;
|
|
let Inst{31-30} = op; // Top two bits are the 'op' field
|
|
@@ -20,6 +21,9 @@ class InstSP<dag outs, dag ins, string asmstr, lis
|
|
dag InOperandList = ins;
|
|
let AsmString = asmstr;
|
|
let Pattern = pattern;
|
|
+
|
|
+ let DecoderNamespace = "Sparc";
|
|
+ field bits<32> SoftFail = 0;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
@@ -58,6 +62,27 @@ class F2_2<bits<3> op2Val, dag outs, dag ins, stri
|
|
let Inst{28-25} = cond;
|
|
}
|
|
|
|
+class F2_3<bits<3> op2Val, bits<2> ccVal, dag outs, dag ins, string asmstr,
|
|
+ list<dag> pattern>
|
|
+ : InstSP<outs, ins, asmstr, pattern> {
|
|
+ bit annul;
|
|
+ bits<4> cond;
|
|
+ bit pred;
|
|
+ bits<19> imm19;
|
|
+
|
|
+ let op = 0; // op = 0
|
|
+
|
|
+ bit annul = 0; // currently unused
|
|
+ let pred = 1; // default is predict taken
|
|
+
|
|
+ let Inst{29} = annul;
|
|
+ let Inst{28-25} = cond;
|
|
+ let Inst{24-22} = op2Val;
|
|
+ let Inst{21-20} = ccVal;
|
|
+ let Inst{19} = pred;
|
|
+ let Inst{18-0} = imm19;
|
|
+}
|
|
+
|
|
//===----------------------------------------------------------------------===//
|
|
// Format #3 instruction classes in the Sparc
|
|
//===----------------------------------------------------------------------===//
|
|
Index: lib/Target/Sparc/LLVMBuild.txt
|
|
===================================================================
|
|
--- lib/Target/Sparc/LLVMBuild.txt
|
|
+++ lib/Target/Sparc/LLVMBuild.txt
|
|
@@ -16,13 +16,15 @@
|
|
;===------------------------------------------------------------------------===;
|
|
|
|
[common]
|
|
-subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo
|
|
+subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo
|
|
|
|
[component_0]
|
|
type = TargetGroup
|
|
name = Sparc
|
|
parent = Target
|
|
+has_asmparser = 1
|
|
has_asmprinter = 1
|
|
+has_disassembler = 1
|
|
has_jit = 1
|
|
|
|
[component_1]
|
|
Index: lib/Target/Sparc/SparcInstrInfo.td
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcInstrInfo.td
|
|
+++ lib/Target/Sparc/SparcInstrInfo.td
|
|
@@ -230,13 +230,13 @@ def FCC_O : FCC_VAL<29>; // Ordered
|
|
multiclass F3_12<string OpcStr, bits<6> Op3Val, SDNode OpNode,
|
|
RegisterClass RC, ValueType Ty, Operand immOp> {
|
|
def rr : F3_1<2, Op3Val,
|
|
- (outs RC:$dst), (ins RC:$b, RC:$c),
|
|
- !strconcat(OpcStr, " $b, $c, $dst"),
|
|
- [(set Ty:$dst, (OpNode Ty:$b, Ty:$c))]>;
|
|
+ (outs RC:$rd), (ins RC:$rs1, RC:$rs2),
|
|
+ !strconcat(OpcStr, " $rs1, $rs2, $rd"),
|
|
+ [(set Ty:$rd, (OpNode Ty:$rs1, Ty:$rs2))]>;
|
|
def ri : F3_2<2, Op3Val,
|
|
- (outs RC:$dst), (ins RC:$b, immOp:$c),
|
|
- !strconcat(OpcStr, " $b, $c, $dst"),
|
|
- [(set Ty:$dst, (OpNode Ty:$b, (Ty simm13:$c)))]>;
|
|
+ (outs RC:$rd), (ins RC:$rs1, immOp:$simm13),
|
|
+ !strconcat(OpcStr, " $rs1, $simm13, $rd"),
|
|
+ [(set Ty:$rd, (OpNode Ty:$rs1, (Ty simm13:$simm13)))]>;
|
|
}
|
|
|
|
/// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no
|
|
@@ -243,11 +243,11 @@ multiclass F3_12<string OpcStr, bits<6> Op3Val, SD
|
|
/// pattern.
|
|
multiclass F3_12np<string OpcStr, bits<6> Op3Val> {
|
|
def rr : F3_1<2, Op3Val,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
|
- !strconcat(OpcStr, " $b, $c, $dst"), []>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
|
|
+ !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>;
|
|
def ri : F3_2<2, Op3Val,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
|
|
- !strconcat(OpcStr, " $b, $c, $dst"), []>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
|
|
+ !strconcat(OpcStr, " $rs1, $simm13, $rd"), []>;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
@@ -488,31 +488,31 @@ let rd = 0, imm22 = 0 in
|
|
defm AND : F3_12<"and", 0b000001, and, IntRegs, i32, i32imm>;
|
|
|
|
def ANDNrr : F3_1<2, 0b000101,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
|
- "andn $b, $c, $dst",
|
|
- [(set i32:$dst, (and i32:$b, (not i32:$c)))]>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
|
|
+ "andn $rs1, $rs2, $rd",
|
|
+ [(set i32:$rd, (and i32:$rs1, (not i32:$rs2)))]>;
|
|
def ANDNri : F3_2<2, 0b000101,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
|
|
- "andn $b, $c, $dst", []>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
|
|
+ "andn $rs1, $simm13, $rd", []>;
|
|
|
|
defm OR : F3_12<"or", 0b000010, or, IntRegs, i32, i32imm>;
|
|
|
|
def ORNrr : F3_1<2, 0b000110,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
|
- "orn $b, $c, $dst",
|
|
- [(set i32:$dst, (or i32:$b, (not i32:$c)))]>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
|
|
+ "orn $rs1, $rs2, $rd",
|
|
+ [(set i32:$rd, (or i32:$rs1, (not i32:$rs2)))]>;
|
|
def ORNri : F3_2<2, 0b000110,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
|
|
- "orn $b, $c, $dst", []>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
|
|
+ "orn $rs1, $simm13, $rd", []>;
|
|
defm XOR : F3_12<"xor", 0b000011, xor, IntRegs, i32, i32imm>;
|
|
|
|
def XNORrr : F3_1<2, 0b000111,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
|
- "xnor $b, $c, $dst",
|
|
- [(set i32:$dst, (not (xor i32:$b, i32:$c)))]>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
|
|
+ "xnor $rs1, $rs2, $rd",
|
|
+ [(set i32:$rd, (not (xor i32:$rs1, i32:$rs2)))]>;
|
|
def XNORri : F3_2<2, 0b000111,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
|
|
- "xnor $b, $c, $dst", []>;
|
|
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
|
|
+ "xnor $rs1, $simm13, $rd", []>;
|
|
|
|
// Section B.12 - Shift Instructions, p. 107
|
|
defm SLL : F3_12<"sll", 0b100101, shl, IntRegs, i32, i32imm>;
|
|
@@ -545,21 +545,15 @@ let Defs = [ICC] in
|
|
|
|
let Defs = [ICC], rd = 0 in {
|
|
def CMPrr : F3_1<2, 0b010100,
|
|
- (outs), (ins IntRegs:$b, IntRegs:$c),
|
|
- "cmp $b, $c",
|
|
- [(SPcmpicc i32:$b, i32:$c)]>;
|
|
+ (outs), (ins IntRegs:$rs1, IntRegs:$rs2),
|
|
+ "cmp $rs1, $rs2",
|
|
+ [(SPcmpicc i32:$rs1, i32:$rs2)]>;
|
|
def CMPri : F3_2<2, 0b010100,
|
|
- (outs), (ins IntRegs:$b, i32imm:$c),
|
|
- "cmp $b, $c",
|
|
- [(SPcmpicc i32:$b, (i32 simm13:$c))]>;
|
|
+ (outs), (ins IntRegs:$rs1, i32imm:$simm13),
|
|
+ "cmp $rs1, $simm13",
|
|
+ [(SPcmpicc i32:$rs1, (i32 simm13:$simm13))]>;
|
|
}
|
|
|
|
-let Uses = [ICC], Defs = [ICC] in
|
|
- def SUBXCCrr: F3_1<2, 0b011100,
|
|
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
|
- "subxcc $b, $c, $dst", []>;
|
|
-
|
|
-
|
|
// Section B.18 - Multiply Instructions, p. 113
|
|
let Defs = [Y] in {
|
|
defm UMUL : F3_12np<"umul", 0b001010>;
|
|
@@ -858,7 +852,7 @@ let Defs = [FCC] in {
|
|
//===----------------------------------------------------------------------===//
|
|
// Instructions for Thread Local Storage(TLS).
|
|
//===----------------------------------------------------------------------===//
|
|
-
|
|
+let isCodeGenOnly = 1, isAsmParserOnly = 1 in {
|
|
def TLS_ADDrr : F3_1<2, 0b000000,
|
|
(outs IntRegs:$rd),
|
|
(ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym),
|
|
@@ -882,6 +876,7 @@ let Uses = [O6], isCall = 1, hasDelaySlot = 1 in
|
|
let op = 1;
|
|
let Inst{29-0} = disp;
|
|
}
|
|
+}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// V9 Instructions
|
|
Index: lib/Target/Sparc/CMakeLists.txt
|
|
===================================================================
|
|
--- lib/Target/Sparc/CMakeLists.txt
|
|
+++ lib/Target/Sparc/CMakeLists.txt
|
|
@@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td)
|
|
tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info)
|
|
tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info)
|
|
tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter)
|
|
+tablegen(LLVM SparcGenDisassemblerTables.inc -gen-disassembler)
|
|
tablegen(LLVM SparcGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
|
|
tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer)
|
|
tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher)
|
|
@@ -34,3 +35,4 @@ add_subdirectory(TargetInfo)
|
|
add_subdirectory(MCTargetDesc)
|
|
add_subdirectory(InstPrinter)
|
|
add_subdirectory(AsmParser)
|
|
+add_subdirectory(Disassembler)
|
|
Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
|
===================================================================
|
|
--- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
|
+++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
|
@@ -0,0 +1,228 @@
|
|
+//===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- 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 Sparc Disassembler.
|
|
+//
|
|
+//===----------------------------------------------------------------------===//
|
|
+
|
|
+#define DEBUG_TYPE "sparc-disassembler"
|
|
+
|
|
+#include "Sparc.h"
|
|
+#include "SparcRegisterInfo.h"
|
|
+#include "SparcSubtarget.h"
|
|
+#include "llvm/MC/MCDisassembler.h"
|
|
+#include "llvm/MC/MCFixedLenDisassembler.h"
|
|
+#include "llvm/Support/MemoryObject.h"
|
|
+#include "llvm/Support/TargetRegistry.h"
|
|
+
|
|
+using namespace llvm;
|
|
+
|
|
+typedef MCDisassembler::DecodeStatus DecodeStatus;
|
|
+
|
|
+namespace {
|
|
+
|
|
+/// SparcDisassembler - a disassembler class for Sparc.
|
|
+class SparcDisassembler : public MCDisassembler {
|
|
+public:
|
|
+ /// Constructor - Initializes the disassembler.
|
|
+ ///
|
|
+ SparcDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) :
|
|
+ MCDisassembler(STI), RegInfo(Info)
|
|
+ {}
|
|
+ virtual ~SparcDisassembler() {}
|
|
+
|
|
+ const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); }
|
|
+
|
|
+ /// getInstruction - See MCDisassembler.
|
|
+ virtual DecodeStatus getInstruction(MCInst &instr,
|
|
+ uint64_t &size,
|
|
+ const MemoryObject ®ion,
|
|
+ uint64_t address,
|
|
+ raw_ostream &vStream,
|
|
+ raw_ostream &cStream) const;
|
|
+private:
|
|
+ OwningPtr<const MCRegisterInfo> RegInfo;
|
|
+};
|
|
+
|
|
+}
|
|
+
|
|
+namespace llvm {
|
|
+ extern Target TheSparcTarget, TheSparcV9Target;
|
|
+}
|
|
+
|
|
+static MCDisassembler *createSparcDisassembler(
|
|
+ const Target &T,
|
|
+ const MCSubtargetInfo &STI) {
|
|
+ return new SparcDisassembler(STI, T.createMCRegInfo(""));
|
|
+}
|
|
+
|
|
+
|
|
+extern "C" void LLVMInitializeSparcDisassembler() {
|
|
+ // Register the disassembler.
|
|
+ TargetRegistry::RegisterMCDisassembler(TheSparcTarget,
|
|
+ createSparcDisassembler);
|
|
+ TargetRegistry::RegisterMCDisassembler(TheSparcV9Target,
|
|
+ createSparcDisassembler);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+static const unsigned IntRegDecoderTable[] = {
|
|
+ SP::G0, SP::G1, SP::G2, SP::G3,
|
|
+ SP::G4, SP::G5, SP::G6, SP::G7,
|
|
+ SP::O0, SP::O1, SP::O2, SP::O3,
|
|
+ SP::O4, SP::O5, SP::O6, SP::O7,
|
|
+ SP::L0, SP::L1, SP::L2, SP::L3,
|
|
+ SP::L4, SP::L5, SP::L6, SP::L7,
|
|
+ SP::I0, SP::I1, SP::I2, SP::I3,
|
|
+ SP::I4, SP::I5, SP::I6, SP::I7 };
|
|
+
|
|
+static const unsigned FPRegDecoderTable[] = {
|
|
+ SP::F0, SP::F1, SP::F2, SP::F3,
|
|
+ SP::F4, SP::F5, SP::F6, SP::F7,
|
|
+ SP::F8, SP::F9, SP::F10, SP::F11,
|
|
+ SP::F12, SP::F13, SP::F14, SP::F15,
|
|
+ SP::F16, SP::F17, SP::F18, SP::F19,
|
|
+ SP::F20, SP::F21, SP::F22, SP::F23,
|
|
+ SP::F24, SP::F25, SP::F26, SP::F27,
|
|
+ SP::F28, SP::F29, SP::F30, SP::F31 };
|
|
+
|
|
+static const unsigned DFPRegDecoderTable[] = {
|
|
+ SP::D0, SP::D16, SP::D1, SP::D17,
|
|
+ SP::D2, SP::D18, SP::D3, SP::D19,
|
|
+ SP::D4, SP::D20, SP::D5, SP::D21,
|
|
+ SP::D6, SP::D22, SP::D7, SP::D23,
|
|
+ SP::D8, SP::D24, SP::D9, SP::D25,
|
|
+ SP::D10, SP::D26, SP::D11, SP::D27,
|
|
+ SP::D12, SP::D28, SP::D13, SP::D29,
|
|
+ SP::D14, SP::D30, SP::D15, SP::D31 };
|
|
+
|
|
+static const unsigned QFPRegDecoderTable[] = {
|
|
+ SP::Q0, SP::Q8, -1, -1,
|
|
+ SP::Q1, SP::Q9, -1, -1,
|
|
+ SP::Q2, SP::Q10, -1, -1,
|
|
+ SP::Q3, SP::Q11, -1, -1,
|
|
+ SP::Q4, SP::Q12, -1, -1,
|
|
+ SP::Q5, SP::Q13, -1, -1,
|
|
+ SP::Q6, SP::Q14, -1, -1,
|
|
+ SP::Q7, SP::Q15, -1, -1 } ;
|
|
+
|
|
+static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst,
|
|
+ unsigned RegNo,
|
|
+ uint64_t Address,
|
|
+ const void *Decoder) {
|
|
+ if (RegNo > 31)
|
|
+ return MCDisassembler::Fail;
|
|
+ unsigned Reg = IntRegDecoderTable[RegNo];
|
|
+ Inst.addOperand(MCOperand::CreateReg(Reg));
|
|
+ return MCDisassembler::Success;
|
|
+}
|
|
+
|
|
+static DecodeStatus DecodeI64RegsRegisterClass(MCInst &Inst,
|
|
+ unsigned RegNo,
|
|
+ uint64_t Address,
|
|
+ const void *Decoder) {
|
|
+ if (RegNo > 31)
|
|
+ return MCDisassembler::Fail;
|
|
+ unsigned Reg = IntRegDecoderTable[RegNo];
|
|
+ Inst.addOperand(MCOperand::CreateReg(Reg));
|
|
+ return MCDisassembler::Success;
|
|
+}
|
|
+
|
|
+
|
|
+static DecodeStatus DecodeFPRegsRegisterClass(MCInst &Inst,
|
|
+ unsigned RegNo,
|
|
+ uint64_t Address,
|
|
+ const void *Decoder) {
|
|
+ if (RegNo > 31)
|
|
+ return MCDisassembler::Fail;
|
|
+ unsigned Reg = FPRegDecoderTable[RegNo];
|
|
+ Inst.addOperand(MCOperand::CreateReg(Reg));
|
|
+ return MCDisassembler::Success;
|
|
+}
|
|
+
|
|
+
|
|
+static DecodeStatus DecodeDFPRegsRegisterClass(MCInst &Inst,
|
|
+ unsigned RegNo,
|
|
+ uint64_t Address,
|
|
+ const void *Decoder) {
|
|
+ if (RegNo > 31)
|
|
+ return MCDisassembler::Fail;
|
|
+ unsigned Reg = DFPRegDecoderTable[RegNo];
|
|
+ Inst.addOperand(MCOperand::CreateReg(Reg));
|
|
+ return MCDisassembler::Success;
|
|
+}
|
|
+
|
|
+
|
|
+static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst,
|
|
+ unsigned RegNo,
|
|
+ uint64_t Address,
|
|
+ const void *Decoder) {
|
|
+ if (RegNo > 31)
|
|
+ return MCDisassembler::Fail;
|
|
+
|
|
+ unsigned Reg = QFPRegDecoderTable[RegNo];
|
|
+ if (Reg == (unsigned)-1)
|
|
+ return MCDisassembler::Fail;
|
|
+ Inst.addOperand(MCOperand::CreateReg(Reg));
|
|
+ return MCDisassembler::Success;
|
|
+}
|
|
+
|
|
+
|
|
+#include "SparcGenDisassemblerTables.inc"
|
|
+
|
|
+/// readInstruction - read four bytes from the MemoryObject
|
|
+/// and return 32 bit word.
|
|
+static DecodeStatus readInstruction32(const MemoryObject ®ion,
|
|
+ uint64_t address,
|
|
+ uint64_t &size,
|
|
+ uint32_t &insn) {
|
|
+ uint8_t Bytes[4];
|
|
+
|
|
+ // We want to read exactly 4 Bytes of data.
|
|
+ if (region.readBytes(address, 4, Bytes) == -1) {
|
|
+ size = 0;
|
|
+ return MCDisassembler::Fail;
|
|
+ }
|
|
+
|
|
+ // Encoded as a big-endian 32-bit word in the stream.
|
|
+ insn = (Bytes[3] << 0) |
|
|
+ (Bytes[2] << 8) |
|
|
+ (Bytes[1] << 16) |
|
|
+ (Bytes[0] << 24);
|
|
+
|
|
+ return MCDisassembler::Success;
|
|
+}
|
|
+
|
|
+
|
|
+DecodeStatus
|
|
+SparcDisassembler::getInstruction(MCInst &instr,
|
|
+ uint64_t &Size,
|
|
+ const MemoryObject &Region,
|
|
+ uint64_t Address,
|
|
+ raw_ostream &vStream,
|
|
+ raw_ostream &cStream) const {
|
|
+ uint32_t Insn;
|
|
+
|
|
+ DecodeStatus Result = readInstruction32(Region, Address, Size, Insn);
|
|
+ if (Result == MCDisassembler::Fail)
|
|
+ return MCDisassembler::Fail;
|
|
+
|
|
+
|
|
+ // Calling the auto-generated decoder function.
|
|
+ Result = decodeInstruction(DecoderTableSparc32, instr, Insn, Address,
|
|
+ this, STI);
|
|
+
|
|
+ if (Result != MCDisassembler::Fail) {
|
|
+ Size = 4;
|
|
+ return Result;
|
|
+ }
|
|
+
|
|
+ return MCDisassembler::Fail;
|
|
+}
|
|
Index: lib/Target/Sparc/Disassembler/LLVMBuild.txt
|
|
===================================================================
|
|
--- lib/Target/Sparc/Disassembler/LLVMBuild.txt
|
|
+++ lib/Target/Sparc/Disassembler/LLVMBuild.txt
|
|
@@ -0,0 +1,23 @@
|
|
+;===- ./lib/Target/Sparc/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 = SparcDisassembler
|
|
+parent = Sparc
|
|
+required_libraries = MC Support SparcInfo
|
|
+add_to_library_groups = Sparc
|
|
Index: lib/Target/Sparc/Disassembler/CMakeLists.txt
|
|
===================================================================
|
|
--- lib/Target/Sparc/Disassembler/CMakeLists.txt
|
|
+++ lib/Target/Sparc/Disassembler/CMakeLists.txt
|
|
@@ -0,0 +1,12 @@
|
|
+add_llvm_library(LLVMSparcDisassembler
|
|
+ SparcDisassembler.cpp
|
|
+ )
|
|
+
|
|
+# workaround for hanging compilation on MSVC9 and 10
|
|
+if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500
|
|
+ OR MSVC_VERSION EQUAL 1600 )
|
|
+set_property(
|
|
+ SOURCE SparcDisassembler.cpp
|
|
+ PROPERTY COMPILE_FLAGS "/Od"
|
|
+ )
|
|
+endif()
|
|
Index: lib/Target/Sparc/Disassembler/Makefile
|
|
===================================================================
|
|
--- lib/Target/Sparc/Disassembler/Makefile
|
|
+++ lib/Target/Sparc/Disassembler/Makefile
|
|
@@ -0,0 +1,16 @@
|
|
+##===- lib/Target/Sparc/Disassembler/Makefile --------------*- Makefile -*-===##
|
|
+#
|
|
+# The LLVM Compiler Infrastructure
|
|
+#
|
|
+# This file is distributed under the University of Illinois Open Source
|
|
+# License. See LICENSE.TXT for details.
|
|
+#
|
|
+##===----------------------------------------------------------------------===##
|
|
+
|
|
+LEVEL = ../../../..
|
|
+LIBRARYNAME = LLVMSparcDisassembler
|
|
+
|
|
+# Hack: we need to include 'main' Sparc target directory to grab private headers
|
|
+CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
|
+
|
|
+include $(LEVEL)/Makefile.common
|
|
Index: lib/Target/Sparc/Makefile
|
|
===================================================================
|
|
--- lib/Target/Sparc/Makefile
|
|
+++ lib/Target/Sparc/Makefile
|
|
@@ -14,11 +14,11 @@ TARGET = Sparc
|
|
# Make sure that tblgen is run, first thing.
|
|
BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \
|
|
SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
|
|
- SparcGenDAGISel.inc \
|
|
+ SparcGenDAGISel.inc SparcGenDisassemblerTables.inc \
|
|
SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
|
|
SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc
|
|
|
|
-DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc
|
|
+DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
|
|
|
|
include $(LEVEL)/Makefile.common
|
|
|
|
Index: lib/Target/Sparc/SparcInstr64Bit.td
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcInstr64Bit.td
|
|
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
|
@@ -141,6 +141,7 @@ def : Pat<(i64 imm:$val),
|
|
let Predicates = [Is64Bit] in {
|
|
|
|
// Register-register instructions.
|
|
+let isCodeGenOnly = 1 in {
|
|
defm ANDX : F3_12<"and", 0b000001, and, I64Regs, i64, i64imm>;
|
|
defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>;
|
|
defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>;
|
|
@@ -161,8 +162,6 @@ def XNORXrr : F3_1<2, 0b000111,
|
|
defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
|
|
defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
|
|
|
|
-def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
|
|
-
|
|
def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd),
|
|
(ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym),
|
|
"add $rs1, $rs2, $rd, $sym",
|
|
@@ -169,18 +168,17 @@ def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$
|
|
[(set i64:$rd,
|
|
(tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>;
|
|
|
|
-// Register-immediate instructions.
|
|
-
|
|
-def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>;
|
|
-
|
|
-def : Pat<(ctpop i64:$src), (POPCrr $src)>;
|
|
-
|
|
// "LEA" form of add
|
|
-let isCodeGenOnly = 1 in
|
|
def LEAX_ADDri : F3_2<2, 0b000000,
|
|
(outs I64Regs:$dst), (ins MEMri:$addr),
|
|
"add ${addr:arith}, $dst",
|
|
[(set iPTR:$dst, ADDRri:$addr)]>;
|
|
+}
|
|
+
|
|
+def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
|
|
+def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>;
|
|
+def : Pat<(ctpop i64:$src), (POPCrr $src)>;
|
|
+
|
|
} // Predicates = [Is64Bit]
|
|
|
|
|
|
@@ -245,7 +243,7 @@ def LDXri : F3_2<3, 0b001011,
|
|
(outs I64Regs:$dst), (ins MEMri:$addr),
|
|
"ldx [$addr], $dst",
|
|
[(set i64:$dst, (load ADDRri:$addr))]>;
|
|
-let mayLoad = 1 in
|
|
+let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in
|
|
def TLS_LDXrr : F3_1<3, 0b001011,
|
|
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
|
|
"ldx [$addr], $dst, $sym",
|
|
@@ -278,11 +276,11 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr
|
|
def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>;
|
|
|
|
// Sign-extending load of i32 into i64 is a new SPARC v9 instruction.
|
|
-def LDSWrr : F3_1<3, 0b001011,
|
|
+def LDSWrr : F3_1<3, 0b001000,
|
|
(outs I64Regs:$dst), (ins MEMrr:$addr),
|
|
"ldsw [$addr], $dst",
|
|
[(set i64:$dst, (sextloadi32 ADDRrr:$addr))]>;
|
|
-def LDSWri : F3_2<3, 0b001011,
|
|
+def LDSWri : F3_2<3, 0b001000,
|
|
(outs I64Regs:$dst), (ins MEMri:$addr),
|
|
"ldsw [$addr], $dst",
|
|
[(set i64:$dst, (sextloadi32 ADDRri:$addr))]>;
|
|
@@ -289,13 +287,13 @@ def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri
|
|
|
|
// 64-bit stores.
|
|
def STXrr : F3_1<3, 0b001110,
|
|
- (outs), (ins MEMrr:$addr, I64Regs:$src),
|
|
- "stx $src, [$addr]",
|
|
- [(store i64:$src, ADDRrr:$addr)]>;
|
|
+ (outs), (ins MEMrr:$addr, I64Regs:$rd),
|
|
+ "stx $rd, [$addr]",
|
|
+ [(store i64:$rd, ADDRrr:$addr)]>;
|
|
def STXri : F3_2<3, 0b001110,
|
|
- (outs), (ins MEMri:$addr, I64Regs:$src),
|
|
- "stx $src, [$addr]",
|
|
- [(store i64:$src, ADDRri:$addr)]>;
|
|
+ (outs), (ins MEMri:$addr, I64Regs:$rd),
|
|
+ "stx $rd, [$addr]",
|
|
+ [(store i64:$rd, ADDRri:$addr)]>;
|
|
|
|
// Truncating stores from i64 are identical to the i32 stores.
|
|
def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>;
|
|
@@ -315,6 +313,15 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADD
|
|
//===----------------------------------------------------------------------===//
|
|
// 64-bit Conditionals.
|
|
//===----------------------------------------------------------------------===//
|
|
+
|
|
+// Conditional branch class on %xcc:
|
|
+class XBranchSP<dag ins, string asmstr, list<dag> pattern>
|
|
+ : F2_3<0b001, 0b10, (outs), ins, asmstr, pattern> {
|
|
+ let isBranch = 1;
|
|
+ let isTerminator = 1;
|
|
+ let hasDelaySlot = 1;
|
|
+}
|
|
+
|
|
//
|
|
// Flag-setting instructions like subcc and addcc set both icc and xcc flags.
|
|
// The icc flags correspond to the 32-bit result, and the xcc are for the
|
|
@@ -326,7 +333,7 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADD
|
|
let Predicates = [Is64Bit] in {
|
|
|
|
let Uses = [ICC] in
|
|
-def BPXCC : BranchSP<(ins brtarget:$imm22, CCOp:$cond),
|
|
+def BPXCC : XBranchSP<(ins brtarget:$imm22, CCOp:$cond),
|
|
"b$cond %xcc, $imm22",
|
|
[(SPbrxcc bb:$imm22, imm:$cond)]>;
|
|
|
|
@@ -409,7 +416,7 @@ def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, im
|
|
|
|
|
|
// 64 bit SETHI
|
|
-let Predicates = [Is64Bit] in {
|
|
+let Predicates = [Is64Bit], isCodeGenOnly = 1 in {
|
|
def SETHIXi : F2_1<0b100,
|
|
(outs IntRegs:$rd), (ins i64imm:$imm22),
|
|
"sethi $imm22, $rd",
|
|
Index: test/MC/Disassembler/Sparc/lit.local.cfg
|
|
===================================================================
|
|
--- test/MC/Disassembler/Sparc/lit.local.cfg
|
|
+++ test/MC/Disassembler/Sparc/lit.local.cfg
|
|
@@ -0,0 +1,4 @@
|
|
+targets = set(config.root.targets_to_build.split())
|
|
+if not 'Sparc' in targets:
|
|
+ config.unsupported = True
|
|
+
|
|
Index: test/MC/Disassembler/Sparc/sparc.txt
|
|
===================================================================
|
|
--- test/MC/Disassembler/Sparc/sparc.txt
|
|
+++ test/MC/Disassembler/Sparc/sparc.txt
|
|
@@ -0,0 +1,82 @@
|
|
+# RUN: llvm-mc --disassemble %s -triple=sparc-unknown-linux | FileCheck %s
|
|
+
|
|
+# CHECK: add %g0, %g0, %g0
|
|
+0x80 0x00 0x00 0x00
|
|
+
|
|
+# CHECK: add %g1, %g2, %g3
|
|
+0x86 0x00 0x40 0x02
|
|
+
|
|
+# CHECK: add %o0, %o1, %l0
|
|
+0xa0 0x02 0x00 0x09
|
|
+
|
|
+# CHECK: add %o0, 10, %l0
|
|
+0xa0 0x02 0x20 0x0a
|
|
+
|
|
+# CHECK: addcc %g1, %g2, %g3
|
|
+0x86 0x80 0x40 0x02
|
|
+
|
|
+# CHECK: addxcc %g1, %g2, %g3
|
|
+0x86 0xc0 0x40 0x02
|
|
+
|
|
+# CHECK: udiv %g1, %g2, %g3
|
|
+0x86 0x70 0x40 0x02
|
|
+
|
|
+# CHECK: sdiv %g1, %g2, %g3
|
|
+0x86 0x78 0x40 0x02
|
|
+
|
|
+# CHECK: and %g1, %g2, %g3
|
|
+0x86 0x08 0x40 0x02
|
|
+
|
|
+# CHECK: andn %g1, %g2, %g3
|
|
+0x86 0x28 0x40 0x02
|
|
+
|
|
+# CHECK: or %g1, %g2, %g3
|
|
+0x86 0x10 0x40 0x02
|
|
+
|
|
+# CHECK: orn %g1, %g2, %g3
|
|
+0x86 0x30 0x40 0x02
|
|
+
|
|
+# CHECK: xor %g1, %g2, %g3
|
|
+0x86 0x18 0x40 0x02
|
|
+
|
|
+# CHECK: xnor %g1, %g2, %g3
|
|
+0x86 0x38 0x40 0x02
|
|
+
|
|
+# CHECK: umul %g1, %g2, %g3
|
|
+0x86 0x50 0x40 0x02
|
|
+
|
|
+# CHECK: smul %g1, %g2, %g3
|
|
+0x86 0x58 0x40 0x02
|
|
+
|
|
+# CHECK: nop
|
|
+0x01 0x00 0x00 0x00
|
|
+
|
|
+# CHECK: sethi 10, %l0
|
|
+0x21 0x00 0x00 0x0a
|
|
+
|
|
+# CHECK: sll %g1, %g2, %g3
|
|
+0x87 0x28 0x40 0x02
|
|
+
|
|
+# CHECK: sll %g1, 31, %g3
|
|
+0x87 0x28 0x60 0x1f
|
|
+
|
|
+# CHECK: srl %g1, %g2, %g3
|
|
+0x87 0x30 0x40 0x02
|
|
+
|
|
+# CHECK: srl %g1, 31, %g3
|
|
+0x87 0x30 0x60 0x1f
|
|
+
|
|
+# CHECK: sra %g1, %g2, %g3
|
|
+0x87 0x38 0x40 0x02
|
|
+
|
|
+# CHECK: sra %g1, 31, %g3
|
|
+0x87 0x38 0x60 0x1f
|
|
+
|
|
+# CHECK: sub %g1, %g2, %g3
|
|
+0x86 0x20 0x40 0x02
|
|
+
|
|
+# CHECK: subcc %g1, %g2, %g3
|
|
+0x86 0xa0 0x40 0x02
|
|
+
|
|
+# CHECK: subxcc %g1, %g2, %g3
|
|
+0x86 0xe0 0x40 0x02
|