summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-07-25 12:13:35 +0000
committerChris Lattner <sabre@nondot.org>2004-07-25 12:13:35 +0000
commit002f29b0f061a5401f63d69466bce00fdefbcfbb (patch)
tree7f78a0855d17ef6d96ffdb0da5a621b88aec90b8 /test
parent70e9b59b0e142e3a965ac6b1c2cf19d8cf76b23f (diff)
downloadllvm-002f29b0f061a5401f63d69466bce00fdefbcfbb.tar.gz
llvm-002f29b0f061a5401f63d69466bce00fdefbcfbb.tar.bz2
llvm-002f29b0f061a5401f63d69466bce00fdefbcfbb.tar.xz
Codify my thoughts on where we want to end up with the target-independent
code generator. Comments welcome. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15205 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/TableGen/TargetInstrInfo.td148
1 files changed, 148 insertions, 0 deletions
diff --git a/test/TableGen/TargetInstrInfo.td b/test/TableGen/TargetInstrInfo.td
new file mode 100644
index 0000000000..bbee7430f5
--- /dev/null
+++ b/test/TableGen/TargetInstrInfo.td
@@ -0,0 +1,148 @@
+// This test describes how we eventually want to describe instructions in
+// the target independent code generators.
+// RUN: tblgen %s
+
+// Target indep stuff.
+class Instruction { // Would have other stuff eventually
+ bit isTwoAddress = 0;
+ string AssemblyString;
+}
+class RegisterClass;
+
+class RTLNode;
+
+def ops; // Marker for operand list.
+
+// Various expressions used in RTL descriptions.
+def imm8 : RTLNode;
+def imm32 : RTLNode;
+def addr : RTLNode;
+
+def set : RTLNode;
+def signext : RTLNode;
+def zeroext : RTLNode;
+def plus : RTLNode;
+def and : RTLNode;
+def xor : RTLNode;
+def shl : RTLNode;
+def load : RTLNode;
+def store : RTLNode;
+def unspec : RTLNode;
+
+// Start of X86 specific stuff.
+
+def R8 : RegisterClass;
+def R16 : RegisterClass;
+def R32 : RegisterClass;
+
+def CL; // As are currently defined
+def AL;
+def AX;
+def EDX;
+
+class Format<bits<5> val> {
+ bits<5> Value = val;
+}
+
+def Pseudo : Format<0>; def RawFrm : Format<1>;
+def AddRegFrm : Format<2>; def MRMDestReg : Format<3>;
+def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>;
+def MRMSrcMem : Format<6>;
+def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>;
+def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>;
+def MRM6r : Format<22>; def MRM7r : Format<23>;
+def MRM0m : Format<24>; def MRM1m : Format<25>; def MRM2m : Format<26>;
+def MRM3m : Format<27>; def MRM4m : Format<28>; def MRM5m : Format<29>;
+def MRM6m : Format<30>; def MRM7m : Format<31>;
+
+
+class Inst<dag opnds, string asmstr, bits<8> opcode,
+ Format f, list<dag> rtl> : Instruction {
+ dag Operands = opnds;
+ string AssemblyString = asmstr;
+ bits<8> Opcode = opcode;
+ Format Format = f;
+ list<dag> RTL = rtl;
+}
+
+
+// Start of instruction definitions, the real point of this file.
+//
+// Note that these patterns show a couple of important things:
+// 1. The order and contents of the operands of the MachineInstr are
+// described here. Eventually we can do away with this when everything
+// is generated from the description.
+// 2. The asm string is captured here, which makes it possible to get rid of
+// a ton of hacks in the various printers and a bunch of flags.
+// 3. Target specific properties (e.g. Format) can still be captured as
+// needed.
+// 4. We capture the behavior of the instruction with a simplified RTL-like
+// expression.
+// 5. The use/def properties for each operand are automatically inferred from
+// the pattern.
+// 6. Address expressions should become first-class entities.
+
+// Simple copy instruction. isMoveInstr could easily be inferred from this,
+// as could MRegisterInfo::copyRegToReg.
+def MOV8rr : Inst<(ops R8:$dst, R8:$src),
+ "mov $dst, $src", 0x88, MRMDestReg,
+ [(set R8:$dst, R8:$src)]>;
+
+// Simple immediate initialization.
+def MOV8ri : Inst<(ops R8:$dst, imm8:$src),
+ "mov $dst, $src", 0xB0, AddRegFrm,
+ [(set R8:$dst, imm8:$src)]>;
+
+// Two address instructions are described as three-addr instructions, with
+// the special target-independent isTwoAddress flag set. The asm pattern
+// should not refer to the $src1, this would be enforced by the
+// TargetInstrInfo tablegen backend.
+let isTwoAddress = 1 in
+def AND8rr : Inst<(ops R8:$dst, R8:$src1, R8:$src2),
+ "and $dst, $src2", 0x20, MRMDestReg,
+ [(set R8:$dst, (and R8:$src1, R8:$src2))]>;
+
+// Instructions that have explicit uses/defs make them explicit in the RTL.
+// Instructions that need extra stuff emitted in the assembly can, trivially.
+let isTwoAddress = 1 in
+def SHL32rCL : Inst<(ops R32:$dst, R32:$src),
+ "shl $dst, CL", 0xD2, MRM4r,
+ [(set R32:$dst, (shl R32:$src, CL))]>;
+
+// The RTL list is a list, allowing complex instructions to be defined easily.
+// Temporary 'internal' registers can be used to break instructions appart.
+let isTwoAddress = 1 in
+def XOR32mi : Inst<(ops addr:$addr, imm32:$imm),
+ "xor $dst, $src2", 0x81, MRM6m,
+ [(set R32:$tmp1, (load addr:$addr)),
+ (set R32:$tmp2, (xor R32:$tmp1, imm32:$imm)),
+ (store addr:$addr, R32:$tmp2)]>;
+
+// Alternatively, if each tmporary register is only used once, the instruction
+// can just be described in nested form. This would be the canonical
+// representation the target generator would convert the above into. Pick your
+// favorite indentation scheme.
+let isTwoAddress = 1 in
+def AND32mr : Inst<(ops addr:$addr, R32:$src),
+ "xor $dst, $src2", 0x81, MRM6m,
+ [(store addr:$addr,
+ (and
+ (load addr:$addr),
+ R32:$src)
+ )
+ ]>;
+
+// Describing complex instructions is not too hard! Note how implicit uses/defs
+// become explicit here.
+def CBW : Inst<(ops),
+ "cbw", 0x98, RawFrm,
+ [(set AX, (signext AL))]>;
+
+// Noop, does nothing.
+def NOOP : Inst<(ops), "nop", 0x90, RawFrm, []>;
+
+
+// Instructions that don't expect optimization can use unspec.
+def IN8rr : Inst<(ops), "in AL, EDX", 0xEC, RawFrm,
+ [(set AL, (unspec EDX))]>;
+