OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 // r2: preserved | 608 // r2: preserved |
609 | 609 |
610 // Drop the execution stack down to the frame pointer and restore | 610 // Drop the execution stack down to the frame pointer and restore |
611 // the caller frame pointer and return address. | 611 // the caller frame pointer and return address. |
612 mov(sp, fp); | 612 mov(sp, fp); |
613 ldm(ia_w, sp, fp.bit() | lr.bit()); | 613 ldm(ia_w, sp, fp.bit() | lr.bit()); |
614 } | 614 } |
615 | 615 |
616 | 616 |
617 void MacroAssembler::EnterExitFrame(bool save_doubles) { | 617 void MacroAssembler::EnterExitFrame(bool save_doubles) { |
618 // r0 is argc. | 618 // Compute the argv pointer in a callee-saved register. |
619 // Compute callee's stack pointer before making changes and save it as | 619 add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); |
620 // ip register so that it is restored as sp register on exit, thereby | 620 sub(r6, r6, Operand(kPointerSize)); |
621 // popping the args. | |
622 | 621 |
623 // ip = sp + kPointerSize * #args; | 622 // Setup the frame structure on the stack. |
624 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); | 623 ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
625 | 624 ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
626 // Compute the argv pointer and keep it in a callee-saved register. | 625 ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
627 sub(r6, ip, Operand(kPointerSize)); | 626 Push(lr, fp); |
628 | 627 mov(fp, Operand(sp)); // Setup new frame pointer. |
629 // Prepare the stack to be aligned when calling into C. After this point there | 628 // Reserve room for saved entry sp and code object. |
630 // are 5 pushes before the call into C, so the stack needs to be aligned after | 629 sub(sp, sp, Operand(2 * kPointerSize)); |
631 // 5 pushes. | 630 if (FLAG_debug_code) { |
632 int frame_alignment = ActivationFrameAlignment(); | 631 mov(ip, Operand(0)); |
633 int frame_alignment_mask = frame_alignment - 1; | 632 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
634 if (frame_alignment != kPointerSize) { | |
635 // The following code needs to be more general if this assert does not hold. | |
636 ASSERT(frame_alignment == 2 * kPointerSize); | |
637 // With 5 pushes left the frame must be unaligned at this point. | |
638 mov(r7, Operand(Smi::FromInt(0))); | |
639 tst(sp, Operand((frame_alignment - kPointerSize) & frame_alignment_mask)); | |
640 push(r7, eq); // Push if aligned to make it unaligned. | |
641 } | 633 } |
642 | |
643 // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. | |
644 stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); | |
645 mov(fp, Operand(sp)); // Setup new frame pointer. | |
646 | |
647 mov(ip, Operand(CodeObject())); | 634 mov(ip, Operand(CodeObject())); |
648 push(ip); // Accessed from ExitFrame::code_slot. | 635 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
649 | 636 |
650 // Save the frame pointer and the context in top. | 637 // Save the frame pointer and the context in top. |
651 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 638 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
652 str(fp, MemOperand(ip)); | 639 str(fp, MemOperand(ip)); |
653 mov(ip, Operand(ExternalReference(Top::k_context_address))); | 640 mov(ip, Operand(ExternalReference(Top::k_context_address))); |
654 str(cp, MemOperand(ip)); | 641 str(cp, MemOperand(ip)); |
655 | 642 |
656 // Setup argc and the builtin function in callee-saved registers. | 643 // Setup argc and the builtin function in callee-saved registers. |
657 mov(r4, Operand(r0)); | 644 mov(r4, Operand(r0)); |
658 mov(r5, Operand(r1)); | 645 mov(r5, Operand(r1)); |
659 | 646 |
660 // Optionally save all double registers. | 647 // Optionally save all double registers. |
661 if (save_doubles) { | 648 if (save_doubles) { |
662 // TODO(regis): Use vstrm instruction. | 649 sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize)); |
663 // The stack alignment code above made sp unaligned, so add space for one | 650 const int offset = -2 * kPointerSize; |
664 // more double register and use aligned addresses. | |
665 ASSERT(kDoubleSize == frame_alignment); | |
666 // Mark the frame as containing doubles by pushing a non-valid return | |
667 // address, i.e. 0. | |
668 ASSERT(ExitFrameConstants::kMarkerOffset == -2 * kPointerSize); | |
669 mov(ip, Operand(0)); // Marker and alignment word. | |
670 push(ip); | |
671 int space = DwVfpRegister::kNumRegisters * kDoubleSize + kPointerSize; | |
672 sub(sp, sp, Operand(space)); | |
673 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 651 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
674 DwVfpRegister reg = DwVfpRegister::from_code(i); | 652 DwVfpRegister reg = DwVfpRegister::from_code(i); |
675 vstr(reg, sp, i * kDoubleSize + kPointerSize); | 653 vstr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
676 } | 654 } |
677 // Note that d0 will be accessible at fp - 2*kPointerSize - | 655 // Note that d0 will be accessible at |
678 // DwVfpRegister::kNumRegisters * kDoubleSize, since the code slot and the | 656 // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize, |
679 // alignment word were pushed after the fp. | 657 // since the sp slot and code slot were pushed after the fp. |
680 } | 658 } |
| 659 |
| 660 // Reserve place for the return address and align the frame preparing for |
| 661 // calling the runtime function. |
| 662 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
| 663 sub(sp, sp, Operand(kPointerSize)); |
| 664 if (frame_alignment > 0) { |
| 665 ASSERT(IsPowerOf2(frame_alignment)); |
| 666 and_(sp, sp, Operand(-frame_alignment)); |
| 667 } |
| 668 |
| 669 // Set the exit frame sp value to point just before the return address |
| 670 // location. |
| 671 add(ip, sp, Operand(kPointerSize)); |
| 672 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
681 } | 673 } |
682 | 674 |
683 | 675 |
684 void MacroAssembler::InitializeNewString(Register string, | 676 void MacroAssembler::InitializeNewString(Register string, |
685 Register length, | 677 Register length, |
686 Heap::RootListIndex map_index, | 678 Heap::RootListIndex map_index, |
687 Register scratch1, | 679 Register scratch1, |
688 Register scratch2) { | 680 Register scratch2) { |
689 mov(scratch1, Operand(length, LSL, kSmiTagSize)); | 681 mov(scratch1, Operand(length, LSL, kSmiTagSize)); |
690 LoadRoot(scratch2, map_index); | 682 LoadRoot(scratch2, map_index); |
(...skipping 17 matching lines...) Expand all Loading... |
708 // if the target platform will need alignment, so this is controlled from a | 700 // if the target platform will need alignment, so this is controlled from a |
709 // flag. | 701 // flag. |
710 return FLAG_sim_stack_alignment; | 702 return FLAG_sim_stack_alignment; |
711 #endif // defined(V8_HOST_ARCH_ARM) | 703 #endif // defined(V8_HOST_ARCH_ARM) |
712 } | 704 } |
713 | 705 |
714 | 706 |
715 void MacroAssembler::LeaveExitFrame(bool save_doubles) { | 707 void MacroAssembler::LeaveExitFrame(bool save_doubles) { |
716 // Optionally restore all double registers. | 708 // Optionally restore all double registers. |
717 if (save_doubles) { | 709 if (save_doubles) { |
718 // TODO(regis): Use vldrm instruction. | |
719 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { | 710 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
720 DwVfpRegister reg = DwVfpRegister::from_code(i); | 711 DwVfpRegister reg = DwVfpRegister::from_code(i); |
721 // Register d15 is just below the marker. | 712 const int offset = -2 * kPointerSize; |
722 const int offset = ExitFrameConstants::kMarkerOffset; | 713 vldr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
723 vldr(reg, fp, (i - DwVfpRegister::kNumRegisters) * kDoubleSize + offset); | |
724 } | 714 } |
725 } | 715 } |
726 | 716 |
727 // Clear top frame. | 717 // Clear top frame. |
728 mov(r3, Operand(0, RelocInfo::NONE)); | 718 mov(r3, Operand(0, RelocInfo::NONE)); |
729 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 719 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
730 str(r3, MemOperand(ip)); | 720 str(r3, MemOperand(ip)); |
731 | 721 |
732 // Restore current context from top and clear it in debug mode. | 722 // Restore current context from top and clear it in debug mode. |
733 mov(ip, Operand(ExternalReference(Top::k_context_address))); | 723 mov(ip, Operand(ExternalReference(Top::k_context_address))); |
734 ldr(cp, MemOperand(ip)); | 724 ldr(cp, MemOperand(ip)); |
735 #ifdef DEBUG | 725 #ifdef DEBUG |
736 str(r3, MemOperand(ip)); | 726 str(r3, MemOperand(ip)); |
737 #endif | 727 #endif |
738 | 728 |
739 // Pop the arguments, restore registers, and return. | 729 // Tear down the exit frame, pop the arguments, and return. Callee-saved |
740 mov(sp, Operand(fp)); // respect ABI stack constraint | 730 // register r4 still holds argc. |
741 ldm(ia, sp, fp.bit() | sp.bit() | pc.bit()); | 731 mov(sp, Operand(fp)); |
| 732 ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 733 add(sp, sp, Operand(r4, LSL, kPointerSizeLog2)); |
| 734 mov(pc, lr); |
742 } | 735 } |
743 | 736 |
744 | 737 |
745 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 738 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
746 const ParameterCount& actual, | 739 const ParameterCount& actual, |
747 Handle<Code> code_constant, | 740 Handle<Code> code_constant, |
748 Register code_reg, | 741 Register code_reg, |
749 Label* done, | 742 Label* done, |
750 InvokeFlag flag, | 743 InvokeFlag flag, |
751 PostCallGenerator* post_call_generator) { | 744 PostCallGenerator* post_call_generator) { |
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2252 | 2245 |
2253 void CodePatcher::Emit(Address addr) { | 2246 void CodePatcher::Emit(Address addr) { |
2254 masm()->emit(reinterpret_cast<Instr>(addr)); | 2247 masm()->emit(reinterpret_cast<Instr>(addr)); |
2255 } | 2248 } |
2256 #endif // ENABLE_DEBUGGER_SUPPORT | 2249 #endif // ENABLE_DEBUGGER_SUPPORT |
2257 | 2250 |
2258 | 2251 |
2259 } } // namespace v8::internal | 2252 } } // namespace v8::internal |
2260 | 2253 |
2261 #endif // V8_TARGET_ARCH_ARM | 2254 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |