1 //==- X86InstrFPStack.td - Describe the X86 Instruction Set -------*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by the Evan Cheng and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 // All FP Stack operations are represented with two instructions here. The
17 // first instruction, generated by the instruction selector, uses "RFP"
18 // registers: a traditional register file to reference floating point values.
19 // These instructions are all psuedo instructions and use the "Fp" prefix.
20 // The second instruction is defined with FPI, which is the actual instruction
21 // emitted by the assembler. The FP stackifier pass converts one to the other
22 // after register allocation occurs.
24 // Note that the FpI instruction should have instruction selection info (e.g.
25 // a pattern) and the FPI instruction should have emission info (e.g. opcode
26 // encoding and asm printing info).
28 // FPI - Floating Point Instruction template.
29 class FPI<bits<8> o, Format F, dag ops, string asm> : I<o, F, ops, asm, []> {}
31 // FpI_ - Floating Point Psuedo Instruction template. Not Predicated.
32 class FpI_<dag ops, FPFormat fp, list<dag> pattern>
33 : X86Inst<0, Pseudo, NoImm, ops, ""> {
34 let FPForm = fp; let FPFormBits = FPForm.Value;
35 let Pattern = pattern;
38 // Random Pseudo Instructions.
39 def FpGETRESULT : FpI_<(ops RFP:$dst), SpecialFP,
40 [(set RFP:$dst, X86fpget)]>; // FPR = ST(0)
43 def FpSETRESULT : FpI_<(ops RFP:$src), SpecialFP,
44 [(X86fpset RFP:$src)]>, Imp<[], [ST0]>; // ST(0) = FPR
46 // FpI - Floating Point Psuedo Instruction template. Predicated on FPStack.
47 class FpI<dag ops, FPFormat fp, list<dag> pattern> :
48 FpI_<ops, fp, pattern>, Requires<[FPStack]>;
51 def FpMOV : FpI<(ops RFP:$dst, RFP:$src), SpecialFP, []>; // f1 = fmov f2
54 // Add, Sub, Mul, Div.
55 def FpADD : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
56 [(set RFP:$dst, (fadd RFP:$src1, RFP:$src2))]>;
57 def FpSUB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
58 [(set RFP:$dst, (fsub RFP:$src1, RFP:$src2))]>;
59 def FpMUL : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
60 [(set RFP:$dst, (fmul RFP:$src1, RFP:$src2))]>;
61 def FpDIV : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
62 [(set RFP:$dst, (fdiv RFP:$src1, RFP:$src2))]>;
64 class FPST0rInst<bits<8> o, string asm>
65 : FPI<o, AddRegFrm, (ops RST:$op), asm>, D8;
66 class FPrST0Inst<bits<8> o, string asm>
67 : FPI<o, AddRegFrm, (ops RST:$op), asm>, DC;
68 class FPrST0PInst<bits<8> o, string asm>
69 : FPI<o, AddRegFrm, (ops RST:$op), asm>, DE;
71 // Binary Ops with a memory source.
72 def FpADD32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
73 [(set RFP:$dst, (fadd RFP:$src1,
74 (extloadf64f32 addr:$src2)))]>;
75 // ST(0) = ST(0) + [mem32]
76 def FpADD64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
77 [(set RFP:$dst, (fadd RFP:$src1, (loadf64 addr:$src2)))]>;
78 // ST(0) = ST(0) + [mem64]
79 def FpMUL32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
80 [(set RFP:$dst, (fmul RFP:$src1,
81 (extloadf64f32 addr:$src2)))]>;
82 // ST(0) = ST(0) * [mem32]
83 def FpMUL64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
84 [(set RFP:$dst, (fmul RFP:$src1, (loadf64 addr:$src2)))]>;
85 // ST(0) = ST(0) * [mem64]
86 def FpSUB32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
87 [(set RFP:$dst, (fsub RFP:$src1,
88 (extloadf64f32 addr:$src2)))]>;
89 // ST(0) = ST(0) - [mem32]
90 def FpSUB64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
91 [(set RFP:$dst, (fsub RFP:$src1, (loadf64 addr:$src2)))]>;
92 // ST(0) = ST(0) - [mem64]
93 def FpSUBR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
94 [(set RFP:$dst, (fsub (extloadf64f32 addr:$src2),
96 // ST(0) = [mem32] - ST(0)
97 def FpSUBR64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
98 [(set RFP:$dst, (fsub (loadf64 addr:$src2), RFP:$src1))]>;
99 // ST(0) = [mem64] - ST(0)
100 def FpDIV32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
101 [(set RFP:$dst, (fdiv RFP:$src1,
102 (extloadf64f32 addr:$src2)))]>;
103 // ST(0) = ST(0) / [mem32]
104 def FpDIV64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
105 [(set RFP:$dst, (fdiv RFP:$src1, (loadf64 addr:$src2)))]>;
106 // ST(0) = ST(0) / [mem64]
107 def FpDIVR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
108 [(set RFP:$dst, (fdiv (extloadf64f32 addr:$src2),
110 // ST(0) = [mem32] / ST(0)
111 def FpDIVR64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
112 [(set RFP:$dst, (fdiv (loadf64 addr:$src2), RFP:$src1))]>;
113 // ST(0) = [mem64] / ST(0)
116 def FADD32m : FPI<0xD8, MRM0m, (ops f32mem:$src), "fadd{s} $src">;
117 def FADD64m : FPI<0xDC, MRM0m, (ops f64mem:$src), "fadd{l} $src">;
118 def FMUL32m : FPI<0xD8, MRM1m, (ops f32mem:$src), "fmul{s} $src">;
119 def FMUL64m : FPI<0xDC, MRM1m, (ops f64mem:$src), "fmul{l} $src">;
120 def FSUB32m : FPI<0xD8, MRM4m, (ops f32mem:$src), "fsub{s} $src">;
121 def FSUB64m : FPI<0xDC, MRM4m, (ops f64mem:$src), "fsub{l} $src">;
122 def FSUBR32m : FPI<0xD8, MRM5m, (ops f32mem:$src), "fsubr{s} $src">;
123 def FSUBR64m : FPI<0xDC, MRM5m, (ops f64mem:$src), "fsubr{l} $src">;
124 def FDIV32m : FPI<0xD8, MRM6m, (ops f32mem:$src), "fdiv{s} $src">;
125 def FDIV64m : FPI<0xDC, MRM6m, (ops f64mem:$src), "fdiv{l} $src">;
126 def FDIVR32m : FPI<0xD8, MRM7m, (ops f32mem:$src), "fdivr{s} $src">;
127 def FDIVR64m : FPI<0xDC, MRM7m, (ops f64mem:$src), "fdivr{l} $src">;
129 def FpIADD16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
130 [(set RFP:$dst, (fadd RFP:$src1,
131 (X86fild addr:$src2, i16)))]>;
132 // ST(0) = ST(0) + [mem16int]
133 def FpIADD32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
134 [(set RFP:$dst, (fadd RFP:$src1,
135 (X86fild addr:$src2, i32)))]>;
136 // ST(0) = ST(0) + [mem32int]
137 def FpIMUL16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
138 [(set RFP:$dst, (fmul RFP:$src1,
139 (X86fild addr:$src2, i16)))]>;
140 // ST(0) = ST(0) * [mem16int]
141 def FpIMUL32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
142 [(set RFP:$dst, (fmul RFP:$src1,
143 (X86fild addr:$src2, i32)))]>;
144 // ST(0) = ST(0) * [mem32int]
145 def FpISUB16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
146 [(set RFP:$dst, (fsub RFP:$src1,
147 (X86fild addr:$src2, i16)))]>;
148 // ST(0) = ST(0) - [mem16int]
149 def FpISUB32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
150 [(set RFP:$dst, (fsub RFP:$src1,
151 (X86fild addr:$src2, i32)))]>;
152 // ST(0) = ST(0) - [mem32int]
153 def FpISUBR16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
154 [(set RFP:$dst, (fsub (X86fild addr:$src2, i16),
156 // ST(0) = [mem16int] - ST(0)
157 def FpISUBR32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
158 [(set RFP:$dst, (fsub (X86fild addr:$src2, i32),
160 // ST(0) = [mem32int] - ST(0)
161 def FpIDIV16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
162 [(set RFP:$dst, (fdiv RFP:$src1,
163 (X86fild addr:$src2, i16)))]>;
164 // ST(0) = ST(0) / [mem16int]
165 def FpIDIV32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
166 [(set RFP:$dst, (fdiv RFP:$src1,
167 (X86fild addr:$src2, i32)))]>;
168 // ST(0) = ST(0) / [mem32int]
169 def FpIDIVR16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
170 [(set RFP:$dst, (fdiv (X86fild addr:$src2, i16),
172 // ST(0) = [mem16int] / ST(0)
173 def FpIDIVR32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
174 [(set RFP:$dst, (fdiv (X86fild addr:$src2, i32),
176 // ST(0) = [mem32int] / ST(0)
178 def FIADD16m : FPI<0xDE, MRM0m, (ops i16mem:$src), "fiadd{s} $src">;
179 def FIADD32m : FPI<0xDA, MRM0m, (ops i32mem:$src), "fiadd{l} $src">;
180 def FIMUL16m : FPI<0xDE, MRM1m, (ops i16mem:$src), "fimul{s} $src">;
181 def FIMUL32m : FPI<0xDA, MRM1m, (ops i32mem:$src), "fimul{l} $src">;
182 def FISUB16m : FPI<0xDE, MRM4m, (ops i16mem:$src), "fisub{s} $src">;
183 def FISUB32m : FPI<0xDA, MRM4m, (ops i32mem:$src), "fisub{l} $src">;
184 def FISUBR16m : FPI<0xDE, MRM5m, (ops i16mem:$src), "fisubr{s} $src">;
185 def FISUBR32m : FPI<0xDA, MRM5m, (ops i32mem:$src), "fisubr{l} $src">;
186 def FIDIV16m : FPI<0xDE, MRM6m, (ops i16mem:$src), "fidiv{s} $src">;
187 def FIDIV32m : FPI<0xDA, MRM6m, (ops i32mem:$src), "fidiv{l} $src">;
188 def FIDIVR16m : FPI<0xDE, MRM7m, (ops i16mem:$src), "fidivr{s} $src">;
189 def FIDIVR32m : FPI<0xDA, MRM7m, (ops i32mem:$src), "fidivr{l} $src">;
191 // NOTE: GAS and apparently all other AT&T style assemblers have a broken notion
192 // of some of the 'reverse' forms of the fsub and fdiv instructions. As such,
193 // we have to put some 'r's in and take them out of weird places.
194 def FADDST0r : FPST0rInst <0xC0, "fadd $op">;
195 def FADDrST0 : FPrST0Inst <0xC0, "fadd {%st(0), $op|$op, %ST(0)}">;
196 def FADDPrST0 : FPrST0PInst<0xC0, "faddp $op">;
197 def FSUBRST0r : FPST0rInst <0xE8, "fsubr $op">;
198 def FSUBrST0 : FPrST0Inst <0xE8, "fsub{r} {%st(0), $op|$op, %ST(0)}">;
199 def FSUBPrST0 : FPrST0PInst<0xE8, "fsub{r}p $op">;
200 def FSUBST0r : FPST0rInst <0xE0, "fsub $op">;
201 def FSUBRrST0 : FPrST0Inst <0xE0, "fsub{|r} {%st(0), $op|$op, %ST(0)}">;
202 def FSUBRPrST0 : FPrST0PInst<0xE0, "fsub{|r}p $op">;
203 def FMULST0r : FPST0rInst <0xC8, "fmul $op">;
204 def FMULrST0 : FPrST0Inst <0xC8, "fmul {%st(0), $op|$op, %ST(0)}">;
205 def FMULPrST0 : FPrST0PInst<0xC8, "fmulp $op">;
206 def FDIVRST0r : FPST0rInst <0xF8, "fdivr $op">;
207 def FDIVrST0 : FPrST0Inst <0xF8, "fdiv{r} {%st(0), $op|$op, %ST(0)}">;
208 def FDIVPrST0 : FPrST0PInst<0xF8, "fdiv{r}p $op">;
209 def FDIVST0r : FPST0rInst <0xF0, "fdiv $op">;
210 def FDIVRrST0 : FPrST0Inst <0xF0, "fdiv{|r} {%st(0), $op|$op, %ST(0)}">;
211 def FDIVRPrST0 : FPrST0PInst<0xF0, "fdiv{|r}p $op">;
215 def FpCHS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
216 [(set RFP:$dst, (fneg RFP:$src))]>;
217 def FpABS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
218 [(set RFP:$dst, (fabs RFP:$src))]>;
219 def FpSQRT : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
220 [(set RFP:$dst, (fsqrt RFP:$src))]>;
221 def FpSIN : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
222 [(set RFP:$dst, (fsin RFP:$src))]>;
223 def FpCOS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
224 [(set RFP:$dst, (fcos RFP:$src))]>;
225 def FpTST : FpI<(ops RFP:$src), OneArgFP,
228 def FCHS : FPI<0xE0, RawFrm, (ops), "fchs">, D9;
229 def FABS : FPI<0xE1, RawFrm, (ops), "fabs">, D9;
230 def FSQRT : FPI<0xFA, RawFrm, (ops), "fsqrt">, D9;
231 def FSIN : FPI<0xFE, RawFrm, (ops), "fsin">, D9;
232 def FCOS : FPI<0xFF, RawFrm, (ops), "fcos">, D9;
233 def FTST : FPI<0xE4, RawFrm, (ops), "ftst">, D9;
236 // Floating point cmovs.
237 let isTwoAddress = 1 in {
238 def FpCMOVB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
239 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
241 def FpCMOVBE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
242 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
244 def FpCMOVE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
245 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
247 def FpCMOVP : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
248 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
250 def FpCMOVNB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
251 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
253 def FpCMOVNBE: FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
254 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
256 def FpCMOVNE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
257 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
259 def FpCMOVNP : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
260 [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
264 def FCMOVB : FPI<0xC0, AddRegFrm, (ops RST:$op),
265 "fcmovb {$op, %st(0)|%ST(0), $op}">, DA;
266 def FCMOVBE : FPI<0xD0, AddRegFrm, (ops RST:$op),
267 "fcmovbe {$op, %st(0)|%ST(0), $op}">, DA;
268 def FCMOVE : FPI<0xC8, AddRegFrm, (ops RST:$op),
269 "fcmove {$op, %st(0)|%ST(0), $op}">, DA;
270 def FCMOVP : FPI<0xD8, AddRegFrm, (ops RST:$op),
271 "fcmovu {$op, %st(0)|%ST(0), $op}">, DA;
272 def FCMOVNB : FPI<0xC0, AddRegFrm, (ops RST:$op),
273 "fcmovnb {$op, %st(0)|%ST(0), $op}">, DB;
274 def FCMOVNBE : FPI<0xD0, AddRegFrm, (ops RST:$op),
275 "fcmovnbe {$op, %st(0)|%ST(0), $op}">, DB;
276 def FCMOVNE : FPI<0xC8, AddRegFrm, (ops RST:$op),
277 "fcmovne {$op, %st(0)|%ST(0), $op}">, DB;
278 def FCMOVNP : FPI<0xD8, AddRegFrm, (ops RST:$op),
279 "fcmovnu {$op, %st(0)|%ST(0), $op}">, DB;
281 // Floating point loads & stores.
282 def FpLD32m : FpI<(ops RFP:$dst, f32mem:$src), ZeroArgFP,
283 [(set RFP:$dst, (extloadf64f32 addr:$src))]>;
284 def FpLD64m : FpI<(ops RFP:$dst, f64mem:$src), ZeroArgFP,
285 [(set RFP:$dst, (loadf64 addr:$src))]>;
286 def FpILD16m : FpI<(ops RFP:$dst, i16mem:$src), ZeroArgFP,
287 [(set RFP:$dst, (X86fild addr:$src, i16))]>;
288 def FpILD32m : FpI<(ops RFP:$dst, i32mem:$src), ZeroArgFP,
289 [(set RFP:$dst, (X86fild addr:$src, i32))]>;
290 def FpILD64m : FpI<(ops RFP:$dst, i64mem:$src), ZeroArgFP,
291 [(set RFP:$dst, (X86fild addr:$src, i64))]>;
293 def FpST32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP,
294 [(truncstore RFP:$src, addr:$op, f32)]>;
295 def FpST64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP,
296 [(store RFP:$src, addr:$op)]>;
298 def FpSTP32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, []>;
299 def FpSTP64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, []>;
300 def FpIST16m : FpI<(ops i16mem:$op, RFP:$src), OneArgFP, []>;
301 def FpIST32m : FpI<(ops i32mem:$op, RFP:$src), OneArgFP, []>;
302 def FpIST64m : FpI<(ops i64mem:$op, RFP:$src), OneArgFP, []>;
304 def FLD32m : FPI<0xD9, MRM0m, (ops f32mem:$src), "fld{s} $src">;
305 def FLD64m : FPI<0xDD, MRM0m, (ops f64mem:$src), "fld{l} $src">;
306 def FILD16m : FPI<0xDF, MRM0m, (ops i16mem:$src), "fild{s} $src">;
307 def FILD32m : FPI<0xDB, MRM0m, (ops i32mem:$src), "fild{l} $src">;
308 def FILD64m : FPI<0xDF, MRM5m, (ops i64mem:$src), "fild{ll} $src">;
309 def FST32m : FPI<0xD9, MRM2m, (ops f32mem:$dst), "fst{s} $dst">;
310 def FST64m : FPI<0xDD, MRM2m, (ops f64mem:$dst), "fst{l} $dst">;
311 def FSTP32m : FPI<0xD9, MRM3m, (ops f32mem:$dst), "fstp{s} $dst">;
312 def FSTP64m : FPI<0xDD, MRM3m, (ops f64mem:$dst), "fstp{l} $dst">;
313 def FIST16m : FPI<0xDF, MRM2m, (ops i16mem:$dst), "fist{s} $dst">;
314 def FIST32m : FPI<0xDB, MRM2m, (ops i32mem:$dst), "fist{l} $dst">;
315 def FISTP16m : FPI<0xDF, MRM3m, (ops i16mem:$dst), "fistp{s} $dst">;
316 def FISTP32m : FPI<0xDB, MRM3m, (ops i32mem:$dst), "fistp{l} $dst">;
317 def FISTP64m : FPI<0xDF, MRM7m, (ops i64mem:$dst), "fistp{ll} $dst">;
319 // FISTTP requires SSE3 even though it's a FPStack op.
320 def FpISTT16m : FpI_<(ops i16mem:$op, RFP:$src), OneArgFP,
321 [(X86fp_to_i16mem RFP:$src, addr:$op)]>,
323 def FpISTT32m : FpI_<(ops i32mem:$op, RFP:$src), OneArgFP,
324 [(X86fp_to_i32mem RFP:$src, addr:$op)]>,
326 def FpISTT64m : FpI_<(ops i64mem:$op, RFP:$src), OneArgFP,
327 [(X86fp_to_i64mem RFP:$src, addr:$op)]>,
330 def FISTTP16m : FPI<0xDF, MRM1m, (ops i16mem:$dst), "fisttp{s} $dst">;
331 def FISTTP32m : FPI<0xDB, MRM1m, (ops i32mem:$dst), "fisttp{l} $dst">;
332 def FISTTP64m : FPI<0xDD, MRM1m, (ops i64mem:$dst), "fisttp{ll} $dst">;
334 // FP Stack manipulation instructions.
335 def FLDrr : FPI<0xC0, AddRegFrm, (ops RST:$op), "fld $op">, D9;
336 def FSTrr : FPI<0xD0, AddRegFrm, (ops RST:$op), "fst $op">, DD;
337 def FSTPrr : FPI<0xD8, AddRegFrm, (ops RST:$op), "fstp $op">, DD;
338 def FXCH : FPI<0xC8, AddRegFrm, (ops RST:$op), "fxch $op">, D9;
340 // Floating point constant loads.
341 def FpLD0 : FpI<(ops RFP:$dst), ZeroArgFP,
342 [(set RFP:$dst, fp64imm0)]>;
343 def FpLD1 : FpI<(ops RFP:$dst), ZeroArgFP,
344 [(set RFP:$dst, fp64imm1)]>;
346 def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9;
347 def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9;
350 // Floating point compares.
351 def FpUCOMr : FpI<(ops RFP:$lhs, RFP:$rhs), CompareFP,
352 []>; // FPSW = cmp ST(0) with ST(i)
353 def FpUCOMIr : FpI<(ops RFP:$lhs, RFP:$rhs), CompareFP,
354 [(X86cmp RFP:$lhs, RFP:$rhs)]>; // CC = cmp ST(0) with ST(i)
356 def FUCOMr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i)
358 "fucom $reg">, DD, Imp<[ST0],[]>;
359 def FUCOMPr : FPI<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop
361 "fucomp $reg">, DD, Imp<[ST0],[]>;
362 def FUCOMPPr : FPI<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop
364 "fucompp">, DA, Imp<[ST0],[]>;
366 def FUCOMIr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i)
368 "fucomi {$reg, %st(0)|%ST(0), $reg}">, DB, Imp<[ST0],[]>;
369 def FUCOMIPr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop
371 "fucomip {$reg, %st(0)|%ST(0), $reg}">, DF, Imp<[ST0],[]>;
374 // Floating point flag ops.
375 def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags
376 (ops), "fnstsw", []>, DF, Imp<[],[AX]>;
378 def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world
379 (ops i16mem:$dst), "fnstcw $dst", []>;
380 def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16]
381 (ops i16mem:$dst), "fldcw $dst", []>;
384 //===----------------------------------------------------------------------===//
385 // Alias Instructions
386 //===----------------------------------------------------------------------===//
388 // Alias instructions that map fld0 to pxor for sse.
389 // FIXME: remove when we can teach regalloc that xor reg, reg is ok.
390 def FsFLD0SS : I<0xEF, MRMInitReg, (ops FR32:$dst),
391 "pxor $dst, $dst", [(set FR32:$dst, fp32imm0)]>,
392 Requires<[HasSSE1]>, TB, OpSize;
393 def FsFLD0SD : I<0xEF, MRMInitReg, (ops FR64:$dst),
394 "pxor $dst, $dst", [(set FR64:$dst, fp64imm0)]>,
395 Requires<[HasSSE2]>, TB, OpSize;
397 // Alias instructions to do FR32 / FR64 reg-to-reg copy using movaps / movapd.
398 // Upper bits are disregarded.
399 def FsMOVAPSrr : I<0x28, MRMSrcReg, (ops V4F32:$dst, V4F32:$src),
400 "movaps {$src, $dst|$dst, $src}", []>,
401 Requires<[HasSSE1]>, TB;
402 def FsMOVAPDrr : I<0x28, MRMSrcReg, (ops V2F64:$dst, V2F64:$src),
403 "movapd {$src, $dst|$dst, $src}", []>,
404 Requires<[HasSSE2]>, TB, OpSize;
406 // Alias instructions to load FR32 / FR64 from f128mem using movaps / movapd.
407 // Upper bits are disregarded.
408 def FsMOVAPSrm : I<0x28, MRMSrcMem, (ops FR32:$dst, f128mem:$src),
409 "movaps {$src, $dst|$dst, $src}",
410 [(set FR32:$dst, (X86loadpf32 addr:$src))]>,
411 Requires<[HasSSE1]>, TB;
412 def FsMOVAPDrm : I<0x28, MRMSrcMem, (ops FR64:$dst, f128mem:$src),
413 "movapd {$src, $dst|$dst, $src}",
414 [(set FR64:$dst, (X86loadpf64 addr:$src))]>,
415 Requires<[HasSSE2]>, TB, OpSize;
417 // Alias bitwise logical operations using SSE logical ops on packed FP values.
418 let isTwoAddress = 1 in {
419 let isCommutable = 1 in {
420 def FsANDPSrr : I<0x54, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
421 "andps {$src2, $dst|$dst, $src2}",
422 [(set FR32:$dst, (X86fand FR32:$src1, FR32:$src2))]>,
423 Requires<[HasSSE1]>, TB;
424 def FsANDPDrr : I<0x54, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
425 "andpd {$src2, $dst|$dst, $src2}",
426 [(set FR64:$dst, (X86fand FR64:$src1, FR64:$src2))]>,
427 Requires<[HasSSE2]>, TB, OpSize;
428 def FsORPSrr : I<0x56, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
429 "orps {$src2, $dst|$dst, $src2}", []>,
430 Requires<[HasSSE1]>, TB;
431 def FsORPDrr : I<0x56, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
432 "orpd {$src2, $dst|$dst, $src2}", []>,
433 Requires<[HasSSE2]>, TB, OpSize;
434 def FsXORPSrr : I<0x57, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
435 "xorps {$src2, $dst|$dst, $src2}",
436 [(set FR32:$dst, (X86fxor FR32:$src1, FR32:$src2))]>,
437 Requires<[HasSSE1]>, TB;
438 def FsXORPDrr : I<0x57, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
439 "xorpd {$src2, $dst|$dst, $src2}",
440 [(set FR64:$dst, (X86fxor FR64:$src1, FR64:$src2))]>,
441 Requires<[HasSSE2]>, TB, OpSize;
443 def FsANDPSrm : I<0x54, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
444 "andps {$src2, $dst|$dst, $src2}",
445 [(set FR32:$dst, (X86fand FR32:$src1,
446 (X86loadpf32 addr:$src2)))]>,
447 Requires<[HasSSE1]>, TB;
448 def FsANDPDrm : I<0x54, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
449 "andpd {$src2, $dst|$dst, $src2}",
450 [(set FR64:$dst, (X86fand FR64:$src1,
451 (X86loadpf64 addr:$src2)))]>,
452 Requires<[HasSSE2]>, TB, OpSize;
453 def FsORPSrm : I<0x56, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
454 "orps {$src2, $dst|$dst, $src2}", []>,
455 Requires<[HasSSE1]>, TB;
456 def FsORPDrm : I<0x56, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
457 "orpd {$src2, $dst|$dst, $src2}", []>,
458 Requires<[HasSSE2]>, TB, OpSize;
459 def FsXORPSrm : I<0x57, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
460 "xorps {$src2, $dst|$dst, $src2}",
461 [(set FR32:$dst, (X86fxor FR32:$src1,
462 (X86loadpf32 addr:$src2)))]>,
463 Requires<[HasSSE1]>, TB;
464 def FsXORPDrm : I<0x57, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
465 "xorpd {$src2, $dst|$dst, $src2}",
466 [(set FR64:$dst, (X86fxor FR64:$src1,
467 (X86loadpf64 addr:$src2)))]>,
468 Requires<[HasSSE2]>, TB, OpSize;
470 def FsANDNPSrr : I<0x55, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
471 "andnps {$src2, $dst|$dst, $src2}", []>,
472 Requires<[HasSSE1]>, TB;
473 def FsANDNPSrm : I<0x55, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
474 "andnps {$src2, $dst|$dst, $src2}", []>,
475 Requires<[HasSSE1]>, TB;
476 def FsANDNPDrr : I<0x55, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
477 "andnpd {$src2, $dst|$dst, $src2}", []>,
478 Requires<[HasSSE2]>, TB, OpSize;
479 def FsANDNPDrm : I<0x55, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
480 "andnpd {$src2, $dst|$dst, $src2}", []>,
481 Requires<[HasSSE2]>, TB, OpSize;