OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 4385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4396 | 4396 |
4397 const char* GetName() { return "ConvertToDoubleStub"; } | 4397 const char* GetName() { return "ConvertToDoubleStub"; } |
4398 | 4398 |
4399 #ifdef DEBUG | 4399 #ifdef DEBUG |
4400 void Print() { PrintF("ConvertToDoubleStub\n"); } | 4400 void Print() { PrintF("ConvertToDoubleStub\n"); } |
4401 #endif | 4401 #endif |
4402 }; | 4402 }; |
4403 | 4403 |
4404 | 4404 |
4405 void ConvertToDoubleStub::Generate(MacroAssembler* masm) { | 4405 void ConvertToDoubleStub::Generate(MacroAssembler* masm) { |
4406 Label not_special, done; | 4406 #ifndef BIG_ENDIAN_FLOATING_POINT |
| 4407 Register exponent = result1_; |
| 4408 Register mantissa = result2_; |
| 4409 #else |
| 4410 Register exponent = result2_; |
| 4411 Register mantissa = result1_; |
| 4412 #endif |
| 4413 Label not_special; |
4407 // Convert from Smi to integer. | 4414 // Convert from Smi to integer. |
4408 __ mov(source_, Operand(source_, ASR, kSmiTagSize)); | 4415 __ mov(source_, Operand(source_, ASR, kSmiTagSize)); |
4409 // Move sign bit from source to destination. This works because the sign bit | 4416 // Move sign bit from source to destination. This works because the sign bit |
4410 // in the exponent word of the double has the same position and polarity as | 4417 // in the exponent word of the double has the same position and polarity as |
4411 // the 2's complement sign bit in a Smi. | 4418 // the 2's complement sign bit in a Smi. |
4412 ASSERT(HeapNumber::kSignMask == 0x80000000u); | 4419 ASSERT(HeapNumber::kSignMask == 0x80000000u); |
4413 __ and_(result1_, source_, Operand(HeapNumber::kSignMask), SetCC); | 4420 __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC); |
4414 // Subtract from 0 if source was negative. | 4421 // Subtract from 0 if source was negative. |
4415 __ rsb(source_, source_, Operand(0), LeaveCC, ne); | 4422 __ rsb(source_, source_, Operand(0), LeaveCC, ne); |
4416 __ cmp(source_, Operand(1)); | 4423 __ cmp(source_, Operand(1)); |
4417 __ b(gt, ¬_special); | 4424 __ b(gt, ¬_special); |
4418 | 4425 |
4419 // We have -1, 0 or 1, which we treat specially. | 4426 // We have -1, 0 or 1, which we treat specially. |
4420 __ cmp(source_, Operand(0)); | 4427 __ cmp(source_, Operand(0)); |
4421 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). | 4428 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). |
4422 static const uint32_t exponent_word_for_1 = | 4429 static const uint32_t exponent_word_for_1 = |
4423 HeapNumber::kExponentBias << HeapNumber::kExponentShift; | 4430 HeapNumber::kExponentBias << HeapNumber::kExponentShift; |
4424 __ orr(result1_, result1_, Operand(exponent_word_for_1), LeaveCC, ne); | 4431 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, ne); |
4425 // 1, 0 and -1 all have 0 for the second word. | 4432 // 1, 0 and -1 all have 0 for the second word. |
4426 __ mov(result2_, Operand(0)); | 4433 __ mov(mantissa, Operand(0)); |
4427 __ jmp(&done); | 4434 __ Ret(); |
4428 | 4435 |
4429 __ bind(¬_special); | 4436 __ bind(¬_special); |
4430 // Count leading zeros. Uses result2 for a scratch register on pre-ARM5. | 4437 // Count leading zeros. Uses result2 for a scratch register on pre-ARM5. |
4431 // Gets the wrong answer for 0, but we already checked for that case above. | 4438 // Gets the wrong answer for 0, but we already checked for that case above. |
4432 CountLeadingZeros(masm, source_, result2_, zeros_); | 4439 CountLeadingZeros(masm, source_, mantissa, zeros_); |
4433 // Compute exponent and or it into the exponent register. | 4440 // Compute exponent and or it into the exponent register. |
4434 // We use result2 as a scratch register here. | 4441 // We use result2 as a scratch register here. |
4435 __ rsb(result2_, zeros_, Operand(31 + HeapNumber::kExponentBias)); | 4442 __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias)); |
4436 __ orr(result1_, | 4443 __ orr(exponent, |
4437 result1_, | 4444 exponent, |
4438 Operand(result2_, LSL, HeapNumber::kExponentShift)); | 4445 Operand(mantissa, LSL, HeapNumber::kExponentShift)); |
4439 // Shift up the source chopping the top bit off. | 4446 // Shift up the source chopping the top bit off. |
4440 __ add(zeros_, zeros_, Operand(1)); | 4447 __ add(zeros_, zeros_, Operand(1)); |
4441 // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. | 4448 // This wouldn't work for 1.0 or -1.0 as the shift would be 32 which means 0. |
4442 __ mov(source_, Operand(source_, LSL, zeros_)); | 4449 __ mov(source_, Operand(source_, LSL, zeros_)); |
4443 // Compute lower part of fraction (last 12 bits). | 4450 // Compute lower part of fraction (last 12 bits). |
4444 __ mov(result2_, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord)); | 4451 __ mov(mantissa, Operand(source_, LSL, HeapNumber::kMantissaBitsInTopWord)); |
4445 // And the top (top 20 bits). | 4452 // And the top (top 20 bits). |
4446 __ orr(result1_, | 4453 __ orr(exponent, |
4447 result1_, | 4454 exponent, |
4448 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); | 4455 Operand(source_, LSR, 32 - HeapNumber::kMantissaBitsInTopWord)); |
4449 __ bind(&done); | |
4450 __ Ret(); | 4456 __ Ret(); |
4451 } | 4457 } |
4452 | 4458 |
4453 | 4459 |
4454 // This stub can convert a signed int32 to a heap number (double). It does | 4460 // This stub can convert a signed int32 to a heap number (double). It does |
4455 // not work for int32s that are in Smi range! No GC occurs during this stub | 4461 // not work for int32s that are in Smi range! No GC occurs during this stub |
4456 // so you don't have to set up the frame. | 4462 // so you don't have to set up the frame. |
4457 class WriteInt32ToHeapNumberStub : public CodeStub { | 4463 class WriteInt32ToHeapNumberStub : public CodeStub { |
4458 public: | 4464 public: |
4459 WriteInt32ToHeapNumberStub(Register the_int, | 4465 WriteInt32ToHeapNumberStub(Register the_int, |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4620 | 4626 |
4621 // Move r0 to a double in r2-r3. | 4627 // Move r0 to a double in r2-r3. |
4622 __ tst(r0, Operand(kSmiTagMask)); | 4628 __ tst(r0, Operand(kSmiTagMask)); |
4623 __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. | 4629 __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. |
4624 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); | 4630 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); |
4625 __ b(ne, &slow); | 4631 __ b(ne, &slow); |
4626 if (mode == OVERWRITE_RIGHT) { | 4632 if (mode == OVERWRITE_RIGHT) { |
4627 __ mov(r5, Operand(r0)); // Overwrite this heap number. | 4633 __ mov(r5, Operand(r0)); // Overwrite this heap number. |
4628 } | 4634 } |
4629 // Calling convention says that second double is in r2 and r3. | 4635 // Calling convention says that second double is in r2 and r3. |
4630 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | 4636 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kValueOffset)); |
4631 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | 4637 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kValueOffset + 4)); |
4632 __ jmp(&finished_loading_r0); | 4638 __ jmp(&finished_loading_r0); |
4633 __ bind(&r0_is_smi); | 4639 __ bind(&r0_is_smi); |
4634 if (mode == OVERWRITE_RIGHT) { | 4640 if (mode == OVERWRITE_RIGHT) { |
4635 // We can't overwrite a Smi so get address of new heap number into r5. | 4641 // We can't overwrite a Smi so get address of new heap number into r5. |
4636 AllocateHeapNumber(masm, &slow, r5, r6, r7); | 4642 AllocateHeapNumber(masm, &slow, r5, r6, r7); |
4637 } | 4643 } |
4638 // Write Smi from r0 to r3 and r2 in double format. | 4644 // Write Smi from r0 to r3 and r2 in double format. |
4639 __ mov(r7, Operand(r0)); | 4645 __ mov(r7, Operand(r0)); |
4640 ConvertToDoubleStub stub3(r3, r2, r7, r6); | 4646 ConvertToDoubleStub stub3(r3, r2, r7, r6); |
4641 __ push(lr); | 4647 __ push(lr); |
4642 __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET); | 4648 __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET); |
4643 __ pop(lr); | 4649 __ pop(lr); |
4644 __ bind(&finished_loading_r0); | 4650 __ bind(&finished_loading_r0); |
4645 | 4651 |
4646 // Move r1 to a double in r0-r1. | 4652 // Move r1 to a double in r0-r1. |
4647 __ tst(r1, Operand(kSmiTagMask)); | 4653 __ tst(r1, Operand(kSmiTagMask)); |
4648 __ b(eq, &r1_is_smi); // It's a Smi so don't check it's a heap number. | 4654 __ b(eq, &r1_is_smi); // It's a Smi so don't check it's a heap number. |
4649 __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE); | 4655 __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE); |
4650 __ b(ne, &slow); | 4656 __ b(ne, &slow); |
4651 if (mode == OVERWRITE_LEFT) { | 4657 if (mode == OVERWRITE_LEFT) { |
4652 __ mov(r5, Operand(r1)); // Overwrite this heap number. | 4658 __ mov(r5, Operand(r1)); // Overwrite this heap number. |
4653 } | 4659 } |
4654 // Calling convention says that first double is in r0 and r1. | 4660 // Calling convention says that first double is in r0 and r1. |
4655 __ ldr(r0, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); | 4661 __ ldr(r0, FieldMemOperand(r1, HeapNumber::kValueOffset)); |
4656 __ ldr(r1, FieldMemOperand(r1, HeapNumber::kExponentOffset)); | 4662 __ ldr(r1, FieldMemOperand(r1, HeapNumber::kValueOffset + 4)); |
4657 __ jmp(&finished_loading_r1); | 4663 __ jmp(&finished_loading_r1); |
4658 __ bind(&r1_is_smi); | 4664 __ bind(&r1_is_smi); |
4659 if (mode == OVERWRITE_LEFT) { | 4665 if (mode == OVERWRITE_LEFT) { |
4660 // We can't overwrite a Smi so get address of new heap number into r5. | 4666 // We can't overwrite a Smi so get address of new heap number into r5. |
4661 AllocateHeapNumber(masm, &slow, r5, r6, r7); | 4667 AllocateHeapNumber(masm, &slow, r5, r6, r7); |
4662 } | 4668 } |
4663 // Write Smi from r1 to r1 and r0 in double format. | 4669 // Write Smi from r1 to r1 and r0 in double format. |
4664 __ mov(r7, Operand(r1)); | 4670 __ mov(r7, Operand(r1)); |
4665 ConvertToDoubleStub stub4(r1, r0, r7, r6); | 4671 ConvertToDoubleStub stub4(r1, r0, r7, r6); |
4666 __ push(lr); | 4672 __ push(lr); |
(...skipping 15 matching lines...) Expand all Loading... |
4682 // Store answer in the overwritable heap number. | 4688 // Store answer in the overwritable heap number. |
4683 __ pop(r4); | 4689 __ pop(r4); |
4684 #if !defined(USE_ARM_EABI) | 4690 #if !defined(USE_ARM_EABI) |
4685 // Double returned in fp coprocessor register 0 and 1, encoded as register | 4691 // Double returned in fp coprocessor register 0 and 1, encoded as register |
4686 // cr8. Offsets must be divisible by 4 for coprocessor so we need to | 4692 // cr8. Offsets must be divisible by 4 for coprocessor so we need to |
4687 // substract the tag from r4. | 4693 // substract the tag from r4. |
4688 __ sub(r5, r4, Operand(kHeapObjectTag)); | 4694 __ sub(r5, r4, Operand(kHeapObjectTag)); |
4689 __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset)); | 4695 __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset)); |
4690 #else | 4696 #else |
4691 // Double returned in registers 0 and 1. | 4697 // Double returned in registers 0 and 1. |
4692 __ str(r0, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); | 4698 __ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset)); |
4693 __ str(r1, FieldMemOperand(r4, HeapNumber::kExponentOffset)); | 4699 __ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + 4)); |
4694 #endif | 4700 #endif |
4695 __ mov(r0, Operand(r4)); | 4701 __ mov(r0, Operand(r4)); |
4696 // And we are done. | 4702 // And we are done. |
4697 __ pop(pc); | 4703 __ pop(pc); |
4698 } | 4704 } |
4699 | 4705 |
4700 | 4706 |
4701 // Tries to get a signed int32 out of a double precision floating point heap | 4707 // Tries to get a signed int32 out of a double precision floating point heap |
4702 // number. Rounds towards 0. Only succeeds for doubles that are in the ranges | 4708 // number. Rounds towards 0. Only succeeds for doubles that are in the ranges |
4703 // -0x7fffffff to -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds | 4709 // -0x7fffffff to -0x40000000 or 0x40000000 to 0x7fffffff. This corresponds |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5650 __ mov(r2, Operand(0)); | 5656 __ mov(r2, Operand(0)); |
5651 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5657 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
5652 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), | 5658 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), |
5653 RelocInfo::CODE_TARGET); | 5659 RelocInfo::CODE_TARGET); |
5654 } | 5660 } |
5655 | 5661 |
5656 | 5662 |
5657 #undef __ | 5663 #undef __ |
5658 | 5664 |
5659 } } // namespace v8::internal | 5665 } } // namespace v8::internal |
OLD | NEW |