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 DECLARE_FLAG(bool, interpret_irregexp); | 21 DECLARE_FLAG(bool, interpret_irregexp); |
| 22 | 22 |
| 23 // When entering intrinsics code: | 23 // When entering intrinsics code: |
| 24 // R5: IC Data | |
| 25 // R4: Arguments descriptor | 24 // R4: Arguments descriptor |
| 26 // LR: Return address | 25 // LR: Return address |
| 27 // The R5, R4 registers can be destroyed only if there is no slow-path, i.e. | 26 // The R4 register can be destroyed only if there is no slow-path, i.e. |
| 28 // if the intrinsified method always executes a return. | 27 // if the intrinsified method always executes a return. |
| 29 // The FP register should not be modified, because it is used by the profiler. | 28 // The FP register should not be modified, because it is used by the profiler. |
| 30 // The THR register (see constants_arm.h) must be preserved. | 29 // The PP and THR registers (see constants_arm.h) must be preserved. |
| 31 | 30 |
| 32 #define __ assembler-> | 31 #define __ assembler-> |
| 33 | 32 |
| 34 | 33 |
| 35 intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; } | 34 intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; } |
| 36 | 35 |
| 37 | 36 |
| 38 // Intrinsify only for Smi value and index. Non-smi values need a store buffer | 37 // Intrinsify only for Smi value and index. Non-smi values need a store buffer |
| 39 // update. Array length is always a Smi. | 38 // update. Array length is always a Smi. |
| 40 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) { | 39 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 __ ldr(R3, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ | 208 __ ldr(R3, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ |
| 210 __ InitializeFieldNoBarrier(R0, \ | 209 __ InitializeFieldNoBarrier(R0, \ |
| 211 FieldAddress(R0, type_name::length_offset()), \ | 210 FieldAddress(R0, type_name::length_offset()), \ |
| 212 R3); \ | 211 R3); \ |
| 213 /* Initialize all array elements to 0. */ \ | 212 /* Initialize all array elements to 0. */ \ |
| 214 /* R0: new object start as a tagged pointer. */ \ | 213 /* R0: new object start as a tagged pointer. */ \ |
| 215 /* R1: new object end address. */ \ | 214 /* R1: new object end address. */ \ |
| 216 /* R2: allocation size. */ \ | 215 /* R2: allocation size. */ \ |
| 217 /* R3: iterator which initially points to the start of the variable */ \ | 216 /* R3: iterator which initially points to the start of the variable */ \ |
| 218 /* R4: allocation stats address */ \ | 217 /* R4: allocation stats address */ \ |
| 219 /* R6, R7: zero. */ \ | 218 /* R8, R9: zero. */ \ |
| 220 /* data area to be initialized. */ \ | 219 /* data area to be initialized. */ \ |
| 221 __ LoadImmediate(R6, 0); \ | 220 __ LoadImmediate(R8, 0); \ |
| 222 __ mov(R7, Operand(R6)); \ | 221 __ mov(R9, Operand(R8)); \ |
| 223 __ AddImmediate(R3, R0, sizeof(Raw##type_name) - 1); \ | 222 __ AddImmediate(R3, R0, sizeof(Raw##type_name) - 1); \ |
| 224 Label init_loop; \ | 223 Label init_loop; \ |
| 225 __ Bind(&init_loop); \ | 224 __ Bind(&init_loop); \ |
| 226 __ AddImmediate(R3, 2 * kWordSize); \ | 225 __ AddImmediate(R3, 2 * kWordSize); \ |
| 227 __ cmp(R3, Operand(R1)); \ | 226 __ cmp(R3, Operand(R1)); \ |
| 228 __ strd(R6, R7, R3, -2 * kWordSize, LS); \ | 227 __ strd(R8, R9, R3, -2 * kWordSize, LS); \ |
| 229 __ b(&init_loop, CC); \ | 228 __ b(&init_loop, CC); \ |
| 230 __ str(R6, Address(R3, -2 * kWordSize), HI); \ | 229 __ str(R8, Address(R3, -2 * kWordSize), HI); \ |
| 231 \ | 230 \ |
| 232 __ IncrementAllocationStatsWithSize(R4, R2, space); \ | 231 __ IncrementAllocationStatsWithSize(R4, R2, space); \ |
| 233 __ Ret(); \ | 232 __ Ret(); \ |
| 234 __ Bind(&fall_through); \ | 233 __ Bind(&fall_through); \ |
| 235 | 234 |
| 236 | 235 |
| 237 static int GetScaleFactor(intptr_t size) { | 236 static int GetScaleFactor(intptr_t size) { |
| 238 switch (size) { | 237 switch (size) { |
| 239 case 1: return 0; | 238 case 1: return 0; |
| 240 case 2: return 1; | 239 case 2: return 1; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 307 __ subs(R0, R1, Operand(R0)); // Subtract. | 306 __ subs(R0, R1, Operand(R0)); // Subtract. |
| 308 __ bx(LR, VC); // Return if no overflow. | 307 __ bx(LR, VC); // Return if no overflow. |
| 309 // Otherwise fall through. | 308 // Otherwise fall through. |
| 310 __ Bind(&fall_through); | 309 __ Bind(&fall_through); |
| 311 } | 310 } |
| 312 | 311 |
| 313 | 312 |
| 314 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { | 313 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { |
| 315 Label fall_through; | 314 Label fall_through; |
| 316 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis | 315 TestBothArgumentsSmis(assembler, &fall_through); // checks two smis |
| 317 __ SmiUntag(R0); // Untags R6. We only want result shifted by one. | 316 __ SmiUntag(R0); // Untags R8. We only want result shifted by one. |
|
Florian Schneider
2015/10/26 17:12:31
This comments seems out-of-sync already here. s/R6
rmacnak
2015/10/26 18:01:50
Done.
| |
| 318 __ smull(R0, IP, R0, R1); // IP:R0 <- R0 * R1. | 317 __ smull(R0, IP, R0, R1); // IP:R0 <- R0 * R1. |
| 319 __ cmp(IP, Operand(R0, ASR, 31)); | 318 __ cmp(IP, Operand(R0, ASR, 31)); |
| 320 __ bx(LR, EQ); | 319 __ bx(LR, EQ); |
| 321 __ Bind(&fall_through); // Fall through on overflow. | 320 __ Bind(&fall_through); // Fall through on overflow. |
| 322 } | 321 } |
| 323 | 322 |
| 324 | 323 |
| 325 void Intrinsifier::Integer_mul(Assembler* assembler) { | 324 void Intrinsifier::Integer_mul(Assembler* assembler) { |
| 326 Integer_mulFromInteger(assembler); | 325 Integer_mulFromInteger(assembler); |
| 327 } | 326 } |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 500 | 499 |
| 501 void Intrinsifier::Integer_bitXor(Assembler* assembler) { | 500 void Intrinsifier::Integer_bitXor(Assembler* assembler) { |
| 502 Integer_bitXorFromInteger(assembler); | 501 Integer_bitXorFromInteger(assembler); |
| 503 } | 502 } |
| 504 | 503 |
| 505 | 504 |
| 506 void Intrinsifier::Integer_shl(Assembler* assembler) { | 505 void Intrinsifier::Integer_shl(Assembler* assembler) { |
| 507 ASSERT(kSmiTagShift == 1); | 506 ASSERT(kSmiTagShift == 1); |
| 508 ASSERT(kSmiTag == 0); | 507 ASSERT(kSmiTag == 0); |
| 509 Label fall_through; | 508 Label fall_through; |
| 510 __ Push(R10); | 509 __ Push(R6); |
| 511 TestBothArgumentsSmis(assembler, &fall_through); | 510 TestBothArgumentsSmis(assembler, &fall_through); |
| 512 __ CompareImmediate(R0, Smi::RawValue(Smi::kBits)); | 511 __ CompareImmediate(R0, Smi::RawValue(Smi::kBits)); |
| 513 __ b(&fall_through, HI); | 512 __ b(&fall_through, HI); |
| 514 | 513 |
| 515 __ SmiUntag(R0); | 514 __ SmiUntag(R0); |
| 516 | 515 |
| 517 // Check for overflow by shifting left and shifting back arithmetically. | 516 // Check for overflow by shifting left and shifting back arithmetically. |
| 518 // If the result is different from the original, there was overflow. | 517 // If the result is different from the original, there was overflow. |
| 519 __ mov(IP, Operand(R1, LSL, R0)); | 518 __ mov(IP, Operand(R1, LSL, R0)); |
| 520 __ cmp(R1, Operand(IP, ASR, R0)); | 519 __ cmp(R1, Operand(IP, ASR, R0)); |
| 521 | 520 |
| 522 // No overflow, result in R0. | 521 // No overflow, result in R0. |
| 523 __ mov(R0, Operand(R1, LSL, R0), EQ); | 522 __ mov(R0, Operand(R1, LSL, R0), EQ); |
| 524 __ bx(LR, EQ); | 523 __ bx(LR, EQ); |
| 525 | 524 |
| 526 // Arguments are Smi but the shift produced an overflow to Mint. | 525 // Arguments are Smi but the shift produced an overflow to Mint. |
| 527 __ CompareImmediate(R1, 0); | 526 __ CompareImmediate(R1, 0); |
| 528 __ b(&fall_through, LT); | 527 __ b(&fall_through, LT); |
| 529 __ SmiUntag(R1); | 528 __ SmiUntag(R1); |
| 530 | 529 |
| 531 // 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 |
| 532 // ((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. |
| 533 // high bits = (((1 << R0) - 1) << (32 - R0)) & R1) >> (32 - R0) | 532 // high bits = (((1 << R0) - 1) << (32 - R0)) & R1) >> (32 - R0) |
| 534 // lo bits = R1 << R0 | 533 // lo bits = R1 << R0 |
| 535 __ LoadImmediate(R7, 1); | 534 __ LoadImmediate(R7, 1); |
| 536 __ mov(R7, Operand(R7, LSL, R0)); // R7 <- 1 << R0 | 535 __ mov(R7, Operand(R7, LSL, R0)); // R7 <- 1 << R0 |
| 537 __ sub(R7, R7, Operand(1)); // R7 <- R7 - 1 | 536 __ sub(R7, R7, Operand(1)); // R7 <- R7 - 1 |
| 538 __ rsb(R10, R0, Operand(32)); // R10 <- 32 - R0 | 537 __ rsb(R6, R0, Operand(32)); // R6 <- 32 - R0 |
| 539 __ mov(R7, Operand(R7, LSL, R10)); // R7 <- R7 << R10 | 538 __ mov(R7, Operand(R7, LSL, R6)); // R7 <- R7 << R6 |
| 540 __ and_(R7, R1, Operand(R7)); // R7 <- R7 & R1 | 539 __ and_(R7, R1, Operand(R7)); // R7 <- R7 & R1 |
| 541 __ mov(R7, Operand(R7, LSR, R10)); // R7 <- R7 >> R10 | 540 __ mov(R7, Operand(R7, LSR, R6)); // R7 <- R7 >> R6 |
| 542 // Now R7 has the bits that fall off of R1 on a left shift. | 541 // Now R7 has the bits that fall off of R1 on a left shift. |
| 543 __ mov(R1, Operand(R1, LSL, R0)); // R1 gets the low bits. | 542 __ mov(R1, Operand(R1, LSL, R0)); // R1 gets the low bits. |
| 544 | 543 |
| 545 const Class& mint_class = Class::Handle( | 544 const Class& mint_class = Class::Handle( |
| 546 Isolate::Current()->object_store()->mint_class()); | 545 Isolate::Current()->object_store()->mint_class()); |
| 547 __ TryAllocate(mint_class, &fall_through, R0, R2); | 546 __ TryAllocate(mint_class, &fall_through, R0, R2); |
| 548 | 547 |
| 549 | 548 |
| 550 __ str(R1, FieldAddress(R0, Mint::value_offset())); | 549 __ str(R1, FieldAddress(R0, Mint::value_offset())); |
| 551 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); | 550 __ str(R7, FieldAddress(R0, Mint::value_offset() + kWordSize)); |
| 552 __ Pop(R10); | 551 __ Pop(R6); |
| 553 __ Ret(); | 552 __ Ret(); |
| 554 __ Bind(&fall_through); | 553 __ Bind(&fall_through); |
| 555 ASSERT(CODE_REG == R10); | 554 ASSERT(CODE_REG == R6); |
| 556 __ Pop(R10); | 555 __ Pop(R6); |
| 557 } | 556 } |
| 558 | 557 |
| 559 | 558 |
| 560 static void Get64SmiOrMint(Assembler* assembler, | 559 static void Get64SmiOrMint(Assembler* assembler, |
| 561 Register res_hi, | 560 Register res_hi, |
| 562 Register res_lo, | 561 Register res_lo, |
| 563 Register reg, | 562 Register reg, |
| 564 Label* not_smi_or_mint) { | 563 Label* not_smi_or_mint) { |
| 565 Label not_smi, done; | 564 Label not_smi, done; |
| 566 __ tst(reg, Operand(kSmiTagMask)); | 565 __ tst(reg, Operand(kSmiTagMask)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 615 break; | 614 break; |
| 616 default: | 615 default: |
| 617 UNREACHABLE(); | 616 UNREACHABLE(); |
| 618 hi_true_cond = hi_false_cond = lo_false_cond = VS; | 617 hi_true_cond = hi_false_cond = lo_false_cond = VS; |
| 619 } | 618 } |
| 620 | 619 |
| 621 __ Bind(&try_mint_smi); | 620 __ Bind(&try_mint_smi); |
| 622 // Get left as 64 bit integer. | 621 // Get left as 64 bit integer. |
| 623 Get64SmiOrMint(assembler, R3, R2, R1, &fall_through); | 622 Get64SmiOrMint(assembler, R3, R2, R1, &fall_through); |
| 624 // Get right as 64 bit integer. | 623 // Get right as 64 bit integer. |
| 625 Get64SmiOrMint(assembler, R7, R6, R0, &fall_through); | 624 Get64SmiOrMint(assembler, R7, R8, R0, &fall_through); |
| 626 // R3: left high. | 625 // R3: left high. |
| 627 // R2: left low. | 626 // R2: left low. |
| 628 // R7: right high. | 627 // R7: right high. |
| 629 // R6: right low. | 628 // R8: right low. |
| 630 | 629 |
| 631 __ cmp(R3, Operand(R7)); // Compare left hi, right high. | 630 __ cmp(R3, Operand(R7)); // Compare left hi, right high. |
| 632 __ b(&is_false, hi_false_cond); | 631 __ b(&is_false, hi_false_cond); |
| 633 __ b(&is_true, hi_true_cond); | 632 __ b(&is_true, hi_true_cond); |
| 634 __ cmp(R2, Operand(R6)); // Compare left lo, right lo. | 633 __ cmp(R2, Operand(R8)); // Compare left lo, right lo. |
| 635 __ b(&is_false, lo_false_cond); | 634 __ b(&is_false, lo_false_cond); |
| 636 // Else is true. | 635 // Else is true. |
| 637 __ b(&is_true); | 636 __ b(&is_true); |
| 638 | 637 |
| 639 __ Bind(&fall_through); | 638 __ Bind(&fall_through); |
| 640 } | 639 } |
| 641 | 640 |
| 642 | 641 |
| 643 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { | 642 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { |
| 644 CompareIntegers(assembler, LT); | 643 CompareIntegers(assembler, LT); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 __ rsb(R0, R0, Operand(32)); | 760 __ rsb(R0, R0, Operand(32)); |
| 762 __ SmiTag(R0); | 761 __ SmiTag(R0); |
| 763 __ Ret(); | 762 __ Ret(); |
| 764 } | 763 } |
| 765 | 764 |
| 766 | 765 |
| 767 void Intrinsifier::Bigint_lsh(Assembler* assembler) { | 766 void Intrinsifier::Bigint_lsh(Assembler* assembler) { |
| 768 // static void _lsh(Uint32List x_digits, int x_used, int n, | 767 // static void _lsh(Uint32List x_digits, int x_used, int n, |
| 769 // Uint32List r_digits) | 768 // Uint32List r_digits) |
| 770 | 769 |
| 771 // R2 = x_used, R3 = x_digits, x_used > 0, x_used is Smi. | 770 // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi. |
| 772 __ ldrd(R2, R3, SP, 2 * kWordSize); | 771 __ ldrd(R0, R1, SP, 2 * kWordSize); |
| 773 // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0. | 772 // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0. |
| 774 __ ldrd(R4, R5, SP, 0 * kWordSize); | 773 __ ldrd(R2, R3, SP, 0 * kWordSize); |
| 775 __ SmiUntag(R5); | 774 __ SmiUntag(R3); |
| 776 // R0 = n ~/ _DIGIT_BITS | 775 // R4 = n ~/ _DIGIT_BITS |
| 777 __ Asr(R0, R5, Operand(5)); | 776 __ Asr(R4, R3, Operand(5)); |
| 778 // R6 = &x_digits[0] | 777 // R8 = &x_digits[0] |
| 779 __ add(R6, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 778 __ add(R8, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 780 // R7 = &x_digits[x_used] | 779 // R7 = &x_digits[x_used] |
| 781 __ add(R7, R6, Operand(R2, LSL, 1)); | 780 __ add(R7, R8, Operand(R0, LSL, 1)); |
| 782 // R10 = &r_digits[1] | 781 // R6 = &r_digits[1] |
| 783 __ add(R10, R4, Operand(TypedData::data_offset() - kHeapObjectTag + | 782 __ add(R6, R2, Operand(TypedData::data_offset() - kHeapObjectTag + |
| 784 Bigint::kBytesPerDigit)); | 783 Bigint::kBytesPerDigit)); |
| 785 // R10 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1] | 784 // R6 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1] |
| 786 __ add(R0, R0, Operand(R2, ASR, 1)); | 785 __ add(R4, R4, Operand(R0, ASR, 1)); |
| 787 __ add(R10, R10, Operand(R0, LSL, 2)); | 786 __ add(R6, R6, Operand(R4, LSL, 2)); |
| 788 // R3 = n % _DIGIT_BITS | 787 // R1 = n % _DIGIT_BITS |
| 789 __ and_(R3, R5, Operand(31)); | 788 __ and_(R1, R3, Operand(31)); |
| 790 // R2 = 32 - R3 | 789 // R0 = 32 - R1 |
| 791 __ rsb(R2, R3, Operand(32)); | 790 __ rsb(R0, R1, Operand(32)); |
| 792 __ mov(R1, Operand(0)); | 791 __ mov(R9, Operand(0)); |
| 793 Label loop; | 792 Label loop; |
| 794 __ Bind(&loop); | 793 __ Bind(&loop); |
| 795 __ ldr(R0, Address(R7, -Bigint::kBytesPerDigit, Address::PreIndex)); | 794 __ ldr(R4, Address(R7, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 796 __ orr(R1, R1, Operand(R0, LSR, R2)); | 795 __ orr(R9, R9, Operand(R4, LSR, R0)); |
| 797 __ str(R1, Address(R10, -Bigint::kBytesPerDigit, Address::PreIndex)); | 796 __ str(R9, Address(R6, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 798 __ mov(R1, Operand(R0, LSL, R3)); | 797 __ mov(R9, Operand(R4, LSL, R1)); |
| 799 __ teq(R7, Operand(R6)); | 798 __ teq(R7, Operand(R8)); |
| 800 __ b(&loop, NE); | 799 __ b(&loop, NE); |
| 801 __ str(R1, Address(R10, -Bigint::kBytesPerDigit, Address::PreIndex)); | 800 __ str(R9, Address(R6, -Bigint::kBytesPerDigit, Address::PreIndex)); |
| 802 // Returning Object::null() is not required, since this method is private. | 801 // Returning Object::null() is not required, since this method is private. |
| 803 __ Ret(); | 802 __ Ret(); |
| 804 } | 803 } |
| 805 | 804 |
| 806 | 805 |
| 807 void Intrinsifier::Bigint_rsh(Assembler* assembler) { | 806 void Intrinsifier::Bigint_rsh(Assembler* assembler) { |
| 808 // static void _lsh(Uint32List x_digits, int x_used, int n, | 807 // static void _lsh(Uint32List x_digits, int x_used, int n, |
| 809 // Uint32List r_digits) | 808 // Uint32List r_digits) |
| 810 | 809 |
| 811 // R2 = x_used, R3 = x_digits, x_used > 0, x_used is Smi. | 810 // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi. |
| 812 __ ldrd(R2, R3, SP, 2 * kWordSize); | 811 __ ldrd(R0, R1, SP, 2 * kWordSize); |
| 813 // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0. | 812 // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0. |
| 814 __ ldrd(R4, R5, SP, 0 * kWordSize); | 813 __ ldrd(R2, R3, SP, 0 * kWordSize); |
| 815 __ SmiUntag(R5); | 814 __ SmiUntag(R3); |
| 816 // R0 = n ~/ _DIGIT_BITS | 815 // R4 = n ~/ _DIGIT_BITS |
| 817 __ Asr(R0, R5, Operand(5)); | 816 __ Asr(R4, R3, Operand(5)); |
| 818 // R10 = &r_digits[0] | 817 // R6 = &r_digits[0] |
| 819 __ add(R10, R4, Operand(TypedData::data_offset() - kHeapObjectTag)); | 818 __ add(R6, R2, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 820 // R7 = &x_digits[n ~/ _DIGIT_BITS] | 819 // R7 = &x_digits[n ~/ _DIGIT_BITS] |
| 821 __ add(R7, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 820 __ add(R7, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 822 __ add(R7, R7, Operand(R0, LSL, 2)); | 821 __ add(R7, R7, Operand(R4, LSL, 2)); |
| 823 // R6 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1] | 822 // R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1] |
| 824 __ add(R0, R0, Operand(1)); | 823 __ add(R4, R4, Operand(1)); |
| 825 __ rsb(R0, R0, Operand(R2, ASR, 1)); | 824 __ rsb(R4, R4, Operand(R0, ASR, 1)); |
| 826 __ add(R6, R10, Operand(R0, LSL, 2)); | 825 __ add(R8, R6, Operand(R4, LSL, 2)); |
| 827 // R3 = n % _DIGIT_BITS | 826 // R1 = n % _DIGIT_BITS |
| 828 __ and_(R3, R5, Operand(31)); | 827 __ and_(R1, R3, Operand(31)); |
| 829 // R2 = 32 - R3 | 828 // R0 = 32 - R1 |
| 830 __ rsb(R2, R3, Operand(32)); | 829 __ rsb(R0, R1, Operand(32)); |
| 831 // R1 = x_digits[n ~/ _DIGIT_BITS] >> (n % _DIGIT_BITS) | 830 // R9 = x_digits[n ~/ _DIGIT_BITS] >> (n % _DIGIT_BITS) |
| 832 __ ldr(R1, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 831 __ ldr(R9, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 833 __ mov(R1, Operand(R1, LSR, R3)); | 832 __ mov(R9, Operand(R9, LSR, R1)); |
| 834 Label loop_entry; | 833 Label loop_entry; |
| 835 __ b(&loop_entry); | 834 __ b(&loop_entry); |
| 836 Label loop; | 835 Label loop; |
| 837 __ Bind(&loop); | 836 __ Bind(&loop); |
| 838 __ ldr(R0, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); | 837 __ ldr(R4, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 839 __ orr(R1, R1, Operand(R0, LSL, R2)); | 838 __ orr(R9, R9, Operand(R4, LSL, R0)); |
| 840 __ str(R1, Address(R10, Bigint::kBytesPerDigit, Address::PostIndex)); | 839 __ str(R9, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 841 __ mov(R1, Operand(R0, LSR, R3)); | 840 __ mov(R9, Operand(R4, LSR, R1)); |
| 842 __ Bind(&loop_entry); | 841 __ Bind(&loop_entry); |
| 843 __ teq(R10, Operand(R6)); | 842 __ teq(R6, Operand(R8)); |
| 844 __ b(&loop, NE); | 843 __ b(&loop, NE); |
| 845 __ str(R1, Address(R10, 0)); | 844 __ str(R9, Address(R6, 0)); |
| 846 // Returning Object::null() is not required, since this method is private. | 845 // Returning Object::null() is not required, since this method is private. |
| 847 __ Ret(); | 846 __ Ret(); |
| 848 } | 847 } |
| 849 | 848 |
| 850 | 849 |
| 851 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { | 850 void Intrinsifier::Bigint_absAdd(Assembler* assembler) { |
| 852 // static void _absAdd(Uint32List digits, int used, | 851 // static void _absAdd(Uint32List digits, int used, |
| 853 // Uint32List a_digits, int a_used, | 852 // Uint32List a_digits, int a_used, |
| 854 // Uint32List r_digits) | 853 // Uint32List r_digits) |
| 855 | 854 |
| 856 // R2 = used, R3 = digits | 855 // R0 = used, R1 = digits |
| 857 __ ldrd(R2, R3, SP, 3 * kWordSize); | 856 __ ldrd(R0, R1, SP, 3 * kWordSize); |
| 858 // R3 = &digits[0] | 857 // R1 = &digits[0] |
| 858 __ add(R1, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | |
| 859 | |
| 860 // R2 = a_used, R3 = a_digits | |
| 861 __ ldrd(R2, R3, SP, 1 * kWordSize); | |
| 862 // R3 = &a_digits[0] | |
| 859 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 863 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 860 | 864 |
| 861 // R4 = a_used, R5 = a_digits | 865 // R8 = r_digits |
| 862 __ ldrd(R4, R5, SP, 1 * kWordSize); | 866 __ ldr(R8, Address(SP, 0 * kWordSize)); |
| 863 // R5 = &a_digits[0] | 867 // R8 = &r_digits[0] |
| 864 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); | 868 __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 865 | |
| 866 // R6 = r_digits | |
| 867 __ ldr(R6, Address(SP, 0 * kWordSize)); | |
| 868 // R6 = &r_digits[0] | |
| 869 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); | |
| 870 | 869 |
| 871 // R7 = &digits[a_used >> 1], a_used is Smi. | 870 // R7 = &digits[a_used >> 1], a_used is Smi. |
| 872 __ add(R7, R3, Operand(R4, LSL, 1)); | 871 __ add(R7, R1, Operand(R2, LSL, 1)); |
| 873 | 872 |
| 874 // R10 = &digits[used >> 1], used is Smi. | 873 // R6 = &digits[used >> 1], used is Smi. |
| 875 __ add(R10, R3, Operand(R2, LSL, 1)); | 874 __ add(R6, R1, Operand(R0, LSL, 1)); |
| 876 | 875 |
| 877 __ adds(R0, R0, Operand(0)); // carry flag = 0 | 876 __ adds(R4, R4, Operand(0)); // carry flag = 0 |
| 878 Label add_loop; | 877 Label add_loop; |
| 879 __ Bind(&add_loop); | 878 __ Bind(&add_loop); |
| 880 // Loop a_used times, a_used > 0. | 879 // Loop a_used times, a_used > 0. |
| 881 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 880 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 882 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 881 __ ldr(R9, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 883 __ adcs(R0, R0, Operand(R1)); | 882 __ adcs(R4, R4, Operand(R9)); |
| 884 __ teq(R3, Operand(R7)); // Does not affect carry flag. | 883 __ teq(R1, Operand(R7)); // Does not affect carry flag. |
| 885 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 884 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 886 __ b(&add_loop, NE); | 885 __ b(&add_loop, NE); |
| 887 | 886 |
| 888 Label last_carry; | 887 Label last_carry; |
| 889 __ teq(R3, Operand(R10)); // Does not affect carry flag. | 888 __ teq(R1, Operand(R6)); // Does not affect carry flag. |
| 890 __ b(&last_carry, EQ); // If used - a_used == 0. | 889 __ b(&last_carry, EQ); // If used - a_used == 0. |
| 891 | 890 |
| 892 Label carry_loop; | 891 Label carry_loop; |
| 893 __ Bind(&carry_loop); | 892 __ Bind(&carry_loop); |
| 894 // Loop used - a_used times, used - a_used > 0. | 893 // Loop used - a_used times, used - a_used > 0. |
| 895 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 894 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 896 __ adcs(R0, R0, Operand(0)); | 895 __ adcs(R4, R4, Operand(0)); |
| 897 __ teq(R3, Operand(R10)); // Does not affect carry flag. | 896 __ teq(R1, Operand(R6)); // Does not affect carry flag. |
| 898 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 897 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 899 __ b(&carry_loop, NE); | 898 __ b(&carry_loop, NE); |
| 900 | 899 |
| 901 __ Bind(&last_carry); | 900 __ Bind(&last_carry); |
| 902 __ mov(R0, Operand(0)); | 901 __ mov(R4, Operand(0)); |
| 903 __ adc(R0, R0, Operand(0)); | 902 __ adc(R4, R4, Operand(0)); |
| 904 __ str(R0, Address(R6, 0)); | 903 __ str(R4, Address(R8, 0)); |
| 905 | 904 |
| 906 // Returning Object::null() is not required, since this method is private. | 905 // Returning Object::null() is not required, since this method is private. |
| 907 __ Ret(); | 906 __ Ret(); |
| 908 } | 907 } |
| 909 | 908 |
| 910 | 909 |
| 911 void Intrinsifier::Bigint_absSub(Assembler* assembler) { | 910 void Intrinsifier::Bigint_absSub(Assembler* assembler) { |
| 912 // static void _absSub(Uint32List digits, int used, | 911 // static void _absSub(Uint32List digits, int used, |
| 913 // Uint32List a_digits, int a_used, | 912 // Uint32List a_digits, int a_used, |
| 914 // Uint32List r_digits) | 913 // Uint32List r_digits) |
| 915 | 914 |
| 916 // R2 = used, R3 = digits | 915 // R0 = used, R1 = digits |
| 917 __ ldrd(R2, R3, SP, 3 * kWordSize); | 916 __ ldrd(R0, R1, SP, 3 * kWordSize); |
| 918 // R3 = &digits[0] | 917 // R1 = &digits[0] |
| 918 __ add(R1, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | |
| 919 | |
| 920 // R2 = a_used, R3 = a_digits | |
| 921 __ ldrd(R2, R3, SP, 1 * kWordSize); | |
| 922 // R3 = &a_digits[0] | |
| 919 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 923 __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 920 | 924 |
| 921 // R4 = a_used, R5 = a_digits | 925 // R8 = r_digits |
| 922 __ ldrd(R4, R5, SP, 1 * kWordSize); | 926 __ ldr(R8, Address(SP, 0 * kWordSize)); |
| 923 // R5 = &a_digits[0] | 927 // R8 = &r_digits[0] |
| 924 __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag)); | 928 __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 925 | |
| 926 // R6 = r_digits | |
| 927 __ ldr(R6, Address(SP, 0 * kWordSize)); | |
| 928 // R6 = &r_digits[0] | |
| 929 __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag)); | |
| 930 | 929 |
| 931 // R7 = &digits[a_used >> 1], a_used is Smi. | 930 // R7 = &digits[a_used >> 1], a_used is Smi. |
| 932 __ add(R7, R3, Operand(R4, LSL, 1)); | 931 __ add(R7, R1, Operand(R2, LSL, 1)); |
| 933 | 932 |
| 934 // R10 = &digits[used >> 1], used is Smi. | 933 // R6 = &digits[used >> 1], used is Smi. |
| 935 __ add(R10, R3, Operand(R2, LSL, 1)); | 934 __ add(R6, R1, Operand(R0, LSL, 1)); |
| 936 | 935 |
| 937 __ subs(R0, R0, Operand(0)); // carry flag = 1 | 936 __ subs(R4, R4, Operand(0)); // carry flag = 1 |
| 938 Label sub_loop; | 937 Label sub_loop; |
| 939 __ Bind(&sub_loop); | 938 __ Bind(&sub_loop); |
| 940 // Loop a_used times, a_used > 0. | 939 // Loop a_used times, a_used > 0. |
| 941 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 940 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 942 __ ldr(R1, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 941 __ ldr(R9, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 943 __ sbcs(R0, R0, Operand(R1)); | 942 __ sbcs(R4, R4, Operand(R9)); |
| 944 __ teq(R3, Operand(R7)); // Does not affect carry flag. | 943 __ teq(R1, Operand(R7)); // Does not affect carry flag. |
| 945 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 944 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 946 __ b(&sub_loop, NE); | 945 __ b(&sub_loop, NE); |
| 947 | 946 |
| 948 Label done; | 947 Label done; |
| 949 __ teq(R3, Operand(R10)); // Does not affect carry flag. | 948 __ teq(R1, Operand(R6)); // Does not affect carry flag. |
| 950 __ b(&done, EQ); // If used - a_used == 0. | 949 __ b(&done, EQ); // If used - a_used == 0. |
| 951 | 950 |
| 952 Label carry_loop; | 951 Label carry_loop; |
| 953 __ Bind(&carry_loop); | 952 __ Bind(&carry_loop); |
| 954 // Loop used - a_used times, used - a_used > 0. | 953 // Loop used - a_used times, used - a_used > 0. |
| 955 __ ldr(R0, Address(R3, Bigint::kBytesPerDigit, Address::PostIndex)); | 954 __ ldr(R4, Address(R1, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 956 __ sbcs(R0, R0, Operand(0)); | 955 __ sbcs(R4, R4, Operand(0)); |
| 957 __ teq(R3, Operand(R10)); // Does not affect carry flag. | 956 __ teq(R1, Operand(R6)); // Does not affect carry flag. |
| 958 __ str(R0, Address(R6, Bigint::kBytesPerDigit, Address::PostIndex)); | 957 __ str(R4, Address(R8, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 959 __ b(&carry_loop, NE); | 958 __ b(&carry_loop, NE); |
| 960 | 959 |
| 961 __ Bind(&done); | 960 __ Bind(&done); |
| 962 // Returning Object::null() is not required, since this method is private. | 961 // Returning Object::null() is not required, since this method is private. |
| 963 __ Ret(); | 962 __ Ret(); |
| 964 } | 963 } |
| 965 | 964 |
| 966 | 965 |
| 967 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { | 966 void Intrinsifier::Bigint_mulAdd(Assembler* assembler) { |
| 968 // Pseudo code: | 967 // Pseudo code: |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 993 // } | 992 // } |
| 994 | 993 |
| 995 Label done; | 994 Label done; |
| 996 // R3 = x, no_op if x == 0 | 995 // R3 = x, no_op if x == 0 |
| 997 __ ldrd(R0, R1, SP, 5 * kWordSize); // R0 = xi as Smi, R1 = x_digits. | 996 __ ldrd(R0, R1, SP, 5 * kWordSize); // R0 = xi as Smi, R1 = x_digits. |
| 998 __ add(R1, R1, Operand(R0, LSL, 1)); | 997 __ add(R1, R1, Operand(R0, LSL, 1)); |
| 999 __ ldr(R3, FieldAddress(R1, TypedData::data_offset())); | 998 __ ldr(R3, FieldAddress(R1, TypedData::data_offset())); |
| 1000 __ tst(R3, Operand(R3)); | 999 __ tst(R3, Operand(R3)); |
| 1001 __ b(&done, EQ); | 1000 __ b(&done, EQ); |
| 1002 | 1001 |
| 1003 // R6 = SmiUntag(n), no_op if n == 0 | 1002 // R8 = SmiUntag(n), no_op if n == 0 |
| 1004 __ ldr(R6, Address(SP, 0 * kWordSize)); | 1003 __ ldr(R8, Address(SP, 0 * kWordSize)); |
| 1005 __ Asrs(R6, R6, Operand(kSmiTagSize)); | 1004 __ Asrs(R8, R8, Operand(kSmiTagSize)); |
| 1006 __ b(&done, EQ); | 1005 __ b(&done, EQ); |
| 1007 | 1006 |
| 1008 // R4 = mip = &m_digits[i >> 1] | 1007 // R4 = mip = &m_digits[i >> 1] |
| 1009 __ ldrd(R0, R1, SP, 3 * kWordSize); // R0 = i as Smi, R1 = m_digits. | 1008 __ ldrd(R0, R1, SP, 3 * kWordSize); // R0 = i as Smi, R1 = m_digits. |
| 1010 __ add(R1, R1, Operand(R0, LSL, 1)); | 1009 __ add(R1, R1, Operand(R0, LSL, 1)); |
| 1011 __ add(R4, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1010 __ add(R4, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 1012 | 1011 |
| 1013 // R5 = ajp = &a_digits[j >> 1] | 1012 // R9 = ajp = &a_digits[j >> 1] |
| 1014 __ ldrd(R0, R1, SP, 1 * kWordSize); // R0 = j as Smi, R1 = a_digits. | 1013 __ ldrd(R0, R1, SP, 1 * kWordSize); // R0 = j as Smi, R1 = a_digits. |
| 1015 __ add(R1, R1, Operand(R0, LSL, 1)); | 1014 __ add(R1, R1, Operand(R0, LSL, 1)); |
| 1016 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1015 __ add(R9, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 1017 | 1016 |
| 1018 // R1 = c = 0 | 1017 // R1 = c = 0 |
| 1019 __ mov(R1, Operand(0)); | 1018 __ mov(R1, Operand(0)); |
| 1020 | 1019 |
| 1021 Label muladd_loop; | 1020 Label muladd_loop; |
| 1022 __ Bind(&muladd_loop); | 1021 __ Bind(&muladd_loop); |
| 1023 // x: R3 | 1022 // x: R3 |
| 1024 // mip: R4 | 1023 // mip: R4 |
| 1025 // ajp: R5 | 1024 // ajp: R9 |
| 1026 // c: R1 | 1025 // c: R1 |
| 1027 // n: R6 | 1026 // n: R8 |
| 1028 | 1027 |
| 1029 // uint32_t mi = *mip++ | 1028 // uint32_t mi = *mip++ |
| 1030 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1029 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1031 | 1030 |
| 1032 // uint32_t aj = *ajp | 1031 // uint32_t aj = *ajp |
| 1033 __ ldr(R0, Address(R5, 0)); | 1032 __ ldr(R0, Address(R9, 0)); |
| 1034 | 1033 |
| 1035 // uint64_t t = x*mi + aj + c | 1034 // uint64_t t = x*mi + aj + c |
| 1036 __ umaal(R0, R1, R2, R3); // R1:R0 = R2*R3 + R1 + R0. | 1035 __ umaal(R0, R1, R2, R3); // R1:R0 = R2*R3 + R1 + R0. |
| 1037 | 1036 |
| 1038 // *ajp++ = low32(t) = R0 | 1037 // *ajp++ = low32(t) = R0 |
| 1039 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1038 __ str(R0, Address(R9, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1040 | 1039 |
| 1041 // c = high32(t) = R1 | 1040 // c = high32(t) = R1 |
| 1042 | 1041 |
| 1043 // while (--n > 0) | 1042 // while (--n > 0) |
| 1044 __ subs(R6, R6, Operand(1)); // --n | 1043 __ subs(R8, R8, Operand(1)); // --n |
| 1045 __ b(&muladd_loop, NE); | 1044 __ b(&muladd_loop, NE); |
| 1046 | 1045 |
| 1047 __ tst(R1, Operand(R1)); | 1046 __ tst(R1, Operand(R1)); |
| 1048 __ b(&done, EQ); | 1047 __ b(&done, EQ); |
| 1049 | 1048 |
| 1050 // *ajp++ += c | 1049 // *ajp++ += c |
| 1051 __ ldr(R0, Address(R5, 0)); | 1050 __ ldr(R0, Address(R9, 0)); |
| 1052 __ adds(R0, R0, Operand(R1)); | 1051 __ adds(R0, R0, Operand(R1)); |
| 1053 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1052 __ str(R0, Address(R9, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1054 __ b(&done, CC); | 1053 __ b(&done, CC); |
| 1055 | 1054 |
| 1056 Label propagate_carry_loop; | 1055 Label propagate_carry_loop; |
| 1057 __ Bind(&propagate_carry_loop); | 1056 __ Bind(&propagate_carry_loop); |
| 1058 __ ldr(R0, Address(R5, 0)); | 1057 __ ldr(R0, Address(R9, 0)); |
| 1059 __ adds(R0, R0, Operand(1)); | 1058 __ adds(R0, R0, Operand(1)); |
| 1060 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1059 __ str(R0, Address(R9, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1061 __ b(&propagate_carry_loop, CS); | 1060 __ b(&propagate_carry_loop, CS); |
| 1062 | 1061 |
| 1063 __ Bind(&done); | 1062 __ Bind(&done); |
| 1064 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. | 1063 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
| 1065 __ Ret(); | 1064 __ Ret(); |
| 1066 } | 1065 } |
| 1067 | 1066 |
| 1068 | 1067 |
| 1069 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { | 1068 void Intrinsifier::Bigint_sqrAdd(Assembler* assembler) { |
| 1070 // Pseudo code: | 1069 // Pseudo code: |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1097 __ 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 |
| 1098 __ add(R3, R3, Operand(R2, LSL, 1)); | 1097 __ add(R3, R3, Operand(R2, LSL, 1)); |
| 1099 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1098 __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 1100 | 1099 |
| 1101 // R3 = x = *xip++, return if x == 0 | 1100 // R3 = x = *xip++, return if x == 0 |
| 1102 Label x_zero; | 1101 Label x_zero; |
| 1103 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1102 __ ldr(R3, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1104 __ tst(R3, Operand(R3)); | 1103 __ tst(R3, Operand(R3)); |
| 1105 __ b(&x_zero, EQ); | 1104 __ b(&x_zero, EQ); |
| 1106 | 1105 |
| 1107 // R5 = ajp = &a_digits[i] | 1106 // R7 = ajp = &a_digits[i] |
| 1108 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits | 1107 __ ldr(R1, Address(SP, 1 * kWordSize)); // a_digits |
| 1109 __ 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. |
| 1110 __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); | 1109 __ add(R7, R1, Operand(TypedData::data_offset() - kHeapObjectTag)); |
| 1111 | 1110 |
| 1112 // R6:R0 = t = x*x + *ajp | 1111 // R8:R0 = t = x*x + *ajp |
| 1113 __ ldr(R0, Address(R5, 0)); | 1112 __ ldr(R0, Address(R7, 0)); |
| 1114 __ mov(R6, Operand(0)); | 1113 __ mov(R8, Operand(0)); |
| 1115 __ umaal(R0, R6, R3, R3); // R6:R0 = R3*R3 + R6 + R0. | 1114 __ umaal(R0, R8, R3, R3); // R8:R0 = R3*R3 + R8 + R0. |
| 1116 | 1115 |
| 1117 // *ajp++ = low32(t) = R0 | 1116 // *ajp++ = low32(t) = R0 |
| 1118 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1117 __ str(R0, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1119 | 1118 |
| 1120 // R6 = low32(c) = high32(t) | 1119 // R8 = low32(c) = high32(t) |
| 1121 // R7 = high32(c) = 0 | 1120 // R9 = high32(c) = 0 |
| 1122 __ mov(R7, Operand(0)); | 1121 __ mov(R9, Operand(0)); |
| 1123 | 1122 |
| 1124 // int n = used - i - 1; while (--n >= 0) ... | 1123 // int n = used - i - 1; while (--n >= 0) ... |
| 1125 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi | 1124 __ ldr(R0, Address(SP, 0 * kWordSize)); // used is Smi |
| 1126 __ sub(R10, R0, Operand(R2)); | 1125 __ sub(R6, R0, Operand(R2)); |
| 1127 __ 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) |
| 1128 __ rsbs(R10, R0, Operand(R10, ASR, kSmiTagSize)); | 1127 __ rsbs(R6, R0, Operand(R6, ASR, kSmiTagSize)); |
| 1129 | 1128 |
| 1130 Label loop, done; | 1129 Label loop, done; |
| 1131 __ b(&done, MI); | 1130 __ b(&done, MI); |
| 1132 | 1131 |
| 1133 __ Bind(&loop); | 1132 __ Bind(&loop); |
| 1134 // x: R3 | 1133 // x: R3 |
| 1135 // xip: R4 | 1134 // xip: R4 |
| 1136 // ajp: R5 | 1135 // ajp: R7 |
| 1137 // c: R7:R6 | 1136 // c: R9:R8 |
| 1138 // t: R2:R1:R0 (not live at loop entry) | 1137 // t: R2:R1:R0 (not live at loop entry) |
| 1139 // n: R10 | 1138 // n: R6 |
| 1140 | 1139 |
| 1141 // uint32_t xi = *xip++ | 1140 // uint32_t xi = *xip++ |
| 1142 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); | 1141 __ ldr(R2, Address(R4, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1143 | 1142 |
| 1144 // uint96_t t = R7:R6:R0 = 2*x*xi + aj + c | 1143 // uint96_t t = R9:R8:R0 = 2*x*xi + aj + c |
| 1145 __ umull(R0, R1, R2, R3); // R1:R0 = R2*R3. | 1144 __ umull(R0, R1, R2, R3); // R1:R0 = R2*R3. |
| 1146 __ adds(R0, R0, Operand(R0)); | 1145 __ adds(R0, R0, Operand(R0)); |
| 1147 __ adcs(R1, R1, Operand(R1)); | 1146 __ adcs(R1, R1, Operand(R1)); |
| 1148 __ mov(R2, Operand(0)); | 1147 __ mov(R2, Operand(0)); |
| 1149 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi. | 1148 __ adc(R2, R2, Operand(0)); // R2:R1:R0 = 2*x*xi. |
| 1150 __ adds(R0, R0, Operand(R6)); | 1149 __ adds(R0, R0, Operand(R8)); |
| 1151 __ adcs(R1, R1, Operand(R7)); | 1150 __ adcs(R1, R1, Operand(R9)); |
| 1152 __ 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. |
| 1153 __ ldr(R6, Address(R5, 0)); // R6 = aj = *ajp. | 1152 __ ldr(R8, Address(R7, 0)); // R8 = aj = *ajp. |
| 1154 __ adds(R0, R0, Operand(R6)); | 1153 __ adds(R0, R0, Operand(R8)); |
| 1155 __ adcs(R6, R1, Operand(0)); | 1154 __ adcs(R8, R1, Operand(0)); |
| 1156 __ adc(R7, R2, Operand(0)); // R7:R6:R0 = 2*x*xi + c + aj. | 1155 __ adc(R9, R2, Operand(0)); // R9:R8:R0 = 2*x*xi + c + aj. |
| 1157 | 1156 |
| 1158 // *ajp++ = low32(t) = R0 | 1157 // *ajp++ = low32(t) = R0 |
| 1159 __ str(R0, Address(R5, Bigint::kBytesPerDigit, Address::PostIndex)); | 1158 __ str(R0, Address(R7, Bigint::kBytesPerDigit, Address::PostIndex)); |
| 1160 | 1159 |
| 1161 // while (--n >= 0) | 1160 // while (--n >= 0) |
| 1162 __ subs(R10, R10, Operand(1)); // --n | 1161 __ subs(R6, R6, Operand(1)); // --n |
| 1163 __ b(&loop, PL); | 1162 __ b(&loop, PL); |
| 1164 | 1163 |
| 1165 __ Bind(&done); | 1164 __ Bind(&done); |
| 1166 // uint32_t aj = *ajp | 1165 // uint32_t aj = *ajp |
| 1167 __ ldr(R0, Address(R5, 0)); | 1166 __ ldr(R0, Address(R7, 0)); |
| 1168 | 1167 |
| 1169 // uint64_t t = aj + c | 1168 // uint64_t t = aj + c |
| 1170 __ adds(R6, R6, Operand(R0)); | 1169 __ adds(R8, R8, Operand(R0)); |
| 1171 __ adc(R7, R7, Operand(0)); | 1170 __ adc(R9, R9, Operand(0)); |
| 1172 | 1171 |
| 1173 // *ajp = low32(t) = R6 | 1172 // *ajp = low32(t) = R8 |
| 1174 // *(ajp + 1) = high32(t) = R7 | 1173 // *(ajp + 1) = high32(t) = R9 |
| 1175 __ strd(R6, R7, R5, 0); | 1174 __ strd(R8, R9, R7, 0); |
| 1176 | 1175 |
| 1177 __ Bind(&x_zero); | 1176 __ Bind(&x_zero); |
| 1178 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. | 1177 __ mov(R0, Operand(Smi::RawValue(1))); // One digit processed. |
| 1179 __ Ret(); | 1178 __ Ret(); |
| 1180 } | 1179 } |
| 1181 | 1180 |
| 1182 | 1181 |
| 1183 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { | 1182 void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) { |
| 1184 // No unsigned 64-bit / 32-bit divide instruction. | 1183 // No unsigned 64-bit / 32-bit divide instruction. |
| 1185 } | 1184 } |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1507 __ ldr(R1, FieldAddress(R0, state_field.Offset())); | 1506 __ ldr(R1, FieldAddress(R0, state_field.Offset())); |
| 1508 // Addresses of _state[0] and _state[1]. | 1507 // Addresses of _state[0] and _state[1]. |
| 1509 | 1508 |
| 1510 const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid); | 1509 const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid); |
| 1511 const int64_t disp_1 = disp_0 + | 1510 const int64_t disp_1 = disp_0 + |
| 1512 Instance::ElementSizeFor(kTypedDataUint32ArrayCid); | 1511 Instance::ElementSizeFor(kTypedDataUint32ArrayCid); |
| 1513 | 1512 |
| 1514 __ LoadImmediate(R0, a_int32_value); | 1513 __ LoadImmediate(R0, a_int32_value); |
| 1515 __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag); | 1514 __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag); |
| 1516 __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag); | 1515 __ LoadFromOffset(kWord, R3, R1, disp_1 - kHeapObjectTag); |
| 1517 __ mov(R6, Operand(0)); // Zero extend unsigned _state[kSTATE_HI]. | 1516 __ mov(R8, Operand(0)); // Zero extend unsigned _state[kSTATE_HI]. |
| 1518 // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3. | 1517 // Unsigned 32-bit multiply and 64-bit accumulate into R8:R3. |
| 1519 __ umlal(R3, R6, R0, R2); // R6:R3 <- R6:R3 + R0 * R2. | 1518 __ umlal(R3, R8, R0, R2); // R8:R3 <- R8:R3 + R0 * R2. |
| 1520 __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag); | 1519 __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag); |
| 1521 __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag); | 1520 __ StoreToOffset(kWord, R8, R1, disp_1 - kHeapObjectTag); |
| 1522 __ Ret(); | 1521 __ Ret(); |
| 1523 } | 1522 } |
| 1524 | 1523 |
| 1525 | 1524 |
| 1526 void Intrinsifier::ObjectEquals(Assembler* assembler) { | 1525 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
| 1527 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1526 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 1528 __ ldr(R1, Address(SP, 1 * kWordSize)); | 1527 __ ldr(R1, Address(SP, 1 * kWordSize)); |
| 1529 __ cmp(R0, Operand(R1)); | 1528 __ cmp(R0, Operand(R1)); |
| 1530 __ LoadObject(R0, Bool::False(), NE); | 1529 __ LoadObject(R0, Bool::False(), NE); |
| 1531 __ LoadObject(R0, Bool::True(), EQ); | 1530 __ LoadObject(R0, Bool::True(), EQ); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1657 | 1656 |
| 1658 __ ldr(R2, FieldAddress(R1, String::length_offset())); | 1657 __ ldr(R2, FieldAddress(R1, String::length_offset())); |
| 1659 | 1658 |
| 1660 Label done; | 1659 Label done; |
| 1661 // If the string is empty, set the hash to 1, and return. | 1660 // If the string is empty, set the hash to 1, and return. |
| 1662 __ cmp(R2, Operand(Smi::RawValue(0))); | 1661 __ cmp(R2, Operand(Smi::RawValue(0))); |
| 1663 __ b(&done, EQ); | 1662 __ b(&done, EQ); |
| 1664 | 1663 |
| 1665 __ SmiUntag(R2); | 1664 __ SmiUntag(R2); |
| 1666 __ mov(R3, Operand(0)); | 1665 __ mov(R3, Operand(0)); |
| 1667 __ AddImmediate(R6, R1, OneByteString::data_offset() - kHeapObjectTag); | 1666 __ AddImmediate(R8, R1, OneByteString::data_offset() - kHeapObjectTag); |
| 1668 // R1: Instance of OneByteString. | 1667 // R1: Instance of OneByteString. |
| 1669 // R2: String length, untagged integer. | 1668 // R2: String length, untagged integer. |
| 1670 // R3: Loop counter, untagged integer. | 1669 // R3: Loop counter, untagged integer. |
| 1671 // R6: String data. | 1670 // R8: String data. |
| 1672 // R0: Hash code, untagged integer. | 1671 // R0: Hash code, untagged integer. |
| 1673 | 1672 |
| 1674 Label loop; | 1673 Label loop; |
| 1675 // Add to hash code: (hash_ is uint32) | 1674 // Add to hash code: (hash_ is uint32) |
| 1676 // hash_ += ch; | 1675 // hash_ += ch; |
| 1677 // hash_ += hash_ << 10; | 1676 // hash_ += hash_ << 10; |
| 1678 // hash_ ^= hash_ >> 6; | 1677 // hash_ ^= hash_ >> 6; |
| 1679 // Get one characters (ch). | 1678 // Get one characters (ch). |
| 1680 __ Bind(&loop); | 1679 __ Bind(&loop); |
| 1681 __ ldrb(R7, Address(R6, 0)); | 1680 __ ldrb(R7, Address(R8, 0)); |
| 1682 // R7: ch. | 1681 // R7: ch. |
| 1683 __ add(R3, R3, Operand(1)); | 1682 __ add(R3, R3, Operand(1)); |
| 1684 __ add(R6, R6, Operand(1)); | 1683 __ add(R8, R8, Operand(1)); |
| 1685 __ add(R0, R0, Operand(R7)); | 1684 __ add(R0, R0, Operand(R7)); |
| 1686 __ add(R0, R0, Operand(R0, LSL, 10)); | 1685 __ add(R0, R0, Operand(R0, LSL, 10)); |
| 1687 __ eor(R0, R0, Operand(R0, LSR, 6)); | 1686 __ eor(R0, R0, Operand(R0, LSR, 6)); |
| 1688 __ cmp(R3, Operand(R2)); | 1687 __ cmp(R3, Operand(R2)); |
| 1689 __ b(&loop, NE); | 1688 __ b(&loop, NE); |
| 1690 | 1689 |
| 1691 // Finalize. | 1690 // Finalize. |
| 1692 // hash_ += hash_ << 3; | 1691 // hash_ += hash_ << 3; |
| 1693 // hash_ ^= hash_ >> 11; | 1692 // hash_ ^= hash_ >> 11; |
| 1694 // hash_ += hash_ << 15; | 1693 // hash_ += hash_ << 15; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1712 // initialized. | 1711 // initialized. |
| 1713 // 'length-reg' (R2) contains tagged length. | 1712 // 'length-reg' (R2) contains tagged length. |
| 1714 // Returns new string as tagged pointer in R0. | 1713 // Returns new string as tagged pointer in R0. |
| 1715 static void TryAllocateOnebyteString(Assembler* assembler, | 1714 static void TryAllocateOnebyteString(Assembler* assembler, |
| 1716 Label* ok, | 1715 Label* ok, |
| 1717 Label* failure) { | 1716 Label* failure) { |
| 1718 const Register length_reg = R2; | 1717 const Register length_reg = R2; |
| 1719 Label fail; | 1718 Label fail; |
| 1720 __ MaybeTraceAllocation(kOneByteStringCid, R0, failure, | 1719 __ MaybeTraceAllocation(kOneByteStringCid, R0, failure, |
| 1721 /* inline_isolate = */ false); | 1720 /* inline_isolate = */ false); |
| 1722 __ mov(R6, Operand(length_reg)); // Save the length register. | 1721 __ mov(R8, Operand(length_reg)); // Save the length register. |
| 1723 // TODO(koda): Protect against negative length and overflow here. | 1722 // TODO(koda): Protect against negative length and overflow here. |
| 1724 __ SmiUntag(length_reg); | 1723 __ SmiUntag(length_reg); |
| 1725 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; | 1724 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; |
| 1726 __ AddImmediate(length_reg, fixed_size); | 1725 __ AddImmediate(length_reg, fixed_size); |
| 1727 __ bic(length_reg, length_reg, Operand(kObjectAlignment - 1)); | 1726 __ bic(length_reg, length_reg, Operand(kObjectAlignment - 1)); |
| 1728 | 1727 |
| 1729 const intptr_t cid = kOneByteStringCid; | 1728 const intptr_t cid = kOneByteStringCid; |
| 1730 Heap::Space space = Heap::SpaceForAllocation(cid); | 1729 Heap::Space space = Heap::SpaceForAllocation(cid); |
| 1731 __ ldr(R3, Address(THR, Thread::heap_offset())); | 1730 __ ldr(R3, Address(THR, Thread::heap_offset())); |
| 1732 __ ldr(R0, Address(R3, Heap::TopOffset(space))); | 1731 __ ldr(R0, Address(R3, Heap::TopOffset(space))); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1762 __ mov(R3, Operand(R2, LSL, shift), LS); | 1761 __ mov(R3, Operand(R2, LSL, shift), LS); |
| 1763 __ mov(R3, Operand(0), HI); | 1762 __ mov(R3, Operand(0), HI); |
| 1764 | 1763 |
| 1765 // Get the class index and insert it into the tags. | 1764 // Get the class index and insert it into the tags. |
| 1766 // R3: size and bit tags. | 1765 // R3: size and bit tags. |
| 1767 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); | 1766 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); |
| 1768 __ orr(R3, R3, Operand(TMP)); | 1767 __ orr(R3, R3, Operand(TMP)); |
| 1769 __ str(R3, FieldAddress(R0, String::tags_offset())); // Store tags. | 1768 __ str(R3, FieldAddress(R0, String::tags_offset())); // Store tags. |
| 1770 } | 1769 } |
| 1771 | 1770 |
| 1772 // Set the length field using the saved length (R6). | 1771 // Set the length field using the saved length (R8). |
| 1773 __ InitializeFieldNoBarrier(R0, | 1772 __ InitializeFieldNoBarrier(R0, |
| 1774 FieldAddress(R0, String::length_offset()), | 1773 FieldAddress(R0, String::length_offset()), |
| 1775 R6); | 1774 R8); |
| 1776 // Clear hash. | 1775 // Clear hash. |
| 1777 __ LoadImmediate(TMP, 0); | 1776 __ LoadImmediate(TMP, 0); |
| 1778 __ InitializeFieldNoBarrier(R0, | 1777 __ InitializeFieldNoBarrier(R0, |
| 1779 FieldAddress(R0, String::hash_offset()), | 1778 FieldAddress(R0, String::hash_offset()), |
| 1780 TMP); | 1779 TMP); |
| 1781 | 1780 |
| 1782 __ IncrementAllocationStatsWithSize(R4, R2, space); | 1781 __ IncrementAllocationStatsWithSize(R4, R2, space); |
| 1783 __ b(ok); | 1782 __ b(ok); |
| 1784 | 1783 |
| 1785 __ Bind(&fail); | 1784 __ Bind(&fail); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1817 | 1816 |
| 1818 // R3: Start address to copy from (untagged). | 1817 // R3: Start address to copy from (untagged). |
| 1819 // R1: Untagged start index. | 1818 // R1: Untagged start index. |
| 1820 __ ldr(R2, Address(SP, kEndIndexOffset)); | 1819 __ ldr(R2, Address(SP, kEndIndexOffset)); |
| 1821 __ SmiUntag(R2); | 1820 __ SmiUntag(R2); |
| 1822 __ sub(R2, R2, Operand(R1)); | 1821 __ sub(R2, R2, Operand(R1)); |
| 1823 | 1822 |
| 1824 // R3: Start address to copy from (untagged). | 1823 // R3: Start address to copy from (untagged). |
| 1825 // R2: Untagged number of bytes to copy. | 1824 // R2: Untagged number of bytes to copy. |
| 1826 // R0: Tagged result string. | 1825 // R0: Tagged result string. |
| 1827 // R6: Pointer into R3. | 1826 // R8: Pointer into R3. |
| 1828 // R7: Pointer into R0. | 1827 // R7: Pointer into R0. |
| 1829 // R1: Scratch register. | 1828 // R1: Scratch register. |
| 1830 Label loop, done; | 1829 Label loop, done; |
| 1831 __ cmp(R2, Operand(0)); | 1830 __ cmp(R2, Operand(0)); |
| 1832 __ b(&done, LE); | 1831 __ b(&done, LE); |
| 1833 __ mov(R6, Operand(R3)); | 1832 __ mov(R8, Operand(R3)); |
| 1834 __ mov(R7, Operand(R0)); | 1833 __ mov(R7, Operand(R0)); |
| 1835 __ Bind(&loop); | 1834 __ Bind(&loop); |
| 1836 __ ldrb(R1, Address(R6, 0)); | 1835 __ ldrb(R1, Address(R8, 0)); |
| 1837 __ AddImmediate(R6, 1); | 1836 __ AddImmediate(R8, 1); |
| 1838 __ sub(R2, R2, Operand(1)); | 1837 __ sub(R2, R2, Operand(1)); |
| 1839 __ cmp(R2, Operand(0)); | 1838 __ cmp(R2, Operand(0)); |
| 1840 __ strb(R1, FieldAddress(R7, OneByteString::data_offset())); | 1839 __ strb(R1, FieldAddress(R7, OneByteString::data_offset())); |
| 1841 __ AddImmediate(R7, 1); | 1840 __ AddImmediate(R7, 1); |
| 1842 __ b(&loop, GT); | 1841 __ b(&loop, GT); |
| 1843 | 1842 |
| 1844 __ Bind(&done); | 1843 __ Bind(&done); |
| 1845 __ Ret(); | 1844 __ Ret(); |
| 1846 __ Bind(&fall_through); | 1845 __ Bind(&fall_through); |
| 1847 } | 1846 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1948 void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) { | 1947 void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) { |
| 1949 if (FLAG_interpret_irregexp) return; | 1948 if (FLAG_interpret_irregexp) return; |
| 1950 | 1949 |
| 1951 static const intptr_t kRegExpParamOffset = 2 * kWordSize; | 1950 static const intptr_t kRegExpParamOffset = 2 * kWordSize; |
| 1952 static const intptr_t kStringParamOffset = 1 * kWordSize; | 1951 static const intptr_t kStringParamOffset = 1 * kWordSize; |
| 1953 // start_index smi is located at offset 0. | 1952 // start_index smi is located at offset 0. |
| 1954 | 1953 |
| 1955 // Incoming registers: | 1954 // Incoming registers: |
| 1956 // R0: Function. (Will be reloaded with the specialized matcher function.) | 1955 // R0: Function. (Will be reloaded with the specialized matcher function.) |
| 1957 // R4: Arguments descriptor. (Will be preserved.) | 1956 // R4: Arguments descriptor. (Will be preserved.) |
| 1958 // R5: Unknown. (Must be GC safe on tail call.) | 1957 // R9: Unknown. (Must be GC safe on tail call.) |
| 1959 | 1958 |
| 1960 // Load the specialized function pointer into R0. Leverage the fact the | 1959 // Load the specialized function pointer into R0. Leverage the fact the |
| 1961 // string CIDs as well as stored function pointers are in sequence. | 1960 // string CIDs as well as stored function pointers are in sequence. |
| 1962 __ ldr(R2, Address(SP, kRegExpParamOffset)); | 1961 __ ldr(R2, Address(SP, kRegExpParamOffset)); |
| 1963 __ ldr(R1, Address(SP, kStringParamOffset)); | 1962 __ ldr(R1, Address(SP, kStringParamOffset)); |
| 1964 __ LoadClassId(R1, R1); | 1963 __ LoadClassId(R1, R1); |
| 1965 __ AddImmediate(R1, R1, -kOneByteStringCid); | 1964 __ AddImmediate(R1, R1, -kOneByteStringCid); |
| 1966 __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2)); | 1965 __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2)); |
| 1967 __ ldr(R0, FieldAddress(R1, JSRegExp::function_offset(kOneByteStringCid))); | 1966 __ ldr(R0, FieldAddress(R1, JSRegExp::function_offset(kOneByteStringCid))); |
| 1968 | 1967 |
| 1969 // Registers are now set up for the lazy compile stub. It expects the function | 1968 // Registers are now set up for the lazy compile stub. It expects the function |
| 1970 // in R0, the argument descriptor in R4, and IC-Data in R5. | 1969 // in R0, the argument descriptor in R4, and IC-Data in R9. |
| 1971 __ eor(R5, R5, Operand(R5)); | 1970 __ eor(R9, R9, Operand(R9)); |
| 1972 | 1971 |
| 1973 // Tail-call the function. | 1972 // Tail-call the function. |
| 1974 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 1973 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 1975 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); | 1974 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
| 1976 __ bx(R1); | 1975 __ bx(R1); |
| 1977 } | 1976 } |
| 1978 | 1977 |
| 1979 | 1978 |
| 1980 // On stack: user tag (+0). | 1979 // On stack: user tag (+0). |
| 1981 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) { | 1980 void Intrinsifier::UserTag_makeCurrent(Assembler* assembler) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 2004 | 2003 |
| 2005 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { | 2004 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { |
| 2006 __ LoadIsolate(R0); | 2005 __ LoadIsolate(R0); |
| 2007 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); | 2006 __ ldr(R0, Address(R0, Isolate::current_tag_offset())); |
| 2008 __ Ret(); | 2007 __ Ret(); |
| 2009 } | 2008 } |
| 2010 | 2009 |
| 2011 } // namespace dart | 2010 } // namespace dart |
| 2012 | 2011 |
| 2013 #endif // defined TARGET_ARCH_ARM | 2012 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |