Commit 65fd5e11 authored by Ilija.Pavlovic's avatar Ilija.Pavlovic Committed by Commit bot

MIPS: Implement MADD.S, MSUB, MADDF and MSUBF.

Implementation MADD.S. MSUB.fmt, MADDF.fmt, MSUBF.fmt and corresponding
tests for assembler and disassembler.

TEST=cctest/test-assembler-mips[64], cctest/test-disasm-mips[64]
BUG=

Review-Url: https://codereview.chromium.org/2313623002
Cr-Commit-Position: refs/heads/master@{#39415}
parent 3999fb07
...@@ -2453,6 +2453,11 @@ void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) { ...@@ -2453,6 +2453,11 @@ void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
GenInstrRegister(COP1, D, ft, fs, fd, MUL_D); GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
} }
void Assembler::madd_s(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r2));
GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_S);
}
void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs, void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) { FPURegister ft) {
...@@ -2460,6 +2465,37 @@ void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs, ...@@ -2460,6 +2465,37 @@ void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D); GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
} }
void Assembler::msub_s(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r2));
GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_S);
}
void Assembler::msub_d(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r2));
GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_D);
}
void Assembler::maddf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, S, ft, fs, fd, MADDF_S);
}
void Assembler::maddf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, D, ft, fs, fd, MADDF_D);
}
void Assembler::msubf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, S, ft, fs, fd, MSUBF_S);
}
void Assembler::msubf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, D, ft, fs, fd, MSUBF_D);
}
void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) { void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) {
GenInstrRegister(COP1, S, ft, fs, fd, DIV_S); GenInstrRegister(COP1, S, ft, fs, fd, DIV_S);
......
...@@ -878,7 +878,14 @@ class Assembler : public AssemblerBase { ...@@ -878,7 +878,14 @@ class Assembler : public AssemblerBase {
void sub_d(FPURegister fd, FPURegister fs, FPURegister ft); void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
void mul_s(FPURegister fd, FPURegister fs, FPURegister ft); void mul_s(FPURegister fd, FPURegister fs, FPURegister ft);
void mul_d(FPURegister fd, FPURegister fs, FPURegister ft); void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
void madd_s(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft); void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void msub_s(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void msub_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void maddf_s(FPURegister fd, FPURegister fs, FPURegister ft);
void maddf_d(FPURegister fd, FPURegister fs, FPURegister ft);
void msubf_s(FPURegister fd, FPURegister fs, FPURegister ft);
void msubf_d(FPURegister fd, FPURegister fs, FPURegister ft);
void div_s(FPURegister fd, FPURegister fs, FPURegister ft); void div_s(FPURegister fd, FPURegister fs, FPURegister ft);
void div_d(FPURegister fd, FPURegister fs, FPURegister ft); void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
void abs_s(FPURegister fd, FPURegister fs); void abs_s(FPURegister fd, FPURegister fs);
......
...@@ -525,6 +525,8 @@ enum SecondaryField : uint32_t { ...@@ -525,6 +525,8 @@ enum SecondaryField : uint32_t {
FLOOR_W_S = ((1U << 3) + 7), FLOOR_W_S = ((1U << 3) + 7),
RECIP_S = ((2U << 3) + 5), RECIP_S = ((2U << 3) + 5),
RSQRT_S = ((2U << 3) + 6), RSQRT_S = ((2U << 3) + 6),
MADDF_S = ((3U << 3) + 0),
MSUBF_S = ((3U << 3) + 1),
CLASS_S = ((3U << 3) + 3), CLASS_S = ((3U << 3) + 3),
CVT_D_S = ((4U << 3) + 1), CVT_D_S = ((4U << 3) + 1),
CVT_W_S = ((4U << 3) + 4), CVT_W_S = ((4U << 3) + 4),
...@@ -550,6 +552,8 @@ enum SecondaryField : uint32_t { ...@@ -550,6 +552,8 @@ enum SecondaryField : uint32_t {
FLOOR_W_D = ((1U << 3) + 7), FLOOR_W_D = ((1U << 3) + 7),
RECIP_D = ((2U << 3) + 5), RECIP_D = ((2U << 3) + 5),
RSQRT_D = ((2U << 3) + 6), RSQRT_D = ((2U << 3) + 6),
MADDF_D = ((3U << 3) + 0),
MSUBF_D = ((3U << 3) + 1),
CLASS_D = ((3U << 3) + 3), CLASS_D = ((3U << 3) + 3),
MIN = ((3U << 3) + 4), MIN = ((3U << 3) + 4),
MINA = ((3U << 3) + 5), MINA = ((3U << 3) + 5),
...@@ -616,8 +620,12 @@ enum SecondaryField : uint32_t { ...@@ -616,8 +620,12 @@ enum SecondaryField : uint32_t {
MOVF = ((2U << 3) + 1), // Function field for MOVT.fmt and MOVF.fmt MOVF = ((2U << 3) + 1), // Function field for MOVT.fmt and MOVF.fmt
SELNEZ_C = ((2U << 3) + 7), // COP1 on FPR registers. SELNEZ_C = ((2U << 3) + 7), // COP1 on FPR registers.
// COP1 Encoding of Function Field When rs=PS. // COP1 Encoding of Function Field When rs=PS.
// COP1X Encoding of Function Field. // COP1X Encoding of Function Field.
MADD_S = ((4U << 3) + 0),
MADD_D = ((4U << 3) + 1), MADD_D = ((4U << 3) + 1),
MSUB_S = ((5U << 3) + 0),
MSUB_D = ((5U << 3) + 1),
// PCREL Encoding of rt Field. // PCREL Encoding of rt Field.
ADDIUPC = ((0U << 2) + 0), ADDIUPC = ((0U << 2) + 0),
......
...@@ -918,6 +918,12 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) { ...@@ -918,6 +918,12 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
case CVT_D_S: case CVT_D_S:
Format(instr, "cvt.d.'t 'fd, 'fs"); Format(instr, "cvt.d.'t 'fd, 'fs");
break; break;
case MADDF_S:
Format(instr, "maddf.s 'fd, 'fs, 'ft");
break;
case MSUBF_S:
Format(instr, "msubf.s 'fd, 'fs, 'ft");
break;
default: default:
Format(instr, "unknown.cop1.'t"); Format(instr, "unknown.cop1.'t");
break; break;
...@@ -928,7 +934,17 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) { ...@@ -928,7 +934,17 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) { void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) {
if (!DecodeTypeRegisterRsType(instr)) { if (!DecodeTypeRegisterRsType(instr)) {
Format(instr, "unknown.cop1.'t"); switch (instr->FunctionFieldRaw()) {
case MADDF_D:
Format(instr, "maddf.d 'fd, 'fs, 'ft");
break;
case MSUBF_D:
Format(instr, "msubf.d 'fd, 'fs, 'ft");
break;
default:
Format(instr, "unknown.cop1.'t");
break;
}
} }
} }
...@@ -1360,9 +1376,18 @@ void Decoder::DecodeTypeRegister(Instruction* instr) { ...@@ -1360,9 +1376,18 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
break; break;
case COP1X: case COP1X:
switch (instr->FunctionFieldRaw()) { switch (instr->FunctionFieldRaw()) {
case MADD_S:
Format(instr, "madd.s 'fd, 'fr, 'fs, 'ft");
break;
case MADD_D: case MADD_D:
Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
break; break;
case MSUB_S:
Format(instr, "msub.s 'fd, 'fr, 'fs, 'ft");
break;
case MSUB_D:
Format(instr, "msub.d 'fd, 'fr, 'fs, 'ft");
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -2482,6 +2482,14 @@ void Simulator::DecodeTypeRegisterDRsType() { ...@@ -2482,6 +2482,14 @@ void Simulator::DecodeTypeRegisterDRsType() {
case SUB_D: case SUB_D:
set_fpu_register_double(fd_reg(), fs - ft); set_fpu_register_double(fd_reg(), fs - ft);
break; break;
case MADDF_D:
DCHECK(IsMipsArchVariant(kMips32r6));
set_fpu_register_double(fd_reg(), fd + (fs * ft));
break;
case MSUBF_D:
DCHECK(IsMipsArchVariant(kMips32r6));
set_fpu_register_double(fd_reg(), fd - (fs * ft));
break;
case MUL_D: case MUL_D:
set_fpu_register_double(fd_reg(), fs * ft); set_fpu_register_double(fd_reg(), fs * ft);
break; break;
...@@ -2887,6 +2895,14 @@ void Simulator::DecodeTypeRegisterSRsType() { ...@@ -2887,6 +2895,14 @@ void Simulator::DecodeTypeRegisterSRsType() {
case SUB_S: case SUB_S:
set_fpu_register_float(fd_reg(), fs - ft); set_fpu_register_float(fd_reg(), fs - ft);
break; break;
case MADDF_S:
DCHECK(IsMipsArchVariant(kMips32r6));
set_fpu_register_float(fd_reg(), fd + (fs * ft));
break;
case MSUBF_S:
DCHECK(IsMipsArchVariant(kMips32r6));
set_fpu_register_float(fd_reg(), fd - (fs * ft));
break;
case MUL_S: case MUL_S:
set_fpu_register_float(fd_reg(), fs * ft); set_fpu_register_float(fd_reg(), fs * ft);
break; break;
...@@ -3375,13 +3391,42 @@ void Simulator::DecodeTypeRegisterCOP1() { ...@@ -3375,13 +3391,42 @@ void Simulator::DecodeTypeRegisterCOP1() {
void Simulator::DecodeTypeRegisterCOP1X() { void Simulator::DecodeTypeRegisterCOP1X() {
switch (get_instr()->FunctionFieldRaw()) { switch (get_instr()->FunctionFieldRaw()) {
case MADD_D: case MADD_S: {
DCHECK(IsMipsArchVariant(kMips32r2));
float fr, ft, fs;
fr = get_fpu_register_float(fr_reg());
fs = get_fpu_register_float(fs_reg());
ft = get_fpu_register_float(ft_reg());
set_fpu_register_float(fd_reg(), fs * ft + fr);
break;
}
case MSUB_S: {
DCHECK(IsMipsArchVariant(kMips32r2));
float fr, ft, fs;
fr = get_fpu_register_float(fr_reg());
fs = get_fpu_register_float(fs_reg());
ft = get_fpu_register_float(ft_reg());
set_fpu_register_float(fd_reg(), fs * ft - fr);
break;
}
case MADD_D: {
DCHECK(IsMipsArchVariant(kMips32r2));
double fr, ft, fs; double fr, ft, fs;
fr = get_fpu_register_double(fr_reg()); fr = get_fpu_register_double(fr_reg());
fs = get_fpu_register_double(fs_reg()); fs = get_fpu_register_double(fs_reg());
ft = get_fpu_register_double(ft_reg()); ft = get_fpu_register_double(ft_reg());
set_fpu_register_double(fd_reg(), fs * ft + fr); set_fpu_register_double(fd_reg(), fs * ft + fr);
break; break;
}
case MSUB_D: {
DCHECK(IsMipsArchVariant(kMips32r2));
double fr, ft, fs;
fr = get_fpu_register_double(fr_reg());
fs = get_fpu_register_double(fs_reg());
ft = get_fpu_register_double(ft_reg());
set_fpu_register_double(fd_reg(), fs * ft - fr);
break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -2780,12 +2780,49 @@ void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) { ...@@ -2780,12 +2780,49 @@ void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
GenInstrRegister(COP1, D, ft, fs, fd, MUL_D); GenInstrRegister(COP1, D, ft, fs, fd, MUL_D);
} }
void Assembler::madd_s(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) {
DCHECK(kArchVariant == kMips64r2);
GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_S);
}
void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs, void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) { FPURegister ft) {
DCHECK(kArchVariant == kMips64r2);
GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D); GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D);
} }
void Assembler::msub_s(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) {
DCHECK(kArchVariant == kMips64r2);
GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_S);
}
void Assembler::msub_d(FPURegister fd, FPURegister fr, FPURegister fs,
FPURegister ft) {
DCHECK(kArchVariant == kMips64r2);
GenInstrRegister(COP1X, fr, ft, fs, fd, MSUB_D);
}
void Assembler::maddf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(COP1, S, ft, fs, fd, MADDF_S);
}
void Assembler::maddf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(COP1, D, ft, fs, fd, MADDF_D);
}
void Assembler::msubf_s(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(COP1, S, ft, fs, fd, MSUBF_S);
}
void Assembler::msubf_d(FPURegister fd, FPURegister fs, FPURegister ft) {
DCHECK(kArchVariant == kMips64r6);
GenInstrRegister(COP1, D, ft, fs, fd, MSUBF_D);
}
void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) { void Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) {
GenInstrRegister(COP1, S, ft, fs, fd, DIV_D); GenInstrRegister(COP1, S, ft, fs, fd, DIV_D);
......
...@@ -939,7 +939,14 @@ class Assembler : public AssemblerBase { ...@@ -939,7 +939,14 @@ class Assembler : public AssemblerBase {
void sub_d(FPURegister fd, FPURegister fs, FPURegister ft); void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
void mul_s(FPURegister fd, FPURegister fs, FPURegister ft); void mul_s(FPURegister fd, FPURegister fs, FPURegister ft);
void mul_d(FPURegister fd, FPURegister fs, FPURegister ft); void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
void madd_s(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft); void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void msub_s(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void msub_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
void maddf_s(FPURegister fd, FPURegister fs, FPURegister ft);
void maddf_d(FPURegister fd, FPURegister fs, FPURegister ft);
void msubf_s(FPURegister fd, FPURegister fs, FPURegister ft);
void msubf_d(FPURegister fd, FPURegister fs, FPURegister ft);
void div_s(FPURegister fd, FPURegister fs, FPURegister ft); void div_s(FPURegister fd, FPURegister fs, FPURegister ft);
void div_d(FPURegister fd, FPURegister fs, FPURegister ft); void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
void abs_s(FPURegister fd, FPURegister fs); void abs_s(FPURegister fd, FPURegister fs);
......
...@@ -555,6 +555,8 @@ enum SecondaryField : uint32_t { ...@@ -555,6 +555,8 @@ enum SecondaryField : uint32_t {
FLOOR_W_S = ((1U << 3) + 7), FLOOR_W_S = ((1U << 3) + 7),
RECIP_S = ((2U << 3) + 5), RECIP_S = ((2U << 3) + 5),
RSQRT_S = ((2U << 3) + 6), RSQRT_S = ((2U << 3) + 6),
MADDF_S = ((3U << 3) + 0),
MSUBF_S = ((3U << 3) + 1),
CLASS_S = ((3U << 3) + 3), CLASS_S = ((3U << 3) + 3),
CVT_D_S = ((4U << 3) + 1), CVT_D_S = ((4U << 3) + 1),
CVT_W_S = ((4U << 3) + 4), CVT_W_S = ((4U << 3) + 4),
...@@ -579,6 +581,8 @@ enum SecondaryField : uint32_t { ...@@ -579,6 +581,8 @@ enum SecondaryField : uint32_t {
FLOOR_W_D = ((1U << 3) + 7), FLOOR_W_D = ((1U << 3) + 7),
RECIP_D = ((2U << 3) + 5), RECIP_D = ((2U << 3) + 5),
RSQRT_D = ((2U << 3) + 6), RSQRT_D = ((2U << 3) + 6),
MADDF_D = ((3U << 3) + 0),
MSUBF_D = ((3U << 3) + 1),
CLASS_D = ((3U << 3) + 3), CLASS_D = ((3U << 3) + 3),
MIN = ((3U << 3) + 4), MIN = ((3U << 3) + 4),
MINA = ((3U << 3) + 5), MINA = ((3U << 3) + 5),
...@@ -646,8 +650,12 @@ enum SecondaryField : uint32_t { ...@@ -646,8 +650,12 @@ enum SecondaryField : uint32_t {
SELNEZ_C = ((2U << 3) + 7), // COP1 on FPR registers. SELNEZ_C = ((2U << 3) + 7), // COP1 on FPR registers.
// COP1 Encoding of Function Field When rs=PS. // COP1 Encoding of Function Field When rs=PS.
// COP1X Encoding of Function Field. // COP1X Encoding of Function Field.
MADD_S = ((4U << 3) + 0),
MADD_D = ((4U << 3) + 1), MADD_D = ((4U << 3) + 1),
MSUB_S = ((5U << 3) + 0),
MSUB_D = ((5U << 3) + 1),
// PCREL Encoding of rt Field. // PCREL Encoding of rt Field.
ADDIUPC = ((0U << 2) + 0), ADDIUPC = ((0U << 2) + 0),
......
...@@ -959,6 +959,12 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) { ...@@ -959,6 +959,12 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
case CVT_D_S: case CVT_D_S:
Format(instr, "cvt.d.'t 'fd, 'fs"); Format(instr, "cvt.d.'t 'fd, 'fs");
break; break;
case MADDF_S:
Format(instr, "maddf.s 'fd, 'fs, 'ft");
break;
case MSUBF_S:
Format(instr, "msubf.s 'fd, 'fs, 'ft");
break;
default: default:
Format(instr, "unknown.cop1.'t"); Format(instr, "unknown.cop1.'t");
break; break;
...@@ -969,7 +975,17 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) { ...@@ -969,7 +975,17 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) { void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) {
if (!DecodeTypeRegisterRsType(instr)) { if (!DecodeTypeRegisterRsType(instr)) {
Format(instr, "unknown.cop1.'t"); switch (instr->FunctionFieldRaw()) {
case MADDF_D:
Format(instr, "maddf.d 'fd, 'fs, 'ft");
break;
case MSUBF_D:
Format(instr, "msubf.d 'fd, 'fs, 'ft");
break;
default:
Format(instr, "unknown.cop1.'t");
break;
}
} }
} }
...@@ -1115,9 +1131,18 @@ void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) { ...@@ -1115,9 +1131,18 @@ void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) {
void Decoder::DecodeTypeRegisterCOP1X(Instruction* instr) { void Decoder::DecodeTypeRegisterCOP1X(Instruction* instr) {
switch (instr->FunctionFieldRaw()) { switch (instr->FunctionFieldRaw()) {
case MADD_S:
Format(instr, "madd.s 'fd, 'fr, 'fs, 'ft");
break;
case MADD_D: case MADD_D:
Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
break; break;
case MSUB_S:
Format(instr, "msub.s 'fd, 'fr, 'fs, 'ft");
break;
case MSUB_D:
Format(instr, "msub.d 'fd, 'fr, 'fs, 'ft");
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -2421,6 +2421,14 @@ void Simulator::DecodeTypeRegisterSRsType() { ...@@ -2421,6 +2421,14 @@ void Simulator::DecodeTypeRegisterSRsType() {
case SUB_S: case SUB_S:
set_fpu_register_float(fd_reg(), fs - ft); set_fpu_register_float(fd_reg(), fs - ft);
break; break;
case MADDF_S:
DCHECK(kArchVariant == kMips64r6);
set_fpu_register_float(fd_reg(), fd + (fs * ft));
break;
case MSUBF_S:
DCHECK(kArchVariant == kMips64r6);
set_fpu_register_float(fd_reg(), fd - (fs * ft));
break;
case MUL_S: case MUL_S:
set_fpu_register_float(fd_reg(), fs * ft); set_fpu_register_float(fd_reg(), fs * ft);
break; break;
...@@ -2824,6 +2832,14 @@ void Simulator::DecodeTypeRegisterDRsType() { ...@@ -2824,6 +2832,14 @@ void Simulator::DecodeTypeRegisterDRsType() {
case SUB_D: case SUB_D:
set_fpu_register_double(fd_reg(), fs - ft); set_fpu_register_double(fd_reg(), fs - ft);
break; break;
case MADDF_D:
DCHECK(kArchVariant == kMips64r6);
set_fpu_register_double(fd_reg(), fd + (fs * ft));
break;
case MSUBF_D:
DCHECK(kArchVariant == kMips64r6);
set_fpu_register_double(fd_reg(), fd - (fs * ft));
break;
case MUL_D: case MUL_D:
set_fpu_register_double(fd_reg(), fs * ft); set_fpu_register_double(fd_reg(), fs * ft);
break; break;
...@@ -3305,13 +3321,42 @@ void Simulator::DecodeTypeRegisterCOP1() { ...@@ -3305,13 +3321,42 @@ void Simulator::DecodeTypeRegisterCOP1() {
void Simulator::DecodeTypeRegisterCOP1X() { void Simulator::DecodeTypeRegisterCOP1X() {
switch (get_instr()->FunctionFieldRaw()) { switch (get_instr()->FunctionFieldRaw()) {
case MADD_D: case MADD_S: {
DCHECK(kArchVariant == kMips64r2);
float fr, ft, fs;
fr = get_fpu_register_float(fr_reg());
fs = get_fpu_register_float(fs_reg());
ft = get_fpu_register_float(ft_reg());
set_fpu_register_float(fd_reg(), fs * ft + fr);
break;
}
case MSUB_S: {
DCHECK(kArchVariant == kMips64r2);
float fr, ft, fs;
fr = get_fpu_register_float(fr_reg());
fs = get_fpu_register_float(fs_reg());
ft = get_fpu_register_float(ft_reg());
set_fpu_register_float(fd_reg(), fs * ft - fr);
break;
}
case MADD_D: {
DCHECK(kArchVariant == kMips64r2);
double fr, ft, fs; double fr, ft, fs;
fr = get_fpu_register_double(fr_reg()); fr = get_fpu_register_double(fr_reg());
fs = get_fpu_register_double(fs_reg()); fs = get_fpu_register_double(fs_reg());
ft = get_fpu_register_double(ft_reg()); ft = get_fpu_register_double(ft_reg());
set_fpu_register_double(fd_reg(), fs * ft + fr); set_fpu_register_double(fd_reg(), fs * ft + fr);
break; break;
}
case MSUB_D: {
DCHECK(kArchVariant == kMips64r2);
double fr, ft, fs;
fr = get_fpu_register_double(fr_reg());
fs = get_fpu_register_double(fs_reg());
ft = get_fpu_register_double(ft_reg());
set_fpu_register_double(fd_reg(), fs * ft - fr);
break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -5386,4 +5386,128 @@ TEST(Trampoline) { ...@@ -5386,4 +5386,128 @@ TEST(Trampoline) {
CHECK_EQ(res, 0); CHECK_EQ(res, 0);
} }
template <class T>
struct TestCaseMaddMsub {
T fr, fs, ft, fd_add, fd_sub;
};
template <typename T, typename F>
void helper_madd_msub_maddf_msubf(F func) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
T x = std::sqrt(static_cast<T>(2.0));
T y = std::sqrt(static_cast<T>(3.0));
T z = std::sqrt(static_cast<T>(5.0));
T x2 = 11.11, y2 = 22.22, z2 = 33.33;
TestCaseMaddMsub<T> test_cases[] = {
{x, y, z, 0.0, 0.0},
{x, y, -z, 0.0, 0.0},
{x, -y, z, 0.0, 0.0},
{x, -y, -z, 0.0, 0.0},
{-x, y, z, 0.0, 0.0},
{-x, y, -z, 0.0, 0.0},
{-x, -y, z, 0.0, 0.0},
{-x, -y, -z, 0.0, 0.0},
{-3.14, 0.2345, -123.000056, 0.0, 0.0},
{7.3, -23.257, -357.1357, 0.0, 0.0},
{x2, y2, z2, 0.0, 0.0},
{x2, y2, -z2, 0.0, 0.0},
{x2, -y2, z2, 0.0, 0.0},
{x2, -y2, -z2, 0.0, 0.0},
{-x2, y2, z2, 0.0, 0.0},
{-x2, y2, -z2, 0.0, 0.0},
{-x2, -y2, z2, 0.0, 0.0},
{-x2, -y2, -z2, 0.0, 0.0},
};
if (std::is_same<T, float>::value) {
__ lwc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
__ lwc1(f6, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fs)));
__ lwc1(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, ft)));
__ lwc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
} else if (std::is_same<T, double>::value) {
__ ldc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
__ ldc1(f6, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fs)));
__ ldc1(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, ft)));
__ ldc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
} else {
UNREACHABLE();
}
func(assm);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F3 f = FUNCTION_CAST<F3>(code->entry());
const size_t kTableLength = sizeof(test_cases) / sizeof(TestCaseMaddMsub<T>);
TestCaseMaddMsub<T> tc;
for (size_t i = 0; i < kTableLength; i++) {
tc.fr = test_cases[i].fr;
tc.fs = test_cases[i].fs;
tc.ft = test_cases[i].ft;
(CALL_GENERATED_CODE(isolate, f, &tc, 0, 0, 0, 0));
T res_add = tc.fr + (tc.fs * tc.ft);
T res_sub;
if (IsMipsArchVariant(kMips32r2)) {
res_sub = (tc.fs * tc.ft) - tc.fr;
} else if (IsMipsArchVariant(kMips32r6)) {
res_sub = tc.fr - (tc.fs * tc.ft);
}
CHECK_EQ(tc.fd_add, res_add);
CHECK_EQ(tc.fd_sub, res_sub);
}
}
TEST(madd_msub_s) {
if (!IsMipsArchVariant(kMips32r2)) return;
helper_madd_msub_maddf_msubf<float>([](MacroAssembler& assm) {
__ madd_s(f10, f4, f6, f8);
__ swc1(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_add)));
__ msub_s(f16, f4, f6, f8);
__ swc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_sub)));
});
}
TEST(madd_msub_d) {
if (!IsMipsArchVariant(kMips32r2)) return;
helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) {
__ madd_d(f10, f4, f6, f8);
__ sdc1(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add)));
__ msub_d(f16, f4, f6, f8);
__ sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub)));
});
}
TEST(maddf_msubf_s) {
if (!IsMipsArchVariant(kMips32r6)) return;
helper_madd_msub_maddf_msubf<float>([](MacroAssembler& assm) {
__ maddf_s(f4, f6, f8);
__ swc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_add)));
__ msubf_s(f16, f6, f8);
__ swc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_sub)));
});
}
TEST(maddf_msubf_d) {
if (!IsMipsArchVariant(kMips32r6)) return;
helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) {
__ maddf_d(f4, f6, f8);
__ sdc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add)));
__ msubf_d(f16, f6, f8);
__ sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub)));
});
}
#undef __ #undef __
...@@ -5934,5 +5934,128 @@ TEST(Trampoline) { ...@@ -5934,5 +5934,128 @@ TEST(Trampoline) {
CHECK_EQ(res, 0); CHECK_EQ(res, 0);
} }
template <class T>
struct TestCaseMaddMsub {
T fr, fs, ft, fd_add, fd_sub;
};
template <typename T, typename F>
void helper_madd_msub_maddf_msubf(F func) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
T x = std::sqrt(static_cast<T>(2.0));
T y = std::sqrt(static_cast<T>(3.0));
T z = std::sqrt(static_cast<T>(5.0));
T x2 = 11.11, y2 = 22.22, z2 = 33.33;
TestCaseMaddMsub<T> test_cases[] = {
{x, y, z, 0.0, 0.0},
{x, y, -z, 0.0, 0.0},
{x, -y, z, 0.0, 0.0},
{x, -y, -z, 0.0, 0.0},
{-x, y, z, 0.0, 0.0},
{-x, y, -z, 0.0, 0.0},
{-x, -y, z, 0.0, 0.0},
{-x, -y, -z, 0.0, 0.0},
{-3.14, 0.2345, -123.000056, 0.0, 0.0},
{7.3, -23.257, -357.1357, 0.0, 0.0},
{x2, y2, z2, 0.0, 0.0},
{x2, y2, -z2, 0.0, 0.0},
{x2, -y2, z2, 0.0, 0.0},
{x2, -y2, -z2, 0.0, 0.0},
{-x2, y2, z2, 0.0, 0.0},
{-x2, y2, -z2, 0.0, 0.0},
{-x2, -y2, z2, 0.0, 0.0},
{-x2, -y2, -z2, 0.0, 0.0},
};
if (std::is_same<T, float>::value) {
__ lwc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
__ lwc1(f6, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fs)));
__ lwc1(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, ft)));
__ lwc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
} else if (std::is_same<T, double>::value) {
__ ldc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
__ ldc1(f6, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fs)));
__ ldc1(f8, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, ft)));
__ ldc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<T>, fr)));
} else {
UNREACHABLE();
}
func(assm);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F3 f = FUNCTION_CAST<F3>(code->entry());
const size_t kTableLength = sizeof(test_cases) / sizeof(TestCaseMaddMsub<T>);
TestCaseMaddMsub<T> tc;
for (size_t i = 0; i < kTableLength; i++) {
tc.fr = test_cases[i].fr;
tc.fs = test_cases[i].fs;
tc.ft = test_cases[i].ft;
(CALL_GENERATED_CODE(isolate, f, &tc, 0, 0, 0, 0));
T res_add = tc.fr + (tc.fs * tc.ft);
T res_sub;
if (kArchVariant != kMips64r6) {
res_sub = (tc.fs * tc.ft) - tc.fr;
} else {
res_sub = tc.fr - (tc.fs * tc.ft);
}
CHECK_EQ(tc.fd_add, res_add);
CHECK_EQ(tc.fd_sub, res_sub);
}
}
TEST(madd_msub_s) {
if (kArchVariant == kMips64r6) return;
helper_madd_msub_maddf_msubf<float>([](MacroAssembler& assm) {
__ madd_s(f10, f4, f6, f8);
__ swc1(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_add)));
__ msub_s(f16, f4, f6, f8);
__ swc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_sub)));
});
}
TEST(madd_msub_d) {
if (kArchVariant == kMips64r6) return;
helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) {
__ madd_d(f10, f4, f6, f8);
__ sdc1(f10, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add)));
__ msub_d(f16, f4, f6, f8);
__ sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub)));
});
}
TEST(maddf_msubf_s) {
if (kArchVariant != kMips64r6) return;
helper_madd_msub_maddf_msubf<float>([](MacroAssembler& assm) {
__ maddf_s(f4, f6, f8);
__ swc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_add)));
__ msubf_s(f16, f6, f8);
__ swc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<float>, fd_sub)));
});
}
TEST(maddf_msubf_d) {
if (kArchVariant != kMips64r6) return;
helper_madd_msub_maddf_msubf<double>([](MacroAssembler& assm) {
__ maddf_d(f4, f6, f8);
__ sdc1(f4, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_add)));
__ msubf_d(f16, f6, f8);
__ sdc1(f16, MemOperand(a0, offsetof(TestCaseMaddMsub<double>, fd_sub)));
});
}
#undef __ #undef __
...@@ -1090,3 +1090,20 @@ TEST(ctc1_cfc1_disasm) { ...@@ -1090,3 +1090,20 @@ TEST(ctc1_cfc1_disasm) {
COMPARE(cfc1(a0, FCSR), "4444f800 cfc1 a0, FCSR"); COMPARE(cfc1(a0, FCSR), "4444f800 cfc1 a0, FCSR");
VERIFY_RUN(); VERIFY_RUN();
} }
TEST(madd_msub_maddf_msubf) {
SET_UP();
if (IsMipsArchVariant(kMips32r2)) {
COMPARE(madd_s(f4, f6, f8, f10), "4cca4120 madd.s f4, f6, f8, f10");
COMPARE(madd_d(f4, f6, f8, f10), "4cca4121 madd.d f4, f6, f8, f10");
COMPARE(msub_s(f4, f6, f8, f10), "4cca4128 msub.s f4, f6, f8, f10");
COMPARE(msub_d(f4, f6, f8, f10), "4cca4129 msub.d f4, f6, f8, f10");
}
if (IsMipsArchVariant(kMips32r6)) {
COMPARE(maddf_s(f4, f8, f10), "460a4118 maddf.s f4, f8, f10");
COMPARE(maddf_d(f4, f8, f10), "462a4118 maddf.d f4, f8, f10");
COMPARE(msubf_s(f4, f8, f10), "460a4119 msubf.s f4, f8, f10");
COMPARE(msubf_d(f4, f8, f10), "462a4119 msubf.d f4, f8, f10");
}
VERIFY_RUN();
}
...@@ -1276,3 +1276,20 @@ TEST(ctc1_cfc1_disasm) { ...@@ -1276,3 +1276,20 @@ TEST(ctc1_cfc1_disasm) {
COMPARE(cfc1(a0, FCSR), "4444f800 cfc1 a0, FCSR"); COMPARE(cfc1(a0, FCSR), "4444f800 cfc1 a0, FCSR");
VERIFY_RUN(); VERIFY_RUN();
} }
TEST(madd_msub_maddf_msubf) {
SET_UP();
if (kArchVariant == kMips64r2) {
COMPARE(madd_s(f4, f6, f8, f10), "4cca4120 madd.s f4, f6, f8, f10");
COMPARE(madd_d(f4, f6, f8, f10), "4cca4121 madd.d f4, f6, f8, f10");
COMPARE(msub_s(f4, f6, f8, f10), "4cca4128 msub.s f4, f6, f8, f10");
COMPARE(msub_d(f4, f6, f8, f10), "4cca4129 msub.d f4, f6, f8, f10");
}
if (kArchVariant == kMips64r6) {
COMPARE(maddf_s(f4, f8, f10), "460a4118 maddf.s f4, f8, f10");
COMPARE(maddf_d(f4, f8, f10), "462a4118 maddf.d f4, f8, f10");
COMPARE(msubf_s(f4, f8, f10), "460a4119 msubf.s f4, f8, f10");
COMPARE(msubf_d(f4, f8, f10), "462a4119 msubf.d f4, f8, f10");
}
VERIFY_RUN();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment