From 43c8a8204942f7286daad33ed5bcf4dcbe9f4c7d Mon Sep 17 00:00:00 2001
From: Raymond Toy <toy.raymond@gmail.com>
Date: Wed, 21 Dec 2011 22:51:42 -0800
Subject: [PATCH] Make stack 16-byte aligned.

lisp/x86-assem.S:
o Make sure the stack is 16-byte aligned in the alloc_overflow_foo and
  alloc_to_foo routines.  These eventually call into C code, and the
  stack is required to be 16-byte aligned on Darwin.  We apply this to
  all x86 implementations since it's harmless.
o Did not update the alloc_8/16_to_foo routines because they are going
  to be deleted.

x86/macros.lisp:
o Don't call the alloc_8/16_to_foo routines when we're not doing
  inline allocation.  I don't think there's much to be gained with
  these special functions and maintainence is a pain with assembly
  code.
---
 src/compiler/x86/macros.lisp |  72 ++++---------
 src/lisp/x86-assem.S         | 199 ++++++++++++++++++++---------------
 2 files changed, 131 insertions(+), 140 deletions(-)

diff --git a/src/compiler/x86/macros.lisp b/src/compiler/x86/macros.lisp
index ea9c89742..731bcf47f 100644
--- a/src/compiler/x86/macros.lisp
+++ b/src/compiler/x86/macros.lisp
@@ -181,65 +181,29 @@
   ;; special entry point. The size may be a register or a constant.
   (ecase (tn-offset alloc-tn)
     (#.eax-offset
-     (case size
-       (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_eax")
-				 :foreign)))
-       (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_eax")
-				  :foreign)))
-       (t
-	(load-size alloc-tn eax-tn size)
-	(inst call (make-fixup (extern-alien-name "alloc_to_eax")
-			       :foreign)))))
+     (load-size alloc-tn eax-tn size)
+     (inst call (make-fixup (extern-alien-name "alloc_to_eax")
+			    :foreign)))
     (#.ecx-offset
-     (case size
-       (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_ecx")
-				 :foreign)))
-       (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_ecx")
-				  :foreign)))
-       (t
-	(load-size alloc-tn ecx-tn size)
-	(inst call (make-fixup (extern-alien-name "alloc_to_ecx")
-			       :foreign)))))
+     (load-size alloc-tn ecx-tn size)
+     (inst call (make-fixup (extern-alien-name "alloc_to_ecx")
+			    :foreign)))
     (#.edx-offset
-     (case size
-       (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_edx")
-				 :foreign)))
-       (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_edx")
-				  :foreign)))
-       (t
-	(load-size alloc-tn edx-tn size)
-	(inst call (make-fixup (extern-alien-name "alloc_to_edx")
-			       :foreign)))))
+     (load-size alloc-tn edx-tn size)
+     (inst call (make-fixup (extern-alien-name "alloc_to_edx")
+			    :foreign)))
     (#.ebx-offset
-     (case size
-       (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_ebx")
-				 :foreign)))
-       (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_ebx")
-				  :foreign)))
-       (t
-	(load-size alloc-tn ebx-tn size)
-	(inst call (make-fixup (extern-alien-name "alloc_to_ebx") 
-			       :foreign)))))
+     (load-size alloc-tn ebx-tn size)
+     (inst call (make-fixup (extern-alien-name "alloc_to_ebx") 
+			    :foreign)))
     (#.esi-offset
-     (case size
-       (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_esi")
-				 :foreign)))
-       (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_esi")
-				  :foreign)))
-       (t
-	(load-size alloc-tn esi-tn size)
-	(inst call (make-fixup (extern-alien-name "alloc_to_esi")
-			       :foreign)))))
+     (load-size alloc-tn esi-tn size)
+     (inst call (make-fixup (extern-alien-name "alloc_to_esi")
+			    :foreign)))
     (#.edi-offset
-     (case size
-       (8 (inst call (make-fixup (extern-alien-name "alloc_8_to_edi")
-				 :foreign)))
-       (16 (inst call (make-fixup (extern-alien-name "alloc_16_to_edi")
-				  :foreign)))
-       (t
-	(load-size alloc-tn edi-tn size)
-	(inst call (make-fixup (extern-alien-name "alloc_to_edi")
-			       :foreign))))))
+     (load-size alloc-tn edi-tn size)
+     (inst call (make-fixup (extern-alien-name "alloc_to_edi")
+			    :foreign))))
   (values))
 
 ;;;
diff --git a/src/lisp/x86-assem.S b/src/lisp/x86-assem.S
index 178e913b3..555706078 100644
--- a/src/lisp/x86-assem.S
+++ b/src/lisp/x86-assem.S
@@ -63,6 +63,22 @@ GNAME(x):			;
 #define	align_16byte	4	
 #endif			
 
+/*
+ * Allocate |bytes| on the stack, and make sure the stack pointer is
+ * aligned on a 16-byte boundary.  (Needed on Darwin, and harmless on 
+ * others that don't need such alignment.)
+ */		
+#define STACK_PROLOGUE(bytes) \
+	pushl	%ebp		; \
+	mov	%esp, %ebp	; \
+	subl	$##bytes, %esp	; \
+	andl	$-16, %esp	; 
+
+/* Undo STACK_PROLOGUE */
+#define STACK_EPILOGUE \
+	movl	%ebp, %esp	; \
+	popl	%ebp		; 
+	
 	.text
 	.globl	GNAME(foreign_function_call_active)
 	
@@ -453,13 +469,14 @@ ENDFUNC(fastcopy16)
    So only eax, ecx, and edx need special care here. */
 		
 FUNCDEF(alloc_to_eax)
-	pushl	%ecx	# Save ecx and edx as C could destroy them.
-	pushl	%edx
-	pushl	%eax	# Push the size
+	STACK_PROLOGUE(12)
+	movl	%ecx, 8(%esp)	# Save ecx and edx as C could destroy them.
+	movl	%edx, 4(%esp)
+	movl	%eax, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
-	popl	%edx	# Restore ecx and edx.
-	popl	%ecx
+	movl	4(%esp), %edx	# Restore ecx and edx.
+	movl	8(%esp), %ecx
+	STACK_EPILOGUE
 	ret
 ENDFUNC(alloc_to_eax)
 
@@ -473,7 +490,7 @@ FUNCDEF(alloc_8_to_eax)
 	popl	%ecx
 	ret
 ENDFUNC(alloc_8_to_eax)
-
+	
 FUNCDEF(alloc_16_to_eax)
 	pushl	%ecx	# Save ecx and edx as C could destroy them.
 	pushl	%edx
@@ -486,14 +503,15 @@ FUNCDEF(alloc_16_to_eax)
 ENDFUNC(alloc_16_to_eax)
 
 FUNCDEF(alloc_to_ecx)
-	pushl	%eax	# Save eax and edx as C could destroy them.
-	pushl	%edx
-	pushl	%ecx	# Push the size
+	STACK_PROLOGUE(12)
+	movl	%eax, 8(%esp)	# Save eax and edx as C could destroy them.
+	movl	%edx, 4(%esp)
+	movl	%ecx, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%ecx	# setup the destination.
-	popl	%edx	# Restore eax and edx.
-	popl	%eax
+	movl	4(%esp), %edx	# Restore eax and edx.
+	movl	8(%esp), %eax
+	STACK_EPILOGUE
 	ret
 ENDFUNC(alloc_to_ecx)
 
@@ -522,14 +540,15 @@ FUNCDEF(alloc_16_to_ecx)
 ENDFUNC(alloc_16_to_ecx)
 
 FUNCDEF(alloc_to_edx)
-	pushl	%eax	# Save eax and ecx as C could destroy them.
-	pushl	%ecx
-	pushl	%edx	# Push the size
+	STACK_PROLOGUE(12)
+	movl	%eax, 8(%esp)	# Save eax and ecx as C could destroy them.
+	movl	%ecx, 4(%esp)
+	movl	%edx, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%edx	# setup the destination.
-	popl	%ecx	# Restore eax and ecx.
-	popl	%eax
+	movl	4(%esp), %ecx	# Restore eax and ecx.
+	movl	8(%esp), %eax
+	STACK_EPILOGUE
 	ret
 ENDFUNC(alloc_to_edx)
 
@@ -558,16 +577,17 @@ FUNCDEF(alloc_16_to_edx)
 ENDFUNC(alloc_16_to_edx)
 
 FUNCDEF(alloc_to_ebx)
-	pushl	%eax	# Save eax, ecx, and edx as C could destroy them.
-	pushl	%ecx
-	pushl	%edx
-	pushl	%ebx	# Push the size
+	STACK_PROLOGUE(16)
+	movl	%eax, 12(%esp)	# Save eax, ecx, and edx as C could destroy them.
+	movl	%ecx, 8(%esp)
+	movl	%edx, 4(%esp)
+	movl	%ebx, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%ebx	# setup the destination.
-	popl	%edx	# Restore eax, ecx and edx.
-	popl	%ecx
-	popl	%eax
+	movl	4(%esp), %edx	# Restore eax, ecx and edx.
+	movl	8(%esp), %ecx
+	movl	12(%esp), %eax
+	STACK_EPILOGUE
 	ret
 ENDFUNC(alloc_to_ebx)
 
@@ -600,16 +620,17 @@ FUNCDEF(alloc_16_to_ebx)
 ENDFUNC(alloc_16_to_ebx)
 
 FUNCDEF(alloc_to_esi)
-	pushl	%eax	# Save eax, ecx, and edx as C could destroy them.
-	pushl	%ecx
-	pushl	%edx
-	pushl	%esi	# Push the size
+	STACK_PROLOGUE(16)
+	movl	%eax, 12(%esp)	# Save eax, ecx, and edx as C could destroy them.
+	movl	%ecx, 8(%esp)
+	movl	%edx, 4(%esp)
+	movl	%esi, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%esi	# setup the destination.
-	popl	%edx	# Restore eax, ecx and edx.
-	popl	%ecx
-	popl	%eax
+	movl	4(%esp), %edx	# Restore eax, ecx and edx.
+	movl	8(%esp), %ecx
+	movl	12(%esp), %eax
+	STACK_EPILOGUE
 	ret
 ENDFUNC(alloc_to_esi)
 
@@ -642,16 +663,17 @@ FUNCDEF(alloc_16_to_esi)
 ENDFUNC(alloc_16_to_esi)
 
 FUNCDEF(alloc_to_edi)
-	pushl	%eax	# Save eax, ecx, and edx as C could destroy them.
-	pushl	%ecx
-	pushl	%edx
-	pushl	%edi	# Push the size
+	STACK_PROLOGUE(16)
+	movl	%eax, 12(%esp)	# Save eax, ecx, and edx as C could destroy them.
+	movl	%ecx, 8(%esp)
+	movl	%edx, 4(%esp)
+	movl	%edi, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%edi	# setup the destination.
-	popl	%edx	# Restore eax, ecx and edx.
-	popl	%ecx
-	popl	%eax
+	movl	4(%esp), %edx	# Restore eax, ecx and edx.
+	movl	8(%esp), %ecx
+	movl	12(%esp), %eax
+	STACK_EPILOGUE
 	ret
 ENDFUNC(alloc_to_edi)
 
@@ -683,7 +705,6 @@ FUNCDEF(alloc_16_to_edi)
 	ret
 ENDFUNC(alloc_16_to_edi)
 
-
 #ifdef GENCGC
 
 /* Called from lisp when an inline allocation overflows.
@@ -694,15 +715,16 @@ ENDFUNC(alloc_16_to_edi)
 /* This routine handles an overflow with eax=crfp+size. So the
    size=eax-crfp. */
 FUNCDEF(alloc_overflow_eax)
-	pushl	%ecx		# Save ecx
-	pushl	%edx		# Save edx
+	STACK_PROLOGUE(12)
+	movl	%ecx, 8(%esp)	# Save ecx
+	movl	%edx, 4(%esp)	# Save edx
 	/* Calculate the size for the allocation. */
 	subl	CURRENT_REGION_FREE_POINTER + SYMBOL_VALUE_OFFSET,%eax
-	pushl	%eax		# Push the size
+	movl	%eax, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
-	popl	%edx	# Restore edx.
-	popl	%ecx	# Restore ecx.
+	movl	4(%esp), %edx	# Restore edx.
+	movl	8(%esp), %ecx	# Restore ecx.
+	STACK_EPILOGUE
 	addl	$6,(%esp) # Adjust the return address to skip the next inst.
 	ret
 ENDFUNC(alloc_overflow_eax)
@@ -710,16 +732,17 @@ ENDFUNC(alloc_overflow_eax)
 /* This routine handles an overflow with ecx=crfp+size. So the
    size=ecx-crfp. */
 FUNCDEF(alloc_overflow_ecx)
-	pushl	%eax		# Save eax
-	pushl	%edx		# Save edx
+	STACK_PROLOGUE(12)
+	movl	%eax, 8(%esp)	# Save eax
+	movl	%edx, 4(%esp)	# Save edx
 	/* Calculate the size for the allocation. */
 	subl	CURRENT_REGION_FREE_POINTER + SYMBOL_VALUE_OFFSET,%ecx
-	pushl	%ecx		# Push the size
+	movl	%ecx, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%ecx	# setup the destination.
-	popl	%edx	# Restore edx.
-	popl	%eax	# Restore eax.
+	movl	4(%esp), %edx	# Restore edx.
+	movl	8(%esp), %eax	# Restore eax.
+	STACK_EPILOGUE
 	addl	$6,(%esp) # Adjust the return address to skip the next inst.
 	ret
 ENDFUNC(alloc_overflow_ecx)
@@ -727,16 +750,17 @@ ENDFUNC(alloc_overflow_ecx)
 /* This routine handles an overflow with edx=crfp+size. So the
    size=edx-crfp. */
 FUNCDEF(alloc_overflow_edx)
-	pushl	%eax		# Save eax
-	pushl	%ecx		# Save ecx
+	STACK_PROLOGUE(12)
+	movl	%eax, 8(%esp)	# Save eax
+	movl	%ecx, 4(%esp)	# Save ecx
 	/* Calculate the size for the allocation. */
 	subl	CURRENT_REGION_FREE_POINTER + SYMBOL_VALUE_OFFSET,%edx
-	pushl	%edx		# Push the size
+	movl	%edx, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%edx	# setup the destination.
-	popl	%ecx	# Restore ecx.
-	popl	%eax	# Restore eax.
+	movl	4(%esp), %ecx	# Restore ecx.
+	movl	8(%esp), %eax	# Restore eax.
+	STACK_EPILOGUE
 	addl	$6,(%esp) # Adjust the return address to skip the next inst.
 	ret
 ENDFUNC(alloc_overflow_edx)
@@ -744,18 +768,19 @@ ENDFUNC(alloc_overflow_edx)
 /* This routine handles an overflow with ebx=crfp+size. So the
    size=ebx-crfp. */
 FUNCDEF(alloc_overflow_ebx)
-	pushl	%eax		# Save eax
-	pushl	%ecx		# Save ecx
-	pushl	%edx		# Save edx
+	STACK_PROLOGUE(16)
+	movl	%eax, 12(%esp)	# Save eax
+	movl	%ecx, 8(%esp)	# Save ecx
+	movl	%edx, 4(%esp)	# Save edx
 	/* Calculate the size for the allocation. */
 	subl	CURRENT_REGION_FREE_POINTER + SYMBOL_VALUE_OFFSET,%ebx
-	pushl	%ebx		# Push the size
+	movl	%ebx, (%esp)		# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%ebx	# setup the destination.
-	popl	%edx	# Restore edx.
-	popl	%ecx	# Restore ecx.
-	popl	%eax	# Restore eax.
+	movl	4(%esp), %edx	# Restore edx.
+	movl	8(%esp), %ecx	# Restore ecx.
+	movl	12(%esp), %eax	# Restore eax.
+	STACK_EPILOGUE
 	addl	$6,(%esp) # Adjust the return address to skip the next inst.
 	ret
 ENDFUNC(alloc_overflow_ebx)
@@ -763,18 +788,19 @@ ENDFUNC(alloc_overflow_ebx)
 /* This routine handles an overflow with esi=crfp+size. So the
    size=esi-crfp. */
 FUNCDEF(alloc_overflow_esi)
-	pushl	%eax		# Save eax
-	pushl	%ecx		# Save ecx
-	pushl	%edx		# Save edx
+	STACK_PROLOGUE(16)
+	movl	%eax, 12(%esp)	# Save eax
+	movl	%ecx, 8(%esp)	# Save ecx
+	movl	%edx, 4(%esp)	# Save edx
 	/* Calculate the size for the allocation. */
 	subl	CURRENT_REGION_FREE_POINTER + SYMBOL_VALUE_OFFSET,%esi
-	pushl	%esi		# Push the size
+	movl	%esi, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%esi	# setup the destination.
-	popl	%edx	# Restore edx.
-	popl	%ecx	# Restore ecx.
-	popl	%eax	# Restore eax.
+	movl	4(%esp), %edx	# Restore edx.
+	movl	8(%esp), %ecx	# Restore ecx.
+	movl	12(%esp), %eax	# Restore eax.
+	STACK_EPILOGUE
 	addl	$6,(%esp) # Adjust the return address to skip the next inst.
 	ret
 ENDFUNC(alloc_overflow_esi)
@@ -782,18 +808,19 @@ ENDFUNC(alloc_overflow_esi)
 /* This routine handles an overflow with edi=crfp+size. So the
    size=edi-crfp. */
 FUNCDEF(alloc_overflow_edi)
-	pushl	%eax		# Save eax
-	pushl	%ecx		# Save ecx
-	pushl	%edx		# Save edx
+	STACK_PROLOGUE(16)
+	movl	%eax, 12(%esp)	# Save eax
+	movl	%ecx, 8(%esp)	# Save ecx
+	movl	%edx, 4(%esp)	# Save edx
 	/* Calculate the size for the allocation. */
 	subl	CURRENT_REGION_FREE_POINTER + SYMBOL_VALUE_OFFSET,%edi
-	pushl	%edi		# Push the size
+	movl	%edi, (%esp)	# Push the size
 	call	GNAME(alloc)
-	addl	$4,%esp	# pop the size arg.
 	movl	%eax,%edi	# setup the destination.
-	popl	%edx	# Restore edx.
-	popl	%ecx	# Restore ecx.
-	popl	%eax	# Restore eax.
+	movl	4(%esp), %edx	# Restore edx.
+	movl	8(%esp), %ecx	# Restore ecx.
+	movl	12(%esp), %eax	# Restore eax.
+	STACK_EPILOGUE
 	addl	$6,(%esp) # Adjust the return address to skip the next inst.
 	ret
 ENDFUNC(alloc_overflow_edi)
-- 
GitLab