This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Yet more rs6000 function arg passing fixes


I thought we had function arg passing fairly reasonable on rs6000, but
close inspection shows quite a few problems remaining.  I guess yours
truly is to blame for the long double bugs..

o  function_arg_partial_nregs was broken for args that need alignment,
   returning higher values than it should, resulting in stack words not
   being written.  It was also broken for fp regs when there was a need
   to return a value for gprs.  long double also returned the wrong
   number of fprs due to an off-by-one error.

o  rs6000_mixed_function_arg, to work around errors in emit_push_insn,
   passes entire args in memory when the correct behaviour is to pass in
   memory only that part not passed in regs.  We're stuck with this
   until emit_push_insn is modified to look inside a PARALLEL for the
   size pf partial args in regs (as it does for partial BLKmode args)
   instead of assuming UNITS_PER_WORD.  I rewrote the function anyway,
   since what we had was basically a collection of hacks.  ;)

o  AIX 32-bit didn't pass long doubles correctly when they needed to be
   passed both in gprs and fprs (variable arg functions, or
   non-prototyped).  For example, if the long double should have been
   passed partially in r8,r9,r10 then only r8 was set.  The fix for this
   problem allows the fpr code in rs6000_mixed_function_arg to
   disappear.

o  function_arg aborted due to an off-by-one error when a long double
   was passed partly on the stack.

o  The ABI_V4 code needs to call rs6000_mixed_function_arg to handle
   gprs correctly when -mpowerpc64.

	* config/rs6000/rs6000.c (rs6000_mixed_function_arg): Rewrite.
	(function_arg): Use rs6000_arg_size rather than CLASS_MAX_NREGS in
	calculating gpr size for altivec.  Simplify and correct
	rs6000_mixed_function_arg calls.  Call rs6000_mixed_function_arg
	for ABI_V4 gpr case too.  Fix off-by-one error in long double
	reg test.  Generate the correct PARALLEL to handle long double
	for ABI_AIX 32-bit.  Use this for -m32 -mpowerpc64 fpr case too.
	(function_arg_partial_nregs): Align before calculating regs left.
	Don't return info on partial fprs when we need info on gprs.
	Correct long double fpr off-by-one error.

The emit_push_insn problem (or perhaps other similar bugs, I've only
superficially looked with gdb) also affects us when passing long doubles
in AIX 32-bit.  When a long double is split between memory and stack,
function_arg emits a PARALLEL with a single DFmode element, and
function_arg_partial_nregs returns 1 to say that only one of the two
DFmode size hunks is in regs.  This is a request to put the other DFmode
size hunk on the stack.  However, the generic code interprets this to
mean that only one of four word size hunks is in regs, putting three
words on the stack.  You could easily hack around this, but I felt it
wasn't worth doing, and should wait until emit_push_insn is fixed.

Bootstrapped powerpc-linux and powerpc64-linux.  No regressions on an
earlier version of the patch.  Current patch in boot/regtest process.  I
don't have access to a darwin box, so if someone would try the patch out
there, I'd appreciate it.  My testing consisted of using options like
-S -m32 -mpowerpc64 -mcall-aixdesc -mabi=altivec -maltivec and various
other combinations, and looking at assembly output for testcases.  Hmm,
I suppose I should polish them up so they can be added to the gcc
testsuite.


*** gcc-virgin/gcc/config/rs6000/rs6000.c	2004-05-10 23:53:25.000000000 +0930
--- gcc-mainline/gcc/config/rs6000/rs6000.c	2004-05-12 21:57:58.000000000 +0930
*************** static int rs6000_get_some_local_dynamic
*** 424,431 ****
  static rtx rs6000_complex_function_value (enum machine_mode);
  static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
  				    enum machine_mode, tree);
! static rtx rs6000_mixed_function_arg (CUMULATIVE_ARGS *,
! 				      enum machine_mode, tree, int);
  static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
  static void setup_incoming_varargs (CUMULATIVE_ARGS *,
  				    enum machine_mode, tree,
--- 424,430 ----
  static rtx rs6000_complex_function_value (enum machine_mode);
  static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
  				    enum machine_mode, tree);
