| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 dest->Split(not_equal); | 735 dest->Split(not_equal); |
| 736 } | 736 } |
| 737 | 737 |
| 738 | 738 |
| 739 class FloatingPointHelper : public AllStatic { | 739 class FloatingPointHelper : public AllStatic { |
| 740 public: | 740 public: |
| 741 // Code pattern for loading a floating point value. Input value must | 741 // Code pattern for loading a floating point value. Input value must |
| 742 // be either a smi or a heap number object (fp value). Requirements: | 742 // be either a smi or a heap number object (fp value). Requirements: |
| 743 // operand in register number. Returns operand as floating point number | 743 // operand in register number. Returns operand as floating point number |
| 744 // on FPU stack. | 744 // on FPU stack. |
| 745 static void LoadFloatOperand(MacroAssembler* masm, Register number); | 745 static void LoadFloatOperand(MacroAssembler* masm, |
| 746 Register number, |
| 747 Register scratch); |
| 746 // Code pattern for loading floating point values. Input values must | 748 // Code pattern for loading floating point values. Input values must |
| 747 // be either smi or heap number objects (fp values). Requirements: | 749 // be either smi or heap number objects (fp values). Requirements: |
| 748 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as | 750 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
| 749 // floating point numbers on FPU stack. | 751 // floating point numbers on FPU stack. |
| 750 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); | 752 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); |
| 751 // Test if operands are smi or number objects (fp). Requirements: | 753 // Test if operands are smi or number objects (fp). Requirements: |
| 752 // operand_1 in eax, operand_2 in edx; falls through on float | 754 // operand_1 in eax, operand_2 in edx; falls through on float |
| 753 // operands, jumps to the non_float label otherwise. | 755 // operands, jumps to the non_float label otherwise. |
| 754 static void CheckFloatOperands(MacroAssembler* masm, | 756 static void CheckFloatOperands(MacroAssembler* masm, |
| 755 Label* non_float, | 757 Label* non_float, |
| 756 Register scratch); | 758 Register scratch); |
| 757 // Test if operands are numbers (smi or HeapNumber objects), and load | 759 // Test if operands are numbers (smi or HeapNumber objects), and load |
| 758 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if | 760 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if |
| 759 // either operand is not a number. Operands are in edx and eax. | 761 // either operand is not a number. Operands are in edx and eax. |
| 760 // Leaves operands unchanged. | 762 // Leaves operands unchanged. |
| 761 static void LoadSse2Operands(MacroAssembler* masm, Label* not_numbers); | 763 static void LoadSse2Operands(MacroAssembler* masm, Register scratch, Label* no
t_numbers); |
| 762 }; | 764 }; |
| 763 | 765 |
| 764 | 766 |
| 765 const char* GenericBinaryOpStub::GetName() { | 767 const char* GenericBinaryOpStub::GetName() { |
| 768 bool smi = (flags_ & NO_SMI_CODE_IN_STUB) == 0; |
| 766 switch (op_) { | 769 switch (op_) { |
| 767 case Token::ADD: return "GenericBinaryOpStub_ADD"; | 770 case Token::ADD: |
| 768 case Token::SUB: return "GenericBinaryOpStub_SUB"; | 771 return smi ? "GenericBinaryOpStub_ADD_Smi" : "GenericBinaryOpStub_ADD"; |
| 769 case Token::MUL: return "GenericBinaryOpStub_MUL"; | 772 case Token::SUB: |
| 770 case Token::DIV: return "GenericBinaryOpStub_DIV"; | 773 return smi ? "GenericBinaryOpStub_SUB_Smi" : "GenericBinaryOpStub_SUB"; |
| 771 case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR"; | 774 case Token::MUL: |
| 772 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; | 775 return smi ? "GenericBinaryOpStub_MUL_Smi" : "GenericBinaryOpStub_MUL"; |
| 773 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; | 776 case Token::DIV: |
| 774 case Token::SAR: return "GenericBinaryOpStub_SAR"; | 777 return smi ? "GenericBinaryOpStub_DIV_Smi" : "GenericBinaryOpStub_DIV"; |
| 775 case Token::SHL: return "GenericBinaryOpStub_SHL"; | 778 case Token::BIT_OR: |
| 776 case Token::SHR: return "GenericBinaryOpStub_SHR"; | 779 return smi ? |
| 777 default: return "GenericBinaryOpStub"; | 780 "GenericBinaryOpStub_BIT_OR_Smi" : |
| 781 "GenericBinaryOpStub_BIT_OR"; |
| 782 case Token::BIT_AND: |
| 783 return smi ? |
| 784 "GenericBinaryOpStub_BIT_AND_Smi" : |
| 785 "GenericBinaryOpStub_BIT_AND"; |
| 786 case Token::BIT_XOR: |
| 787 return smi ? |
| 788 "GenericBinaryOpStub_BIT_XOR_Smi" : |
| 789 "GenericBinaryOpStub_BIT_XOR"; |
| 790 case Token::SAR: |
| 791 return smi ? "GenericBinaryOpStub_SAR_Smi" : "GenericBinaryOpStub_SAR"; |
| 792 case Token::SHL: |
| 793 return smi ? "GenericBinaryOpStub_SHL_Smi" : "GenericBinaryOpStub_SHL"; |
| 794 case Token::SHR: |
| 795 return smi ? "GenericBinaryOpStub_SHR_Smi" : "GenericBinaryOpStub_SHR"; |
| 796 default: |
| 797 return "GenericBinaryOpStub"; |
| 778 } | 798 } |
| 779 } | 799 } |
| 780 | 800 |
| 781 | 801 |
| 782 // Call the specialized stub for a binary operation. | 802 // Call the specialized stub for a binary operation. |
| 783 class DeferredInlineBinaryOperation: public DeferredCode { | 803 class DeferredInlineBinaryOperation: public DeferredCode { |
| 784 public: | 804 public: |
| 785 DeferredInlineBinaryOperation(Token::Value op, | 805 DeferredInlineBinaryOperation(Token::Value op, |
| 786 Register dst, | 806 Register dst, |
| 787 Register left, | 807 Register left, |
| (...skipping 4359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5147 JumpTarget done; | 5167 JumpTarget done; |
| 5148 JumpTarget call_runtime; | 5168 JumpTarget call_runtime; |
| 5149 ASSERT(args->length() == 1); | 5169 ASSERT(args->length() == 1); |
| 5150 | 5170 |
| 5151 // Load number and duplicate it. | 5171 // Load number and duplicate it. |
| 5152 Load(args->at(0)); | 5172 Load(args->at(0)); |
| 5153 frame_->Dup(); | 5173 frame_->Dup(); |
| 5154 | 5174 |
| 5155 // Get the number into an unaliased register and load it onto the | 5175 // Get the number into an unaliased register and load it onto the |
| 5156 // floating point stack still leaving one copy on the frame. | 5176 // floating point stack still leaving one copy on the frame. |
| 5177 Result scratch = allocator_->Allocate(); |
| 5178 ASSERT(scratch.is_valid()); |
| 5157 Result number = frame_->Pop(); | 5179 Result number = frame_->Pop(); |
| 5158 number.ToRegister(); | 5180 number.ToRegister(); |
| 5159 frame_->Spill(number.reg()); | 5181 frame_->Spill(number.reg()); |
| 5160 FloatingPointHelper::LoadFloatOperand(masm_, number.reg()); | 5182 FloatingPointHelper::LoadFloatOperand(masm_, number.reg(), scratch.reg()); |
| 5161 number.Unuse(); | 5183 number.Unuse(); |
| 5184 scratch.Unuse(); |
| 5162 | 5185 |
| 5163 // Perform the operation on the number. | 5186 // Perform the operation on the number. |
| 5164 switch (op) { | 5187 switch (op) { |
| 5165 case SIN: | 5188 case SIN: |
| 5166 __ fsin(); | 5189 __ fsin(); |
| 5167 break; | 5190 break; |
| 5168 case COS: | 5191 case COS: |
| 5169 __ fcos(); | 5192 __ fcos(); |
| 5170 break; | 5193 break; |
| 5171 } | 5194 } |
| 5172 | 5195 |
| 5173 // Go slow case if argument to operation is out of range. | 5196 // Go slow case if argument to operation is out of range. |
| 5174 Result eax_reg = allocator_->Allocate(eax); | 5197 Result eax_reg = allocator_->Allocate(eax); |
| 5175 ASSERT(eax_reg.is_valid()); | 5198 ASSERT(eax_reg.is_valid()); |
| 5176 __ fnstsw_ax(); | 5199 __ fnstsw_ax(); |
| 5177 __ sahf(); | 5200 __ sahf(); |
| 5178 eax_reg.Unuse(); | 5201 eax_reg.Unuse(); |
| 5179 call_runtime.Branch(parity_even, not_taken); | 5202 call_runtime.Branch(parity_even, not_taken); |
| 5180 | 5203 |
| 5181 // Allocate heap number for result if possible. | 5204 // Allocate heap number for result if possible. |
| 5182 Result scratch1 = allocator()->Allocate(); | 5205 Result scratch1 = allocator()->Allocate(); |
| 5183 Result scratch2 = allocator()->Allocate(); | 5206 Result scratch2 = allocator()->Allocate(); |
| 5184 Result heap_number = allocator()->Allocate(); | 5207 Result heap_number = allocator()->Allocate(); |
| 5185 __ AllocateHeapNumber(heap_number.reg(), | 5208 __ AllocateHeapNumber(heap_number.reg(), |
| 5186 scratch1.reg(), | 5209 scratch1.reg(), |
| 5187 scratch2.reg(), | 5210 scratch2.reg(), |
| 5188 call_runtime.entry_label()); | 5211 call_runtime.entry_label()); |
| 5189 scratch1.Unuse(); | 5212 scratch1.Unuse(); |
| 5213 |
| 5214 // Store the result in the allocated heap number. |
| 5215 __ GenerateHeapNumberValueAddress(scratch2.reg(), heap_number.reg()); |
| 5216 __ fstp_d(Operand(scratch2.reg(), 0)); |
| 5190 scratch2.Unuse(); | 5217 scratch2.Unuse(); |
| 5191 | 5218 |
| 5192 // Store the result in the allocated heap number. | |
| 5193 __ fstp_d(FieldOperand(heap_number.reg(), HeapNumber::kValueOffset)); | |
| 5194 // Replace the extra copy of the argument with the result. | 5219 // Replace the extra copy of the argument with the result. |
| 5195 frame_->SetElementAt(0, &heap_number); | 5220 frame_->SetElementAt(0, &heap_number); |
| 5196 done.Jump(); | 5221 done.Jump(); |
| 5197 | 5222 |
| 5198 call_runtime.Bind(); | 5223 call_runtime.Bind(); |
| 5199 // Free ST(0) which was not popped before calling into the runtime. | 5224 // Free ST(0) which was not popped before calling into the runtime. |
| 5200 __ ffree(0); | 5225 __ ffree(0); |
| 5201 Result answer; | 5226 Result answer; |
| 5202 switch (op) { | 5227 switch (op) { |
| 5203 case SIN: | 5228 case SIN: |
| (...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6507 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); | 6532 __ mov(edx, FieldOperand(eax, String::kLengthOffset)); |
| 6508 __ test(edx, Operand(edx)); | 6533 __ test(edx, Operand(edx)); |
| 6509 __ j(zero, &false_result); | 6534 __ j(zero, &false_result); |
| 6510 __ jmp(&true_result); | 6535 __ jmp(&true_result); |
| 6511 | 6536 |
| 6512 __ bind(¬_string); | 6537 __ bind(¬_string); |
| 6513 // HeapNumber => false iff +0, -0, or NaN. | 6538 // HeapNumber => false iff +0, -0, or NaN. |
| 6514 __ cmp(edx, Factory::heap_number_map()); | 6539 __ cmp(edx, Factory::heap_number_map()); |
| 6515 __ j(not_equal, &true_result); | 6540 __ j(not_equal, &true_result); |
| 6516 __ fldz(); | 6541 __ fldz(); |
| 6517 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 6542 __ GenerateHeapNumberValueAddress(edx, eax); |
| 6543 __ fld_d(Operand(edx, 0)); |
| 6518 __ FCmp(); | 6544 __ FCmp(); |
| 6519 __ j(zero, &false_result); | 6545 __ j(zero, &false_result); |
| 6520 // Fall through to |true_result|. | 6546 // Fall through to |true_result|. |
| 6521 | 6547 |
| 6522 // Return 1/0 for true/false in eax. | 6548 // Return 1/0 for true/false in eax. |
| 6523 __ bind(&true_result); | 6549 __ bind(&true_result); |
| 6524 __ mov(eax, 1); | 6550 __ mov(eax, 1); |
| 6525 __ ret(1 * kPointerSize); | 6551 __ ret(1 * kPointerSize); |
| 6526 __ bind(&false_result); | 6552 __ bind(&false_result); |
| 6527 __ mov(eax, 0); | 6553 __ mov(eax, 0); |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6819 switch (op_) { | 6845 switch (op_) { |
| 6820 case Token::ADD: | 6846 case Token::ADD: |
| 6821 case Token::SUB: | 6847 case Token::SUB: |
| 6822 case Token::MUL: | 6848 case Token::MUL: |
| 6823 case Token::DIV: { | 6849 case Token::DIV: { |
| 6824 // eax: y | 6850 // eax: y |
| 6825 // edx: x | 6851 // edx: x |
| 6826 | 6852 |
| 6827 if (CpuFeatures::IsSupported(SSE2)) { | 6853 if (CpuFeatures::IsSupported(SSE2)) { |
| 6828 CpuFeatures::Scope use_sse2(SSE2); | 6854 CpuFeatures::Scope use_sse2(SSE2); |
| 6829 FloatingPointHelper::LoadSse2Operands(masm, &call_runtime); | 6855 FloatingPointHelper::LoadSse2Operands(masm, ecx, &call_runtime); |
| 6830 | 6856 |
| 6831 switch (op_) { | 6857 switch (op_) { |
| 6832 case Token::ADD: __ addsd(xmm0, xmm1); break; | 6858 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| 6833 case Token::SUB: __ subsd(xmm0, xmm1); break; | 6859 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 6834 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 6860 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 6835 case Token::DIV: __ divsd(xmm0, xmm1); break; | 6861 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 6836 default: UNREACHABLE(); | 6862 default: UNREACHABLE(); |
| 6837 } | 6863 } |
| 6838 // Allocate a heap number, if needed. | 6864 // Allocate a heap number, if needed. |
| 6839 Label skip_allocation; | 6865 Label skip_allocation; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 6852 // for the possible runtime call. | 6878 // for the possible runtime call. |
| 6853 __ AllocateHeapNumber(ebx, ecx, no_reg, &call_runtime); | 6879 __ AllocateHeapNumber(ebx, ecx, no_reg, &call_runtime); |
| 6854 // Now eax can be overwritten losing one of the arguments as we are | 6880 // Now eax can be overwritten losing one of the arguments as we are |
| 6855 // now done and will not need it any more. | 6881 // now done and will not need it any more. |
| 6856 __ mov(eax, ebx); | 6882 __ mov(eax, ebx); |
| 6857 __ bind(&skip_allocation); | 6883 __ bind(&skip_allocation); |
| 6858 break; | 6884 break; |
| 6859 } | 6885 } |
| 6860 default: UNREACHABLE(); | 6886 default: UNREACHABLE(); |
| 6861 } | 6887 } |
| 6862 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 6888 __ GenerateHeapNumberValueAddress(ecx, eax); |
| 6889 __ movdbl(Operand(ecx, 0), xmm0); |
| 6863 GenerateReturn(masm); | 6890 GenerateReturn(masm); |
| 6864 } else { // SSE2 not available, use FPU. | 6891 } else { // SSE2 not available, use FPU. |
| 6865 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); | 6892 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); |
| 6866 // Allocate a heap number, if needed. | 6893 // Allocate a heap number, if needed. |
| 6867 Label skip_allocation; | 6894 Label skip_allocation; |
| 6868 switch (mode_) { | 6895 switch (mode_) { |
| 6869 case OVERWRITE_LEFT: | 6896 case OVERWRITE_LEFT: |
| 6870 __ mov(eax, Operand(edx)); | 6897 __ mov(eax, Operand(edx)); |
| 6871 // Fall through! | 6898 // Fall through! |
| 6872 case OVERWRITE_RIGHT: | 6899 case OVERWRITE_RIGHT: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6888 } | 6915 } |
| 6889 FloatingPointHelper::LoadFloatOperands(masm, ecx); | 6916 FloatingPointHelper::LoadFloatOperands(masm, ecx); |
| 6890 | 6917 |
| 6891 switch (op_) { | 6918 switch (op_) { |
| 6892 case Token::ADD: __ faddp(1); break; | 6919 case Token::ADD: __ faddp(1); break; |
| 6893 case Token::SUB: __ fsubp(1); break; | 6920 case Token::SUB: __ fsubp(1); break; |
| 6894 case Token::MUL: __ fmulp(1); break; | 6921 case Token::MUL: __ fmulp(1); break; |
| 6895 case Token::DIV: __ fdivp(1); break; | 6922 case Token::DIV: __ fdivp(1); break; |
| 6896 default: UNREACHABLE(); | 6923 default: UNREACHABLE(); |
| 6897 } | 6924 } |
| 6898 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 6925 __ GenerateHeapNumberValueAddress(ecx, eax); |
| 6926 __ fstp_d(Operand(ecx, 0)); |
| 6899 GenerateReturn(masm); | 6927 GenerateReturn(masm); |
| 6900 } | 6928 } |
| 6901 } | 6929 } |
| 6902 case Token::MOD: { | 6930 case Token::MOD: { |
| 6903 // For MOD we go directly to runtime in the non-smi case. | 6931 // For MOD we go directly to runtime in the non-smi case. |
| 6904 break; | 6932 break; |
| 6905 } | 6933 } |
| 6906 case Token::BIT_OR: | 6934 case Token::BIT_OR: |
| 6907 case Token::BIT_AND: | 6935 case Token::BIT_AND: |
| 6908 case Token::BIT_XOR: | 6936 case Token::BIT_XOR: |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6985 // Fall through! | 7013 // Fall through! |
| 6986 case NO_OVERWRITE: | 7014 case NO_OVERWRITE: |
| 6987 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 7015 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 6988 __ bind(&skip_allocation); | 7016 __ bind(&skip_allocation); |
| 6989 break; | 7017 break; |
| 6990 default: UNREACHABLE(); | 7018 default: UNREACHABLE(); |
| 6991 } | 7019 } |
| 6992 // Store the result in the HeapNumber and return. | 7020 // Store the result in the HeapNumber and return. |
| 6993 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 7021 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 6994 __ fild_s(Operand(esp, 1 * kPointerSize)); | 7022 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 6995 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 7023 __ GenerateHeapNumberValueAddress(ecx, eax); |
| 7024 __ fstp_d(Operand(ecx, 0)); |
| 6996 GenerateReturn(masm); | 7025 GenerateReturn(masm); |
| 6997 } | 7026 } |
| 6998 | 7027 |
| 6999 // Clear the FPU exception flag and reset the stack before calling | 7028 // Clear the FPU exception flag and reset the stack before calling |
| 7000 // the runtime system. | 7029 // the runtime system. |
| 7001 __ bind(&operand_conversion_failure); | 7030 __ bind(&operand_conversion_failure); |
| 7002 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 7031 __ add(Operand(esp), Immediate(2 * kPointerSize)); |
| 7003 if (use_sse3_) { | 7032 if (use_sse3_) { |
| 7004 // If we've used the SSE3 instructions for truncating the | 7033 // If we've used the SSE3 instructions for truncating the |
| 7005 // floating point values to integers and it failed, we have a | 7034 // floating point values to integers and it failed, we have a |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7129 // returning. | 7158 // returning. |
| 7130 if (!HasArgumentsInRegisters()) { | 7159 if (!HasArgumentsInRegisters()) { |
| 7131 __ ret(2 * kPointerSize); // Remove both operands | 7160 __ ret(2 * kPointerSize); // Remove both operands |
| 7132 } else { | 7161 } else { |
| 7133 __ ret(0); | 7162 __ ret(0); |
| 7134 } | 7163 } |
| 7135 } | 7164 } |
| 7136 | 7165 |
| 7137 | 7166 |
| 7138 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 7167 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
| 7139 Register number) { | 7168 Register number, |
| 7169 Register scratch) { |
| 7140 Label load_smi, done; | 7170 Label load_smi, done; |
| 7141 | 7171 |
| 7142 __ test(number, Immediate(kSmiTagMask)); | 7172 __ test(number, Immediate(kSmiTagMask)); |
| 7143 __ j(zero, &load_smi, not_taken); | 7173 __ j(zero, &load_smi, not_taken); |
| 7144 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 7174 __ GenerateHeapNumberValueAddress(scratch, number); |
| 7175 __ fld_d(Operand(scratch, 0)); |
| 7145 __ jmp(&done); | 7176 __ jmp(&done); |
| 7146 | 7177 |
| 7147 __ bind(&load_smi); | 7178 __ bind(&load_smi); |
| 7148 __ sar(number, kSmiTagSize); | 7179 __ sar(number, kSmiTagSize); |
| 7149 __ push(number); | 7180 __ push(number); |
| 7150 __ fild_s(Operand(esp, 0)); | 7181 __ fild_s(Operand(esp, 0)); |
| 7151 __ pop(number); | 7182 __ pop(number); |
| 7152 | 7183 |
| 7153 __ bind(&done); | 7184 __ bind(&done); |
| 7154 } | 7185 } |
| 7155 | 7186 |
| 7156 | 7187 |
| 7157 void FloatingPointHelper::LoadSse2Operands(MacroAssembler* masm, | 7188 void FloatingPointHelper::LoadSse2Operands(MacroAssembler* masm, |
| 7189 Register scratch, |
| 7158 Label* not_numbers) { | 7190 Label* not_numbers) { |
| 7159 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; | 7191 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; |
| 7160 // Load operand in edx into xmm0, or branch to not_numbers. | 7192 // Load operand in edx into xmm0, or branch to not_numbers. |
| 7161 __ test(edx, Immediate(kSmiTagMask)); | 7193 __ test(edx, Immediate(kSmiTagMask)); |
| 7162 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. | 7194 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. |
| 7163 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); | 7195 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Factory::heap_number_map()); |
| 7164 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 7196 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
| 7165 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 7197 __ GenerateHeapNumberValueAddress(scratch, edx); |
| 7198 __ movdbl(xmm0, Operand(scratch, 0)); |
| 7166 __ bind(&load_eax); | 7199 __ bind(&load_eax); |
| 7167 // Load operand in eax into xmm1, or branch to not_numbers. | 7200 // Load operand in eax into xmm1, or branch to not_numbers. |
| 7168 __ test(eax, Immediate(kSmiTagMask)); | 7201 __ test(eax, Immediate(kSmiTagMask)); |
| 7169 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 7202 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. |
| 7170 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); | 7203 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); |
| 7171 __ j(equal, &load_float_eax); | 7204 __ j(equal, &load_float_eax); |
| 7172 __ jmp(not_numbers); // Argument in eax is not a number. | 7205 __ jmp(not_numbers); // Argument in eax is not a number. |
| 7173 __ bind(&load_smi_edx); | 7206 __ bind(&load_smi_edx); |
| 7174 __ sar(edx, 1); // Untag smi before converting to float. | 7207 __ sar(edx, 1); // Untag smi before converting to float. |
| 7175 __ cvtsi2sd(xmm0, Operand(edx)); | 7208 __ cvtsi2sd(xmm0, Operand(edx)); |
| 7176 __ shl(edx, 1); // Retag smi for heap number overwriting test. | 7209 __ shl(edx, 1); // Retag smi for heap number overwriting test. |
| 7177 __ jmp(&load_eax); | 7210 __ jmp(&load_eax); |
| 7178 __ bind(&load_smi_eax); | 7211 __ bind(&load_smi_eax); |
| 7179 __ sar(eax, 1); // Untag smi before converting to float. | 7212 __ sar(eax, 1); // Untag smi before converting to float. |
| 7180 __ cvtsi2sd(xmm1, Operand(eax)); | 7213 __ cvtsi2sd(xmm1, Operand(eax)); |
| 7181 __ shl(eax, 1); // Retag smi for heap number overwriting test. | 7214 __ shl(eax, 1); // Retag smi for heap number overwriting test. |
| 7182 __ jmp(&done); | 7215 __ jmp(&done); |
| 7183 __ bind(&load_float_eax); | 7216 __ bind(&load_float_eax); |
| 7184 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 7217 __ GenerateHeapNumberValueAddress(scratch, eax); |
| 7218 __ movdbl(xmm1, Operand(scratch, 0)); |
| 7185 __ bind(&done); | 7219 __ bind(&done); |
| 7186 } | 7220 } |
| 7187 | 7221 |
| 7188 | 7222 |
| 7189 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 7223 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
| 7190 Register scratch) { | 7224 Register scratch) { |
| 7191 Label load_smi_1, load_smi_2, done_load_1, done; | 7225 Label load_smi_1, load_smi_2, done_load_1, done; |
| 7192 __ mov(scratch, Operand(esp, 2 * kPointerSize)); | 7226 __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
| 7193 __ test(scratch, Immediate(kSmiTagMask)); | 7227 __ test(scratch, Immediate(kSmiTagMask)); |
| 7194 __ j(zero, &load_smi_1, not_taken); | 7228 __ j(zero, &load_smi_1, not_taken); |
| 7195 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 7229 __ GenerateHeapNumberValueAddress(scratch, scratch); |
| 7230 __ fld_d(Operand(scratch, 0)); |
| 7196 __ bind(&done_load_1); | 7231 __ bind(&done_load_1); |
| 7197 | 7232 |
| 7198 __ mov(scratch, Operand(esp, 1 * kPointerSize)); | 7233 __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
| 7199 __ test(scratch, Immediate(kSmiTagMask)); | 7234 __ test(scratch, Immediate(kSmiTagMask)); |
| 7200 __ j(zero, &load_smi_2, not_taken); | 7235 __ j(zero, &load_smi_2, not_taken); |
| 7201 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 7236 __ GenerateHeapNumberValueAddress(scratch, scratch); |
| 7237 __ fld_d(Operand(scratch, 0)); |
| 7202 __ jmp(&done); | 7238 __ jmp(&done); |
| 7203 | 7239 |
| 7204 __ bind(&load_smi_1); | 7240 __ bind(&load_smi_1); |
| 7205 __ sar(scratch, kSmiTagSize); | 7241 __ sar(scratch, kSmiTagSize); |
| 7206 __ push(scratch); | 7242 __ push(scratch); |
| 7207 __ fild_s(Operand(esp, 0)); | 7243 __ fild_s(Operand(esp, 0)); |
| 7208 __ pop(scratch); | 7244 __ pop(scratch); |
| 7209 __ jmp(&done_load_1); | 7245 __ jmp(&done_load_1); |
| 7210 | 7246 |
| 7211 __ bind(&load_smi_2); | 7247 __ bind(&load_smi_2); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7278 __ push(eax); | 7314 __ push(eax); |
| 7279 __ push(ecx); // push return address | 7315 __ push(ecx); // push return address |
| 7280 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | 7316 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); |
| 7281 | 7317 |
| 7282 // Try floating point case. | 7318 // Try floating point case. |
| 7283 __ bind(&try_float); | 7319 __ bind(&try_float); |
| 7284 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 7320 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 7285 __ cmp(edx, Factory::heap_number_map()); | 7321 __ cmp(edx, Factory::heap_number_map()); |
| 7286 __ j(not_equal, &slow); | 7322 __ j(not_equal, &slow); |
| 7287 if (overwrite_) { | 7323 if (overwrite_) { |
| 7288 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 7324 __ GenerateHeapNumberValueAddress(ebx, eax); |
| 7325 __ mov(edx, Operand(ebx, HeapNumber::kExponentRelativeOffset)); |
| 7289 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. | 7326 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. |
| 7290 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); | 7327 __ mov(Operand(ebx, HeapNumber::kExponentRelativeOffset), edx); |
| 7291 } else { | 7328 } else { |
| 7292 __ mov(edx, Operand(eax)); | 7329 __ mov(edx, Operand(eax)); |
| 7293 // edx: operand | 7330 // edx: operand |
| 7294 __ AllocateHeapNumber(eax, ebx, ecx, &undo); | 7331 __ AllocateHeapNumber(eax, ebx, ecx, &undo); |
| 7295 // eax: allocated 'empty' number | 7332 // eax: allocated 'empty' number |
| 7296 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 7333 __ GenerateHeapNumberValueAddress(edx, edx); |
| 7334 __ GenerateHeapNumberValueAddress(ebx, eax); |
| 7335 __ mov(ecx, Operand(edx, HeapNumber::kExponentRelativeOffset)); |
| 7297 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | 7336 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. |
| 7298 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | 7337 __ mov(Operand(ebx, HeapNumber::kExponentRelativeOffset), ecx); |
| 7299 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | 7338 __ mov(ecx, Operand(edx, HeapNumber::kMantissaRelativeOffset)); |
| 7300 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 7339 __ mov(Operand(ebx, HeapNumber::kMantissaRelativeOffset), ecx); |
| 7301 } | 7340 } |
| 7302 | 7341 |
| 7303 __ bind(&done); | 7342 __ bind(&done); |
| 7304 | 7343 |
| 7305 __ StubReturn(1); | 7344 __ StubReturn(1); |
| 7306 } | 7345 } |
| 7307 | 7346 |
| 7308 | 7347 |
| 7309 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { | 7348 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { |
| 7310 // Check if the calling frame is an arguments adaptor frame. | 7349 // Check if the calling frame is an arguments adaptor frame. |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7441 // not NaN. | 7480 // not NaN. |
| 7442 // The representation of NaN values has all exponent bits (52..62) set, | 7481 // The representation of NaN values has all exponent bits (52..62) set, |
| 7443 // and not all mantissa bits (0..51) clear. | 7482 // and not all mantissa bits (0..51) clear. |
| 7444 // We only accept QNaNs, which have bit 51 set. | 7483 // We only accept QNaNs, which have bit 51 set. |
| 7445 // Read top bits of double representation (second word of value). | 7484 // Read top bits of double representation (second word of value). |
| 7446 | 7485 |
| 7447 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., | 7486 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., |
| 7448 // all bits in the mask are set. We only need to check the word | 7487 // all bits in the mask are set. We only need to check the word |
| 7449 // that contains the exponent and high bit of the mantissa. | 7488 // that contains the exponent and high bit of the mantissa. |
| 7450 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); | 7489 ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); |
| 7451 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 7490 __ GenerateHeapNumberValueAddress(edx, edx); |
| 7491 __ mov(edx, Operand(edx, HeapNumber::kExponentRelativeOffset)); |
| 7452 __ xor_(eax, Operand(eax)); | 7492 __ xor_(eax, Operand(eax)); |
| 7453 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost bits. | 7493 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost bits. |
| 7454 __ add(edx, Operand(edx)); | 7494 __ add(edx, Operand(edx)); |
| 7455 __ cmp(edx, kQuietNaNHighBitsMask << 1); | 7495 __ cmp(edx, kQuietNaNHighBitsMask << 1); |
| 7456 __ setcc(above_equal, eax); | 7496 __ setcc(above_equal, eax); |
| 7457 __ ret(0); | 7497 __ ret(0); |
| 7458 | 7498 |
| 7459 __ bind(¬_identical); | 7499 __ bind(¬_identical); |
| 7460 } | 7500 } |
| 7461 | 7501 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7545 __ push(ecx); | 7585 __ push(ecx); |
| 7546 | 7586 |
| 7547 // Inlined floating point compare. | 7587 // Inlined floating point compare. |
| 7548 // Call builtin if operands are not floating point or smi. | 7588 // Call builtin if operands are not floating point or smi. |
| 7549 Label check_for_symbols; | 7589 Label check_for_symbols; |
| 7550 Label unordered; | 7590 Label unordered; |
| 7551 if (CpuFeatures::IsSupported(SSE2)) { | 7591 if (CpuFeatures::IsSupported(SSE2)) { |
| 7552 CpuFeatures::Scope use_sse2(SSE2); | 7592 CpuFeatures::Scope use_sse2(SSE2); |
| 7553 CpuFeatures::Scope use_cmov(CMOV); | 7593 CpuFeatures::Scope use_cmov(CMOV); |
| 7554 | 7594 |
| 7555 FloatingPointHelper::LoadSse2Operands(masm, &check_for_symbols); | 7595 FloatingPointHelper::LoadSse2Operands(masm, ecx, &check_for_symbols); |
| 7556 __ comisd(xmm0, xmm1); | 7596 __ comisd(xmm0, xmm1); |
| 7557 | 7597 |
| 7558 // Jump to builtin for NaN. | 7598 // Jump to builtin for NaN. |
| 7559 __ j(parity_even, &unordered, not_taken); | 7599 __ j(parity_even, &unordered, not_taken); |
| 7560 __ mov(eax, 0); // equal | 7600 __ mov(eax, 0); // equal |
| 7561 __ mov(ecx, Immediate(Smi::FromInt(1))); | 7601 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 7562 __ cmov(above, eax, Operand(ecx)); | 7602 __ cmov(above, eax, Operand(ecx)); |
| 7563 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 7603 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 7564 __ cmov(below, eax, Operand(ecx)); | 7604 __ cmov(below, eax, Operand(ecx)); |
| 7565 __ ret(2 * kPointerSize); | 7605 __ ret(2 * kPointerSize); |
| (...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8399 __ add(Operand(dest), Immediate(2)); | 8439 __ add(Operand(dest), Immediate(2)); |
| 8400 } | 8440 } |
| 8401 __ sub(Operand(count), Immediate(1)); | 8441 __ sub(Operand(count), Immediate(1)); |
| 8402 __ j(not_zero, &loop); | 8442 __ j(not_zero, &loop); |
| 8403 } | 8443 } |
| 8404 | 8444 |
| 8405 | 8445 |
| 8406 #undef __ | 8446 #undef __ |
| 8407 | 8447 |
| 8408 } } // namespace v8::internal | 8448 } } // namespace v8::internal |
| OLD | NEW |