| 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 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 | 524 |
| 525 // Arguments are Smi but the shift produced an overflow to Mint. | 525 // Arguments are Smi but the shift produced an overflow to Mint. |
| 526 __ CompareImmediate(R1, 0); | 526 __ CompareImmediate(R1, 0); |
| 527 __ b(&fall_through, LT); | 527 __ b(&fall_through, LT); |
| 528 __ SmiUntag(R1); | 528 __ SmiUntag(R1); |
| 529 | 529 |
| 530 // Pull off high bits that will be shifted off of R1 by making a mask | 530 // Pull off high bits that will be shifted off of R1 by making a mask |
| 531 // ((1 << R0) - 1), shifting it to the left, masking R1, then shifting back. | 531 // ((1 << R0) - 1), shifting it to the left, masking R1, then shifting back. |
| 532 // high bits = (((1 << R0) - 1) << (32 - R0)) & R1) >> (32 - R0) | 532 // high bits = (((1 << R0) - 1) << (32 - R0)) & R1) >> (32 - R0) |
| 533 // lo bits = R1 << R0 | 533 // lo bits = R1 << R0 |
| 534 __ LoadImmediate(R7, 1); | 534 __ LoadImmediate(R711, 1); |
| 535 __ mov(R7, Operand(R7, LSL, R0)); // R7 <- 1 << R0 | 535 __ mov(R711, Operand(R711, LSL, R0)); // R711 <- 1 << R0 |
| 536 __ sub(R7, R7, Operand(1)); // R7 <- R7 - 1 | 536 __ sub(R711, R711, Operand(1)); // R711 <- R711 - 1 |
| 537 __ rsb(R6, R0, Operand(32)); // R6 <- 32 - R0 | 537 __ rsb(R6, R0, Operand(32)); // R6 <- 32 - R0 |
| 538 __ mov(R7, Operand(R7, LSL, R6)); // R7 <- R7 << R6 | 538 __ mov(R711, Operand(R711, LSL, R6)); // R711 <- R711 << R6 |
| 539 __ and_(R7, R1, Operand(R7)); // R7 <- R7 & R1 | 539 __ and_(R711, R1, Operand(R711)); // R711 <- R711 & R1 |
| 540 __ mov(R7, Operand(R7, LSR, R6)); // R7 <- R7 >> R6 | 540 __ mov(R711, Operand(R711, LSR, R6)); // R711 <- R711 >> R6 |
| 541 // Now R7 has the bits that fall off of R1 on a left shift. | 541 // Now R711 has the bits that fall off of R1 on a left shift. |
| 542 __ mov(R1, Operand(R1, LSL, R0)); // R1 gets the low bits. | 542 __ mov(R1, Operand(R1, LSL, R0)); // R1 gets the low bits. |
| 543 | 543 |
| 544 const Class& mint_class = Class::Handle( | 544 const Class& mint_class = Class::Handle( |
| 545 Isolate::Current()->object_store()->mint_class()); | 545 Isolate::Current()->object_store()->mint_class()); |
| 546 __ TryAllocate(mint_class, &fall_through, R0, R2); | 546 __ TryAllocate(mint_class, &fall_through, R0, R2); |
| 547 | 547 |
| 548 | 548 |
| 549 __ str(R1, FieldAddress(R0, Mint::value_offset())); | 549 __ str(R1, FieldAddress(R0, Mint::value_offset())); |
| 550 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); | 550 __ str(R711, FieldAddress(R0, Mint::value_offset() + kWordSize)); |
| 551 __ Pop(R6); | 551 __ Pop(R6); |
| 552 __ Ret(); | 552 __ Ret(); |
| 553 __ Bind(&fall_through); | 553 __ Bind(&fall_through); |
| 554 ASSERT(CODE_REG == R6); | 554 ASSERT(CODE_REG == R6); |
| 555 __ Pop(R6); | 555 __ Pop(R6); |
| 556 } | 556 } |
| 557 | 557 |
| 558 | 558 |
| 559 static void Get64SmiOrMint(Assembler* assembler, | 559 static void Get64SmiOrMint(Assembler* assembler, |
| 560 Register res_hi, | 560 Register res_hi, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 break; | 614 break; |
| 615 default: | 615 default: |
| 616 UNREACHABLE(); | 616 UNREACHABLE(); |
| 617 hi_true_cond = hi_false_cond = lo_false_cond = VS; | 617 hi_true_cond = hi_false_cond = lo_false_cond = VS; |
| 618 } | 618 } |
| 619 | 619 |
| 620 __ Bind(&try_mint_smi); | 620 __ Bind(&try_mint_smi); |
| 621 // Get left as 64 bit integer. | 621 // Get left as 64 bit integer. |
| 622 Get64SmiOrMint(assembler, R3, R2, R1, &fall_through); | 622 Get64SmiOrMint(assembler, R3, R2, R1, &fall_through); |
| 623 // Get right as 64 bit integer. | 623 // Get right as 64 bit integer. |
| 624 Get64SmiOrMint(assembler, R7, R8, R0, &fall_through); | 624 Get64SmiOrMint(assembler, R711, R8, R0, &fall_through); |
| 625 // R3: left high. | 625 // R3: left high. |
| 626 // R2: left low. | 626 // R2: left low. |
| 627 // R7: right high. | 627 // R711: right high. |
| 628 // R8: right low. | 628 // R8: right low. |
| 629 | 629 |
| 630 __ cmp(R3, Operand(R7)); // Compare left hi, right high. | 630 __ cmp(R3, Operand(R711)); // Compare left hi, right high. |
| 631 __ b(&is_false, hi_false_cond); | 631 __ b(&is_false, hi_false_cond); |
| 632 __ b(&is_true, hi_true_cond); | 632 __ b(&is_true, hi_true_cond); |
| 633 __ cmp(R2, Operand(R8)); // Compare left lo, right lo. | 633 __ cmp(R2, Operand(R8)); // Compare left lo, right lo. |
| 634 __ b(&is_false, lo_false_cond); | 634 __ b(&is_false, lo_false_cond); |
| 635 // Else is true. | 635 // Else is true. |
| 636 __ b(&is_true); | 636 __ b(&is_true); |
| 637 | 637 |
| 638 __ Bind(&fall_through); | 638 __ Bind(&fall_through); |
| 639 } | 639 } |
| 640 | 640 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 | 769 |
| 770 // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi. | 770 // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi. |
| 771 __ ldrd(R0, R1, SP, 2 * kWordSize); | 771 __ ldrd(R0, R1, SP, 2 * kWordSize); |
| 772 // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0. | 772 // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0. |
| 773 __ ldrd(R2, R3, SP, 0 * kWordSize); | 773 __ ldrd(R2, R3, SP, 0 * kWordSize); |
| 774 __ SmiUntag(R3); | 774 __ SmiUntag(R3); |
| 775 // R4 = n ~/ _DIGIT_BITS | 775 // R4 = n ~/ _DIGIT_BITS |
| 776 __ Asr(R4, R3, Operand(5)); | 776 __ Asr(R4, R3, Operand(5)); |
| 777 // R8 = &x_digits[0] | 777 // R8 = &x_digits[0] |
| 778 __ add(R8, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 778 __ add(R8, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 779 // R7 = &x_digits[x_used] | 779 // R711 = &x_digits[x_used] |
| 780 __ add(R7, R8, Operand(R0, LSL, 1)); | 780 __ add(R711, R8, Operand(R0, LSL, 1)); |
| 781 // R6 = &r_digits[1] | 781 // R6 = &r_digits[1] |
| 782 __ add(R6, R2, Operand(TypedData::data_offset() - kHeapObjectTag + | 782 __ add(R6, R2, Operand(TypedData::data_offset() - kHeapObjectTag + |
| 783 Bigint::kBytesPerDigit)); | 783 Bigint::kBytesPerDigit)); |
| 784 // R6 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1] | 784 // R6 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1] |
| 785 __ add(R4, R4, Operand(R0, ASR, 1)); | 785 __ add(R4, R4, Operand(R0, ASR, 1)); |
| 786 __ add(R6, R6, Operand(R4, LSL, 2)); | 786 __ add(R6, R6, Operand(R4, LSL, 2)); |
| 787 // R1 = n % _DIGIT_BITS | 787 // R1 = n % _DIGIT_BITS |
| 788 __ and_(R1, R3, Operand(31)); | 788 __ and_(R1, R3, Operand(31)); |
| 789 // R0 = 32 - R1 | 789 // R0 = 32 - R1 |
| 790 __ rsb(R0, R1, Operand(32)); | 790 __ rsb(R0, R1, Operand(32)); |
| 791 __ mov(R9, Operand(0)); | 791 __ mov(R9, Operand(0)); |
| 792 Label loop; | 792 Label loop; |
| 793 __ Bind(&loop); | 793 __ Bind(&loop); |
| 794 __ ldr(R4, Address(R7, -Bigint::kBytesPerDigit, Address::PreIndex)); | 794 __ ldr(R4, Address(R711, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 795 __ orr(R9, R9, Operand(R4, LSR, R0)); | 795 __ orr(R9, R9, Operand(R4, LSR, R0)); |
| 796 __ str(R9, Address(R6, -Bigint::kBytesPerDigit, Address::PreIndex)); | 796 __ str(R9, Address(R6, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 797 __ mov(R9, Operand(R4, LSL, R1)); | 797 __ mov(R9, Operand(R4, LSL, R1)); |
| 798 __ teq(R7, Operand(R8)); | 798 __ teq(R711, Operand(R8)); |
| 799 __ b(&loop, NE); | 799 __ b(&loop, NE); |
| 800 __ str(R9, Address(R6, -Bigint::kBytesPerDigit, Address::PreIndex)); | 800 __ str(R9, Address(R6, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 801 // Returning Object::null() is not required, since this method is private. | 801 // Returning Object::null() is not required, since this method is private. |
| 802 __ Ret(); | 802 __ Ret(); |
| 803 } | 803 } |
| 804 | 804 |
| 805 | 805 |
| 806 void Intrinsifier::Bigint_rsh(Assembler* assembler) { | 806 void Intrinsifier::Bigint_rsh(Assembler* assembler) { |
| 807 // static void _lsh(Uint32List x_digits, int x_used, int n, | 807 // static void _lsh(Uint32List x_digits, int x_used, int n, |
| 808 // Uint32List r_digits) | 808 // Uint32List r_digits) |
| 809 | 809 |
| 810 // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi. | 810 // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi. |
| 811 __ ldrd(R0, R1, SP, 2 * kWordSize); | 811 __ ldrd(R0, R1, SP, 2 * kWordSize); |
| 812 // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0. | 812 // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0. |
| 813 __ ldrd(R2, R3, SP, 0 * kWordSize); | 813 __ ldrd(R2, R3, SP, 0 * kWordSize); |
| 814 __ SmiUntag(R3); | 814 __ SmiUntag(R3); |
| 815 // R4 = n ~/ _DIGIT_BITS | 815 // R4 = n ~/ _DIGIT_BITS |
| 816 __ Asr(R4, R3, Operand(5)); | 816 __ Asr(R4, R3, Operand(5)); |
| 817 // R6 = &r_digits[0] | 817 // R6 = &r_digits[0] |
| 818 __ add(R6, R2, Operand(TypedData::data_offset() - kHeapObjectTag)); | 818 __ add(R6, R2, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 819 // R7 = &x_digits[n ~/ _DIGIT_BITS] | 819 // R711 = &x_digits[n ~/ _DIGIT_BITS] |
| 820 __ add(R7, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 820 __ add(R711, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 821 __ add(R7, R7, Operand(R4, LSL, 2)); | 821 __ add(R711, R711, Operand(R4, LSL, 2)); |
| 822 // R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1] | 822 // R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1] |
| 823 __ add(R4, R4, Operand(1)); | 823 __ add(R4, R4, Operand(1)); |
| 824 __ rsb(R4, R4, Operand(R0, ASR, 1)); | 824 __ rsb(R4, R4, Operand(R0, ASR, 1)); |
| 825 __ add(R8, R6, Operand(R4, LSL, 2)); | 825 __ add(R8, R6, Operand(R4, LSL, 2)); |
| 826 // R1 = n % _DIGIT_BITS | 826 // R1 = n % _DIGIT_BITS |
| 827 __ and_(R1, R3, Operand(31)); | 827 __ and_(R1, R3, Operand(31)); |
| 828 // R0 = 32 - R1 | 828 // R0 = 32 - R1 |
| 829 __ rsb(R0, R1, Operand(32)); | 829 __ rsb(R0, R1, Operand(32)); |
| 830 // R9 = x_digits[n ~/ _DIGIT_BITS] >> (n % _DIGIT_BITS) | 830 // R9 = x_digits[n ~/ _DIGIT_BITS] >> (n % _DIGIT_BITS) |
| 831 __ ldr(R9, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 831 __ ldr(R9, Address(R711, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 832 __ mov(R9, Operand(R9, LSR, R1)); | 832 __ mov(R9, Operand(R9, LSR, R1)); |
| 833 Label loop_entry; | 833 Label loop_entry; |
| 834 __ b(&loop_entry); | 834 __ b(&loop_entry); |
| 835 Label loop; | 835 Label loop; |
| 836 __ Bind(&loop); | 836 __ Bind(&loop); |
| 837 __ ldr(R4, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 837 __ ldr(R4, Address(R711, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 838 __ orr(R9, R9, Operand(R4, LSL, R0)); | 838 __ orr(R9, R9, Operand(R4, LSL, R0)); |
| 839 __ str(R9, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 839 __ str(R9, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 840 __ mov(R9, Operand(R4, LSR, R1)); | 840 __ mov(R9, Operand(R4, LSR, R1)); |
| 841 __ Bind(&loop_entry); | 841 __ Bind(&loop_entry); |
| 842 __ teq(R6, Operand(R8)); | 842 __ teq(R6, Operand(R8)); |
| 843 __ b(&loop, NE); | 843 __ b(&loop, NE); |
| 844 __ str(R9, Address(R6, 0)); | 844 __ str(R9, Address(R6, 0)); |
| 845 // Returning Object::null() is not required, since this method is private. | 845 // Returning Object::null() is not required, since this method is private. |
| 846 __ Ret(); | 846 __ Ret(); |
| 847 } | 847 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 860 // R2 = a_used, R3 = a_digits | 860 // R2 = a_used, R3 = a_digits |
| 861 __ ldrd(R2, R3, SP, 1 * kWordSize); | 861 __ ldrd(R2, R3, SP, 1 * kWordSize); |
| 862 // R3 = &a_digits[0] | 862 // R3 = &a_digits[0] |
| 863 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 863 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 864 | 864 |
| 865 // R8 = r_digits | 865 // R8 = r_digits |
| 866 __ ldr(R8, Address(SP, 0 * kWordSize)); | 866 __ ldr(R8, Address(SP, 0 * kWordSize)); |
| 867 // R8 = &r_digits[0] | 867 // R8 = &r_digits[0] |
| 868 __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag)); | 868 __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 869 | 869 |
| 870 // R7 = &digits[a_used >> 1], a_used is Smi. | 870 // R711 = &digits[a_used >> 1], a_used is Smi. |
| 871 __ add(R7, R1, Operand(R2, LSL, 1)); | 871 __ add(R711, R1, Operand(R2, LSL, 1)); |
| 872 | 872 |
| 873 // R6 = &digits[used >> 1], used is Smi. | 873 // R6 = &digits[used >> 1], used is Smi. |
| 874 __ add(R6, R1, Operand(R0, LSL, 1)); | 874 __ add(R6, R1, Operand(R0, LSL, 1)); |
| 875 | 875 |
| 876 __ adds(R4, R4, Operand(0)); // carry flag = 0 | 876 __ adds(R4, R4, Operand(0)); // carry flag = 0 |
| 877 Label add_loop; | 877 Label add_loop; |
| 878 __ Bind(&add_loop); | 878 __ Bind(&add_loop); |
| 879 // Loop a_used times, a_used > 0. | 879 // Loop a_used times, a_used > 0. |
| 880 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); | 880 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 881 __ ldr(R9, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 881 __ ldr(R9, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 882 __ adcs(R4, R4, Operand(R9)); | 882 __ adcs(R4, R4, Operand(R9)); |
| 883 __ teq(R1, Operand(R7)); // Does not affect carry flag. | 883 __ teq(R1, Operand(R711)); // Does not affect carry flag. |
| 884 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); | 884 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 885 __ b(&add_loop, NE); | 885 __ b(&add_loop, NE); |
| 886 | 886 |
| 887 Label last_carry; | 887 Label last_carry; |
| 888 __ teq(R1, Operand(R6)); // Does not affect carry flag. | 888 __ teq(R1, Operand(R6)); // Does not affect carry flag. |
| 889 __ b(&last_carry, EQ); // If used - a_used == 0. | 889 __ b(&last_carry, EQ); // If used - a_used == 0. |
| 890 | 890 |
| 891 Label carry_loop; | 891 Label carry_loop; |
| 892 __ Bind(&carry_loop); | 892 __ Bind(&carry_loop); |
| 893 // Loop used - a_used times, used - a_used > 0. | 893 // Loop used - a_used times, used - a_used > 0. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 920 // R2 = a_used, R3 = a_digits | 920 // R2 = a_used, R3 = a_digits |
| 921 __ ldrd(R2, R3, SP, 1 * kWordSize); | 921 __ ldrd(R2, R3, SP, 1 * kWordSize); |
| 922 // R3 = &a_digits[0] | 922 // R3 = &a_digits[0] |
| 923 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 923 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 924 | 924 |
| 925 // R8 = r_digits | 925 // R8 = r_digits |
| 926 __ ldr(R8, Address(SP, 0 * kWordSize)); | 926 __ ldr(R8, Address(SP, 0 * kWordSize)); |
| 927 // R8 = &r_digits[0] | 927 // R8 = &r_digits[0] |
| 928 __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag)); | 928 __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 929 | 929 |
| 930 // R7 = &digits[a_used >> 1], a_used is Smi. | 930 // R711 = &digits[a_used >> 1], a_used is Smi. |
| 931 __ add(R7, R1, Operand(R2, LSL, 1)); | 931 __ add(R711, R1, Operand(R2, LSL, 1)); |
| 932 | 932 |
| 933 // R6 = &digits[used >> 1], used is Smi. | 933 // R6 = &digits[used >> 1], used is Smi. |
| 934 __ add(R6, R1, Operand(R0, LSL, 1)); | 934 __ add(R6, R1, Operand(R0, LSL, 1)); |
| 935 | 935 |
| 936 __ subs(R4, R4, Operand(0)); // carry flag = 1 | 936 __ subs(R4, R4, Operand(0)); // carry flag = 1 |
| 937 Label sub_loop; | 937 Label sub_loop; |
| 938 __ Bind(&sub_loop); | 938 __ Bind(&sub_loop); |
| 939 // Loop a_used times, a_used > 0. | 939 // Loop a_used times, a_used > 0. |
| 940 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); | 940 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 941 __ ldr(R9, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 941 __ ldr(R9, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 942 __ sbcs(R4, R4, Operand(R9)); | 942 __ sbcs(R4, R4, Operand(R9)); |
| 943 __ teq(R1, Operand(R7)); // Does not affect carry flag. | 943 __ teq(R1, Operand(R711)); // Does not affect carry flag. |
| 944 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); | 944 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 945 __ b(&sub_loop, NE); | 945 __ b(&sub_loop, NE); |
| 946 | 946 |
| 947 Label done; | 947 Label done; |
| 948 __ teq(R1, Operand(R6)); // Does not affect carry flag. | 948 __ teq(R1, Operand(R6)); // Does not affect carry flag. |
| 949 __ b(&done, EQ); // If used - a_used == 0. | 949 __ b(&done, EQ); // If used - a_used == 0. |
| 950 | 950 |
| 951 Label carry_loop; | 951 Label carry_loop; |
| 952 __ Bind(&carry_loop); | 952 __ Bind(&carry_loop); |
| 953 // Loop used - a_used times, used - a_used > 0. | 953 // Loop used - a_used times, used - a_used > 0. |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 __ ldrd(R2, R3, SP, 2 * kWordSize); // R2 = i as Smi, R3 = x_digits | 1096 __ ldrd(R2, R3, SP, 2 * kWordSize); // R2 = i as Smi, R3 = x_digits |
| 1097 __ add(R3, R3, Operand(R2, LSL, 1)); | 1097 __ add(R3, R3, Operand(R2, LSL, 1)); |
| 1098 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1098 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 1099 | 1099 |
| 1100 // R3 = x = *xip++, return if x == 0 | 1100 // R3 = x = *xip++, return if x == 0 |
| 1101 Label x_zero; | 1101 Label x_zero; |
| 1102 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1102 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1103 __ tst(R3, Operand(R3)); | 1103 __ tst(R3, Operand(R3)); |
| 1104 __ b(&x_zero, EQ); | 1104 __ b(&x_zero, EQ); |
| 1105 | 1105 |
| 1106 // R7 = ajp = &a_digits[i] | 1106 // R711 = ajp = &a_digits[i] |
| 1107 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits | 1107 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits |
| 1108 __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi. | 1108 __ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi. |
| 1109 __ add(R7, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1109 __ add(R711, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 1110 | 1110 |
| 1111 // R8:R0 = t = x*x + *ajp | 1111 // R8:R0 = t = x*x + *ajp |
| 1112 __ ldr(R0, Address(R7, 0)); | 1112 __ ldr(R0, Address(R711, 0)); |
| 1113 __ mov(R8, Operand(0)); | 1113 __ mov(R8, Operand(0)); |
| 1114 __ umaal(R0, R8, R3, R3); // R8:R0 = R3*R3 + R8 + R0. | 1114 __ umaal(R0, R8, R3, R3); // R8:R0 = R3*R3 + R8 + R0. |
| 1115 | 1115 |
| 1116 // *ajp++ = low32(t) = R0 | 1116 // *ajp++ = low32(t) = R0 |
| 1117 __ str(R0, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 1117 __ str(R0, Address(R711, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1118 | 1118 |
| 1119 // R8 = low32(c) = high32(t) | 1119 // R8 = low32(c) = high32(t) |
| 1120 // R9 = high32(c) = 0 | 1120 // R9 = high32(c) = 0 |
| 1121 __ mov(R9, Operand(0)); | 1121 __ mov(R9, Operand(0)); |
| 1122 | 1122 |
| 1123 // int n = used - i - 1; while (--n >= 0) ... | 1123 // int n = used - i - 1; while (--n >= 0) ... |
| 1124 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi | 1124 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi |
| 1125 __ sub(R6, R0, Operand(R2)); | 1125 __ sub(R6, R0, Operand(R2)); |
| 1126 __ mov(R0, Operand(2)); // n = used - i - 2; if (n >= 0) ... while (--n >= 0) | 1126 __ mov(R0, Operand(2)); // n = used - i - 2; if (n >= 0) ... while (--n >= 0) |
| 1127 __ rsbs(R6, R0, Operand(R6, ASR, kSmiTagSize)); | 1127 __ rsbs(R6, R0, Operand(R6, ASR, kSmiTagSize)); |
| 1128 | 1128 |
| 1129 Label loop, done; | 1129 Label loop, done; |
| 1130 __ b(&done, MI); | 1130 __ b(&done, MI); |
| 1131 | 1131 |
| 1132 __ Bind(&loop); | 1132 __ Bind(&loop); |
| 1133 // x: R3 | 1133 // x: R3 |
| 1134 // xip: R4 | 1134 // xip: R4 |
| 1135 // ajp: R7 | 1135 // ajp: R711 |
| 1136 // c: R9:R8 | 1136 // c: R9:R8 |
| 1137 // t: R2:R1:R0 (not live at loop entry) | 1137 // t: R2:R1:R0 (not live at loop entry) |
| 1138 // n: R6 | 1138 // n: R6 |
| 1139 | 1139 |
| 1140 // uint32_t xi = *xip++ | 1140 // uint32_t xi = *xip++ |
| 1141 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1141 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1142 | 1142 |
| 1143 // uint96_t t = R9:R8:R0 = 2*x*xi + aj + c | 1143 // uint96_t t = R9:R8:R0 = 2*x*xi + aj + c |
| 1144 __ umull(R0, R1, R2, R3); // R1:R0 = R2*R3. | 1144 __ umull(R0, R1, R2, R3); // R1:R0 = R2*R3. |
| 1145 __ adds(R0, R0, Operand(R0)); | 1145 __ adds(R0, R0, Operand(R0)); |
| 1146 __ adcs(R1, R1, Operand(R1)); | 1146 __ adcs(R1, R1, Operand(R1)); |
| 1147 __ mov(R2, Operand(0)); | 1147 __ mov(R2, Operand(0)); |
| 1148 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi. | 1148 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi. |
| 1149 __ adds(R0, R0, Operand(R8)); | 1149 __ adds(R0, R0, Operand(R8)); |
| 1150 __ adcs(R1, R1, Operand(R9)); | 1150 __ adcs(R1, R1, Operand(R9)); |
| 1151 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi + c. | 1151 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi + c. |
| 1152 __ ldr(R8, Address(R7, 0)); // R8 = aj = *ajp. | 1152 __ ldr(R8, Address(R711, 0)); // R8 = aj = *ajp. |
| 1153 __ adds(R0, R0, Operand(R8)); | 1153 __ adds(R0, R0, Operand(R8)); |
| 1154 __ adcs(R8, R1, Operand(0)); | 1154 __ adcs(R8, R1, Operand(0)); |
| 1155 __ adc(R9, R2, Operand(0)); // R9:R8:R0 = 2*x*xi + c + aj. | 1155 __ adc(R9, R2, Operand(0)); // R9:R8:R0 = 2*x*xi + c + aj. |
| 1156 | 1156 |
| 1157 // *ajp++ = low32(t) = R0 | 1157 // *ajp++ = low32(t) = R0 |
| 1158 __ str(R0, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 1158 __ str(R0, Address(R711, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1159 | 1159 |
| 1160 // while (--n >= 0) | 1160 // while (--n >= 0) |
| 1161 __ subs(R6, R6, Operand(1)); // --n | 1161 __ subs(R6, R6, Operand(1)); // --n |
| 1162 __ b(&loop, PL); | 1162 __ b(&loop, PL); |
| 1163 | 1163 |
| 1164 __ Bind(&done); | 1164 __ Bind(&done); |
| 1165 // uint32_t aj = *ajp | 1165 // uint32_t aj = *ajp |
| 1166 __ ldr(R0, Address(R7, 0)); | 1166 __ ldr(R0, Address(R711, 0)); |
| 1167 | 1167 |
| 1168 // uint64_t t = aj + c | 1168 // uint64_t t = aj + c |
| 1169 __ adds(R8, R8, Operand(R0)); | 1169 __ adds(R8, R8, Operand(R0)); |
| 1170 __ adc(R9, R9, Operand(0)); | 1170 __ adc(R9, R9, Operand(0)); |
| 1171 | 1171 |
| 1172 // *ajp = low32(t) = R8 | 1172 // *ajp = low32(t) = R8 |
| 1173 // *(ajp + 1) = high32(t) = R9 | 1173 // *(ajp + 1) = high32(t) = R9 |
| 1174 __ strd(R8, R9, R7, 0); | 1174 __ strd(R8, R9, R711, 0); |
| 1175 | 1175 |
| 1176 __ Bind(&x_zero); | 1176 __ Bind(&x_zero); |
| 1177 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. | 1177 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
| 1178 __ Ret(); | 1178 __ Ret(); |
| 1179 } | 1179 } |
| 1180 | 1180 |
| 1181 | 1181 |
| 1182 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1182 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
| 1183 // No unsigned 64-bit / 32-bit divide instruction. | 1183 // No unsigned 64-bit / 32-bit divide instruction. |
| 1184 } | 1184 } |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1670 // R8: String data. | 1670 // R8: String data. |
| 1671 // R0: Hash code, untagged integer. | 1671 // R0: Hash code, untagged integer. |
| 1672 | 1672 |
| 1673 Label loop; | 1673 Label loop; |
| 1674 // Add to hash code: (hash_ is uint32) | 1674 // Add to hash code: (hash_ is uint32) |
| 1675 // hash_ += ch; | 1675 // hash_ += ch; |
| 1676 // hash_ += hash_ << 10; | 1676 // hash_ += hash_ << 10; |
| 1677 // hash_ ^= hash_ >> 6; | 1677 // hash_ ^= hash_ >> 6; |
| 1678 // Get one characters (ch). | 1678 // Get one characters (ch). |
| 1679 __ Bind(&loop); | 1679 __ Bind(&loop); |
| 1680 __ ldrb(R7, Address(R8, 0)); | 1680 __ ldrb(R711, Address(R8, 0)); |
| 1681 // R7: ch. | 1681 // R711: ch. |
| 1682 __ add(R3, R3, Operand(1)); | 1682 __ add(R3, R3, Operand(1)); |
| 1683 __ add(R8, R8, Operand(1)); | 1683 __ add(R8, R8, Operand(1)); |
| 1684 __ add(R0, R0, Operand(R7)); | 1684 __ add(R0, R0, Operand(R711)); |
| 1685 __ add(R0, R0, Operand(R0, LSL, 10)); | 1685 __ add(R0, R0, Operand(R0, LSL, 10)); |
| 1686 __ eor(R0, R0, Operand(R0, LSR, 6)); | 1686 __ eor(R0, R0, Operand(R0, LSR, 6)); |
| 1687 __ cmp(R3, Operand(R2)); | 1687 __ cmp(R3, Operand(R2)); |
| 1688 __ b(&loop, NE); | 1688 __ b(&loop, NE); |
| 1689 | 1689 |
| 1690 // Finalize. | 1690 // Finalize. |
| 1691 // hash_ += hash_ << 3; | 1691 // hash_ += hash_ << 3; |
| 1692 // hash_ ^= hash_ >> 11; | 1692 // hash_ ^= hash_ >> 11; |
| 1693 // hash_ += hash_ << 15; | 1693 // hash_ += hash_ << 15; |
| 1694 __ add(R0, R0, Operand(R0, LSL, 3)); | 1694 __ add(R0, R0, Operand(R0, LSL, 3)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1732 | 1732 |
| 1733 // length_reg: allocation size. | 1733 // length_reg: allocation size. |
| 1734 __ adds(R1, R0, Operand(length_reg)); | 1734 __ adds(R1, R0, Operand(length_reg)); |
| 1735 __ b(&fail, CS); // Fail on unsigned overflow. | 1735 __ b(&fail, CS); // Fail on unsigned overflow. |
| 1736 | 1736 |
| 1737 // Check if the allocation fits into the remaining space. | 1737 // Check if the allocation fits into the remaining space. |
| 1738 // R0: potential new object start. | 1738 // R0: potential new object start. |
| 1739 // R1: potential next object start. | 1739 // R1: potential next object start. |
| 1740 // R2: allocation size. | 1740 // R2: allocation size. |
| 1741 // R3: heap. | 1741 // R3: heap. |
| 1742 __ ldr(R7, Address(R3, Heap::EndOffset(space))); | 1742 __ ldr(R711, Address(R3, Heap::EndOffset(space))); |
| 1743 __ cmp(R1, Operand(R7)); | 1743 __ cmp(R1, Operand(R711)); |
| 1744 __ b(&fail, CS); | 1744 __ b(&fail, CS); |
| 1745 | 1745 |
| 1746 // Successfully allocated the object(s), now update top to point to | 1746 // Successfully allocated the object(s), now update top to point to |
| 1747 // next object start and initialize the object. | 1747 // next object start and initialize the object. |
| 1748 __ LoadAllocationStatsAddress(R4, cid, /* inline_isolate = */ false); | 1748 __ LoadAllocationStatsAddress(R4, cid, /* inline_isolate = */ false); |
| 1749 __ str(R1, Address(R3, Heap::TopOffset(space))); | 1749 __ str(R1, Address(R3, Heap::TopOffset(space))); |
| 1750 __ AddImmediate(R0, kHeapObjectTag); | 1750 __ AddImmediate(R0, kHeapObjectTag); |
| 1751 | 1751 |
| 1752 // Initialize the tags. | 1752 // Initialize the tags. |
| 1753 // R0: new object start as a tagged pointer. | 1753 // R0: new object start as a tagged pointer. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1817 // R3: Start address to copy from (untagged). | 1817 // R3: Start address to copy from (untagged). |
| 1818 // R1: Untagged start index. | 1818 // R1: Untagged start index. |
| 1819 __ ldr(R2, Address(SP, kEndIndexOffset)); | 1819 __ ldr(R2, Address(SP, kEndIndexOffset)); |
| 1820 __ SmiUntag(R2); | 1820 __ SmiUntag(R2); |
| 1821 __ sub(R2, R2, Operand(R1)); | 1821 __ sub(R2, R2, Operand(R1)); |
| 1822 | 1822 |
| 1823 // R3: Start address to copy from (untagged). | 1823 // R3: Start address to copy from (untagged). |
| 1824 // R2: Untagged number of bytes to copy. | 1824 // R2: Untagged number of bytes to copy. |
| 1825 // R0: Tagged result string. | 1825 // R0: Tagged result string. |
| 1826 // R8: Pointer into R3. | 1826 // R8: Pointer into R3. |
| 1827 // R7: Pointer into R0. | 1827 // R711: Pointer into R0. |
| 1828 // R1: Scratch register. | 1828 // R1: Scratch register. |
| 1829 Label loop, done; | 1829 Label loop, done; |
| 1830 __ cmp(R2, Operand(0)); | 1830 __ cmp(R2, Operand(0)); |
| 1831 __ b(&done, LE); | 1831 __ b(&done, LE); |
| 1832 __ mov(R8, Operand(R3)); | 1832 __ mov(R8, Operand(R3)); |
| 1833 __ mov(R7, Operand(R0)); | 1833 __ mov(R711, Operand(R0)); |
| 1834 __ Bind(&loop); | 1834 __ Bind(&loop); |
| 1835 __ ldrb(R1, Address(R8, 0)); | 1835 __ ldrb(R1, Address(R8, 0)); |
| 1836 __ AddImmediate(R8, 1); | 1836 __ AddImmediate(R8, 1); |
| 1837 __ sub(R2, R2, Operand(1)); | 1837 __ sub(R2, R2, Operand(1)); |
| 1838 __ cmp(R2, Operand(0)); | 1838 __ cmp(R2, Operand(0)); |
| 1839 __ strb(R1, FieldAddress(R7, OneByteString::data_offset())); | 1839 __ strb(R1, FieldAddress(R711, OneByteString::data_offset())); |
| 1840 __ AddImmediate(R7, 1); | 1840 __ AddImmediate(R711, 1); |
| 1841 __ b(&loop, GT); | 1841 __ b(&loop, GT); |
| 1842 | 1842 |
| 1843 __ Bind(&done); | 1843 __ Bind(&done); |
| 1844 __ Ret(); | 1844 __ Ret(); |
| 1845 __ Bind(&fall_through); | 1845 __ Bind(&fall_through); |
| 1846 } | 1846 } |
| 1847 | 1847 |
| 1848 | 1848 |
| 1849 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) { | 1849 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) { |
| 1850 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. | 1850 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2003 | 2003 |
| 2004 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { | 2004 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { |
| 2005 __ LoadIsolate(R0); | 2005 __ LoadIsolate(R0); |
| 2006 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); | 2006 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); |
| 2007 __ Ret(); | 2007 __ Ret(); |
| 2008 } | 2008 } |
| 2009 | 2009 |
| 2010 } // namespace dart | 2010 } // namespace dart |
| 2011 | 2011 |
| 2012 #endif // defined TARGET_ARCH_ARM | 2012 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |