Skip to content
X86InstrInfo.td 154 KiB
Newer Older
def SBB32ri  : Ii32<0x81, MRM3r, (ops R32:$dst, R32:$src1, i32imm:$src2),
                    "sbb{l} {$src2, $dst|$dst, $src2}",
                    [(set R32:$dst, (X86sbb R32:$src1, imm:$src2))]>;
def SBB16ri8 : Ii8<0x83, MRM3r, (ops R16:$dst, R16:$src1, i16i8imm:$src2),
                   "sbb{w} {$src2, $dst|$dst, $src2}",
                   [(set R16:$dst, (X86sbb R16:$src1, i16immSExt8:$src2))]>,
                   OpSize;
def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i32i8imm:$src2),
                   "sbb{l} {$src2, $dst|$dst, $src2}",
                   [(set R32:$dst, (X86sbb R32:$src1, i32immSExt8:$src2))]>;
let isCommutable = 1 in {  // X = IMUL Y, Z --> X = IMUL Z, Y
def IMUL16rr : I<0xAF, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
Evan Cheng's avatar
Evan Cheng committed
                 "imul{w} {$src2, $dst|$dst, $src2}",
                 [(set R16:$dst, (mul R16:$src1, R16:$src2))]>, TB, OpSize;
def IMUL32rr : I<0xAF, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
Evan Cheng's avatar
Evan Cheng committed
                 "imul{l} {$src2, $dst|$dst, $src2}",
                 [(set R32:$dst, (mul R32:$src1, R32:$src2))]>, TB;
def IMUL16rm : I<0xAF, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
                 "imul{w} {$src2, $dst|$dst, $src2}",
                 [(set R16:$dst, (mul R16:$src1, (load addr:$src2)))]>,
                 TB, OpSize;
def IMUL32rm : I<0xAF, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
                 "imul{l} {$src2, $dst|$dst, $src2}",
                 [(set R32:$dst, (mul R32:$src1, (load addr:$src2)))]>, TB;
// Suprisingly enough, these are not two address instructions!
def IMUL16rri  : Ii16<0x69, MRMSrcReg,                      // R16 = R16*I16
                      (ops R16:$dst, R16:$src1, i16imm:$src2),
                      "imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}",
                      [(set R16:$dst, (mul R16:$src1, imm:$src2))]>, OpSize;
def IMUL32rri  : Ii32<0x69, MRMSrcReg,                      // R32 = R32*I32
                      (ops R32:$dst, R32:$src1, i32imm:$src2),
                      "imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}",
                      [(set R32:$dst, (mul R32:$src1, imm:$src2))]>;
def IMUL16rri8 : Ii8<0x6B, MRMSrcReg,                       // R16 = R16*I8
                     (ops R16:$dst, R16:$src1, i16i8imm:$src2),
                     "imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}",
                     [(set R16:$dst, (mul R16:$src1, i16immSExt8:$src2))]>,
                     OpSize;
def IMUL32rri8 : Ii8<0x6B, MRMSrcReg,                       // R32 = R32*I8
                     (ops R32:$dst, R32:$src1, i32i8imm:$src2),
                     "imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}",
                     [(set R32:$dst, (mul R32:$src1, i32immSExt8:$src2))]>;

def IMUL16rmi  : Ii16<0x69, MRMSrcMem,                      // R16 = [mem16]*I16
                      (ops R16:$dst, i16mem:$src1, i16imm:$src2),
                      "imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}",
                      [(set R16:$dst, (mul (load addr:$src1), imm:$src2))]>,
                      OpSize;
def IMUL32rmi  : Ii32<0x69, MRMSrcMem,                      // R32 = [mem32]*I32
                      (ops R32:$dst, i32mem:$src1, i32imm:$src2),
                      "imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}",
                      [(set R32:$dst, (mul (load addr:$src1), imm:$src2))]>;
def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem,                       // R16 = [mem16]*I8
                     (ops R16:$dst, i16mem:$src1, i16i8imm :$src2),
                     "imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}",
                  [(set R16:$dst, (mul (load addr:$src1), i16immSExt8:$src2))]>,
                     OpSize;
def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem,                       // R32 = [mem32]*I8
                     (ops R32:$dst, i32mem:$src1, i32i8imm: $src2),
                     "imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}",
                  [(set R32:$dst, (mul (load addr:$src1), i32immSExt8:$src2))]>;
//===----------------------------------------------------------------------===//
// Test instructions are just like AND, except they don't generate a result.
Chris Lattner's avatar
Chris Lattner committed
let isCommutable = 1 in {   // TEST X, Y   --> TEST Y, X
def TEST8rr  : I<0x84, MRMDestReg, (ops R8:$src1, R8:$src2),
                 "test{b} {$src2, $src1|$src1, $src2}",
def TEST16rr : I<0x85, MRMDestReg, (ops R16:$src1, R16:$src2),
                 "test{w} {$src2, $src1|$src1, $src2}",
                 [(X86test R16:$src1, R16:$src2)]>, OpSize;
def TEST32rr : I<0x85, MRMDestReg, (ops R32:$src1, R32:$src2),
                 "test{l} {$src2, $src1|$src1, $src2}",
Chris Lattner's avatar
Chris Lattner committed
}
def TEST8mr  : I<0x84, MRMDestMem, (ops i8mem :$src1, R8 :$src2),
                 "test{b} {$src2, $src1|$src1, $src2}",
                 [(X86test (loadi8 addr:$src1), R8:$src2)]>;
def TEST16mr : I<0x85, MRMDestMem, (ops i16mem:$src1, R16:$src2),
                 "test{w} {$src2, $src1|$src1, $src2}",
                 [(X86test (loadi16 addr:$src1), R16:$src2)]>,
               OpSize;
def TEST32mr : I<0x85, MRMDestMem, (ops i32mem:$src1, R32:$src2),
                 "test{l} {$src2, $src1|$src1, $src2}",
                 [(X86test (loadi32 addr:$src1), R32:$src2)]>;
def TEST8rm  : I<0x84, MRMSrcMem, (ops R8 :$src1, i8mem :$src2),
                 "test{b} {$src2, $src1|$src1, $src2}",
                 [(X86test R8:$src1, (loadi8 addr:$src2))]>;
def TEST16rm : I<0x85, MRMSrcMem, (ops R16:$src1, i16mem:$src2),
                 "test{w} {$src2, $src1|$src1, $src2}",
                 [(X86test R16:$src1, (loadi16 addr:$src2))]>,
               OpSize;
def TEST32rm : I<0x85, MRMSrcMem, (ops R32:$src1, i32mem:$src2),
                 "test{l} {$src2, $src1|$src1, $src2}",
                 [(X86test R32:$src1, (loadi32 addr:$src2))]>;
def TEST8ri  : Ii8 <0xF6, MRM0r,                     // flags = R8  & imm8
                    (ops R8:$src1, i8imm:$src2),
                    "test{b} {$src2, $src1|$src1, $src2}",
def TEST16ri : Ii16<0xF7, MRM0r,                     // flags = R16 & imm16
                    (ops R16:$src1, i16imm:$src2),
                    "test{w} {$src2, $src1|$src1, $src2}",
                    [(X86test R16:$src1, imm:$src2)]>, OpSize;
def TEST32ri : Ii32<0xF7, MRM0r,                     // flags = R32 & imm32
                    (ops R32:$src1, i32imm:$src2),
                    "test{l} {$src2, $src1|$src1, $src2}",
def TEST8mi  : Ii8 <0xF6, MRM0m,                     // flags = [mem8]  & imm8
                    (ops i8mem:$src1, i8imm:$src2),
                    "test{b} {$src2, $src1|$src1, $src2}",
                    [(X86test (loadi8 addr:$src1), imm:$src2)]>;
def TEST16mi : Ii16<0xF7, MRM0m,                     // flags = [mem16] & imm16
                    (ops i16mem:$src1, i16imm:$src2),
                    "test{w} {$src2, $src1|$src1, $src2}",
                    [(X86test (loadi16 addr:$src1), imm:$src2)]>,
               OpSize;
def TEST32mi : Ii32<0xF7, MRM0m,                     // flags = [mem32] & imm32
                    (ops i32mem:$src1, i32imm:$src2),
                    "test{l} {$src2, $src1|$src1, $src2}",
                    [(X86test (loadi32 addr:$src1), imm:$src2)]>;
// Condition code ops, incl. set if equal/not equal/...
Evan Cheng's avatar
Evan Cheng committed
def SAHF     : I<0x9E, RawFrm, (ops), "sahf", []>, Imp<[AH],[]>;  // flags = AH
def LAHF     : I<0x9F, RawFrm, (ops), "lahf", []>, Imp<[],[AH]>;  // AH = flags
Evan Cheng's avatar
Evan Cheng committed
                 "sete $dst",
                 [(set R8:$dst, (X86setcc X86_COND_E))]>,
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "sete $dst",
                 [(store (X86setcc X86_COND_E), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed
                 "setne $dst",
                 [(set R8:$dst, (X86setcc X86_COND_NE))]>,
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setne $dst",
                 [(store (X86setcc X86_COND_NE), addr:$dst)]>,
               TB;                        // [mem8] = !=
def SETLr    : I<0x9C, MRM0r, 
                 (ops R8   :$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setl $dst",
                 [(set R8:$dst, (X86setcc X86_COND_L))]>,
               TB;                        // R8 = <  signed
def SETLm    : I<0x9C, MRM0m, 
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setl $dst",
                 [(store (X86setcc X86_COND_L), addr:$dst)]>,
               TB;                        // [mem8] = <  signed
def SETGEr   : I<0x9D, MRM0r, 
                 (ops R8   :$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setge $dst",
                 [(set R8:$dst, (X86setcc X86_COND_GE))]>,
               TB;                        // R8 = >= signed
def SETGEm   : I<0x9D, MRM0m, 
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setge $dst",
                 [(store (X86setcc X86_COND_GE), addr:$dst)]>,
               TB;                        // [mem8] = >= signed
def SETLEr   : I<0x9E, MRM0r, 
                 (ops R8   :$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setle $dst",
                 [(set R8:$dst, (X86setcc X86_COND_LE))]>,
               TB;                        // R8 = <= signed
def SETLEm   : I<0x9E, MRM0m, 
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setle $dst",
                 [(store (X86setcc X86_COND_LE), addr:$dst)]>,
               TB;                        // [mem8] = <= signed
def SETGr    : I<0x9F, MRM0r, 
                 (ops R8   :$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setg $dst",
                 [(set R8:$dst, (X86setcc X86_COND_G))]>,
               TB;                        // R8 = >  signed
def SETGm    : I<0x9F, MRM0m, 
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setg $dst",
                 [(store (X86setcc X86_COND_G), addr:$dst)]>,
               TB;                        // [mem8] = >  signed

def SETBr    : I<0x92, MRM0r,
                 (ops R8   :$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setb $dst",
                 [(set R8:$dst, (X86setcc X86_COND_B))]>,
               TB;                        // R8 = <  unsign
def SETBm    : I<0x92, MRM0m,
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setb $dst",
                 [(store (X86setcc X86_COND_B), addr:$dst)]>,
               TB;                        // [mem8] = <  unsign
def SETAEr   : I<0x93, MRM0r, 
                 (ops R8   :$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setae $dst",
                 [(set R8:$dst, (X86setcc X86_COND_AE))]>,
               TB;                        // R8 = >= unsign
def SETAEm   : I<0x93, MRM0m, 
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setae $dst",
                 [(store (X86setcc X86_COND_AE), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed
                 "setbe $dst",
                 [(set R8:$dst, (X86setcc X86_COND_BE))]>,
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setbe $dst",
                 [(store (X86setcc X86_COND_BE), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed
                 "seta $dst",
                 [(set R8:$dst, (X86setcc X86_COND_A))]>,
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "seta $dst",
                 [(store (X86setcc X86_COND_A), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed

Evan Cheng's avatar
Evan Cheng committed
                 "sets $dst",
                 [(set R8:$dst, (X86setcc X86_COND_S))]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // R8 = <sign bit>
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "sets $dst",
                 [(store (X86setcc X86_COND_S), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // [mem8] = <sign bit>
Evan Cheng's avatar
Evan Cheng committed
                 "setns $dst",
                 [(set R8:$dst, (X86setcc X86_COND_NS))]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // R8 = !<sign bit>
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setns $dst",
                 [(store (X86setcc X86_COND_NS), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // [mem8] = !<sign bit>
Evan Cheng's avatar
Evan Cheng committed
                 "setp $dst",
                 [(set R8:$dst, (X86setcc X86_COND_P))]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // R8 = parity
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setp $dst",
                 [(store (X86setcc X86_COND_P), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // [mem8] = parity
Chris Lattner's avatar
Chris Lattner committed
def SETNPr   : I<0x9B, MRM0r, 
Evan Cheng's avatar
Evan Cheng committed
                 "setnp $dst",
                 [(set R8:$dst, (X86setcc X86_COND_NP))]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // R8 = not parity
Chris Lattner's avatar
Chris Lattner committed
def SETNPm   : I<0x9B, MRM0m, 
                 (ops i8mem:$dst),
Evan Cheng's avatar
Evan Cheng committed
                 "setnp $dst",
                 [(store (X86setcc X86_COND_NP), addr:$dst)]>,
Evan Cheng's avatar
Evan Cheng committed
               TB;                        // [mem8] = not parity

// Integer comparisons
def CMP8rr  : I<0x38, MRMDestReg,
                (ops R8 :$src1, R8 :$src2),
                "cmp{b} {$src2, $src1|$src1, $src2}",
def CMP16rr : I<0x39, MRMDestReg,
                (ops R16:$src1, R16:$src2),
                "cmp{w} {$src2, $src1|$src1, $src2}",
                [(X86cmp R16:$src1, R16:$src2)]>, OpSize;
def CMP32rr : I<0x39, MRMDestReg,
                (ops R32:$src1, R32:$src2),
                "cmp{l} {$src2, $src1|$src1, $src2}",
def CMP8mr  : I<0x38, MRMDestMem,
                (ops i8mem :$src1, R8 :$src2),
                "cmp{b} {$src2, $src1|$src1, $src2}",
                [(X86cmp (loadi8 addr:$src1), R8:$src2)]>;
def CMP16mr : I<0x39, MRMDestMem,
                (ops i16mem:$src1, R16:$src2),
                "cmp{w} {$src2, $src1|$src1, $src2}",
                [(X86cmp (loadi16 addr:$src1), R16:$src2)]>, OpSize;
def CMP32mr : I<0x39, MRMDestMem,
                (ops i32mem:$src1, R32:$src2),
                "cmp{l} {$src2, $src1|$src1, $src2}",
                [(X86cmp (loadi32 addr:$src1), R32:$src2)]>;
def CMP8rm  : I<0x3A, MRMSrcMem,
                (ops R8 :$src1, i8mem :$src2),
                "cmp{b} {$src2, $src1|$src1, $src2}",
                [(X86cmp R8:$src1, (loadi8 addr:$src2))]>;
def CMP16rm : I<0x3B, MRMSrcMem,
                (ops R16:$src1, i16mem:$src2),
                "cmp{w} {$src2, $src1|$src1, $src2}",
                [(X86cmp R16:$src1, (loadi16 addr:$src2))]>, OpSize;
def CMP32rm : I<0x3B, MRMSrcMem,
                (ops R32:$src1, i32mem:$src2),
                "cmp{l} {$src2, $src1|$src1, $src2}",
                [(X86cmp R32:$src1, (loadi32 addr:$src2))]>;
                  (ops R8:$src1, i8imm:$src2),
                  "cmp{b} {$src2, $src1|$src1, $src2}",
def CMP16ri : Ii16<0x81, MRM7r,
                   (ops R16:$src1, i16imm:$src2),
                   "cmp{w} {$src2, $src1|$src1, $src2}",
                   [(X86cmp R16:$src1, imm:$src2)]>, OpSize;
def CMP32ri : Ii32<0x81, MRM7r,
                   (ops R32:$src1, i32imm:$src2),
                   "cmp{l} {$src2, $src1|$src1, $src2}",
def CMP8mi  : Ii8 <0x80, MRM7m,
                   (ops i8mem :$src1, i8imm :$src2),
                   "cmp{b} {$src2, $src1|$src1, $src2}",
                   [(X86cmp (loadi8 addr:$src1), imm:$src2)]>;
def CMP16mi : Ii16<0x81, MRM7m,
                   (ops i16mem:$src1, i16imm:$src2),
                   "cmp{w} {$src2, $src1|$src1, $src2}",
                   [(X86cmp (loadi16 addr:$src1), imm:$src2)]>, OpSize;
def CMP32mi : Ii32<0x81, MRM7m,
                   (ops i32mem:$src1, i32imm:$src2),
                   "cmp{l} {$src2, $src1|$src1, $src2}",
                   [(X86cmp (loadi32 addr:$src1), imm:$src2)]>;

// Sign/Zero extenders
def MOVSX16rr8 : I<0xBE, MRMSrcReg, (ops R16:$dst, R8 :$src),
Evan Cheng's avatar
Evan Cheng committed
                   "movs{bw|x} {$src, $dst|$dst, $src}",
                   [(set R16:$dst, (sext R8:$src))]>, TB, OpSize;
def MOVSX16rm8 : I<0xBE, MRMSrcMem, (ops R16:$dst, i8mem :$src),
                   "movs{bw|x} {$src, $dst|$dst, $src}",
                   [(set R16:$dst, (sextloadi16i8 addr:$src))]>, TB, OpSize;
def MOVSX32rr8 : I<0xBE, MRMSrcReg, (ops R32:$dst, R8 :$src),
Evan Cheng's avatar
Evan Cheng committed
                   "movs{bl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (sext R8:$src))]>, TB;
def MOVSX32rm8 : I<0xBE, MRMSrcMem, (ops R32:$dst, i8mem :$src),
                   "movs{bl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (sextloadi32i8 addr:$src))]>, TB;
def MOVSX32rr16: I<0xBF, MRMSrcReg, (ops R32:$dst, R16:$src),
Evan Cheng's avatar
Evan Cheng committed
                   "movs{wl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (sext R16:$src))]>, TB;
def MOVSX32rm16: I<0xBF, MRMSrcMem, (ops R32:$dst, i16mem:$src),
                   "movs{wl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (sextloadi32i16 addr:$src))]>, TB;

def MOVZX16rr8 : I<0xB6, MRMSrcReg, (ops R16:$dst, R8 :$src),
Evan Cheng's avatar
Evan Cheng committed
                   "movz{bw|x} {$src, $dst|$dst, $src}",
                   [(set R16:$dst, (zext R8:$src))]>, TB, OpSize;
def MOVZX16rm8 : I<0xB6, MRMSrcMem, (ops R16:$dst, i8mem :$src),
                   "movz{bw|x} {$src, $dst|$dst, $src}",
                   [(set R16:$dst, (zextloadi16i8 addr:$src))]>, TB, OpSize;
def MOVZX32rr8 : I<0xB6, MRMSrcReg, (ops R32:$dst, R8 :$src),
Evan Cheng's avatar
Evan Cheng committed
                   "movz{bl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (zext R8:$src))]>, TB;
def MOVZX32rm8 : I<0xB6, MRMSrcMem, (ops R32:$dst, i8mem :$src),
                   "movz{bl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (zextloadi32i8 addr:$src))]>, TB;
def MOVZX32rr16: I<0xB7, MRMSrcReg, (ops R32:$dst, R16:$src),
Evan Cheng's avatar
Evan Cheng committed
                   "movz{wl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (zext R16:$src))]>, TB;
def MOVZX32rm16: I<0xB7, MRMSrcMem, (ops R32:$dst, i16mem:$src),
                   "movz{wl|x} {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (zextloadi32i16 addr:$src))]>, TB;

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

def MOVSSrr : I<0x10, MRMSrcReg, (ops FR32:$dst, FR32:$src),
                "movss {$src, $dst|$dst, $src}", []>,
              Requires<[HasSSE1]>, XS;
def MOVSDrr : I<0x10, MRMSrcReg, (ops FR64:$dst, FR64:$src),
                "movsd {$src, $dst|$dst, $src}", []>,
              Requires<[HasSSE2]>, XD;
def MOVSSrm : I<0x10, MRMSrcMem, (ops FR32:$dst, f32mem:$src),
                "movss {$src, $dst|$dst, $src}",
                [(set FR32:$dst, (loadf32 addr:$src))]>,
              Requires<[HasSSE1]>, XS;
def MOVSSmr : I<0x11, MRMDestMem, (ops f32mem:$dst, FR32:$src),
                "movss {$src, $dst|$dst, $src}",
                [(store FR32:$src, addr:$dst)]>,
              Requires<[HasSSE1]>, 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 CVTTSS2SIrr: I<0x2C, MRMSrcReg, (ops R32:$dst, FR32:$src),
                   "cvttss2si {$src, $dst|$dst, $src}",
                   [(set R32:$dst, (fp_to_sint FR32:$src))]>,
                 Requires<[HasSSE1]>, 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<[HasSSE1]>, XS;
def CVTTSD2SIrr: I<0x2C, MRMSrcReg, (ops R32:$dst, FR64:$src),
                   "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 CVTSS2SDrr: I<0x5A, MRMSrcReg, (ops FR64:$dst, FR32:$src),
                  "cvtss2sd {$src, $dst|$dst, $src}",
                  [(set FR64:$dst, (fextend FR32:$src))]>,
                Requires<[HasSSE2]>, XS;
def CVTSS2SDrm: I<0x5A, MRMSrcMem, (ops FR64:$dst, f32mem:$src),
                  "cvtss2sd {$src, $dst|$dst, $src}",
                  [(set FR64:$dst, (fextend (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]>, XD;
def CVTSD2SSrm: I<0x5A, MRMSrcMem, (ops FR32:$dst, f64mem:$src), 
                  "cvtsd2ss {$src, $dst|$dst, $src}",
                  [(set FR32:$dst, (fround (loadf64 addr:$src)))]>,
                Requires<[HasSSE2]>, XD;
def CVTSI2SSrr: I<0x2A, MRMSrcReg, (ops FR32:$dst, R32:$src),
                  "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),
                  "cvtsi2sd {$src, $dst|$dst, $src}",
                  [(set FR64:$dst, (sint_to_fp (loadi32 addr:$src)))]>,
def SQRTSSrr : I<0x51, MRMSrcReg, (ops FR32:$dst, FR32:$src),
                 "sqrtss {$src, $dst|$dst, $src}",
                 [(set FR32:$dst, (fsqrt FR32:$src))]>,
               Requires<[HasSSE1]>, XS;
def SQRTSSrm : I<0x51, MRMSrcMem, (ops FR32:$dst, f32mem:$src),
                 "sqrtss {$src, $dst|$dst, $src}",
                 [(set FR32:$dst, (fsqrt (loadf32 addr:$src)))]>,
               Requires<[HasSSE1]>, XS;
def SQRTSDrr : I<0x51, MRMSrcReg, (ops FR64:$dst, FR64:$src),
                 "sqrtsd {$src, $dst|$dst, $src}",
                 [(set FR64:$dst, (fsqrt FR64:$src))]>,
               Requires<[HasSSE2]>, XD;
def SQRTSDrm : I<0x51, MRMSrcMem, (ops FR64:$dst, f64mem:$src),
                 "sqrtsd {$src, $dst|$dst, $src}",
                 [(set FR64:$dst, (fsqrt (loadf64 addr:$src)))]>,
               Requires<[HasSSE2]>, XD;
Evan Cheng's avatar
Evan Cheng committed
def UCOMISSrr: I<0x2E, MRMSrcReg, (ops FR32:$src1, FR32:$src2),
                 "ucomiss {$src2, $src1|$src1, $src2}",
                 [(X86cmp FR32:$src1, FR32:$src2)]>,
               Requires<[HasSSE1]>, TB;
Evan Cheng's avatar
Evan Cheng committed
def UCOMISSrm: I<0x2E, MRMSrcMem, (ops FR32:$src1, f32mem:$src2),
                 "ucomiss {$src2, $src1|$src1, $src2}",
                 [(X86cmp FR32:$src1, (loadf32 addr:$src2))]>,
               Requires<[HasSSE1]>, TB;
def UCOMISDrr: I<0x2E, MRMSrcReg, (ops FR64:$src1, FR64:$src2),
                 "ucomisd {$src2, $src1|$src1, $src2}",
                 [(X86cmp FR64:$src1, FR64:$src2)]>,
               Requires<[HasSSE2]>, TB, OpSize;
def UCOMISDrm: I<0x2E, MRMSrcMem, (ops FR64:$src1, f64mem:$src2),
                 "ucomisd {$src2, $src1|$src1, $src2}",
                 [(X86cmp FR64:$src1, (loadf64 addr:$src2))]>,
               Requires<[HasSSE2]>, TB, OpSize;
// Pseudo-instructions that map fld0 to pxor for sse.
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
def FLD0SS : I<0xEF, MRMInitReg, (ops FR32:$dst),
               "pxor $dst, $dst", [(set FR32:$dst, fp32imm0)]>,
Evan Cheng's avatar
Evan Cheng committed
             Requires<[HasSSE1]>, TB;
def FLD0SD : I<0xEF, MRMInitReg, (ops FR64:$dst),
               "pxor $dst, $dst", [(set FR64:$dst, fp64imm0)]>,
Evan Cheng's avatar
Evan Cheng committed
             Requires<[HasSSE2]>, TB, OpSize;
// SSE Scalar Arithmetic
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))]>,
              Requires<[HasSSE1]>, 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))]>,
              Requires<[HasSSE2]>, XD;
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))]>,
              Requires<[HasSSE1]>, 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))]>,
              Requires<[HasSSE2]>, XD;
def ADDSSrm : I<0x58, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
                "addss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fadd FR32:$src1, (loadf32 addr:$src2)))]>,
              Requires<[HasSSE1]>, XS;
def ADDSDrm : I<0x58, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
                "addsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fadd FR64:$src1, (loadf64 addr:$src2)))]>,
              Requires<[HasSSE2]>, XD;
def MULSSrm : I<0x59, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
                "mulss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fmul FR32:$src1, (loadf32 addr:$src2)))]>,
              Requires<[HasSSE1]>, XS;
def MULSDrm : I<0x59, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
                "mulsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fmul FR64:$src1, (loadf64 addr:$src2)))]>,
              Requires<[HasSSE2]>, XD;
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))]>,
              Requires<[HasSSE1]>, XS;
def DIVSSrm : I<0x5E, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
                "divss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fdiv FR32:$src1, (loadf32 addr:$src2)))]>,
              Requires<[HasSSE1]>, XS;
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))]>,
              Requires<[HasSSE2]>, XD;
def DIVSDrm : I<0x5E, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
                "divsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fdiv FR64:$src1, (loadf64 addr:$src2)))]>,
              Requires<[HasSSE2]>, XD;
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))]>,
              Requires<[HasSSE1]>, XS;
def SUBSSrm : I<0x5C, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f32mem:$src2),
                "subss {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (fsub FR32:$src1, (loadf32 addr:$src2)))]>,
              Requires<[HasSSE1]>, XS;
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))]>,
              Requires<[HasSSE2]>, XD;
def SUBSDrm : I<0x5C, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f64mem:$src2),
                "subsd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (fsub FR64:$src1, (loadf64 addr:$src2)))]>,
              Requires<[HasSSE2]>, XD;

// SSE compare
def CMPSSrr : I<0xC2, MRMSrcReg, 
                (ops FR32:$dst, FR32:$src1, FR32:$src, SSECC:$cc),
                "cmp${cc}ss {$src, $dst|$dst, $src}", []>,
              Requires<[HasSSE1]>, XS;
def CMPSSrm : I<0xC2, MRMSrcMem, 
                (ops FR32:$dst, FR32:$src1, f32mem:$src, SSECC:$cc),
                "cmp${cc}ss {$src, $dst|$dst, $src}", []>,
              Requires<[HasSSE1]>, XS;
def CMPSDrr : I<0xC2, MRMSrcReg, 
                (ops FR64:$dst, FR64:$src1, FR64:$src, SSECC:$cc),
                "cmp${cc}sd {$src, $dst|$dst, $src}", []>,
              Requires<[HasSSE1]>, XD;
def CMPSDrm : I<0xC2, MRMSrcMem, 
                (ops FR64:$dst, FR64:$src1, f64mem:$src, SSECC:$cc),
                "cmp${cc}sd {$src, $dst|$dst, $src}", []>,
              Requires<[HasSSE2]>, XD;

