| Chris Lattner | 3afbb93 | 2004-07-25 12:13:35 +0000 | [diff] [blame] | 1 | // This test describes how we eventually want to describe instructions in | 
|  | 2 | // the target independent code generators. | 
|  | 3 | // RUN: tblgen %s | 
| Jeffrey Yasskin | 2f87b54 | 2010-03-20 23:08:45 +0000 | [diff] [blame] | 4 | // XFAIL: vg_leak | 
| Chris Lattner | 3afbb93 | 2004-07-25 12:13:35 +0000 | [diff] [blame] | 5 |  | 
|  | 6 | // Target indep stuff. | 
|  | 7 | class Instruction {   // Would have other stuff eventually | 
|  | 8 | bit isTwoAddress = 0; | 
|  | 9 | string AssemblyString; | 
|  | 10 | } | 
|  | 11 | class RegisterClass; | 
|  | 12 |  | 
|  | 13 | class RTLNode; | 
|  | 14 |  | 
|  | 15 | def ops;                 // Marker for operand list. | 
|  | 16 |  | 
|  | 17 | // Various expressions used in RTL descriptions. | 
|  | 18 | def imm8    : RTLNode; | 
|  | 19 | def imm32   : RTLNode; | 
|  | 20 | def addr    : RTLNode; | 
|  | 21 |  | 
|  | 22 | def set     : RTLNode; | 
|  | 23 | def signext : RTLNode; | 
|  | 24 | def zeroext : RTLNode; | 
|  | 25 | def plus    : RTLNode; | 
|  | 26 | def and     : RTLNode; | 
|  | 27 | def xor     : RTLNode; | 
|  | 28 | def shl     : RTLNode; | 
|  | 29 | def load    : RTLNode; | 
|  | 30 | def store   : RTLNode; | 
|  | 31 | def unspec  : RTLNode; | 
|  | 32 |  | 
|  | 33 | // Start of X86 specific stuff. | 
|  | 34 |  | 
|  | 35 | def R8  : RegisterClass; | 
|  | 36 | def R16 : RegisterClass; | 
|  | 37 | def R32 : RegisterClass; | 
|  | 38 |  | 
|  | 39 | def CL;  // As are currently defined | 
|  | 40 | def AL; | 
|  | 41 | def AX; | 
|  | 42 | def EDX; | 
|  | 43 |  | 
|  | 44 | class Format<bits<5> val> { | 
|  | 45 | bits<5> Value = val; | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | def Pseudo     : Format<0>; def RawFrm     : Format<1>; | 
|  | 49 | def AddRegFrm  : Format<2>; def MRMDestReg : Format<3>; | 
|  | 50 | def MRMDestMem : Format<4>; def MRMSrcReg  : Format<5>; | 
|  | 51 | def MRMSrcMem  : Format<6>; | 
|  | 52 | def MRM0r  : Format<16>; def MRM1r  : Format<17>; def MRM2r  : Format<18>; | 
|  | 53 | def MRM3r  : Format<19>; def MRM4r  : Format<20>; def MRM5r  : Format<21>; | 
|  | 54 | def MRM6r  : Format<22>; def MRM7r  : Format<23>; | 
|  | 55 | def MRM0m  : Format<24>; def MRM1m  : Format<25>; def MRM2m  : Format<26>; | 
|  | 56 | def MRM3m  : Format<27>; def MRM4m  : Format<28>; def MRM5m  : Format<29>; | 
|  | 57 | def MRM6m  : Format<30>; def MRM7m  : Format<31>; | 
|  | 58 |  | 
|  | 59 |  | 
|  | 60 | class Inst<dag opnds, string asmstr, bits<8> opcode, | 
|  | 61 | Format f, list<dag> rtl> : Instruction { | 
|  | 62 | dag Operands = opnds; | 
|  | 63 | string AssemblyString = asmstr; | 
|  | 64 | bits<8> Opcode = opcode; | 
|  | 65 | Format Format = f; | 
|  | 66 | list<dag> RTL = rtl; | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 |  | 
|  | 70 | // Start of instruction definitions, the real point of this file. | 
|  | 71 | // | 
|  | 72 | // Note that these patterns show a couple of important things: | 
|  | 73 | //  1. The order and contents of the operands of the MachineInstr are | 
|  | 74 | //     described here.  Eventually we can do away with this when everything | 
|  | 75 | //     is generated from the description. | 
|  | 76 | //  2. The asm string is captured here, which makes it possible to get rid of | 
|  | 77 | //     a ton of hacks in the various printers and a bunch of flags. | 
|  | 78 | //  3. Target specific properties (e.g. Format) can still be captured as | 
|  | 79 | //     needed. | 
|  | 80 | //  4. We capture the behavior of the instruction with a simplified RTL-like | 
|  | 81 | //     expression. | 
|  | 82 | //  5. The use/def properties for each operand are automatically inferred from | 
|  | 83 | //     the pattern. | 
|  | 84 | //  6. Address expressions should become first-class entities. | 
|  | 85 |  | 
| Jakob Stoklund Olesen | c4227f1 | 2010-07-11 17:01:17 +0000 | [diff] [blame^] | 86 | // Simple copy instruction. | 
| Chris Lattner | 3afbb93 | 2004-07-25 12:13:35 +0000 | [diff] [blame] | 87 | def MOV8rr : Inst<(ops R8:$dst, R8:$src), | 
|  | 88 | "mov $dst, $src", 0x88, MRMDestReg, | 
|  | 89 | [(set R8:$dst, R8:$src)]>; | 
|  | 90 |  | 
|  | 91 | // Simple immediate initialization. | 
|  | 92 | def MOV8ri : Inst<(ops R8:$dst, imm8:$src), | 
|  | 93 | "mov $dst, $src", 0xB0, AddRegFrm, | 
|  | 94 | [(set R8:$dst, imm8:$src)]>; | 
|  | 95 |  | 
|  | 96 | // Two address instructions are described as three-addr instructions, with | 
|  | 97 | // the special target-independent isTwoAddress flag set.  The asm pattern | 
|  | 98 | // should not refer to the $src1, this would be enforced by the | 
|  | 99 | // TargetInstrInfo tablegen backend. | 
|  | 100 | let isTwoAddress = 1 in | 
|  | 101 | def AND8rr : Inst<(ops R8:$dst, R8:$src1, R8:$src2), | 
|  | 102 | "and $dst, $src2", 0x20, MRMDestReg, | 
|  | 103 | [(set R8:$dst, (and R8:$src1, R8:$src2))]>; | 
|  | 104 |  | 
|  | 105 | // Instructions that have explicit uses/defs make them explicit in the RTL. | 
|  | 106 | // Instructions that need extra stuff emitted in the assembly can, trivially. | 
|  | 107 | let isTwoAddress = 1 in | 
|  | 108 | def SHL32rCL : Inst<(ops R32:$dst, R32:$src), | 
|  | 109 | "shl $dst, CL", 0xD2, MRM4r, | 
|  | 110 | [(set R32:$dst, (shl R32:$src, CL))]>; | 
|  | 111 |  | 
|  | 112 | // The RTL list is a list, allowing complex instructions to be defined easily. | 
|  | 113 | // Temporary 'internal' registers can be used to break instructions appart. | 
|  | 114 | let isTwoAddress = 1 in | 
|  | 115 | def XOR32mi : Inst<(ops addr:$addr, imm32:$imm), | 
|  | 116 | "xor $dst, $src2", 0x81, MRM6m, | 
|  | 117 | [(set R32:$tmp1, (load addr:$addr)), | 
|  | 118 | (set R32:$tmp2, (xor R32:$tmp1, imm32:$imm)), | 
|  | 119 | (store addr:$addr, R32:$tmp2)]>; | 
|  | 120 |  | 
|  | 121 | // Alternatively, if each tmporary register is only used once, the instruction | 
|  | 122 | // can just be described in nested form.  This would be the canonical | 
|  | 123 | // representation the target generator would convert the above into.  Pick your | 
|  | 124 | // favorite indentation scheme. | 
|  | 125 | let isTwoAddress = 1 in | 
|  | 126 | def AND32mr : Inst<(ops addr:$addr, R32:$src), | 
|  | 127 | "xor $dst, $src2", 0x81, MRM6m, | 
|  | 128 | [(store addr:$addr, | 
|  | 129 | (and | 
|  | 130 | (load addr:$addr), | 
|  | 131 | R32:$src) | 
|  | 132 | ) | 
|  | 133 | ]>; | 
|  | 134 |  | 
|  | 135 | // Describing complex instructions is not too hard!  Note how implicit uses/defs | 
|  | 136 | // become explicit here. | 
|  | 137 | def CBW : Inst<(ops), | 
|  | 138 | "cbw", 0x98, RawFrm, | 
|  | 139 | [(set AX, (signext AL))]>; | 
|  | 140 |  | 
|  | 141 | // Noop, does nothing. | 
|  | 142 | def NOOP : Inst<(ops), "nop", 0x90, RawFrm, []>; | 
|  | 143 |  | 
|  | 144 |  | 
|  | 145 | // Instructions that don't expect optimization can use unspec. | 
|  | 146 | def IN8rr : Inst<(ops), "in AL, EDX", 0xEC, RawFrm, | 
|  | 147 | [(set AL, (unspec EDX))]>; | 
|  | 148 |  |