! static rtx rs6000_mixed_function_arg (enum machine_mode, tree, int);
  static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
  static void setup_incoming_varargs (CUMULATIVE_ARGS *,
  				    enum machine_mode, tree,
*************** rs6000_spe_function_arg (CUMULATIVE_ARGS
*** 4404,4527 ****
  /* Determine where to place an argument in 64-bit mode with 32-bit ABI.  */
  
  static rtx
! rs6000_mixed_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, 
! 			   tree type, int align_words)
  {
!   if (mode == DFmode)
      {
!       /* -mpowerpc64 with 32bit ABI splits up a DFmode argument
! 	 in vararg list into zero, one or two GPRs */
!       if (align_words >= GP_ARG_NUM_REG)
! 	return gen_rtx_PARALLEL (DFmode,
! 		 gen_rtvec (2,
! 			    gen_rtx_EXPR_LIST (VOIDmode,
! 					       NULL_RTX, const0_rtx), 
! 			    gen_rtx_EXPR_LIST (VOIDmode,
! 					       gen_rtx_REG (mode,
! 							    cum->fregno),
! 					       const0_rtx)));
!       else if (align_words + rs6000_arg_size (mode, type)
! 	       > GP_ARG_NUM_REG)
! 	/* If this is partially on the stack, then we only
! 	   include the portion actually in registers here.  */
! 	return gen_rtx_PARALLEL (DFmode,
! 		 gen_rtvec (2,   
! 			    gen_rtx_EXPR_LIST (VOIDmode,
! 					       gen_rtx_REG (SImode,
! 							    GP_ARG_MIN_REG
! 							    + align_words),
! 					       const0_rtx),
! 			    gen_rtx_EXPR_LIST (VOIDmode,
! 					       gen_rtx_REG (mode,
! 							    cum->fregno),
! 					       const0_rtx)));
! 
!       /* split a DFmode arg into two GPRs */
!       return gen_rtx_PARALLEL (DFmode,
! 	       gen_rtvec (3,
! 			  gen_rtx_EXPR_LIST (VOIDmode,       
! 					     gen_rtx_REG (SImode,
! 							  GP_ARG_MIN_REG
! 							  + align_words),
! 					     const0_rtx),
! 			  gen_rtx_EXPR_LIST (VOIDmode,
! 					     gen_rtx_REG (SImode,
! 							  GP_ARG_MIN_REG
! 							  + align_words + 1),
! 					     GEN_INT (4)),
! 			  gen_rtx_EXPR_LIST (VOIDmode,
! 					     gen_rtx_REG (mode, cum->fregno),
! 					     const0_rtx)));
      }
!   /* -mpowerpc64 with 32bit ABI splits up a DImode argument into one
!      or two GPRs */
!   else if (mode == DImode)
!     {
!       if (align_words < GP_ARG_NUM_REG - 1)
! 	return gen_rtx_PARALLEL (DImode,
! 		 gen_rtvec (2,
! 			    gen_rtx_EXPR_LIST (VOIDmode,
! 					       gen_rtx_REG (SImode,
! 							    GP_ARG_MIN_REG
! 							    + align_words),
! 					       const0_rtx),
! 			    gen_rtx_EXPR_LIST (VOIDmode,
! 					       gen_rtx_REG (SImode,
! 							    GP_ARG_MIN_REG
! 							    + align_words + 1),
! 					       GEN_INT (4))));
!       else if (align_words == GP_ARG_NUM_REG - 1)
! 	  return gen_rtx_PARALLEL (DImode,
! 		   gen_rtvec (2,
! 			      gen_rtx_EXPR_LIST (VOIDmode,
! 						 NULL_RTX, const0_rtx),
! 			      gen_rtx_EXPR_LIST (VOIDmode,
! 						 gen_rtx_REG (SImode,
! 							      GP_ARG_MIN_REG
! 							      + align_words),
! 						 const0_rtx)));
!     }
!   else if (ALTIVEC_VECTOR_MODE (mode) && align_words == GP_ARG_NUM_REG - 2)
!     {
!       /* Varargs vector regs must be saved in R9-R10.  */
!       return gen_rtx_PARALLEL (mode,
! 	   		       gen_rtvec (3,
! 			         gen_rtx_EXPR_LIST (VOIDmode,
! 						     NULL_RTX, const0_rtx),
! 			         gen_rtx_EXPR_LIST (VOIDmode,
! 						    gen_rtx_REG (SImode,
! 							         GP_ARG_MIN_REG
! 							         + align_words),
! 						    const0_rtx),
! 			         gen_rtx_EXPR_LIST (VOIDmode,
! 						    gen_rtx_REG (SImode,
! 							         GP_ARG_MIN_REG
! 							         + align_words + 1),
! 						    GEN_INT (4))));
!     }
!   else if ((mode == BLKmode || ALTIVEC_VECTOR_MODE (mode))
!            && align_words <= (GP_ARG_NUM_REG - 1))
!     {
!       /* AltiVec vector regs are saved in R5-R8. */
!       int k;
!       int size = int_size_in_bytes (type);
!       int no_units = ((size - 1) / 4) + 1;
!       int max_no_words = GP_ARG_NUM_REG - align_words;
!       int rtlvec_len = no_units < max_no_words ? no_units : max_no_words;
!       rtx *rtlvec = (rtx *) alloca (rtlvec_len * sizeof (rtx));
! 
!       memset ((char *) rtlvec, 0, rtlvec_len * sizeof (rtx));
! 
!       for (k=0; k < rtlvec_len; k++)
! 	rtlvec[k] = gen_rtx_EXPR_LIST (VOIDmode,
! 				       gen_rtx_REG (SImode,
! 						    GP_ARG_MIN_REG
! 						    + align_words + k),
! 				       k == 0 ? const0_rtx : GEN_INT (k*4));
  
!       return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rtlvec));
!     }
!   return NULL_RTX;
  }
  
  /* Determine where to put an argument to a function.
--- 4403,4448 ----
  /* Determine where to place an argument in 64-bit mode with 32-bit ABI.  */
  
  static rtx
! rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
  {
!   int n_units;
!   int i, k;
!   rtx rvec[GP_ARG_NUM_REG + 1];
! 
!   if (align_words >= GP_ARG_NUM_REG)
!     return NULL_RTX;
! 
!   n_units = rs6000_arg_size (mode, type);
! 
!   /* Optimize the simple case where the arg fits in one gpr.  */
!   if (n_units <= 1)
!     return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
! 
!   k = 0;
!   if (align_words + n_units > GP_ARG_NUM_REG)
!     /* Not all of the arg fits in gprs.  Say that it goes in memory too,
!        using a magic NULL_RTX component.
!        FIXME: This is not strictly correct.  Only some of the arg
!        belongs in memory, not all of it.  However, there isn't any way
!        to do this currently, apart from building rtx descriptions for
!        the pieces of memory we want stored.  Due to bugs in the generic
!        code we can't use the normal function_arg_partial_nregs scheme
!        with the PARALLEL arg description we emit here.
!        In any case, the code to store the whole arg to memory is often
!        more efficient than code to store pieces, and we know that space
!        is available in the right place for the whole arg.  */
!     rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
! 
!   i = 0;
!   do
      {
!       rtx r = gen_rtx_REG (SImode, GP_ARG_MIN_REG + align_words);
!       rtx off = GEN_INT (i++ * 4);
!       rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
      }
!   while (++align_words < GP_ARG_NUM_REG && --n_units != 0);
  
!   return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
  }
  
  /* Determine where to put an argument to a function.
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4616,4623 ****
  	{
  	  /* Vector parameters to varargs functions under AIX or Darwin
  	     get passed in memory and possibly also in GPRs.  */
! 	  int align, align_words;
! 	  enum machine_mode part_mode = mode;
  
  	  /* Vector parameters must be 16-byte aligned.  This places them at
  	     2 mod 4 in terms of words in 32-bit mode, since the parameter
--- 4537,4544 ----
  	{
  	  /* Vector parameters to varargs functions under AIX or Darwin
  	     get passed in memory and possibly also in GPRs.  */
! 	  int align, align_words, n_words;
! 	  enum machine_mode part_mode;
  
  	  /* Vector parameters must be 16-byte aligned.  This places them at
  	     2 mod 4 in terms of words in 32-bit mode, since the parameter
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4633,4652 ****
  	  /* Out of registers?  Memory, then.  */
  	  if (align_words >= GP_ARG_NUM_REG)
  	    return NULL_RTX;
! 	  
  	  /* The vector value goes in GPRs.  Only the part of the
  	     value in GPRs is reported here.  */
! 	  if (align_words + CLASS_MAX_NREGS (mode, GENERAL_REGS)
! 	      > GP_ARG_NUM_REG)
  	    /* Fortunately, there are only two possibilities, the value
  	       is either wholly in GPRs or half in GPRs and half not.  */
  	    part_mode = DImode;
! 	  
! 	  if (TARGET_32BIT
! 	      && (TARGET_POWERPC64 || (align_words == GP_ARG_NUM_REG - 2)))
! 	    return rs6000_mixed_function_arg (cum, part_mode, type, align_words);
! 	  else
! 	    return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
  	}
      }
    else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
--- 4554,4573 ----
  	  /* Out of registers?  Memory, then.  */
  	  if (align_words >= GP_ARG_NUM_REG)
  	    return NULL_RTX;
! 
! 	  if (TARGET_32BIT && TARGET_POWERPC64)
! 	    return rs6000_mixed_function_arg (mode, type, align_words);
! 
  	  /* The vector value goes in GPRs.  Only the part of the
  	     value in GPRs is reported here.  */
! 	  part_mode = mode;
! 	  n_words = rs6000_arg_size (mode, type);
! 	  if (align_words + n_words > GP_ARG_NUM_REG)
  	    /* Fortunately, there are only two possibilities, the value
  	       is either wholly in GPRs or half in GPRs and half not.  */
  	    part_mode = DImode;
! 
! 	  return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
  	}
      }
    else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4673,4682 ****
  	    gregno += (1 - gregno) & 1;
  
  	  /* Multi-reg args are not split between registers and stack.  */
! 	  if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
! 	    return gen_rtx_REG (mode, gregno);
! 	  else
  	    return NULL_RTX;
  	}
      }
    else
--- 4594,4606 ----
  	    gregno += (1 - gregno) & 1;
  
  	  /* Multi-reg args are not split between registers and stack.  */
! 	  if (gregno + n_words - 1 > GP_ARG_MAX_REG)
  	    return NULL_RTX;
+ 
+ 	  if (TARGET_32BIT && TARGET_POWERPC64)
+ 	    return rs6000_mixed_function_arg (mode, type,
+ 					      gregno - GP_ARG_MIN_REG);
+ 	  return gen_rtx_REG (mode, gregno);
  	}
      }
    else
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4686,4710 ****
  
        if (USE_FP_FOR_ARG_P (cum, mode, type))
  	{
! 	  rtx fpr[2];
! 	  rtx *r;
  	  bool needs_psave;
  	  enum machine_mode fmode = mode;
- 	  int n;
  	  unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
  
  	  if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
  	    {
- 	      /* Long double split over regs and memory.  */
- 	      if (fmode == TFmode)
- 		fmode = DFmode;
- 
  	      /* Currently, we only ever need one reg here because complex
  		 doubles are split.  */
! 	      if (cum->fregno != FP_ARG_MAX_REG - 1)
  		abort ();
  	    }
- 	  fpr[1] = gen_rtx_REG (fmode, cum->fregno);
  
  	  /* Do we also need to pass this arg in the parameter save
  	     area?  */
--- 4610,4632 ----
  
        if (USE_FP_FOR_ARG_P (cum, mode, type))
  	{
! 	  rtx rvec[GP_ARG_NUM_REG + 1];
! 	  rtx r;
! 	  int k;
  	  bool needs_psave;
  	  enum machine_mode fmode = mode;
  	  unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
  
  	  if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
  	    {
  	      /* Currently, we only ever need one reg here because complex
  		 doubles are split.  */
! 	      if (cum->fregno != FP_ARG_MAX_REG || fmode != TFmode)
  		abort ();
+ 
+ 	      /* Long double split over regs and memory.  */
+ 	      fmode = DFmode;
  	    }
  
  	  /* Do we also need to pass this arg in the parameter save
  	     area?  */
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4715,4760 ****
  				 && align_words >= GP_ARG_NUM_REG)));
  
  	  if (!needs_psave && mode == fmode)
! 	    return fpr[1];
! 
!           if (TARGET_32BIT && TARGET_POWERPC64
!               && mode == DFmode && cum->stdarg)
!             return rs6000_mixed_function_arg (cum, mode, type, align_words);
! 
! 	  /* Describe where this piece goes.  */
! 	  r = fpr + 1;
! 	  *r = gen_rtx_EXPR_LIST (VOIDmode, *r, const0_rtx);
! 	  n = 1;
  
  	  if (needs_psave)
  	    {
! 	      /* Now describe the part that goes in gprs or the stack.
  		 This piece must come first, before the fprs.  */
- 	      rtx reg = NULL_RTX;
  	      if (align_words < GP_ARG_NUM_REG)
  		{
  		  unsigned long n_words = rs6000_arg_size (mode, type);
- 		  enum machine_mode rmode = mode;
  
! 		  if (align_words + n_words > GP_ARG_NUM_REG)
! 		    /* If this is partially on the stack, then we only
! 		       include the portion actually in registers here.
! 		       We know this can only be one register because
! 		       complex doubles are splt.  */
! 		    rmode = Pmode;
! 		  reg = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words);
  		}
! 	      *--r = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
! 	      ++n;
  	    }
  
! 	  return gen_rtx_PARALLEL (mode, gen_rtvec_v (n, r));
  	}
        else if (align_words < GP_ARG_NUM_REG)
  	{
! 	  if (TARGET_32BIT && TARGET_POWERPC64
! 	      && (mode == DImode || mode == BLKmode))
! 	    return rs6000_mixed_function_arg (cum, mode, type, align_words);
  
  	  return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
  	}
--- 4637,4691 ----
  				 && align_words >= GP_ARG_NUM_REG)));
  
  	  if (!needs_psave && mode == fmode)
! 	    return gen_rtx_REG (fmode, cum->fregno);
  
+ 	  k = 0;
  	  if (needs_psave)
  	    {
! 	      /* Describe the part that goes in gprs or the stack.
  		 This piece must come first, before the fprs.  */
  	      if (align_words < GP_ARG_NUM_REG)
  		{
  		  unsigned long n_words = rs6000_arg_size (mode, type);
  
! 		  if (align_words + n_words > GP_ARG_NUM_REG
! 		      || (TARGET_32BIT && TARGET_POWERPC64))
! 		    {
! 		      /* If this is partially on the stack, then we only
! 			 include the portion actually in registers here.  */
! 		      enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
! 		      rtx off;
! 		      do
! 			{
! 			  r = gen_rtx_REG (rmode,
! 					   GP_ARG_MIN_REG + align_words);
! 			  off = GEN_INT (k * GET_MODE_SIZE (rmode));
! 			  rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
! 			}
! 		      while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
! 		    }
! 		  else
! 		    {
! 		      /* The whole arg fits in gprs.  */
! 		      r = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
! 		      rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
! 		    }
  		}
! 	      else
! 		/* It's entirely in memory.  */
! 		rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
  	    }
  
! 	  /* Describe where this piece goes in the fprs.  */
! 	  r = gen_rtx_REG (fmode, cum->fregno);
! 	  rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, const0_rtx);
! 
! 	  return gen_rtx_PARALLEL (mode, gen_rtvec_v (k, rvec));
  	}
        else if (align_words < GP_ARG_NUM_REG)
  	{
! 	  if (TARGET_32BIT && TARGET_POWERPC64)
! 	    return rs6000_mixed_function_arg (mode, type, align_words);
  
  	  return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
  	}
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4763,4777 ****
      }
  }
  
! /* For an arg passed partly in registers and partly in memory,
!    this is the number of registers used.
!    For args passed entirely in registers or entirely in memory, zero.  */
  
  int
  function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode, 
  			    tree type, int named)
  {
    int ret = 0;
  
    if (DEFAULT_ABI == ABI_V4)
      return 0;
--- 4694,4713 ----
      }
  }
  
! /* For an arg passed partly in registers and partly in memory, this is
!    the number of registers used.  For args passed entirely in registers
!    or entirely in memory, zero.  When an arg is described by a PARALLEL,
!    perhaps using more than one register type, this function returns the
!    number of registers used by the first element of the PARALLEL.  */
  
  int
  function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode, 
  			    tree type, int named)
  {
    int ret = 0;
+   int align;
+   int parm_offset;
+   int align_words;
  
    if (DEFAULT_ABI == ABI_V4)
      return 0;
*************** function_arg_partial_nregs (CUMULATIVE_A
*** 4780,4796 ****
        && cum->nargs_prototype >= 0)
      return 0;
  
!   if (USE_FP_FOR_ARG_P (cum, mode, type))
      {
        if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
! 	ret = FP_ARG_MAX_REG - cum->fregno;
        else if (cum->nargs_prototype >= 0)
  	return 0;
      }
  
!   if (cum->words < GP_ARG_NUM_REG
!       && GP_ARG_NUM_REG < cum->words + rs6000_arg_size (mode, type))
!     ret = GP_ARG_NUM_REG - cum->words;
  
    if (ret != 0 && TARGET_DEBUG_ARG)
      fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
--- 4716,4744 ----
        && cum->nargs_prototype >= 0)
      return 0;
  
!   align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
!   parm_offset = TARGET_32BIT ? 2 : 0;
!   align_words = cum->words + ((parm_offset - cum->words) & align);
! 
!   if (USE_FP_FOR_ARG_P (cum, mode, type)
!       /* If we are passing this arg in gprs as well, then this function
! 	 should return the number of gprs (or memory) partially passed,
! 	 *not* the number of fprs.  */
!       && !(type
! 	   && (cum->nargs_prototype <= 0
! 	       || (DEFAULT_ABI == ABI_AIX
! 		   && TARGET_XL_CALL
! 		   && align_words >= GP_ARG_NUM_REG))))
      {
        if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
! 	ret = FP_ARG_MAX_REG + 1 - cum->fregno;
        else if (cum->nargs_prototype >= 0)
  	return 0;
      }
  
!   if (align_words < GP_ARG_NUM_REG
!       && GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
!     ret = GP_ARG_NUM_REG - align_words;
  
    if (ret != 0 && TARGET_DEBUG_ARG)
      fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]