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}
This commit is contained in:
parent
3999fb0788
commit
65fd5e1165
@ -2453,6 +2453,11 @@ void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
|
||||
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,
|
||||
FPURegister ft) {
|
||||
@ -2460,6 +2465,37 @@ void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs,
|
||||
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) {
|
||||
GenInstrRegister(COP1, S, ft, fs, fd, DIV_S);
|
||||
|
@ -878,7 +878,14 @@ class Assembler : public AssemblerBase {
|
||||
void sub_d(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 madd_s(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_d(FPURegister fd, FPURegister fs, FPURegister ft);
|
||||
void abs_s(FPURegister fd, FPURegister fs);
|
||||
|
@ -525,6 +525,8 @@ enum SecondaryField : uint32_t {
|
||||
FLOOR_W_S = ((1U << 3) + 7),
|
||||
RECIP_S = ((2U << 3) + 5),
|
||||
RSQRT_S = ((2U << 3) + 6),
|
||||
MADDF_S = ((3U << 3) + 0),
|
||||
MSUBF_S = ((3U << 3) + 1),
|
||||
CLASS_S = ((3U << 3) + 3),
|
||||
CVT_D_S = ((4U << 3) + 1),
|
||||
CVT_W_S = ((4U << 3) + 4),
|
||||
@ -550,6 +552,8 @@ enum SecondaryField : uint32_t {
|
||||
FLOOR_W_D = ((1U << 3) + 7),
|
||||
RECIP_D = ((2U << 3) + 5),
|
||||
RSQRT_D = ((2U << 3) + 6),
|
||||
MADDF_D = ((3U << 3) + 0),
|
||||
MSUBF_D = ((3U << 3) + 1),
|
||||
CLASS_D = ((3U << 3) + 3),
|
||||
MIN = ((3U << 3) + 4),
|
||||
MINA = ((3U << 3) + 5),
|
||||
@ -616,8 +620,12 @@ enum SecondaryField : uint32_t {
|
||||
MOVF = ((2U << 3) + 1), // Function field for MOVT.fmt and MOVF.fmt
|
||||
SELNEZ_C = ((2U << 3) + 7), // COP1 on FPR registers.
|
||||
// COP1 Encoding of Function Field When rs=PS.
|
||||
|
||||
// COP1X Encoding of Function Field.
|
||||
MADD_S = ((4U << 3) + 0),
|
||||
MADD_D = ((4U << 3) + 1),
|
||||
MSUB_S = ((5U << 3) + 0),
|
||||
MSUB_D = ((5U << 3) + 1),
|
||||
|
||||
// PCREL Encoding of rt Field.
|
||||
ADDIUPC = ((0U << 2) + 0),
|
||||
|
@ -918,6 +918,12 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
|
||||
case CVT_D_S:
|
||||
Format(instr, "cvt.d.'t 'fd, 'fs");
|
||||
break;
|
||||
case MADDF_S:
|
||||
Format(instr, "maddf.s 'fd, 'fs, 'ft");
|
||||
break;
|
||||
case MSUBF_S:
|
||||
Format(instr, "msubf.s 'fd, 'fs, 'ft");
|
||||
break;
|
||||
default:
|
||||
Format(instr, "unknown.cop1.'t");
|
||||
break;
|
||||
@ -928,7 +934,17 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
|
||||
|
||||
void Decoder::DecodeTypeRegisterDRsType(Instruction* 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) {
|
||||
break;
|
||||
case COP1X:
|
||||
switch (instr->FunctionFieldRaw()) {
|
||||
case MADD_S:
|
||||
Format(instr, "madd.s 'fd, 'fr, 'fs, 'ft");
|
||||
break;
|
||||
case MADD_D:
|
||||
Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
|
||||
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:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -2482,6 +2482,14 @@ void Simulator::DecodeTypeRegisterDRsType() {
|
||||
case SUB_D:
|
||||
set_fpu_register_double(fd_reg(), fs - ft);
|
||||
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:
|
||||
set_fpu_register_double(fd_reg(), fs * ft);
|
||||
break;
|
||||
@ -2887,6 +2895,14 @@ void Simulator::DecodeTypeRegisterSRsType() {
|
||||
case SUB_S:
|
||||
set_fpu_register_float(fd_reg(), fs - ft);
|
||||
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:
|
||||
set_fpu_register_float(fd_reg(), fs * ft);
|
||||
break;
|
||||
@ -3375,13 +3391,42 @@ void Simulator::DecodeTypeRegisterCOP1() {
|
||||
|
||||
void Simulator::DecodeTypeRegisterCOP1X() {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -2780,12 +2780,49 @@ void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) {
|
||||
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,
|
||||
FPURegister ft) {
|
||||
DCHECK(kArchVariant == kMips64r2);
|
||||
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) {
|
||||
GenInstrRegister(COP1, S, ft, fs, fd, DIV_D);
|
||||
|
@ -939,7 +939,14 @@ class Assembler : public AssemblerBase {
|
||||
void sub_d(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 madd_s(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_d(FPURegister fd, FPURegister fs, FPURegister ft);
|
||||
void abs_s(FPURegister fd, FPURegister fs);
|
||||
|
@ -555,6 +555,8 @@ enum SecondaryField : uint32_t {
|
||||
FLOOR_W_S = ((1U << 3) + 7),
|
||||
RECIP_S = ((2U << 3) + 5),
|
||||
RSQRT_S = ((2U << 3) + 6),
|
||||
MADDF_S = ((3U << 3) + 0),
|
||||
MSUBF_S = ((3U << 3) + 1),
|
||||
CLASS_S = ((3U << 3) + 3),
|
||||
CVT_D_S = ((4U << 3) + 1),
|
||||
CVT_W_S = ((4U << 3) + 4),
|
||||
@ -579,6 +581,8 @@ enum SecondaryField : uint32_t {
|
||||
FLOOR_W_D = ((1U << 3) + 7),
|
||||
RECIP_D = ((2U << 3) + 5),
|
||||
RSQRT_D = ((2U << 3) + 6),
|
||||
MADDF_D = ((3U << 3) + 0),
|
||||
MSUBF_D = ((3U << 3) + 1),
|
||||
CLASS_D = ((3U << 3) + 3),
|
||||
MIN = ((3U << 3) + 4),
|
||||
MINA = ((3U << 3) + 5),
|
||||
@ -646,8 +650,12 @@ enum SecondaryField : uint32_t {
|
||||
SELNEZ_C = ((2U << 3) + 7), // COP1 on FPR registers.
|
||||
|
||||
// COP1 Encoding of Function Field When rs=PS.
|
||||
|
||||
// COP1X Encoding of Function Field.
|
||||
MADD_S = ((4U << 3) + 0),
|
||||
MADD_D = ((4U << 3) + 1),
|
||||
MSUB_S = ((5U << 3) + 0),
|
||||
MSUB_D = ((5U << 3) + 1),
|
||||
|
||||
// PCREL Encoding of rt Field.
|
||||
ADDIUPC = ((0U << 2) + 0),
|
||||
|
@ -959,6 +959,12 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
|
||||
case CVT_D_S:
|
||||
Format(instr, "cvt.d.'t 'fd, 'fs");
|
||||
break;
|
||||
case MADDF_S:
|
||||
Format(instr, "maddf.s 'fd, 'fs, 'ft");
|
||||
break;
|
||||
case MSUBF_S:
|
||||
Format(instr, "msubf.s 'fd, 'fs, 'ft");
|
||||
break;
|
||||
default:
|
||||
Format(instr, "unknown.cop1.'t");
|
||||
break;
|
||||
@ -969,7 +975,17 @@ void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
|
||||
|
||||
void Decoder::DecodeTypeRegisterDRsType(Instruction* 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) {
|
||||
|
||||
void Decoder::DecodeTypeRegisterCOP1X(Instruction* instr) {
|
||||
switch (instr->FunctionFieldRaw()) {
|
||||
case MADD_S:
|
||||
Format(instr, "madd.s 'fd, 'fr, 'fs, 'ft");
|
||||
break;
|
||||
case MADD_D:
|
||||
Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
|
||||
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:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -2421,6 +2421,14 @@ void Simulator::DecodeTypeRegisterSRsType() {
|
||||
case SUB_S:
|
||||
set_fpu_register_float(fd_reg(), fs - ft);
|
||||
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:
|
||||
set_fpu_register_float(fd_reg(), fs * ft);
|
||||
break;
|
||||
@ -2824,6 +2832,14 @@ void Simulator::DecodeTypeRegisterDRsType() {
|
||||
case SUB_D:
|
||||
set_fpu_register_double(fd_reg(), fs - ft);
|
||||
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:
|
||||
set_fpu_register_double(fd_reg(), fs * ft);
|
||||
break;
|
||||
@ -3305,13 +3321,42 @@ void Simulator::DecodeTypeRegisterCOP1() {
|
||||
|
||||
void Simulator::DecodeTypeRegisterCOP1X() {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -5386,4 +5386,128 @@ TEST(Trampoline) {
|
||||
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 __
|
||||
|
@ -5934,5 +5934,128 @@ TEST(Trampoline) {
|
||||
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 __
|
||||
|
@ -1090,3 +1090,20 @@ TEST(ctc1_cfc1_disasm) {
|
||||
COMPARE(cfc1(a0, FCSR), "4444f800 cfc1 a0, FCSR");
|
||||
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) {
|
||||
COMPARE(cfc1(a0, FCSR), "4444f800 cfc1 a0, FCSR");
|
||||
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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user