// SSE Logical - these all operate on packed values
let isCommutable = 1 in {
def ANDPSrr : I<0x54, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
                "andps {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (X86fand FR32:$src1, FR32:$src2))]>,
              Requires<[HasSSE1]>, TB;
def ANDPDrr : I<0x54, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
                "andpd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (X86fand FR64:$src1, FR64:$src2))]>,
              Requires<[HasSSE2]>, TB, OpSize;
def ORPSrr : I<0x56, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
                "orps {$src2, $dst|$dst, $src2}", []>,
             Requires<[HasSSE1]>, TB;
def ORPDrr : I<0x56, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
                "orpd {$src2, $dst|$dst, $src2}", []>,
             Requires<[HasSSE2]>, TB, OpSize;
def XORPSrr : I<0x57, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
                "xorps {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (X86fxor FR32:$src1, FR32:$src2))]>,
              Requires<[HasSSE1]>, TB;
def XORPDrr : I<0x57, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
                "xorpd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (X86fxor FR64:$src1, FR64:$src2))]>,
              Requires<[HasSSE2]>, TB, OpSize;
}
def ANDPSrm : I<0x54, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
                "andps {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (X86fand FR32:$src1,
                                  (X86loadpf32 addr:$src2)))]>,
              Requires<[HasSSE1]>, TB;
def ANDPDrm : I<0x54, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
                "andpd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (X86fand FR64:$src1,
                                  (X86loadpf64 addr:$src2)))]>,
              Requires<[HasSSE2]>, TB, OpSize;
def ORPSrm : I<0x56, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
                "orps {$src2, $dst|$dst, $src2}", []>,
             Requires<[HasSSE1]>, TB;
def ORPDrm : I<0x56, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
                "orpd {$src2, $dst|$dst, $src2}", []>,
             Requires<[HasSSE2]>, TB, OpSize;
def XORPSrm : I<0x57, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
                "xorps {$src2, $dst|$dst, $src2}",
                [(set FR32:$dst, (X86fxor FR32:$src1,
                                  (X86loadpf32 addr:$src2)))]>,
              Requires<[HasSSE1]>, TB;
def XORPDrm : I<0x57, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
                "xorpd {$src2, $dst|$dst, $src2}",
                [(set FR64:$dst, (X86fxor FR64:$src1,
                                  (X86loadpf64 addr:$src2)))]>,
              Requires<[HasSSE2]>, TB, OpSize;

def ANDNPSrr : I<0x55, MRMSrcReg, (ops FR32:$dst, FR32:$src1, FR32:$src2),
                "andnps {$src2, $dst|$dst, $src2}", []>,
               Requires<[HasSSE1]>, TB;
def ANDNPSrm : I<0x55, MRMSrcMem, (ops FR32:$dst, FR32:$src1, f128mem:$src2),
                "andnps {$src2, $dst|$dst, $src2}", []>,
               Requires<[HasSSE1]>, TB;
def ANDNPDrr : I<0x55, MRMSrcReg, (ops FR64:$dst, FR64:$src1, FR64:$src2),
                "andnpd {$src2, $dst|$dst, $src2}", []>,
               Requires<[HasSSE2]>, TB, OpSize;
def ANDNPDrm : I<0x55, MRMSrcMem, (ops FR64:$dst, FR64:$src1, f128mem:$src2),
                "andnpd {$src2, $dst|$dst, $src2}", []>,
               Requires<[HasSSE2]>, TB, OpSize;

//===----------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed
// Floating Point Stack Support
//===----------------------------------------------------------------------===//

// Floating point support.  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, []> {}
Evan Cheng's avatar
Evan Cheng committed
// 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;
}

Evan Cheng's avatar
Evan Cheng committed
def FpGETRESULT : FpI_<(ops RFP:$dst), SpecialFP,
                  [(set RFP:$dst, X86fpget)]>;                    // FPR = ST(0)
Evan Cheng's avatar
Evan Cheng committed
  def FpSETRESULT : FpI_<(ops RFP:$src), SpecialFP,
                        [(X86fpset RFP:$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]>;
def FpMOV       : FpI<(ops RFP:$dst, RFP:$src), SpecialFP, []>; // f1 = fmov f2
// Arithmetic
// Add, Sub, Mul, Div.
def FpADD : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
                [(set RFP:$dst, (fadd RFP:$src1, RFP:$src2))]>;
def FpSUB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
                [(set RFP:$dst, (fsub RFP:$src1, RFP:$src2))]>;
def FpMUL : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
                [(set RFP:$dst, (fmul RFP:$src1, RFP:$src2))]>;
def FpDIV : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP,
                [(set RFP:$dst, (fdiv RFP:$src1, RFP:$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 RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fadd RFP:$src1,
                                     (extloadf64f32 addr:$src2)))]>;
                // ST(0) = ST(0) + [mem32]
Evan Cheng's avatar
Evan Cheng committed
def FpADD64m  : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fadd RFP:$src1, (loadf64 addr:$src2)))]>;
                // ST(0) = ST(0) + [mem64]
