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 6347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6358 // the operands were not both Smi. The operands are in r0 and r1. In order | 6358 // the operands were not both Smi. The operands are in r0 and r1. In order |
6359 // to call the C-implemented binary fp operation routines we need to end up | 6359 // to call the C-implemented binary fp operation routines we need to end up |
6360 // with the double precision floating point operands in r0 and r1 (for the | 6360 // with the double precision floating point operands in r0 and r1 (for the |
6361 // value in r1) and r2 and r3 (for the value in r0). | 6361 // value in r1) and r2 and r3 (for the value in r0). |
6362 void GenericBinaryOpStub::HandleBinaryOpSlowCases( | 6362 void GenericBinaryOpStub::HandleBinaryOpSlowCases( |
6363 MacroAssembler* masm, | 6363 MacroAssembler* masm, |
6364 Label* not_smi, | 6364 Label* not_smi, |
6365 Register lhs, | 6365 Register lhs, |
6366 Register rhs, | 6366 Register rhs, |
6367 const Builtins::JavaScript& builtin) { | 6367 const Builtins::JavaScript& builtin) { |
6368 Label slow, slow_pop_2_first, do_the_call; | 6368 Label slow, slow_reverse, do_the_call; |
6369 Label r0_is_smi, r1_is_smi, finished_loading_r0, finished_loading_r1; | |
6370 bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_; | 6369 bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_; |
6371 | 6370 |
6372 ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0))); | 6371 ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0))); |
6373 | 6372 |
6374 if (ShouldGenerateSmiCode()) { | 6373 if (ShouldGenerateSmiCode()) { |
6375 // Smi-smi case (overflow). | 6374 // Smi-smi case (overflow). |
6376 // Since both are Smis there is no heap number to overwrite, so allocate. | 6375 // Since both are Smis there is no heap number to overwrite, so allocate. |
6377 // The new heap number is in r5. r6 and r7 are scratch. | 6376 // The new heap number is in r5. r6 and r7 are scratch. |
6378 __ AllocateHeapNumber(r5, r6, r7, &slow); | 6377 __ AllocateHeapNumber(r5, r6, r7, lhs.is(r0) ? &slow_reverse : &slow); |
6379 | 6378 |
6380 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV, | 6379 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV, |
6381 // using registers d7 and d6 for the double values. | 6380 // using registers d7 and d6 for the double values. |
6382 if (use_fp_registers) { | 6381 if (use_fp_registers) { |
6383 CpuFeatures::Scope scope(VFP3); | 6382 CpuFeatures::Scope scope(VFP3); |
6384 __ mov(r7, Operand(rhs, ASR, kSmiTagSize)); | 6383 __ mov(r7, Operand(rhs, ASR, kSmiTagSize)); |
6385 __ vmov(s15, r7); | 6384 __ vmov(s15, r7); |
6386 __ vcvt_f64_s32(d7, s15); | 6385 __ vcvt_f64_s32(d7, s15); |
6387 __ mov(r7, Operand(lhs, ASR, kSmiTagSize)); | 6386 __ mov(r7, Operand(lhs, ASR, kSmiTagSize)); |
6388 __ vmov(s13, r7); | 6387 __ vmov(s13, r7); |
6389 __ vcvt_f64_s32(d6, s13); | 6388 __ vcvt_f64_s32(d6, s13); |
6390 } else { | 6389 } else { |
6391 // Write Smi from rhs to r3 and r2 in double format. r6 is scratch. | 6390 // Write Smi from rhs to r3 and r2 in double format. r6 is scratch. |
6392 __ mov(r7, Operand(rhs)); | 6391 __ mov(r7, Operand(rhs)); |
6393 ConvertToDoubleStub stub1(r3, r2, r7, r6); | 6392 ConvertToDoubleStub stub1(r3, r2, r7, r6); |
6394 __ push(lr); | 6393 __ push(lr); |
6395 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); | 6394 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); |
6396 // Write Smi from lhs to r1 and r0 in double format. r6 is scratch. | 6395 // Write Smi from lhs to r1 and r0 in double format. r6 is scratch. |
6397 __ mov(r7, Operand(lhs)); | 6396 __ mov(r7, Operand(lhs)); |
6398 ConvertToDoubleStub stub2(r1, r0, r7, r6); | 6397 ConvertToDoubleStub stub2(r1, r0, r7, r6); |
6399 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); | 6398 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); |
6400 __ pop(lr); | 6399 __ pop(lr); |
6401 } | 6400 } |
6402 __ jmp(&do_the_call); // Tail call. No return. | 6401 __ jmp(&do_the_call); // Tail call. No return. |
6403 } | 6402 } |
6404 | 6403 |
6405 // We branch here if at least one of r0 and r1 is not a Smi. | 6404 // We branch here if at least one of r0 and r1 is not a Smi. |
6406 __ bind(not_smi); | 6405 __ bind(not_smi); |
6407 | 6406 |
| 6407 // After this point we have the left hand side in r1 and the right hand side |
| 6408 // in r0. |
6408 if (lhs.is(r0)) { | 6409 if (lhs.is(r0)) { |
6409 __ Swap(r0, r1, ip); | 6410 __ Swap(r0, r1, ip); |
6410 } | 6411 } |
6411 | 6412 |
6412 if (ShouldGenerateFPCode()) { | 6413 if (ShouldGenerateFPCode()) { |
| 6414 Label r0_is_smi, r1_is_smi, finished_loading_r0, finished_loading_r1; |
| 6415 |
6413 if (runtime_operands_type_ == BinaryOpIC::DEFAULT) { | 6416 if (runtime_operands_type_ == BinaryOpIC::DEFAULT) { |
6414 switch (op_) { | 6417 switch (op_) { |
6415 case Token::ADD: | 6418 case Token::ADD: |
6416 case Token::SUB: | 6419 case Token::SUB: |
6417 case Token::MUL: | 6420 case Token::MUL: |
6418 case Token::DIV: | 6421 case Token::DIV: |
6419 GenerateTypeTransition(masm); | 6422 GenerateTypeTransition(masm); |
6420 break; | 6423 break; |
6421 | 6424 |
6422 default: | 6425 default: |
6423 break; | 6426 break; |
6424 } | 6427 } |
6425 } | 6428 } |
6426 | 6429 |
6427 if (mode_ == NO_OVERWRITE) { | 6430 if (mode_ == NO_OVERWRITE) { |
6428 // In the case where there is no chance of an overwritable float we may as | 6431 // In the case where there is no chance of an overwritable float we may as |
6429 // well do the allocation immediately while r0 and r1 are untouched. | 6432 // well do the allocation immediately while r0 and r1 are untouched. |
6430 __ AllocateHeapNumber(r5, r6, r7, &slow); | 6433 __ AllocateHeapNumber(r5, r6, r7, &slow); |
6431 } | 6434 } |
6432 | 6435 |
6433 // Move r0 to a double in r2-r3. | 6436 // Move r0 to a double in r2-r3. |
6434 __ tst(r0, Operand(kSmiTagMask)); | 6437 __ tst(r0, Operand(kSmiTagMask)); |
6435 __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. | 6438 __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. |
6436 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); | 6439 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); |
6437 __ b(ne, &slow); | 6440 __ b(ne, &slow); |
6438 if (mode_ == OVERWRITE_RIGHT) { | 6441 if (mode_ == OVERWRITE_RIGHT) { |
6439 __ mov(r5, Operand(r0)); // Overwrite this heap number. | 6442 __ mov(r5, Operand(r0)); // Overwrite this heap number. |
6440 } | 6443 } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6571 #else | 6574 #else |
6572 // Double returned in registers 0 and 1. | 6575 // Double returned in registers 0 and 1. |
6573 __ str(r0, FieldMemOperand(r5, HeapNumber::kValueOffset)); | 6576 __ str(r0, FieldMemOperand(r5, HeapNumber::kValueOffset)); |
6574 __ str(r1, FieldMemOperand(r5, HeapNumber::kValueOffset + 4)); | 6577 __ str(r1, FieldMemOperand(r5, HeapNumber::kValueOffset + 4)); |
6575 #endif | 6578 #endif |
6576 __ mov(r0, Operand(r5)); | 6579 __ mov(r0, Operand(r5)); |
6577 // And we are done. | 6580 // And we are done. |
6578 __ pop(pc); | 6581 __ pop(pc); |
6579 } | 6582 } |
6580 } | 6583 } |
| 6584 |
| 6585 |
| 6586 if (lhs.is(r0)) { |
| 6587 __ b(&slow); |
| 6588 __ bind(&slow_reverse); |
| 6589 __ Swap(r0, r1, ip); |
| 6590 } |
| 6591 |
6581 // We jump to here if something goes wrong (one param is not a number of any | 6592 // We jump to here if something goes wrong (one param is not a number of any |
6582 // sort or new-space allocation fails). | 6593 // sort or new-space allocation fails). |
6583 __ bind(&slow); | 6594 __ bind(&slow); |
6584 | 6595 |
6585 // Push arguments to the stack | 6596 // Push arguments to the stack |
6586 __ push(r1); | 6597 __ push(r1); |
6587 __ push(r0); | 6598 __ push(r0); |
6588 | 6599 |
6589 if (Token::ADD == op_) { | 6600 if (Token::ADD == op_) { |
6590 // Test for string arguments before calling runtime. | 6601 // Test for string arguments before calling runtime. |
(...skipping 2748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9339 | 9350 |
9340 // Just jump to runtime to add the two strings. | 9351 // Just jump to runtime to add the two strings. |
9341 __ bind(&string_add_runtime); | 9352 __ bind(&string_add_runtime); |
9342 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 9353 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
9343 } | 9354 } |
9344 | 9355 |
9345 | 9356 |
9346 #undef __ | 9357 #undef __ |
9347 | 9358 |
9348 } } // namespace v8::internal | 9359 } } // namespace v8::internal |
OLD | NEW |