1//===- X86InstrFPStack.td - FPU Instruction Set ------------*- 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 x87 FPU instruction set, defining the 10// instructions, and properties of the instructions which are needed for code 11// generation, machine code emission, and analysis. 12// 13//===----------------------------------------------------------------------===// 14 15//===----------------------------------------------------------------------===// 16// FPStack specific DAG Nodes. 17//===----------------------------------------------------------------------===// 18 19def SDTX86Fld : SDTypeProfile<1, 1, [SDTCisFP<0>, 20 SDTCisPtrTy<1>]>; 21def SDTX86Fst : SDTypeProfile<0, 2, [SDTCisFP<0>, 22 SDTCisPtrTy<1>]>; 23def SDTX86Fild : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisPtrTy<1>]>; 24def SDTX86Fist : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; 25 26def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; 27def SDTX86CwdLoad : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; 28 29def X86fp80_add : SDNode<"X86ISD::FP80_ADD", SDTFPBinOp, [SDNPCommutative]>; 30def X86strict_fp80_add : SDNode<"X86ISD::STRICT_FP80_ADD", SDTFPBinOp, 31 [SDNPHasChain,SDNPCommutative]>; 32def any_X86fp80_add : PatFrags<(ops node:$lhs, node:$rhs), 33 [(X86strict_fp80_add node:$lhs, node:$rhs), 34 (X86fp80_add node:$lhs, node:$rhs)]>; 35 36def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, 37 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; 38def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, 39 [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; 40def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, 41 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; 42def X86fist : SDNode<"X86ISD::FIST", SDTX86Fist, 43 [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; 44def X86fp_to_mem : SDNode<"X86ISD::FP_TO_INT_IN_MEM", SDTX86Fst, 45 [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; 46def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, 47 [SDNPHasChain, SDNPMayStore, SDNPSideEffect, 48 SDNPMemOperand]>; 49def X86fp_cwd_set16 : SDNode<"X86ISD::FLDCW16m", SDTX86CwdLoad, 50 [SDNPHasChain, SDNPMayLoad, SDNPSideEffect, 51 SDNPMemOperand]>; 52 53def X86fstf32 : PatFrag<(ops node:$val, node:$ptr), 54 (X86fst node:$val, node:$ptr), [{ 55 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::f32; 56}]>; 57def X86fstf64 : PatFrag<(ops node:$val, node:$ptr), 58 (X86fst node:$val, node:$ptr), [{ 59 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::f64; 60}]>; 61def X86fstf80 : PatFrag<(ops node:$val, node:$ptr), 62 (X86fst node:$val, node:$ptr), [{ 63 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::f80; 64}]>; 65 66def X86fldf32 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ 67 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::f32; 68}]>; 69def X86fldf64 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ 70 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::f64; 71}]>; 72def X86fldf80 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ 73 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::f80; 74}]>; 75 76def X86fild16 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ 77 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16; 78}]>; 79def X86fild32 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ 80 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; 81}]>; 82def X86fild64 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ 83 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; 84}]>; 85 86def X86fist32 : PatFrag<(ops node:$val, node:$ptr), 87 (X86fist node:$val, node:$ptr), [{ 88 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; 89}]>; 90 91def X86fist64 : PatFrag<(ops node:$val, node:$ptr), 92 (X86fist node:$val, node:$ptr), [{ 93 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; 94}]>; 95 96def X86fp_to_i16mem : PatFrag<(ops node:$val, node:$ptr), 97 (X86fp_to_mem node:$val, node:$ptr), [{ 98 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16; 99}]>; 100def X86fp_to_i32mem : PatFrag<(ops node:$val, node:$ptr), 101 (X86fp_to_mem node:$val, node:$ptr), [{ 102 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; 103}]>; 104def X86fp_to_i64mem : PatFrag<(ops node:$val, node:$ptr), 105 (X86fp_to_mem node:$val, node:$ptr), [{ 106 return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; 107}]>; 108 109//===----------------------------------------------------------------------===// 110// FPStack pattern fragments 111//===----------------------------------------------------------------------===// 112 113def fpimm0 : FPImmLeaf<fAny, [{ 114 return Imm.isExactlyValue(+0.0); 115}]>; 116 117def fpimmneg0 : FPImmLeaf<fAny, [{ 118 return Imm.isExactlyValue(-0.0); 119}]>; 120 121def fpimm1 : FPImmLeaf<fAny, [{ 122 return Imm.isExactlyValue(+1.0); 123}]>; 124 125def fpimmneg1 : FPImmLeaf<fAny, [{ 126 return Imm.isExactlyValue(-1.0); 127}]>; 128 129// Some 'special' instructions - expanded after instruction selection. 130// Clobbers EFLAGS due to OR instruction used internally. 131// FIXME: Can we model this in SelectionDAG? 132let usesCustomInserter = 1, hasNoSchedulingInfo = 1, Defs = [EFLAGS] in { 133 def FP32_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP32:$src), 134 [(X86fp_to_i16mem RFP32:$src, addr:$dst)]>; 135 def FP32_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP32:$src), 136 [(X86fp_to_i32mem RFP32:$src, addr:$dst)]>; 137 def FP32_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP32:$src), 138 [(X86fp_to_i64mem RFP32:$src, addr:$dst)]>; 139 def FP64_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP64:$src), 140 [(X86fp_to_i16mem RFP64:$src, addr:$dst)]>; 141 def FP64_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP64:$src), 142 [(X86fp_to_i32mem RFP64:$src, addr:$dst)]>; 143 def FP64_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP64:$src), 144 [(X86fp_to_i64mem RFP64:$src, addr:$dst)]>; 145 def FP80_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP80:$src), 146 [(X86fp_to_i16mem RFP80:$src, addr:$dst)]>; 147 def FP80_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP80:$src), 148 [(X86fp_to_i32mem RFP80:$src, addr:$dst)]>; 149 def FP80_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP80:$src), 150 [(X86fp_to_i64mem RFP80:$src, addr:$dst)]>; 151 152 def FP80_ADDr : PseudoI<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), 153 [(set RFP80:$dst, 154 (any_X86fp80_add RFP80:$src1, RFP80:$src2))]>; 155 def FP80_ADDm32 : PseudoI<(outs RFP80:$dst), (ins RFP80:$src1, f32mem:$src2), 156 [(set RFP80:$dst, 157 (any_X86fp80_add RFP80:$src1, 158 (f80 (extloadf32 addr:$src2))))]>; 159} 160 161// All FP Stack operations are represented with four instructions here. The 162// first three instructions, generated by the instruction selector, use "RFP32" 163// "RFP64" or "RFP80" registers: traditional register files to reference 32-bit, 164// 64-bit or 80-bit floating point values. These sizes apply to the values, 165// not the registers, which are always 80 bits; RFP32, RFP64 and RFP80 can be 166// copied to each other without losing information. These instructions are all 167// pseudo instructions and use the "_Fp" suffix. 168// In some cases there are additional variants with a mixture of different 169// register sizes. 170// The second instruction is defined with FPI, which is the actual instruction 171// emitted by the assembler. These use "RST" registers, although frequently 172// the actual register(s) used are implicit. These are always 80 bits. 173// The FP stackifier pass converts one to the other after register allocation 174// occurs. 175// 176// Note that the FpI instruction should have instruction selection info (e.g. 177// a pattern) and the FPI instruction should have emission info (e.g. opcode 178// encoding and asm printing info). 179 180// FpIf32, FpIf64 - Floating Point Pseudo Instruction template. 181// f32 instructions can use SSE1 and are predicated on FPStackf32 == !SSE1. 182// f64 instructions can use SSE2 and are predicated on FPStackf64 == !SSE2. 183// f80 instructions cannot use SSE and use neither of these. 184class FpIf32<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 185 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf32]>; 186class FpIf64<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 187 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf64]>; 188 189// Factoring for arithmetic. 190multiclass FPBinary_rr<SDPatternOperator OpNode> { 191// Register op register -> register 192// These are separated out because they have no reversed form. 193def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), TwoArgFP, 194 [(set RFP32:$dst, (OpNode RFP32:$src1, RFP32:$src2))]>; 195def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), TwoArgFP, 196 [(set RFP64:$dst, (OpNode RFP64:$src1, RFP64:$src2))]>; 197def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), TwoArgFP, 198 [(set RFP80:$dst, (OpNode RFP80:$src1, RFP80:$src2))]>; 199} 200// The FopST0 series are not included here because of the irregularities 201// in where the 'r' goes in assembly output. 202// These instructions cannot address 80-bit memory. 203multiclass FPBinary<SDPatternOperator OpNode, Format fp, string asmstring, 204 bit Forward = 1> { 205// ST(0) = ST(0) + [mem] 206def _Fp32m : FpIf32<(outs RFP32:$dst), 207 (ins RFP32:$src1, f32mem:$src2), OneArgFPRW, 208 [!if(Forward, 209 (set RFP32:$dst, 210 (OpNode RFP32:$src1, (loadf32 addr:$src2))), 211 (set RFP32:$dst, 212 (OpNode (loadf32 addr:$src2), RFP32:$src1)))]>; 213def _Fp64m : FpIf64<(outs RFP64:$dst), 214 (ins RFP64:$src1, f64mem:$src2), OneArgFPRW, 215 [!if(Forward, 216 (set RFP64:$dst, 217 (OpNode RFP64:$src1, (loadf64 addr:$src2))), 218 (set RFP64:$dst, 219 (OpNode (loadf64 addr:$src2), RFP64:$src1)))]>; 220def _Fp64m32: FpIf64<(outs RFP64:$dst), 221 (ins RFP64:$src1, f32mem:$src2), OneArgFPRW, 222 [!if(Forward, 223 (set RFP64:$dst, 224 (OpNode RFP64:$src1, (f64 (extloadf32 addr:$src2)))), 225 (set RFP64:$dst, 226 (OpNode (f64 (extloadf32 addr:$src2)), RFP64:$src1)))]>; 227def _Fp80m32: FpI_<(outs RFP80:$dst), 228 (ins RFP80:$src1, f32mem:$src2), OneArgFPRW, 229 [!if(Forward, 230 (set RFP80:$dst, 231 (OpNode RFP80:$src1, (f80 (extloadf32 addr:$src2)))), 232 (set RFP80:$dst, 233 (OpNode (f80 (extloadf32 addr:$src2)), RFP80:$src1)))]>; 234def _Fp80m64: FpI_<(outs RFP80:$dst), 235 (ins RFP80:$src1, f64mem:$src2), OneArgFPRW, 236 [!if(Forward, 237 (set RFP80:$dst, 238 (OpNode RFP80:$src1, (f80 (extloadf64 addr:$src2)))), 239 (set RFP80:$dst, 240 (OpNode (f80 (extloadf64 addr:$src2)), RFP80:$src1)))]>; 241let mayLoad = 1 in 242def _F32m : FPI<0xD8, fp, (outs), (ins f32mem:$src), 243 !strconcat("f", asmstring, "{s}\t$src")>; 244let mayLoad = 1 in 245def _F64m : FPI<0xDC, fp, (outs), (ins f64mem:$src), 246 !strconcat("f", asmstring, "{l}\t$src")>; 247// ST(0) = ST(0) + [memint] 248def _FpI16m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i16mem:$src2), 249 OneArgFPRW, 250 [!if(Forward, 251 (set RFP32:$dst, 252 (OpNode RFP32:$src1, (X86fild16 addr:$src2))), 253 (set RFP32:$dst, 254 (OpNode (X86fild16 addr:$src2), RFP32:$src1)))]>; 255def _FpI32m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i32mem:$src2), 256 OneArgFPRW, 257 [!if(Forward, 258 (set RFP32:$dst, 259 (OpNode RFP32:$src1, (X86fild32 addr:$src2))), 260 (set RFP32:$dst, 261 (OpNode (X86fild32 addr:$src2), RFP32:$src1)))]>; 262def _FpI16m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i16mem:$src2), 263 OneArgFPRW, 264 [!if(Forward, 265 (set RFP64:$dst, 266 (OpNode RFP64:$src1, (X86fild16 addr:$src2))), 267 (set RFP64:$dst, 268 (OpNode (X86fild16 addr:$src2), RFP64:$src1)))]>; 269def _FpI32m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i32mem:$src2), 270 OneArgFPRW, 271 [!if(Forward, 272 (set RFP64:$dst, 273 (OpNode RFP64:$src1, (X86fild32 addr:$src2))), 274 (set RFP64:$dst, 275 (OpNode (X86fild32 addr:$src2), RFP64:$src1)))]>; 276def _FpI16m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i16mem:$src2), 277 OneArgFPRW, 278 [!if(Forward, 279 (set RFP80:$dst, 280 (OpNode RFP80:$src1, (X86fild16 addr:$src2))), 281 (set RFP80:$dst, 282 (OpNode (X86fild16 addr:$src2), RFP80:$src1)))]>; 283def _FpI32m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i32mem:$src2), 284 OneArgFPRW, 285 [!if(Forward, 286 (set RFP80:$dst, 287 (OpNode RFP80:$src1, (X86fild32 addr:$src2))), 288 (set RFP80:$dst, 289 (OpNode (X86fild32 addr:$src2), RFP80:$src1)))]>; 290let mayLoad = 1 in 291def _FI16m : FPI<0xDE, fp, (outs), (ins i16mem:$src), 292 !strconcat("fi", asmstring, "{s}\t$src")>; 293let mayLoad = 1 in 294def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), 295 !strconcat("fi", asmstring, "{l}\t$src")>; 296} 297 298let Uses = [FPCW], mayRaiseFPException = 1 in { 299// FPBinary_rr just defines pseudo-instructions, no need to set a scheduling 300// resources. 301let hasNoSchedulingInfo = 1 in { 302defm ADD : FPBinary_rr<any_fadd>; 303defm SUB : FPBinary_rr<any_fsub>; 304defm MUL : FPBinary_rr<any_fmul>; 305defm DIV : FPBinary_rr<any_fdiv>; 306} 307 308// Sets the scheduling resources for the actual NAME#_F<size>m definitions. 309let SchedRW = [WriteFAddLd] in { 310defm ADD : FPBinary<any_fadd, MRM0m, "add">; 311defm SUB : FPBinary<any_fsub, MRM4m, "sub">; 312defm SUBR: FPBinary<any_fsub ,MRM5m, "subr", 0>; 313} 314 315let SchedRW = [WriteFMulLd] in { 316defm MUL : FPBinary<any_fmul, MRM1m, "mul">; 317} 318 319let SchedRW = [WriteFDivLd] in { 320defm DIV : FPBinary<any_fdiv, MRM6m, "div">; 321defm DIVR: FPBinary<any_fdiv, MRM7m, "divr", 0>; 322} 323} // Uses = [FPCW], mayRaiseFPException = 1 324 325class FPST0rInst<Format fp, string asm> 326 : FPI<0xD8, fp, (outs), (ins RSTi:$op), asm>; 327class FPrST0Inst<Format fp, string asm> 328 : FPI<0xDC, fp, (outs), (ins RSTi:$op), asm>; 329class FPrST0PInst<Format fp, string asm> 330 : FPI<0xDE, fp, (outs), (ins RSTi:$op), asm>; 331 332// NOTE: GAS and apparently all other AT&T style assemblers have a broken notion 333// of some of the 'reverse' forms of the fsub and fdiv instructions. As such, 334// we have to put some 'r's in and take them out of weird places. 335let SchedRW = [WriteFAdd], Uses = [FPCW], mayRaiseFPException = 1 in { 336def ADD_FST0r : FPST0rInst <MRM0r, "fadd\t{$op, %st|st, $op}">; 337def ADD_FrST0 : FPrST0Inst <MRM0r, "fadd\t{%st, $op|$op, st}">; 338def ADD_FPrST0 : FPrST0PInst<MRM0r, "faddp\t{%st, $op|$op, st}">; 339def SUBR_FST0r : FPST0rInst <MRM5r, "fsubr\t{$op, %st|st, $op}">; 340def SUB_FrST0 : FPrST0Inst <MRM5r, "fsub{r}\t{%st, $op|$op, st}">; 341def SUB_FPrST0 : FPrST0PInst<MRM5r, "fsub{r}p\t{%st, $op|$op, st}">; 342def SUB_FST0r : FPST0rInst <MRM4r, "fsub\t{$op, %st|st, $op}">; 343def SUBR_FrST0 : FPrST0Inst <MRM4r, "fsub{|r}\t{%st, $op|$op, st}">; 344def SUBR_FPrST0 : FPrST0PInst<MRM4r, "fsub{|r}p\t{%st, $op|$op, st}">; 345} // SchedRW 346let SchedRW = [WriteFCom], Uses = [FPCW], mayRaiseFPException = 1 in { 347def COM_FST0r : FPST0rInst <MRM2r, "fcom\t$op">; 348def COMP_FST0r : FPST0rInst <MRM3r, "fcomp\t$op">; 349} // SchedRW 350let SchedRW = [WriteFMul], Uses = [FPCW], mayRaiseFPException = 1 in { 351def MUL_FST0r : FPST0rInst <MRM1r, "fmul\t{$op, %st|st, $op}">; 352def MUL_FrST0 : FPrST0Inst <MRM1r, "fmul\t{%st, $op|$op, st}">; 353def MUL_FPrST0 : FPrST0PInst<MRM1r, "fmulp\t{%st, $op|$op, st}">; 354} // SchedRW 355let SchedRW = [WriteFDiv], Uses = [FPCW], mayRaiseFPException = 1 in { 356def DIVR_FST0r : FPST0rInst <MRM7r, "fdivr\t{$op, %st|st, $op}">; 357def DIV_FrST0 : FPrST0Inst <MRM7r, "fdiv{r}\t{%st, $op|$op, st}">; 358def DIV_FPrST0 : FPrST0PInst<MRM7r, "fdiv{r}p\t{%st, $op|$op, st}">; 359def DIV_FST0r : FPST0rInst <MRM6r, "fdiv\t{$op, %st|st, $op}">; 360def DIVR_FrST0 : FPrST0Inst <MRM6r, "fdiv{|r}\t{%st, $op|$op, st}">; 361def DIVR_FPrST0 : FPrST0PInst<MRM6r, "fdiv{|r}p\t{%st, $op|$op, st}">; 362} // SchedRW 363 364// Unary operations. 365multiclass FPUnary<SDPatternOperator OpNode, Format fp, string asmstring> { 366def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), OneArgFPRW, 367 [(set RFP32:$dst, (OpNode RFP32:$src))]>; 368def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), OneArgFPRW, 369 [(set RFP64:$dst, (OpNode RFP64:$src))]>; 370def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src), OneArgFPRW, 371 [(set RFP80:$dst, (OpNode RFP80:$src))]>; 372def _F : FPI<0xD9, fp, (outs), (ins), asmstring>; 373} 374 375let SchedRW = [WriteFSign] in { 376defm CHS : FPUnary<fneg, MRM_E0, "fchs">; 377defm ABS : FPUnary<fabs, MRM_E1, "fabs">; 378} 379 380let Uses = [FPCW], mayRaiseFPException = 1 in { 381let SchedRW = [WriteFSqrt80] in 382defm SQRT: FPUnary<any_fsqrt,MRM_FA, "fsqrt">; 383 384let SchedRW = [WriteFCom] in { 385let hasSideEffects = 0 in { 386def TST_Fp32 : FpIf32<(outs), (ins RFP32:$src), OneArgFP, []>; 387def TST_Fp64 : FpIf64<(outs), (ins RFP64:$src), OneArgFP, []>; 388def TST_Fp80 : FpI_<(outs), (ins RFP80:$src), OneArgFP, []>; 389} // hasSideEffects 390 391def TST_F : FPI<0xD9, MRM_E4, (outs), (ins), "ftst">; 392} // SchedRW 393} // Uses = [FPCW], mayRaiseFPException = 1 394 395let SchedRW = [WriteFTest], Defs = [FPSW] in { 396def XAM_Fp32 : FpIf32<(outs), (ins RFP32:$src), OneArgFP, []>; 397def XAM_Fp64 : FpIf64<(outs), (ins RFP64:$src), OneArgFP, []>; 398def XAM_Fp80 : FpI_<(outs), (ins RFP80:$src), OneArgFP, []>; 399def XAM_F : FPI<0xD9, MRM_E5, (outs), (ins), "fxam">; 400} // SchedRW 401 402// Versions of FP instructions that take a single memory operand. Added for the 403// disassembler; remove as they are included with patterns elsewhere. 404let SchedRW = [WriteFComLd], Uses = [FPCW], mayRaiseFPException = 1, 405 mayLoad = 1 in { 406def FCOM32m : FPI<0xD8, MRM2m, (outs), (ins f32mem:$src), "fcom{s}\t$src">; 407def FCOMP32m : FPI<0xD8, MRM3m, (outs), (ins f32mem:$src), "fcomp{s}\t$src">; 408 409def FCOM64m : FPI<0xDC, MRM2m, (outs), (ins f64mem:$src), "fcom{l}\t$src">; 410def FCOMP64m : FPI<0xDC, MRM3m, (outs), (ins f64mem:$src), "fcomp{l}\t$src">; 411 412def FICOM16m : FPI<0xDE, MRM2m, (outs), (ins i16mem:$src), "ficom{s}\t$src">; 413def FICOMP16m: FPI<0xDE, MRM3m, (outs), (ins i16mem:$src), "ficomp{s}\t$src">; 414 415def FICOM32m : FPI<0xDA, MRM2m, (outs), (ins i32mem:$src), "ficom{l}\t$src">; 416def FICOMP32m: FPI<0xDA, MRM3m, (outs), (ins i32mem:$src), "ficomp{l}\t$src">; 417} // SchedRW 418 419let SchedRW = [WriteMicrocoded] in { 420let Defs = [FPSW, FPCW], mayLoad = 1 in { 421def FLDENVm : FPI<0xD9, MRM4m, (outs), (ins anymem:$src), "fldenv\t$src">; 422def FRSTORm : FPI<0xDD, MRM4m, (outs), (ins anymem:$src), "frstor\t$src">; 423} 424 425let Defs = [FPSW, FPCW], Uses = [FPSW, FPCW], mayStore = 1 in { 426def FSTENVm : FPI<0xD9, MRM6m, (outs), (ins anymem:$dst), "fnstenv\t$dst">; 427def FSAVEm : FPI<0xDD, MRM6m, (outs), (ins anymem:$dst), "fnsave\t$dst">; 428} 429 430let Uses = [FPSW], mayStore = 1 in 431def FNSTSWm : FPI<0xDD, MRM7m, (outs), (ins i16mem:$dst), "fnstsw\t$dst">; 432 433let mayLoad = 1 in 434def FBLDm : FPI<0xDF, MRM4m, (outs), (ins f80mem:$src), "fbld\t$src">; 435let Uses = [FPCW] ,mayRaiseFPException = 1, mayStore = 1 in 436def FBSTPm : FPI<0xDF, MRM6m, (outs), (ins f80mem:$dst), "fbstp\t$dst">; 437} // SchedRW 438 439// Floating point cmovs. 440class FpIf32CMov<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 441 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf32, HasCMOV]>; 442class FpIf64CMov<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 443 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf64, HasCMOV]>; 444 445multiclass FPCMov<PatLeaf cc> { 446 def _Fp32 : FpIf32CMov<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), 447 CondMovFP, 448 [(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2, 449 cc, EFLAGS))]>; 450 def _Fp64 : FpIf64CMov<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), 451 CondMovFP, 452 [(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2, 453 cc, EFLAGS))]>; 454 def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), 455 CondMovFP, 456 [(set RFP80:$dst, (X86cmov RFP80:$src1, RFP80:$src2, 457 cc, EFLAGS))]>, 458 Requires<[HasCMOV]>; 459} 460 461let SchedRW = [WriteFCMOV] in { 462let Uses = [EFLAGS], Constraints = "$src1 = $dst" in { 463defm CMOVB : FPCMov<X86_COND_B>; 464defm CMOVBE : FPCMov<X86_COND_BE>; 465defm CMOVE : FPCMov<X86_COND_E>; 466defm CMOVP : FPCMov<X86_COND_P>; 467defm CMOVNB : FPCMov<X86_COND_AE>; 468defm CMOVNBE: FPCMov<X86_COND_A>; 469defm CMOVNE : FPCMov<X86_COND_NE>; 470defm CMOVNP : FPCMov<X86_COND_NP>; 471} // Uses = [EFLAGS], Constraints = "$src1 = $dst" 472 473let Predicates = [HasCMOV] in { 474// These are not factored because there's no clean way to pass DA/DB. 475def CMOVB_F : FPI<0xDA, MRM0r, (outs), (ins RSTi:$op), 476 "fcmovb\t{$op, %st|st, $op}">; 477def CMOVBE_F : FPI<0xDA, MRM2r, (outs), (ins RSTi:$op), 478 "fcmovbe\t{$op, %st|st, $op}">; 479def CMOVE_F : FPI<0xDA, MRM1r, (outs), (ins RSTi:$op), 480 "fcmove\t{$op, %st|st, $op}">; 481def CMOVP_F : FPI<0xDA, MRM3r, (outs), (ins RSTi:$op), 482 "fcmovu\t{$op, %st|st, $op}">; 483def CMOVNB_F : FPI<0xDB, MRM0r, (outs), (ins RSTi:$op), 484 "fcmovnb\t{$op, %st|st, $op}">; 485def CMOVNBE_F: FPI<0xDB, MRM2r, (outs), (ins RSTi:$op), 486 "fcmovnbe\t{$op, %st|st, $op}">; 487def CMOVNE_F : FPI<0xDB, MRM1r, (outs), (ins RSTi:$op), 488 "fcmovne\t{$op, %st|st, $op}">; 489def CMOVNP_F : FPI<0xDB, MRM3r, (outs), (ins RSTi:$op), 490 "fcmovnu\t{$op, %st|st, $op}">; 491} // Predicates = [HasCMOV] 492} // SchedRW 493 494let mayRaiseFPException = 1 in { 495// Floating point loads & stores. 496let SchedRW = [WriteLoad], Uses = [FPCW] in { 497let canFoldAsLoad = 1 in { 498def LD_Fp32m : FpIf32<(outs RFP32:$dst), (ins f32mem:$src), ZeroArgFP, 499 [(set RFP32:$dst, (loadf32 addr:$src))]>; 500def LD_Fp64m : FpIf64<(outs RFP64:$dst), (ins f64mem:$src), ZeroArgFP, 501 [(set RFP64:$dst, (loadf64 addr:$src))]>; 502def LD_Fp80m : FpI_<(outs RFP80:$dst), (ins f80mem:$src), ZeroArgFP, 503 [(set RFP80:$dst, (loadf80 addr:$src))]>; 504} // canFoldAsLoad 505def LD_Fp32m64 : FpIf64<(outs RFP64:$dst), (ins f32mem:$src), ZeroArgFP, 506 [(set RFP64:$dst, (f64 (extloadf32 addr:$src)))]>; 507def LD_Fp64m80 : FpI_<(outs RFP80:$dst), (ins f64mem:$src), ZeroArgFP, 508 [(set RFP80:$dst, (f80 (extloadf64 addr:$src)))]>; 509def LD_Fp32m80 : FpI_<(outs RFP80:$dst), (ins f32mem:$src), ZeroArgFP, 510 [(set RFP80:$dst, (f80 (extloadf32 addr:$src)))]>; 511let mayRaiseFPException = 0 in { 512def ILD_Fp16m32: FpIf32<(outs RFP32:$dst), (ins i16mem:$src), ZeroArgFP, 513 [(set RFP32:$dst, (X86fild16 addr:$src))]>; 514def ILD_Fp32m32: FpIf32<(outs RFP32:$dst), (ins i32mem:$src), ZeroArgFP, 515 [(set RFP32:$dst, (X86fild32 addr:$src))]>; 516def ILD_Fp64m32: FpIf32<(outs RFP32:$dst), (ins i64mem:$src), ZeroArgFP, 517 [(set RFP32:$dst, (X86fild64 addr:$src))]>; 518def ILD_Fp16m64: FpIf64<(outs RFP64:$dst), (ins i16mem:$src), ZeroArgFP, 519 [(set RFP64:$dst, (X86fild16 addr:$src))]>; 520def ILD_Fp32m64: FpIf64<(outs RFP64:$dst), (ins i32mem:$src), ZeroArgFP, 521 [(set RFP64:$dst, (X86fild32 addr:$src))]>; 522def ILD_Fp64m64: FpIf64<(outs RFP64:$dst), (ins i64mem:$src), ZeroArgFP, 523 [(set RFP64:$dst, (X86fild64 addr:$src))]>; 524def ILD_Fp16m80: FpI_<(outs RFP80:$dst), (ins i16mem:$src), ZeroArgFP, 525 [(set RFP80:$dst, (X86fild16 addr:$src))]>; 526def ILD_Fp32m80: FpI_<(outs RFP80:$dst), (ins i32mem:$src), ZeroArgFP, 527 [(set RFP80:$dst, (X86fild32 addr:$src))]>; 528def ILD_Fp64m80: FpI_<(outs RFP80:$dst), (ins i64mem:$src), ZeroArgFP, 529 [(set RFP80:$dst, (X86fild64 addr:$src))]>; 530} // mayRaiseFPException = 0 531} // SchedRW 532 533let SchedRW = [WriteStore], Uses = [FPCW] in { 534def ST_Fp32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, 535 [(store RFP32:$src, addr:$op)]>; 536def ST_Fp64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, 537 [(truncstoref32 RFP64:$src, addr:$op)]>; 538def ST_Fp64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, 539 [(store RFP64:$src, addr:$op)]>; 540def ST_Fp80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, 541 [(truncstoref32 RFP80:$src, addr:$op)]>; 542def ST_Fp80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, 543 [(truncstoref64 RFP80:$src, addr:$op)]>; 544// FST does not support 80-bit memory target; FSTP must be used. 545 546let mayStore = 1, hasSideEffects = 0 in { 547def ST_FpP32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, []>; 548def ST_FpP64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, []>; 549def ST_FpP64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, []>; 550def ST_FpP80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, []>; 551def ST_FpP80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, []>; 552} // mayStore 553 554def ST_FpP80m : FpI_<(outs), (ins f80mem:$op, RFP80:$src), OneArgFP, 555 [(store RFP80:$src, addr:$op)]>; 556 557let mayStore = 1, hasSideEffects = 0 in { 558def IST_Fp16m32 : FpIf32<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, []>; 559def IST_Fp32m32 : FpIf32<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, 560 [(X86fist32 RFP32:$src, addr:$op)]>; 561def IST_Fp64m32 : FpIf32<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, 562 [(X86fist64 RFP32:$src, addr:$op)]>; 563def IST_Fp16m64 : FpIf64<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, []>; 564def IST_Fp32m64 : FpIf64<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, 565 [(X86fist32 RFP64:$src, addr:$op)]>; 566def IST_Fp64m64 : FpIf64<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, 567 [(X86fist64 RFP64:$src, addr:$op)]>; 568def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; 569def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, 570 [(X86fist32 RFP80:$src, addr:$op)]>; 571def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, 572 [(X86fist64 RFP80:$src, addr:$op)]>; 573} // mayStore 574} // SchedRW, Uses = [FPCW] 575 576let mayLoad = 1, SchedRW = [WriteLoad], Uses = [FPCW] in { 577def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; 578def LD_F64m : FPI<0xDD, MRM0m, (outs), (ins f64mem:$src), "fld{l}\t$src">; 579def LD_F80m : FPI<0xDB, MRM5m, (outs), (ins f80mem:$src), "fld{t}\t$src">; 580let mayRaiseFPException = 0 in { 581def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; 582def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; 583def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; 584} 585} 586let mayStore = 1, SchedRW = [WriteStore], Uses = [FPCW] in { 587def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; 588def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; 589def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; 590def ST_FP64m : FPI<0xDD, MRM3m, (outs), (ins f64mem:$dst), "fstp{l}\t$dst">; 591def ST_FP80m : FPI<0xDB, MRM7m, (outs), (ins f80mem:$dst), "fstp{t}\t$dst">; 592def IST_F16m : FPI<0xDF, MRM2m, (outs), (ins i16mem:$dst), "fist{s}\t$dst">; 593def IST_F32m : FPI<0xDB, MRM2m, (outs), (ins i32mem:$dst), "fist{l}\t$dst">; 594def IST_FP16m : FPI<0xDF, MRM3m, (outs), (ins i16mem:$dst), "fistp{s}\t$dst">; 595def IST_FP32m : FPI<0xDB, MRM3m, (outs), (ins i32mem:$dst), "fistp{l}\t$dst">; 596def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; 597} 598 599// FISTTP requires SSE3 even though it's a FPStack op. 600let Predicates = [HasSSE3], SchedRW = [WriteStore], Uses = [FPCW] in { 601def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, 602 [(X86fp_to_i16mem RFP32:$src, addr:$op)]>; 603def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, 604 [(X86fp_to_i32mem RFP32:$src, addr:$op)]>; 605def ISTT_Fp64m32 : FpI_<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, 606 [(X86fp_to_i64mem RFP32:$src, addr:$op)]>; 607def ISTT_Fp16m64 : FpI_<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, 608 [(X86fp_to_i16mem RFP64:$src, addr:$op)]>; 609def ISTT_Fp32m64 : FpI_<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, 610 [(X86fp_to_i32mem RFP64:$src, addr:$op)]>; 611def ISTT_Fp64m64 : FpI_<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, 612 [(X86fp_to_i64mem RFP64:$src, addr:$op)]>; 613def ISTT_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, 614 [(X86fp_to_i16mem RFP80:$src, addr:$op)]>; 615def ISTT_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, 616 [(X86fp_to_i32mem RFP80:$src, addr:$op)]>; 617def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, 618 [(X86fp_to_i64mem RFP80:$src, addr:$op)]>; 619} // Predicates = [HasSSE3] 620 621let mayStore = 1, SchedRW = [WriteStore], Uses = [FPCW] in { 622def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; 623def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; 624def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst">; 625} 626 627// FP Stack manipulation instructions. 628let SchedRW = [WriteMove], Uses = [FPCW] in { 629def LD_Frr : FPI<0xD9, MRM0r, (outs), (ins RSTi:$op), "fld\t$op">; 630def ST_Frr : FPI<0xDD, MRM2r, (outs), (ins RSTi:$op), "fst\t$op">; 631def ST_FPrr : FPI<0xDD, MRM3r, (outs), (ins RSTi:$op), "fstp\t$op">; 632let mayRaiseFPException = 0 in 633def XCH_F : FPI<0xD9, MRM1r, (outs), (ins RSTi:$op), "fxch\t$op">; 634} 635 636// Floating point constant loads. 637let SchedRW = [WriteZero], Uses = [FPCW] in { 638def LD_Fp032 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, 639 [(set RFP32:$dst, fpimm0)]>; 640def LD_Fp132 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, 641 [(set RFP32:$dst, fpimm1)]>; 642def LD_Fp064 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, 643 [(set RFP64:$dst, fpimm0)]>; 644def LD_Fp164 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, 645 [(set RFP64:$dst, fpimm1)]>; 646def LD_Fp080 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, 647 [(set RFP80:$dst, fpimm0)]>; 648def LD_Fp180 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, 649 [(set RFP80:$dst, fpimm1)]>; 650} 651 652let SchedRW = [WriteFLD0], Uses = [FPCW], mayRaiseFPException = 0 in 653def LD_F0 : FPI<0xD9, MRM_EE, (outs), (ins), "fldz">; 654 655let SchedRW = [WriteFLD1], Uses = [FPCW], mayRaiseFPException = 0 in 656def LD_F1 : FPI<0xD9, MRM_E8, (outs), (ins), "fld1">; 657 658let SchedRW = [WriteFLDC], Defs = [FPSW], Uses = [FPCW], mayRaiseFPException = 0 in { 659def FLDL2T : I<0xD9, MRM_E9, (outs), (ins), "fldl2t", []>; 660def FLDL2E : I<0xD9, MRM_EA, (outs), (ins), "fldl2e", []>; 661def FLDPI : I<0xD9, MRM_EB, (outs), (ins), "fldpi", []>; 662def FLDLG2 : I<0xD9, MRM_EC, (outs), (ins), "fldlg2", []>; 663def FLDLN2 : I<0xD9, MRM_ED, (outs), (ins), "fldln2", []>; 664} // SchedRW 665 666// Floating point compares. 667let SchedRW = [WriteFCom], Uses = [FPCW], hasSideEffects = 0 in { 668def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, []>; 669def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, []>; 670def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, []>; 671def COM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, []>; 672def COM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, []>; 673def COM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, []>; 674} // SchedRW 675} // mayRaiseFPException = 1 676 677let SchedRW = [WriteFCom], mayRaiseFPException = 1 in { 678// CC = ST(0) cmp ST(i) 679let Defs = [EFLAGS, FPSW], Uses = [FPCW] in { 680def UCOM_FpIr32: FpI_<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, 681 [(set EFLAGS, (X86any_fcmp RFP32:$lhs, RFP32:$rhs))]>, 682 Requires<[FPStackf32, HasCMOV]>; 683def UCOM_FpIr64: FpI_<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, 684 [(set EFLAGS, (X86any_fcmp RFP64:$lhs, RFP64:$rhs))]>, 685 Requires<[FPStackf64, HasCMOV]>; 686def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, 687 [(set EFLAGS, (X86any_fcmp RFP80:$lhs, RFP80:$rhs))]>, 688 Requires<[HasCMOV]>; 689def COM_FpIr32: FpI_<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, 690 [(set EFLAGS, (X86strict_fcmps RFP32:$lhs, RFP32:$rhs))]>, 691 Requires<[FPStackf32, HasCMOV]>; 692def COM_FpIr64: FpI_<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, 693 [(set EFLAGS, (X86strict_fcmps RFP64:$lhs, RFP64:$rhs))]>, 694 Requires<[FPStackf64, HasCMOV]>; 695def COM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, 696 [(set EFLAGS, (X86strict_fcmps RFP80:$lhs, RFP80:$rhs))]>, 697 Requires<[HasCMOV]>; 698} 699 700let Uses = [ST0, FPCW] in { 701def UCOM_Fr : FPI<0xDD, MRM4r, // FPSW = cmp ST(0) with ST(i) 702 (outs), (ins RSTi:$reg), "fucom\t$reg">; 703def UCOM_FPr : FPI<0xDD, MRM5r, // FPSW = cmp ST(0) with ST(i), pop 704 (outs), (ins RSTi:$reg), "fucomp\t$reg">; 705def UCOM_FPPr : FPI<0xDA, MRM_E9, // cmp ST(0) with ST(1), pop, pop 706 (outs), (ins), "fucompp">; 707} 708 709let Defs = [EFLAGS, FPSW], Uses = [ST0, FPCW] in { 710def UCOM_FIr : FPI<0xDB, MRM5r, // CC = cmp ST(0) with ST(i) 711 (outs), (ins RSTi:$reg), "fucomi\t{$reg, %st|st, $reg}">; 712def UCOM_FIPr : FPI<0xDF, MRM5r, // CC = cmp ST(0) with ST(i), pop 713 (outs), (ins RSTi:$reg), "fucompi\t{$reg, %st|st, $reg}">; 714 715def COM_FIr : FPI<0xDB, MRM6r, (outs), (ins RSTi:$reg), 716 "fcomi\t{$reg, %st|st, $reg}">; 717def COM_FIPr : FPI<0xDF, MRM6r, (outs), (ins RSTi:$reg), 718 "fcompi\t{$reg, %st|st, $reg}">; 719} 720} // SchedRW 721 722// Floating point flag ops. 723let SchedRW = [WriteALU] in { 724let Defs = [AX, FPSW], Uses = [FPSW], hasSideEffects = 0 in 725def FNSTSW16r : I<0xDF, MRM_E0, // AX = fp flags 726 (outs), (ins), "fnstsw\t{%ax|ax}", []>; 727let Defs = [FPSW], Uses = [FPCW] in 728def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world 729 (outs), (ins i16mem:$dst), "fnstcw\t$dst", 730 [(X86fp_cwd_get16 addr:$dst)]>; 731} // SchedRW 732let Defs = [FPSW,FPCW], mayLoad = 1 in 733def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] 734 (outs), (ins i16mem:$dst), "fldcw\t$dst", 735 [(X86fp_cwd_set16 addr:$dst)]>, 736 Sched<[WriteLoad]>; 737 738// FPU control instructions 739let SchedRW = [WriteMicrocoded] in { 740def FFREE : FPI<0xDD, MRM0r, (outs), (ins RSTi:$reg), "ffree\t$reg">; 741def FFREEP : FPI<0xDF, MRM0r, (outs), (ins RSTi:$reg), "ffreep\t$reg">; 742 743let Defs = [FPSW, FPCW] in 744def FNINIT : I<0xDB, MRM_E3, (outs), (ins), "fninit", []>; 745// Clear exceptions 746let Defs = [FPSW] in 747def FNCLEX : I<0xDB, MRM_E2, (outs), (ins), "fnclex", []>; 748} // SchedRW 749 750// Operand-less floating-point instructions for the disassembler. 751let Defs = [FPSW] in 752def FNOP : I<0xD9, MRM_D0, (outs), (ins), "fnop", []>, Sched<[WriteNop]>; 753 754let SchedRW = [WriteMicrocoded] in { 755let Defs = [FPSW] in { 756def WAIT : I<0x9B, RawFrm, (outs), (ins), "wait", []>; 757def FDECSTP : I<0xD9, MRM_F6, (outs), (ins), "fdecstp", []>; 758def FINCSTP : I<0xD9, MRM_F7, (outs), (ins), "fincstp", []>; 759let Uses = [FPCW], mayRaiseFPException = 1 in { 760def F2XM1 : I<0xD9, MRM_F0, (outs), (ins), "f2xm1", []>; 761def FYL2X : I<0xD9, MRM_F1, (outs), (ins), "fyl2x", []>; 762def FPTAN : I<0xD9, MRM_F2, (outs), (ins), "fptan", []>; 763def FPATAN : I<0xD9, MRM_F3, (outs), (ins), "fpatan", []>; 764def FXTRACT : I<0xD9, MRM_F4, (outs), (ins), "fxtract", []>; 765def FPREM1 : I<0xD9, MRM_F5, (outs), (ins), "fprem1", []>; 766def FPREM : I<0xD9, MRM_F8, (outs), (ins), "fprem", []>; 767def FYL2XP1 : I<0xD9, MRM_F9, (outs), (ins), "fyl2xp1", []>; 768def FSIN : I<0xD9, MRM_FE, (outs), (ins), "fsin", []>; 769def FCOS : I<0xD9, MRM_FF, (outs), (ins), "fcos", []>; 770def FSINCOS : I<0xD9, MRM_FB, (outs), (ins), "fsincos", []>; 771def FRNDINT : I<0xD9, MRM_FC, (outs), (ins), "frndint", []>; 772def FSCALE : I<0xD9, MRM_FD, (outs), (ins), "fscale", []>; 773def FCOMPP : I<0xDE, MRM_D9, (outs), (ins), "fcompp", []>; 774} // Uses = [FPCW], mayRaiseFPException = 1 775} // Defs = [FPSW] 776 777let Uses = [FPSW, FPCW] in { 778def FXSAVE : I<0xAE, MRM0m, (outs), (ins opaquemem:$dst), 779 "fxsave\t$dst", [(int_x86_fxsave addr:$dst)]>, PS, 780 Requires<[HasFXSR]>; 781def FXSAVE64 : RI<0xAE, MRM0m, (outs), (ins opaquemem:$dst), 782 "fxsave64\t$dst", [(int_x86_fxsave64 addr:$dst)]>, 783 PS, Requires<[HasFXSR, In64BitMode]>; 784} // Uses = [FPSW, FPCW] 785 786let Defs = [FPSW, FPCW] in { 787def FXRSTOR : I<0xAE, MRM1m, (outs), (ins opaquemem:$src), 788 "fxrstor\t$src", [(int_x86_fxrstor addr:$src)]>, 789 PS, Requires<[HasFXSR]>; 790def FXRSTOR64 : RI<0xAE, MRM1m, (outs), (ins opaquemem:$src), 791 "fxrstor64\t$src", [(int_x86_fxrstor64 addr:$src)]>, 792 PS, Requires<[HasFXSR, In64BitMode]>; 793} // Defs = [FPSW, FPCW] 794} // SchedRW 795 796//===----------------------------------------------------------------------===// 797// Non-Instruction Patterns 798//===----------------------------------------------------------------------===// 799 800// Required for RET of f32 / f64 / f80 values. 801def : Pat<(X86fldf32 addr:$src), (LD_Fp32m addr:$src)>; 802def : Pat<(X86fldf32 addr:$src), (LD_Fp32m64 addr:$src)>; 803def : Pat<(X86fldf64 addr:$src), (LD_Fp64m addr:$src)>; 804def : Pat<(X86fldf32 addr:$src), (LD_Fp32m80 addr:$src)>; 805def : Pat<(X86fldf64 addr:$src), (LD_Fp64m80 addr:$src)>; 806def : Pat<(X86fldf80 addr:$src), (LD_Fp80m addr:$src)>; 807 808// Required for CALL which return f32 / f64 / f80 values. 809def : Pat<(X86fstf32 RFP32:$src, addr:$op), (ST_Fp32m addr:$op, RFP32:$src)>; 810def : Pat<(X86fstf32 RFP64:$src, addr:$op), (ST_Fp64m32 addr:$op, RFP64:$src)>; 811def : Pat<(X86fstf64 RFP64:$src, addr:$op), (ST_Fp64m addr:$op, RFP64:$src)>; 812def : Pat<(X86fstf32 RFP80:$src, addr:$op), (ST_Fp80m32 addr:$op, RFP80:$src)>; 813def : Pat<(X86fstf64 RFP80:$src, addr:$op), (ST_Fp80m64 addr:$op, RFP80:$src)>; 814def : Pat<(X86fstf80 RFP80:$src, addr:$op), (ST_FpP80m addr:$op, RFP80:$src)>; 815 816// Floating point constant -0.0 and -1.0 817def : Pat<(f32 fpimmneg0), (CHS_Fp32 (LD_Fp032))>, Requires<[FPStackf32]>; 818def : Pat<(f32 fpimmneg1), (CHS_Fp32 (LD_Fp132))>, Requires<[FPStackf32]>; 819def : Pat<(f64 fpimmneg0), (CHS_Fp64 (LD_Fp064))>, Requires<[FPStackf64]>; 820def : Pat<(f64 fpimmneg1), (CHS_Fp64 (LD_Fp164))>, Requires<[FPStackf64]>; 821def : Pat<(f80 fpimmneg0), (CHS_Fp80 (LD_Fp080))>; 822def : Pat<(f80 fpimmneg1), (CHS_Fp80 (LD_Fp180))>; 823 824// FP extensions map onto simple pseudo-value conversions if they are to/from 825// the FP stack. 826def : Pat<(f64 (any_fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>, 827 Requires<[FPStackf32]>; 828def : Pat<(f80 (any_fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>, 829 Requires<[FPStackf32]>; 830def : Pat<(f80 (any_fpextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>, 831 Requires<[FPStackf64]>; 832 833// FP truncations map onto simple pseudo-value conversions if they are to/from 834// the FP stack. We have validated that only value-preserving truncations make 835// it through isel. 836def : Pat<(f32 (any_fpround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>, 837 Requires<[FPStackf32]>; 838def : Pat<(f32 (any_fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>, 839 Requires<[FPStackf32]>; 840def : Pat<(f64 (any_fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>, 841 Requires<[FPStackf64]>; 842