Fix fp problems in runtime code on ARM EABI by 8-byte aligning
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 May 2009 20:11:01 +0000 (20:11 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 May 2009 20:11:01 +0000 (20:11 +0000)
the stack on exit to C.
Review URL: http://codereview.chromium.org/115256

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1922 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/assembler-arm.h
src/arm/macro-assembler-arm.cc
src/platform-linux.cc

index d7535e0..d4c7979 100644 (file)
@@ -622,8 +622,8 @@ class Assembler : public Malloced {
   // Pseudo instructions
   void nop()  { mov(r0, Operand(r0)); }
 
-  void push(Register src) {
-    str(src, MemOperand(sp, 4, NegPreIndex), al);
+  void push(Register src, Condition cond = al) {
+    str(src, MemOperand(sp, 4, NegPreIndex), cond);
   }
 
   void pop(Register dst) {
index 365c1ad..ee82da1 100644 (file)
@@ -291,6 +291,12 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
 
 void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
   ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
+  // Compute the argv pointer and keep it in a callee-saved register.
+  // r0 is argc.
+  add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
+  sub(r6, r6, Operand(kPointerSize));
+
   // Compute parameter pointer before making changes and save it as ip
   // register so that it is restored as sp register on exit, thereby
   // popping the args.
@@ -298,6 +304,17 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
   // ip = sp + kPointerSize * #args;
   add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
 
+  // Align the stack at this point.  After this point we have 5 pushes,
+  // so in fact we have to unalign here!  See also the assert on the
+  // alignment immediately below.
+  if (OS::ActivationFrameAlignment() != kPointerSize) {
+    // This code needs to be made more general if this assert doesn't hold.
+    ASSERT(OS::ActivationFrameAlignment() == 2 * kPointerSize);
+    mov(r7, Operand(Smi::FromInt(0)));
+    tst(sp, Operand(OS::ActivationFrameAlignment() - 1));
+    push(r7, eq);  // Conditional push instruction.
+  }
+
   // Push in reverse order: caller_fp, sp_on_exit, and caller_pc.
   stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
   mov(fp, Operand(sp));  // setup new frame pointer
@@ -316,9 +333,6 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
   mov(r4, Operand(r0));
   mov(r5, Operand(r1));
 
-  // Compute the argv pointer and keep it in a callee-saved register.
-  add(r6, fp, Operand(r4, LSL, kPointerSizeLog2));
-  add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Save the state of all registers to the stack from the memory
index c02eebc..69e767a 100644 (file)
@@ -88,6 +88,8 @@ double OS::nan_value() {
 
 int OS::ActivationFrameAlignment() {
   // Floating point code runs faster if the stack is 8-byte aligned.
+  // On EABI ARM targets this is required for fp correctness in the
+  // runtime system.
   return 8;
 }