MIPS patch: fix varargs for -msingle-float -fshort-double

Richard Sandiford rsandifo@redhat.com
Tue Apr 9 04:37:00 GMT 2002


This patch makes the EABI va-arg handler cope with sub-word
register save slots.  As far as I know, they only come about
with the combination:

  -mgp64 -mabi=eabi -msingle-float -fshort-double

Then each floating-point value takes up 4 bytes when stored in the
register save area, but 8 when passed on the stack (because each
stack argument is word-aligned).

Tested by setting the default ABI to EABI for mipsisa32-elf,
no regressions.

OK to install?

Richard


	* config/mips/mips.c (mips_va_arg): For the full EABI va_list, let
        a register save slot take up less room than a stack argument.

Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.189
diff -c -p -d -r1.189 mips.c
*** config/mips/mips.c	5 Apr 2002 08:00:32 -0000	1.189
--- config/mips/mips.c	9 Apr 2002 11:30:09 -0000
*************** mips_va_arg (valist, type)
*** 4582,4587 ****
--- 4592,4598 ----
  	  tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
  	  tree ovfl, top, off;
  	  rtx lab_over = NULL_RTX, lab_false;
+ 	  HOST_WIDE_INT osize;
  
  	  f_ovfl = TYPE_FIELDS (va_list_type_node);
  	  f_gtop = TREE_CHAIN (f_ovfl);
*************** mips_va_arg (valist, type)
*** 4596,4602 ****
  		 TOP be the top of the register save area;
  		 OFF be the offset from TOP of the next register;
  		 ADDR_RTX be the address of the argument; and
! 		 RSIZE be the number of bytes used to store the argument.
  
  	     The code we want is:
  
--- 4607,4617 ----
  		 TOP be the top of the register save area;
  		 OFF be the offset from TOP of the next register;
  		 ADDR_RTX be the address of the argument; and
! 		 RSIZE be the number of bytes used to store the argument
! 		   when it's in the register save area
! 		 OSIZE be the number of bytes used to store it when it's
! 		   in the stack overflow area
! 		 PADDING be (BYTES_BIG_ENDIAN ? OSIZE - RSIZE : 0)
  
  	     The code we want is:
  
*************** mips_va_arg (valist, type)
*** 4608,4617 ****
  		  6:   }
  		  7: else
  		  8:   {
! 		  9:	 ovfl += ((intptr_t) ovfl + rsize - 1) & -rsize;
! 		 10:	 addr_rtx = ovfl;
! 		 11:	 ovfl += rsize;
! 		 12:   }
  
  	     [1] and [9] can sometimes be optimized away.  */
  
--- 4623,4632 ----
  		  6:   }
  		  7: else
  		  8:   {
! 		  9:	 ovfl += ((intptr_t) ovfl + osize - 1) & -osize;
! 		 10:	 addr_rtx = ovfl + PADDING;
! 		 11:	 ovfl += osize;
! 		 14:   }
  
  	     [1] and [9] can sometimes be optimized away.  */
  
*************** mips_va_arg (valist, type)
*** 4643,4648 ****
--- 4658,4670 ----
  		  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  		}
  	    }
+ 	  /* Every overflow argument must take up at least UNITS_PER_WORD
+ 	     bytes (= PARM_BOUNDARY bits).  RSIZE can sometimes be smaller
+ 	     than that, such as in the combination -mgp64 -msingle-float
+ 	     -fshort-double.  Doubles passed in registers will then take
+ 	     up UNITS_PER_FPVALUE bytes, but those passed on the stack
+ 	     take up UNITS_PER_WORD bytes.  */
+ 	  osize = MAX (rsize, UNITS_PER_WORD);
  
  	  /* [2] Emit code to branch if off == 0.  */
  	  r = expand_expr (off, NULL_RTX, TYPE_MODE (TREE_TYPE (off)),
*************** mips_va_arg (valist, type)
*** 4668,4688 ****
  	  emit_barrier ();
  	  emit_label (lab_false);
  
! 	  if (rsize > UNITS_PER_WORD)
  	    {
! 	      /* [9] Emit: ovfl += ((intptr_t) ovfl + rsize - 1) & -rsize.  */
  	      t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl,
! 			 build_int_2 (rsize - 1, 0));
  	      t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t,
! 			 build_int_2 (-rsize, -1));
  	      t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
  	      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  	    }
  
  	  /* [10, 11].	Emit code to store ovfl in addr_rtx, then
! 	     post-increment ovfl by rsize.  */
  	  t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl,
! 		     size_int (rsize));
  	  r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
  	  if (r != addr_rtx)
  	    emit_move_insn (addr_rtx, r);
--- 4690,4714 ----
  	  emit_barrier ();
  	  emit_label (lab_false);
  
! 	  if (osize > UNITS_PER_WORD)
  	    {
! 	      /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize.  */
  	      t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl,
! 			 build_int_2 (osize - 1, 0));
  	      t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t,
! 			 build_int_2 (-osize, -1));
  	      t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
  	      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  	    }
  
  	  /* [10, 11].	Emit code to store ovfl in addr_rtx, then
! 	     post-increment ovfl by osize.  On big-endian machines,
! 	     the argument has OSIZE - RSIZE bytes of leading padding.  */
  	  t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl,
! 		     size_int (osize));
! 	  if (BYTES_BIG_ENDIAN && osize > rsize)
! 	    t = build (PLUS_EXPR, TREE_TYPE (t), t,
! 		       build_int_2 (osize - rsize, 0));
  	  r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
  	  if (r != addr_rtx)
  	    emit_move_insn (addr_rtx, r);



More information about the Gcc-patches mailing list