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]

PowerPC FP constant and profiling changes


	I have ripped out all of the stack PUSH/POP stuff that was causing
ABI problems and replaced it with explicit moves to a temporary register.
This includes having the SVR4 ABI act more like AIX using a register
instead of the dangerous stack save/restore game.  I could not test the
SVR4 changes, so I would appreciate if the LinuxPPC testers would make
sure that I have not broken anything when profiling is enabled.

	I also changed float/double constants to use the IEEE 754
bit-patterns instead of emiting constants as FP values subject to
assembler interpretation.

David


	* rs6000.h (ASM_OUTPUT_{DOUBLE,FLOAT}): Always generate IEEE 754
	bit-pattern directly.
	(ASM_OUTPUT_REG_{PUSH,POP}): Delete.
	* rs6000.c (first_reg_to_save): If profiling and context needed,
	allocate a reg to save static chain for all ABIs.  For AIX
	profiling, calculate parameter registers to save based on need.
	(output_function_profiler): Save and restore static chain around
	profile call for all ABIs. 

Index: rs6000.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.42
diff -c -p -r1.42 rs6000.h
*** rs6000.h	1999/03/05 21:19:46	1.42
--- rs6000.h	1999/03/16 01:38:47
*************** extern char rs6000_reg_names[][8];	/* re
*** 3000,3042 ****
  
  /* This is how to output an assembler line defining a `double' constant.  */
  
! #define ASM_OUTPUT_DOUBLE(FILE, VALUE)					\
!   {									\
!     if (REAL_VALUE_ISINF (VALUE)					\
!         || REAL_VALUE_ISNAN (VALUE)					\
! 	|| REAL_VALUE_MINUS_ZERO (VALUE))				\
!       {									\
! 	long t[2];							\
! 	REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t);			\
! 	fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n",		\
! 		t[0] & 0xffffffff, t[1] & 0xffffffff);			\
!       }									\
!     else								\
!       {									\
! 	char str[30];							\
! 	REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str);			\
! 	fprintf (FILE, "\t.double 0d%s\n", str);			\
!       }									\
    }
  
  /* This is how to output an assembler line defining a `float' constant.  */
  
! #define ASM_OUTPUT_FLOAT(FILE, VALUE)					\
!   {									\
!     if (REAL_VALUE_ISINF (VALUE)					\
!         || REAL_VALUE_ISNAN (VALUE)					\
! 	|| REAL_VALUE_MINUS_ZERO (VALUE))				\
!       {									\
! 	long t;								\
! 	REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t);			\
! 	fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff);		\
!       }									\
!     else								\
!       {									\
! 	char str[30];							\
! 	REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", str);			\
! 	fprintf (FILE, "\t.float 0d%s\n", str);				\
!       }									\
    }
  
  /* This is how to output an assembler line defining an `int' constant.  */
--- 3000,3020 ----
  
  /* This is how to output an assembler line defining a `double' constant.  */
  
! #define ASM_OUTPUT_DOUBLE(FILE, VALUE)			\
!   {							\
!     long t[2];						\
!     REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t);		\
!     fprintf (FILE, "\t.long 0x%lx\n\t.long 0x%lx\n",	\
! 	     t[0] & 0xffffffff, t[1] & 0xffffffff);	\
    }
  
  /* This is how to output an assembler line defining a `float' constant.  */
  
! #define ASM_OUTPUT_FLOAT(FILE, VALUE)			\
!   {							\
!     long t;						\
!     REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t);		\
!     fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff);	\
    }
  
  /* This is how to output an assembler line defining an `int' constant.  */
*************** do {									\
*** 3084,3121 ****
     at P to FILE.  */
  
  #define ASM_OUTPUT_ASCII(FILE, P, N)  output_ascii ((FILE), (P), (N))
- 
- /* This is how to output code to push a register on the stack.
-    It need not be very fast code.
- 
-    On the rs6000, we must keep the backchain up to date.  In order
-    to simplify things, always allocate 16 bytes for a push (System V
-    wants to keep stack aligned to a 16 byte boundary).  */
- 
- #define ASM_OUTPUT_REG_PUSH(FILE,REGNO)					\
- do {									\
-   extern char *reg_names[];						\
-   asm_fprintf (FILE,							\
- 	       (TARGET_32BIT)						\
- 	       ? "\t{stu|stwu} %s,-16(%s)\n\t{st|stw} %s,12(%s)\n"	\
- 	       : "\tstdu %s,-32(%s)\n\tstd %s,24(%s)\n",		\
- 	       reg_names[1], reg_names[1], reg_names[REGNO],		\
- 	       reg_names[1]);						\
- } while (0)
- 
- /* This is how to output an insn to pop a register from the stack.
-    It need not be very fast code.  */
- 
- #define ASM_OUTPUT_REG_POP(FILE,REGNO)					\
- do {									\
-   extern char *reg_names[];						\
-   asm_fprintf (FILE,							\
- 	       (TARGET_32BIT)						\
- 	       ? "\t{l|lwz} %s,12(%s)\n\t{ai|addic} %s,%s,16\n"		\
- 	       : "\tld %s,24(%s)\n\t{ai|addic} %s,%s,32\n",		\
- 	       reg_names[REGNO], reg_names[1], reg_names[1],		\
- 	       reg_names[1]);						\
- } while (0)
  
  /* This is how to output an element of a case-vector that is absolute.
     (RS/6000 does not use such vectors, but we must define this macro
--- 3062,3067 ----
Index: rs6000.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.62
diff -c -p -r1.62 rs6000.c
*** rs6000.c	1999/02/28 12:27:05	1.62
--- rs6000.c	1999/03/16 01:39:04
*************** first_reg_to_save ()
*** 3229,3242 ****
      if (regs_ever_live[first_reg])
        break;
  
!   /* If profiling, then we must save/restore every register that contains
!      a parameter before/after the .__mcount call.  Use registers from 30 down
!      to 23 to do this.  Don't use the frame pointer in reg 31.
! 
!      For now, save enough room for all of the parameter registers.  */
!   if (DEFAULT_ABI == ABI_AIX && profile_flag)
!     if (first_reg > 23)
!       first_reg = 23;
  
    return first_reg;
  }
