OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 8040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8051 __ fcos(); | 8051 __ fcos(); |
8052 break; | 8052 break; |
8053 default: | 8053 default: |
8054 UNREACHABLE(); | 8054 UNREACHABLE(); |
8055 } | 8055 } |
8056 __ bind(&done); | 8056 __ bind(&done); |
8057 } | 8057 } |
8058 | 8058 |
8059 | 8059 |
8060 // Get the integer part of a heap number. | 8060 // Get the integer part of a heap number. |
8061 // Trashes rdi and rbx. Dest is rcx. Source cannot be rcx or one of the | 8061 // Overwrites the contents of rdi, rbx and rcx. Result cannot be rdi or rbx. |
8062 // trashed registers. | |
8063 void IntegerConvert(MacroAssembler* masm, | 8062 void IntegerConvert(MacroAssembler* masm, |
8064 Register source, | 8063 Register result, |
8065 Label* conversion_failure) { | 8064 Register source) { |
8066 ASSERT(!source.is(rcx) && !source.is(rdi) && !source.is(rbx)); | 8065 // Result may be rcx. If result and source are the same register, source will |
8067 Register scratch = rbx; | 8066 // be overwritten. |
8068 Register scratch2 = rdi; | 8067 ASSERT(!result.is(rdi) && !result.is(rbx)); |
8069 // Get exponent word. | 8068 // TODO(lrn): When type info reaches here, if value is a 32-bit integer, use |
8070 __ movq(scratch2, FieldOperand(source, HeapNumber::kValueOffset)); | 8069 // cvttsd2si (32-bit version) directly. |
8071 // Get exponent alone in scratch2. | 8070 Register double_exponent = rbx; |
8072 __ movq(xmm0, scratch2); | 8071 Register double_value = rdi; |
8073 __ shr(scratch2, Immediate(HeapNumber::kMantissaBits)); | 8072 Label done, exponent_63_plus; |
8074 __ andl(scratch2, Immediate((1 << HeapNumber::KExponentBits) - 1)); | 8073 // Get double and extract exponent. |
| 8074 __ movq(double_value, FieldOperand(source, HeapNumber::kValueOffset)); |
| 8075 // Clear result preemptively, in case we need to return zero. |
| 8076 __ xorl(result, result); |
| 8077 __ movq(xmm0, double_value); // Save copy in xmm0 in case we need it there. |
| 8078 // Double to remove sign bit, shift exponent down to least significant bits. |
| 8079 // and subtract bias to get the unshifted, unbiased exponent. |
| 8080 __ lea(double_exponent, Operand(double_value, double_value, times_1, 0)); |
| 8081 __ shr(double_exponent, Immediate(64 - HeapNumber::KExponentBits)); |
| 8082 __ subl(double_exponent, Immediate(HeapNumber::kExponentBias)); |
8075 // Check whether the exponent is too big for a 63 bit unsigned integer. | 8083 // Check whether the exponent is too big for a 63 bit unsigned integer. |
8076 // (Notice: Doesn't handle MIN_SMI). | 8084 __ cmpl(double_exponent, Immediate(63)); |
8077 __ cmpl(scratch2, Immediate(63 + HeapNumber::kExponentBias)); | 8085 __ j(above_equal, &exponent_63_plus); |
8078 __ j(greater_equal, conversion_failure); | 8086 // Handle exponent range 0..62. |
8079 // Handle exponent range -inf..62. | 8087 __ cvttsd2siq(result, xmm0); |
8080 __ cvttsd2siq(rcx, xmm0); | 8088 __ jmp(&done); |
8081 // TODO(lrn): Do bit-fiddling for exponents in range 63..84 and return | 8089 |
8082 // zero for everything else (also including negative exponents). | 8090 __ bind(&exponent_63_plus); |
| 8091 // Exponent negative or 63+. |
| 8092 __ cmpl(double_exponent, Immediate(83)); |
| 8093 // If exponent negative or above 83, number contains no significant bits in |
| 8094 // the range 0..2^31, so result is zero, and rcx already holds zero. |
| 8095 __ j(above, &done); |
| 8096 |
| 8097 // Exponent in rage 63..83. |
| 8098 // Mantissa * 2^exponent contains bits in the range 2^0..2^31, namely |
| 8099 // the least significant exponent-52 bits. |
| 8100 |
| 8101 // Negate low bits of mantissa if value is negative. |
| 8102 __ addq(double_value, double_value); // Move sign bit to carry. |
| 8103 __ sbbl(result, result); // And convert carry to -1 in result register. |
| 8104 // if scratch2 is negative, do (scratch2-1)^-1, otherwise (scratch2-0)^0. |
| 8105 __ addl(double_value, result); |
| 8106 // Do xor in opposite directions depending on where we want the result |
| 8107 // (depending on whether result is rcx or not). |
| 8108 |
| 8109 if (result.is(rcx)) { |
| 8110 __ xorl(double_value, result); |
| 8111 // Left shift mantissa by (exponent - mantissabits - 1) to save the |
| 8112 // bits that have positional values below 2^32 (the extra -1 comes from the |
| 8113 // doubling done above to move the sign bit into the carry flag). |
| 8114 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1)); |
| 8115 __ shll_cl(double_value); |
| 8116 __ movl(result, double_value); |
| 8117 } else { |
| 8118 // As the then-branch, but move double-value to result before shifting. |
| 8119 __ xorl(result, double_value); |
| 8120 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1)); |
| 8121 __ shll_cl(result); |
| 8122 } |
| 8123 |
| 8124 __ bind(&done); |
8083 } | 8125 } |
8084 | 8126 |
8085 | 8127 |
8086 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | 8128 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
8087 Label slow, done; | 8129 Label slow, done; |
8088 | 8130 |
8089 if (op_ == Token::SUB) { | 8131 if (op_ == Token::SUB) { |
8090 // Check whether the value is a smi. | 8132 // Check whether the value is a smi. |
8091 Label try_float; | 8133 Label try_float; |
8092 __ JumpIfNotSmi(rax, &try_float); | 8134 __ JumpIfNotSmi(rax, &try_float); |
(...skipping 29 matching lines...) Expand all Loading... |
8122 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); | 8164 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); |
8123 __ movq(rax, rcx); | 8165 __ movq(rax, rcx); |
8124 } | 8166 } |
8125 } else if (op_ == Token::BIT_NOT) { | 8167 } else if (op_ == Token::BIT_NOT) { |
8126 // Check if the operand is a heap number. | 8168 // Check if the operand is a heap number. |
8127 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 8169 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
8128 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); | 8170 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); |
8129 __ j(not_equal, &slow); | 8171 __ j(not_equal, &slow); |
8130 | 8172 |
8131 // Convert the heap number in rax to an untagged integer in rcx. | 8173 // Convert the heap number in rax to an untagged integer in rcx. |
8132 IntegerConvert(masm, rax, &slow); | 8174 IntegerConvert(masm, rax, rax); |
8133 | 8175 |
8134 // Do the bitwise operation and check if the result fits in a smi. | 8176 // Do the bitwise operation and smi tag the result. |
8135 Label try_float; | 8177 __ notl(rax); |
8136 __ not_(rcx); | 8178 __ Integer32ToSmi(rax, rax); |
8137 // Tag the result as a smi and we're done. | |
8138 ASSERT(kSmiTagSize == 1); | |
8139 __ Integer32ToSmi(rax, rcx); | |
8140 } | 8179 } |
8141 | 8180 |
8142 // Return from the stub. | 8181 // Return from the stub. |
8143 __ bind(&done); | 8182 __ bind(&done); |
8144 __ StubReturn(1); | 8183 __ StubReturn(1); |
8145 | 8184 |
8146 // Handle the slow case by jumping to the JavaScript builtin. | 8185 // Handle the slow case by jumping to the JavaScript builtin. |
8147 __ bind(&slow); | 8186 __ bind(&slow); |
8148 __ pop(rcx); // pop return address | 8187 __ pop(rcx); // pop return address |
8149 __ push(rax); | 8188 __ push(rax); |
(...skipping 1575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9725 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 9764 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
9726 __ j(not_equal, conversion_failure); | 9765 __ j(not_equal, conversion_failure); |
9727 __ movl(rdx, Immediate(0)); | 9766 __ movl(rdx, Immediate(0)); |
9728 __ jmp(&load_arg2); | 9767 __ jmp(&load_arg2); |
9729 | 9768 |
9730 __ bind(&arg1_is_object); | 9769 __ bind(&arg1_is_object); |
9731 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 9770 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
9732 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); | 9771 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); |
9733 __ j(not_equal, &check_undefined_arg1); | 9772 __ j(not_equal, &check_undefined_arg1); |
9734 // Get the untagged integer version of the edx heap number in rcx. | 9773 // Get the untagged integer version of the edx heap number in rcx. |
9735 IntegerConvert(masm, rdx, conversion_failure); | 9774 IntegerConvert(masm, rdx, rdx); |
9736 __ movl(rdx, rcx); | |
9737 | 9775 |
9738 // Here rdx has the untagged integer, rax has a Smi or a heap number. | 9776 // Here rdx has the untagged integer, rax has a Smi or a heap number. |
9739 __ bind(&load_arg2); | 9777 __ bind(&load_arg2); |
9740 // Test if arg2 is a Smi. | 9778 // Test if arg2 is a Smi. |
9741 __ JumpIfNotSmi(rax, &arg2_is_object); | 9779 __ JumpIfNotSmi(rax, &arg2_is_object); |
9742 __ SmiToInteger32(rax, rax); | 9780 __ SmiToInteger32(rax, rax); |
9743 __ movl(rcx, rax); | 9781 __ movl(rcx, rax); |
9744 __ jmp(&done); | 9782 __ jmp(&done); |
9745 | 9783 |
9746 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 9784 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
9747 __ bind(&check_undefined_arg2); | 9785 __ bind(&check_undefined_arg2); |
9748 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 9786 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
9749 __ j(not_equal, conversion_failure); | 9787 __ j(not_equal, conversion_failure); |
9750 __ movl(rcx, Immediate(0)); | 9788 __ movl(rcx, Immediate(0)); |
9751 __ jmp(&done); | 9789 __ jmp(&done); |
9752 | 9790 |
9753 __ bind(&arg2_is_object); | 9791 __ bind(&arg2_is_object); |
9754 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 9792 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
9755 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); | 9793 __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex); |
9756 __ j(not_equal, &check_undefined_arg2); | 9794 __ j(not_equal, &check_undefined_arg2); |
9757 // Get the untagged integer version of the eax heap number in ecx. | 9795 // Get the untagged integer version of the eax heap number in ecx. |
9758 IntegerConvert(masm, rax, conversion_failure); | 9796 IntegerConvert(masm, rcx, rax); |
9759 __ bind(&done); | 9797 __ bind(&done); |
9760 __ movl(rax, rdx); | 9798 __ movl(rax, rdx); |
9761 } | 9799 } |
9762 | 9800 |
9763 | 9801 |
9764 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 9802 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
9765 Register lhs, | 9803 Register lhs, |
9766 Register rhs) { | 9804 Register rhs) { |
9767 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done; | 9805 Label load_smi_lhs, load_smi_rhs, done_load_lhs, done; |
9768 __ JumpIfSmi(lhs, &load_smi_lhs); | 9806 __ JumpIfSmi(lhs, &load_smi_lhs); |
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11572 // Call the function from C++. | 11610 // Call the function from C++. |
11573 return FUNCTION_CAST<ModuloFunction>(buffer); | 11611 return FUNCTION_CAST<ModuloFunction>(buffer); |
11574 } | 11612 } |
11575 | 11613 |
11576 #endif | 11614 #endif |
11577 | 11615 |
11578 | 11616 |
11579 #undef __ | 11617 #undef __ |
11580 | 11618 |
11581 } } // namespace v8::internal | 11619 } } // namespace v8::internal |
OLD | NEW |