1//===-- X86InstrCMovSetCC.td - Conditional Move and SetCC --*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file describes the X86 conditional move and set on condition 10// instructions. 11// 12//===----------------------------------------------------------------------===// 13 14 15// CMOV instructions. 16multiclass Cmov<X86TypeInfo t, string args, bit ndd = 0, string suffix = ""> { 17let isCommutable = 1, SchedRW = [WriteCMOV] in 18 def rr#suffix : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst), 19 (ins t.RegClass:$src1, t.RegClass:$src2, ccode:$cond), 20 "cmov${cond}", args, 21 [(set t.RegClass:$dst, (X86cmov t.RegClass:$src1, 22 t.RegClass:$src2, timm:$cond, EFLAGS))]>, UseEFLAGS, NDD<ndd>; 23let SchedRW = [WriteCMOV.Folded, WriteCMOV.ReadAfterFold] in 24 def rm#suffix : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst), 25 (ins t.RegClass:$src1, t.MemOperand:$src2, ccode:$cond), 26 "cmov${cond}", args, 27 [(set t.RegClass:$dst, (X86cmov t.RegClass:$src1, 28 (t.LoadNode addr:$src2), timm:$cond, EFLAGS))]>, UseEFLAGS, NDD<ndd>; 29} 30 31multiclass Cfcmov<X86TypeInfo t> { 32let isCommutable = 1, SchedRW = [WriteCMOV] in { 33let Predicates = [HasCMOV, HasCF, In64BitMode] in { 34 def rr : ITy<0x40, MRMDestRegCC, t, (outs t.RegClass:$dst), 35 (ins t.RegClass:$src1, ccode:$cond), 36 "cfcmov${cond}", unaryop_ndd_args, 37 [(set t.RegClass:$dst, 38 (X86cmov 0, t.RegClass:$src1, timm:$cond, EFLAGS))]>, UseEFLAGS, NF; 39 def rr_REV : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst), 40 (ins t.RegClass:$src1, ccode:$cond), 41 "cfcmov${cond}", unaryop_ndd_args, 42 []>, UseEFLAGS, EVEX, T_MAP4; 43} 44let Predicates = [HasCMOV, HasCF, HasNDD, In64BitMode] in 45 def rr_ND : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst), 46 (ins t.RegClass:$src1, t.RegClass:$src2, ccode:$cond), 47 "cfcmov${cond}", binop_ndd_args, []>, UseEFLAGS, NDD<1>, NF; 48} 49let SchedRW = [WriteCMOV.Folded, WriteCMOV.ReadAfterFold] in { 50 let Predicates = [HasCMOV, HasCF, In64BitMode], mayLoad = 1 in 51 def rm : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst), 52 (ins t.MemOperand:$src1, ccode:$cond), 53 "cfcmov${cond}", unaryop_ndd_args, []>, UseEFLAGS, EVEX, T_MAP4; 54 let Predicates = [HasCMOV, HasCF, HasNDD, In64BitMode], mayLoad = 1 in 55 def rm_ND : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst), 56 (ins t.RegClass:$src1, t.MemOperand:$src2, ccode:$cond), 57 "cfcmov${cond}", binop_ndd_args, []>, UseEFLAGS, NDD<1>, NF; 58} 59let SchedRW = [WriteCMOV, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], 60 Predicates = [HasCMOV, HasCF, In64BitMode], mayStore = 1 in 61 def mr : ITy<0x40, MRMDestMemCC, t, (outs), 62 (ins t.MemOperand:$dst, t.RegClass:$src1, ccode:$cond), 63 "cfcmov${cond}", unaryop_ndd_args, []>, UseEFLAGS, NF; 64} 65 66let isCodeGenOnly = 1, ForceDisassemble = 1 in { 67 let Predicates = [HasCMOV, NoNDD], Constraints = "$dst = $src1" in { 68 defm CMOV16 : Cmov<Xi16, binop_args>, OpSize16, TB; 69 defm CMOV32 : Cmov<Xi32, binop_args>, OpSize32, TB; 70 defm CMOV64 : Cmov<Xi64, binop_args>, TB; 71 } 72 73 let Predicates = [HasCMOV, HasNDD, In64BitMode] in { 74 defm CMOV16 : Cmov<Xi16, binop_ndd_args, 1, "_ND">, PD; 75 defm CMOV32 : Cmov<Xi32, binop_ndd_args, 1, "_ND">; 76 defm CMOV64 : Cmov<Xi64, binop_ndd_args, 1, "_ND">; 77 } 78 79 defm CFCMOV16 : Cfcmov<Xi16>, PD; 80 defm CFCMOV32 : Cfcmov<Xi32>; 81 defm CFCMOV64 : Cfcmov<Xi64>; 82} // isCodeGenOnly = 1, ForceDisassemble = 1 83 84def inv_cond_XFORM : SDNodeXForm<imm, [{ 85 X86::CondCode CC = static_cast<X86::CondCode>(N->getZExtValue()); 86 return CurDAG->getTargetConstant(X86::GetOppositeBranchCondition(CC), 87 SDLoc(N), MVT::i8); 88}]>; 89 90// Conditional moves with folded loads with operands swapped and conditions 91// inverted. 92let Predicates = [HasCMOV, NoNDD] in { 93 def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, timm:$cond, EFLAGS), 94 (CMOV16rm GR16:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; 95 def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, timm:$cond, EFLAGS), 96 (CMOV32rm GR32:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; 97 def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, timm:$cond, EFLAGS), 98 (CMOV64rm GR64:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; 99} 100 101let Predicates = [HasCMOV, HasNDD] in { 102 def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, timm:$cond, EFLAGS), 103 (CMOV16rm_ND GR16:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; 104 def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, timm:$cond, EFLAGS), 105 (CMOV32rm_ND GR32:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; 106 def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, timm:$cond, EFLAGS), 107 (CMOV64rm_ND GR64:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; 108} 109let Predicates = [HasCMOV, HasCF] in { 110 def : Pat<(X86cmov GR16:$src1, 0, timm:$cond, EFLAGS), 111 (CFCMOV16rr GR16:$src1, (inv_cond_XFORM timm:$cond))>; 112 def : Pat<(X86cmov GR32:$src1, 0, timm:$cond, EFLAGS), 113 (CFCMOV32rr GR32:$src1, (inv_cond_XFORM timm:$cond))>; 114 def : Pat<(X86cmov GR64:$src1, 0, timm:$cond, EFLAGS), 115 (CFCMOV64rr GR64:$src1, (inv_cond_XFORM timm:$cond))>; 116 117 def : Pat<(X86cload addr:$src1, 0, timm:$cond, EFLAGS), 118 (CFCMOV16rm addr:$src1, timm:$cond)>; 119 def : Pat<(X86cload addr:$src1, 0, timm:$cond, EFLAGS), 120 (CFCMOV32rm addr:$src1, timm:$cond)>; 121 def : Pat<(X86cload addr:$src1, 0, timm:$cond, EFLAGS), 122 (CFCMOV64rm addr:$src1, timm:$cond)>; 123 124 def : Pat<(X86cload addr:$src2, GR16:$src1, timm:$cond, EFLAGS), 125 (CFCMOV16rm_ND GR16:$src1, addr:$src2, timm:$cond)>; 126 def : Pat<(X86cload addr:$src2, GR32:$src1, timm:$cond, EFLAGS), 127 (CFCMOV32rm_ND GR32:$src1, addr:$src2, timm:$cond)>; 128 def : Pat<(X86cload addr:$src2, GR64:$src1, timm:$cond, EFLAGS), 129 (CFCMOV64rm_ND GR64:$src1, addr:$src2, timm:$cond)>; 130 131 def : Pat<(X86cstore GR16:$src2, addr:$src1, timm:$cond, EFLAGS), 132 (CFCMOV16mr addr:$src1, GR16:$src2, timm:$cond)>; 133 def : Pat<(X86cstore GR32:$src2, addr:$src1, timm:$cond, EFLAGS), 134 (CFCMOV32mr addr:$src1, GR32:$src2, timm:$cond)>; 135 def : Pat<(X86cstore GR64:$src2, addr:$src1, timm:$cond, EFLAGS), 136 (CFCMOV64mr addr:$src1, GR64:$src2, timm:$cond)>; 137} 138 139// SetCC instructions. 140let Uses = [EFLAGS], isCodeGenOnly = 1, ForceDisassemble = 1 in { 141 def SETCCr : I<0x90, MRMXrCC, (outs GR8:$dst), (ins ccode:$cond), 142 "set${cond}\t$dst", 143 [(set GR8:$dst, (X86setcc timm:$cond, EFLAGS))]>, 144 TB, Sched<[WriteSETCC]>; 145 def SETCCm : I<0x90, MRMXmCC, (outs), (ins i8mem:$dst, ccode:$cond), 146 "set${cond}\t$dst", 147 [(store (X86setcc timm:$cond, EFLAGS), addr:$dst)]>, 148 TB, Sched<[WriteSETCCStore]>; 149} // Uses = [EFLAGS] 150 151// SetZUCC and promoted SetCC instructions. 152let Uses = [EFLAGS], isCodeGenOnly = 1, ForceDisassemble = 1, 153 hasSideEffects = 0, Predicates = [In64BitMode], Predicates = [HasNDD] in { 154 def SETZUCCr : I<0x40, MRMXrCC, (outs GR8:$dst), (ins ccode:$cond), 155 "setzu${cond}\t$dst", []>, 156 XD, ZU, NoCD8, Sched<[WriteSETCC]>; 157 def SETCCr_EVEX : I<0x40, MRMXrCC, (outs GR8:$dst), (ins ccode:$cond), 158 "set${cond}\t$dst", []>, 159 XD, PL, Sched<[WriteSETCC]>; 160 let mayStore = 1 in { 161 def SETZUCCm : I<0x40, MRMXmCC, (outs), (ins i8mem:$dst, ccode:$cond), 162 "setzu${cond}\t$dst", []>, 163 XD, ZU, NoCD8, Sched<[WriteSETCCStore]>; 164 def SETCCm_EVEX : I<0x40, MRMXmCC, (outs), (ins i8mem:$dst, ccode:$cond), 165 "set${cond}\t$dst", []>, 166 XD, PL, Sched<[WriteSETCCStore]>; 167 } 168} 169 170// SALC is an undocumented instruction. Information for this instruction can be found 171// here http://www.rcollins.org/secrets/opcodes/SALC.html 172// Set AL if carry. 173let Uses = [EFLAGS], Defs = [AL], SchedRW = [WriteALU] in { 174 def SALC : I<0xD6, RawFrm, (outs), (ins), "salc", []>, Requires<[Not64BitMode]>; 175} 176