Skip to content
X86InstrSSE.td 180 KiB
Newer Older
Evan Cheng's avatar
Evan Cheng committed
let Predicates = [HasSSE1] in {
  def : Pat<(v2i64 immAllZerosV), (V_SET0)>;
  def : Pat<(v8i16 immAllZerosV), (V_SET0)>;
  def : Pat<(v16i8 immAllZerosV), (V_SET0)>;
  def : Pat<(v2f64 immAllZerosV), (V_SET0)>;
  def : Pat<(v4f32 immAllZerosV), (V_SET0)>;
}

// FR32 to 128-bit vector conversion.
Evan Cheng's avatar
Evan Cheng committed
let isAsCheapAsAMove = 1 in
def MOVSS2PSrr : SSI<0x10, MRMSrcReg, (outs VR128:$dst), (ins FR32:$src),
                      "movss\t{$src, $dst|$dst, $src}",
                      [(set VR128:$dst,
                        (v4f32 (scalar_to_vector FR32:$src)))]>;
def MOVSS2PSrm : SSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f32mem:$src),
                     "movss\t{$src, $dst|$dst, $src}",
                     [(set VR128:$dst,
                       (v4f32 (scalar_to_vector (loadf32 addr:$src))))]>;

// FIXME: may not be able to eliminate this movss with coalescing the src and
// dest register classes are different. We really want to write this pattern
// like this:
// def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))),
//           (f32 FR32:$src)>;
Evan Cheng's avatar
Evan Cheng committed
let isAsCheapAsAMove = 1 in
def MOVPS2SSrr : SSI<0x10, MRMSrcReg, (outs FR32:$dst), (ins VR128:$src),
                     "movss\t{$src, $dst|$dst, $src}",
                     [(set FR32:$dst, (vector_extract (v4f32 VR128:$src),
                                       (iPTR 0)))]>;
def MOVPS2SSmr : SSI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, VR128:$src),
                     "movss\t{$src, $dst|$dst, $src}",
                     [(store (f32 (vector_extract (v4f32 VR128:$src),
                                   (iPTR 0))), addr:$dst)]>;


// Move to lower bits of a VR128, leaving upper bits alone.
// Three operand (but two address) aliases.
let Constraints = "$src1 = $dst" in {
Chris Lattner's avatar
Chris Lattner committed
let neverHasSideEffects = 1 in
  def MOVLSS2PSrr : SSI<0x10, MRMSrcReg,
                        (outs VR128:$dst), (ins VR128:$src1, FR32:$src2),
                        "movss\t{$src2, $dst|$dst, $src2}", []>;

  let AddedComplexity = 15 in
    def MOVLPSrr : SSI<0x10, MRMSrcReg,
                       (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                       "movss\t{$src2, $dst|$dst, $src2}",
                       [(set VR128:$dst,
                         (v4f32 (vector_shuffle VR128:$src1, VR128:$src2,
                                 MOVL_shuffle_mask)))]>;
}

// Move to lower bits of a VR128 and zeroing upper bits.
// Loading from memory automatically zeroing upper bits.
let AddedComplexity = 20 in
def MOVZSS2PSrm : SSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f32mem:$src),
                      "movss\t{$src, $dst|$dst, $src}",
                   [(set VR128:$dst, (v4f32 (X86vzmovl (v4f32 (scalar_to_vector
def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))),

//===----------------------------------------------------------------------===//
// SSE2 Instructions
//===----------------------------------------------------------------------===//

// Move Instructions
Chris Lattner's avatar
Chris Lattner committed
let neverHasSideEffects = 1 in
def MOVSDrr : SDI<0x10, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src),
                  "movsd\t{$src, $dst|$dst, $src}", []>;
let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in
def MOVSDrm : SDI<0x10, MRMSrcMem, (outs FR64:$dst), (ins f64mem:$src),
                  "movsd\t{$src, $dst|$dst, $src}",
                  [(set FR64:$dst, (loadf64 addr:$src))]>;
def MOVSDmr : SDI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src),
                  "movsd\t{$src, $dst|$dst, $src}",
def CVTTSD2SIrr : SDI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins FR64:$src),
                      "cvttsd2si\t{$src, $dst|$dst, $src}",
                      [(set GR32:$dst, (fp_to_sint FR64:$src))]>;
def CVTTSD2SIrm : SDI<0x2C, MRMSrcMem, (outs GR32:$dst), (ins f64mem:$src),
                      "cvttsd2si\t{$src, $dst|$dst, $src}",
                      [(set GR32:$dst, (fp_to_sint (loadf64 addr:$src)))]>;
def CVTSD2SSrr  : SDI<0x5A, MRMSrcReg, (outs FR32:$dst), (ins FR64:$src),
                      "cvtsd2ss\t{$src, $dst|$dst, $src}",
                      [(set FR32:$dst, (fround FR64:$src))]>;
def CVTSD2SSrm  : SDI<0x5A, MRMSrcMem, (outs FR32:$dst), (ins f64mem:$src), 
                      "cvtsd2ss\t{$src, $dst|$dst, $src}",
                      [(set FR32:$dst, (fround (loadf64 addr:$src)))]>;
def CVTSI2SDrr  : SDI<0x2A, MRMSrcReg, (outs FR64:$dst), (ins GR32:$src),
                      "cvtsi2sd\t{$src, $dst|$dst, $src}",
                      [(set FR64:$dst, (sint_to_fp GR32:$src))]>;
def CVTSI2SDrm  : SDI<0x2A, MRMSrcMem, (outs FR64:$dst), (ins i32mem:$src),
                      "cvtsi2sd\t{$src, $dst|$dst, $src}",
                      [(set FR64:$dst, (sint_to_fp (loadi32 addr:$src)))]>;
def CVTSS2SDrr : I<0x5A, MRMSrcReg, (outs FR64:$dst), (ins FR32:$src),
                   "cvtss2sd\t{$src, $dst|$dst, $src}",
                   [(set FR64:$dst, (fextend FR32:$src))]>, XS,
                 Requires<[HasSSE2]>;
def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src),
                   "cvtss2sd\t{$src, $dst|$dst, $src}",
                   [(set FR64:$dst, (extloadf32 addr:$src))]>, XS,
                 Requires<[HasSSE2]>;
// Match intrinsics which expect XMM operand(s).
def Int_CVTSD2SIrr : SDI<0x2D, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src),
                         "cvtsd2si\t{$src, $dst|$dst, $src}",
                         [(set GR32:$dst, (int_x86_sse2_cvtsd2si VR128:$src))]>;
def Int_CVTSD2SIrm : SDI<0x2D, MRMSrcMem, (outs GR32:$dst), (ins f128mem:$src),
                         "cvtsd2si\t{$src, $dst|$dst, $src}",
                         [(set GR32:$dst, (int_x86_sse2_cvtsd2si
                                           (load addr:$src)))]>;
// Match intrinisics which expect MM and XMM operand(s).
def Int_CVTPD2PIrr : PDI<0x2D, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src),
                         "cvtpd2pi\t{$src, $dst|$dst, $src}",
                         [(set VR64:$dst, (int_x86_sse_cvtpd2pi VR128:$src))]>;
def Int_CVTPD2PIrm : PDI<0x2D, MRMSrcMem, (outs VR64:$dst), (ins f128mem:$src),
                         "cvtpd2pi\t{$src, $dst|$dst, $src}",
                         [(set VR64:$dst, (int_x86_sse_cvtpd2pi 
def Int_CVTTPD2PIrr: PDI<0x2C, MRMSrcReg, (outs VR64:$dst), (ins VR128:$src),
                         "cvttpd2pi\t{$src, $dst|$dst, $src}",
                         [(set VR64:$dst, (int_x86_sse_cvttpd2pi VR128:$src))]>;
def Int_CVTTPD2PIrm: PDI<0x2C, MRMSrcMem, (outs VR64:$dst), (ins f128mem:$src),
                         "cvttpd2pi\t{$src, $dst|$dst, $src}",
                         [(set VR64:$dst, (int_x86_sse_cvttpd2pi 
def Int_CVTPI2PDrr : PDI<0x2A, MRMSrcReg, (outs VR128:$dst), (ins VR64:$src),
                         "cvtpi2pd\t{$src, $dst|$dst, $src}",
                         [(set VR128:$dst, (int_x86_sse_cvtpi2pd VR64:$src))]>;
def Int_CVTPI2PDrm : PDI<0x2A, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
                         "cvtpi2pd\t{$src, $dst|$dst, $src}",
                         [(set VR128:$dst, (int_x86_sse_cvtpi2pd 
                                            (load addr:$src)))]>;

// Aliases for intrinsics
def Int_CVTTSD2SIrr : SDI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src),
                          "cvttsd2si\t{$src, $dst|$dst, $src}",
                          [(set GR32:$dst,
                            (int_x86_sse2_cvttsd2si VR128:$src))]>;
def Int_CVTTSD2SIrm : SDI<0x2C, MRMSrcMem, (outs GR32:$dst), (ins f128mem:$src),
                          "cvttsd2si\t{$src, $dst|$dst, $src}",
                          [(set GR32:$dst, (int_x86_sse2_cvttsd2si
                                            (load addr:$src)))]>;
// Comparison instructions
let Constraints = "$src1 = $dst", neverHasSideEffects = 1 in {
  def CMPSDrr : SDIi8<0xC2, MRMSrcReg, 
                    (outs FR64:$dst), (ins FR64:$src1, FR64:$src, SSECC:$cc),
                    "cmp${cc}sd\t{$src, $dst|$dst, $src}", []>;
Chris Lattner's avatar
Chris Lattner committed
let mayLoad = 1 in
  def CMPSDrm : SDIi8<0xC2, MRMSrcMem, 
                    (outs FR64:$dst), (ins FR64:$src1, f64mem:$src, SSECC:$cc),
                    "cmp${cc}sd\t{$src, $dst|$dst, $src}", []>;
def UCOMISDrr: PDI<0x2E, MRMSrcReg, (outs), (ins FR64:$src1, FR64:$src2),
                   "ucomisd\t{$src2, $src1|$src1, $src2}",
                   [(X86cmp FR64:$src1, FR64:$src2), (implicit EFLAGS)]>;
def UCOMISDrm: PDI<0x2E, MRMSrcMem, (outs), (ins FR64:$src1, f64mem:$src2),
                   "ucomisd\t{$src2, $src1|$src1, $src2}",
                   [(X86cmp FR64:$src1, (loadf64 addr:$src2)),
// Aliases to match intrinsics which expect XMM operand(s).
let Constraints = "$src1 = $dst" in {
  def Int_CMPSDrr : SDIi8<0xC2, MRMSrcReg, 
                        (outs VR128:$dst), (ins VR128:$src1, VR128:$src, SSECC:$cc),
                        "cmp${cc}sd\t{$src, $dst|$dst, $src}",
                        [(set VR128:$dst, (int_x86_sse2_cmp_sd VR128:$src1,
                                           VR128:$src, imm:$cc))]>;
  def Int_CMPSDrm : SDIi8<0xC2, MRMSrcMem, 
                        (outs VR128:$dst), (ins VR128:$src1, f64mem:$src, SSECC:$cc),
                        "cmp${cc}sd\t{$src, $dst|$dst, $src}",
                        [(set VR128:$dst, (int_x86_sse2_cmp_sd VR128:$src1,
                                           (load addr:$src), imm:$cc))]>;
def Int_UCOMISDrr: PDI<0x2E, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2),
                       "ucomisd\t{$src2, $src1|$src1, $src2}",
                       [(X86ucomi (v2f64 VR128:$src1), (v2f64 VR128:$src2)),
def Int_UCOMISDrm: PDI<0x2E, MRMSrcMem, (outs),(ins VR128:$src1, f128mem:$src2),
                       "ucomisd\t{$src2, $src1|$src1, $src2}",
                       [(X86ucomi (v2f64 VR128:$src1), (load addr:$src2)),
def Int_COMISDrr: PDI<0x2F, MRMSrcReg, (outs), (ins VR128:$src1, VR128:$src2),
                      "comisd\t{$src2, $src1|$src1, $src2}",
                      [(X86comi (v2f64 VR128:$src1), (v2f64 VR128:$src2)),
def Int_COMISDrm: PDI<0x2F, MRMSrcMem, (outs), (ins VR128:$src1, f128mem:$src2),
                      "comisd\t{$src2, $src1|$src1, $src2}",
                      [(X86comi (v2f64 VR128:$src1), (load addr:$src2)),
// Aliases of packed SSE2 instructions for scalar use. These all have names that

// Alias instructions that map fld0 to pxor for sse.
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def FsFLD0SD : I<0xEF, MRMInitReg, (outs FR64:$dst), (ins),
                 "pxor\t$dst, $dst", [(set FR64:$dst, fpimm0)]>,
               Requires<[HasSSE2]>, TB, OpSize;

// Alias instruction to do FR64 reg-to-reg copy using movapd. Upper bits are
def FsMOVAPDrr : PDI<0x28, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src),
                     "movapd\t{$src, $dst|$dst, $src}", []>;
// Alias instruction to load FR64 from f128mem using movapd. Upper bits are
def FsMOVAPDrm : PDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src),
                     "movapd\t{$src, $dst|$dst, $src}",
                     [(set FR64:$dst, (alignedloadfsf64 addr:$src))]>;
// Alias bitwise logical operations using SSE logical ops on packed FP values.
let Constraints = "$src1 = $dst" in {
Evan Cheng's avatar
Evan Cheng committed
  def FsANDPDrr : PDI<0x54, MRMSrcReg, (outs FR64:$dst),
                                       (ins FR64:$src1, FR64:$src2),
                      "andpd\t{$src2, $dst|$dst, $src2}",
                      [(set FR64:$dst, (X86fand FR64:$src1, FR64:$src2))]>;
Evan Cheng's avatar
Evan Cheng committed
  def FsORPDrr  : PDI<0x56, MRMSrcReg, (outs FR64:$dst),
                                       (ins FR64:$src1, FR64:$src2),
                      "orpd\t{$src2, $dst|$dst, $src2}",
                      [(set FR64:$dst, (X86for FR64:$src1, FR64:$src2))]>;
Evan Cheng's avatar
Evan Cheng committed
  def FsXORPDrr : PDI<0x57, MRMSrcReg, (outs FR64:$dst),
                                       (ins FR64:$src1, FR64:$src2),
                      "xorpd\t{$src2, $dst|$dst, $src2}",
                      [(set FR64:$dst, (X86fxor FR64:$src1, FR64:$src2))]>;
}

Evan Cheng's avatar
Evan Cheng committed
def FsANDPDrm : PDI<0x54, MRMSrcMem, (outs FR64:$dst),
                                     (ins FR64:$src1, f128mem:$src2),
                    "andpd\t{$src2, $dst|$dst, $src2}",
                    [(set FR64:$dst, (X86fand FR64:$src1,
Evan Cheng's avatar
Evan Cheng committed
def FsORPDrm  : PDI<0x56, MRMSrcMem, (outs FR64:$dst),
                                     (ins FR64:$src1, f128mem:$src2),
                    "orpd\t{$src2, $dst|$dst, $src2}",
                    [(set FR64:$dst, (X86for FR64:$src1,
Evan Cheng's avatar
Evan Cheng committed
def FsXORPDrm : PDI<0x57, MRMSrcMem, (outs FR64:$dst),
                                     (ins FR64:$src1, f128mem:$src2),
                    "xorpd\t{$src2, $dst|$dst, $src2}",
                    [(set FR64:$dst, (X86fxor FR64:$src1,
def FsANDNPDrr : PDI<0x55, MRMSrcReg,
                     (outs FR64:$dst), (ins FR64:$src1, FR64:$src2),
                     "andnpd\t{$src2, $dst|$dst, $src2}", []>;
def FsANDNPDrm : PDI<0x55, MRMSrcMem,
                     (outs FR64:$dst), (ins FR64:$src1, f128mem:$src2),
                     "andnpd\t{$src2, $dst|$dst, $src2}", []>;
/// basic_sse2_fp_binop_rm - SSE2 binops come in both scalar and vector forms.
///
/// In addition, we also have a special variant of the scalar form here to
/// represent the associated intrinsic operation.  This form is unlike the
/// plain scalar form, in that it takes an entire vector (instead of a scalar)
/// and leaves the top elements undefined.
/// These three forms can each be reg+reg or reg+mem, so there are a total of
/// six "instructions".
let Constraints = "$src1 = $dst" in {
multiclass basic_sse2_fp_binop_rm<bits<8> opc, string OpcodeStr,
                                  SDNode OpNode, Intrinsic F64Int,
                                  bit Commutable = 0> {
  def SDrr : SDI<opc, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src1, FR64:$src2),
                 !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                 [(set FR64:$dst, (OpNode FR64:$src1, FR64:$src2))]> {
    let isCommutable = Commutable;
  }

  // Scalar operation, reg+mem.
  def SDrm : SDI<opc, MRMSrcMem, (outs FR64:$dst),
                                 (ins FR64:$src1, f64mem:$src2),
                 !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                 [(set FR64:$dst, (OpNode FR64:$src1, (load addr:$src2)))]>;
                 
  def PDrr : PDI<opc, MRMSrcReg, (outs VR128:$dst),
                                 (ins VR128:$src1, VR128:$src2),
               !strconcat(OpcodeStr, "pd\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (v2f64 (OpNode VR128:$src1, VR128:$src2)))]> {
    let isCommutable = Commutable;
  }

  // Vector operation, reg+mem.
  def PDrm : PDI<opc, MRMSrcMem, (outs VR128:$dst),
                                 (ins VR128:$src1, f128mem:$src2),
                 !strconcat(OpcodeStr, "pd\t{$src2, $dst|$dst, $src2}"),
             [(set VR128:$dst, (OpNode VR128:$src1, (memopv2f64 addr:$src2)))]>;
  def SDrr_Int : SDI<opc, MRMSrcReg, (outs VR128:$dst),
                                     (ins VR128:$src1, VR128:$src2),
                     !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                     [(set VR128:$dst, (F64Int VR128:$src1, VR128:$src2))]> {
    let isCommutable = Commutable;
  }
  def SDrm_Int : SDI<opc, MRMSrcMem, (outs VR128:$dst),
                                     (ins VR128:$src1, sdmem:$src2),
                     !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                     [(set VR128:$dst, (F64Int VR128:$src1,
                                               sse_load_f64:$src2))]>;
defm ADD : basic_sse2_fp_binop_rm<0x58, "add", fadd, int_x86_sse2_add_sd, 1>;
defm MUL : basic_sse2_fp_binop_rm<0x59, "mul", fmul, int_x86_sse2_mul_sd, 1>;
defm SUB : basic_sse2_fp_binop_rm<0x5C, "sub", fsub, int_x86_sse2_sub_sd>;
defm DIV : basic_sse2_fp_binop_rm<0x5E, "div", fdiv, int_x86_sse2_div_sd>;
/// sse2_fp_binop_rm - Other SSE2 binops
///
/// This multiclass is like basic_sse2_fp_binop_rm, with the addition of
/// instructions for a full-vector intrinsic form.  Operations that map
/// onto C operators don't use this form since they just use the plain
/// vector form instead of having a separate vector intrinsic form.
///
/// This provides a total of eight "instructions".
///
let Constraints = "$src1 = $dst" in {
multiclass sse2_fp_binop_rm<bits<8> opc, string OpcodeStr,
                            SDNode OpNode,
                            Intrinsic F64Int,
                            Intrinsic V2F64Int,
                            bit Commutable = 0> {

  // Scalar operation, reg+reg.
  def SDrr : SDI<opc, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src1, FR64:$src2),
                 !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                 [(set FR64:$dst, (OpNode FR64:$src1, FR64:$src2))]> {
    let isCommutable = Commutable;
  }

  // Scalar operation, reg+mem.
  def SDrm : SDI<opc, MRMSrcMem, (outs FR64:$dst),
                                 (ins FR64:$src1, f64mem:$src2),
                 !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                 [(set FR64:$dst, (OpNode FR64:$src1, (load addr:$src2)))]>;
                 
  // Vector operation, reg+reg.
  def PDrr : PDI<opc, MRMSrcReg, (outs VR128:$dst),
                                 (ins VR128:$src1, VR128:$src2),
               !strconcat(OpcodeStr, "pd\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (v2f64 (OpNode VR128:$src1, VR128:$src2)))]> {
    let isCommutable = Commutable;
  }

  // Vector operation, reg+mem.
  def PDrm : PDI<opc, MRMSrcMem, (outs VR128:$dst),
                                 (ins VR128:$src1, f128mem:$src2),
                 !strconcat(OpcodeStr, "pd\t{$src2, $dst|$dst, $src2}"),
             [(set VR128:$dst, (OpNode VR128:$src1, (memopv2f64 addr:$src2)))]>;
  def SDrr_Int : SDI<opc, MRMSrcReg, (outs VR128:$dst),
                                     (ins VR128:$src1, VR128:$src2),
                     !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                     [(set VR128:$dst, (F64Int VR128:$src1, VR128:$src2))]> {
    let isCommutable = Commutable;
  }

  // Intrinsic operation, reg+mem.
  def SDrm_Int : SDI<opc, MRMSrcMem, (outs VR128:$dst),
                                     (ins VR128:$src1, sdmem:$src2),
                     !strconcat(OpcodeStr, "sd\t{$src2, $dst|$dst, $src2}"),
                     [(set VR128:$dst, (F64Int VR128:$src1,
                                               sse_load_f64:$src2))]>;

  // Vector intrinsic operation, reg+reg.
  def PDrr_Int : PDI<opc, MRMSrcReg, (outs VR128:$dst),
                                     (ins VR128:$src1, VR128:$src2),
                     !strconcat(OpcodeStr, "pd\t{$src2, $dst|$dst, $src2}"),
                     [(set VR128:$dst, (V2F64Int VR128:$src1, VR128:$src2))]> {
    let isCommutable = Commutable;
  }

  // Vector intrinsic operation, reg+mem.
  def PDrm_Int : PDI<opc, MRMSrcMem, (outs VR128:$dst),
                                     (ins VR128:$src1, f128mem:$src2),
                     !strconcat(OpcodeStr, "pd\t{$src2, $dst|$dst, $src2}"),
                     [(set VR128:$dst, (V2F64Int VR128:$src1,
                                                 (memopv2f64 addr:$src2)))]>;
}
}

defm MAX : sse2_fp_binop_rm<0x5F, "max", X86fmax,
                            int_x86_sse2_max_sd, int_x86_sse2_max_pd>;
defm MIN : sse2_fp_binop_rm<0x5D, "min", X86fmin,
                            int_x86_sse2_min_sd, int_x86_sse2_min_pd>;

//===----------------------------------------------------------------------===//
Evan Cheng's avatar
Evan Cheng committed
// SSE packed FP Instructions
Evan Cheng's avatar
Evan Cheng committed

def MOVAPDrr : PDI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                   "movapd\t{$src, $dst|$dst, $src}", []>;
let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in
def MOVAPDrm : PDI<0x28, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                   "movapd\t{$src, $dst|$dst, $src}",
                   [(set VR128:$dst, (alignedloadv2f64 addr:$src))]>;
def MOVAPDmr : PDI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
                   "movapd\t{$src, $dst|$dst, $src}",
                   [(alignedstore (v2f64 VR128:$src), addr:$dst)]>;
Chris Lattner's avatar
Chris Lattner committed
let neverHasSideEffects = 1 in
def MOVUPDrr : PDI<0x10, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                   "movupd\t{$src, $dst|$dst, $src}", []>;
def MOVUPDrm : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                   "movupd\t{$src, $dst|$dst, $src}",
                   [(set VR128:$dst, (loadv2f64 addr:$src))]>;
def MOVUPDmr : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
                   "movupd\t{$src, $dst|$dst, $src}",
                   [(store (v2f64 VR128:$src), addr:$dst)]>;

// Intrinsic forms of MOVUPD load and store
def MOVUPDrm_Int : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                       "movupd\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>;
def MOVUPDmr_Int : PDI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src),
                       "movupd\t{$src, $dst|$dst, $src}",
                       [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>;
let Constraints = "$src1 = $dst" in {
  let AddedComplexity = 20 in {
    def MOVLPDrm : PDI<0x12, MRMSrcMem,
                       (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2),
                       "movlpd\t{$src2, $dst|$dst, $src2}",
                       [(set VR128:$dst, 
                         (v2f64 (vector_shuffle VR128:$src1,
                                 (scalar_to_vector (loadf64 addr:$src2)),
                                 MOVLP_shuffle_mask)))]>;
    def MOVHPDrm : PDI<0x16, MRMSrcMem,
                       (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2),
                       "movhpd\t{$src2, $dst|$dst, $src2}",
                       [(set VR128:$dst, 
                         (v2f64 (vector_shuffle VR128:$src1,
                                 (scalar_to_vector (loadf64 addr:$src2)),
                                 MOVHP_shuffle_mask)))]>;
  } // AddedComplexity
} // Constraints = "$src1 = $dst"
def MOVLPDmr : PDI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src),
                   "movlpd\t{$src, $dst|$dst, $src}",
                   [(store (f64 (vector_extract (v2f64 VR128:$src),
// v2f64 extract element 1 is always custom lowered to unpack high to low
// and extract element 0 so the non-store version isn't too horrible.
def MOVHPDmr : PDI<0x17, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src),
                   "movhpd\t{$src, $dst|$dst, $src}",
                   [(store (f64 (vector_extract
                                 (v2f64 (vector_shuffle VR128:$src, (undef),
                                         UNPCKH_shuffle_mask)), (iPTR 0))),

// SSE2 instructions without OpSize prefix
def Int_CVTDQ2PSrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                       "cvtdq2ps\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_cvtdq2ps VR128:$src))]>,
                     TB, Requires<[HasSSE2]>;
def Int_CVTDQ2PSrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                      "cvtdq2ps\t{$src, $dst|$dst, $src}",
                      [(set VR128:$dst, (int_x86_sse2_cvtdq2ps
                                        (bitconvert (memopv2i64 addr:$src))))]>,
                     TB, Requires<[HasSSE2]>;
def Int_CVTDQ2PDrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                       "cvtdq2pd\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_cvtdq2pd VR128:$src))]>,
                     XS, Requires<[HasSSE2]>;
def Int_CVTDQ2PDrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
Evan Cheng's avatar
Evan Cheng committed
                     "cvtdq2pd\t{$src, $dst|$dst, $src}",
                     [(set VR128:$dst, (int_x86_sse2_cvtdq2pd
                                        (bitconvert (memopv2i64 addr:$src))))]>,
                     XS, Requires<[HasSSE2]>;

def Int_CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
Evan Cheng's avatar
Evan Cheng committed
                        "cvtps2dq\t{$src, $dst|$dst, $src}",
                        [(set VR128:$dst, (int_x86_sse2_cvtps2dq VR128:$src))]>;
def Int_CVTPS2DQrm : PDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                         "cvtps2dq\t{$src, $dst|$dst, $src}",
                         [(set VR128:$dst, (int_x86_sse2_cvtps2dq
// SSE2 packed instructions with XS prefix
def Int_CVTTPS2DQrr : I<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                        "cvttps2dq\t{$src, $dst|$dst, $src}",
                        [(set VR128:$dst, (int_x86_sse2_cvttps2dq VR128:$src))]>,
                      XS, Requires<[HasSSE2]>;
def Int_CVTTPS2DQrm : I<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                        "cvttps2dq\t{$src, $dst|$dst, $src}",
                        [(set VR128:$dst, (int_x86_sse2_cvttps2dq
                      XS, Requires<[HasSSE2]>;
// SSE2 packed instructions with XD prefix
def Int_CVTPD2DQrr : I<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                       "cvtpd2dq\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_cvtpd2dq VR128:$src))]>,
                     XD, Requires<[HasSSE2]>;
def Int_CVTPD2DQrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                       "cvtpd2dq\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_cvtpd2dq
                     XD, Requires<[HasSSE2]>;
def Int_CVTTPD2DQrr : PDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                          "cvttpd2dq\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_cvttpd2dq VR128:$src))]>;
Evan Cheng's avatar
Evan Cheng committed
def Int_CVTTPD2DQrm : PDI<0xE6, MRMSrcMem, (outs VR128:$dst),(ins f128mem:$src),
                          "cvttpd2dq\t{$src, $dst|$dst, $src}",
                          [(set VR128:$dst, (int_x86_sse2_cvttpd2dq

// SSE2 instructions without OpSize prefix
def Int_CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                       "cvtps2pd\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_cvtps2pd VR128:$src))]>,
                     TB, Requires<[HasSSE2]>;
def Int_CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
                       "cvtps2pd\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_cvtps2pd
                                          (load addr:$src)))]>,
                     TB, Requires<[HasSSE2]>;

def Int_CVTPD2PSrr : PDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                         "cvtpd2ps\t{$src, $dst|$dst, $src}",
                        [(set VR128:$dst, (int_x86_sse2_cvtpd2ps VR128:$src))]>;
def Int_CVTPD2PSrm : PDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                         "cvtpd2ps\t{$src, $dst|$dst, $src}",
                         [(set VR128:$dst, (int_x86_sse2_cvtpd2ps
// Match intrinsics which expect XMM operand(s).
// Aliases for intrinsics
let Constraints = "$src1 = $dst" in {
def Int_CVTSI2SDrr: SDI<0x2A, MRMSrcReg,
                        (outs VR128:$dst), (ins VR128:$src1, GR32:$src2),
                        "cvtsi2sd\t{$src2, $dst|$dst, $src2}",
                        [(set VR128:$dst, (int_x86_sse2_cvtsi2sd VR128:$src1,
def Int_CVTSI2SDrm: SDI<0x2A, MRMSrcMem,
                        (outs VR128:$dst), (ins VR128:$src1, i32mem:$src2),
                        "cvtsi2sd\t{$src2, $dst|$dst, $src2}",
                        [(set VR128:$dst, (int_x86_sse2_cvtsi2sd VR128:$src1,
                                           (loadi32 addr:$src2)))]>;
def Int_CVTSD2SSrr: SDI<0x5A, MRMSrcReg,
                        (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                   "cvtsd2ss\t{$src2, $dst|$dst, $src2}",
                   [(set VR128:$dst, (int_x86_sse2_cvtsd2ss VR128:$src1,
                                      VR128:$src2))]>;
def Int_CVTSD2SSrm: SDI<0x5A, MRMSrcMem,
                        (outs VR128:$dst), (ins VR128:$src1, f64mem:$src2), 
                   "cvtsd2ss\t{$src2, $dst|$dst, $src2}",
                   [(set VR128:$dst, (int_x86_sse2_cvtsd2ss VR128:$src1,
                                      (load addr:$src2)))]>;
def Int_CVTSS2SDrr: I<0x5A, MRMSrcReg,
                      (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                    "cvtss2sd\t{$src2, $dst|$dst, $src2}",
                    [(set VR128:$dst, (int_x86_sse2_cvtss2sd VR128:$src1,
                                       VR128:$src2))]>, XS,
                    Requires<[HasSSE2]>;
def Int_CVTSS2SDrm: I<0x5A, MRMSrcMem,
                      (outs VR128:$dst), (ins VR128:$src1, f32mem:$src2),
                    "cvtss2sd\t{$src2, $dst|$dst, $src2}",
                    [(set VR128:$dst, (int_x86_sse2_cvtss2sd VR128:$src1,
                                       (load addr:$src2)))]>, XS,
                    Requires<[HasSSE2]>;
}

// Arithmetic

/// sse2_fp_unop_rm - SSE2 unops come in both scalar and vector forms.
/// In addition, we also have a special variant of the scalar form here to
/// represent the associated intrinsic operation.  This form is unlike the
/// plain scalar form, in that it takes an entire vector (instead of a
/// scalar) and leaves the top elements undefined.
///
/// And, we have a special variant form for a full-vector intrinsic form.
///
/// These four forms can each have a reg or a mem operand, so there are a
/// total of eight "instructions".
///
multiclass sse2_fp_unop_rm<bits<8> opc, string OpcodeStr,
                           SDNode OpNode,
                           Intrinsic F64Int,
                           Intrinsic V2F64Int,
                           bit Commutable = 0> {
  // Scalar operation, reg.
  def SDr : SDI<opc, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src),
                !strconcat(OpcodeStr, "sd\t{$src, $dst|$dst, $src}"),
                [(set FR64:$dst, (OpNode FR64:$src))]> {
    let isCommutable = Commutable;
  }
  def SDm : SDI<opc, MRMSrcMem, (outs FR64:$dst), (ins f64mem:$src),
                !strconcat(OpcodeStr, "sd\t{$src, $dst|$dst, $src}"),
                [(set FR64:$dst, (OpNode (load addr:$src)))]>;
                 
  // Vector operation, reg.
  def PDr : PDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
              !strconcat(OpcodeStr, "pd\t{$src, $dst|$dst, $src}"),
              [(set VR128:$dst, (v2f64 (OpNode VR128:$src)))]> {
    let isCommutable = Commutable;
  }
  def PDm : PDI<opc, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                !strconcat(OpcodeStr, "pd\t{$src, $dst|$dst, $src}"),
                [(set VR128:$dst, (OpNode (memopv2f64 addr:$src)))]>;
  def SDr_Int : SDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                    !strconcat(OpcodeStr, "sd\t{$src, $dst|$dst, $src}"),
                    [(set VR128:$dst, (F64Int VR128:$src))]> {
    let isCommutable = Commutable;
  }
  def SDm_Int : SDI<opc, MRMSrcMem, (outs VR128:$dst), (ins sdmem:$src),
                    !strconcat(OpcodeStr, "sd\t{$src, $dst|$dst, $src}"),
                    [(set VR128:$dst, (F64Int sse_load_f64:$src))]>;
  def PDr_Int : PDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                    !strconcat(OpcodeStr, "pd\t{$src, $dst|$dst, $src}"),
                    [(set VR128:$dst, (V2F64Int VR128:$src))]> {
    let isCommutable = Commutable;
  def PDm_Int : PDI<opc, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
                    !strconcat(OpcodeStr, "pd\t{$src, $dst|$dst, $src}"),
                    [(set VR128:$dst, (V2F64Int (memopv2f64 addr:$src)))]>;
// Square root.
defm SQRT  : sse2_fp_unop_rm<0x51, "sqrt",  fsqrt,
                             int_x86_sse2_sqrt_sd, int_x86_sse2_sqrt_pd>;

// There is no f64 version of the reciprocal approximation instructions.

let Constraints = "$src1 = $dst" in {
  let isCommutable = 1 in {
    def ANDPDrr : PDI<0x54, MRMSrcReg,
                      (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                      "andpd\t{$src2, $dst|$dst, $src2}",
                      [(set VR128:$dst,
                        (and (bc_v2i64 (v2f64 VR128:$src1)),
                         (bc_v2i64 (v2f64 VR128:$src2))))]>;
                      (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                      "orpd\t{$src2, $dst|$dst, $src2}",
                      [(set VR128:$dst,
                        (or (bc_v2i64 (v2f64 VR128:$src1)),
                         (bc_v2i64 (v2f64 VR128:$src2))))]>;
                      (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                      "xorpd\t{$src2, $dst|$dst, $src2}",
                      [(set VR128:$dst,
                        (xor (bc_v2i64 (v2f64 VR128:$src1)),
                         (bc_v2i64 (v2f64 VR128:$src2))))]>;
  }

  def ANDPDrm : PDI<0x54, MRMSrcMem,
                    (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2),
                    "andpd\t{$src2, $dst|$dst, $src2}",
                    [(set VR128:$dst,
                      (and (bc_v2i64 (v2f64 VR128:$src1)),
                    (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2),
                    "orpd\t{$src2, $dst|$dst, $src2}",
                    [(set VR128:$dst,
                      (or (bc_v2i64 (v2f64 VR128:$src1)),
                    (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2),
                    "xorpd\t{$src2, $dst|$dst, $src2}",
                    [(set VR128:$dst,
                      (xor (bc_v2i64 (v2f64 VR128:$src1)),
  def ANDNPDrr : PDI<0x55, MRMSrcReg,
                     (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                     "andnpd\t{$src2, $dst|$dst, $src2}",
                     [(set VR128:$dst,
                       (and (vnot (bc_v2i64 (v2f64 VR128:$src1))),
                        (bc_v2i64 (v2f64 VR128:$src2))))]>;
  def ANDNPDrm : PDI<0x55, MRMSrcMem,
                     (outs VR128:$dst), (ins VR128:$src1,f128mem:$src2),
                     "andnpd\t{$src2, $dst|$dst, $src2}",
                     [(set VR128:$dst,
                       (and (vnot (bc_v2i64 (v2f64 VR128:$src1))),
let Constraints = "$src1 = $dst" in {
  def CMPPDrri : PDIi8<0xC2, MRMSrcReg, 
Evan Cheng's avatar
Evan Cheng committed
                    (outs VR128:$dst), (ins VR128:$src1, VR128:$src, SSECC:$cc),
                    "cmp${cc}pd\t{$src, $dst|$dst, $src}",
                    [(set VR128:$dst, (int_x86_sse2_cmp_pd VR128:$src1,
                                                        VR128:$src, imm:$cc))]>;
  def CMPPDrmi : PDIi8<0xC2, MRMSrcMem, 
Evan Cheng's avatar
Evan Cheng committed
                  (outs VR128:$dst), (ins VR128:$src1, f128mem:$src, SSECC:$cc),
                  "cmp${cc}pd\t{$src, $dst|$dst, $src}",
                  [(set VR128:$dst, (int_x86_sse2_cmp_pd VR128:$src1,
def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), VR128:$src2, imm:$cc)),
          (CMPPDrri VR128:$src1, VR128:$src2, imm:$cc)>;
def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), (memop addr:$src2), imm:$cc)),
          (CMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>;
// Shuffle and unpack instructions
let Constraints = "$src1 = $dst" in {
  def SHUFPDrri : PDIi8<0xC6, MRMSrcReg, 
Evan Cheng's avatar
Evan Cheng committed
                 (outs VR128:$dst), (ins VR128:$src1, VR128:$src2, i8imm:$src3),
                 "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}",
                 [(set VR128:$dst, (v2f64 (vector_shuffle
                                           VR128:$src1, VR128:$src2,
                                           SHUFP_shuffle_mask:$src3)))]>;
  def SHUFPDrmi : PDIi8<0xC6, MRMSrcMem, 
                        (outs VR128:$dst), (ins VR128:$src1,
                        "shufpd\t{$src3, $src2, $dst|$dst, $src2, $src3}",
                        [(set VR128:$dst,
                          (v2f64 (vector_shuffle
                                  VR128:$src1, (memopv2f64 addr:$src2),
                                  SHUFP_shuffle_mask:$src3)))]>;

  let AddedComplexity = 10 in {
    def UNPCKHPDrr : PDI<0x15, MRMSrcReg, 
                         (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                         "unpckhpd\t{$src2, $dst|$dst, $src2}",
                         [(set VR128:$dst,
                           (v2f64 (vector_shuffle
                                   VR128:$src1, VR128:$src2,
                                   UNPCKH_shuffle_mask)))]>;
    def UNPCKHPDrm : PDI<0x15, MRMSrcMem, 
                         (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2),
                         "unpckhpd\t{$src2, $dst|$dst, $src2}",
                         [(set VR128:$dst,
                           (v2f64 (vector_shuffle
                                   VR128:$src1, (memopv2f64 addr:$src2),
                                   UNPCKH_shuffle_mask)))]>;

    def UNPCKLPDrr : PDI<0x14, MRMSrcReg, 
                         (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                         "unpcklpd\t{$src2, $dst|$dst, $src2}",
                         [(set VR128:$dst,
                           (v2f64 (vector_shuffle
                                   VR128:$src1, VR128:$src2,
                                   UNPCKL_shuffle_mask)))]>;
    def UNPCKLPDrm : PDI<0x14, MRMSrcMem, 
                         (outs VR128:$dst), (ins VR128:$src1, f128mem:$src2),
                         "unpcklpd\t{$src2, $dst|$dst, $src2}",
                         [(set VR128:$dst,
                           (v2f64 (vector_shuffle
                                   VR128:$src1, (memopv2f64 addr:$src2),
                                   UNPCKL_shuffle_mask)))]>;
  } // AddedComplexity
} // Constraints = "$src1 = $dst"
//===----------------------------------------------------------------------===//
// SSE integer instructions

// Move Instructions
Chris Lattner's avatar
Chris Lattner committed
let neverHasSideEffects = 1 in
def MOVDQArr : PDI<0x6F, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
                   "movdqa\t{$src, $dst|$dst, $src}", []>;
let canFoldAsLoad = 1, mayLoad = 1 in
def MOVDQArm : PDI<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
                   "movdqa\t{$src, $dst|$dst, $src}",
                   [/*(set VR128:$dst, (alignedloadv2i64 addr:$src))*/]>;
Chris Lattner's avatar
Chris Lattner committed
let mayStore = 1 in
def MOVDQAmr : PDI<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src),
                   "movdqa\t{$src, $dst|$dst, $src}",
                   [/*(alignedstore (v2i64 VR128:$src), addr:$dst)*/]>;
let canFoldAsLoad = 1, mayLoad = 1 in
def MOVDQUrm :   I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
                   "movdqu\t{$src, $dst|$dst, $src}",
                   [/*(set VR128:$dst, (loadv2i64 addr:$src))*/]>,
Evan Cheng's avatar
Evan Cheng committed
                 XS, Requires<[HasSSE2]>;
Chris Lattner's avatar
Chris Lattner committed
let mayStore = 1 in
def MOVDQUmr :   I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src),
                   "movdqu\t{$src, $dst|$dst, $src}",
                   [/*(store (v2i64 VR128:$src), addr:$dst)*/]>,
Evan Cheng's avatar
Evan Cheng committed
                 XS, Requires<[HasSSE2]>;
// Intrinsic forms of MOVDQU load and store
def MOVDQUrm_Int :   I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src),
                       "movdqu\t{$src, $dst|$dst, $src}",
                       [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>,
                 XS, Requires<[HasSSE2]>;
def MOVDQUmr_Int :   I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src),
                       "movdqu\t{$src, $dst|$dst, $src}",
                       [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>,
                     XS, Requires<[HasSSE2]>;
let Constraints = "$src1 = $dst" in {
Chris Lattner's avatar
Chris Lattner committed
multiclass PDI_binop_rm_int<bits<8> opc, string OpcodeStr, Intrinsic IntId,
                            bit Commutable = 0> {
  def rr : PDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (IntId VR128:$src1, VR128:$src2))]> {
    let isCommutable = Commutable;
  }
  def rm : PDI<opc, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (IntId VR128:$src1,
                                        (bitconvert (memopv2i64 addr:$src2))))]>;
multiclass PDI_binop_rmi_int<bits<8> opc, bits<8> opc2, Format ImmForm,
                             string OpcodeStr,
                             Intrinsic IntId, Intrinsic IntId2> {
  def rr : PDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (IntId VR128:$src1, VR128:$src2))]>;
  def rm : PDI<opc, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (IntId VR128:$src1,
                                        (bitconvert (memopv2i64 addr:$src2))))]>;
  def ri : PDIi8<opc2, ImmForm, (outs VR128:$dst), (ins VR128:$src1, i32i8imm:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (IntId2 VR128:$src1, (i32 imm:$src2)))]>;
}

/// PDI_binop_rm - Simple SSE2 binary operator.
multiclass PDI_binop_rm<bits<8> opc, string OpcodeStr, SDNode OpNode,
                        ValueType OpVT, bit Commutable = 0> {
  def rr : PDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (OpVT (OpNode VR128:$src1, VR128:$src2)))]> {
    let isCommutable = Commutable;
  }
  def rm : PDI<opc, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (OpVT (OpNode VR128:$src1,
                                       (bitconvert (memopv2i64 addr:$src2)))))]>;

/// PDI_binop_rm_v2i64 - Simple SSE2 binary operator whose type is v2i64.
///
/// FIXME: we could eliminate this and use PDI_binop_rm instead if tblgen knew
/// to collapse (bitconvert VT to VT) into its operand.
///
multiclass PDI_binop_rm_v2i64<bits<8> opc, string OpcodeStr, SDNode OpNode,
                              bit Commutable = 0> {
  def rr : PDI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (v2i64 (OpNode VR128:$src1, VR128:$src2)))]> {
    let isCommutable = Commutable;
  def rm : PDI<opc, MRMSrcMem, (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),
               !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"),
               [(set VR128:$dst, (OpNode VR128:$src1,(memopv2i64 addr:$src2)))]>;
} // Constraints = "$src1 = $dst"
// 128-bit Integer Arithmetic

defm PADDB : PDI_binop_rm<0xFC, "paddb", add, v16i8, 1>;
defm PADDW : PDI_binop_rm<0xFD, "paddw", add, v8i16, 1>;
defm PADDD : PDI_binop_rm<0xFE, "paddd", add, v4i32, 1>;
defm PADDQ : PDI_binop_rm_v2i64<0xD4, "paddq", add, 1>;
Chris Lattner's avatar
Chris Lattner committed
defm PADDSB  : PDI_binop_rm_int<0xEC, "paddsb" , int_x86_sse2_padds_b, 1>;
defm PADDSW  : PDI_binop_rm_int<0xED, "paddsw" , int_x86_sse2_padds_w, 1>;
defm PADDUSB : PDI_binop_rm_int<0xDC, "paddusb", int_x86_sse2_paddus_b, 1>;
defm PADDUSW : PDI_binop_rm_int<0xDD, "paddusw", int_x86_sse2_paddus_w, 1>;
defm PSUBB : PDI_binop_rm<0xF8, "psubb", sub, v16i8>;
defm PSUBW : PDI_binop_rm<0xF9, "psubw", sub, v8i16>;
defm PSUBD : PDI_binop_rm<0xFA, "psubd", sub, v4i32>;
defm PSUBQ : PDI_binop_rm_v2i64<0xFB, "psubq", sub>;
Chris Lattner's avatar
Chris Lattner committed
defm PSUBSB  : PDI_binop_rm_int<0xE8, "psubsb" , int_x86_sse2_psubs_b>;
defm PSUBSW  : PDI_binop_rm_int<0xE9, "psubsw" , int_x86_sse2_psubs_w>;
defm PSUBUSB : PDI_binop_rm_int<0xD8, "psubusb", int_x86_sse2_psubus_b>;
defm PSUBUSW : PDI_binop_rm_int<0xD9, "psubusw", int_x86_sse2_psubus_w>;
defm PMULLW : PDI_binop_rm<0xD5, "pmullw", mul, v8i16, 1>;
Chris Lattner's avatar
Chris Lattner committed
defm PMULHUW : PDI_binop_rm_int<0xE4, "pmulhuw", int_x86_sse2_pmulhu_w, 1>;
defm PMULHW  : PDI_binop_rm_int<0xE5, "pmulhw" , int_x86_sse2_pmulh_w , 1>;
defm PMULUDQ : PDI_binop_rm_int<0xF4, "pmuludq", int_x86_sse2_pmulu_dq, 1>;
Chris Lattner's avatar
Chris Lattner committed
defm PMADDWD : PDI_binop_rm_int<0xF5, "pmaddwd", int_x86_sse2_pmadd_wd, 1>;
Chris Lattner's avatar
Chris Lattner committed
defm PAVGB  : PDI_binop_rm_int<0xE0, "pavgb", int_x86_sse2_pavg_b, 1>;
defm PAVGW  : PDI_binop_rm_int<0xE3, "pavgw", int_x86_sse2_pavg_w, 1>;
Chris Lattner's avatar
Chris Lattner committed
defm PMINUB : PDI_binop_rm_int<0xDA, "pminub", int_x86_sse2_pminu_b, 1>;
defm PMINSW : PDI_binop_rm_int<0xEA, "pminsw", int_x86_sse2_pmins_w, 1>;
defm PMAXUB : PDI_binop_rm_int<0xDE, "pmaxub", int_x86_sse2_pmaxu_b, 1>;
defm PMAXSW : PDI_binop_rm_int<0xEE, "pmaxsw", int_x86_sse2_pmaxs_w, 1>;
defm PSADBW : PDI_binop_rm_int<0xE0, "psadbw", int_x86_sse2_psad_bw, 1>;
defm PSLLW : PDI_binop_rmi_int<0xF1, 0x71, MRM6r, "psllw",
                               int_x86_sse2_psll_w, int_x86_sse2_pslli_w>;
defm PSLLD : PDI_binop_rmi_int<0xF2, 0x72, MRM6r, "pslld",
                               int_x86_sse2_psll_d, int_x86_sse2_pslli_d>;
defm PSLLQ : PDI_binop_rmi_int<0xF3, 0x73, MRM6r, "psllq",
                               int_x86_sse2_psll_q, int_x86_sse2_pslli_q>;

defm PSRLW : PDI_binop_rmi_int<0xD1, 0x71, MRM2r, "psrlw",
                               int_x86_sse2_psrl_w, int_x86_sse2_psrli_w>;
defm PSRLD : PDI_binop_rmi_int<0xD2, 0x72, MRM2r, "psrld",
                               int_x86_sse2_psrl_d, int_x86_sse2_psrli_d>;
Nate Begeman's avatar
Nate Begeman committed
defm PSRLQ : PDI_binop_rmi_int<0xD3, 0x73, MRM2r, "psrlq",
                               int_x86_sse2_psrl_q, int_x86_sse2_psrli_q>;

defm PSRAW : PDI_binop_rmi_int<0xE1, 0x71, MRM4r, "psraw",
                               int_x86_sse2_psra_w, int_x86_sse2_psrai_w>;
defm PSRAD : PDI_binop_rmi_int<0xE2, 0x72, MRM4r, "psrad",
                               int_x86_sse2_psra_d, int_x86_sse2_psrai_d>;
Chris Lattner's avatar
Chris Lattner committed
// 128-bit logical shifts.
let Constraints = "$src1 = $dst", neverHasSideEffects = 1 in {
                       (outs VR128:$dst), (ins VR128:$src1, i32i8imm:$src2),
                       "pslldq\t{$src2, $dst|$dst, $src2}", []>;
                       (outs VR128:$dst), (ins VR128:$src1, i32i8imm:$src2),
                       "psrldq\t{$src2, $dst|$dst, $src2}", []>;
  // PSRADQri doesn't exist in SSE[1-3].
Chris Lattner's avatar
Chris Lattner committed
let Predicates = [HasSSE2] in {
  def : Pat<(int_x86_sse2_psll_dq VR128:$src1, imm:$src2),
            (v2i64 (PSLLDQri VR128:$src1, (PSxLDQ_imm imm:$src2)))>;
  def : Pat<(int_x86_sse2_psrl_dq VR128:$src1, imm:$src2),
            (v2i64 (PSRLDQri VR128:$src1, (PSxLDQ_imm imm:$src2)))>;
  def : Pat<(int_x86_sse2_psll_dq_bs VR128:$src1, imm:$src2),
            (v2i64 (PSLLDQri VR128:$src1, imm:$src2))>;
  def : Pat<(int_x86_sse2_psrl_dq_bs VR128:$src1, imm:$src2),
            (v2i64 (PSRLDQri VR128:$src1, imm:$src2))>;
  def : Pat<(v2f64 (X86fsrl VR128:$src1, i32immSExt8:$src2)),
            (v2f64 (PSRLDQri VR128:$src1, (PSxLDQ_imm imm:$src2)))>;

  // Shift up / down and insert zero's.
  def : Pat<(v2i64 (X86vshl  VR128:$src, (i8 imm:$amt))),
            (v2i64 (PSLLDQri VR128:$src, (PSxLDQ_imm imm:$amt)))>;
  def : Pat<(v2i64 (X86vshr  VR128:$src, (i8 imm:$amt))),
            (v2i64 (PSRLDQri VR128:$src, (PSxLDQ_imm imm:$amt)))>;
defm PAND : PDI_binop_rm_v2i64<0xDB, "pand", and, 1>;
defm POR  : PDI_binop_rm_v2i64<0xEB, "por" , or , 1>;
defm PXOR : PDI_binop_rm_v2i64<0xEF, "pxor", xor, 1>;
let Constraints = "$src1 = $dst" in {
                    (outs VR128:$dst), (ins VR128:$src1, VR128:$src2),
                    "pandn\t{$src2, $dst|$dst, $src2}",
                    [(set VR128:$dst, (v2i64 (and (vnot VR128:$src1),
                                              VR128:$src2)))]>;

  def PANDNrm : PDI<0xDF, MRMSrcMem,
                    (outs VR128:$dst), (ins VR128:$src1, i128mem:$src2),