| 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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 // - left > 0 && left < right | 664 // - left > 0 && left < right |
| 665 // R1: Tagged left (dividend). | 665 // R1: Tagged left (dividend). |
| 666 // R0: Tagged right (divisor). | 666 // R0: Tagged right (divisor). |
| 667 // Returns with result in R0, OR: | 667 // Returns with result in R0, OR: |
| 668 // R1: Untagged result (remainder). | 668 // R1: Untagged result (remainder). |
| 669 static void EmitRemainderOperation(Assembler* assembler) { | 669 static void EmitRemainderOperation(Assembler* assembler) { |
| 670 Label modulo; | 670 Label modulo; |
| 671 const Register left = R1; | 671 const Register left = R1; |
| 672 const Register right = R0; | 672 const Register right = R0; |
| 673 const Register result = R1; | 673 const Register result = R1; |
| 674 const Register tmp = R2; |
| 674 ASSERT(left == result); | 675 ASSERT(left == result); |
| 675 | 676 |
| 676 // Check for quick zero results. | 677 // Check for quick zero results. |
| 677 __ cmp(left, ShifterOperand(0)); | 678 __ cmp(left, ShifterOperand(0)); |
| 678 __ mov(R0, ShifterOperand(0), EQ); | 679 __ mov(R0, ShifterOperand(0), EQ); |
| 679 __ bx(LR, EQ); // left is 0? Return 0. | 680 __ bx(LR, EQ); // left is 0? Return 0. |
| 680 __ cmp(left, ShifterOperand(right)); | 681 __ cmp(left, ShifterOperand(right)); |
| 681 __ mov(R0, ShifterOperand(0), EQ); | 682 __ mov(R0, ShifterOperand(0), EQ); |
| 682 __ bx(LR, EQ); // left == right? Return 0. | 683 __ bx(LR, EQ); // left == right? Return 0. |
| 683 | 684 |
| 684 // Check if result should be left. | 685 // Check if result should be left. |
| 685 __ cmp(left, ShifterOperand(0)); | 686 __ cmp(left, ShifterOperand(0)); |
| 686 __ b(&modulo, LT); | 687 __ b(&modulo, LT); |
| 687 // left is positive. | 688 // left is positive. |
| 688 __ cmp(left, ShifterOperand(right)); | 689 __ cmp(left, ShifterOperand(right)); |
| 689 // left is less than right, result is left. | 690 // left is less than right, result is left. |
| 690 __ mov(R0, ShifterOperand(left), LT); | 691 __ mov(R0, ShifterOperand(left), LT); |
| 691 __ bx(LR, LT); | 692 __ bx(LR, LT); |
| 692 | 693 |
| 693 __ Bind(&modulo); | 694 __ Bind(&modulo); |
| 694 // result <- left - right * (left / right) | 695 // result <- left - right * (left / right) |
| 695 __ SmiUntag(left); | 696 __ SmiUntag(left); |
| 696 __ SmiUntag(right); | 697 __ SmiUntag(right); |
| 697 __ sdiv(TMP, left, right); // TMP <- left / right | 698 |
| 698 __ mls(result, right, TMP, left); // result <- left - right * TMP | 699 __ IntegerDivide(tmp, left, right, D1, D0); |
| 700 |
| 701 __ mls(result, right, tmp, left); // result <- left - right * TMP |
| 699 return; | 702 return; |
| 700 } | 703 } |
| 701 | 704 |
| 702 | 705 |
| 703 // Implementation: | 706 // Implementation: |
| 704 // res = left % right; | 707 // res = left % right; |
| 705 // if (res < 0) { | 708 // if (res < 0) { |
| 706 // if (right < 0) { | 709 // if (right < 0) { |
| 707 // res = res - right; | 710 // res = res - right; |
| 708 // } else { | 711 // } else { |
| 709 // res = res + right; | 712 // res = res + right; |
| 710 // } | 713 // } |
| 711 // } | 714 // } |
| 712 bool Intrinsifier::Integer_modulo(Assembler* assembler) { | 715 bool Intrinsifier::Integer_modulo(Assembler* assembler) { |
| 713 // Check to see if we have integer division | 716 // Check to see if we have integer division |
| 714 if (!CPUFeatures::integer_division_supported()) | |
| 715 return false; | |
| 716 | |
| 717 Label fall_through, subtract; | 717 Label fall_through, subtract; |
| 718 TestBothArgumentsSmis(assembler, &fall_through); | 718 TestBothArgumentsSmis(assembler, &fall_through); |
| 719 // R1: Tagged left (dividend). | 719 // R1: Tagged left (dividend). |
| 720 // R0: Tagged right (divisor). | 720 // R0: Tagged right (divisor). |
| 721 // Check if modulo by zero -> exception thrown in main function. | 721 // Check if modulo by zero -> exception thrown in main function. |
| 722 __ cmp(R0, ShifterOperand(0)); | 722 __ cmp(R0, ShifterOperand(0)); |
| 723 __ b(&fall_through, EQ); | 723 __ b(&fall_through, EQ); |
| 724 EmitRemainderOperation(assembler); | 724 EmitRemainderOperation(assembler); |
| 725 // Untagged right in R0. Untagged remainder result in R1. | 725 // Untagged right in R0. Untagged remainder result in R1. |
| 726 | 726 |
| 727 __ cmp(R1, ShifterOperand(0)); | 727 __ cmp(R1, ShifterOperand(0)); |
| 728 __ mov(R0, ShifterOperand(R1, LSL, 1), GE); // Tag and move result to R0. | 728 __ mov(R0, ShifterOperand(R1, LSL, 1), GE); // Tag and move result to R0. |
| 729 __ bx(LR, GE); | 729 __ bx(LR, GE); |
| 730 | 730 |
| 731 // Result is negative, adjust it. | 731 // Result is negative, adjust it. |
| 732 __ cmp(R0, ShifterOperand(0)); | 732 __ cmp(R0, ShifterOperand(0)); |
| 733 __ sub(R0, R1, ShifterOperand(R0), LT); | 733 __ sub(R0, R1, ShifterOperand(R0), LT); |
| 734 __ add(R0, R1, ShifterOperand(R0), GE); | 734 __ add(R0, R1, ShifterOperand(R0), GE); |
| 735 __ SmiTag(R0); | 735 __ SmiTag(R0); |
| 736 __ Ret(); | 736 __ Ret(); |
| 737 | 737 |
| 738 __ Bind(&fall_through); | 738 __ Bind(&fall_through); |
| 739 return false; | 739 return false; |
| 740 } | 740 } |
| 741 | 741 |
| 742 | 742 |
| 743 bool Intrinsifier::Integer_remainder(Assembler* assembler) { | 743 bool Intrinsifier::Integer_remainder(Assembler* assembler) { |
| 744 // Check to see if we have integer division | 744 // Check to see if we have integer division |
| 745 if (!CPUFeatures::integer_division_supported()) | |
| 746 return false; | |
| 747 | |
| 748 Label fall_through; | 745 Label fall_through; |
| 749 TestBothArgumentsSmis(assembler, &fall_through); | 746 TestBothArgumentsSmis(assembler, &fall_through); |
| 750 // R1: Tagged left (dividend). | 747 // R1: Tagged left (dividend). |
| 751 // R0: Tagged right (divisor). | 748 // R0: Tagged right (divisor). |
| 752 // Check if modulo by zero -> exception thrown in main function. | 749 // Check if modulo by zero -> exception thrown in main function. |
| 753 __ cmp(R0, ShifterOperand(0)); | 750 __ cmp(R0, ShifterOperand(0)); |
| 754 __ b(&fall_through, EQ); | 751 __ b(&fall_through, EQ); |
| 755 EmitRemainderOperation(assembler); | 752 EmitRemainderOperation(assembler); |
| 756 // Untagged remainder result in R1. | 753 // Untagged remainder result in R1. |
| 757 __ mov(R0, ShifterOperand(R1, LSL, 1)); // Tag result and return. | 754 __ mov(R0, ShifterOperand(R1, LSL, 1)); // Tag result and return. |
| 758 __ Ret(); | 755 __ Ret(); |
| 759 | 756 |
| 760 __ Bind(&fall_through); | 757 __ Bind(&fall_through); |
| 761 return false; | 758 return false; |
| 762 } | 759 } |
| 763 | 760 |
| 764 | 761 |
| 765 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { | 762 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { |
| 766 // Check to see if we have integer division | 763 // Check to see if we have integer division |
| 767 if (!CPUFeatures::integer_division_supported()) | |
| 768 return false; | |
| 769 | |
| 770 Label fall_through; | 764 Label fall_through; |
| 771 | 765 |
| 772 TestBothArgumentsSmis(assembler, &fall_through); | 766 TestBothArgumentsSmis(assembler, &fall_through); |
| 773 __ cmp(R0, ShifterOperand(0)); | 767 __ cmp(R0, ShifterOperand(0)); |
| 774 __ b(&fall_through, EQ); // If b is 0, fall through. | 768 __ b(&fall_through, EQ); // If b is 0, fall through. |
| 775 | 769 |
| 776 __ SmiUntag(R0); | 770 __ SmiUntag(R0); |
| 777 __ SmiUntag(R1); | 771 __ SmiUntag(R1); |
| 778 __ sdiv(R0, R1, R0); | 772 |
| 773 __ IntegerDivide(R0, R1, R0, D1, D0); |
| 774 |
| 779 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we | 775 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we |
| 780 // cannot tag the result. | 776 // cannot tag the result. |
| 781 __ CompareImmediate(R0, 0x40000000); | 777 __ CompareImmediate(R0, 0x40000000); |
| 782 __ SmiTag(R0, NE); // Not equal. Okay to tag and return. | 778 __ SmiTag(R0, NE); // Not equal. Okay to tag and return. |
| 783 __ bx(LR, NE); // Return. | 779 __ bx(LR, NE); // Return. |
| 784 __ Bind(&fall_through); | 780 __ Bind(&fall_through); |
| 785 return false; | 781 return false; |
| 786 } | 782 } |
| 787 | 783 |
| 788 | 784 |
| (...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1697 __ Bind(&ok); | 1693 __ Bind(&ok); |
| 1698 __ Ret(); | 1694 __ Ret(); |
| 1699 | 1695 |
| 1700 __ Bind(&fall_through); | 1696 __ Bind(&fall_through); |
| 1701 return false; | 1697 return false; |
| 1702 } | 1698 } |
| 1703 | 1699 |
| 1704 } // namespace dart | 1700 } // namespace dart |
| 1705 | 1701 |
| 1706 #endif // defined TARGET_ARCH_ARM | 1702 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |