Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 2634) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -169,6 +169,62 @@ |
}; |
+class FloatingPointHelper : public AllStatic { |
+ public: |
+ // Code pattern for loading a floating point value. Input value must |
+ // be either a smi or a heap number object (fp value). Requirements: |
+ // operand on TOS+1. Returns operand as floating point number on FPU |
+ // stack. |
+ static void LoadFloatOperand(MacroAssembler* masm, Register scratch); |
Lasse Reichstein
2009/08/06 12:49:39
Add an empty line after declarations.
|
+ // Code pattern for loading a floating point value. Input value must |
+ // be either a smi or a heap number object (fp value). Requirements: |
+ // operand in src register. Returns operand as floating point number |
+ // in XMM register |
+ static void LoadFloatOperand(MacroAssembler* masm, |
+ Register src, |
+ XMMRegister dst); |
+ // Code pattern for loading floating point values. Input values must |
+ // be either smi or heap number objects (fp values). Requirements: |
+ // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
+ // floating point numbers in XMM registers. |
+ static void LoadFloatOperands(MacroAssembler* masm, |
+ XMMRegister dst1, |
+ XMMRegister dst2); |
+ |
+ // Code pattern for loading floating point values onto the fp stack. |
+ // Input values must be either smi or heap number objects (fp values). |
+ // Requirements: |
+ // Register version: operands in registers lhs and rhs. |
+ // Stack version: operands on TOS+1 and TOS+2. |
+ // Returns operands as floating point numbers on fp stack. |
+ static void LoadFloatOperands(MacroAssembler* masm); |
+ static void LoadFloatOperands(MacroAssembler* masm, |
+ Register lhs, |
+ Register rhs); |
+ |
+ // Code pattern for loading a floating point value and converting it |
+ // to a 32 bit integer. Input value must be either a smi or a heap number |
+ // object. |
+ // Returns operands as 32-bit sign extended integers in a general purpose |
+ // registers. |
+ static void LoadInt32Operand(MacroAssembler* masm, |
+ const Operand& src, |
+ Register dst); |
+ |
+ // Test if operands are smi or number objects (fp). Requirements: |
Lasse Reichstein
2009/08/06 12:49:39
Unclear whether it tests (is smi or is heapnumber)
|
+ // operand_1 in rax, operand_2 in rdx; falls through on float |
+ // operands, jumps to the non_float label otherwise. |
+ static void CheckFloatOperands(MacroAssembler* masm, |
+ Label* non_float); |
+ // Allocate a heap number in new space with undefined value. |
+ // Returns tagged pointer in result, or jumps to need_gc if new space is full. |
+ static void AllocateHeapNumber(MacroAssembler* masm, |
+ Label* need_gc, |
+ Register scratch, |
+ Register result); |
+}; |
+ |
+ |
// ----------------------------------------------------------------------------- |
// CodeGenerator implementation. |
@@ -3531,11 +3587,55 @@ |
void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) { |
- // TODO(X64): Use inline floating point in the fast case. |
+ JumpTarget done; |
+ JumpTarget call_runtime; |
ASSERT(args->length() == 1); |
- // Load number. |
+ // Load number and duplicate it. |
Load(args->at(0)); |
+ frame_->Dup(); |
+ |
+ // Get the number into an unaliased register and load it onto the |
+ // floating point stack still leaving one copy on the frame. |
+ Result number = frame_->Pop(); |
+ number.ToRegister(); |
+ frame_->Spill(number.reg()); |
+ FloatingPointHelper::LoadFloatOperand(masm_, number.reg()); |
+ number.Unuse(); |
+ |
+ // Perform the operation on the number. |
+ switch (op) { |
+ case SIN: |
+ __ fsin(); |
+ break; |
+ case COS: |
+ __ fcos(); |
+ break; |
+ } |
+ |
+ // Go slow case if argument to operation is out of range. |
+ __ fnstsw_ax(); |
+ __ sahf(); |
Lasse Reichstein
2009/08/06 12:49:39
Using sahf is theoretically unsafe (not supported
|
+ call_runtime.Branch(parity_even); |
+ |
+ // Allocate heap number for result if possible. |
+ Result scratch = allocator()->Allocate(); |
+ Result heap_number = allocator()->Allocate(); |
+ FloatingPointHelper::AllocateHeapNumber(masm_, |
+ call_runtime.entry_label(), |
+ scratch.reg(), |
+ heap_number.reg()); |
+ scratch.Unuse(); |
+ |
+ // Store the result in the allocated heap number. |
+ __ fstp_d(FieldOperand(heap_number.reg(), HeapNumber::kValueOffset)); |
+ // Replace the extra copy of the argument with the result. |
+ frame_->SetElementAt(0, &heap_number); |
+ done.Jump(); |
+ |
+ call_runtime.Bind(); |
+ // Free ST(0) which was not popped before calling into the runtime. |
+ __ ffree(0); |
Result answer; |
switch (op) { |
case SIN: |
@@ -3546,6 +3646,7 @@ |
break; |
} |
frame_->Push(&answer); |
+ done.Bind(); |
} |
@@ -4606,57 +4707,6 @@ |
} |
-class FloatingPointHelper : public AllStatic { |
- public: |
- // Code pattern for loading a floating point value. Input value must |
- // be either a smi or a heap number object (fp value). Requirements: |
- // operand in src register. Returns operand as floating point number |
- // in XMM register |
- static void LoadFloatOperand(MacroAssembler* masm, |
- Register src, |
- XMMRegister dst); |
- // Code pattern for loading floating point values. Input values must |
- // be either smi or heap number objects (fp values). Requirements: |
- // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
- // floating point numbers in XMM registers. |
- static void LoadFloatOperands(MacroAssembler* masm, |
- XMMRegister dst1, |
- XMMRegister dst2); |
- |
- // Code pattern for loading floating point values onto the fp stack. |
- // Input values must be either smi or heap number objects (fp values). |
- // Requirements: |
- // Register version: operands in registers lhs and rhs. |
- // Stack version: operands on TOS+1 and TOS+2. |
- // Returns operands as floating point numbers on fp stack. |
- static void LoadFloatOperands(MacroAssembler* masm); |
- static void LoadFloatOperands(MacroAssembler* masm, |
- Register lhs, |
- Register rhs); |
- |
- // Code pattern for loading a floating point value and converting it |
- // to a 32 bit integer. Input value must be either a smi or a heap number |
- // object. |
- // Returns operands as 32-bit sign extended integers in a general purpose |
- // registers. |
- static void LoadInt32Operand(MacroAssembler* masm, |
- const Operand& src, |
- Register dst); |
- |
- // Test if operands are smi or number objects (fp). Requirements: |
- // operand_1 in rax, operand_2 in rdx; falls through on float |
- // operands, jumps to the non_float label otherwise. |
- static void CheckFloatOperands(MacroAssembler* masm, |
- Label* non_float); |
- // Allocate a heap number in new space with undefined value. |
- // Returns tagged pointer in result, or jumps to need_gc if new space is full. |
- static void AllocateHeapNumber(MacroAssembler* masm, |
- Label* need_gc, |
- Register scratch, |
- Register result); |
-}; |
- |
- |
class DeferredInlineBinaryOperation: public DeferredCode { |
public: |
DeferredInlineBinaryOperation(Token::Value op, |
@@ -6760,7 +6810,25 @@ |
} |
+void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
+ Register number) { |
+ Label load_smi, done; |
+ __ testl(number, Immediate(kSmiTagMask)); |
+ __ j(zero, &load_smi); |
+ __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); |
+ __ jmp(&done); |
+ |
+ __ bind(&load_smi); |
+ __ sarl(number, Immediate(kSmiTagSize)); |
+ __ push(number); |
+ __ fild_s(Operand(rsp, 0)); |
+ __ pop(number); |
+ |
+ __ bind(&done); |
+} |
+ |
+ |
void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
Register src, |
XMMRegister dst) { |