| // This test describes how we eventually want to describe instructions in | 
 | // the target independent code generators. | 
 | // RUN: llvm-tblgen %s | 
 | // XFAIL: vg_leak | 
 |  | 
 | // 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. | 
 | 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 apart. | 
 | 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))]>; | 
 |  |