1 // This test describes how we eventually want to describe instructions in 2 // the target independent code generators. 3 // RUN: llvm-tblgen %s 4 // XFAIL: vg_leak 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 86 // Simple copy instruction. 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 apart. 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 149