MIPS: ARM: Fast path for integer inputs to EmitVFPTruncate
Port r12676 (7d5e7e81) BUG= TEST= Review URL: https://codereview.chromium.org/11308134 Patch from Akos Palfi <palfia@homejinni.com>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13086 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a74d30f0df
commit
273b97f9b4
@ -816,6 +816,7 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
|
|||||||
Register object,
|
Register object,
|
||||||
Destination destination,
|
Destination destination,
|
||||||
DoubleRegister double_dst,
|
DoubleRegister double_dst,
|
||||||
|
DoubleRegister double_scratch,
|
||||||
Register dst1,
|
Register dst1,
|
||||||
Register dst2,
|
Register dst2,
|
||||||
Register heap_number_map,
|
Register heap_number_map,
|
||||||
@ -851,9 +852,10 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm,
|
|||||||
|
|
||||||
Register except_flag = scratch2;
|
Register except_flag = scratch2;
|
||||||
__ EmitFPUTruncate(kRoundToZero,
|
__ EmitFPUTruncate(kRoundToZero,
|
||||||
single_scratch,
|
|
||||||
double_dst,
|
|
||||||
scratch1,
|
scratch1,
|
||||||
|
double_dst,
|
||||||
|
at,
|
||||||
|
double_scratch,
|
||||||
except_flag,
|
except_flag,
|
||||||
kCheckForInexactConversion);
|
kCheckForInexactConversion);
|
||||||
|
|
||||||
@ -895,7 +897,8 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
|
|||||||
Register scratch1,
|
Register scratch1,
|
||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
DoubleRegister double_scratch,
|
DoubleRegister double_scratch0,
|
||||||
|
DoubleRegister double_scratch1,
|
||||||
Label* not_int32) {
|
Label* not_int32) {
|
||||||
ASSERT(!dst.is(object));
|
ASSERT(!dst.is(object));
|
||||||
ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
|
ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
|
||||||
@ -918,22 +921,19 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
|
|||||||
if (CpuFeatures::IsSupported(FPU)) {
|
if (CpuFeatures::IsSupported(FPU)) {
|
||||||
CpuFeatures::Scope scope(FPU);
|
CpuFeatures::Scope scope(FPU);
|
||||||
// Load the double value.
|
// Load the double value.
|
||||||
__ ldc1(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset));
|
__ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset));
|
||||||
|
|
||||||
FPURegister single_scratch = double_scratch.low();
|
|
||||||
Register except_flag = scratch2;
|
Register except_flag = scratch2;
|
||||||
__ EmitFPUTruncate(kRoundToZero,
|
__ EmitFPUTruncate(kRoundToZero,
|
||||||
single_scratch,
|
dst,
|
||||||
double_scratch,
|
double_scratch0,
|
||||||
scratch1,
|
scratch1,
|
||||||
|
double_scratch1,
|
||||||
except_flag,
|
except_flag,
|
||||||
kCheckForInexactConversion);
|
kCheckForInexactConversion);
|
||||||
|
|
||||||
// Jump to not_int32 if the operation did not succeed.
|
// Jump to not_int32 if the operation did not succeed.
|
||||||
__ Branch(not_int32, ne, except_flag, Operand(zero_reg));
|
__ Branch(not_int32, ne, except_flag, Operand(zero_reg));
|
||||||
// Get the result in the destination register.
|
|
||||||
__ mfc1(dst, single_scratch);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Load the double value in the destination registers.
|
// Load the double value in the destination registers.
|
||||||
__ lw(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset));
|
__ lw(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset));
|
||||||
@ -2955,6 +2955,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
right,
|
right,
|
||||||
destination,
|
destination,
|
||||||
f14,
|
f14,
|
||||||
|
f16,
|
||||||
a2,
|
a2,
|
||||||
a3,
|
a3,
|
||||||
heap_number_map,
|
heap_number_map,
|
||||||
@ -2966,6 +2967,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
left,
|
left,
|
||||||
destination,
|
destination,
|
||||||
f12,
|
f12,
|
||||||
|
f16,
|
||||||
t0,
|
t0,
|
||||||
t1,
|
t1,
|
||||||
heap_number_map,
|
heap_number_map,
|
||||||
@ -3002,9 +3004,10 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
|
|
||||||
Register except_flag = scratch2;
|
Register except_flag = scratch2;
|
||||||
__ EmitFPUTruncate(kRoundToZero,
|
__ EmitFPUTruncate(kRoundToZero,
|
||||||
single_scratch,
|
|
||||||
f10,
|
|
||||||
scratch1,
|
scratch1,
|
||||||
|
f10,
|
||||||
|
at,
|
||||||
|
f16,
|
||||||
except_flag);
|
except_flag);
|
||||||
|
|
||||||
if (result_type_ <= BinaryOpIC::INT32) {
|
if (result_type_ <= BinaryOpIC::INT32) {
|
||||||
@ -3013,7 +3016,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the result fits in a smi.
|
// Check if the result fits in a smi.
|
||||||
__ mfc1(scratch1, single_scratch);
|
|
||||||
__ Addu(scratch2, scratch1, Operand(0x40000000));
|
__ Addu(scratch2, scratch1, Operand(0x40000000));
|
||||||
// If not try to return a heap number.
|
// If not try to return a heap number.
|
||||||
__ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg));
|
__ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg));
|
||||||
@ -3108,6 +3110,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
scratch2,
|
scratch2,
|
||||||
scratch3,
|
scratch3,
|
||||||
f0,
|
f0,
|
||||||
|
f2,
|
||||||
&transition);
|
&transition);
|
||||||
FloatingPointHelper::LoadNumberAsInt32(masm,
|
FloatingPointHelper::LoadNumberAsInt32(masm,
|
||||||
right,
|
right,
|
||||||
@ -3117,6 +3120,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
|||||||
scratch2,
|
scratch2,
|
||||||
scratch3,
|
scratch3,
|
||||||
f0,
|
f0,
|
||||||
|
f2,
|
||||||
&transition);
|
&transition);
|
||||||
|
|
||||||
// The ECMA-262 standard specifies that, for shift operations, only the
|
// The ECMA-262 standard specifies that, for shift operations, only the
|
||||||
@ -3683,9 +3687,10 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
|||||||
Label int_exponent_convert;
|
Label int_exponent_convert;
|
||||||
// Detect integer exponents stored as double.
|
// Detect integer exponents stored as double.
|
||||||
__ EmitFPUTruncate(kRoundToMinusInf,
|
__ EmitFPUTruncate(kRoundToMinusInf,
|
||||||
single_scratch,
|
|
||||||
double_exponent,
|
|
||||||
scratch,
|
scratch,
|
||||||
|
double_exponent,
|
||||||
|
at,
|
||||||
|
double_scratch,
|
||||||
scratch2,
|
scratch2,
|
||||||
kCheckForInexactConversion);
|
kCheckForInexactConversion);
|
||||||
// scratch2 == 0 means there was no conversion error.
|
// scratch2 == 0 means there was no conversion error.
|
||||||
@ -3743,7 +3748,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
|||||||
__ push(ra);
|
__ push(ra);
|
||||||
{
|
{
|
||||||
AllowExternalCallThatCantCauseGC scope(masm);
|
AllowExternalCallThatCantCauseGC scope(masm);
|
||||||
__ PrepareCallCFunction(0, 2, scratch);
|
__ PrepareCallCFunction(0, 2, scratch2);
|
||||||
__ SetCallCDoubleArguments(double_base, double_exponent);
|
__ SetCallCDoubleArguments(double_base, double_exponent);
|
||||||
__ CallCFunction(
|
__ CallCFunction(
|
||||||
ExternalReference::power_double_double_function(masm->isolate()),
|
ExternalReference::power_double_double_function(masm->isolate()),
|
||||||
@ -3754,7 +3759,6 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
|||||||
__ jmp(&done);
|
__ jmp(&done);
|
||||||
|
|
||||||
__ bind(&int_exponent_convert);
|
__ bind(&int_exponent_convert);
|
||||||
__ mfc1(scratch, single_scratch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate power with integer exponent.
|
// Calculate power with integer exponent.
|
||||||
|
@ -657,6 +657,7 @@ class FloatingPointHelper : public AllStatic {
|
|||||||
Register object,
|
Register object,
|
||||||
Destination destination,
|
Destination destination,
|
||||||
FPURegister double_dst,
|
FPURegister double_dst,
|
||||||
|
FPURegister double_scratch,
|
||||||
Register dst1,
|
Register dst1,
|
||||||
Register dst2,
|
Register dst2,
|
||||||
Register heap_number_map,
|
Register heap_number_map,
|
||||||
@ -678,7 +679,8 @@ class FloatingPointHelper : public AllStatic {
|
|||||||
Register scratch1,
|
Register scratch1,
|
||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
FPURegister double_scratch,
|
FPURegister double_scratch0,
|
||||||
|
FPURegister double_scratch1,
|
||||||
Label* not_int32);
|
Label* not_int32);
|
||||||
|
|
||||||
// Generate non FPU code to check if a double can be exactly represented by a
|
// Generate non FPU code to check if a double can be exactly represented by a
|
||||||
|
@ -3262,22 +3262,19 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
|
|||||||
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
|
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
|
||||||
DoubleRegister input = ToDoubleRegister(instr->value());
|
DoubleRegister input = ToDoubleRegister(instr->value());
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
FPURegister single_scratch = double_scratch0().low();
|
|
||||||
Register scratch1 = scratch0();
|
Register scratch1 = scratch0();
|
||||||
Register except_flag = ToRegister(instr->temp());
|
Register except_flag = ToRegister(instr->temp());
|
||||||
|
|
||||||
__ EmitFPUTruncate(kRoundToMinusInf,
|
__ EmitFPUTruncate(kRoundToMinusInf,
|
||||||
single_scratch,
|
result,
|
||||||
input,
|
input,
|
||||||
scratch1,
|
scratch1,
|
||||||
|
double_scratch0(),
|
||||||
except_flag);
|
except_flag);
|
||||||
|
|
||||||
// Deopt if the operation did not succeed.
|
// Deopt if the operation did not succeed.
|
||||||
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
||||||
|
|
||||||
// Load the result.
|
|
||||||
__ mfc1(result, single_scratch);
|
|
||||||
|
|
||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
// Test for -0.
|
// Test for -0.
|
||||||
Label done;
|
Label done;
|
||||||
@ -3293,6 +3290,7 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
|
|||||||
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
||||||
DoubleRegister input = ToDoubleRegister(instr->value());
|
DoubleRegister input = ToDoubleRegister(instr->value());
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
|
DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
|
||||||
Register scratch = scratch0();
|
Register scratch = scratch0();
|
||||||
Label done, check_sign_on_zero;
|
Label done, check_sign_on_zero;
|
||||||
|
|
||||||
@ -3344,17 +3342,15 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Register except_flag = scratch;
|
Register except_flag = scratch;
|
||||||
|
|
||||||
__ EmitFPUTruncate(kRoundToMinusInf,
|
__ EmitFPUTruncate(kRoundToMinusInf,
|
||||||
double_scratch0().low(),
|
|
||||||
double_scratch0(),
|
|
||||||
result,
|
result,
|
||||||
|
double_scratch0(),
|
||||||
|
at,
|
||||||
|
double_scratch1,
|
||||||
except_flag);
|
except_flag);
|
||||||
|
|
||||||
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
||||||
|
|
||||||
__ mfc1(result, double_scratch0().low());
|
|
||||||
|
|
||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
// Test for -0.
|
// Test for -0.
|
||||||
__ Branch(&done, ne, result, Operand(zero_reg));
|
__ Branch(&done, ne, result, Operand(zero_reg));
|
||||||
@ -4391,7 +4387,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
|||||||
Register scratch1 = scratch0();
|
Register scratch1 = scratch0();
|
||||||
Register scratch2 = ToRegister(instr->temp());
|
Register scratch2 = ToRegister(instr->temp());
|
||||||
DoubleRegister double_scratch = double_scratch0();
|
DoubleRegister double_scratch = double_scratch0();
|
||||||
FPURegister single_scratch = double_scratch.low();
|
DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp3());
|
||||||
|
|
||||||
ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
|
ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
|
||||||
ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
|
ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
|
||||||
@ -4407,7 +4403,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
|||||||
|
|
||||||
if (instr->truncating()) {
|
if (instr->truncating()) {
|
||||||
Register scratch3 = ToRegister(instr->temp2());
|
Register scratch3 = ToRegister(instr->temp2());
|
||||||
DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp3());
|
FPURegister single_scratch = double_scratch.low();
|
||||||
ASSERT(!scratch3.is(input_reg) &&
|
ASSERT(!scratch3.is(input_reg) &&
|
||||||
!scratch3.is(scratch1) &&
|
!scratch3.is(scratch1) &&
|
||||||
!scratch3.is(scratch2));
|
!scratch3.is(scratch2));
|
||||||
@ -4442,18 +4438,16 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
|
|||||||
|
|
||||||
Register except_flag = scratch2;
|
Register except_flag = scratch2;
|
||||||
__ EmitFPUTruncate(kRoundToZero,
|
__ EmitFPUTruncate(kRoundToZero,
|
||||||
single_scratch,
|
input_reg,
|
||||||
double_scratch,
|
double_scratch,
|
||||||
scratch1,
|
scratch1,
|
||||||
|
double_scratch2,
|
||||||
except_flag,
|
except_flag,
|
||||||
kCheckForInexactConversion);
|
kCheckForInexactConversion);
|
||||||
|
|
||||||
// Deopt if the operation did not succeed.
|
// Deopt if the operation did not succeed.
|
||||||
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
||||||
|
|
||||||
// Load the result.
|
|
||||||
__ mfc1(input_reg, single_scratch);
|
|
||||||
|
|
||||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||||
__ Branch(&done, ne, input_reg, Operand(zero_reg));
|
__ Branch(&done, ne, input_reg, Operand(zero_reg));
|
||||||
|
|
||||||
@ -4515,10 +4509,10 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
|||||||
Register scratch1 = scratch0();
|
Register scratch1 = scratch0();
|
||||||
Register scratch2 = ToRegister(instr->temp());
|
Register scratch2 = ToRegister(instr->temp());
|
||||||
DoubleRegister double_input = ToDoubleRegister(instr->value());
|
DoubleRegister double_input = ToDoubleRegister(instr->value());
|
||||||
FPURegister single_scratch = double_scratch0().low();
|
|
||||||
|
|
||||||
if (instr->truncating()) {
|
if (instr->truncating()) {
|
||||||
Register scratch3 = ToRegister(instr->temp2());
|
Register scratch3 = ToRegister(instr->temp2());
|
||||||
|
FPURegister single_scratch = double_scratch0().low();
|
||||||
__ EmitECMATruncate(result_reg,
|
__ EmitECMATruncate(result_reg,
|
||||||
double_input,
|
double_input,
|
||||||
single_scratch,
|
single_scratch,
|
||||||
@ -4529,17 +4523,15 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
|
|||||||
Register except_flag = scratch2;
|
Register except_flag = scratch2;
|
||||||
|
|
||||||
__ EmitFPUTruncate(kRoundToMinusInf,
|
__ EmitFPUTruncate(kRoundToMinusInf,
|
||||||
single_scratch,
|
result_reg,
|
||||||
double_input,
|
double_input,
|
||||||
scratch1,
|
scratch1,
|
||||||
|
double_scratch0(),
|
||||||
except_flag,
|
except_flag,
|
||||||
kCheckForInexactConversion);
|
kCheckForInexactConversion);
|
||||||
|
|
||||||
// Deopt if the operation did not succeed (except_flag != 0).
|
// Deopt if the operation did not succeed (except_flag != 0).
|
||||||
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
|
||||||
|
|
||||||
// Load the result.
|
|
||||||
__ mfc1(result_reg, single_scratch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1049,7 +1049,9 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
|
|||||||
return DefineFixedDouble(result, f4);
|
return DefineFixedDouble(result, f4);
|
||||||
} else {
|
} else {
|
||||||
LOperand* input = UseRegisterAtStart(instr->value());
|
LOperand* input = UseRegisterAtStart(instr->value());
|
||||||
LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
|
|
||||||
|
LOperand* temp = (op == kMathRound) ? FixedTemp(f6) :
|
||||||
|
(op == kMathFloor) ? TempRegister() : NULL;
|
||||||
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
|
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case kMathAbs:
|
case kMathAbs:
|
||||||
@ -1566,8 +1568,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
|
|||||||
LOperand* temp1 = TempRegister();
|
LOperand* temp1 = TempRegister();
|
||||||
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
|
LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
|
||||||
: NULL;
|
: NULL;
|
||||||
LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(f22)
|
LOperand* temp3 = FixedTemp(f22);
|
||||||
: NULL;
|
|
||||||
res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
|
res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
|
||||||
temp1,
|
temp1,
|
||||||
temp2,
|
temp2,
|
||||||
|
@ -1395,49 +1395,68 @@ void MacroAssembler::ConvertToInt32(Register source,
|
|||||||
|
|
||||||
|
|
||||||
void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
|
void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode,
|
||||||
FPURegister result,
|
Register result,
|
||||||
DoubleRegister double_input,
|
DoubleRegister double_input,
|
||||||
Register scratch1,
|
Register scratch,
|
||||||
|
DoubleRegister double_scratch,
|
||||||
Register except_flag,
|
Register except_flag,
|
||||||
CheckForInexactConversion check_inexact) {
|
CheckForInexactConversion check_inexact) {
|
||||||
|
ASSERT(!result.is(scratch));
|
||||||
|
ASSERT(!double_input.is(double_scratch));
|
||||||
|
ASSERT(!except_flag.is(scratch));
|
||||||
|
|
||||||
ASSERT(CpuFeatures::IsSupported(FPU));
|
ASSERT(CpuFeatures::IsSupported(FPU));
|
||||||
CpuFeatures::Scope scope(FPU);
|
CpuFeatures::Scope scope(FPU);
|
||||||
|
Label done;
|
||||||
|
|
||||||
|
// Clear the except flag (0 = no exception)
|
||||||
|
mov(except_flag, zero_reg);
|
||||||
|
|
||||||
|
// Test for values that can be exactly represented as a signed 32-bit integer.
|
||||||
|
cvt_w_d(double_scratch, double_input);
|
||||||
|
mfc1(result, double_scratch);
|
||||||
|
cvt_d_w(double_scratch, double_scratch);
|
||||||
|
BranchF(&done, NULL, eq, double_input, double_scratch);
|
||||||
|
|
||||||
int32_t except_mask = kFCSRFlagMask; // Assume interested in all exceptions.
|
int32_t except_mask = kFCSRFlagMask; // Assume interested in all exceptions.
|
||||||
|
|
||||||
if (check_inexact == kDontCheckForInexactConversion) {
|
if (check_inexact == kDontCheckForInexactConversion) {
|
||||||
// Ingore inexact exceptions.
|
// Ignore inexact exceptions.
|
||||||
except_mask &= ~kFCSRInexactFlagMask;
|
except_mask &= ~kFCSRInexactFlagMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save FCSR.
|
// Save FCSR.
|
||||||
cfc1(scratch1, FCSR);
|
cfc1(scratch, FCSR);
|
||||||
// Disable FPU exceptions.
|
// Disable FPU exceptions.
|
||||||
ctc1(zero_reg, FCSR);
|
ctc1(zero_reg, FCSR);
|
||||||
|
|
||||||
// Do operation based on rounding mode.
|
// Do operation based on rounding mode.
|
||||||
switch (rounding_mode) {
|
switch (rounding_mode) {
|
||||||
case kRoundToNearest:
|
case kRoundToNearest:
|
||||||
Round_w_d(result, double_input);
|
Round_w_d(double_scratch, double_input);
|
||||||
break;
|
break;
|
||||||
case kRoundToZero:
|
case kRoundToZero:
|
||||||
Trunc_w_d(result, double_input);
|
Trunc_w_d(double_scratch, double_input);
|
||||||
break;
|
break;
|
||||||
case kRoundToPlusInf:
|
case kRoundToPlusInf:
|
||||||
Ceil_w_d(result, double_input);
|
Ceil_w_d(double_scratch, double_input);
|
||||||
break;
|
break;
|
||||||
case kRoundToMinusInf:
|
case kRoundToMinusInf:
|
||||||
Floor_w_d(result, double_input);
|
Floor_w_d(double_scratch, double_input);
|
||||||
break;
|
break;
|
||||||
} // End of switch-statement.
|
} // End of switch-statement.
|
||||||
|
|
||||||
// Retrieve FCSR.
|
// Retrieve FCSR.
|
||||||
cfc1(except_flag, FCSR);
|
cfc1(except_flag, FCSR);
|
||||||
// Restore FCSR.
|
// Restore FCSR.
|
||||||
ctc1(scratch1, FCSR);
|
ctc1(scratch, FCSR);
|
||||||
|
// Move the converted value into the result register.
|
||||||
|
mfc1(result, double_scratch);
|
||||||
|
|
||||||
// Check for fpu exceptions.
|
// Check for fpu exceptions.
|
||||||
And(except_flag, except_flag, Operand(except_mask));
|
And(except_flag, except_flag, Operand(except_mask));
|
||||||
|
|
||||||
|
bind(&done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -753,14 +753,16 @@ class MacroAssembler: public Assembler {
|
|||||||
FPURegister double_scratch,
|
FPURegister double_scratch,
|
||||||
Label *not_int32);
|
Label *not_int32);
|
||||||
|
|
||||||
// Truncates a double using a specific rounding mode.
|
// Truncates a double using a specific rounding mode, and writes the value
|
||||||
|
// to the result register.
|
||||||
// The except_flag will contain any exceptions caused by the instruction.
|
// The except_flag will contain any exceptions caused by the instruction.
|
||||||
// If check_inexact is kDontCheckForInexactConversion, then the inexacat
|
// If check_inexact is kDontCheckForInexactConversion, then the inexact
|
||||||
// exception is masked.
|
// exception is masked.
|
||||||
void EmitFPUTruncate(FPURoundingMode rounding_mode,
|
void EmitFPUTruncate(FPURoundingMode rounding_mode,
|
||||||
FPURegister result,
|
Register result,
|
||||||
DoubleRegister double_input,
|
DoubleRegister double_input,
|
||||||
Register scratch1,
|
Register scratch,
|
||||||
|
DoubleRegister double_scratch,
|
||||||
Register except_flag,
|
Register except_flag,
|
||||||
CheckForInexactConversion check_inexact
|
CheckForInexactConversion check_inexact
|
||||||
= kDontCheckForInexactConversion);
|
= kDontCheckForInexactConversion);
|
||||||
|
@ -3695,6 +3695,7 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm,
|
|||||||
Register scratch0,
|
Register scratch0,
|
||||||
Register scratch1,
|
Register scratch1,
|
||||||
FPURegister double_scratch0,
|
FPURegister double_scratch0,
|
||||||
|
FPURegister double_scratch1,
|
||||||
Label* fail) {
|
Label* fail) {
|
||||||
if (CpuFeatures::IsSupported(FPU)) {
|
if (CpuFeatures::IsSupported(FPU)) {
|
||||||
CpuFeatures::Scope scope(FPU);
|
CpuFeatures::Scope scope(FPU);
|
||||||
@ -3710,15 +3711,15 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm,
|
|||||||
DONT_DO_SMI_CHECK);
|
DONT_DO_SMI_CHECK);
|
||||||
__ ldc1(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset));
|
__ ldc1(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset));
|
||||||
__ EmitFPUTruncate(kRoundToZero,
|
__ EmitFPUTruncate(kRoundToZero,
|
||||||
double_scratch0,
|
|
||||||
double_scratch0,
|
|
||||||
scratch0,
|
scratch0,
|
||||||
|
double_scratch0,
|
||||||
|
at,
|
||||||
|
double_scratch1,
|
||||||
scratch1,
|
scratch1,
|
||||||
kCheckForInexactConversion);
|
kCheckForInexactConversion);
|
||||||
|
|
||||||
__ Branch(fail, ne, scratch1, Operand(zero_reg));
|
__ Branch(fail, ne, scratch1, Operand(zero_reg));
|
||||||
|
|
||||||
__ mfc1(scratch0, double_scratch0);
|
|
||||||
__ SmiTagCheckOverflow(key, scratch0, scratch1);
|
__ SmiTagCheckOverflow(key, scratch0, scratch1);
|
||||||
__ BranchOnOverflow(fail, scratch1);
|
__ BranchOnOverflow(fail, scratch1);
|
||||||
__ bind(&key_ok);
|
__ bind(&key_ok);
|
||||||
@ -3746,7 +3747,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
|||||||
// have been verified by the caller to not be a smi.
|
// have been verified by the caller to not be a smi.
|
||||||
|
|
||||||
// Check that the key is a smi or a heap number convertible to a smi.
|
// Check that the key is a smi or a heap number convertible to a smi.
|
||||||
GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic);
|
GenerateSmiKeyCheck(masm, key, t0, t1, f2, f4, &miss_force_generic);
|
||||||
|
|
||||||
__ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
__ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||||
// a3: elements array
|
// a3: elements array
|
||||||
@ -4088,7 +4089,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
|||||||
// have been verified by the caller to not be a smi.
|
// have been verified by the caller to not be a smi.
|
||||||
|
|
||||||
// Check that the key is a smi or a heap number convertible to a smi.
|
// Check that the key is a smi or a heap number convertible to a smi.
|
||||||
GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic);
|
GenerateSmiKeyCheck(masm, key, t0, t1, f2, f4, &miss_force_generic);
|
||||||
|
|
||||||
__ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
__ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
||||||
|
|
||||||
@ -4477,7 +4478,7 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
|
|||||||
// have been verified by the caller to not be a smi.
|
// have been verified by the caller to not be a smi.
|
||||||
|
|
||||||
// Check that the key is a smi or a heap number convertible to a smi.
|
// Check that the key is a smi or a heap number convertible to a smi.
|
||||||
GenerateSmiKeyCheck(masm, a0, t0, t1, f2, &miss_force_generic);
|
GenerateSmiKeyCheck(masm, a0, t0, t1, f2, f4, &miss_force_generic);
|
||||||
|
|
||||||
// Get the elements array.
|
// Get the elements array.
|
||||||
__ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset));
|
__ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset));
|
||||||
@ -4528,7 +4529,7 @@ void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
|
|||||||
// have been verified by the caller to not be a smi.
|
// have been verified by the caller to not be a smi.
|
||||||
|
|
||||||
// Check that the key is a smi or a heap number convertible to a smi.
|
// Check that the key is a smi or a heap number convertible to a smi.
|
||||||
GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic);
|
GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, f4, &miss_force_generic);
|
||||||
|
|
||||||
// Get the elements array.
|
// Get the elements array.
|
||||||
__ lw(elements_reg,
|
__ lw(elements_reg,
|
||||||
@ -4602,7 +4603,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
|||||||
// have been verified by the caller to not be a smi.
|
// have been verified by the caller to not be a smi.
|
||||||
|
|
||||||
// Check that the key is a smi or a heap number convertible to a smi.
|
// Check that the key is a smi or a heap number convertible to a smi.
|
||||||
GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic);
|
GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, f4, &miss_force_generic);
|
||||||
|
|
||||||
if (IsFastSmiElementsKind(elements_kind)) {
|
if (IsFastSmiElementsKind(elements_kind)) {
|
||||||
__ JumpIfNotSmi(value_reg, &transition_elements_kind);
|
__ JumpIfNotSmi(value_reg, &transition_elements_kind);
|
||||||
@ -4771,7 +4772,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
|||||||
// have been verified by the caller to not be a smi.
|
// have been verified by the caller to not be a smi.
|
||||||
|
|
||||||
// Check that the key is a smi or a heap number convertible to a smi.
|
// Check that the key is a smi or a heap number convertible to a smi.
|
||||||
GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic);
|
GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, f4, &miss_force_generic);
|
||||||
|
|
||||||
__ lw(elements_reg,
|
__ lw(elements_reg,
|
||||||
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
|
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
|
||||||
|
Loading…
Reference in New Issue
Block a user