--- 3229,3274 ----
      if (regs_ever_live[first_reg])
        break;
  
!   if (profile_flag)
!     {
!       /* AIX must save/restore every register that contains a parameter
! 	 before/after the .__mcount call plus an additional register
! 	 for the static chain, if needed; use registers from 30 down to 22
! 	 to do this.  */
!       if (DEFAULT_ABI == ABI_AIX)
! 	{
! 	  int last_parm_reg, profile_first_reg;
! 
! 	  /* Figure out last used parameter register.  The proper thing
! 	     to do is to walk incoming args of the function.  A function
! 	     might have live parameter registers even if it has no
! 	     incoming args.  */
! 	  for (last_parm_reg = 10;
! 	       last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];
! 	       last_parm_reg--)
! 	    ;
! 
! 	  /* Calculate first reg for saving parameter registers
! 	     and static chain.
! 	     Skip reg 31 which may contain the frame pointer.  */
! 	  profile_first_reg = (33 - last_parm_reg
! 			       - (current_function_needs_context ? 1 : 0));
! 	  /* Do not save frame pointer if no parameters needs to be saved.  */
! 	  if (profile_first_reg == 31)
! 	    profile_first_reg = 32;
! 
! 	  if (first_reg > profile_first_reg)
! 	    first_reg = profile_first_reg;
! 	}
! 
!       /* SVR4 may need one register to preserve the static chain.  */
!       else if (current_function_needs_context)
! 	{
! 	  /* Skip reg 31 which may contain the frame pointer.  */
! 	  if (first_reg > 30)
! 	    first_reg = 30;
! 	}
!     }
  
    return first_reg;
  }
*************** output_function_profiler (file, labelno)
*** 5051,5063 ****
  	  asm_fprintf (file, "\t{liu|lis} %s,", reg_names[12]);
  	  assemble_name (file, buf);
  	  fputs ("@ha\n", file);
! 	  asm_fprintf (file, "\t{st|stw} %s,4(%s)\n", reg_names[0], reg_names[1]);
  	  asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
  	  assemble_name (file, buf);
  	  asm_fprintf (file, "@l(%s)\n", reg_names[12]);
  	}
  
        fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
        break;
  
      case ABI_AIX:
--- 5083,5102 ----
  	  asm_fprintf (file, "\t{liu|lis} %s,", reg_names[12]);
  	  assemble_name (file, buf);
  	  fputs ("@ha\n", file);
! 	  asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
! 		       reg_names[0], reg_names[1]);
  	  asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
  	  assemble_name (file, buf);
  	  asm_fprintf (file, "@l(%s)\n", reg_names[12]);
  	}
  
+       if (current_function_needs_context)
+ 	asm_fprintf (file, "\tmr %s,%s\n",
+ 		     reg_names[30], reg_names[STATIC_CHAIN_REGNUM]);
        fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+       if (current_function_needs_context)
+ 	asm_fprintf (file, "\tmr %s,%s\n",
+ 		     reg_names[STATIC_CHAIN_REGNUM], reg_names[30]);
        break;
  
      case ABI_AIX:
*************** output_function_profiler (file, labelno)
*** 5089,5099 ****
  	   last_parm_reg--)
  	;
  
!   /* Save parameter registers in regs 23-30.  Don't overwrite reg 31, since
!      it might be set up as the frame pointer.  */
  
        for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
  	asm_fprintf (file, "\tmr %d,%d\n", j, i);
  
    /* Load location address into r3, and call mcount.  */
  
--- 5128,5140 ----
  	   last_parm_reg--)
  	;
  
!   /* Save parameter registers in regs 23-30 and static chain in r22.
!      Don't overwrite reg 31, since it might be set up as the frame pointer.  */
  
        for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
  	asm_fprintf (file, "\tmr %d,%d\n", j, i);
+       if (current_function_needs_context)
+ 	asm_fprintf (file, "\tmr %d,%d\n", j, STATIC_CHAIN_REGNUM);
  
    /* Load location address into r3, and call mcount.  */
  
*************** output_function_profiler (file, labelno)
*** 5104,5113 ****
        asm_fprintf (file, "(%s)\n\tbl %s\n\t%s\n",
  		   reg_names[2], RS6000_MCOUNT, RS6000_CALL_GLUE);
  
!   /* Restore parameter registers.  */
  
        for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
  	asm_fprintf (file, "\tmr %d,%d\n", i, j);
        break;
      }
  }
--- 5145,5157 ----
        asm_fprintf (file, "(%s)\n\tbl %s\n\t%s\n",
  		   reg_names[2], RS6000_MCOUNT, RS6000_CALL_GLUE);
  
!   /* Restore parameter registers and static chain.  */
  
        for (i = 3, j = 30; i <= last_parm_reg; i++, j--)
  	asm_fprintf (file, "\tmr %d,%d\n", i, j);
+       if (current_function_needs_context)
+ 	asm_fprintf (file, "\tmr %d,%d\n", STATIC_CHAIN_REGNUM, j);
+ 
        break;
      }
  }


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