Index: runtime/vm/intrinsifier_x64.cc |
=================================================================== |
--- runtime/vm/intrinsifier_x64.cc (revision 44828) |
+++ runtime/vm/intrinsifier_x64.cc (working copy) |
@@ -725,6 +725,84 @@ |
} |
+void Intrinsifier::Bigint_lsh(Assembler* assembler) { |
+ // static void _lsh(Uint32List x_digits, int x_used, int n, |
+ // Uint32List r_digits) |
+ |
+ __ movq(RDI, Address(RSP, 4 * kWordSize)); // x_digits |
+ __ movq(R8, Address(RSP, 3 * kWordSize)); // x_used is Smi |
+ __ subq(R8, Immediate(2)); // x_used > 0, Smi. R8 = x_used - 1, round up. |
+ __ sarq(R8, Immediate(2)); // R8 + 1 = number of digit pairs to read. |
+ __ movq(RCX, Address(RSP, 2 * kWordSize)); // n is Smi |
+ __ SmiUntag(RCX); |
+ __ movq(RBX, Address(RSP, 1 * kWordSize)); // r_digits |
+ __ movq(RSI, RCX); |
+ __ sarq(RSI, Immediate(6)); // RSI = n ~/ (2*_DIGIT_BITS). |
+ __ leaq(RBX, FieldAddress(RBX, RSI, TIMES_8, TypedData::data_offset())); |
+ __ xorq(RAX, RAX); // RAX = 0. |
+ __ movq(RDX, FieldAddress(RDI, R8, TIMES_8, TypedData::data_offset())); |
+ __ shldq(RAX, RDX, RCX); |
+ __ movq(Address(RBX, R8, TIMES_8, 2 * Bigint::kBytesPerDigit), RAX); |
+ Label last; |
+ __ cmpq(R8, Immediate(0)); |
+ __ j(EQUAL, &last, Assembler::kNearJump); |
+ Label loop; |
+ __ Bind(&loop); |
+ __ movq(RAX, RDX); |
+ __ movq(RDX, |
+ FieldAddress(RDI, R8, TIMES_8, |
+ TypedData::data_offset() - 2 * Bigint::kBytesPerDigit)); |
+ __ shldq(RAX, RDX, RCX); |
+ __ movq(Address(RBX, R8, TIMES_8, 0), RAX); |
+ __ decq(R8); |
+ __ j(NOT_ZERO, &loop, Assembler::kNearJump); |
+ __ Bind(&last); |
+ __ xorq(RAX, RAX); // RAX = 0. |
+ __ shldq(RDX, RAX, RCX); |
+ __ movq(Address(RBX, 0), RDX); |
+ // Returning Object::null() is not required, since this method is private. |
+ __ ret(); |
+} |
+ |
+ |
+void Intrinsifier::Bigint_rsh(Assembler* assembler) { |
+ // static void _rsh(Uint32List x_digits, int x_used, int n, |
+ // Uint32List r_digits) |
+ |
+ __ movq(RDI, Address(RSP, 4 * kWordSize)); // x_digits |
+ __ movq(R8, Address(RSP, 3 * kWordSize)); // x_used is Smi |
+ __ subq(R8, Immediate(2)); // x_used > 0, Smi. R8 = x_used - 1, round up. |
+ __ sarq(R8, Immediate(2)); |
+ __ movq(RCX, Address(RSP, 2 * kWordSize)); // n is Smi |
+ __ SmiUntag(RCX); |
+ __ movq(RBX, Address(RSP, 1 * kWordSize)); // r_digits |
+ __ movq(RSI, RCX); |
+ __ sarq(RSI, Immediate(6)); // RSI = n ~/ (2*_DIGIT_BITS). |
+ __ leaq(RDI, FieldAddress(RDI, RSI, TIMES_8, TypedData::data_offset())); |
+ __ movq(RDX, Address(RDI, 0)); |
+ __ subq(R8, RSI); // R8 + 1 = number of digit pairs to read. |
+ Label last; |
+ __ cmpq(R8, Immediate(0)); |
+ __ j(EQUAL, &last, Assembler::kNearJump); |
+ __ xorq(R9, R9); // R9 = 0. |
+ Label loop; |
+ __ Bind(&loop); |
+ __ movq(RAX, RDX); |
+ __ movq(RDX, Address(RDI, R9, TIMES_8, 2 * Bigint::kBytesPerDigit)); |
+ __ shrdq(RAX, RDX, RCX); |
+ __ movq(FieldAddress(RBX, R9, TIMES_8, TypedData::data_offset()), RAX); |
+ __ incq(R9); |
+ __ cmpq(R9, R8); |
+ __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
+ __ Bind(&last); |
+ __ xorq(RAX, RAX); // RAX = 0. |
+ __ shrdq(RDX, RAX, RCX); |
+ __ movq(FieldAddress(RBX, R8, TIMES_8, TypedData::data_offset()), RDX); |
+ // Returning Object::null() is not required, since this method is private. |
+ __ ret(); |
+} |
+ |
+ |
void Intrinsifier::Bigint_absAdd(Assembler* assembler) { |
// static void _absAdd(Uint32List digits, int used, |
// Uint32List a_digits, int a_used, |