PowerPC FP constant and profiling changes
David Edelsohn
dje@watson.ibm.com
Mon Mar 15 20:04:00 GMT 1999
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;
}
}
More information about the Gcc-patches
mailing list