Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Side by Side Diff: runtime/vm/intrinsifier_arm.cc

Issue 18331006: Adds support for integer division for ARM chips without the sdiv instruction. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW
« runtime/vm/assembler_arm.cc ('K') | « runtime/vm/intermediate_language_arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698