OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // | 4 // |
5 // The intrinsic code below is executed before a method has built its frame. | 5 // The intrinsic code below is executed before a method has built its frame. |
6 // The return address is on the stack and the arguments below it. | 6 // The return address is on the stack and the arguments below it. |
7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. | 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. |
8 // Each intrinsification method returns true if the corresponding | 8 // Each intrinsification method returns true if the corresponding |
9 // Dart method was intrinsified. | 9 // Dart method was intrinsified. |
10 | 10 |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 __ Bind(&fall_through); | 660 __ Bind(&fall_through); |
661 return false; | 661 return false; |
662 } | 662 } |
663 | 663 |
664 | 664 |
665 bool Intrinsifier::Integer_mul(Assembler* assembler) { | 665 bool Intrinsifier::Integer_mul(Assembler* assembler) { |
666 return Integer_mulFromInteger(assembler); | 666 return Integer_mulFromInteger(assembler); |
667 } | 667 } |
668 | 668 |
669 | 669 |
670 bool Intrinsifier::Integer_modulo(Assembler* assembler) { | 670 // Optimizations: |
671 Label fall_through, return_zero, try_modulo; | 671 // - result is 0 if: |
672 TestBothArgumentsSmis(assembler, &fall_through); | 672 // - left is 0 |
673 // EAX: right argument (divisor) | 673 // - left equals right |
674 // Check if modulo by zero -> exception thrown in main function. | 674 // - result is left if |
| 675 // - left > 0 && left < right |
| 676 // EAX: Tagged left (dividend). |
| 677 // EBX: Tagged right (divisor). |
| 678 // EDX: Untagged result (remainder). |
| 679 void EmitRemainderOperation(Assembler* assembler) { |
| 680 Label return_zero, modulo; |
| 681 // Check for quick zero results. |
675 __ cmpl(EAX, Immediate(0)); | 682 __ cmpl(EAX, Immediate(0)); |
676 __ j(EQUAL, &fall_through, Assembler::kNearJump); | |
677 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). | |
678 __ cmpl(EBX, Immediate(0)); | |
679 __ j(LESS, &fall_through, Assembler::kNearJump); | |
680 __ cmpl(EBX, EAX); | |
681 __ j(EQUAL, &return_zero, Assembler::kNearJump); | 683 __ j(EQUAL, &return_zero, Assembler::kNearJump); |
682 __ j(GREATER, &try_modulo, Assembler::kNearJump); | 684 __ cmpl(EAX, EBX); |
683 __ movl(EAX, EBX); // Return dividend as it is smaller than divisor. | 685 __ j(EQUAL, &return_zero, Assembler::kNearJump); |
| 686 |
| 687 // Check if result equals left. |
| 688 __ cmpl(EAX, Immediate(0)); |
| 689 __ j(LESS, &modulo, Assembler::kNearJump); |
| 690 // left is positive. |
| 691 __ cmpl(EAX, EBX); |
| 692 __ j(GREATER, &modulo, Assembler::kNearJump); |
| 693 // left is less than right, result is left (EAX). |
684 __ ret(); | 694 __ ret(); |
| 695 |
685 __ Bind(&return_zero); | 696 __ Bind(&return_zero); |
686 __ xorl(EAX, EAX); // Return zero. | 697 __ xorl(EAX, EAX); |
687 __ ret(); | 698 __ ret(); |
688 __ Bind(&try_modulo); | 699 |
689 // EAX: right (non-null divisor). | 700 __ Bind(&modulo); |
690 __ movl(EBX, EAX); | |
691 __ SmiUntag(EBX); | 701 __ SmiUntag(EBX); |
692 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). | |
693 __ SmiUntag(EAX); | 702 __ SmiUntag(EAX); |
694 __ cdq(); | 703 __ cdq(); |
695 __ idivl(EBX); | 704 __ idivl(EBX); |
| 705 } |
| 706 |
| 707 |
| 708 // Implementation: |
| 709 // res = left % right; |
| 710 // if (res < 0) { |
| 711 // if (right < 0) { |
| 712 // res = res - right; |
| 713 // } else { |
| 714 // res = res + right; |
| 715 // } |
| 716 // } |
| 717 bool Intrinsifier::Integer_modulo(Assembler* assembler) { |
| 718 Label fall_through, subtract; |
| 719 TestBothArgumentsSmis(assembler, &fall_through); |
| 720 // EAX: right argument (divisor) |
| 721 __ movl(EBX, EAX); |
| 722 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). |
| 723 // EAX: Tagged left (dividend). |
| 724 // EBX: Tagged right (divisor). |
| 725 // Check if modulo by zero -> exception thrown in main function. |
| 726 __ cmpl(EBX, Immediate(0)); |
| 727 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 728 EmitRemainderOperation(assembler); |
| 729 // Untagged remainder result in EDX. |
| 730 Label done; |
| 731 __ movl(EAX, EDX); |
| 732 __ cmpl(EAX, Immediate(0)); |
| 733 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); |
| 734 // Result is negative, adjust it. |
| 735 __ cmpl(EBX, Immediate(0)); |
| 736 __ j(LESS, &subtract, Assembler::kNearJump); |
| 737 __ addl(EAX, EBX); |
| 738 __ SmiTag(EAX); |
| 739 __ ret(); |
| 740 |
| 741 __ Bind(&subtract); |
| 742 __ subl(EAX, EBX); |
| 743 |
| 744 __ Bind(&done); |
| 745 // The remainder of two Smi-s is always a Smi, no overflow check needed. |
| 746 __ SmiTag(EAX); |
| 747 __ ret(); |
| 748 |
| 749 __ Bind(&fall_through); |
| 750 return false; |
| 751 } |
| 752 |
| 753 |
| 754 bool Intrinsifier::Integer_remainder(Assembler* assembler) { |
| 755 Label fall_through; |
| 756 TestBothArgumentsSmis(assembler, &fall_through); |
| 757 // EAX: right argument (divisor) |
| 758 __ movl(EBX, EAX); |
| 759 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). |
| 760 // EAX: Tagged left (dividend). |
| 761 // EBX: Tagged right (divisor). |
| 762 // Check if modulo by zero -> exception thrown in main function. |
| 763 __ cmpl(EBX, Immediate(0)); |
| 764 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 765 EmitRemainderOperation(assembler); |
| 766 // Untagged remainder result in EDX. |
696 __ movl(EAX, EDX); | 767 __ movl(EAX, EDX); |
697 __ SmiTag(EAX); | 768 __ SmiTag(EAX); |
698 __ ret(); | 769 __ ret(); |
| 770 |
699 __ Bind(&fall_through); | 771 __ Bind(&fall_through); |
700 return false; | 772 return false; |
701 } | 773 } |
702 | 774 |
703 | 775 |
704 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { | 776 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { |
705 Label fall_through; | 777 Label fall_through; |
706 TestBothArgumentsSmis(assembler, &fall_through); | 778 TestBothArgumentsSmis(assembler, &fall_through); |
707 // EAX: right argument (divisor) | 779 // EAX: right argument (divisor) |
708 __ cmpl(EAX, Immediate(0)); | 780 __ cmpl(EAX, Immediate(0)); |
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1606 __ j(LESS, &loop, Assembler::kNearJump); | 1678 __ j(LESS, &loop, Assembler::kNearJump); |
1607 __ ret(); | 1679 __ ret(); |
1608 __ Bind(&fall_through); | 1680 __ Bind(&fall_through); |
1609 return false; | 1681 return false; |
1610 } | 1682 } |
1611 | 1683 |
1612 #undef __ | 1684 #undef __ |
1613 } // namespace dart | 1685 } // namespace dart |
1614 | 1686 |
1615 #endif // defined TARGET_ARCH_IA32 | 1687 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |