1//===- X86InstrFPStack.td - FPU 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. 440let Predicates = [HasSSE3] in { 441def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, 442 [(X86fp_to_i16mem RFP32:$src, addr:$op)]>; 443def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, 444 [(X86fp_to_i32mem RFP32:$src, addr:$op)]>; 445def ISTT_Fp64m32 : FpI_<(outs), (ins i64mem:$op, RFP32:$src), OneArgFP, 446 [(X86fp_to_i64mem RFP32:$src, addr:$op)]>; 447def ISTT_Fp16m64 : FpI_<(outs), (ins i16mem:$op, RFP64:$src), OneArgFP, 448 [(X86fp_to_i16mem RFP64:$src, addr:$op)]>; 449def ISTT_Fp32m64 : FpI_<(outs), (ins i32mem:$op, RFP64:$src), OneArgFP, 450 [(X86fp_to_i32mem RFP64:$src, addr:$op)]>; 451def ISTT_Fp64m64 : FpI_<(outs), (ins i64mem:$op, RFP64:$src), OneArgFP, 452 [(X86fp_to_i64mem RFP64:$src, addr:$op)]>; 453def ISTT_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, 454 [(X86fp_to_i16mem RFP80:$src, addr:$op)]>; 455def ISTT_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, 456 [(X86fp_to_i32mem RFP80:$src, addr:$op)]>; 457def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, 458 [(X86fp_to_i64mem RFP80:$src, addr:$op)]>; 459} // Predicates = [HasSSE3] 460 461let mayStore = 1 in { 462def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; 463def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; 464def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), 465 "fisttp{ll}\t$dst">; 466} 467 468// FP Stack manipulation instructions. 469def LD_Frr : FPI<0xC0, AddRegFrm, (outs), (ins RST:$op), "fld\t$op">, D9; 470def ST_Frr : FPI<0xD0, AddRegFrm, (outs), (ins RST:$op), "fst\t$op">, DD; 471def ST_FPrr : FPI<0xD8, AddRegFrm, (outs), (ins RST:$op), "fstp\t$op">, DD; 472def XCH_F : FPI<0xC8, AddRegFrm, (outs), (ins RST:$op), "fxch\t$op">, D9; 473 474// Floating point constant loads. 475let isReMaterializable = 1 in { 476def LD_Fp032 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, 477 [(set RFP32:$dst, fpimm0)]>; 478def LD_Fp132 : FpIf32<(outs RFP32:$dst), (ins), ZeroArgFP, 479 [(set RFP32:$dst, fpimm1)]>; 480def LD_Fp064 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, 481 [(set RFP64:$dst, fpimm0)]>; 482def LD_Fp164 : FpIf64<(outs RFP64:$dst), (ins), ZeroArgFP, 483 [(set RFP64:$dst, fpimm1)]>; 484def LD_Fp080 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, 485 [(set RFP80:$dst, fpimm0)]>; 486def LD_Fp180 : FpI_<(outs RFP80:$dst), (ins), ZeroArgFP, 487 [(set RFP80:$dst, fpimm1)]>; 488} 489 490def LD_F0 : FPI<0xEE, RawFrm, (outs), (ins), "fldz">, D9; 491def LD_F1 : FPI<0xE8, RawFrm, (outs), (ins), "fld1">, D9; 492 493 494// Floating point compares. 495let Defs = [EFLAGS] in { 496def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, 497 []>; // FPSW = cmp ST(0) with ST(i) 498def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, 499 []>; // FPSW = cmp ST(0) with ST(i) 500def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, 501 []>; // FPSW = cmp ST(0) with ST(i) 502 503// CC = ST(0) cmp ST(i) 504def UCOM_FpIr32: FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, 505 [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>; 506def UCOM_FpIr64: FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, 507 [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>; 508def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, 509 [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>; 510} 511 512let Defs = [EFLAGS], Uses = [ST0] in { 513def UCOM_Fr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i) 514 (outs), (ins RST:$reg), 515 "fucom\t$reg">, DD; 516def UCOM_FPr : FPI<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop 517 (outs), (ins RST:$reg), 518 "fucomp\t$reg">, DD; 519def UCOM_FPPr : FPI<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop 520 (outs), (ins), 521 "fucompp">, DA; 522 523def UCOM_FIr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i) 524 (outs), (ins RST:$reg), 525 "fucomi\t$reg">, DB; 526def UCOM_FIPr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop 527 (outs), (ins RST:$reg), 528 "fucompi\t$reg">, DF; 529} 530 531def COM_FIr : FPI<0xF0, AddRegFrm, (outs), (ins RST:$reg), 532 "fcomi\t$reg">, DB; 533def COM_FIPr : FPI<0xF0, AddRegFrm, (outs), (ins RST:$reg), 534 "fcompi\t$reg">, DF; 535 536// Floating point flag ops. 537let Defs = [AX] in 538def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags 539 (outs), (ins), "fnstsw %ax", []>, DF; 540 541def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world 542 (outs), (ins i16mem:$dst), "fnstcw\t$dst", 543 [(X86fp_cwd_get16 addr:$dst)]>; 544 545let mayLoad = 1 in 546def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] 547 (outs), (ins i16mem:$dst), "fldcw\t$dst", []>; 548 549// FPU control instructions 550def FNINIT : I<0xE3, RawFrm, (outs), (ins), "fninit", []>, DB; 551def FFREE : FPI<0xC0, AddRegFrm, (outs), (ins RST:$reg), 552 "ffree\t$reg">, DD; 553 554// Clear exceptions 555 556def FNCLEX : I<0xE2, RawFrm, (outs), (ins), "fnclex", []>, DB; 557 558// Operandless floating-point instructions for the disassembler. 559def WAIT : I<0x9B, RawFrm, (outs), (ins), "wait", []>; 560 561def FNOP : I<0xD0, RawFrm, (outs), (ins), "fnop", []>, D9; 562def FXAM : I<0xE5, RawFrm, (outs), (ins), "fxam", []>, D9; 563def FLDL2T : I<0xE9, RawFrm, (outs), (ins), "fldl2t", []>, D9; 564def FLDL2E : I<0xEA, RawFrm, (outs), (ins), "fldl2e", []>, D9; 565def FLDPI : I<0xEB, RawFrm, (outs), (ins), "fldpi", []>, D9; 566def FLDLG2 : I<0xEC, RawFrm, (outs), (ins), "fldlg2", []>, D9; 567def FLDLN2 : I<0xED, RawFrm, (outs), (ins), "fldln2", []>, D9; 568def F2XM1 : I<0xF0, RawFrm, (outs), (ins), "f2xm1", []>, D9; 569def FYL2X : I<0xF1, RawFrm, (outs), (ins), "fyl2x", []>, D9; 570def FPTAN : I<0xF2, RawFrm, (outs), (ins), "fptan", []>, D9; 571def FPATAN : I<0xF3, RawFrm, (outs), (ins), "fpatan", []>, D9; 572def FXTRACT : I<0xF4, RawFrm, (outs), (ins), "fxtract", []>, D9; 573def FPREM1 : I<0xF5, RawFrm, (outs), (ins), "fprem1", []>, D9; 574def FDECSTP : I<0xF6, RawFrm, (outs), (ins), "fdecstp", []>, D9; 575def FINCSTP : I<0xF7, RawFrm, (outs), (ins), "fincstp", []>, D9; 576def FPREM : I<0xF8, RawFrm, (outs), (ins), "fprem", []>, D9; 577def FYL2XP1 : I<0xF9, RawFrm, (outs), (ins), "fyl2xp1", []>, D9; 578def FSINCOS : I<0xFB, RawFrm, (outs), (ins), "fsincos", []>, D9; 579def FRNDINT : I<0xFC, RawFrm, (outs), (ins), "frndint", []>, D9; 580def FSCALE : I<0xFD, RawFrm, (outs), (ins), "fscale", []>, D9; 581def FCOMPP : I<0xD9, RawFrm, (outs), (ins), "fcompp", []>, DE; 582 583def FXSAVE : I<0xAE, MRM0m, (outs opaque512mem:$dst), (ins), 584 "fxsave\t$dst", []>, TB; 585def FXSAVE64 : I<0xAE, MRM0m, (outs opaque512mem:$dst), (ins), 586 "fxsaveq\t$dst", []>, TB, REX_W, Requires<[In64BitMode]>; 587def FXRSTOR : I<0xAE, MRM1m, (outs), (ins opaque512mem:$src), 588 "fxrstor\t$src", []>, TB; 589def FXRSTOR64 : I<0xAE, MRM1m, (outs), (ins opaque512mem:$src), 590 "fxrstorq\t$src", []>, TB, REX_W, Requires<[In64BitMode]>; 591 592//===----------------------------------------------------------------------===// 593// Non-Instruction Patterns 594//===----------------------------------------------------------------------===// 595 596// Required for RET of f32 / f64 / f80 values. 597def : Pat<(X86fld addr:$src, f32), (LD_Fp32m addr:$src)>; 598def : Pat<(X86fld addr:$src, f64), (LD_Fp64m addr:$src)>; 599def : Pat<(X86fld addr:$src, f80), (LD_Fp80m addr:$src)>; 600 601// Required for CALL which return f32 / f64 / f80 values. 602def : Pat<(X86fst RFP32:$src, addr:$op, f32), (ST_Fp32m addr:$op, RFP32:$src)>; 603def : Pat<(X86fst RFP64:$src, addr:$op, f32), (ST_Fp64m32 addr:$op, 604 RFP64:$src)>; 605def : Pat<(X86fst RFP64:$src, addr:$op, f64), (ST_Fp64m addr:$op, RFP64:$src)>; 606def : Pat<(X86fst RFP80:$src, addr:$op, f32), (ST_Fp80m32 addr:$op, 607 RFP80:$src)>; 608def : Pat<(X86fst RFP80:$src, addr:$op, f64), (ST_Fp80m64 addr:$op, 609 RFP80:$src)>; 610def : Pat<(X86fst RFP80:$src, addr:$op, f80), (ST_FpP80m addr:$op, 611 RFP80:$src)>; 612 613// Floating point constant -0.0 and -1.0 614def : Pat<(f32 fpimmneg0), (CHS_Fp32 (LD_Fp032))>, Requires<[FPStackf32]>; 615def : Pat<(f32 fpimmneg1), (CHS_Fp32 (LD_Fp132))>, Requires<[FPStackf32]>; 616def : Pat<(f64 fpimmneg0), (CHS_Fp64 (LD_Fp064))>, Requires<[FPStackf64]>; 617def : Pat<(f64 fpimmneg1), (CHS_Fp64 (LD_Fp164))>, Requires<[FPStackf64]>; 618def : Pat<(f80 fpimmneg0), (CHS_Fp80 (LD_Fp080))>; 619def : Pat<(f80 fpimmneg1), (CHS_Fp80 (LD_Fp180))>; 620 621// Used to conv. i64 to f64 since there isn't a SSE version. 622def : Pat<(X86fildflag addr:$src, i64), (ILD_Fp64m64 addr:$src)>; 623 624// FP extensions map onto simple pseudo-value conversions if they are to/from 625// the FP stack. 626def : Pat<(f64 (fextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>, 627 Requires<[FPStackf32]>; 628def : Pat<(f80 (fextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>, 629 Requires<[FPStackf32]>; 630def : Pat<(f80 (fextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>, 631 Requires<[FPStackf64]>; 632 633// FP truncations map onto simple pseudo-value conversions if they are to/from 634// the FP stack. We have validated that only value-preserving truncations make 635// it through isel. 636def : Pat<(f32 (fround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>, 637 Requires<[FPStackf32]>; 638def : Pat<(f32 (fround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>, 639 Requires<[FPStackf32]>; 640def : Pat<(f64 (fround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>, 641 Requires<[FPStackf64]>; 642