def FpMUL32m  : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fmul RFP:$src1,
                                     (extloadf64f32 addr:$src2)))]>;
                // ST(0) = ST(0) * [mem32]
Evan Cheng's avatar
Evan Cheng committed
def FpMUL64m  : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fmul RFP:$src1, (loadf64 addr:$src2)))]>;
                // ST(0) = ST(0) * [mem64]
def FpSUB32m  : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fsub RFP:$src1,
                                    (extloadf64f32 addr:$src2)))]>;
                // ST(0) = ST(0) - [mem32]
Evan Cheng's avatar
Evan Cheng committed
def FpSUB64m  : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fsub RFP:$src1, (loadf64 addr:$src2)))]>;
                // ST(0) = ST(0) - [mem64]
def FpSUBR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
Evan Cheng's avatar
Evan Cheng committed
                    [(set RFP:$dst, (fsub (extloadf64f32 addr:$src2),
                                     RFP:$src1))]>;
                // ST(0) = [mem32] - ST(0)
Evan Cheng's avatar
Evan Cheng committed
def FpSUBR64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fsub (loadf64 addr:$src2), RFP:$src1))]>;
                // ST(0) = [mem64] - ST(0)
def FpDIV32m  : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fdiv RFP:$src1,
                                    (extloadf64f32 addr:$src2)))]>;
                // ST(0) = ST(0) / [mem32]
