Index: runtime/vm/intrinsifier_ia32.cc |
=================================================================== |
--- runtime/vm/intrinsifier_ia32.cc (revision 45179) |
+++ runtime/vm/intrinsifier_ia32.cc (working copy) |
@@ -26,6 +26,13 @@ |
DECLARE_FLAG(bool, enable_type_checks); |
+// When entering intrinsics code: |
+// ECX: IC Data |
+// EDX: Arguments descriptor |
+// TOS: Return address |
+// The ECX, EDX registers can be destroyed only if there is no slow-path, i.e. |
+// if the intrinsified method always executes a return. |
+// The EBP register should not be modified, because it is used by the profiler. |
#define __ assembler-> |
@@ -572,7 +579,7 @@ |
__ movl(EAX, EBX); |
__ shll(EBX, ECX); |
__ xorl(EDI, EDI); |
- __ shldl(EDI, EAX); |
+ __ shldl(EDI, EAX, ECX); |
// Result in EDI (high) and EBX (low). |
const Class& mint_class = Class::Handle( |
Isolate::Current()->object_store()->mint_class()); |
@@ -806,12 +813,80 @@ |
void Intrinsifier::Bigint_lsh(Assembler* assembler) { |
- // TODO(regis): Implement. |
+ // static void _lsh(Uint32List x_digits, int x_used, int n, |
+ // Uint32List r_digits) |
+ |
+ __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits |
+ __ movl(ECX, Address(ESP, 2 * kWordSize)); // n is Smi |
+ __ SmiUntag(ECX); |
+ __ movl(EBX, Address(ESP, 1 * kWordSize)); // r_digits |
+ __ movl(ESI, ECX); |
+ __ sarl(ESI, Immediate(5)); // ESI = n ~/ _DIGIT_BITS. |
+ __ leal(EBX, FieldAddress(EBX, ESI, TIMES_4, TypedData::data_offset())); |
+ __ movl(ESI, Address(ESP, 3 * kWordSize)); // x_used > 0, Smi. |
+ __ SmiUntag(ESI); |
+ __ decl(ESI); |
+ __ xorl(EAX, EAX); // EAX = 0. |
+ __ movl(EDX, FieldAddress(EDI, ESI, TIMES_4, TypedData::data_offset())); |
+ __ shldl(EAX, EDX, ECX); |
+ __ movl(Address(EBX, ESI, TIMES_4, Bigint::kBytesPerDigit), EAX); |
+ Label last; |
+ __ cmpl(ESI, Immediate(0)); |
+ __ j(EQUAL, &last, Assembler::kNearJump); |
+ Label loop; |
+ __ Bind(&loop); |
+ __ movl(EAX, EDX); |
+ __ movl(EDX, |
+ FieldAddress(EDI, ESI, TIMES_4, |
+ TypedData::data_offset() - Bigint::kBytesPerDigit)); |
+ __ shldl(EAX, EDX, ECX); |
+ __ movl(Address(EBX, ESI, TIMES_4, 0), EAX); |
+ __ decl(ESI); |
+ __ j(NOT_ZERO, &loop, Assembler::kNearJump); |
+ __ Bind(&last); |
+ __ shldl(EDX, ESI, ECX); // ESI == 0. |
+ __ movl(Address(EBX, 0), EDX); |
+ // Returning Object::null() is not required, since this method is private. |
+ __ ret(); |
} |
void Intrinsifier::Bigint_rsh(Assembler* assembler) { |
- // TODO(regis): Implement. |
+ // static void _rsh(Uint32List x_digits, int x_used, int n, |
+ // Uint32List r_digits) |
+ |
+ __ movl(EDI, Address(ESP, 4 * kWordSize)); // x_digits |
+ __ movl(ECX, Address(ESP, 2 * kWordSize)); // n is Smi |
+ __ SmiUntag(ECX); |
+ __ movl(EBX, Address(ESP, 1 * kWordSize)); // r_digits |
+ __ movl(EDX, ECX); |
+ __ sarl(EDX, Immediate(5)); // EDX = n ~/ _DIGIT_BITS. |
+ __ movl(ESI, Address(ESP, 3 * kWordSize)); // x_used > 0, Smi. |
+ __ SmiUntag(ESI); |
+ __ decl(ESI); |
+ // EDI = &x_digits[x_used - 1]. |
+ __ leal(EDI, FieldAddress(EDI, ESI, TIMES_4, TypedData::data_offset())); |
+ __ subl(ESI, EDX); |
+ // EBX = &r_digits[x_used - 1 - (n ~/ 32)]. |
+ __ leal(EBX, FieldAddress(EBX, ESI, TIMES_4, TypedData::data_offset())); |
+ __ negl(ESI); |
+ __ movl(EDX, Address(EDI, ESI, TIMES_4, 0)); |
+ Label last; |
+ __ cmpl(ESI, Immediate(0)); |
+ __ j(EQUAL, &last, Assembler::kNearJump); |
+ Label loop; |
+ __ Bind(&loop); |
+ __ movl(EAX, EDX); |
+ __ movl(EDX, Address(EDI, ESI, TIMES_4, Bigint::kBytesPerDigit)); |
+ __ shrdl(EAX, EDX, ECX); |
+ __ movl(Address(EBX, ESI, TIMES_4, 0), EAX); |
+ __ incl(ESI); |
+ __ j(NOT_ZERO, &loop, Assembler::kNearJump); |
+ __ Bind(&last); |
+ __ shrdl(EDX, ESI, ECX); // ESI == 0. |
+ __ movl(Address(EBX, 0), EDX); |
+ // Returning Object::null() is not required, since this method is private. |
+ __ ret(); |
} |