def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>;
// MADD*/MSUB*
-def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, ISA_MIPS32;
-def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, ISA_MIPS32;
-def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, ISA_MIPS32;
-def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, ISA_MIPS32;
+def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>,
+ ISA_MIPS32_NOT_32R6_64R6;
let AdditionalPredicates = [NotDSP] in {
def PseudoMULT : MultDivPseudo<MULT, ACC64, GPR32Opnd, MipsMult, II_MULT>,
def PseudoMFHI : PseudoMFLOHI<GPR32, ACC64, MipsMFHI>, ISA_MIPS1_NOT_32R6_64R6;
def PseudoMFLO : PseudoMFLOHI<GPR32, ACC64, MipsMFLO>, ISA_MIPS1_NOT_32R6_64R6;
def PseudoMTLOHI : PseudoMTLOHI<ACC64, GPR32>, ISA_MIPS1_NOT_32R6_64R6;
-def PseudoMADD : MAddSubPseudo<MADD, MipsMAdd, II_MADD>;
-def PseudoMADDU : MAddSubPseudo<MADDU, MipsMAddu, II_MADDU>;
-def PseudoMSUB : MAddSubPseudo<MSUB, MipsMSub, II_MSUB>;
-def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>;
+def PseudoMADD : MAddSubPseudo<MADD, MipsMAdd, II_MADD>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def PseudoMADDU : MAddSubPseudo<MADDU, MipsMAddu, II_MADDU>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def PseudoMSUB : MAddSubPseudo<MSUB, MipsMSub, II_MSUB>,
+ ISA_MIPS32_NOT_32R6_64R6;
+def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>,
+ ISA_MIPS32_NOT_32R6_64R6;
}
def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV,
-; RUN: llc -march=mips < %s | FileCheck %s -check-prefix=32
-; RUN: llc -march=mips -mattr=dsp < %s | FileCheck %s -check-prefix=DSP
+; RUN: llc -march=mips -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32
+; RUN: llc -march=mips -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32
+; RUN: llc -march=mips -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=32R6
+; RUN: llc -march=mips -mcpu=mips32 -mattr=dsp < %s | FileCheck %s -check-prefix=DSP
+; RUN: llc -march=mips -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64
+; RUN: llc -march=mips -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64
+; RUN: llc -march=mips -mcpu=mips64r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=64R6
+
+; FIXME: The MIPS16 test should check its output
; RUN: llc -march=mips -mcpu=mips16 < %s
-; 32: madd ${{[0-9]+}}
-; DSP: madd $ac
+; ALL-LABEL: madd1:
+
+; 32-DAG: sra $[[T0:[0-9]+]], $6, 31
+; 32-DAG: mtlo $6
+; 32-DAG: [[m:m]]add ${{[45]}}, ${{[45]}}
+; 32-DAG: [[m]]fhi $2
+; 32-DAG: [[m]]flo $3
+
+; DSP-DAG: sra $[[T0:[0-9]+]], $6, 31
+; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6
+; DSP-DAG: madd $[[AC]], ${{[45]}}, ${{[45]}}
+; DSP-DAG: mfhi $2, $[[AC]]
+; DSP-DAG: mflo $3, $[[AC]]
+
+; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6
+; 32R6-DAG: sra $[[T3:[0-9]+]], $6, 31
+; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $[[T3]]
+; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: addu $2, $[[T5]], $[[T4]]
+
+; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]]
+; 64-DAG: [[m]]flo $[[T2:[0-9]+]]
+; 64-DAG: sll $[[T3:[0-9]+]], $6, 0
+; 64-DAG: daddu $2, $[[T2]], $[[T3]]
+
+; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]]
+; 64R6-DAG: sll $[[T3:[0-9]+]], $6, 0
+; 64R6-DAG: daddu $2, $[[T2]], $[[T3]]
+
define i64 @madd1(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64
ret i64 %add
}
-; 32: maddu ${{[0-9]+}}
-; DSP: maddu $ac
+; ALL-LABEL: madd2:
+
+; FIXME: We don't really need this instruction
+; 32-DAG: addiu $[[T0:[0-9]+]], $zero, 0
+; 32-DAG: mtlo $6
+; 32-DAG: [[m:m]]addu ${{[45]}}, ${{[45]}}
+; 32-DAG: [[m]]fhi $2
+; 32-DAG: [[m]]flo $3
+
+; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0
+; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6
+; DSP-DAG: maddu $[[AC]], ${{[45]}}, ${{[45]}}
+; DSP-DAG: mfhi $2, $[[AC]]
+; DSP-DAG: mflo $3, $[[AC]]
+
+; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6
+; FIXME: There's a redundant move here. We should remove it
+; 32R6-DAG: muhu $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: addu $2, $[[T3]], $[[T2]]
+
+; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32
+; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32
+; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32
+; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]]
+; 64-DAG: [[m]]flo $[[T4:[0-9]+]]
+; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32
+; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32
+; 64-DAG: daddu $2, $[[T4]], $[[T6]]
+
+; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32
+; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32
+; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32
+; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]]
+; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32
+; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32
+; 64R6-DAG: daddu $2, $[[T4]], $[[T6]]
+
define i64 @madd2(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = zext i32 %a to i64
ret i64 %add
}
-; 32: madd ${{[0-9]+}}
-; DSP: madd $ac
+; ALL-LABEL: madd3:
+
+; 32-DAG: mthi $6
+; 32-DAG: mtlo $7
+; 32-DAG: [[m:m]]add ${{[45]}}, ${{[45]}}
+; 32-DAG: [[m]]fhi $2
+; 32-DAG: [[m]]flo $3
+
+; DSP-DAG: mthi $[[AC:ac[0-3]+]], $6
+; DSP-DAG: mtlo $[[AC]], $7
+; DSP-DAG: madd $[[AC]], ${{[45]}}, ${{[45]}}
+; DSP-DAG: mfhi $2, $[[AC]]
+; DSP-DAG: mflo $3, $[[AC]]
+
+; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $7
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $7
+; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $6
+; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: addu $2, $[[T5]], $[[T4]]
+
+; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]]
+; 64-DAG: [[m]]flo $[[T2:[0-9]+]]
+; 64-DAG: daddu $2, $[[T2]], $6
+
+; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]]
+; 64R6-DAG: daddu $2, $[[T2]], $6
+
define i64 @madd3(i32 %a, i32 %b, i64 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64
ret i64 %add
}
-; 32: msub ${{[0-9]+}}
-; DSP: msub $ac
+; ALL-LABEL: msub1:
+
+; 32-DAG: sra $[[T0:[0-9]+]], $6, 31
+; 32-DAG: mtlo $6
+; 32-DAG: [[m:m]]sub ${{[45]}}, ${{[45]}}
+; 32-DAG: [[m]]fhi $2
+; 32-DAG: [[m]]flo $3
+
+; DSP-DAG: sra $[[T0:[0-9]+]], $6, 31
+; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6
+; DSP-DAG: msub $[[AC]], ${{[45]}}, ${{[45]}}
+; DSP-DAG: mfhi $2, $[[AC]]
+; DSP-DAG: mflo $3, $[[AC]]
+
+; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: sltu $[[T3:[0-9]+]], $6, $[[T1]]
+; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T3]], $[[T0]]
+; 32R6-DAG: sra $[[T5:[0-9]+]], $6, 31
+; 32R6-DAG: subu $2, $[[T5]], $[[T4]]
+; 32R6-DAG: subu $3, $6, $[[T1]]
+
+; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]]
+; 64-DAG: [[m]]flo $[[T2:[0-9]+]]
+; 64-DAG: sll $[[T3:[0-9]+]], $6, 0
+; 64-DAG: dsubu $2, $[[T3]], $[[T2]]
+
+; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]]
+; 64R6-DAG: sll $[[T3:[0-9]+]], $6, 0
+; 64R6-DAG: dsubu $2, $[[T3]], $[[T2]]
+
define i64 @msub1(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = sext i32 %c to i64
ret i64 %sub
}
-; 32: msubu ${{[0-9]+}}
-; DSP: msubu $ac
+; ALL-LABEL: msub2:
+
+; FIXME: We don't really need this instruction
+; 32-DAG: addiu $[[T0:[0-9]+]], $zero, 0
+; 32-DAG: mtlo $6
+; 32-DAG: [[m:m]]subu ${{[45]}}, ${{[45]}}
+; 32-DAG: [[m]]fhi $2
+; 32-DAG: [[m]]flo $3
+
+; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0
+; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6
+; DSP-DAG: msubu $[[AC]], ${{[45]}}, ${{[45]}}
+; DSP-DAG: mfhi $2, $[[AC]]
+; DSP-DAG: mflo $3, $[[AC]]
+
+; 32R6-DAG: muhu $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}}
+
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $6, $[[T1]]
+; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]]
+; 32R6-DAG: negu $2, $[[T3]]
+; 32R6-DAG: subu $3, $6, $[[T1]]
+
+; 64-DAG: dsll $[[T0:[0-9]+]], $4, 32
+; 64-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32
+; 64-DAG: dsll $[[T2:[0-9]+]], $5, 32
+; 64-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+; 64-DAG: d[[m:m]]ult $[[T3]], $[[T1]]
+; 64-DAG: [[m]]flo $[[T4:[0-9]+]]
+; 64-DAG: dsll $[[T5:[0-9]+]], $6, 32
+; 64-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32
+; 64-DAG: dsubu $2, $[[T6]], $[[T4]]
+
+; 64R6-DAG: dsll $[[T0:[0-9]+]], $4, 32
+; 64R6-DAG: dsrl $[[T1:[0-9]+]], $[[T0]], 32
+; 64R6-DAG: dsll $[[T2:[0-9]+]], $5, 32
+; 64R6-DAG: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+; 64R6-DAG: dmul $[[T4:[0-9]+]], $[[T3]], $[[T1]]
+; 64R6-DAG: dsll $[[T5:[0-9]+]], $6, 32
+; 64R6-DAG: dsrl $[[T6:[0-9]+]], $[[T5]], 32
+; 64R6-DAG: dsubu $2, $[[T6]], $[[T4]]
+
define i64 @msub2(i32 %a, i32 %b, i32 %c) nounwind readnone {
entry:
%conv = zext i32 %c to i64
ret i64 %sub
}
-; 32: msub ${{[0-9]+}}
-; DSP: msub $ac
+; ALL-LABEL: msub3:
+
+; FIXME: We don't really need this instruction
+; 32-DAG: mthi $6
+; 32-DAG: mtlo $7
+; 32-DAG: [[m:m]]sub ${{[45]}}, ${{[45]}}
+; 32-DAG: [[m]]fhi $2
+; 32-DAG: [[m]]flo $3
+
+; DSP-DAG: addiu $[[T0:[0-9]+]], $zero, 0
+; DSP-DAG: mtlo $[[AC:ac[0-3]+]], $6
+; DSP-DAG: msub $[[AC]], ${{[45]}}, ${{[45]}}
+; DSP-DAG: mfhi $2, $[[AC]]
+; DSP-DAG: mflo $3, $[[AC]]
+
+; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $7, $[[T1]]
+; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]]
+; 32R6-DAG: subu $2, $6, $[[T3]]
+; 32R6-DAG: subu $3, $7, $[[T1]]
+
+; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64-DAG: d[[m:m]]ult $[[T1]], $[[T0]]
+; 64-DAG: [[m]]flo $[[T2:[0-9]+]]
+; 64-DAG: dsubu $2, $6, $[[T2]]
+
+; 64R6-DAG: sll $[[T0:[0-9]+]], $4, 0
+; 64R6-DAG: sll $[[T1:[0-9]+]], $5, 0
+; 64R6-DAG: dmul $[[T2:[0-9]+]], $[[T1]], $[[T0]]
+; 64R6-DAG: dsubu $2, $6, $[[T2]]
+
define i64 @msub3(i32 %a, i32 %b, i64 %c) nounwind readnone {
entry:
%conv = sext i32 %a to i64