1//==- X86InstrFPStack.td - Describe the X86 Instruction Set --*- tablegen -*-=// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file describes the X86 x87 FPU instruction set, defining the 11// instructions, and properties of the instructions which are needed for code 12// generation, machine code emission, and analysis. 13// 14//===----------------------------------------------------------------------===// 15 16//===----------------------------------------------------------------------===// 17// FPStack specific DAG Nodes. 18//===----------------------------------------------------------------------===// 19 20def SDTX86FpGet2 : SDTypeProfile<2, 0, [SDTCisVT<0, f80>, 21 SDTCisVT<1, f80>]>; 22def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>, 23 SDTCisPtrTy<1>, 24 SDTCisVT<2, OtherVT>]>; 25def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, 26 SDTCisPtrTy<1>, 27 SDTCisVT<2, OtherVT>]>; 28def SDTX86Fild : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisPtrTy<1>, 29 SDTCisVT<2, OtherVT>]>; 30def SDTX86FpToIMem : SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; 31 32def SDTX86CwdStore : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; 33 34def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, 35 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; 36def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, 37 [SDNPHasChain, SDNPInGlue, SDNPMayStore, 38 SDNPMemOperand]>; 39def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, 40 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; 41def X86fildflag : SDNode<"X86ISD::FILD_FLAG", SDTX86Fild, 42 [SDNPHasChain, SDNPOutGlue, SDNPMayLoad, 43 SDNPMemOperand]>; 44def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem, 45 [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; 46def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem, 47 [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; 48def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem, 49 [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; 50def X86fp_cwd_get16 : SDNode<"X86ISD::FNSTCW16m", SDTX86CwdStore, 51 [SDNPHasChain, SDNPMayStore, SDNPSideEffect, 52 SDNPMemOperand]>; 53 54//===----------------------------------------------------------------------===// 55// FPStack pattern fragments 56//===----------------------------------------------------------------------===// 57 58def fpimm0 : PatLeaf<(fpimm), [{ 59 return N->isExactlyValue(+0.0); 60}]>; 61 62def fpimmneg0 : PatLeaf<(fpimm), [{ 63 return N->isExactlyValue(-0.0); 64}]>; 65 66def fpimm1 : PatLeaf<(fpimm), [{ 67 return N->isExactlyValue(+1.0); 68}]>; 69 70def fpimmneg1 : PatLeaf<(fpimm), [{ 71 return N->isExactlyValue(-1.0); 72}]>; 73 74// Some 'special' instructions 75let usesCustomInserter = 1 in { // Expanded after instruction selection. 76 def FP32_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP32:$src), 77 [(X86fp_to_i16mem RFP32:$src, addr:$dst)]>; 78 def FP32_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP32:$src), 79 [(X86fp_to_i32mem RFP32:$src, addr:$dst)]>; 80 def FP32_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP32:$src), 81 [(X86fp_to_i64mem RFP32:$src, addr:$dst)]>; 82 def FP64_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP64:$src), 83 [(X86fp_to_i16mem RFP64:$src, addr:$dst)]>; 84 def FP64_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP64:$src), 85 [(X86fp_to_i32mem RFP64:$src, addr:$dst)]>; 86 def FP64_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP64:$src), 87 [(X86fp_to_i64mem RFP64:$src, addr:$dst)]>; 88 def FP80_TO_INT16_IN_MEM : PseudoI<(outs), (ins i16mem:$dst, RFP80:$src), 89 [(X86fp_to_i16mem RFP80:$src, addr:$dst)]>; 90 def FP80_TO_INT32_IN_MEM : PseudoI<(outs), (ins i32mem:$dst, RFP80:$src), 91 [(X86fp_to_i32mem RFP80:$src, addr:$dst)]>; 92 def FP80_TO_INT64_IN_MEM : PseudoI<(outs), (ins i64mem:$dst, RFP80:$src), 93 [(X86fp_to_i64mem RFP80:$src, addr:$dst)]>; 94} 95 96// All FP Stack operations are represented with four instructions here. The 97// first three instructions, generated by the instruction selector, use "RFP32" 98// "RFP64" or "RFP80" registers: traditional register files to reference 32-bit, 99// 64-bit or 80-bit floating point values. These sizes apply to the values, 100// not the registers, which are always 80 bits; RFP32, RFP64 and RFP80 can be 101// copied to each other without losing information. These instructions are all 102// pseudo instructions and use the "_Fp" suffix. 103// In some cases there are additional variants with a mixture of different 104// register sizes. 105// The second instruction is defined with FPI, which is the actual instruction 106// emitted by the assembler. These use "RST" registers, although frequently 107// the actual register(s) used are implicit. These are always 80 bits. 108// The FP stackifier pass converts one to the other after register allocation 109// occurs. 110// 111// Note that the FpI instruction should have instruction selection info (e.g. 112// a pattern) and the FPI instruction should have emission info (e.g. opcode 113// encoding and asm printing info). 114 115// Pseudo Instruction for FP stack return values. 116def FpPOP_RETVAL : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; 117 118// FpIf32, FpIf64 - Floating Point Pseudo Instruction template. 119// f32 instructions can use SSE1 and are predicated on FPStackf32 == !SSE1. 120// f64 instructions can use SSE2 and are predicated on FPStackf64 == !SSE2. 121// f80 instructions cannot use SSE and use neither of these. 122class FpIf32<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 123 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf32]>; 124class FpIf64<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 125 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf64]>; 126 127// Factoring for arithmetic. 128multiclass FPBinary_rr<SDNode OpNode> { 129// Register op register -> register 130// These are separated out because they have no reversed form. 131def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), TwoArgFP, 132 [(set RFP32:$dst, (OpNode RFP32:$src1, RFP32:$src2))]>; 133def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), TwoArgFP, 134 [(set RFP64:$dst, (OpNode RFP64:$src1, RFP64:$src2))]>; 135def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), TwoArgFP, 136 [(set RFP80:$dst, (OpNode RFP80:$src1, RFP80:$src2))]>; 137} 138// The FopST0 series are not included here because of the irregularities 139// in where the 'r' goes in assembly output. 140// These instructions cannot address 80-bit memory. 141multiclass FPBinary<SDNode OpNode, Format fp, string asmstring> { 142// ST(0) = ST(0) + [mem] 143def _Fp32m : FpIf32<(outs RFP32:$dst), 144 (ins RFP32:$src1, f32mem:$src2), OneArgFPRW, 145 [(set RFP32:$dst, 146 (OpNode RFP32:$src1, (loadf32 addr:$src2)))]>; 147def _Fp64m : FpIf64<(outs RFP64:$dst), 148 (ins RFP64:$src1, f64mem:$src2), OneArgFPRW, 149 [(set RFP64:$dst, 150 (OpNode RFP64:$src1, (loadf64 addr:$src2)))]>; 151def _Fp64m32: FpIf64<(outs RFP64:$dst), 152 (ins RFP64:$src1, f32mem:$src2), OneArgFPRW, 153 [(set RFP64:$dst, 154 (OpNode RFP64:$src1, (f64 (extloadf32 addr:$src2))))]>; 155def _Fp80m32: FpI_<(outs RFP80:$dst), 156 (ins RFP80:$src1, f32mem:$src2), OneArgFPRW, 157 [(set RFP80:$dst, 158 (OpNode RFP80:$src1, (f80 (extloadf32 addr:$src2))))]>; 159def _Fp80m64: FpI_<(outs RFP80:$dst), 160 (ins RFP80:$src1, f64mem:$src2), OneArgFPRW, 161 [(set RFP80:$dst, 162 (OpNode RFP80:$src1, (f80 (extloadf64 addr:$src2))))]>; 163def _F32m : FPI<0xD8, fp, (outs), (ins f32mem:$src), 164 !strconcat("f", asmstring, "{s}\t$src")> { 165 let mayLoad = 1; 166} 167def _F64m : FPI<0xDC, fp, (outs), (ins f64mem:$src), 168 !strconcat("f", asmstring, "{l}\t$src")> { 169 let mayLoad = 1; 170} 171// ST(0) = ST(0) + [memint] 172def _FpI16m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i16mem:$src2), 173 OneArgFPRW, 174 [(set RFP32:$dst, (OpNode RFP32:$src1, 175 (X86fild addr:$src2, i16)))]>; 176def _FpI32m32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src1, i32mem:$src2), 177 OneArgFPRW, 178 [(set RFP32:$dst, (OpNode RFP32:$src1, 179 (X86fild addr:$src2, i32)))]>; 180def _FpI16m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i16mem:$src2), 181 OneArgFPRW, 182 [(set RFP64:$dst, (OpNode RFP64:$src1, 183 (X86fild addr:$src2, i16)))]>; 184def _FpI32m64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src1, i32mem:$src2), 185 OneArgFPRW, 186 [(set RFP64:$dst, (OpNode RFP64:$src1, 187 (X86fild addr:$src2, i32)))]>; 188def _FpI16m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i16mem:$src2), 189 OneArgFPRW, 190 [(set RFP80:$dst, (OpNode RFP80:$src1, 191 (X86fild addr:$src2, i16)))]>; 192def _FpI32m80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, i32mem:$src2), 193 OneArgFPRW, 194 [(set RFP80:$dst, (OpNode RFP80:$src1, 195 (X86fild addr:$src2, i32)))]>; 196def _FI16m : FPI<0xDE, fp, (outs), (ins i16mem:$src), 197 !strconcat("fi", asmstring, "{s}\t$src")> { 198 let mayLoad = 1; 199} 200def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), 201 !strconcat("fi", asmstring, "{l}\t$src")> { 202 let mayLoad = 1; 203} 204} 205 206defm ADD : FPBinary_rr<fadd>; 207defm SUB : FPBinary_rr<fsub>; 208defm MUL : FPBinary_rr<fmul>; 209defm DIV : FPBinary_rr<fdiv>; 210defm ADD : FPBinary<fadd, MRM0m, "add">; 211defm SUB : FPBinary<fsub, MRM4m, "sub">; 212defm SUBR: FPBinary<fsub ,MRM5m, "subr">; 213defm MUL : FPBinary<fmul, MRM1m, "mul">; 214defm DIV : FPBinary<fdiv, MRM6m, "div">; 215defm DIVR: FPBinary<fdiv, MRM7m, "divr">; 216 217class FPST0rInst<bits<8> o, string asm> 218 : FPI<o, AddRegFrm, (outs), (ins RST:$op), asm>, D8; 219class FPrST0Inst<bits<8> o, string asm> 220 : FPI<o, AddRegFrm, (outs), (ins RST:$op), asm>, DC; 221class FPrST0PInst<bits<8> o, string asm> 222 : FPI<o, AddRegFrm, (outs), (ins RST:$op), asm>, DE; 223 224// NOTE: GAS and apparently all other AT&T style assemblers have a broken notion 225// of some of the 'reverse' forms of the fsub and fdiv instructions. As such, 226// we have to put some 'r's in and take them out of weird places. 227def ADD_FST0r : FPST0rInst <0xC0, "fadd\t$op">; 228def ADD_FrST0 : FPrST0Inst <0xC0, "fadd\t{%st(0), $op|$op, %ST(0)}">; 229def ADD_FPrST0 : FPrST0PInst<0xC0, "faddp\t$op">; 230def SUBR_FST0r : FPST0rInst <0xE8, "fsubr\t$op">; 231def SUB_FrST0 : FPrST0Inst <0xE8, "fsub{r}\t{%st(0), $op|$op, %ST(0)}">; 232def SUB_FPrST0 : FPrST0PInst<0xE8, "fsub{r}p\t$op">; 233def SUB_FST0r : FPST0rInst <0xE0, "fsub\t$op">; 234def SUBR_FrST0 : FPrST0Inst <0xE0, "fsub{|r}\t{%st(0), $op|$op, %ST(0)}">; 235def SUBR_FPrST0 : FPrST0PInst<0xE0, "fsub{|r}p\t$op">; 236def MUL_FST0r : FPST0rInst <0xC8, "fmul\t$op">; 237def MUL_FrST0 : FPrST0Inst <0xC8, "fmul\t{%st(0), $op|$op, %ST(0)}">; 238def MUL_FPrST0 : FPrST0PInst<0xC8, "fmulp\t$op">; 239def DIVR_FST0r : FPST0rInst <0xF8, "fdivr\t$op">; 240def DIV_FrST0 : FPrST0Inst <0xF8, "fdiv{r}\t{%st(0), $op|$op, %ST(0)}">; 241def DIV_FPrST0 : FPrST0PInst<0xF8, "fdiv{r}p\t$op">; 242def DIV_FST0r : FPST0rInst <0xF0, "fdiv\t$op">; 243def DIVR_FrST0 : FPrST0Inst <0xF0, "fdiv{|r}\t{%st(0), $op|$op, %ST(0)}">; 244def DIVR_FPrST0 : FPrST0PInst<0xF0, "fdiv{|r}p\t$op">; 245 246def COM_FST0r : FPST0rInst <0xD0, "fcom\t$op">; 247def COMP_FST0r : FPST0rInst <0xD8, "fcomp\t$op">; 248 249// Unary operations. 250multiclass FPUnary<SDNode OpNode, bits<8> opcode, string asmstring> { 251def _Fp32 : FpIf32<(outs RFP32:$dst), (ins RFP32:$src), OneArgFPRW, 252 [(set RFP32:$dst, (OpNode RFP32:$src))]>; 253def _Fp64 : FpIf64<(outs RFP64:$dst), (ins RFP64:$src), OneArgFPRW, 254 [(set RFP64:$dst, (OpNode RFP64:$src))]>; 255def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src), OneArgFPRW, 256 [(set RFP80:$dst, (OpNode RFP80:$src))]>; 257def _F : FPI<opcode, RawFrm, (outs), (ins), asmstring>, D9; 258} 259 260defm CHS : FPUnary<fneg, 0xE0, "fchs">; 261defm ABS : FPUnary<fabs, 0xE1, "fabs">; 262defm SQRT: FPUnary<fsqrt,0xFA, "fsqrt">; 263defm SIN : FPUnary<fsin, 0xFE, "fsin">; 264defm COS : FPUnary<fcos, 0xFF, "fcos">; 265 266let neverHasSideEffects = 1 in { 267def TST_Fp32 : FpIf32<(outs), (ins RFP32:$src), OneArgFP, []>; 268def TST_Fp64 : FpIf64<(outs), (ins RFP64:$src), OneArgFP, []>; 269def TST_Fp80 : FpI_<(outs), (ins RFP80:$src), OneArgFP, []>; 270} 271def TST_F : FPI<0xE4, RawFrm, (outs), (ins), "ftst">, D9; 272 273// Versions of FP instructions that take a single memory operand. Added for the 274// disassembler; remove as they are included with patterns elsewhere. 275def FCOM32m : FPI<0xD8, MRM2m, (outs), (ins f32mem:$src), "fcom{s}\t$src">; 276def FCOMP32m : FPI<0xD8, MRM3m, (outs), (ins f32mem:$src), "fcomp{s}\t$src">; 277 278def FLDENVm : FPI<0xD9, MRM4m, (outs), (ins f32mem:$src), "fldenv\t$src">; 279def FSTENVm : FPI<0xD9, MRM6m, (outs f32mem:$dst), (ins), "fnstenv\t$dst">; 280 281def FICOM32m : FPI<0xDA, MRM2m, (outs), (ins i32mem:$src), "ficom{l}\t$src">; 282def FICOMP32m: FPI<0xDA, MRM3m, (outs), (ins i32mem:$src), "ficomp{l}\t$src">; 283 284def FCOM64m : FPI<0xDC, MRM2m, (outs), (ins f64mem:$src), "fcom{l}\t$src">; 285def FCOMP64m : FPI<0xDC, MRM3m, (outs), (ins f64mem:$src), "fcomp{l}\t$src">; 286 287def FRSTORm : FPI<0xDD, MRM4m, (outs f32mem:$dst), (ins), "frstor\t$dst">; 288def FSAVEm : FPI<0xDD, MRM6m, (outs f32mem:$dst), (ins), "fnsave\t$dst">; 289def FNSTSWm : FPI<0xDD, MRM7m, (outs f32mem:$dst), (ins), "fnstsw\t$dst">; 290 291def FICOM16m : FPI<0xDE, MRM2m, (outs), (ins i16mem:$src), "ficom{s}\t$src">; 292def FICOMP16m: FPI<0xDE, MRM3m, (outs), (ins i16mem:$src), "ficomp{s}\t$src">; 293 294def FBLDm : FPI<0xDF, MRM4m, (outs), (ins f32mem:$src), "fbld\t$src">; 295def FBSTPm : FPI<0xDF, MRM6m, (outs f32mem:$dst), (ins), "fbstp\t$dst">; 296 297// Floating point cmovs. 298class FpIf32CMov<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 299 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf32, HasCMov]>; 300class FpIf64CMov<dag outs, dag ins, FPFormat fp, list<dag> pattern> : 301 FpI_<outs, ins, fp, pattern>, Requires<[FPStackf64, HasCMov]>; 302 303multiclass FPCMov<PatLeaf cc> { 304 def _Fp32 : FpIf32CMov<(outs RFP32:$dst), (ins RFP32:$src1, RFP32:$src2), 305 CondMovFP, 306 [(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2, 307 cc, EFLAGS))]>; 308 def _Fp64 : FpIf64CMov<(outs RFP64:$dst), (ins RFP64:$src1, RFP64:$src2), 309 CondMovFP, 310 [(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2, 311 cc, EFLAGS))]>; 312 def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src1, RFP80:$src2), 313 CondMovFP, 314 [(set RFP80:$dst, (X86cmov RFP80:$src1, RFP80:$src2, 315 cc, EFLAGS))]>, 316 Requires<[HasCMov]>; 317} 318 319let Uses = [EFLAGS], Constraints = "$src1 = $dst" in { 320defm CMOVB : FPCMov<X86_COND_B>; 321defm CMOVBE : FPCMov<X86_COND_BE>; 322defm CMOVE : FPCMov<X86_COND_E>; 323defm CMOVP : FPCMov<X86_COND_P>; 324defm CMOVNB : FPCMov<X86_COND_AE>; 325defm CMOVNBE: FPCMov<X86_COND_A>; 326defm CMOVNE : FPCMov<X86_COND_NE>; 327defm CMOVNP : FPCMov<X86_COND_NP>; 328} // Uses = [EFLAGS], Constraints = "$src1 = $dst" 329 330let Predicates = [HasCMov] in { 331// These are not factored because there's no clean way to pass DA/DB. 332def CMOVB_F : FPI<0xC0, AddRegFrm, (outs RST:$op), (ins), 333 "fcmovb\t{$op, %st(0)|%ST(0), $op}">, DA; 334def CMOVBE_F : FPI<0xD0, AddRegFrm, (outs RST:$op), (ins), 335 "fcmovbe\t{$op, %st(0)|%ST(0), $op}">, DA; 336def CMOVE_F : FPI<0xC8, AddRegFrm, (outs RST:$op), (ins), 337 "fcmove\t{$op, %st(0)|%ST(0), $op}">, DA; 338def CMOVP_F : FPI<0xD8, AddRegFrm, (outs RST:$op), (ins), 339 "fcmovu\t {$op, %st(0)|%ST(0), $op}">, DA; 340def CMOVNB_F : FPI<0xC0, AddRegFrm, (outs RST:$op), (ins), 341 "fcmovnb\t{$op, %st(0)|%ST(0), $op}">, DB; 342def CMOVNBE_F: FPI<0xD0, AddRegFrm, (outs RST:$op), (ins), 343 "fcmovnbe\t{$op, %st(0)|%ST(0), $op}">, DB; 344def CMOVNE_F : FPI<0xC8, AddRegFrm, (outs RST:$op), (ins), 345 "fcmovne\t{$op, %st(0)|%ST(0), $op}">, DB; 346def CMOVNP_F : FPI<0xD8, AddRegFrm, (outs RST:$op), (ins), 347 "fcmovnu\t{$op, %st(0)|%ST(0), $op}">, DB; 348} // Predicates = [HasCMov] 349 350// Floating point loads & stores. 351let canFoldAsLoad = 1 in { 352def LD_Fp32m : FpIf32<(outs RFP32:$dst), (ins f32mem:$src), ZeroArgFP, 353 [(set RFP32:$dst, (loadf32 addr:$src))]>; 354let isReMaterializable = 1 in 355 def LD_Fp64m : FpIf64<(outs RFP64:$dst), (ins f64mem:$src), ZeroArgFP, 356 [(set RFP64:$dst, (loadf64 addr:$src))]>; 357def LD_Fp80m : FpI_<(outs RFP80:$dst), (ins f80mem:$src), ZeroArgFP, 358 [(set RFP80:$dst, (loadf80 addr:$src))]>; 359} 360def LD_Fp32m64 : FpIf64<(outs RFP64:$dst), (ins f32mem:$src), ZeroArgFP, 361 [(set RFP64:$dst, (f64 (extloadf32 addr:$src)))]>; 362def LD_Fp64m80 : FpI_<(outs RFP80:$dst), (ins f64mem:$src), ZeroArgFP, 363 [(set RFP80:$dst, (f80 (extloadf64 addr:$src)))]>; 364def LD_Fp32m80 : FpI_<(outs RFP80:$dst), (ins f32mem:$src), ZeroArgFP, 365 [(set RFP80:$dst, (f80 (extloadf32 addr:$src)))]>; 366def ILD_Fp16m32: FpIf32<(outs RFP32:$dst), (ins i16mem:$src), ZeroArgFP, 367 [(set RFP32:$dst, (X86fild addr:$src, i16))]>; 368def ILD_Fp32m32: FpIf32<(outs RFP32:$dst), (ins i32mem:$src), ZeroArgFP, 369 [(set RFP32:$dst, (X86fild addr:$src, i32))]>; 370def ILD_Fp64m32: FpIf32<(outs RFP32:$dst), (ins i64mem:$src), ZeroArgFP, 371 [(set RFP32:$dst, (X86fild addr:$src, i64))]>; 372def ILD_Fp16m64: FpIf64<(outs RFP64:$dst), (ins i16mem:$src), ZeroArgFP, 373 [(set RFP64:$dst, (X86fild addr:$src, i16))]>; 374def ILD_Fp32m64: FpIf64<(outs RFP64:$dst), (ins i32mem:$src), ZeroArgFP, 375 [(set RFP64:$dst, (X86fild addr:$src, i32))]>; 376def ILD_Fp64m64: FpIf64<(outs RFP64:$dst), (ins i64mem:$src), ZeroArgFP, 377 [(set RFP64:$dst, (X86fild addr:$src, i64))]>; 378def ILD_Fp16m80: FpI_<(outs RFP80:$dst), (ins i16mem:$src), ZeroArgFP, 379 [(set RFP80:$dst, (X86fild addr:$src, i16))]>; 380def ILD_Fp32m80: FpI_<(outs RFP80:$dst), (ins i32mem:$src), ZeroArgFP, 381 [(set RFP80:$dst, (X86fild addr:$src, i32))]>; 382def ILD_Fp64m80: FpI_<(outs RFP80:$dst), (ins i64mem:$src), ZeroArgFP, 383 [(set RFP80:$dst, (X86fild addr:$src, i64))]>; 384 385def ST_Fp32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, 386 [(store RFP32:$src, addr:$op)]>; 387def ST_Fp64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, 388 [(truncstoref32 RFP64:$src, addr:$op)]>; 389def ST_Fp64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, 390 [(store RFP64:$src, addr:$op)]>; 391def ST_Fp80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, 392 [(truncstoref32 RFP80:$src, addr:$op)]>; 393def ST_Fp80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, 394 [(truncstoref64 RFP80:$src, addr:$op)]>; 395// FST does not support 80-bit memory target; FSTP must be used. 396 397let mayStore = 1, neverHasSideEffects = 1 in { 398def ST_FpP32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, []>; 399def ST_FpP64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, []>; 400def ST_FpP64m : FpIf64<(outs), (ins f64mem:$op, RFP64:$src), OneArgFP, []>; 401def ST_FpP80m32 : FpI_<(outs), (ins f32mem:$op, RFP80:$src), OneArgFP, []>; 402def ST_FpP80m64 : FpI_<(outs), (ins f64mem:$op, RFP80:$src), OneArgFP, []>; 403} 404def ST_FpP80m : FpI_<(outs), (ins f80mem:$op, RFP80:$src), OneArgFP, 405 [(store RFP80:$src, addr:$op)]>; 406let mayStore = 1, neverHasSideEffects = 1 in { 407def IST_Fp16m32 : FpIf32<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, []>; 408def IST_Fp32m32 : FpIf32<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, []>; 409def IST_Fp64m32 : FpIf32<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, []>; 410def IST_Fp16m64 : FpIf64<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, []>; 411def IST_Fp32m64 : FpIf64<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, []>; 412def IST_Fp64m64 : FpIf64<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, []>; 413def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; 414def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, []>; 415def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, []>; 416} 417 418let mayLoad = 1 in { 419def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; 420def LD_F64m : FPI<0xDD, MRM0m, (outs), (ins f64mem:$src), "fld{l}\t$src">; 421def LD_F80m : FPI<0xDB, MRM5m, (outs), (ins f80mem:$src), "fld{t}\t$src">; 422def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; 423def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; 424def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; 425} 426let mayStore = 1 in { 427def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; 428def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; 429def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; 430def ST_FP64m : FPI<0xDD, MRM3m, (outs), (ins f64mem:$dst), "fstp{l}\t$dst">; 431def ST_FP80m : FPI<0xDB, MRM7m, (outs), (ins f80mem:$dst), "fstp{t}\t$dst">; 432def IST_F16m : FPI<0xDF, MRM2m, (outs), (ins i16mem:$dst), "fist{s}\t$dst">; 433def IST_F32m : FPI<0xDB, MRM2m, (outs), (ins i32mem:$dst), "fist{l}\t$dst">; 434def IST_FP16m : FPI<0xDF, MRM3m, (outs), (ins i16mem:$dst), "fistp{s}\t$dst">; 435def IST_FP32m : FPI<0xDB, MRM3m, (outs), (ins i32mem:$dst), "fistp{l}\t$dst">; 436def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; 437} 438 439// FISTTP requires SSE3 even though it's a FPStack op. 440def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, 441 [(X86fp_to_i16mem RFP32:$src, addr:$op)]>, 442 Requires<[HasSSE3]>; 443def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, 444 [(X86fp_to_i32mem RFP32:$src, addr:$op)]>, 445 Requires<[HasSSE3]>; 446def ISTT_Fp64m32 : FpI_<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, 447 [(X86fp_to_i64mem RFP32:$src, addr:$op)]>, 448 Requires<[HasSSE3]>; 449def ISTT_Fp16m64 : FpI_<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, 450 [(X86fp_to_i16mem RFP64:$src, addr:$op)]>, 451 Requires<[HasSSE3]>; 452def ISTT_Fp32m64 : FpI_<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, 453 [(X86fp_to_i32mem RFP64:$src, addr:$op)]>, 454 Requires<[HasSSE3]>; 455def ISTT_Fp64m64 : FpI_<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, 456 [(X86fp_to_i64mem RFP64:$src, addr:$op)]>, 457 Requires<[HasSSE3]>; 458def ISTT_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, 459 [(X86fp_to_i16mem RFP80:$src, addr:$op)]>, 460 Requires<[HasSSE3]>; 461def ISTT_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, 462 [(X86fp_to_i32mem RFP80:$src, addr:$op)]>, 463 Requires<[HasSSE3]>; 464def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, 465 [(X86fp_to_i64mem RFP80:$src, addr:$op)]>, 466 Requires<[HasSSE3]>; 467 468let mayStore = 1 in { 469def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; 470def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; 471def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), 472 "fisttp{ll}\t$dst">; 473} 474 475// FP Stack manipulation instructions. 476def LD_Frr : FPI<0xC0, AddRegFrm, (outs), (ins RST:$op), "fld\t$op">, D9; 477def ST_Frr : FPI<0xD0, AddRegFrm, (outs), (ins RST:$op), "fst\t$op">, DD; 478def ST_FPrr : FPI<0xD8, AddRegFrm, (outs), (ins RST:$op), "fstp\t$op">, DD; 479def XCH_F : FPI<0xC8, AddRegFrm, (outs), (ins RST:$op), "fxch\t$op">, D9; 480 481// Floating point constant loads. 482let isReMaterializable = 1 in { 483def LD_Fp032 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, 484 [(set RFP32:$dst, fpimm0)]>; 485def LD_Fp132 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, 486 [(set RFP32:$dst, fpimm1)]>; 487def LD_Fp064 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, 488 [(set RFP64:$dst, fpimm0)]>; 489def LD_Fp164 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, 490 [(set RFP64:$dst, fpimm1)]>; 491def LD_Fp080 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, 492 [(set RFP80:$dst, fpimm0)]>; 493def LD_Fp180 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, 494 [(set RFP80:$dst, fpimm1)]>; 495} 496 497def LD_F0 : FPI<0xEE, RawFrm, (outs), (ins), "fldz">, D9; 498def LD_F1 : FPI<0xE8, RawFrm, (outs), (ins), "fld1">, D9; 499 500 501// Floating point compares. 502let Defs = [EFLAGS] in { 503def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, 504 []>; // FPSW = cmp ST(0) with ST(i) 505def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, 506 []>; // FPSW = cmp ST(0) with ST(i) 507def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, 508 []>; // FPSW = cmp ST(0) with ST(i) 509 510// CC = ST(0) cmp ST(i) 511def UCOM_FpIr32: FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, 512 [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>; 513def UCOM_FpIr64: FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, 514 [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>; 515def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, 516 [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>; 517} 518 519let Defs = [EFLAGS], Uses = [ST0] in { 520def UCOM_Fr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i) 521 (outs), (ins RST:$reg), 522 "fucom\t$reg">, DD; 523def UCOM_FPr : FPI<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop 524 (outs), (ins RST:$reg), 525 "fucomp\t$reg">, DD; 526def UCOM_FPPr : FPI<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop 527 (outs), (ins), 528 "fucompp">, DA; 529 530def UCOM_FIr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i) 531 (outs), (ins RST:$reg), 532 "fucomi\t$reg">, DB; 533def UCOM_FIPr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop 534 (outs), (ins RST:$reg), 535 "fucompi\t$reg">, DF; 536} 537 538def COM_FIr : FPI<0xF0, AddRegFrm, (outs), (ins RST:$reg), 539 "fcomi\t$reg">, DB; 540def COM_FIPr : FPI<0xF0, AddRegFrm, (outs), (ins RST:$reg), 541 "fcompi\t$reg">, DF; 542 543// Floating point flag ops. 544let Defs = [AX] in 545def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags 546 (outs), (ins), "fnstsw %ax", []>, DF; 547 548def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world 549 (outs), (ins i16mem:$dst), "fnstcw\t$dst", 550 [(X86fp_cwd_get16 addr:$dst)]>; 551 552let mayLoad = 1 in 553def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] 554 (outs), (ins i16mem:$dst), "fldcw\t$dst", []>; 555 556// FPU control instructions 557def FNINIT : I<0xE3, RawFrm, (outs), (ins), "fninit", []>, DB; 558def FFREE : FPI<0xC0, AddRegFrm, (outs), (ins RST:$reg), 559 "ffree\t$reg">, DD; 560 561// Clear exceptions 562 563def FNCLEX : I<0xE2, RawFrm, (outs), (ins), "fnclex", []>, DB; 564 565// Operandless floating-point instructions for the disassembler. 566def WAIT : I<0x9B, RawFrm, (outs), (ins), "wait", []>; 567 568def FNOP : I<0xD0, RawFrm, (outs), (ins), "fnop", []>, D9; 569def FXAM : I<0xE5, RawFrm, (outs), (ins), "fxam", []>, D9; 570def FLDL2T : I<0xE9, RawFrm, (outs), (ins), "fldl2t", []>, D9; 571def FLDL2E : I<0xEA, RawFrm, (outs), (ins), "fldl2e", []>, D9; 572def FLDPI : I<0xEB, RawFrm, (outs), (ins), "fldpi", []>, D9; 573def FLDLG2 : I<0xEC, RawFrm, (outs), (ins), "fldlg2", []>, D9; 574def FLDLN2 : I<0xED, RawFrm, (outs), (ins), "fldln2", []>, D9; 575def F2XM1 : I<0xF0, RawFrm, (outs), (ins), "f2xm1", []>, D9; 576def FYL2X : I<0xF1, RawFrm, (outs), (ins), "fyl2x", []>, D9; 577def FPTAN : I<0xF2, RawFrm, (outs), (ins), "fptan", []>, D9; 578def FPATAN : I<0xF3, RawFrm, (outs), (ins), "fpatan", []>, D9; 579def FXTRACT : I<0xF4, RawFrm, (outs), (ins), "fxtract", []>, D9; 580def FPREM1 : I<0xF5, RawFrm, (outs), (ins), "fprem1", []>, D9; 581def FDECSTP : I<0xF6, RawFrm, (outs), (ins), "fdecstp", []>, D9; 582def FINCSTP : I<0xF7, RawFrm, (outs), (ins), "fincstp", []>, D9; 583def FPREM : I<0xF8, RawFrm, (outs), (ins), "fprem", []>, D9; 584def FYL2XP1 : I<0xF9, RawFrm, (outs), (ins), "fyl2xp1", []>, D9; 585def FSINCOS : I<0xFB, RawFrm, (outs), (ins), "fsincos", []>, D9; 586def FRNDINT : I<0xFC, RawFrm, (outs), (ins), "frndint", []>, D9; 587def FSCALE : I<0xFD, RawFrm, (outs), (ins), "fscale", []>, D9; 588def FCOMPP : I<0xD9, RawFrm, (outs), (ins), "fcompp", []>, DE; 589 590def FXSAVE : I<0xAE, MRM0m, (outs opaque512mem:$dst), (ins), 591 "fxsave\t$dst", []>, TB; 592def FXSAVE64 : I<0xAE, MRM0m, (outs opaque512mem:$dst), (ins), 593 "fxsaveq\t$dst", []>, TB, REX_W, Requires<[In64BitMode]>; 594def FXRSTOR : I<0xAE, MRM1m, (outs), (ins opaque512mem:$src), 595 "fxrstor\t$src", []>, TB; 596def FXRSTOR64 : I<0xAE, MRM1m, (outs), (ins opaque512mem:$src), 597 "fxrstorq\t$src", []>, TB, REX_W, Requires<[In64BitMode]>; 598 599//===----------------------------------------------------------------------===// 600// Non-Instruction Patterns 601//===----------------------------------------------------------------------===// 602 603// Required for RET of f32 / f64 / f80 values. 604def : Pat<(X86fld addr:$src, f32), (LD_Fp32m addr:$src)>; 605def : Pat<(X86fld addr:$src, f64), (LD_Fp64m addr:$src)>; 606def : Pat<(X86fld addr:$src, f80), (LD_Fp80m addr:$src)>; 607 608// Required for CALL which return f32 / f64 / f80 values. 609def : Pat<(X86fst RFP32:$src, addr:$op, f32), (ST_Fp32m addr:$op, RFP32:$src)>; 610def : Pat<(X86fst RFP64:$src, addr:$op, f32), (ST_Fp64m32 addr:$op, 611 RFP64:$src)>; 612def : Pat<(X86fst RFP64:$src, addr:$op, f64), (ST_Fp64m addr:$op, RFP64:$src)>; 613def : Pat<(X86fst RFP80:$src, addr:$op, f32), (ST_Fp80m32 addr:$op, 614 RFP80:$src)>; 615def : Pat<(X86fst RFP80:$src, addr:$op, f64), (ST_Fp80m64 addr:$op, 616 RFP80:$src)>; 617def : Pat<(X86fst RFP80:$src, addr:$op, f80), (ST_FpP80m addr:$op, 618 RFP80:$src)>; 619 620// Floating point constant -0.0 and -1.0 621def : Pat<(f32 fpimmneg0), (CHS_Fp32 (LD_Fp032))>, Requires<[FPStackf32]>; 622def : Pat<(f32 fpimmneg1), (CHS_Fp32 (LD_Fp132))>, Requires<[FPStackf32]>; 623def : Pat<(f64 fpimmneg0), (CHS_Fp64 (LD_Fp064))>, Requires<[FPStackf64]>; 624def : Pat<(f64 fpimmneg1), (CHS_Fp64 (LD_Fp164))>, Requires<[FPStackf64]>; 625def : Pat<(f80 fpimmneg0), (CHS_Fp80 (LD_Fp080))>; 626def : Pat<(f80 fpimmneg1), (CHS_Fp80 (LD_Fp180))>; 627 628// Used to conv. i64 to f64 since there isn't a SSE version. 629def : Pat<(X86fildflag addr:$src, i64), (ILD_Fp64m64 addr:$src)>; 630 631// FP extensions map onto simple pseudo-value conversions if they are to/from 632// the FP stack. 633def : Pat<(f64 (fextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>, 634 Requires<[FPStackf32]>; 635def : Pat<(f80 (fextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>, 636 Requires<[FPStackf32]>; 637def : Pat<(f80 (fextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>, 638 Requires<[FPStackf64]>; 639 640// FP truncations map onto simple pseudo-value conversions if they are to/from 641// the FP stack. We have validated that only value-preserving truncations make 642// it through isel. 643def : Pat<(f32 (fround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>, 644 Requires<[FPStackf32]>; 645def : Pat<(f32 (fround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>, 646 Requires<[FPStackf32]>; 647def : Pat<(f64 (fround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>, 648 Requires<[FPStackf64]>; 649