Index: src/arm/macro-assembler-arm.cc |
=================================================================== |
--- src/arm/macro-assembler-arm.cc (revision 6446) |
+++ src/arm/macro-assembler-arm.cc (working copy) |
@@ -1,4 +1,4 @@ |
-// Copyright 2010 the V8 project authors. All rights reserved. |
+// Copyright 2011 the V8 project authors. All rights reserved. |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
@@ -615,37 +615,24 @@ |
void MacroAssembler::EnterExitFrame(bool save_doubles) { |
- // r0 is argc. |
- // Compute callee's stack pointer before making changes and save it as |
- // ip register so that it is restored as sp register on exit, thereby |
- // popping the args. |
+ // Compute the argv pointer in a callee-saved register. |
+ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); |
+ sub(r6, r6, Operand(kPointerSize)); |
- // ip = sp + kPointerSize * #args; |
- add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); |
- |
- // Compute the argv pointer and keep it in a callee-saved register. |
- sub(r6, ip, Operand(kPointerSize)); |
- |
- // Prepare the stack to be aligned when calling into C. After this point there |
- // are 5 pushes before the call into C, so the stack needs to be aligned after |
- // 5 pushes. |
- int frame_alignment = ActivationFrameAlignment(); |
- int frame_alignment_mask = frame_alignment - 1; |
- if (frame_alignment != kPointerSize) { |
- // The following code needs to be more general if this assert does not hold. |
- ASSERT(frame_alignment == 2 * kPointerSize); |
- // With 5 pushes left the frame must be unaligned at this point. |
- mov(r7, Operand(Smi::FromInt(0))); |
- tst(sp, Operand((frame_alignment - kPointerSize) & frame_alignment_mask)); |
- push(r7, eq); // Push if aligned to make it unaligned. |
- } |
- |
- // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. |
- stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); |
+ // Setup the frame structure on the stack. |
+ ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
+ ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
+ ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
+ Push(lr, fp); |
mov(fp, Operand(sp)); // Setup new frame pointer. |
- |
+ // Reserve room for saved entry sp and code object. |
+ sub(sp, sp, Operand(2 * kPointerSize)); |
+ if (FLAG_debug_code) { |
+ mov(ip, Operand(0)); |
+ str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
+ } |
mov(ip, Operand(CodeObject())); |
- push(ip); // Accessed from ExitFrame::code_slot. |
+ str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
// Save the frame pointer and the context in top. |
mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
@@ -659,25 +646,30 @@ |
// Optionally save all double registers. |
if (save_doubles) { |
- // TODO(regis): Use vstrm instruction. |
- // The stack alignment code above made sp unaligned, so add space for one |
- // more double register and use aligned addresses. |
- ASSERT(kDoubleSize == frame_alignment); |
- // Mark the frame as containing doubles by pushing a non-valid return |
- // address, i.e. 0. |
- ASSERT(ExitFrameConstants::kMarkerOffset == -2 * kPointerSize); |
- mov(ip, Operand(0)); // Marker and alignment word. |
- push(ip); |
- int space = DwVfpRegister::kNumRegisters * kDoubleSize + kPointerSize; |
- sub(sp, sp, Operand(space)); |
+ sub(sp, sp, Operand(DwVfpRegister::kNumRegisters * kDoubleSize)); |
+ const int offset = -2 * kPointerSize; |
for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
DwVfpRegister reg = DwVfpRegister::from_code(i); |
- vstr(reg, sp, i * kDoubleSize + kPointerSize); |
+ vstr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
} |
- // Note that d0 will be accessible at fp - 2*kPointerSize - |
- // DwVfpRegister::kNumRegisters * kDoubleSize, since the code slot and the |
- // alignment word were pushed after the fp. |
+ // Note that d0 will be accessible at |
+ // fp - 2 * kPointerSize - DwVfpRegister::kNumRegisters * kDoubleSize, |
+ // since the sp slot and code slot were pushed after the fp. |
} |
+ |
+ // Reserve place for the return address and align the frame preparing for |
+ // calling the runtime function. |
+ const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
+ sub(sp, sp, Operand(kPointerSize)); |
+ if (frame_alignment > 0) { |
+ ASSERT(IsPowerOf2(frame_alignment)); |
+ and_(sp, sp, Operand(-frame_alignment)); |
+ } |
+ |
+ // Set the exit frame sp value to point just before the return address |
+ // location. |
+ add(ip, sp, Operand(kPointerSize)); |
+ str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
} |
@@ -715,12 +707,10 @@ |
void MacroAssembler::LeaveExitFrame(bool save_doubles) { |
// Optionally restore all double registers. |
if (save_doubles) { |
- // TODO(regis): Use vldrm instruction. |
for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
DwVfpRegister reg = DwVfpRegister::from_code(i); |
- // Register d15 is just below the marker. |
- const int offset = ExitFrameConstants::kMarkerOffset; |
- vldr(reg, fp, (i - DwVfpRegister::kNumRegisters) * kDoubleSize + offset); |
+ const int offset = -2 * kPointerSize; |
+ vldr(reg, fp, offset - ((i + 1) * kDoubleSize)); |
} |
} |
@@ -736,9 +726,12 @@ |
str(r3, MemOperand(ip)); |
#endif |
- // Pop the arguments, restore registers, and return. |
- mov(sp, Operand(fp)); // respect ABI stack constraint |
- ldm(ia, sp, fp.bit() | sp.bit() | pc.bit()); |
+ // Tear down the exit frame, pop the arguments, and return. Callee-saved |
+ // register r4 still holds argc. |
+ mov(sp, Operand(fp)); |
+ ldm(ia_w, sp, fp.bit() | lr.bit()); |
+ add(sp, sp, Operand(r4, LSL, kPointerSizeLog2)); |
+ mov(pc, lr); |
} |