Commit e1c5d09b authored by marija.antic's avatar marija.antic Committed by Commit bot

MIPS: Implement Neg_d and Neg_s instruction macros.

Implement Neg_d and Neg_s in macro-assembler.
Floating point negate instructions are removed in release 6.
On r2, these instructoin do not change the sign of NaN operands.

TEST=cctest/test-run-wasm/RunWasmCompiled_Float32Neg, cctest/test-run-wasm/RunWasmCompiled_Float64Neg
BUG=

Review-Url: https://codereview.chromium.org/2256963003
Cr-Commit-Position: refs/heads/master@{#38749}
parent 21f2eb6c
......@@ -1147,10 +1147,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ abs_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kMipsNegS:
__ neg_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
__ Neg_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
break;
case kMipsNegD:
__ neg_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
__ Neg_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kMipsSqrtD: {
__ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
......
......@@ -1291,7 +1291,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ abs_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
break;
case kMips64NegS:
__ neg_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
__ Neg_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
break;
case kMips64SqrtS: {
__ sqrt_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
......@@ -1343,7 +1343,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ abs_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kMips64NegD:
__ neg_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
__ Neg_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kMips64SqrtD: {
__ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
......
......@@ -3442,10 +3442,8 @@ void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
// Math.sqrt(-Infinity) == NaN
Label done;
__ Move(temp, static_cast<double>(-V8_INFINITY));
__ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input);
// Set up Infinity in the delay slot.
// result is overwritten if the branch is not taken.
__ neg_d(result, temp);
__ Neg_d(result, temp);
__ BranchF(&done, NULL, eq, temp, input);
// Add +0 to convert -0 to +0.
__ add_d(result, input, kDoubleRegZero);
......
......@@ -3649,10 +3649,8 @@ void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
// Math.sqrt(-Infinity) == NaN
Label done;
__ Move(temp, static_cast<double>(-V8_INFINITY));
__ BranchF(USE_DELAY_SLOT, &done, NULL, eq, temp, input);
// Set up Infinity in the delay slot.
// result is overwritten if the branch is not taken.
__ neg_d(result, temp);
__ Neg_d(result, temp);
__ BranchF(&done, NULL, eq, temp, input);
// Add +0 to convert -0 to +0.
__ add_d(result, input, kDoubleRegZero);
......
......@@ -2492,11 +2492,13 @@ void Assembler::mov_s(FPURegister fd, FPURegister fs) {
void Assembler::neg_s(FPURegister fd, FPURegister fs) {
DCHECK(!IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, S, f0, fs, fd, NEG_S);
}
void Assembler::neg_d(FPURegister fd, FPURegister fs) {
DCHECK(!IsMipsArchVariant(kMips32r6));
GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
}
......
......@@ -1914,6 +1914,66 @@ void MacroAssembler::Ins(Register rt,
}
}
void MacroAssembler::Neg_s(FPURegister fd, FPURegister fs) {
Register scratch1 = t8;
Register scratch2 = t9;
if (IsMipsArchVariant(kMips32r2)) {
Label is_nan, done;
Register scratch1 = t8;
Register scratch2 = t9;
BranchF32(nullptr, &is_nan, eq, fs, fs);
Branch(USE_DELAY_SLOT, &done);
// For NaN input, neg_s will return the same NaN value,
// while the sign has to be changed separately.
neg_s(fd, fs); // In delay slot.
bind(&is_nan);
mfc1(scratch1, fs);
And(scratch2, scratch1, Operand(~kBinary32SignMask));
And(scratch1, scratch1, Operand(kBinary32SignMask));
Xor(scratch1, scratch1, Operand(kBinary32SignMask));
Or(scratch2, scratch2, scratch1);
mtc1(scratch2, fd);
bind(&done);
} else {
mfc1(scratch1, fs);
And(scratch2, scratch1, Operand(~kBinary32SignMask));
And(scratch1, scratch1, Operand(kBinary32SignMask));
Xor(scratch1, scratch1, Operand(kBinary32SignMask));
Or(scratch2, scratch2, scratch1);
mtc1(scratch2, fd);
}
}
void MacroAssembler::Neg_d(FPURegister fd, FPURegister fs) {
Register scratch1 = t8;
Register scratch2 = t9;
if (IsMipsArchVariant(kMips32r2)) {
Label is_nan, done;
BranchF64(nullptr, &is_nan, eq, fs, fs);
Branch(USE_DELAY_SLOT, &done);
// For NaN input, neg_d will return the same NaN value,
// while the sign has to be changed separately.
neg_d(fd, fs); // In delay slot.
bind(&is_nan);
Mfhc1(scratch1, fs);
And(scratch2, scratch1, Operand(~HeapNumber::kSignMask));
And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
Xor(scratch1, scratch1, Operand(HeapNumber::kSignMask));
Or(scratch2, scratch2, scratch1);
Mthc1(scratch2, fd);
bind(&done);
} else {
Move_d(fd, fs);
Mfhc1(scratch1, fs);
And(scratch2, scratch1, Operand(~HeapNumber::kSignMask));
And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
Xor(scratch1, scratch1, Operand(HeapNumber::kSignMask));
Or(scratch2, scratch2, scratch1);
Mthc1(scratch2, fd);
}
}
void MacroAssembler::Cvt_d_uw(FPURegister fd, Register rs,
FPURegister scratch) {
......@@ -2319,7 +2379,7 @@ void MacroAssembler::Move(FPURegister dst, double imm) {
if (imm_bits == bit_cast<int64_t>(0.0) && has_double_zero_reg_set_) {
mov_d(dst, kDoubleRegZero);
} else if (imm_bits == bit_cast<int64_t>(-0.0) && has_double_zero_reg_set_) {
neg_d(dst, kDoubleRegZero);
Neg_d(dst, kDoubleRegZero);
} else {
uint32_t lo, hi;
DoubleAsTwoUInt32(imm, &lo, &hi);
......
......@@ -830,6 +830,8 @@ class MacroAssembler: public Assembler {
// MIPS32 R2 instruction macro.
void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
void Neg_s(FPURegister fd, FPURegister fs);
void Neg_d(FPURegister fd, FPURegister fs);
// MIPS32 R6 instruction macros.
void Bovc(Register rt, Register rs, Label* L);
......
......@@ -2818,11 +2818,13 @@ void Assembler::mov_s(FPURegister fd, FPURegister fs) {
void Assembler::neg_s(FPURegister fd, FPURegister fs) {
DCHECK(kArchVariant == kMips64r2);
GenInstrRegister(COP1, S, f0, fs, fd, NEG_D);
}
void Assembler::neg_d(FPURegister fd, FPURegister fs) {
DCHECK(kArchVariant == kMips64r2);
GenInstrRegister(COP1, D, f0, fs, fd, NEG_D);
}
......
......@@ -1959,6 +1959,61 @@ void MacroAssembler::Ins(Register rt,
ins_(rt, rs, pos, size);
}
void MacroAssembler::Neg_s(FPURegister fd, FPURegister fs) {
Register scratch1 = t8;
Register scratch2 = t9;
if (kArchVariant == kMips64r2) {
Label is_nan, done;
BranchF32(nullptr, &is_nan, eq, fs, fs);
Branch(USE_DELAY_SLOT, &done);
// For NaN input, neg_s will return the same NaN value,
// while the sign has to be changed separately.
neg_s(fd, fs); // In delay slot.
bind(&is_nan);
mfc1(scratch1, fs);
And(scratch2, scratch1, Operand(~kBinary32SignMask));
And(scratch1, scratch1, Operand(kBinary32SignMask));
Xor(scratch1, scratch1, Operand(kBinary32SignMask));
Or(scratch2, scratch2, scratch1);
mtc1(scratch2, fd);
bind(&done);
} else {
mfc1(scratch1, fs);
And(scratch2, scratch1, Operand(~kBinary32SignMask));
And(scratch1, scratch1, Operand(kBinary32SignMask));
Xor(scratch1, scratch1, Operand(kBinary32SignMask));
Or(scratch2, scratch2, scratch1);
mtc1(scratch2, fd);
}
}
void MacroAssembler::Neg_d(FPURegister fd, FPURegister fs) {
Register scratch1 = t8;
Register scratch2 = t9;
if (kArchVariant == kMips64r2) {
Label is_nan, done;
BranchF64(nullptr, &is_nan, eq, fs, fs);
Branch(USE_DELAY_SLOT, &done);
// For NaN input, neg_d will return the same NaN value,
// while the sign has to be changed separately.
neg_d(fd, fs); // In delay slot.
bind(&is_nan);
dmfc1(scratch1, fs);
And(scratch2, scratch1, Operand(~Double::kSignMask));
And(scratch1, scratch1, Operand(Double::kSignMask));
Xor(scratch1, scratch1, Operand(Double::kSignMask));
Or(scratch2, scratch2, scratch1);
dmtc1(scratch2, fd);
bind(&done);
} else {
dmfc1(scratch1, fs);
And(scratch2, scratch1, Operand(~Double::kSignMask));
And(scratch1, scratch1, Operand(Double::kSignMask));
Xor(scratch1, scratch1, Operand(Double::kSignMask));
Or(scratch2, scratch2, scratch1);
dmtc1(scratch2, fd);
}
}
void MacroAssembler::Cvt_d_uw(FPURegister fd, FPURegister fs) {
// Move the data from fs to t8.
......@@ -2537,7 +2592,7 @@ void MacroAssembler::Move(FPURegister dst, double imm) {
if (imm_bits == bit_cast<int64_t>(0.0) && has_double_zero_reg_set_) {
mov_d(dst, kDoubleRegZero);
} else if (imm_bits == bit_cast<int64_t>(-0.0) && has_double_zero_reg_set_) {
neg_d(dst, kDoubleRegZero);
Neg_d(dst, kDoubleRegZero);
} else {
uint32_t lo, hi;
DoubleAsTwoUInt32(imm, &lo, &hi);
......
......@@ -880,6 +880,8 @@ class MacroAssembler: public Assembler {
void Dext(Register rt, Register rs, uint16_t pos, uint16_t size);
void Dextm(Register rt, Register rs, uint16_t pos, uint16_t size);
void Dextu(Register rt, Register rs, uint16_t pos, uint16_t size);
void Neg_s(FPURegister fd, FPURegister fs);
void Neg_d(FPURegister fd, FPURegister fs);
// MIPS64 R6 instruction macros.
void Bovc(Register rt, Register rs, Label* L);
......
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