Newer
Older
//==- X86InstrFPStack.td - Describe the X86 Instruction Set -------*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the Evan Cheng and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the X86 x87 FPU instruction set, defining the
// instructions, and properties of the instructions which are needed for code
// generation, machine code emission, and analysis.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// FPStack specific DAG Nodes.
//===----------------------------------------------------------------------===//
def SDTX86FpGet : SDTypeProfile<1, 0, [SDTCisFP<0>]>;
def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>;
def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>,
SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>,
SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
def SDTX86Fild : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisPtrTy<1>,
SDTCisVT<2, OtherVT>]>;
def SDTX86FpToIMem: SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>;
def X86fpget : SDNode<"X86ISD::FP_GET_RESULT", SDTX86FpGet,
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", SDTX86FpSet,
[SDNPHasChain, SDNPOutFlag]>;
def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld,
[SDNPHasChain]>;
def X86fst : SDNode<"X86ISD::FST", SDTX86Fst,
[SDNPHasChain, SDNPInFlag]>;
def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild,
[SDNPHasChain]>;
def X86fildflag: SDNode<"X86ISD::FILD_FLAG",SDTX86Fild,
[SDNPHasChain, SDNPOutFlag]>;
def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem,
[SDNPHasChain]>;
def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem,
[SDNPHasChain]>;
def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem,
[SDNPHasChain]>;
//===----------------------------------------------------------------------===//
// FPStack pattern fragments
//===----------------------------------------------------------------------===//
def fpimm0 : PatLeaf<(fpimm), [{
return N->isExactlyValue(+0.0);
}]>;
def fpimmneg0 : PatLeaf<(fpimm), [{
return N->isExactlyValue(-0.0);
}]>;
def fpimm1 : PatLeaf<(fpimm), [{
return N->isExactlyValue(+1.0);
}]>;
def fpimmneg1 : PatLeaf<(fpimm), [{
return N->isExactlyValue(-1.0);
}]>;
def extloadf64f32 : PatFrag<(ops node:$ptr), (f64 (extloadf32 node:$ptr))>;
// Some 'special' instructions
let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
def FP32_TO_INT16_IN_MEM : I<0, Pseudo,
(ops i16mem:$dst, RFP32:$src),
"#FP32_TO_INT16_IN_MEM PSEUDO!",
[(X86fp_to_i16mem RFP32:$src, addr:$dst)]>;
def FP32_TO_INT32_IN_MEM : I<0, Pseudo,
(ops i32mem:$dst, RFP32:$src),
"#FP32_TO_INT32_IN_MEM PSEUDO!",
[(X86fp_to_i32mem RFP32:$src, addr:$dst)]>;
def FP32_TO_INT64_IN_MEM : I<0, Pseudo,
(ops i64mem:$dst, RFP32:$src),
"#FP32_TO_INT64_IN_MEM PSEUDO!",
[(X86fp_to_i64mem RFP32:$src, addr:$dst)]>;
def FP64_TO_INT16_IN_MEM : I<0, Pseudo,
(ops i16mem:$dst, RFP64:$src),
"#FP64_TO_INT16_IN_MEM PSEUDO!",
[(X86fp_to_i16mem RFP64:$src, addr:$dst)]>;
def FP64_TO_INT32_IN_MEM : I<0, Pseudo,
(ops i32mem:$dst, RFP64:$src),
"#FP64_TO_INT32_IN_MEM PSEUDO!",
[(X86fp_to_i32mem RFP64:$src, addr:$dst)]>;
def FP64_TO_INT64_IN_MEM : I<0, Pseudo,
(ops i64mem:$dst, RFP64:$src),
"#FP64_TO_INT64_IN_MEM PSEUDO!",
[(X86fp_to_i64mem RFP64:$src, addr:$dst)]>;
}
let isTerminator = 1 in
let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in
def FP_REG_KILL : I<0, Pseudo, (ops), "#FP_REG_KILL", []>;
// All FP Stack operations are represented with two instructions here. The
// first instruction, generated by the instruction selector, uses "RFP"
// registers: a traditional register file to reference floating point values.
// These instructions are all psuedo instructions and use the "Fp" prefix.
// The second instruction is defined with FPI, which is the actual instruction
// emitted by the assembler. The FP stackifier pass converts one to the other
// after register allocation occurs.
//
// Note that the FpI instruction should have instruction selection info (e.g.
// a pattern) and the FPI instruction should have emission info (e.g. opcode
// encoding and asm printing info).
// FPI - Floating Point Instruction template.
class FPI<bits<8> o, Format F, dag ops, string asm> : I<o, F, ops, asm, []> {}
// FpI_ - Floating Point Psuedo Instruction template. Not Predicated.
class FpI_<dag ops, FPFormat fp, list<dag> pattern>
: X86Inst<0, Pseudo, NoImm, ops, ""> {
let FPForm = fp; let FPFormBits = FPForm.Value;
let Pattern = pattern;
}
// Random Pseudo Instructions.
def FpGETRESULT32 : FpI_<(ops RFP32:$dst), SpecialFP,
[(set RFP32:$dst, X86fpget)]>; // FPR = ST(0)
def FpGETRESULT64 : FpI_<(ops RFP64:$dst), SpecialFP,
[(set RFP64:$dst, X86fpget)]>; // FPR = ST(0)
let noResults = 1 in {
def FpSETRESULT32 : FpI_<(ops RFP32:$src), SpecialFP,
[(X86fpset RFP32:$src)]>, Imp<[], [ST0]>; // ST(0) = FPR
def FpSETRESULT64 : FpI_<(ops RFP64:$src), SpecialFP,
[(X86fpset RFP64:$src)]>, Imp<[], [ST0]>; // ST(0) = FPR
}
// FpI - Floating Point Psuedo Instruction template. Predicated on FPStack.
class FpI<dag ops, FPFormat fp, list<dag> pattern> :
FpI_<ops, fp, pattern>, Requires<[FPStack]>;
// Register copies. Just copies, the 64->32 version does not truncate.
def FpMOV3232 : FpI<(ops RFP32:$dst, RFP32:$src), SpecialFP, []>; // f1 = fmov f2
def FpMOV3264 : FpI<(ops RFP64:$dst, RFP32:$src), SpecialFP, []>; // f1 = fmov f2
def FpMOV6432 : FpI<(ops RFP32:$dst, RFP64:$src), SpecialFP, []>; // f1 = fmov f2
def FpMOV6464 : FpI<(ops RFP64:$dst, RFP64:$src), SpecialFP, []>; // f1 = fmov f2
// Arithmetic
// Add, Sub, Mul, Div.
def FpADD32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), TwoArgFP,
[(set RFP32:$dst, (fadd RFP32:$src1, RFP32:$src2))]>;
def FpSUB32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), TwoArgFP,
[(set RFP32:$dst, (fsub RFP32:$src1, RFP32:$src2))]>;
def FpMUL32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), TwoArgFP,
[(set RFP32:$dst, (fmul RFP32:$src1, RFP32:$src2))]>;
def FpDIV32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), TwoArgFP,
[(set RFP32:$dst, (fdiv RFP32:$src1, RFP32:$src2))]>;
def FpADD64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), TwoArgFP,
[(set RFP64:$dst, (fadd RFP64:$src1, RFP64:$src2))]>;
def FpSUB64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), TwoArgFP,
[(set RFP64:$dst, (fsub RFP64:$src1, RFP64:$src2))]>;
def FpMUL64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), TwoArgFP,
[(set RFP64:$dst, (fmul RFP64:$src1, RFP64:$src2))]>;
def FpDIV64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), TwoArgFP,
[(set RFP64:$dst, (fdiv RFP64:$src1, RFP64:$src2))]>;
class FPST0rInst<bits<8> o, string asm>
: FPI<o, AddRegFrm, (ops RST:$op), asm>, D8;
class FPrST0Inst<bits<8> o, string asm>
: FPI<o, AddRegFrm, (ops RST:$op), asm>, DC;
class FPrST0PInst<bits<8> o, string asm>
: FPI<o, AddRegFrm, (ops RST:$op), asm>, DE;
// Binary Ops with a memory source.
def FpADD32m : FpI<(ops RFP32:$dst, RFP32:$src1, f32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fadd RFP32:$src1, (loadf32 addr:$src2)))]>;
// ST(0) = ST(0) + [mem32]
def FpADD64m : FpI<(ops RFP64:$dst, RFP64:$src1, f64mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fadd RFP64:$src1, (loadf64 addr:$src2)))]>;
// ST(0) = ST(0) + [mem64]
def FpMUL32m : FpI<(ops RFP32:$dst, RFP32:$src1, f32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fmul RFP32:$src1, (loadf32 addr:$src2)))]>;
// ST(0) = ST(0) * [mem32]
def FpMUL64m : FpI<(ops RFP64:$dst, RFP64:$src1, f64mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fmul RFP64:$src1, (loadf64 addr:$src2)))]>;
// ST(0) = ST(0) * [mem64]
def FpSUB32m : FpI<(ops RFP32:$dst, RFP32:$src1, f32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fsub RFP32:$src1, (loadf32 addr:$src2)))]>;
// ST(0) = ST(0) - [mem32]
def FpSUB64m : FpI<(ops RFP64:$dst, RFP64:$src1, f64mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fsub RFP64:$src1, (loadf64 addr:$src2)))]>;
// ST(0) = ST(0) - [mem64]
def FpSUBR32m : FpI<(ops RFP32:$dst, RFP32:$src1, f32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fsub (loadf32 addr:$src2), RFP32:$src1))]>;
// ST(0) = [mem32] - ST(0)
def FpSUBR64m : FpI<(ops RFP64:$dst, RFP64:$src1, f64mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fsub (loadf64 addr:$src2), RFP64:$src1))]>;
// ST(0) = [mem64] - ST(0)
def FpDIV32m : FpI<(ops RFP32:$dst, RFP32:$src1, f32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fdiv RFP32:$src1, (loadf32 addr:$src2)))]>;
// ST(0) = ST(0) / [mem32]
def FpDIV64m : FpI<(ops RFP64:$dst, RFP64:$src1, f64mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fdiv RFP64:$src1, (loadf64 addr:$src2)))]>;
// ST(0) = ST(0) / [mem64]
def FpDIVR32m : FpI<(ops RFP32:$dst, RFP32:$src1, f32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fdiv (loadf32 addr:$src2), RFP32:$src1))]>;
// ST(0) = [mem32] / ST(0)
def FpDIVR64m : FpI<(ops RFP64:$dst, RFP64:$src1, f64mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fdiv (loadf64 addr:$src2), RFP64:$src1))]>;
// ST(0) = [mem64] / ST(0)
def FADD32m : FPI<0xD8, MRM0m, (ops f32mem:$src), "fadd{s} $src">;
def FADD64m : FPI<0xDC, MRM0m, (ops f64mem:$src), "fadd{l} $src">;
def FMUL32m : FPI<0xD8, MRM1m, (ops f32mem:$src), "fmul{s} $src">;
def FMUL64m : FPI<0xDC, MRM1m, (ops f64mem:$src), "fmul{l} $src">;
def FSUB32m : FPI<0xD8, MRM4m, (ops f32mem:$src), "fsub{s} $src">;
def FSUB64m : FPI<0xDC, MRM4m, (ops f64mem:$src), "fsub{l} $src">;
def FSUBR32m : FPI<0xD8, MRM5m, (ops f32mem:$src), "fsubr{s} $src">;
def FSUBR64m : FPI<0xDC, MRM5m, (ops f64mem:$src), "fsubr{l} $src">;
def FDIV32m : FPI<0xD8, MRM6m, (ops f32mem:$src), "fdiv{s} $src">;
def FDIV64m : FPI<0xDC, MRM6m, (ops f64mem:$src), "fdiv{l} $src">;
def FDIVR32m : FPI<0xD8, MRM7m, (ops f32mem:$src), "fdivr{s} $src">;
def FDIVR64m : FPI<0xDC, MRM7m, (ops f64mem:$src), "fdivr{l} $src">;
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
def FpIADD16m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fadd RFP32:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) + [mem16int]
def FpIADD32m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fadd RFP32:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) + [mem32int]
def FpIMUL16m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fmul RFP32:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) * [mem16int]
def FpIMUL32m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fmul RFP32:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) * [mem32int]
def FpISUB16m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fsub RFP32:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) - [mem16int]
def FpISUB32m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fsub RFP32:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) - [mem32int]
def FpISUBR16m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fsub (X86fild addr:$src2, i16),
RFP32:$src1))]>;
// ST(0) = [mem16int] - ST(0)
def FpISUBR32m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fsub (X86fild addr:$src2, i32),
RFP32:$src1))]>;
// ST(0) = [mem32int] - ST(0)
def FpIDIV16m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fdiv RFP32:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) / [mem16int]
def FpIDIV32m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fdiv RFP32:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) / [mem32int]
def FpIDIVR16m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fdiv (X86fild addr:$src2, i16),
RFP32:$src1))]>;
// ST(0) = [mem16int] / ST(0)
def FpIDIVR32m32 : FpI<(ops RFP32:$dst, RFP32:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP32:$dst, (fdiv (X86fild addr:$src2, i32),
RFP32:$src1))]>;
// ST(0) = [mem32int] / ST(0)
def FpIADD16m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fadd RFP64:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) + [mem16int]
def FpIADD32m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fadd RFP64:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) + [mem32int]
def FpIMUL16m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fmul RFP64:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) * [mem16int]
def FpIMUL32m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fmul RFP64:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) * [mem32int]
def FpISUB16m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fsub RFP64:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) - [mem16int]
def FpISUB32m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fsub RFP64:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) - [mem32int]
def FpISUBR16m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fsub (X86fild addr:$src2, i16),
RFP64:$src1))]>;
// ST(0) = [mem16int] - ST(0)
def FpISUBR32m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fsub (X86fild addr:$src2, i32),
RFP64:$src1))]>;
// ST(0) = [mem32int] - ST(0)
def FpIDIV16m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fdiv RFP64:$src1,
(X86fild addr:$src2, i16)))]>;
// ST(0) = ST(0) / [mem16int]
def FpIDIV32m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fdiv RFP64:$src1,
(X86fild addr:$src2, i32)))]>;
// ST(0) = ST(0) / [mem32int]
def FpIDIVR16m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i16mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fdiv (X86fild addr:$src2, i16),
RFP64:$src1))]>;
// ST(0) = [mem16int] / ST(0)
def FpIDIVR32m64 : FpI<(ops RFP64:$dst, RFP64:$src1, i32mem:$src2), OneArgFPRW,
[(set RFP64:$dst, (fdiv (X86fild addr:$src2, i32),
RFP64:$src1))]>;
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
// ST(0) = [mem32int] / ST(0)
def FIADD16m : FPI<0xDE, MRM0m, (ops i16mem:$src), "fiadd{s} $src">;
def FIADD32m : FPI<0xDA, MRM0m, (ops i32mem:$src), "fiadd{l} $src">;
def FIMUL16m : FPI<0xDE, MRM1m, (ops i16mem:$src), "fimul{s} $src">;
def FIMUL32m : FPI<0xDA, MRM1m, (ops i32mem:$src), "fimul{l} $src">;
def FISUB16m : FPI<0xDE, MRM4m, (ops i16mem:$src), "fisub{s} $src">;
def FISUB32m : FPI<0xDA, MRM4m, (ops i32mem:$src), "fisub{l} $src">;
def FISUBR16m : FPI<0xDE, MRM5m, (ops i16mem:$src), "fisubr{s} $src">;
def FISUBR32m : FPI<0xDA, MRM5m, (ops i32mem:$src), "fisubr{l} $src">;
def FIDIV16m : FPI<0xDE, MRM6m, (ops i16mem:$src), "fidiv{s} $src">;
def FIDIV32m : FPI<0xDA, MRM6m, (ops i32mem:$src), "fidiv{l} $src">;
def FIDIVR16m : FPI<0xDE, MRM7m, (ops i16mem:$src), "fidivr{s} $src">;
def FIDIVR32m : FPI<0xDA, MRM7m, (ops i32mem:$src), "fidivr{l} $src">;
// NOTE: GAS and apparently all other AT&T style assemblers have a broken notion
// of some of the 'reverse' forms of the fsub and fdiv instructions. As such,
// we have to put some 'r's in and take them out of weird places.
def FADDST0r : FPST0rInst <0xC0, "fadd $op">;
def FADDrST0 : FPrST0Inst <0xC0, "fadd {%st(0), $op|$op, %ST(0)}">;
def FADDPrST0 : FPrST0PInst<0xC0, "faddp $op">;
def FSUBRST0r : FPST0rInst <0xE8, "fsubr $op">;
def FSUBrST0 : FPrST0Inst <0xE8, "fsub{r} {%st(0), $op|$op, %ST(0)}">;
def FSUBPrST0 : FPrST0PInst<0xE8, "fsub{r}p $op">;
def FSUBST0r : FPST0rInst <0xE0, "fsub $op">;
def FSUBRrST0 : FPrST0Inst <0xE0, "fsub{|r} {%st(0), $op|$op, %ST(0)}">;
def FSUBRPrST0 : FPrST0PInst<0xE0, "fsub{|r}p $op">;
def FMULST0r : FPST0rInst <0xC8, "fmul $op">;
def FMULrST0 : FPrST0Inst <0xC8, "fmul {%st(0), $op|$op, %ST(0)}">;
def FMULPrST0 : FPrST0PInst<0xC8, "fmulp $op">;
def FDIVRST0r : FPST0rInst <0xF8, "fdivr $op">;
def FDIVrST0 : FPrST0Inst <0xF8, "fdiv{r} {%st(0), $op|$op, %ST(0)}">;
def FDIVPrST0 : FPrST0PInst<0xF8, "fdiv{r}p $op">;
def FDIVST0r : FPST0rInst <0xF0, "fdiv $op">;
def FDIVRrST0 : FPrST0Inst <0xF0, "fdiv{|r} {%st(0), $op|$op, %ST(0)}">;
def FDIVRPrST0 : FPrST0PInst<0xF0, "fdiv{|r}p $op">;
// Unary operations.
def FpCHS32 : FpI<(ops RFP32:$dst, RFP32:$src), OneArgFPRW,
[(set RFP32:$dst, (fneg RFP32:$src))]>;
def FpABS32 : FpI<(ops RFP32:$dst, RFP32:$src), OneArgFPRW,
[(set RFP32:$dst, (fabs RFP32:$src))]>;
def FpSQRT32 : FpI<(ops RFP32:$dst, RFP32:$src), OneArgFPRW,
[(set RFP32:$dst, (fsqrt RFP32:$src))]>;
def FpSIN32 : FpI<(ops RFP32:$dst, RFP32:$src), OneArgFPRW,
[(set RFP32:$dst, (fsin RFP32:$src))]>;
def FpCOS32 : FpI<(ops RFP32:$dst, RFP32:$src), OneArgFPRW,
[(set RFP32:$dst, (fcos RFP32:$src))]>;
def FpTST32 : FpI<(ops RFP32:$src), OneArgFP,
[]>;
def FpCHS64 : FpI<(ops RFP64:$dst, RFP64:$src), OneArgFPRW,
[(set RFP64:$dst, (fneg RFP64:$src))]>;
def FpABS64 : FpI<(ops RFP64:$dst, RFP64:$src), OneArgFPRW,
[(set RFP64:$dst, (fabs RFP64:$src))]>;
def FpSQRT64 : FpI<(ops RFP64:$dst, RFP64:$src), OneArgFPRW,
[(set RFP64:$dst, (fsqrt RFP64:$src))]>;
def FpSIN64 : FpI<(ops RFP64:$dst, RFP64:$src), OneArgFPRW,
[(set RFP64:$dst, (fsin RFP64:$src))]>;
def FpCOS64 : FpI<(ops RFP64:$dst, RFP64:$src), OneArgFPRW,
[(set RFP64:$dst, (fcos RFP64:$src))]>;
def FpTST64 : FpI<(ops RFP64:$src), OneArgFP,
[]>;
def FCHS : FPI<0xE0, RawFrm, (ops), "fchs">, D9;
def FABS : FPI<0xE1, RawFrm, (ops), "fabs">, D9;
def FSQRT : FPI<0xFA, RawFrm, (ops), "fsqrt">, D9;
def FSIN : FPI<0xFE, RawFrm, (ops), "fsin">, D9;
def FCOS : FPI<0xFF, RawFrm, (ops), "fcos">, D9;
def FTST : FPI<0xE4, RawFrm, (ops), "ftst">, D9;
// Floating point cmovs.
let isTwoAddress = 1 in {
def FpCMOVB32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_B))]>;
def FpCMOVBE32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_BE))]>;
def FpCMOVE32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_E))]>;
def FpCMOVP32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_P))]>;
def FpCMOVNB32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_AE))]>;
def FpCMOVNBE32: FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_A))]>;
def FpCMOVNE32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_NE))]>;
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
def FpCMOVNP32 : FpI<(ops RFP32:$dst, RFP32:$src1, RFP32:$src2), CondMovFP,
[(set RFP32:$dst, (X86cmov RFP32:$src1, RFP32:$src2,
X86_COND_NP))]>;
def FpCMOVB64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_B))]>;
def FpCMOVBE64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_BE))]>;
def FpCMOVE64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_E))]>;
def FpCMOVP64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_P))]>;
def FpCMOVNB64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_AE))]>;
def FpCMOVNBE64: FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_A))]>;
def FpCMOVNE64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_NE))]>;
def FpCMOVNP64 : FpI<(ops RFP64:$dst, RFP64:$src1, RFP64:$src2), CondMovFP,
[(set RFP64:$dst, (X86cmov RFP64:$src1, RFP64:$src2,
X86_COND_NP))]>;
}
def FCMOVB : FPI<0xC0, AddRegFrm, (ops RST:$op),
"fcmovb {$op, %st(0)|%ST(0), $op}">, DA;
def FCMOVBE : FPI<0xD0, AddRegFrm, (ops RST:$op),
"fcmovbe {$op, %st(0)|%ST(0), $op}">, DA;
def FCMOVE : FPI<0xC8, AddRegFrm, (ops RST:$op),
"fcmove {$op, %st(0)|%ST(0), $op}">, DA;
def FCMOVP : FPI<0xD8, AddRegFrm, (ops RST:$op),
"fcmovu {$op, %st(0)|%ST(0), $op}">, DA;
def FCMOVNB : FPI<0xC0, AddRegFrm, (ops RST:$op),
"fcmovnb {$op, %st(0)|%ST(0), $op}">, DB;
def FCMOVNBE : FPI<0xD0, AddRegFrm, (ops RST:$op),
"fcmovnbe {$op, %st(0)|%ST(0), $op}">, DB;
def FCMOVNE : FPI<0xC8, AddRegFrm, (ops RST:$op),
"fcmovne {$op, %st(0)|%ST(0), $op}">, DB;
def FCMOVNP : FPI<0xD8, AddRegFrm, (ops RST:$op),
"fcmovnu {$op, %st(0)|%ST(0), $op}">, DB;
// Floating point loads & stores.
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
def FpLD32m : FpI<(ops RFP32:$dst, f32mem:$src), ZeroArgFP,
[(set RFP32:$dst, (loadf32 addr:$src))]>;
def FpLD64m : FpI<(ops RFP64:$dst, f64mem:$src), ZeroArgFP,
[(set RFP64:$dst, (loadf64 addr:$src))]>;
def FpILD16m32 : FpI<(ops RFP32:$dst, i16mem:$src), ZeroArgFP,
[(set RFP32:$dst, (X86fild addr:$src, i16))]>;
def FpILD32m32 : FpI<(ops RFP32:$dst, i32mem:$src), ZeroArgFP,
[(set RFP32:$dst, (X86fild addr:$src, i32))]>;
def FpILD64m32 : FpI<(ops RFP32:$dst, i64mem:$src), ZeroArgFP,
[(set RFP32:$dst, (X86fild addr:$src, i64))]>;
def FpILD16m64 : FpI<(ops RFP64:$dst, i16mem:$src), ZeroArgFP,
[(set RFP64:$dst, (X86fild addr:$src, i16))]>;
def FpILD32m64 : FpI<(ops RFP64:$dst, i32mem:$src), ZeroArgFP,
[(set RFP64:$dst, (X86fild addr:$src, i32))]>;
def FpILD64m64 : FpI<(ops RFP64:$dst, i64mem:$src), ZeroArgFP,
[(set RFP64:$dst, (X86fild addr:$src, i64))]>;
def FpST32m : FpI<(ops f32mem:$op, RFP32:$src), OneArgFP,
[(store RFP32:$src, addr:$op)]>;
def FpST64m32 : FpI<(ops f32mem:$op, RFP64:$src), OneArgFP,
[(truncstoref32 RFP64:$src, addr:$op)]>;
def FpST64m : FpI<(ops f64mem:$op, RFP64:$src), OneArgFP,
[(store RFP64:$src, addr:$op)]>;
def FpSTP32m : FpI<(ops f32mem:$op, RFP32:$src), OneArgFP, []>;
def FpSTP64m32 : FpI<(ops f32mem:$op, RFP64:$src), OneArgFP, []>;
def FpSTP64m : FpI<(ops f64mem:$op, RFP64:$src), OneArgFP, []>;
def FpIST16m32 : FpI<(ops i16mem:$op, RFP32:$src), OneArgFP, []>;
def FpIST32m32 : FpI<(ops i32mem:$op, RFP32:$src), OneArgFP, []>;
def FpIST64m32 : FpI<(ops i64mem:$op, RFP32:$src), OneArgFP, []>;
def FpIST16m64 : FpI<(ops i16mem:$op, RFP64:$src), OneArgFP, []>;
def FpIST32m64 : FpI<(ops i32mem:$op, RFP64:$src), OneArgFP, []>;
def FpIST64m64 : FpI<(ops i64mem:$op, RFP64:$src), OneArgFP, []>;
def FLD32m : FPI<0xD9, MRM0m, (ops f32mem:$src), "fld{s} $src">;
def FLD64m : FPI<0xDD, MRM0m, (ops f64mem:$src), "fld{l} $src">;
def FILD16m : FPI<0xDF, MRM0m, (ops i16mem:$src), "fild{s} $src">;
def FILD32m : FPI<0xDB, MRM0m, (ops i32mem:$src), "fild{l} $src">;
def FILD64m : FPI<0xDF, MRM5m, (ops i64mem:$src), "fild{ll} $src">;
def FST32m : FPI<0xD9, MRM2m, (ops f32mem:$dst), "fst{s} $dst">;
def FST64m : FPI<0xDD, MRM2m, (ops f64mem:$dst), "fst{l} $dst">;
def FSTP32m : FPI<0xD9, MRM3m, (ops f32mem:$dst), "fstp{s} $dst">;
def FSTP64m : FPI<0xDD, MRM3m, (ops f64mem:$dst), "fstp{l} $dst">;
def FIST16m : FPI<0xDF, MRM2m, (ops i16mem:$dst), "fist{s} $dst">;
def FIST32m : FPI<0xDB, MRM2m, (ops i32mem:$dst), "fist{l} $dst">;
def FISTP16m : FPI<0xDF, MRM3m, (ops i16mem:$dst), "fistp{s} $dst">;
def FISTP32m : FPI<0xDB, MRM3m, (ops i32mem:$dst), "fistp{l} $dst">;
def FISTP64m : FPI<0xDF, MRM7m, (ops i64mem:$dst), "fistp{ll} $dst">;
// FISTTP requires SSE3 even though it's a FPStack op.
def FpISTT16m32 : FpI_<(ops i16mem:$op, RFP32:$src), OneArgFP,
[(X86fp_to_i16mem RFP32:$src, addr:$op)]>,
Requires<[HasSSE3]>;
def FpISTT32m32 : FpI_<(ops i32mem:$op, RFP32:$src), OneArgFP,
[(X86fp_to_i32mem RFP32:$src, addr:$op)]>,
Requires<[HasSSE3]>;
def FpISTT64m32 : FpI_<(ops i64mem:$op, RFP32:$src), OneArgFP,
[(X86fp_to_i64mem RFP32:$src, addr:$op)]>,
Requires<[HasSSE3]>;
def FpISTT16m64 : FpI_<(ops i16mem:$op, RFP64:$src), OneArgFP,
[(X86fp_to_i16mem RFP64:$src, addr:$op)]>,
Requires<[HasSSE3]>;
def FpISTT32m64 : FpI_<(ops i32mem:$op, RFP64:$src), OneArgFP,
[(X86fp_to_i32mem RFP64:$src, addr:$op)]>,
Requires<[HasSSE3]>;
def FpISTT64m64 : FpI_<(ops i64mem:$op, RFP64:$src), OneArgFP,
[(X86fp_to_i64mem RFP64:$src, addr:$op)]>,
Requires<[HasSSE3]>;
def FISTTP16m : FPI<0xDF, MRM1m, (ops i16mem:$dst), "fisttp{s} $dst">;
def FISTTP32m : FPI<0xDB, MRM1m, (ops i32mem:$dst), "fisttp{l} $dst">;
def FISTTP64m : FPI<0xDD, MRM1m, (ops i64mem:$dst), "fisttp{ll} $dst">;
// FP Stack manipulation instructions.
def FLDrr : FPI<0xC0, AddRegFrm, (ops RST:$op), "fld $op">, D9;
def FSTrr : FPI<0xD0, AddRegFrm, (ops RST:$op), "fst $op">, DD;
def FSTPrr : FPI<0xD8, AddRegFrm, (ops RST:$op), "fstp $op">, DD;
def FXCH : FPI<0xC8, AddRegFrm, (ops RST:$op), "fxch $op">, D9;
// Floating point constant loads.
let isReMaterializable = 1 in {
def FpLD032 : FpI<(ops RFP32:$dst), ZeroArgFP,
[(set RFP32:$dst, fpimm0)]>;
def FpLD132 : FpI<(ops RFP32:$dst), ZeroArgFP,
[(set RFP32:$dst, fpimm1)]>;
def FpLD064 : FpI<(ops RFP64:$dst), ZeroArgFP,
[(set RFP64:$dst, fpimm0)]>;
def FpLD164 : FpI<(ops RFP64:$dst), ZeroArgFP,
[(set RFP64:$dst, fpimm1)]>;
def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9;
def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9;
// Floating point compares.
def FpUCOMr32 : FpI<(ops RFP32:$lhs, RFP32:$rhs), CompareFP,
[]>; // FPSW = cmp ST(0) with ST(i)
def FpUCOMIr32 : FpI<(ops RFP32:$lhs, RFP32:$rhs), CompareFP,
[(X86cmp RFP32:$lhs, RFP32:$rhs)]>; // CC = cmp ST(0) with ST(i)
def FpUCOMr64 : FpI<(ops RFP64:$lhs, RFP64:$rhs), CompareFP,
[]>; // FPSW = cmp ST(0) with ST(i)
def FpUCOMIr64 : FpI<(ops RFP64:$lhs, RFP64:$rhs), CompareFP,
[(X86cmp RFP64:$lhs, RFP64:$rhs)]>; // CC = cmp ST(0) with ST(i)
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
def FUCOMr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i)
(ops RST:$reg),
"fucom $reg">, DD, Imp<[ST0],[]>;
def FUCOMPr : FPI<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop
(ops RST:$reg),
"fucomp $reg">, DD, Imp<[ST0],[]>;
def FUCOMPPr : FPI<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop
(ops),
"fucompp">, DA, Imp<[ST0],[]>;
def FUCOMIr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i)
(ops RST:$reg),
"fucomi {$reg, %st(0)|%ST(0), $reg}">, DB, Imp<[ST0],[]>;
def FUCOMIPr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop
(ops RST:$reg),
"fucomip {$reg, %st(0)|%ST(0), $reg}">, DF, Imp<[ST0],[]>;
// Floating point flag ops.
def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags
(ops), "fnstsw", []>, DF, Imp<[],[AX]>;
def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world
(ops i16mem:$dst), "fnstcw $dst", []>;
def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16]
(ops i16mem:$dst), "fldcw $dst", []>;
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//===----------------------------------------------------------------------===//
// Required for RET of f32 / f64 values.
def : Pat<(X86fld addr:$src, f32), (FpLD32m addr:$src)>;
def : Pat<(X86fld addr:$src, f64), (FpLD64m addr:$src)>;
// Required for CALL which return f32 / f64 values.
def : Pat<(X86fst RFP32:$src, addr:$op, f32), (FpST32m addr:$op, RFP32:$src)>;
def : Pat<(X86fst RFP64:$src, addr:$op, f32), (FpST64m32 addr:$op, RFP64:$src)>;
def : Pat<(X86fst RFP64:$src, addr:$op, f64), (FpST64m addr:$op, RFP64:$src)>;
// Floating point constant -0.0 and -1.0
def : Pat<(f32 fpimmneg0), (FpCHS32 (FpLD032))>, Requires<[FPStack]>;
def : Pat<(f32 fpimmneg1), (FpCHS32 (FpLD132))>, Requires<[FPStack]>;
def : Pat<(f64 fpimmneg0), (FpCHS64 (FpLD064))>, Requires<[FPStack]>;
def : Pat<(f64 fpimmneg1), (FpCHS64 (FpLD164))>, Requires<[FPStack]>;
// Used to conv. i64 to f64 since there isn't a SSE version.
def : Pat<(X86fildflag addr:$src, i64), (FpILD64m64 addr:$src)>;
def : Pat<(extloadf32 addr:$src), (FpMOV3264 (FpLD32m addr:$src))>, Requires<[FPStack]>;
def : Pat<(fextend RFP32:$src), (FpMOV3264 RFP32:$src)>, Requires<[FPStack]>;