Subject: Re: pkg/23790
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: Valeriy E. Ushakov <uwe@ptc.spbu.ru>
List: pkgsrc-bugs
Date: 05/17/2005 08:35:01
The following reply was made to PR pkg/23790; it has been noted by GNATS.

From: "Valeriy E. Ushakov" <uwe@ptc.spbu.ru>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: pkg/23790
Date: Tue, 17 May 2005 12:34:02 +0400

 devel/ffcall has numerous problems on sparc64.  clisp ships with and
 uses a private copy of ffcall, so the same fixes should be applied to
 both.
 
 
 === 1 ===
 
 The CL_SMALL_STRUCT_RETURN autoconf test for small struct returns
 tests if the return value of the function, that returns:
 
     typedef struct { int x; } foo;
 
 returns an int that is == the int x.
         
 On sparc64 the structure is returned in a register, but the 32bit int
 is returned in the MSW of the %o0 register, and so the test, that
 checks the LSW of the %o0, fails.
 
 Workaround: I forced cl_cv_c_struct_return_small=yes via environment
 when running configure.
 
 
 === 2 ===
 
 There's a trivial vacall fix that should be applied twice: once in
 vacall, and once in callback/vacall_r.  Then the .S file(s) need to be
 regenerated (for a package fix, probably just copied over from
 FILESDIR).
 
 --- vacall-sparc64.c-dist	2004-06-02 21:00:22.000000000 +0200
 +++ vacall-sparc64.c	2005-05-17 01:08:04.000000000 +0200
 @@ -110,6 +110,7 @@
    list.farg[15] = farg15;
    /* Prepare the va_alist. */
    list.flags = 0;
 +  list.anum = 0;
    list.aptr = (long)(&firstword - 6);
    list.raddr = (void*)0;
    list.rtype = __VAvoid;
 
 
 === 3 ===
 
 Then the following patch should be applied to avcall, avcall-sparc64.S
 regenerated *and* fixed manually: the "nop" after the avcall that is
 necessary to support functions retunring structures should be moved
 one instruction up.
 
 .  gcc versions prior to gcc3.4 have an ABI bug that affects passing
    small structs with a 'float' member in registers.  I've fixed the
    code to comply to ABI, but it fails passing 'Float' tests with
    gcc3.3.3 that we have in-tree. 
 
 .  returning small structs with fp members doesn't work, as fp members
    are returned in fp regs and the generic avcall code doesn't know
    what members of the structure are, so it doesn't know if it should
    pick the result from fp or from integer registers.
 
 --- avcall-sparc64.c-dist	2004-01-26 15:58:39.000000000 +0100
 +++ avcall-sparc64.c	2005-05-16 03:31:07.000000000 +0200
 @@ -103,79 +103,44 @@
  
    __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 */
 +  __avword *argframe = (void *)((unsigned long)(sp + 16)+2047); /* 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]));
    }
  
    {
 @@ -188,7 +153,7 @@
    i = ({ __avword iret;	/* %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;
         });
  
 --- avcall.h.in-dist	2004-01-26 15:58:41.000000000 +0100
 +++ avcall.h.in	2005-05-16 03:30:27.000000000 +0200
 @@ -382,8 +382,7 @@
  #if defined(__sparc64__)
    /* store the floating-point arguments in an extra array */
    int			anum;		/* redundant: (LIST).aptr = &(LIST).args[(LIST).anum] */
 -  unsigned int		farg_mask;	/* bitmask of those entries in farg[] which have a value */
 -  unsigned int		darg_mask;	/* bitmask of those entries in args[] which have a double value */
 +  unsigned int		darg_mask;	/* bitmask of those entries in args[] which have a float or double value */
  #endif
  #if defined(__ia64__) || defined(__x86_64__)
    /* store the floating-point arguments in an extra array */
 @@ -467,7 +466,6 @@
  #if defined(__sparc64__)
  #define __av_start1(LIST)						\
     (LIST).anum = 0,							\
 -   (LIST).farg_mask = 0,						\
     (LIST).darg_mask = 0,						\
     (LIST).aptr = &(LIST).args[0],					\
     (LIST).eptr = &(LIST).args[__AV_ALIST_WORDS],
 @@ -906,8 +904,8 @@
   */
  #define __av_float(LIST,VAL)						\
    ((LIST).aptr >= __av_eptr(LIST)					\
 -   ? -1 : (((LIST).anum < 16 && ((LIST).farg_mask |= (1 << (LIST).anum))), \
 -	   (*(float*)(LIST).aptr = (float)(VAL)),			\
 +   ? -1 : (((LIST).anum < 16 && ((LIST).darg_mask |= (1 << (LIST).anum))), \
 +	   (((float*)(LIST).aptr)[1] = (float)(VAL)),			\
  	   (LIST).anum++,						\
  	   (LIST).aptr++,						\
  	   0))
 @@ -1307,10 +1305,8 @@
        ? -1 : (ASSIGN(TYPE,TYPE_SIZE,TYPE_ALIGN,(void*)((__avword)(LIST).aptr-(TYPE_SIZE)),VAL),\
  	      (LIST).aptr = (__avword*)(((__avword)(LIST).aptr+sizeof(__avword)-1) & -(long)sizeof(__avword)),\
  	      ((LIST).anum < 16						\
 -		&& ((LIST).farg_mask |= (-1 << (LIST).anum),		\
 -		    (LIST).darg_mask |= (-1 << (LIST).anum))),		\
 +		&& ((LIST).darg_mask |= (-1 << (LIST).anum))),		\
  	      (LIST).anum += (((((TYPE_SIZE)+(TYPE_ALIGN)-1) & -(long)(TYPE_ALIGN)) + sizeof(__avword)-1) & -(long)sizeof(__avword))/sizeof(__avword),\
 -	      (LIST).farg_mask &= (1 << ((LIST).anum < 16 ? (LIST).anum : 16)) - 1, \
  	      (LIST).darg_mask &= (1 << ((LIST).anum < 16 ? (LIST).anum : 16)) - 1, \
  	      0)))
  #endif
 
 
 
 SY, Uwe
 -- 
 uwe@ptc.spbu.ru                         |       Zu Grunde kommen
 http://www.ptc.spbu.ru/~uwe/            |       Ist zu Grunde gehen