Chromium Code Reviews| 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" |
| 11 #include "vm/cpu.h" | 11 #include "vm/cpu.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
| 14 #include "vm/object.h" | 14 #include "vm/object.h" |
| 15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 16 #include "vm/regexp_assembler.h" | 16 #include "vm/regexp_assembler.h" |
| 17 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
| 18 | 18 |
| 19 namespace dart { | 19 namespace dart { |
| 20 | 20 |
| 21 // When entering intrinsics code: | 21 // When entering intrinsics code: |
| 22 // R5: IC Data | 22 // R5: IC Data |
| 23 // R4: Arguments descriptor | 23 // R4: Arguments descriptor |
| 24 // LR: Return address | 24 // LR: Return address |
| 25 // The R5, R4 registers can be destroyed only if there is no slow-path, i.e. | 25 // The R5, R4 registers can be destroyed only if there is no slow-path, i.e. |
| 26 // if the intrinsified method always executes a return. | 26 // if the intrinsified method always executes a return. |
| 27 // The FP register should not be modified, because it is used by the profiler. | 27 // The FP register should not be modified, because it is used by the profiler. |
|
srdjan
2015/05/26 20:10:44
Mention THR(R8) as not allowed to be modified,
koda
2015/05/26 20:29:12
Done.
| |
| 28 | 28 |
| 29 #define __ assembler-> | 29 #define __ assembler-> |
| 30 | 30 |
| 31 | 31 |
| 32 intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; } | 32 intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; } |
| 33 | 33 |
| 34 | 34 |
| 35 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { | 35 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { |
| 36 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 36 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 37 const Class& cls = Class::Handle( | 37 const Class& cls = Class::Handle( |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 __ b(&fall_through, LT); | 569 __ b(&fall_through, LT); |
| 570 __ SmiUntag(R1); | 570 __ SmiUntag(R1); |
| 571 | 571 |
| 572 // Pull off high bits that will be shifted off of R1 by making a mask | 572 // Pull off high bits that will be shifted off of R1 by making a mask |
| 573 // ((1 << R0) - 1), shifting it to the left, masking R1, then shifting back. | 573 // ((1 << R0) - 1), shifting it to the left, masking R1, then shifting back. |
| 574 // high bits = (((1 << R0) - 1) << (32 - R0)) & R1) >> (32 - R0) | 574 // high bits = (((1 << R0) - 1) << (32 - R0)) & R1) >> (32 - R0) |
| 575 // lo bits = R1 << R0 | 575 // lo bits = R1 << R0 |
| 576 __ LoadImmediate(R7, 1); | 576 __ LoadImmediate(R7, 1); |
| 577 __ mov(R7, Operand(R7, LSL, R0)); // R7 <- 1 << R0 | 577 __ mov(R7, Operand(R7, LSL, R0)); // R7 <- 1 << R0 |
| 578 __ sub(R7, R7, Operand(1)); // R7 <- R7 - 1 | 578 __ sub(R7, R7, Operand(1)); // R7 <- R7 - 1 |
| 579 __ rsb(R8, R0, Operand(32)); // R8 <- 32 - R0 | 579 __ rsb(R9, R0, Operand(32)); // R9 <- 32 - R0 |
| 580 __ mov(R7, Operand(R7, LSL, R8)); // R7 <- R7 << R8 | 580 __ mov(R7, Operand(R7, LSL, R9)); // R7 <- R7 << R9 |
| 581 __ and_(R7, R1, Operand(R7)); // R7 <- R7 & R1 | 581 __ and_(R7, R1, Operand(R7)); // R7 <- R7 & R1 |
| 582 __ mov(R7, Operand(R7, LSR, R8)); // R7 <- R7 >> R8 | 582 __ mov(R7, Operand(R7, LSR, R9)); // R7 <- R7 >> R9 |
| 583 // Now R7 has the bits that fall off of R1 on a left shift. | 583 // Now R7 has the bits that fall off of R1 on a left shift. |
| 584 __ mov(R1, Operand(R1, LSL, R0)); // R1 gets the low bits. | 584 __ mov(R1, Operand(R1, LSL, R0)); // R1 gets the low bits. |
| 585 | 585 |
| 586 const Class& mint_class = Class::Handle( | 586 const Class& mint_class = Class::Handle( |
| 587 Isolate::Current()->object_store()->mint_class()); | 587 Isolate::Current()->object_store()->mint_class()); |
| 588 __ TryAllocate(mint_class, &fall_through, R0, R2); | 588 __ TryAllocate(mint_class, &fall_through, R0, R2); |
| 589 | 589 |
| 590 | 590 |
| 591 __ str(R1, FieldAddress(R0, Mint::value_offset())); | 591 __ str(R1, FieldAddress(R0, Mint::value_offset())); |
| 592 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); | 592 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 __ ldrd(R2, SP, 2 * kWordSize); | 810 __ ldrd(R2, SP, 2 * kWordSize); |
| 811 // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0. | 811 // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0. |
| 812 __ ldrd(R4, SP, 0 * kWordSize); | 812 __ ldrd(R4, SP, 0 * kWordSize); |
| 813 __ SmiUntag(R5); | 813 __ SmiUntag(R5); |
| 814 // R0 = n ~/ _DIGIT_BITS | 814 // R0 = n ~/ _DIGIT_BITS |
| 815 __ Asr(R0, R5, Operand(5)); | 815 __ Asr(R0, R5, Operand(5)); |
| 816 // R6 = &x_digits[0] | 816 // R6 = &x_digits[0] |
| 817 __ add(R6, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 817 __ add(R6, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 818 // R7 = &x_digits[x_used] | 818 // R7 = &x_digits[x_used] |
| 819 __ add(R7, R6, Operand(R2, LSL, 1)); | 819 __ add(R7, R6, Operand(R2, LSL, 1)); |
| 820 // R8 = &r_digits[1] | 820 // R9 = &r_digits[1] |
| 821 __ add(R8, R4, Operand(TypedData::data_offset() - kHeapObjectTag + | 821 __ add(R9, R4, Operand(TypedData::data_offset() - kHeapObjectTag + |
| 822 Bigint::kBytesPerDigit)); | 822 Bigint::kBytesPerDigit)); |
| 823 // R8 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1] | 823 // R9 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1] |
| 824 __ add(R0, R0, Operand(R2, ASR, 1)); | 824 __ add(R0, R0, Operand(R2, ASR, 1)); |
| 825 __ add(R8, R8, Operand(R0, LSL, 2)); | 825 __ add(R9, R9, Operand(R0, LSL, 2)); |
| 826 // R3 = n % _DIGIT_BITS | 826 // R3 = n % _DIGIT_BITS |
| 827 __ and_(R3, R5, Operand(31)); | 827 __ and_(R3, R5, Operand(31)); |
| 828 // R2 = 32 - R3 | 828 // R2 = 32 - R3 |
| 829 __ rsb(R2, R3, Operand(32)); | 829 __ rsb(R2, R3, Operand(32)); |
| 830 __ mov(R1, Operand(0)); | 830 __ mov(R1, Operand(0)); |
| 831 Label loop; | 831 Label loop; |
| 832 __ Bind(&loop); | 832 __ Bind(&loop); |
| 833 __ ldr(R0, Address(R7, -Bigint::kBytesPerDigit, Address::PreIndex)); | 833 __ ldr(R0, Address(R7, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 834 __ orr(R1, R1, Operand(R0, LSR, R2)); | 834 __ orr(R1, R1, Operand(R0, LSR, R2)); |
| 835 __ str(R1, Address(R8, -Bigint::kBytesPerDigit, Address::PreIndex)); | 835 __ str(R1, Address(R9, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 836 __ mov(R1, Operand(R0, LSL, R3)); | 836 __ mov(R1, Operand(R0, LSL, R3)); |
| 837 __ teq(R7, Operand(R6)); | 837 __ teq(R7, Operand(R6)); |
| 838 __ b(&loop, NE); | 838 __ b(&loop, NE); |
| 839 __ str(R1, Address(R8, -Bigint::kBytesPerDigit, Address::PreIndex)); | 839 __ str(R1, Address(R9, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 840 // Returning Object::null() is not required, since this method is private. | 840 // Returning Object::null() is not required, since this method is private. |
| 841 __ Ret(); | 841 __ Ret(); |
| 842 } | 842 } |
| 843 | 843 |
| 844 | 844 |
| 845 void Intrinsifier::Bigint_rsh(Assembler* assembler) { | 845 void Intrinsifier::Bigint_rsh(Assembler* assembler) { |
| 846 // static void _lsh(Uint32List x_digits, int x_used, int n, | 846 // static void _lsh(Uint32List x_digits, int x_used, int n, |
| 847 // Uint32List r_digits) | 847 // Uint32List r_digits) |
| 848 | 848 |
| 849 // R2 = x_used, R3 = x_digits, x_used > 0, x_used is Smi. | 849 // R2 = x_used, R3 = x_digits, x_used > 0, x_used is Smi. |
| 850 __ ldrd(R2, SP, 2 * kWordSize); | 850 __ ldrd(R2, SP, 2 * kWordSize); |
| 851 // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0. | 851 // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0. |
| 852 __ ldrd(R4, SP, 0 * kWordSize); | 852 __ ldrd(R4, SP, 0 * kWordSize); |
| 853 __ SmiUntag(R5); | 853 __ SmiUntag(R5); |
| 854 // R0 = n ~/ _DIGIT_BITS | 854 // R0 = n ~/ _DIGIT_BITS |
| 855 __ Asr(R0, R5, Operand(5)); | 855 __ Asr(R0, R5, Operand(5)); |
| 856 // R8 = &r_digits[0] | 856 // R9 = &r_digits[0] |
| 857 __ add(R8, R4, Operand(TypedData::data_offset() - kHeapObjectTag)); | 857 __ add(R9, R4, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 858 // R7 = &x_digits[n ~/ _DIGIT_BITS] | 858 // R7 = &x_digits[n ~/ _DIGIT_BITS] |
| 859 __ add(R7, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 859 __ add(R7, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 860 __ add(R7, R7, Operand(R0, LSL, 2)); | 860 __ add(R7, R7, Operand(R0, LSL, 2)); |
| 861 // R6 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1] | 861 // R6 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1] |
| 862 __ add(R0, R0, Operand(1)); | 862 __ add(R0, R0, Operand(1)); |
| 863 __ rsb(R0, R0, Operand(R2, ASR, 1)); | 863 __ rsb(R0, R0, Operand(R2, ASR, 1)); |
| 864 __ add(R6, R8, Operand(R0, LSL, 2)); | 864 __ add(R6, R9, Operand(R0, LSL, 2)); |
| 865 // R3 = n % _DIGIT_BITS | 865 // R3 = n % _DIGIT_BITS |
| 866 __ and_(R3, R5, Operand(31)); | 866 __ and_(R3, R5, Operand(31)); |
| 867 // R2 = 32 - R3 | 867 // R2 = 32 - R3 |
| 868 __ rsb(R2, R3, Operand(32)); | 868 __ rsb(R2, R3, Operand(32)); |
| 869 // R1 = x_digits[n ~/ _DIGIT_BITS] >> (n % _DIGIT_BITS) | 869 // R1 = x_digits[n ~/ _DIGIT_BITS] >> (n % _DIGIT_BITS) |
| 870 __ ldr(R1, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 870 __ ldr(R1, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 871 __ mov(R1, Operand(R1, LSR, R3)); | 871 __ mov(R1, Operand(R1, LSR, R3)); |
| 872 Label loop_entry; | 872 Label loop_entry; |
| 873 __ b(&loop_entry); | 873 __ b(&loop_entry); |
| 874 Label loop; | 874 Label loop; |
| 875 __ Bind(&loop); | 875 __ Bind(&loop); |
| 876 __ ldr(R0, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 876 __ ldr(R0, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 877 __ orr(R1, R1, Operand(R0, LSL, R2)); | 877 __ orr(R1, R1, Operand(R0, LSL, R2)); |
| 878 __ str(R1, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); | 878 __ str(R1, Address(R9, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 879 __ mov(R1, Operand(R0, LSR, R3)); | 879 __ mov(R1, Operand(R0, LSR, R3)); |
| 880 __ Bind(&loop_entry); | 880 __ Bind(&loop_entry); |
| 881 __ teq(R8, Operand(R6)); | 881 __ teq(R9, Operand(R6)); |
| 882 __ b(&loop, NE); | 882 __ b(&loop, NE); |
| 883 __ str(R1, Address(R8, 0)); | 883 __ str(R1, Address(R9, 0)); |
| 884 // Returning Object::null() is not required, since this method is private. | 884 // Returning Object::null() is not required, since this method is private. |
| 885 __ Ret(); | 885 __ Ret(); |
| 886 } | 886 } |
| 887 | 887 |
| 888 | 888 |
| 889 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { | 889 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { |
| 890 // static void _absAdd(Uint32List digits, int used, | 890 // static void _absAdd(Uint32List digits, int used, |
| 891 // Uint32List a_digits, int a_used, | 891 // Uint32List a_digits, int a_used, |
| 892 // Uint32List r_digits) | 892 // Uint32List r_digits) |
| 893 | 893 |
| 894 // R2 = used, R3 = digits | 894 // R2 = used, R3 = digits |
| 895 __ ldrd(R2, SP, 3 * kWordSize); | 895 __ ldrd(R2, SP, 3 * kWordSize); |
| 896 // R3 = &digits[0] | 896 // R3 = &digits[0] |
| 897 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 897 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 898 | 898 |
| 899 // R4 = a_used, R5 = a_digits | 899 // R4 = a_used, R5 = a_digits |
| 900 __ ldrd(R4, SP, 1 * kWordSize); | 900 __ ldrd(R4, SP, 1 * kWordSize); |
| 901 // R5 = &a_digits[0] | 901 // R5 = &a_digits[0] |
| 902 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); | 902 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 903 | 903 |
| 904 // R6 = r_digits | 904 // R6 = r_digits |
| 905 __ ldr(R6, Address(SP, 0 * kWordSize)); | 905 __ ldr(R6, Address(SP, 0 * kWordSize)); |
| 906 // R6 = &r_digits[0] | 906 // R6 = &r_digits[0] |
| 907 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); | 907 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 908 | 908 |
| 909 // R7 = &digits[a_used >> 1], a_used is Smi. | 909 // R7 = &digits[a_used >> 1], a_used is Smi. |
| 910 __ add(R7, R3, Operand(R4, LSL, 1)); | 910 __ add(R7, R3, Operand(R4, LSL, 1)); |
| 911 | 911 |
| 912 // R8 = &digits[used >> 1], used is Smi. | 912 // R9 = &digits[used >> 1], used is Smi. |
| 913 __ add(R8, R3, Operand(R2, LSL, 1)); | 913 __ add(R9, R3, Operand(R2, LSL, 1)); |
| 914 | 914 |
| 915 __ adds(R0, R0, Operand(0)); // carry flag = 0 | 915 __ adds(R0, R0, Operand(0)); // carry flag = 0 |
| 916 Label add_loop; | 916 Label add_loop; |
| 917 __ Bind(&add_loop); | 917 __ Bind(&add_loop); |
| 918 // Loop a_used times, a_used > 0. | 918 // Loop a_used times, a_used > 0. |
| 919 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 919 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 920 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 920 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 921 __ adcs(R0, R0, Operand(R1)); | 921 __ adcs(R0, R0, Operand(R1)); |
| 922 __ teq(R3, Operand(R7)); // Does not affect carry flag. | 922 __ teq(R3, Operand(R7)); // Does not affect carry flag. |
| 923 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 923 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 924 __ b(&add_loop, NE); | 924 __ b(&add_loop, NE); |
| 925 | 925 |
| 926 Label last_carry; | 926 Label last_carry; |
| 927 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 927 __ teq(R3, Operand(R9)); // Does not affect carry flag. |
| 928 __ b(&last_carry, EQ); // If used - a_used == 0. | 928 __ b(&last_carry, EQ); // If used - a_used == 0. |
| 929 | 929 |
| 930 Label carry_loop; | 930 Label carry_loop; |
| 931 __ Bind(&carry_loop); | 931 __ Bind(&carry_loop); |
| 932 // Loop used - a_used times, used - a_used > 0. | 932 // Loop used - a_used times, used - a_used > 0. |
| 933 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 933 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 934 __ adcs(R0, R0, Operand(0)); | 934 __ adcs(R0, R0, Operand(0)); |
| 935 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 935 __ teq(R3, Operand(R9)); // Does not affect carry flag. |
| 936 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 936 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 937 __ b(&carry_loop, NE); | 937 __ b(&carry_loop, NE); |
| 938 | 938 |
| 939 __ Bind(&last_carry); | 939 __ Bind(&last_carry); |
| 940 __ mov(R0, Operand(0)); | 940 __ mov(R0, Operand(0)); |
| 941 __ adc(R0, R0, Operand(0)); | 941 __ adc(R0, R0, Operand(0)); |
| 942 __ str(R0, Address(R6, 0)); | 942 __ str(R0, Address(R6, 0)); |
| 943 | 943 |
| 944 // Returning Object::null() is not required, since this method is private. | 944 // Returning Object::null() is not required, since this method is private. |
| 945 __ Ret(); | 945 __ Ret(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 962 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); | 962 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 963 | 963 |
| 964 // R6 = r_digits | 964 // R6 = r_digits |
| 965 __ ldr(R6, Address(SP, 0 * kWordSize)); | 965 __ ldr(R6, Address(SP, 0 * kWordSize)); |
| 966 // R6 = &r_digits[0] | 966 // R6 = &r_digits[0] |
| 967 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); | 967 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 968 | 968 |
| 969 // R7 = &digits[a_used >> 1], a_used is Smi. | 969 // R7 = &digits[a_used >> 1], a_used is Smi. |
| 970 __ add(R7, R3, Operand(R4, LSL, 1)); | 970 __ add(R7, R3, Operand(R4, LSL, 1)); |
| 971 | 971 |
| 972 // R8 = &digits[used >> 1], used is Smi. | 972 // R9 = &digits[used >> 1], used is Smi. |
| 973 __ add(R8, R3, Operand(R2, LSL, 1)); | 973 __ add(R9, R3, Operand(R2, LSL, 1)); |
| 974 | 974 |
| 975 __ subs(R0, R0, Operand(0)); // carry flag = 1 | 975 __ subs(R0, R0, Operand(0)); // carry flag = 1 |
| 976 Label sub_loop; | 976 Label sub_loop; |
| 977 __ Bind(&sub_loop); | 977 __ Bind(&sub_loop); |
| 978 // Loop a_used times, a_used > 0. | 978 // Loop a_used times, a_used > 0. |
| 979 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 979 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 980 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 980 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 981 __ sbcs(R0, R0, Operand(R1)); | 981 __ sbcs(R0, R0, Operand(R1)); |
| 982 __ teq(R3, Operand(R7)); // Does not affect carry flag. | 982 __ teq(R3, Operand(R7)); // Does not affect carry flag. |
| 983 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 983 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 984 __ b(&sub_loop, NE); | 984 __ b(&sub_loop, NE); |
| 985 | 985 |
| 986 Label done; | 986 Label done; |
| 987 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 987 __ teq(R3, Operand(R9)); // Does not affect carry flag. |
| 988 __ b(&done, EQ); // If used - a_used == 0. | 988 __ b(&done, EQ); // If used - a_used == 0. |
| 989 | 989 |
| 990 Label carry_loop; | 990 Label carry_loop; |
| 991 __ Bind(&carry_loop); | 991 __ Bind(&carry_loop); |
| 992 // Loop used - a_used times, used - a_used > 0. | 992 // Loop used - a_used times, used - a_used > 0. |
| 993 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 993 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 994 __ sbcs(R0, R0, Operand(0)); | 994 __ sbcs(R0, R0, Operand(0)); |
| 995 __ teq(R3, Operand(R8)); // Does not affect carry flag. | 995 __ teq(R3, Operand(R9)); // Does not affect carry flag. |
| 996 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 996 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 997 __ b(&carry_loop, NE); | 997 __ b(&carry_loop, NE); |
| 998 | 998 |
| 999 __ Bind(&done); | 999 __ Bind(&done); |
| 1000 // Returning Object::null() is not required, since this method is private. | 1000 // Returning Object::null() is not required, since this method is private. |
| 1001 __ Ret(); | 1001 __ Ret(); |
| 1002 } | 1002 } |
| 1003 | 1003 |
| 1004 | 1004 |
| 1005 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 1005 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1154 | 1154 |
| 1155 // *ajp++ = low32(t) = R0 | 1155 // *ajp++ = low32(t) = R0 |
| 1156 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1156 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1157 | 1157 |
| 1158 // R6 = low32(c) = high32(t) | 1158 // R6 = low32(c) = high32(t) |
| 1159 // R7 = high32(c) = 0 | 1159 // R7 = high32(c) = 0 |
| 1160 __ mov(R7, Operand(0)); | 1160 __ mov(R7, Operand(0)); |
| 1161 | 1161 |
| 1162 // int n = used - i - 1; while (--n >= 0) ... | 1162 // int n = used - i - 1; while (--n >= 0) ... |
| 1163 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi | 1163 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi |
| 1164 __ sub(R8, R0, Operand(R2)); | 1164 __ sub(R9, R0, Operand(R2)); |
| 1165 __ mov(R0, Operand(2)); // n = used - i - 2; if (n >= 0) ... while (--n >= 0) | 1165 __ mov(R0, Operand(2)); // n = used - i - 2; if (n >= 0) ... while (--n >= 0) |
| 1166 __ rsbs(R8, R0, Operand(R8, ASR, kSmiTagSize)); | 1166 __ rsbs(R9, R0, Operand(R9, ASR, kSmiTagSize)); |
| 1167 | 1167 |
| 1168 Label loop, done; | 1168 Label loop, done; |
| 1169 __ b(&done, MI); | 1169 __ b(&done, MI); |
| 1170 | 1170 |
| 1171 __ Bind(&loop); | 1171 __ Bind(&loop); |
| 1172 // x: R3 | 1172 // x: R3 |
| 1173 // xip: R4 | 1173 // xip: R4 |
| 1174 // ajp: R5 | 1174 // ajp: R5 |
| 1175 // c: R7:R6 | 1175 // c: R7:R6 |
| 1176 // t: R2:R1:R0 (not live at loop entry) | 1176 // t: R2:R1:R0 (not live at loop entry) |
| 1177 // n: R8 | 1177 // n: R9 |
| 1178 | 1178 |
| 1179 // uint32_t xi = *xip++ | 1179 // uint32_t xi = *xip++ |
| 1180 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1180 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1181 | 1181 |
| 1182 // uint96_t t = R7:R6:R0 = 2*x*xi + aj + c | 1182 // uint96_t t = R7:R6:R0 = 2*x*xi + aj + c |
| 1183 __ umull(R0, R1, R2, R3); // R1:R0 = R2*R3. | 1183 __ umull(R0, R1, R2, R3); // R1:R0 = R2*R3. |
| 1184 __ adds(R0, R0, Operand(R0)); | 1184 __ adds(R0, R0, Operand(R0)); |
| 1185 __ adcs(R1, R1, Operand(R1)); | 1185 __ adcs(R1, R1, Operand(R1)); |
| 1186 __ mov(R2, Operand(0)); | 1186 __ mov(R2, Operand(0)); |
| 1187 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi. | 1187 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi. |
| 1188 __ adds(R0, R0, Operand(R6)); | 1188 __ adds(R0, R0, Operand(R6)); |
| 1189 __ adcs(R1, R1, Operand(R7)); | 1189 __ adcs(R1, R1, Operand(R7)); |
| 1190 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi + c. | 1190 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi + c. |
| 1191 __ ldr(R6, Address(R5, 0)); // R6 = aj = *ajp. | 1191 __ ldr(R6, Address(R5, 0)); // R6 = aj = *ajp. |
| 1192 __ adds(R0, R0, Operand(R6)); | 1192 __ adds(R0, R0, Operand(R6)); |
| 1193 __ adcs(R6, R1, Operand(0)); | 1193 __ adcs(R6, R1, Operand(0)); |
| 1194 __ adc(R7, R2, Operand(0)); // R7:R6:R0 = 2*x*xi + c + aj. | 1194 __ adc(R7, R2, Operand(0)); // R7:R6:R0 = 2*x*xi + c + aj. |
| 1195 | 1195 |
| 1196 // *ajp++ = low32(t) = R0 | 1196 // *ajp++ = low32(t) = R0 |
| 1197 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1197 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1198 | 1198 |
| 1199 // while (--n >= 0) | 1199 // while (--n >= 0) |
| 1200 __ subs(R8, R8, Operand(1)); // --n | 1200 __ subs(R9, R9, Operand(1)); // --n |
| 1201 __ b(&loop, PL); | 1201 __ b(&loop, PL); |
| 1202 | 1202 |
| 1203 __ Bind(&done); | 1203 __ Bind(&done); |
| 1204 // uint32_t aj = *ajp | 1204 // uint32_t aj = *ajp |
| 1205 __ ldr(R0, Address(R5, 0)); | 1205 __ ldr(R0, Address(R5, 0)); |
| 1206 | 1206 |
| 1207 // uint64_t t = aj + c | 1207 // uint64_t t = aj + c |
| 1208 __ adds(R6, R6, Operand(R0)); | 1208 __ adds(R6, R6, Operand(R0)); |
| 1209 __ adc(R7, R7, Operand(0)); | 1209 __ adc(R7, R7, Operand(0)); |
| 1210 | 1210 |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2026 Isolate* isolate = Isolate::Current(); | 2026 Isolate* isolate = Isolate::Current(); |
| 2027 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); | 2027 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); |
| 2028 // Set return value to Isolate::current_tag_. | 2028 // Set return value to Isolate::current_tag_. |
| 2029 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); | 2029 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); |
| 2030 __ Ret(); | 2030 __ Ret(); |
| 2031 } | 2031 } |
| 2032 | 2032 |
| 2033 } // namespace dart | 2033 } // namespace dart |
| 2034 | 2034 |
| 2035 #endif // defined TARGET_ARCH_ARM | 2035 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |