Blob Blame History Raw
--- ffcall-20091110cvs.orig/avcall/avcall-sparc64.c	2005-05-23 12:17:21.000000000 +0200
+++ ffcall-20091110cvs/avcall/avcall-sparc64.c	2010-04-04 12:44:30.460013164 +0200
@@ -86,7 +86,6 @@
 #define RETURN(TYPE,VAL)	(*(TYPE*)l->raddr = (TYPE)(VAL))
 #define OFFSETOF(struct,member) ((int)&(((struct*)0)->member))
 
-register void* callee	__asm__("%g2");  /* any global or local register */
 register __avword o0	__asm__("%o0");
 register __avword o1	__asm__("%o1");
 register __avword o2	__asm__("%o2");
@@ -102,83 +101,58 @@ __builtin_avcall(av_alist* l)
   register double dret	__asm__("%f0");  /* %f0,%f1 */
 
   __avword trampoline[6];		/* room for a trampoline */
-  __avword space[__AV_ALIST_WORDS];	/* space for callee's stack frame */
-  __avword *argframe = sp + 17;		/* stack offset for argument list */
   int arglen = l->aptr - l->args;
   __avword i;
 
-  if (l->farg_mask) {
-    /* push leading float args */
-    if (l->farg_mask & (1<<0))
-      __asm__("ld %1(%0),%%f1" : : "p" (l), "i" OFFSETOF(av_alist,args[0]));
-    if (l->farg_mask & (1<<1))
-      __asm__("ld %1(%0),%%f3" : : "p" (l), "i" OFFSETOF(av_alist,args[1]));
-    if (l->farg_mask & (1<<2))
-      __asm__("ld %1(%0),%%f5" : : "p" (l), "i" OFFSETOF(av_alist,args[2]));
-    if (l->farg_mask & (1<<3))
-      __asm__("ld %1(%0),%%f7" : : "p" (l), "i" OFFSETOF(av_alist,args[3]));
-    if (l->farg_mask & (1<<4))
-      __asm__("ld %1(%0),%%f9" : : "p" (l), "i" OFFSETOF(av_alist,args[4]));
-    if (l->farg_mask & (1<<5))
-      __asm__("ld %1(%0),%%f11" : : "p" (l), "i" OFFSETOF(av_alist,args[5]));
-    if (l->farg_mask & (1<<6))
-      __asm__("ld %1(%0),%%f13" : : "p" (l), "i" OFFSETOF(av_alist,args[6]));
-    if (l->farg_mask & (1<<7))
-      __asm__("ld %1(%0),%%f15" : : "p" (l), "i" OFFSETOF(av_alist,args[7]));
-    if (l->farg_mask & (1<<8))
-      __asm__("ld %1(%0),%%f17" : : "p" (l), "i" OFFSETOF(av_alist,args[8]));
-    if (l->farg_mask & (1<<9))
-      __asm__("ld %1(%0),%%f19" : : "p" (l), "i" OFFSETOF(av_alist,args[9]));
-    if (l->farg_mask & (1<<10))
-      __asm__("ld %1(%0),%%f21" : : "p" (l), "i" OFFSETOF(av_alist,args[10]));
-    if (l->farg_mask & (1<<11))
-      __asm__("ld %1(%0),%%f23" : : "p" (l), "i" OFFSETOF(av_alist,args[11]));
-    if (l->farg_mask & (1<<12))
-      __asm__("ld %1(%0),%%f25" : : "p" (l), "i" OFFSETOF(av_alist,args[12]));
-    if (l->farg_mask & (1<<13))
-      __asm__("ld %1(%0),%%f27" : : "p" (l), "i" OFFSETOF(av_alist,args[13]));
-    if (l->farg_mask & (1<<14))
-      __asm__("ld %1(%0),%%f29" : : "p" (l), "i" OFFSETOF(av_alist,args[14]));
-    if (l->farg_mask & (1<<15))
-      __asm__("ld %1(%0),%%f31" : : "p" (l), "i" OFFSETOF(av_alist,args[15]));
-  }
   if (l->darg_mask) {
-    /* push leading double args */
+    /* push leading float/double args */
     if (l->darg_mask & (1<<0))
-      __asm__("ldd %1(%0),%%f0" : : "p" (l), "i" OFFSETOF(av_alist,args[0]));
+      __asm__("ldd [%0+%1],%%f0" : : "p" (l), "i" OFFSETOF(av_alist,args[0]));
     if (l->darg_mask & (1<<1))
-      __asm__("ldd %1(%0),%%f2" : : "p" (l), "i" OFFSETOF(av_alist,args[1]));
+      __asm__("ldd [%0+%1],%%f2" : : "p" (l), "i" OFFSETOF(av_alist,args[1]));
     if (l->darg_mask & (1<<2))
-      __asm__("ldd %1(%0),%%f4" : : "p" (l), "i" OFFSETOF(av_alist,args[2]));
+      __asm__("ldd [%0+%1],%%f4" : : "p" (l), "i" OFFSETOF(av_alist,args[2]));
     if (l->darg_mask & (1<<3))
-      __asm__("ldd %1(%0),%%f6" : : "p" (l), "i" OFFSETOF(av_alist,args[3]));
+      __asm__("ldd [%0+%1],%%f6" : : "p" (l), "i" OFFSETOF(av_alist,args[3]));
     if (l->darg_mask & (1<<4))
-      __asm__("ldd %1(%0),%%f8" : : "p" (l), "i" OFFSETOF(av_alist,args[4]));
+      __asm__("ldd [%0+%1],%%f8" : : "p" (l), "i" OFFSETOF(av_alist,args[4]));
     if (l->darg_mask & (1<<5))
-      __asm__("ldd %1(%0),%%f10" : : "p" (l), "i" OFFSETOF(av_alist,args[5]));
+      __asm__("ldd [%0+%1],%%f10" : : "p" (l), "i" OFFSETOF(av_alist,args[5]));
     if (l->darg_mask & (1<<6))
-      __asm__("ldd %1(%0),%%f12" : : "p" (l), "i" OFFSETOF(av_alist,args[6]));
+      __asm__("ldd [%0+%1],%%f12" : : "p" (l), "i" OFFSETOF(av_alist,args[6]));
     if (l->darg_mask & (1<<7))
-      __asm__("ldd %1(%0),%%f14" : : "p" (l), "i" OFFSETOF(av_alist,args[7]));
+      __asm__("ldd [%0+%1],%%f14" : : "p" (l), "i" OFFSETOF(av_alist,args[7]));
     if (l->darg_mask & (1<<8))
-      __asm__("ldd %1(%0),%%f16" : : "p" (l), "i" OFFSETOF(av_alist,args[8]));
+      __asm__("ldd [%0+%1],%%f16" : : "p" (l), "i" OFFSETOF(av_alist,args[8]));
     if (l->darg_mask & (1<<9))
-      __asm__("ldd %1(%0),%%f18" : : "p" (l), "i" OFFSETOF(av_alist,args[9]));
+      __asm__("ldd [%0+%1],%%f18" : : "p" (l), "i" OFFSETOF(av_alist,args[9]));
     if (l->darg_mask & (1<<10))
-      __asm__("ldd %1(%0),%%f20" : : "p" (l), "i" OFFSETOF(av_alist,args[10]));
+      __asm__("ldd [%0+%1],%%f20" : : "p" (l), "i" OFFSETOF(av_alist,args[10]));
     if (l->darg_mask & (1<<11))
-      __asm__("ldd %1(%0),%%f22" : : "p" (l), "i" OFFSETOF(av_alist,args[11]));
+      __asm__("ldd [%0+%1],%%f22" : : "p" (l), "i" OFFSETOF(av_alist,args[11]));
     if (l->darg_mask & (1<<12))
-      __asm__("ldd %1(%0),%%f24" : : "p" (l), "i" OFFSETOF(av_alist,args[12]));
+      __asm__("ldd [%0+%1],%%f24" : : "p" (l), "i" OFFSETOF(av_alist,args[12]));
     if (l->darg_mask & (1<<13))
-      __asm__("ldd %1(%0),%%f26" : : "p" (l), "i" OFFSETOF(av_alist,args[13]));
+      __asm__("ldd [%0+%1],%%f26" : : "p" (l), "i" OFFSETOF(av_alist,args[13]));
     if (l->darg_mask & (1<<14))
-      __asm__("ldd %1(%0),%%f28" : : "p" (l), "i" OFFSETOF(av_alist,args[14]));
+      __asm__("ldd [%0+%1],%%f28" : : "p" (l), "i" OFFSETOF(av_alist,args[14]));
     if (l->darg_mask & (1<<15))
-      __asm__("ldd %1(%0),%%f30" : : "p" (l), "i" OFFSETOF(av_alist,args[15]));
+      __asm__("ldd [%0+%1],%%f30" : : "p" (l), "i" OFFSETOF(av_alist,args[15]));
   }
 
-  {
+  if (arglen > 6) {
+    /* alloca space is separated from the extra outgoing args area by
+     * the area for compiler temps (addressable with postive offsets from sp)
+     * but they shouldn't be needed for this function, so, effectively,
+     * space returned by alloca is safe to use as the area for extra args.
+     */
+    void *extra_args_area = __builtin_alloca(sizeof(__avword) * (arglen - 6));
+    __avword *argframe = (__avword *)extra_args_area - 6;
+#if 0
+    /* "by construction" */
+    assert(argframe == (void *)((unsigned long)(sp + 16)+2047));
+#endif
+
     int i;
     for (i = 6; i < arglen; i++)	/* push excess function args */
       argframe[i] = l->args[i];
@@ -188,7 +162,7 @@ __builtin_avcall(av_alist* l)
   i = ({ register __avword iret __asm__ ("%o0");
          iret = (*l->func)(l->args[0], l->args[1], l->args[2],
 			   l->args[3], l->args[4], l->args[5]);
-         asm ("nop");	/* struct returning functions skip this instruction */
+         asm __volatile__("nop");	/* struct returning functions skip this instruction */
          iret;
        });