Skip to content
X86InstrInfo.td 124 KiB
Newer Older
                   "movz{wl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (zextloadi32i16 addr:$src))]>, TB;

// Handling 1 bit zextload and sextload
def : Pat<(sextloadi16i1 addr:$src), (MOVSX16rm8  addr:$src)>;
def : Pat<(sextloadi32i1 addr:$src), (MOVSX32rm8  addr:$src)>;
def : Pat<(zextloadi16i1 addr:$src), (MOVZX16rm8  addr:$src)>;
def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8  addr:$src)>;
// Handling 1 bit extload
def : Pat<(extloadi8i1 addr:$src), (MOV8rm  addr:$src)>;

// Modeling anyext as zext
def : Pat<(i16 (anyext R8 :$src)), (MOVZX16rr8  R8 :$src)>;
def : Pat<(i32 (anyext R8 :$src)), (MOVZX32rr8  R8 :$src)>;
def : Pat<(i32 (anyext R16:$src)), (MOVZX32rr16 R16:$src)>;

//===----------------------------------------------------------------------===//
// XMM Floating point support (requires SSE2)
//===----------------------------------------------------------------------===//

def MOVSSrr : I<0x10, MRMSrcReg, (ops FR32:$dst, FR32:$src),
Evan Cheng's avatar
Evan Cheng committed
                "movss {$src, $dst|$dst, $src}", []>, XS;
def MOVSDrr : I<0x10, MRMSrcReg, (ops FR64:$dst, FR64:$src),
Evan Cheng's avatar
Evan Cheng committed
                "movsd {$src, $dst|$dst, $src}", []>, XD;
def MOVSSrm : I<0x10, MRMSrcMem, (ops FR32:$dst, f32mem:$src),
                "movss {$src, $dst|$dst, $src}",
                [(set FR32:$dst, (loadf32 addr:$src))]>,
                Requires<[HasSSE2]>, XS;
def MOVSSmr : I<0x11, MRMDestMem, (ops f32mem:$dst, FR32:$src),
                "movss {$src, $dst|$dst, $src}",
                [(store FR32:$src, addr:$dst)]>, XS;
def MOVSDrm : I<0x10, MRMSrcMem, (ops FR64:$dst, f64mem:$src),
                "movsd {$src, $dst|$dst, $src}",
                [(set FR64:$dst, (loadf64 addr:$src))]>,
                Requires<[HasSSE2]>, XD;
def MOVSDmr : I<0x11, MRMDestMem, (ops f64mem:$dst, FR64:$src),
                "movsd {$src, $dst|$dst, $src}",
                [(store FR64:$src, addr:$dst)]>,
                Requires<[HasSSE2]>, XD;

def CVTTSD2SIrr: I<0x2C, MRMSrcReg, (ops R32:$dst, FR64:$src),
Evan Cheng's avatar
Evan Cheng committed
                "cvttsd2si {$src, $dst|$dst, $src}",
                [(set R32:$dst, (fp_to_sint FR64:$src))]>,
                Requires<[HasSSE2]>, XD;
def CVTTSD2SIrm: I<0x2C, MRMSrcMem, (ops R32:$dst, f64mem:$src),
                "cvttsd2si {$src, $dst|$dst, $src}",
                [(set R32:$dst, (fp_to_sint (loadf64 addr:$src)))]>,
                Requires<[HasSSE2]>, XD;
def CVTTSS2SIrr: I<0x2C, MRMSrcReg, (ops R32:$dst, FR32:$src),
Evan Cheng's avatar
Evan Cheng committed
                "cvttss2si {$src, $dst|$dst, $src}",
                [(set R32:$dst, (fp_to_sint FR32:$src))]>,
                Requires<[HasSSE2]>, XS;
def CVTTSS2SIrm: I<0x2C, MRMSrcMem, (ops R32:$dst, f32mem:$src),
                "cvttss2si {$src, $dst|$dst, $src}",
                [(set R32:$dst, (fp_to_sint (loadf32 addr:$src)))]>,
                Requires<[HasSSE2]>, XS;
def CVTSD2SSrr: I<0x5A, MRMSrcReg, (ops FR32:$dst, FR64:$src),
                "cvtsd2ss {$src, $dst|$dst, $src}",
                [(set FR32:$dst, (fround FR64:$src))]>,
                Requires<[HasSSE2]>, XS;
def CVTSD2SSrm: I<0x5A, MRMSrcMem, (ops FR32:$dst, f64mem:$src), 
Evan Cheng's avatar
Evan Cheng committed
                "cvtsd2ss {$src, $dst|$dst, $src}",
                [(set FR32:$dst, (fround (loadf64 addr:$src)))]>,
                Requires<[HasSSE2]>, XS;
def CVTSS2SDrr: I<0x5A, MRMSrcReg, (ops FR64:$dst, FR32:$src),
                "cvtss2sd {$src, $dst|$dst, $src}",
                [(set FR64:$dst, (fextend FR32:$src))]>,
                Requires<[HasSSE2]>, XD;
def CVTSS2SDrm: I<0x5A, MRMSrcMem, (ops FR64:$dst, f32mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                "cvtss2sd {$src, $dst|$dst, $src}",
                [(set FR64:$dst, (fextend (loadf32 addr:$src)))]>,
                Requires<[HasSSE2]>, XD;
def CVTSI2SSrr: I<0x2A, MRMSrcReg, (ops FR32:$dst, R32:$src),
Evan Cheng's avatar
Evan Cheng committed
                "cvtsi2ss {$src, $dst|$dst, $src}",
                [(set FR32:$dst, (sint_to_fp R32:$src))]>,
                Requires<[HasSSE2]>, XS;
def CVTSI2SSrm: I<0x2A, MRMSrcMem, (ops FR32:$dst, i32mem:$src),
                "cvtsi2ss {$src, $dst|$dst, $src}",
                [(set FR32:$dst, (sint_to_fp (loadi32 addr:$src)))]>,
                Requires<[HasSSE2]>, XS;
def CVTSI2SDrr: I<0x2A, MRMSrcReg, (ops FR64:$dst, R32:$src),
                "cvtsi2sd {$src, $dst|$dst, $src}",
                [(set FR64:$dst, (sint_to_fp R32:$src))]>,
                Requires<[HasSSE2]>, XD;
def CVTSI2SDrm: I<0x2A, MRMSrcMem, (ops FR64:$dst, i32mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                "cvtsi2sd {$src, $dst|$dst, $src}",
                [(set FR64:$dst, (sint_to_fp (loadi32 addr:$src)))]>,
                Requires<[HasSSE2]>, XD;
def SQRTSSrm : I<0x51, MRMSrcMem, (ops FR32:$dst, f32mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                "sqrtss {$src, $dst|$dst, $src}", []>, XS;
def SQRTSSrr : I<0x51, MRMSrcReg, (ops FR32:$dst, FR32:$src),
Evan Cheng's avatar
Evan Cheng committed
                "sqrtss {$src, $dst|$dst, $src}",
                [(set FR32:$dst, (fsqrt FR32:$src))]>, XS;
def SQRTSDrm : I<0x51, MRMSrcMem, (ops FR64:$dst, f64mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                "sqrtsd {$src, $dst|$dst, $src}", []>, XD;
def SQRTSDrr : I<0x51, MRMSrcReg, (ops FR64:$dst, FR64:$src),
Evan Cheng's avatar
Evan Cheng committed
                "sqrtsd {$src, $dst|$dst, $src}",
                [(set FR64:$dst, (fsqrt FR64:$src))]>, XD;
def UCOMISDrr: I<0x2E, MRMSrcReg, (ops FR64:$dst, FR64:$src),
Evan Cheng's avatar
Evan Cheng committed
                "ucomisd {$src, $dst|$dst, $src}", []>, TB, OpSize;
def UCOMISDrm: I<0x2E, MRMSrcMem, (ops FR64:$dst, f64mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                "ucomisd {$src, $dst|$dst, $src}", []>, TB, OpSize;
def UCOMISSrr: I<0x2E, MRMSrcReg, (ops FR32:$dst, FR32:$src),
Evan Cheng's avatar
Evan Cheng committed
                "ucomiss {$src, $dst|$dst, $src}", []>, TB;
def UCOMISSrm: I<0x2E, MRMSrcMem, (ops FR32:$dst, f32mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                "ucomiss {$src, $dst|$dst, $src}", []>, TB;
Evan Cheng's avatar
Evan Cheng committed
// Pseudo-instructions that map fld0 to xorps/xorpd for sse.
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
def FLD0SS : I<0x57, MRMSrcReg, (ops FR32:$dst),
Evan Cheng's avatar
Evan Cheng committed
                "xorps $dst, $dst", []>, TB;
def FLD0SD : I<0x57, MRMSrcReg, (ops FR64:$dst),
Evan Cheng's avatar
Evan Cheng committed
                "xorpd $dst, $dst", []>, TB, OpSize;
let isTwoAddress = 1 in {
let isCommutable = 1 in {
def ADDSSrr : I<0x58, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "addss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fadd FR32:$src1, FR32:$src2))]>, XS;
def ADDSDrr : I<0x58, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "addsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fadd FR64:$src1, FR64:$src2))]>, XD;
def ANDPSrr : I<0x54, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "andps {$src2, $dst|$dst, $src2}", []>, TB;
def ANDPDrr : I<0x54, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "andpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def MULSSrr : I<0x59, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "mulss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fmul FR32:$src1, FR32:$src2))]>, XS;
def MULSDrr : I<0x59, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "mulsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fmul FR64:$src1, FR64:$src2))]>, XD;
def ORPSrr : I<0x56, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "orps {$src2, $dst|$dst, $src2}", []>, TB;
def ORPDrr : I<0x56, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "orpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def XORPSrr : I<0x57, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "xorps {$src2, $dst|$dst, $src2}", []>, TB;
def XORPDrr : I<0x57, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "xorpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def ANDNPSrr : I<0x55, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "andnps {$src2, $dst|$dst, $src2}", []>, TB;
def ANDNPDrr : I<0x55, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "andnpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def ADDSSrm : I<0x58, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "addss {$src2, $dst|$dst, $src2}", []>, XS;
def ADDSDrm : I<0x58, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "addsd {$src2, $dst|$dst, $src2}", []>, XD;
def MULSSrm : I<0x59, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "mulss {$src2, $dst|$dst, $src2}", []>, XS;
def MULSDrm : I<0x59, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "mulsd {$src2, $dst|$dst, $src2}", []>, XD;

def DIVSSrm : I<0x5E, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "divss {$src2, $dst|$dst, $src2}", []>, XS;
def DIVSSrr : I<0x5E, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "divss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fdiv FR32:$src1, FR32:$src2))]>, XS;
def DIVSDrm : I<0x5E, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "divsd {$src2, $dst|$dst, $src2}", []>, XD;
def DIVSDrr : I<0x5E, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "divsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fdiv FR64:$src1, FR64:$src2))]>, XD;
def SUBSSrm : I<0x5C, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "subss {$src2, $dst|$dst, $src2}", []>, XS;
def SUBSSrr : I<0x5C, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "subss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fsub FR32:$src1, FR32:$src2))]>, XS;
def SUBSDrm : I<0x5C, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "subsd {$src2, $dst|$dst, $src2}", []>, XD;
def SUBSDrr : I<0x5C, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
Evan Cheng's avatar
Evan Cheng committed
                "subsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fsub FR64:$src1, FR64:$src2))]>, XD;
                (ops FR32:$dst, FR32:$src1, FR32:$src, SSECC:$cc),
Evan Cheng's avatar
Evan Cheng committed
                "cmp${cc}ss {$src, $dst|$dst, $src}", []>, XS;
                (ops FR32:$dst, FR32:$src1, f32mem:$src, SSECC:$cc),
Evan Cheng's avatar
Evan Cheng committed
                "cmp${cc}ss {$src, $dst|$dst, $src}", []>, XS;
                (ops FR64:$dst, FR64:$src1, FR64:$src, SSECC:$cc),
Evan Cheng's avatar
Evan Cheng committed
                "cmp${cc}sd {$src, $dst|$dst, $src}", []>, XD;
                (ops FR64:$dst, FR64:$src1, f64mem:$src, SSECC:$cc),
Evan Cheng's avatar
Evan Cheng committed
                "cmp${cc}sd {$src, $dst|$dst, $src}", []>, XD;
Chris Lattner's avatar
Chris Lattner committed
//===----------------------------------------------------------------------===//
// Miscellaneous Instructions
//===----------------------------------------------------------------------===//

Evan Cheng's avatar
Evan Cheng committed
def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", []>, TB, Imp<[],[EAX,EDX]>;
//===----------------------------------------------------------------------===//
// Stack-based Floating point support
//===----------------------------------------------------------------------===//

// FIXME: These need to indicate mod/ref sets for FP regs... & FP 'TOP'

// Floating point instruction template
class FPI<bits<8> o, Format F, FPFormat fp, dag ops, string asm,
          list<dag> pattern>
  let FPForm = fp; let FPFormBits = FPForm.Value;
// Pseudo instructions for floating point.  We use these pseudo instructions
// because they can be expanded by the fp spackifier into one of many different
// forms of instructions for doing these operations.  Until the stackifier runs,
// we prefer to be abstract.
def FpMOV : FPI<0, Pseudo, SpecialFP,
                (ops RFP:$dst, RFP:$src), "", []>;   // f1 = fmov f2
def FpADD : FPI<0, Pseudo, TwoArgFP ,
                (ops RFP:$dst, RFP:$src1, RFP:$src2), "",
                []>; // f1 = fadd f2, f3
def FpSUB : FPI<0, Pseudo, TwoArgFP ,
                (ops RFP:$dst, RFP:$src1, RFP:$src2), "",
                []>;    // f1 = fsub f2, f3
def FpMUL : FPI<0, Pseudo, TwoArgFP ,
                (ops RFP:$dst, RFP:$src1, RFP:$src2), "",
                []>;    // f1 = fmul f2, f3
def FpDIV : FPI<0, Pseudo, TwoArgFP ,
                (ops RFP:$dst, RFP:$src1, RFP:$src2), "",
                []>;    // f1 = fdiv f2, f3
def FpLD32m  : FPI<0xD9, MRM0m, ZeroArgFP,
                   (ops RFP:$dst, f32mem:$src),
                   "fld{s} $src",
                   [(set RFP:$dst, (X86fld addr:$src, f32))]>;

def FpLD64m  : FPI<0xDD, MRM0m, ZeroArgFP,
                   (ops RFP:$dst, f64mem:$src),
                   "fld{l} $src",
                   [(set RFP:$dst, (X86fld addr:$src, f64))]>;

def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "", []>,
def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "",
                      [(X86fpset RFP:$src)]>,
// FADD reg, mem: Before stackification, these are represented by:
// R1 = FADD* R2, [mem]
def FADD32m  : FPI<0xD8, MRM0m, OneArgFPRW,    // ST(0) = ST(0) + [mem32real]
                   (ops f32mem:$src, variable_ops),
def FADD64m  : FPI<0xDC, MRM0m, OneArgFPRW,    // ST(0) = ST(0) + [mem64real]
                   (ops f64mem:$src, variable_ops),
//def FIADD16m : FPI<0xDE, MRM0m, OneArgFPRW>;    // ST(0) = ST(0) + [mem16int]
//def FIADD32m : FPI<0xDA, MRM0m, OneArgFPRW>;    // ST(0) = ST(0) + [mem32int]
// FMUL reg, mem: Before stackification, these are represented by:
// R1 = FMUL* R2, [mem]
def FMUL32m  : FPI<0xD8, MRM1m, OneArgFPRW,    // ST(0) = ST(0) * [mem32real]
                   (ops f32mem:$src, variable_ops),
def FMUL64m  : FPI<0xDC, MRM1m, OneArgFPRW,    // ST(0) = ST(0) * [mem64real]
                   (ops f64mem:$src, variable_ops),
// ST(0) = ST(0) * [mem16int]
//def FIMUL16m : FPI16m<"fimul", 0xDE, MRM1m, OneArgFPRW>;
// ST(0) = ST(0) * [mem32int]
//def FIMUL32m : FPI32m<"fimul", 0xDA, MRM1m, OneArgFPRW>;

// FSUB reg, mem: Before stackification, these are represented by:
// R1 = FSUB* R2, [mem]
def FSUB32m  : FPI<0xD8, MRM4m, OneArgFPRW,    // ST(0) = ST(0) - [mem32real]
Chris Lattner's avatar
Chris Lattner committed
                   (ops f32mem:$src, variable_ops),
def FSUB64m  : FPI<0xDC, MRM4m, OneArgFPRW,    // ST(0) = ST(0) - [mem64real]
Chris Lattner's avatar
Chris Lattner committed
                   (ops f64mem:$src, variable_ops),
// ST(0) = ST(0) - [mem16int]
//def FISUB16m : FPI16m<"fisub", 0xDE, MRM4m, OneArgFPRW>;
// ST(0) = ST(0) - [mem32int]
//def FISUB32m : FPI32m<"fisub", 0xDA, MRM4m, OneArgFPRW>;

// FSUBR reg, mem: Before stackification, these are represented by:
// R1 = FSUBR* R2, [mem]

// Note that the order of operands does not reflect the operation being
// performed.
def FSUBR32m  : FPI<0xD8, MRM5m, OneArgFPRW,  // ST(0) = [mem32real] - ST(0)
                    (ops f32mem:$src, variable_ops),
def FSUBR64m  : FPI<0xDC, MRM5m, OneArgFPRW,  // ST(0) = [mem64real] - ST(0)
                    (ops f64mem:$src, variable_ops),
// ST(0) = [mem16int] - ST(0)
//def FISUBR16m : FPI16m<"fisubr", 0xDE, MRM5m, OneArgFPRW>;
// ST(0) = [mem32int] - ST(0)
//def FISUBR32m : FPI32m<"fisubr", 0xDA, MRM5m, OneArgFPRW>;

// FDIV reg, mem: Before stackification, these are represented by:
// R1 = FDIV* R2, [mem]
def FDIV32m  : FPI<0xD8, MRM6m, OneArgFPRW,    // ST(0) = ST(0) / [mem32real]
                   (ops f32mem:$src, variable_ops),
def FDIV64m  : FPI<0xDC, MRM6m, OneArgFPRW,    // ST(0) = ST(0) / [mem64real]
                   (ops f64mem:$src, variable_ops),
// ST(0) = ST(0) / [mem16int]
//def FIDIV16m : FPI16m<"fidiv", 0xDE, MRM6m, OneArgFPRW>;
// ST(0) = ST(0) / [mem32int]
//def FIDIV32m : FPI32m<"fidiv", 0xDA, MRM6m, OneArgFPRW>;

// FDIVR reg, mem: Before stackification, these are represented by:
// R1 = FDIVR* R2, [mem]
// Note that the order of operands does not reflect the operation being
// performed.
def FDIVR32m  : FPI<0xD8, MRM7m, OneArgFPRW,  // ST(0) = [mem32real] / ST(0)
Chris Lattner's avatar
Chris Lattner committed
                    (ops f32mem:$src, variable_ops),
def FDIVR64m  : FPI<0xDC, MRM7m, OneArgFPRW,  // ST(0) = [mem64real] / ST(0)
Chris Lattner's avatar
Chris Lattner committed
                    (ops f64mem:$src, variable_ops),
// ST(0) = [mem16int] / ST(0)
//def FIDIVR16m : FPI16m<"fidivr", 0xDE, MRM7m, OneArgFPRW>;
// ST(0) = [mem32int] / ST(0)
//def FIDIVR32m : FPI32m<"fidivr", 0xDA, MRM7m, OneArgFPRW>;
let isTwoAddress = 1, Uses = [ST0], Defs = [ST0] in {
  def FCMOVB  : FPI<0xC0, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmovb {$op, %ST(0)|%ST(0), $op}", []>, DA;
  def FCMOVBE : FPI<0xD0, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmovbe {$op, %ST(0)|%ST(0), $op}", []>, DA;
  def FCMOVE  : FPI<0xC8, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmove {$op, %ST(0)|%ST(0), $op}", []>, DA;
  def FCMOVP  : FPI<0xD8, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmovu  {$op, %ST(0)|%ST(0), $op}", []>, DA;
  def FCMOVAE : FPI<0xC0, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmovae {$op, %ST(0)|%ST(0), $op}", []>, DB;
  def FCMOVA  : FPI<0xD0, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmova {$op, %ST(0)|%ST(0), $op}", []>, DB;
  def FCMOVNE : FPI<0xC8, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmovne {$op, %ST(0)|%ST(0), $op}", []>, DB;
  def FCMOVNP : FPI<0xD8, AddRegFrm, CondMovFP,
                    (ops RST:$op, variable_ops),
                    "fcmovnu {$op, %ST(0)|%ST(0), $op}", []>, DB;
// Floating point loads & stores...
// FIXME: these are all marked variable_ops because they have an implicit 
// destination.  Instructions like FILD* that are generated by the instruction
//  selector (not the fp stackifier) need more accurate operand accounting.
def FLDrr   : FPI<0xC0, AddRegFrm, NotFP,
                  (ops RST:$src, variable_ops),
def FLD32m  : FPI<0xD9, MRM0m, ZeroArgFP,
                  (ops f32mem:$src, variable_ops),
def FLD64m  : FPI<0xDD, MRM0m, ZeroArgFP,
                  (ops f64mem:$src, variable_ops),
def FLD80m  : FPI<0xDB, MRM5m, ZeroArgFP,
                  (ops f80mem:$src, variable_ops),
def FILD16m : FPI<0xDF, MRM0m, ZeroArgFP,
                  (ops i16mem:$src, variable_ops),
def FILD32m : FPI<0xDB, MRM0m, ZeroArgFP,
                  (ops i32mem:$src, variable_ops),
def FILD64m : FPI<0xDF, MRM5m, ZeroArgFP,
                  (ops i64mem:$src, variable_ops),

def FSTrr    : FPI<0xD0, AddRegFrm, NotFP,
                   (ops RST:$op, variable_ops),
def FSTPrr   : FPI<0xD8, AddRegFrm, NotFP,
                   (ops RST:$op, variable_ops),
def FST32m   : FPI<0xD9, MRM2m, OneArgFP,
                   (ops f32mem:$op, variable_ops),
def FST64m   : FPI<0xDD, MRM2m, OneArgFP,
                   (ops f64mem:$op, variable_ops),
def FSTP32m  : FPI<0xD9, MRM3m, OneArgFP,
                   (ops f32mem:$op, variable_ops),
def FSTP64m  : FPI<0xDD, MRM3m, OneArgFP,
                   (ops f64mem:$op, variable_ops),
def FSTP80m  : FPI<0xDB, MRM7m, OneArgFP,
                   (ops f80mem:$op, variable_ops),

def FIST16m  : FPI<0xDF, MRM2m , OneArgFP,
                   (ops i16mem:$op, variable_ops),
def FIST32m  : FPI<0xDB, MRM2m , OneArgFP,
                   (ops i32mem:$op, variable_ops),
def FISTP16m : FPI<0xDF, MRM3m , NotFP   ,
                   (ops i16mem:$op, variable_ops),
def FISTP32m : FPI<0xDB, MRM3m , NotFP   ,
                   (ops i32mem:$op, variable_ops),
def FISTP64m : FPI<0xDF, MRM7m , OneArgFP,
                   (ops i64mem:$op, variable_ops),
def FXCH     : FPI<0xC8, AddRegFrm, NotFP,
                   (ops RST:$op), "fxch $op", []>, D9;      // fxch ST(i), ST(0)

// Floating point constant loads...
def FLD0 : FPI<0xEE, RawFrm, ZeroArgFP, (ops variable_ops), "fldz", []>, D9;
def FLD1 : FPI<0xE8, RawFrm, ZeroArgFP, (ops variable_ops), "fld1", []>, D9;
Chris Lattner's avatar
Chris Lattner committed
// Unary operations...
def FCHS  : FPI<0xE0, RawFrm, OneArgFPRW,   // f1 = fchs f2
                (ops variable_ops),
def FABS  : FPI<0xE1, RawFrm, OneArgFPRW,   // f1 = fabs f2
                (ops variable_ops),
def FSQRT : FPI<0xFA, RawFrm, OneArgFPRW,   // fsqrt ST(0)
                (ops variable_ops),
def FSIN  : FPI<0xFE, RawFrm, OneArgFPRW,   // fsin  ST(0)
                (ops variable_ops),
def FCOS  : FPI<0xFF, RawFrm, OneArgFPRW,   // fcos  ST(0)
                (ops variable_ops),
def FTST  : FPI<0xE4, RawFrm, OneArgFP  ,   // ftst ST(0)
                (ops variable_ops),
// Binary arithmetic operations...
class FPST0rInst<bits<8> o, dag ops, string asm>
Evan Cheng's avatar
Evan Cheng committed
  : I<o, AddRegFrm, ops, asm, []>, D8 {
  list<Register> Uses = [ST0];
  list<Register> Defs = [ST0];
}
class FPrST0Inst<bits<8> o, dag ops, string asm>
Evan Cheng's avatar
Evan Cheng committed
  : I<o, AddRegFrm, ops, asm, []>, DC {
  list<Register> Uses = [ST0];
}
class FPrST0PInst<bits<8> o, dag ops, string asm>
Evan Cheng's avatar
Evan Cheng committed
  : I<o, AddRegFrm, ops, asm, []>, DE {
  list<Register> Uses = [ST0];
}

def FADDST0r   : FPST0rInst <0xC0, (ops RST:$op),
                             "fadd $op">;
def FADDrST0   : FPrST0Inst <0xC0, (ops RST:$op),
                             "fadd {%ST(0), $op|$op, %ST(0)}">;
def FADDPrST0  : FPrST0PInst<0xC0, (ops RST:$op),
                             "faddp $op">;

// 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 FSUBRST0r  : FPST0rInst <0xE8, (ops RST:$op),
                             "fsubr $op">;
def FSUBrST0   : FPrST0Inst <0xE8, (ops RST:$op),
                             "fsub{r} {%ST(0), $op|$op, %ST(0)}">;
def FSUBPrST0  : FPrST0PInst<0xE8, (ops RST:$op),

def FSUBST0r   : FPST0rInst <0xE0, (ops RST:$op),
                             "fsub $op">;
def FSUBRrST0  : FPrST0Inst <0xE0, (ops RST:$op),
                             "fsub{|r} {%ST(0), $op|$op, %ST(0)}">;
def FSUBRPrST0 : FPrST0PInst<0xE0, (ops RST:$op),

def FMULST0r   : FPST0rInst <0xC8, (ops RST:$op),
                             "fmul $op">;
def FMULrST0   : FPrST0Inst <0xC8, (ops RST:$op),
                             "fmul {%ST(0), $op|$op, %ST(0)}">;
def FMULPrST0  : FPrST0PInst<0xC8, (ops RST:$op),
                             "fmulp $op">;

def FDIVRST0r  : FPST0rInst <0xF8, (ops RST:$op),
                             "fdivr $op">;
def FDIVrST0   : FPrST0Inst <0xF8, (ops RST:$op),
                             "fdiv{r} {%ST(0), $op|$op, %ST(0)}">;
def FDIVPrST0  : FPrST0PInst<0xF8, (ops RST:$op),

def FDIVST0r   : FPST0rInst <0xF0, (ops RST:$op),  // ST(0) = ST(0) / ST(i)
                             "fdiv $op">;
def FDIVRrST0  : FPrST0Inst <0xF0, (ops RST:$op),  // ST(i) = ST(0) / ST(i)
                             "fdiv{|r} {%ST(0), $op|$op, %ST(0)}">;
def FDIVRPrST0 : FPrST0PInst<0xF0, (ops RST:$op),  // ST(i) = ST(0) / ST(i), pop

// Floating point compares
def FUCOMr    : FPI<0xE0, AddRegFrm, CompareFP,   // FPSW = cmp ST(0) with ST(i)
                    (ops RST:$reg, variable_ops),
                    "fucom $reg", []>, DD, Imp<[ST0],[]>;
def FUCOMPr   : I<0xE8, AddRegFrm,           // FPSW = cmp ST(0) with ST(i), pop
                  (ops RST:$reg, variable_ops),
Evan Cheng's avatar
Evan Cheng committed
                  "fucomp $reg", []>, DD, Imp<[ST0],[]>;
def FUCOMPPr  : I<0xE9, RawFrm,                // cmp ST(0) with ST(1), pop, pop
                  (ops variable_ops),
Evan Cheng's avatar
Evan Cheng committed
                  "fucompp", []>, DA, Imp<[ST0],[]>;

def FUCOMIr  : FPI<0xE8, AddRegFrm, CompareFP,  // CC = cmp ST(0) with ST(i)
                   (ops RST:$reg, variable_ops),
                   "fucomi {$reg, %ST(0)|%ST(0), $reg}", []>, DB, Imp<[ST0],[]>;
def FUCOMIPr : I<0xE8, AddRegFrm,              // CC = cmp ST(0) with ST(i), pop
                 (ops RST:$reg, variable_ops),
Evan Cheng's avatar
Evan Cheng committed
                 "fucomip {$reg, %ST(0)|%ST(0), $reg}", []>, DF, Imp<[ST0],[]>;
// Floating point flag ops
def FNSTSW8r  : I<0xE0, RawFrm,                  // AX = fp flags
Evan Cheng's avatar
Evan Cheng committed
                  (ops), "fnstsw", []>, DF, Imp<[],[AX]>;
def FNSTCW16m : I<0xD9, MRM7m,                   // [mem16] = X87 control world
Evan Cheng's avatar
Evan Cheng committed
                  (ops i16mem:$dst), "fnstcw $dst", []>;
def FLDCW16m  : I<0xD9, MRM5m,                   // X87 control world = [mem16]
Evan Cheng's avatar
Evan Cheng committed
                  (ops i16mem:$dst), "fldcw $dst", []>;