Index: src/compiler/ia32/code-generator-ia32.cc |
diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc |
index 9bb5a22cd19b45707165323321d109aaeca32cc9..3e9b6cb37b4f47a9bcfa4bc66f0f6d6adccd7b43 100644 |
--- a/src/compiler/ia32/code-generator-ia32.cc |
+++ b/src/compiler/ia32/code-generator-ia32.cc |
@@ -654,10 +654,53 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
break; |
} |
case kSSEFloat32Round: { |
- CpuFeatureScope sse_scope(masm(), SSE4_1); |
RoundingMode const mode = |
static_cast<RoundingMode>(MiscField::decode(instr->opcode())); |
+ if (CpuFeatures::IsSupported(SSE4_1)) { |
+ CpuFeatureScope sse_scope(masm(), SSE4_1); |
__ roundss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode); |
+ } else { |
+ Register kScratchRegister = i.TempRegister(0); |
titzer
2016/01/18 10:44:28
Don't call this kScratchRegister, it's not a const
ahaas
2016/01/18 15:30:30
Done.
|
+ |
+ // We have to store the original rounding mode to restore it later. |
titzer
2016/01/18 10:44:28
This code sucks so much I think it should go to ma
ahaas
2016/01/18 15:30:30
Done.
|
+ __ sub(esp, Immediate(kPointerSize * 2)); |
+ __ stmxcsr(Operand(esp, 0)); |
+ __ mov(kScratchRegister, Operand(esp, 0)); |
+ __ and_(kScratchRegister, Immediate(0xffff9fff)); |
+ __ or_(kScratchRegister, Immediate(mode << 13)); |
+ __ mov(Operand(esp, kPointerSize), kScratchRegister); |
+ __ ldmxcsr(Operand(esp, kPointerSize)); |
+ |
+ // Convert the input to int32. |
+ if (instr->InputAt(0)->IsDoubleRegister()) { |
+ __ cvtss2si(kScratchRegister, i.InputDoubleRegister(0)); |
titzer
2016/01/18 10:44:28
If you require the input to be in a register, you
ahaas
2016/01/18 15:30:30
Done.
|
+ } else { |
+ __ cvtss2si(kScratchRegister, i.InputOperand(0)); |
+ } |
+ |
+ Label out_of_range; |
+ Label done; |
+ // Check whether the input is within int32 range. |
+ __ cmp(kScratchRegister, Immediate(1)); |
+ __ j(overflow, &out_of_range); |
+ // The input is within int32 range. We achieve rounding by converting |
+ // back to float. |
+ __ cvtsi2ss(i.OutputDoubleRegister(), kScratchRegister); |
+ __ jmp(&done); |
+ __ bind(&out_of_range); |
+ |
+ // The input value is already an integer number, no rounding necessary. |
titzer
2016/01/18 10:44:28
If you do a DefineSameAsFirst, you can get rid of
ahaas
2016/01/18 15:30:30
Done.
|
+ if (instr->InputAt(0)->IsDoubleRegister()) { |
+ __ movss(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
+ } else { |
+ __ movss(i.OutputDoubleRegister(), i.InputOperand(0)); |
+ } |
+ |
+ __ bind(&done); |
+ // Restore the original rounding mode. |
+ __ ldmxcsr(Operand(esp, 0)); |
+ __ add(esp, Immediate(kPointerSize * 2)); |
+ } |
break; |
} |
case kSSEFloat64Cmp: |
@@ -727,10 +770,95 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
__ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0)); |
break; |
case kSSEFloat64Round: { |
- CpuFeatureScope sse_scope(masm(), SSE4_1); |
RoundingMode const mode = |
static_cast<RoundingMode>(MiscField::decode(instr->opcode())); |
- __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode); |
+ if (CpuFeatures::IsSupported(SSE4_1)) { |
+ CpuFeatureScope sse_scope(masm(), SSE4_1); |
+ __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode); |
+ } else { |
+ Register kScratchRegister = i.TempRegister(0); |
+ |
+ // We have to store the original rounding mode to restore it later. |
+ __ sub(esp, Immediate(kPointerSize * 2)); |
+ __ stmxcsr(Operand(esp, 0)); |
+ __ mov(kScratchRegister, Operand(esp, 0)); |
+ __ and_(kScratchRegister, Immediate(0xffff9fff)); |
+ __ or_(kScratchRegister, Immediate(mode << 13)); |
+ __ mov(Operand(esp, kPointerSize), kScratchRegister); |
+ __ ldmxcsr(Operand(esp, kPointerSize)); |
+ |
+ // Convert the input to int32. |
+ if (instr->InputAt(0)->IsDoubleRegister()) { |
titzer
2016/01/18 10:44:28
Same for this one. Require the input in a register
ahaas
2016/01/18 15:30:30
Done.
|
+ __ cvtsd2si(kScratchRegister, i.InputDoubleRegister(0)); |
+ } else { |
+ __ cvtsd2si(kScratchRegister, i.InputOperand(0)); |
+ } |
+ |
+ Label out_of_range; |
+ Label done; |
+ // Check whether the input is within int32 range. |
+ __ cmp(kScratchRegister, Immediate(1)); |
+ __ j(overflow, &out_of_range); |
+ // The input is within int32 range. We achieve rounding by converting |
+ // back to float. |
+ __ Cvtsi2sd(i.OutputDoubleRegister(), kScratchRegister); |
+ __ jmp(&done); |
+ __ bind(&out_of_range); |
+ |
+ if (instr->InputAt(0)->IsDoubleRegister()) { |
+ __ movsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
+ } else { |
+ __ movsd(i.OutputDoubleRegister(), i.InputOperand(0)); |
+ } |
+ |
+ // If the input is outside [-2^52, 2^52], then the result = input. |
+ int64_t offset = 1; |
+ offset <<= 52; |
+ __ Move(kScratchDoubleReg, static_cast<double>(offset)); |
+ |
+ if (instr->InputAt(0)->IsDoubleRegister()) { |
+ __ ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0)); |
+ } else { |
+ __ ucomisd(kScratchDoubleReg, i.InputOperand(0)); |
+ } |
+ |
+ __ j(below_equal, &done); |
+ |
+ __ Move(kScratchDoubleReg, static_cast<double>(-offset)); |
+ |
+ if (instr->InputAt(0)->IsDoubleRegister()) { |
+ __ ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0)); |
+ } else { |
+ __ ucomisd(kScratchDoubleReg, i.InputOperand(0)); |
+ } |
+ __ j(above_equal, &done); |
+ |
+ // Positive number have to be handled differently than negative numbers. |
+ __ xorpd(kScratchDoubleReg, kScratchDoubleReg); |
+ if (instr->InputAt(0)->IsDoubleRegister()) { |
+ __ ucomisd(kScratchDoubleReg, i.InputDoubleRegister(0)); |
+ } else { |
+ __ ucomisd(kScratchDoubleReg, i.InputOperand(0)); |
+ } |
+ |
+ __ Move(kScratchDoubleReg, static_cast<double>(offset)); |
+ |
+ Label below_zero; |
+ __ j(above, &below_zero); |
+ |
+ __ addsd(i.OutputDoubleRegister(), kScratchDoubleReg); |
+ __ subsd(i.OutputDoubleRegister(), kScratchDoubleReg); |
+ __ jmp(&done); |
+ |
+ __ bind(&below_zero); |
+ __ subsd(i.OutputDoubleRegister(), kScratchDoubleReg); |
+ __ addsd(i.OutputDoubleRegister(), kScratchDoubleReg); |
+ |
+ __ bind(&done); |
+ // Restore the original rounding mode. |
+ __ ldmxcsr(Operand(esp, 0)); |
+ __ add(esp, Immediate(kPointerSize * 2)); |
+ } |
break; |
} |
case kSSEFloat32ToFloat64: |