Chromium Code Reviews| 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: |