Evan Cheng's avatar
Evan Cheng committed
def FpDIV64m  : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fdiv RFP:$src1, (loadf64 addr:$src2)))]>;
                // ST(0) = ST(0) / [mem64]
def FpDIVR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fdiv (extloadf64f32 addr:$src2),
                                     RFP:$src1))]>;
                // ST(0) = [mem32] / ST(0)
Evan Cheng's avatar
Evan Cheng committed
def FpDIVR64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fdiv (loadf64 addr:$src2), RFP:$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">;

Evan Cheng's avatar
Evan Cheng committed
def FpIADD16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fadd RFP:$src1,
                                     (X86fild addr:$src2, i16)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) + [mem16int]
Evan Cheng's avatar
Evan Cheng committed
def FpIADD32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
Evan Cheng's avatar
Evan Cheng committed
                    [(set RFP:$dst, (fadd RFP:$src1,
                                     (X86fild addr:$src2, i32)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) + [mem32int]
def FpIMUL16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fmul RFP:$src1,
                                     (X86fild addr:$src2, i16)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) * [mem16int]
Evan Cheng's avatar
Evan Cheng committed
def FpIMUL32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
Evan Cheng's avatar
Evan Cheng committed
                    [(set RFP:$dst, (fmul RFP:$src1,
                                     (X86fild addr:$src2, i32)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) * [mem32int]
def FpISUB16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fsub RFP:$src1,
                                     (X86fild addr:$src2, i16)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) - [mem16int]
Evan Cheng's avatar
Evan Cheng committed
def FpISUB32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
Evan Cheng's avatar
Evan Cheng committed
                    [(set RFP:$dst, (fsub RFP:$src1,
                                     (X86fild addr:$src2, i32)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) - [mem32int]
def FpISUBR16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
                     [(set RFP:$dst, (fsub (X86fild addr:$src2, i16),
Evan Cheng's avatar
Evan Cheng committed
                                      RFP:$src1))]>;
                // ST(0) = [mem16int] - ST(0)
Evan Cheng's avatar
Evan Cheng committed
def FpISUBR32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
                     [(set RFP:$dst, (fsub (X86fild addr:$src2, i32),
Evan Cheng's avatar
Evan Cheng committed
                                      RFP:$src1))]>;
                // ST(0) = [mem32int] - ST(0)
def FpIDIV16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
                    [(set RFP:$dst, (fdiv RFP:$src1,
                                     (X86fild addr:$src2, i16)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) / [mem16int]
Evan Cheng's avatar
Evan Cheng committed
def FpIDIV32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
Evan Cheng's avatar
Evan Cheng committed
                    [(set RFP:$dst, (fdiv RFP:$src1,
                                     (X86fild addr:$src2, i32)))]>;
Evan Cheng's avatar
Evan Cheng committed
                // ST(0) = ST(0) / [mem32int]
def FpIDIVR16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW,
                     [(set RFP:$dst, (fdiv (X86fild addr:$src2, i16),
Evan Cheng's avatar
Evan Cheng committed
                                      RFP:$src1))]>;
                // ST(0) = [mem16int] / ST(0)
Evan Cheng's avatar
Evan Cheng committed
def FpIDIVR32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW,
                     [(set RFP:$dst, (fdiv (X86fild addr:$src2, i32),
Evan Cheng's avatar
Evan Cheng committed
                                      RFP:$src1))]>;
                // 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">;
Evan Cheng's avatar
Evan Cheng committed
def FIDIV32m  : FPI<0xDA, MRM6m, (ops i32mem:$src), "fidiv{l} $src">;
Evan Cheng's avatar
Evan Cheng committed
def FIDIVR16m : FPI<0xDE, MRM7m, (ops i16mem:$src), "fidivr{s} $src">;
Evan Cheng's avatar
Evan Cheng committed
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 FpCHS  : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
                 [(set RFP:$dst, (fneg RFP:$src))]>;
def FpABS  : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
                 [(set RFP:$dst, (fabs RFP:$src))]>;
def FpSQRT : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
                 [(set RFP:$dst, (fsqrt RFP:$src))]>;
def FpSIN  : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
                 [(set RFP:$dst, (fsin RFP:$src))]>;
def FpCOS  : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW,
                 [(set RFP:$dst, (fcos RFP:$src))]>;
def FpTST  : FpI<(ops RFP:$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 FpCMOVB  : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
  def FpCMOVBE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
  def FpCMOVE  : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
  def FpCMOVP  : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
  def FpCMOVNB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
  def FpCMOVNBE: FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
  def FpCMOVNE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
  def FpCMOVNP : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP,
                     [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2,
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.
def FpLD32m  : FpI<(ops RFP:$dst, f32mem:$src), ZeroArgFP,
                   [(set RFP:$dst, (extloadf64f32 addr:$src))]>;
def FpLD64m  : FpI<(ops RFP:$dst, f64mem:$src), ZeroArgFP,
                   [(set RFP:$dst, (loadf64 addr:$src))]>;
def FpILD16m : FpI<(ops RFP:$dst, i16mem:$src), ZeroArgFP,
                   [(set RFP:$dst, (X86fild addr:$src, i16))]>;
def FpILD32m : FpI<(ops RFP:$dst, i32mem:$src), ZeroArgFP,
                   [(set RFP:$dst, (X86fild addr:$src, i32))]>;
def FpILD64m : FpI<(ops RFP:$dst, i64mem:$src), ZeroArgFP,
                   [(set RFP:$dst, (X86fild addr:$src, i64))]>;
def FpST32m   : FpI<(ops f32mem:$op, RFP:$src), OneArgFP,
                [(truncstore RFP:$src, addr:$op, f32)]>;
def FpST64m   : FpI<(ops f64mem:$op, RFP:$src), OneArgFP,
                [(store RFP:$src, addr:$op)]>;
def FpSTP32m  : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, []>;
def FpSTP64m  : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, []>;
def FpIST16m  : FpI<(ops i16mem:$op, RFP:$src), OneArgFP, []>;
def FpIST32m  : FpI<(ops i32mem:$op, RFP:$src), OneArgFP, []>;
def FpIST64m  : FpI<(ops i64mem:$op, RFP:$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">;

// 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.
Evan Cheng's avatar
Evan Cheng committed
def FpLD0 : FpI<(ops RFP:$dst), ZeroArgFP,
                [(set RFP:$dst, fp64imm0)]>;
def FpLD1 : FpI<(ops RFP:$dst), ZeroArgFP,
                [(set RFP:$dst, fp64imm1)]>;

def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9;
def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9;


// Floating point compares.
Evan Cheng's avatar
Evan Cheng committed
def FpUCOMr   : FpI<(ops RFP:$lhs, RFP:$rhs), CompareFP,
Evan Cheng's avatar
Evan Cheng committed
def FpUCOMIr  : FpI<(ops RFP:$lhs, RFP:$rhs), CompareFP,
                    [(X86cmp RFP:$lhs, RFP:$rhs)]>; // CC = cmp ST(0) with ST(i)

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],[]>;