| Index: src/ia32/lithium-codegen-ia32.cc
|
| diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
|
| index 137d62c554648a367a14cf67e69f1d404389017e..14db90d08018a6e22b409dcf4098d53f5bcf8c9c 100644
|
| --- a/src/ia32/lithium-codegen-ia32.cc
|
| +++ b/src/ia32/lithium-codegen-ia32.cc
|
| @@ -3016,6 +3016,129 @@ void LCodeGen::DoPower(LPower* instr) {
|
| }
|
|
|
|
|
| +void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
|
| + Label return_left, return_right;
|
| + bool is_min = instr->IsMin();
|
| + bool can_be_minus_zero = instr->hydrogen()->range()->CanBeMinusZero();
|
| + if (instr->TempAt(0) == NULL) {
|
| + // Integer32 case
|
| + Register left = ToRegister(instr->InputAt(0));
|
| + Register right = ToRegister(instr->InputAt(1));
|
| + Register result = ToRegister(instr->result());
|
| + ASSERT(left.is(result));
|
| + __ cmp(left, right);
|
| + __ j(is_min ? less : greater, &return_left, Label::kNear);
|
| + __ j(is_min ? greater : less, &return_right, Label::kNear);
|
| + if (can_be_minus_zero) {
|
| + // Both are equal, check whether we are comparing zeros.
|
| + __ test(result, result);
|
| + __ j(not_zero, &return_left, Label::kNear);
|
| + // Deoptimize to check for minus zero.
|
| + DeoptimizeIf(no_condition, instr->environment());
|
| + }
|
| + __ bind(&return_right);
|
| + __ mov(result, right);
|
| + __ bind(&return_left);
|
| + return;
|
| + }
|
| +
|
| + // Tagged or unpacked double.
|
| + bool tagged = !instr->result()->IsDoubleRegister();
|
| + Label return_nan, bailout, both_smi;
|
| + DoubleRegister leftxmm, rightxmm, tempxmm ;
|
| + Register left, right;
|
| + Register temp = ToRegister(instr->TempAt(0));
|
| + if (tagged) {
|
| + left = ToRegister(instr->InputAt(0));
|
| + right = ToRegister(instr->InputAt(1));
|
| + leftxmm = ToDoubleRegister(instr->TempAt(1));
|
| + rightxmm = ToDoubleRegister(instr->TempAt(2));
|
| + tempxmm = rightxmm;
|
| + Label left_smi, right_not_smi, left_prepared, right_prepared;
|
| +
|
| + __ JumpIfSmi(left, &left_smi, Label::kNear);
|
| + __ cmp(FieldOperand(left, HeapObject::kMapOffset),
|
| + masm()->isolate()->factory()->heap_number_map());
|
| + __ j(not_equal, &bailout);
|
| + __ movdbl(leftxmm, FieldOperand(left, HeapNumber::kValueOffset));
|
| + __ jmp(&left_prepared, Label::kNear);
|
| +
|
| + __ bind(&left_smi);
|
| + __ JumpIfSmi(right, &both_smi);
|
| + __ SmiUntag(left);
|
| + __ cvtsi2sd(leftxmm, left);
|
| + __ SmiTag(left);
|
| + __ jmp(&right_not_smi, Label::kNear);
|
| + __ bind(&left_prepared);
|
| +
|
| + __ JumpIfNotSmi(right, &right_not_smi, Label::kNear);
|
| + __ SmiUntag(right);
|
| + __ cvtsi2sd(rightxmm, right);
|
| + __ SmiTag(right);
|
| + __ jmp(&right_prepared, Label::kNear);
|
| +
|
| + __ bind(&right_not_smi);
|
| + __ cmp(FieldOperand(right, HeapObject::kMapOffset),
|
| + masm()->isolate()->factory()->heap_number_map());
|
| + __ j(not_equal, &bailout);
|
| + __ movdbl(rightxmm, FieldOperand(right, HeapNumber::kValueOffset));
|
| + __ bind(&right_prepared);
|
| + } else {
|
| + leftxmm = ToDoubleRegister(instr->InputAt(0));
|
| + rightxmm = ToDoubleRegister(instr->InputAt(1));
|
| + tempxmm = ToDoubleRegister(instr->TempAt(1));
|
| + }
|
| +
|
| + // Compare doubles.
|
| + __ ucomisd(leftxmm, rightxmm);
|
| + __ j(is_min ? below : above, &return_left);
|
| + __ j(is_min ? above : below, &return_right);
|
| + if (can_be_minus_zero) {
|
| + __ j(carry, &return_nan);
|
| + __ xorpd(tempxmm, tempxmm);
|
| + __ ucomisd(leftxmm, tempxmm);
|
| + __ j(not_equal, &return_left);
|
| + __ movmskpd(temp, leftxmm);
|
| + __ test(temp, Immediate(1));
|
| + __ j(is_min ? zero : not_zero, &return_right);
|
| + __ jmp(&return_left);
|
| + __ bind(&return_nan);
|
| + } else {
|
| + __ j(not_carry, &return_left);
|
| + }
|
| +
|
| + if (tagged) {
|
| + Register result = ToRegister(instr->result());
|
| + ASSERT(left.is(result));
|
| + // Return NaN.
|
| + __ mov(result, masm()->isolate()->factory()->nan_value());
|
| + __ jmp(&return_left);
|
| +
|
| + __ bind(&bailout);
|
| + DeoptimizeIf(no_condition, instr->environment());
|
| +
|
| + // Both smi. Neither can be minus zero.
|
| + __ bind(&both_smi);
|
| + __ cmp(left, right);
|
| + __ j(is_min ? less : greater, &return_left, Label::kNear);
|
| + __ bind(&return_right);
|
| + __ mov(result, right);
|
| + __ bind(&return_left);
|
| + } else {
|
| + DoubleRegister result = ToDoubleRegister(instr->result());
|
| + ASSERT(leftxmm.is(result));
|
| + // Return NaN.
|
| + __ xorps(result, result);
|
| + __ divsd(result, result);
|
| + __ jmp(&return_left, Label::kNear);
|
| +
|
| + __ bind(&return_right);
|
| + __ movsd(result, rightxmm);
|
| + __ bind(&return_left);
|
| + }
|
| +}
|
| +
|
| +
|
| void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
|
| ASSERT(instr->value()->Equals(instr->result()));
|
| XMMRegister input_reg = ToDoubleRegister(instr->value());
|
|
|