VM: Improve and fix double negation on MIPS.

Add neg-instruction to the MIPS backend and use it instead of mul with -1.

Fixes the test that requires that identical(nan, -nan) == false.

TEST=language/nan_identical_test
R=zra@google.com

Review URL: https://codereview.chromium.org/1425143003 .
This commit is contained in:
Florian Schneider 2015-10-29 22:34:46 +01:00
parent 7cacbff77b
commit 64261cbb9d
7 changed files with 36 additions and 10 deletions

View file

@ -762,6 +762,12 @@ class Assembler : public ValueObject {
EmitRType(SPECIAL, rs, rt, R0, 0, MULTU);
}
void negd(DRegister dd, DRegister ds) {
FRegister fd = static_cast<FRegister>(dd * 2);
FRegister fs = static_cast<FRegister>(ds * 2);
EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_NEG);
}
void nop() {
Emit(Instr::kNopInstruction);
}

View file

@ -1639,6 +1639,21 @@ ASSEMBLER_TEST_RUN(Movd, test) {
}
ASSEMBLER_TEST_GENERATE(Negd, assembler) {
__ LoadImmediate(D1, 1.0);
__ negd(D0, D1);
__ Ret();
}
ASSEMBLER_TEST_RUN(Negd, test) {
typedef double (*SimpleCode)() DART_UNUSED;
EXPECT(test != NULL);
double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
EXPECT_FLOAT_EQ(-1.0, res, 0.001);
}
ASSEMBLER_TEST_GENERATE(Sdc1Ldc1, assembler) {
__ mov(T0, SP);
__ AddImmediate(SP, -3 * kWordSize);

View file

@ -439,6 +439,7 @@ enum Cop1Function {
COP1_DIV = 0x03,
COP1_SQRT = 0x04,
COP1_MOV = 0x06,
COP1_NEG = 0x07,
COP1_CVT_S = 0x20,
COP1_CVT_D = 0x21,
COP1_CVT_W = 0x24,

View file

@ -543,6 +543,10 @@ void MIPSDecoder::DecodeCop1(Instr* instr) {
Format(instr, "mov.'fmt 'fd, 'fs");
break;
}
case COP1_NEG: {
Format(instr, "neg.'fmt 'fd, 'fs");
break;
}
case COP1_C_F: {
Format(instr, "c.f.'fmt 'fs, 'ft");
break;

View file

@ -4118,25 +4118,19 @@ void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 1;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(zone) LocationSummary(
zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresFpuRegister());
summary->set_out(0, Location::RequiresFpuRegister());
summary->set_temp(0, Location::RequiresFpuRegister());
return summary;
}
void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// TODO(zra): Implement vneg.
const Double& minus_one = Double::ZoneHandle(Double::NewCanonical(-1));
__ LoadObject(TMP, minus_one);
FpuRegister result = locs()->out(0).fpu_reg();
FpuRegister value = locs()->in(0).fpu_reg();
FpuRegister temp_fp = locs()->temp(0).fpu_reg();
__ LoadDFromOffset(temp_fp, TMP, Double::value_offset() - kHeapObjectTag);
__ muld(result, value, temp_fp);
__ negd(result, value);
}

View file

@ -1813,6 +1813,12 @@ void Simulator::DecodeCop1(Instr* instr) {
set_fregister_double(instr->FdField(), fs_val);
break;
}
case COP1_NEG: {
// Format(instr, "neg.'fmt 'fd, 'fs");
ASSERT(instr->FormatField() == FMT_D);
set_fregister_double(instr->FdField(), -fs_val);
break;
}
case COP1_C_F: {
ASSERT(instr->FormatField() == FMT_D); // Only D supported.
ASSERT(instr->FdField() == F0);

View file

@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test a new statement by itself.
// VMOptions=--optimization-counter-threshold=4 --no-use-osr
// VMOptions=--optimization-counter-threshold=4
import 'dart:typed_data';
@ -48,4 +48,4 @@ main() {
}
}
checkIdentical(a, b) => identical(a, b);
checkIdentical(a, b) => identical(a, b);