This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] - Use of powerpc 64bit instructions in 32bit ABI
- From: David Edelsohn <dje at watson dot ibm dot com>
- To: Fariborz Jahanian <fjahanian at apple dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 20 Oct 2003 13:37:03 -0400
- Subject: Re: [PATCH] - Use of powerpc 64bit instructions in 32bit ABI
- References: <200310161519.h9GFJEg25394@makai.watson.ibm.com>
I'm experimenting with the following patch for 64-bit mode with
32-bit ABI.
David
Index: rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.290
diff -c -p -r1.290 rs6000.h
*** rs6000.h 13 Oct 2003 21:16:31 -0000 1.290
--- rs6000.h 20 Oct 2003 01:01:11 -0000
*************** extern enum rs6000_dependence_cost rs600
*** 601,607 ****
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
! #define UNITS_PER_WORD (! TARGET_POWERPC64 ? 4 : 8)
#ifdef IN_LIBGCC2
#define MIN_UNITS_PER_WORD UNITS_PER_WORD
#else
--- 601,607 ----
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
! #define UNITS_PER_WORD (TARGET_32BIT ? 4 : 8)
#ifdef IN_LIBGCC2
#define MIN_UNITS_PER_WORD UNITS_PER_WORD
#else
*************** extern enum rs6000_dependence_cost rs600
*** 964,969 ****
--- 964,971 ----
POWER and PowerPC GPRs hold 32 bits worth;
PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
+ #define UNITS_PER_GPR_WORD (! TARGET_POWERPC64 ? 4 : 8)
+
#define HARD_REGNO_NREGS(REGNO, MODE) \
(FP_REGNO_P (REGNO) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
*************** extern enum rs6000_dependence_cost rs600
*** 971,977 ****
? ((GET_MODE_SIZE (MODE) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD) \
: ALTIVEC_REGNO_P (REGNO) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD) \
! : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
#define ALTIVEC_VECTOR_MODE(MODE) \
((MODE) == V16QImode \
--- 973,984 ----
? ((GET_MODE_SIZE (MODE) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD) \
: ALTIVEC_REGNO_P (REGNO) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD) \
! : ((GET_MODE_SIZE (MODE) + UNITS_PER_GPR_WORD - 1) / UNITS_PER_GPR_WORD))
!
! #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
! ((TARGET_32BIT && TARGET_POWERPC64 \
! && (MODE == DImode || MODE == DFmode) \
! && INT_REGNO_P (REGNO)) ? 1 : 0)
#define ALTIVEC_VECTOR_MODE(MODE) \
((MODE) == V16QImode \
*************** extern enum rs6000_dependence_cost rs600
*** 1011,1017 ****
: SPE_SIMD_REGNO_P (REGNO) && TARGET_SPE && SPE_VECTOR_MODE (MODE) ? 1 \
: CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \
: XER_REGNO_P (REGNO) ? (MODE) == PSImode \
! : GET_MODE_SIZE (MODE) <= UNITS_PER_WORD)
/* Value is 1 if it is a good idea to tie two pseudo registers
when one has mode MODE1 and one has mode MODE2.
--- 1018,1024 ----
: SPE_SIMD_REGNO_P (REGNO) && TARGET_SPE && SPE_VECTOR_MODE (MODE) ? 1 \
: CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \
: XER_REGNO_P (REGNO) ? (MODE) == PSImode \
! : GET_MODE_SIZE (MODE) <= UNITS_PER_GPR_WORD)
/* Value is 1 if it is a good idea to tie two pseudo registers
when one has mode MODE1 and one has mode MODE2.
*************** enum reg_class
*** 1434,1440 ****
#define CLASS_MAX_NREGS(CLASS, MODE) \
(((CLASS) == FLOAT_REGS) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
! : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* Return a class of registers that cannot change FROM mode to TO mode. */
--- 1441,1447 ----
#define CLASS_MAX_NREGS(CLASS, MODE) \
(((CLASS) == FLOAT_REGS) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
! : ((GET_MODE_SIZE (MODE) + UNITS_PER_GPR_WORD - 1) / UNITS_PER_GPR_WORD))
/* Return a class of registers that cannot change FROM mode to TO mode. */
Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.534
diff -c -p -r1.534 rs6000.c
*** rs6000.c 17 Oct 2003 20:20:37 -0000 1.534
--- rs6000.c 20 Oct 2003 01:01:11 -0000
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4040,4045 ****
--- 4064,4116 ----
|| (align_words < GP_ARG_NUM_REG))))
return gen_rtx_REG (mode, cum->fregno);
+ if (TARGET_32BIT && TARGET_POWERPC64 && 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 (mode,
+ 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 (mode,
+ 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 (mode,
+ 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_rtx_CONST_INT (SImode, 4)),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, cum->fregno),
+ const0_rtx)));
+ }
+
return gen_rtx_PARALLEL (mode,
gen_rtvec (2,
gen_rtx_EXPR_LIST (VOIDmode,
*************** function_arg (CUMULATIVE_ARGS *cum, enum
*** 4060,4065 ****
--- 4131,4169 ----
gen_rtx_REG (mode, cum->fregno),
const0_rtx)));
}
+ /* -mpowerpc64 with 32bit ABI splits up a DImode argument into one
+ or two GPRs */
+ else if (TARGET_32BIT && TARGET_POWERPC64 && mode==DImode
+ && align_words < GP_ARG_NUM_REG - 1)
+ {
+ return gen_rtx (PARALLEL, mode,
+ 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_rtx_CONST_INT (SImode,
+ 4))));
+ }
+ else if (TARGET_32BIT && TARGET_POWERPC64 && mode==DImode
+ && align_words == GP_ARG_NUM_REG - 1)
+ {
+ return gen_rtx (PARALLEL, mode,
+ 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 (align_words < GP_ARG_NUM_REG)
return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
else
*************** void
*** 11247,11254 ****
rs6000_emit_prologue (void)
{
rs6000_stack_t *info = rs6000_stack_info ();
! enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
! int reg_size = TARGET_POWERPC64 ? 8 : 4;
rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 12);
rtx frame_reg_rtx = sp_reg_rtx;
--- 11351,11358 ----
rs6000_emit_prologue (void)
{
rs6000_stack_t *info = rs6000_stack_info ();
! enum machine_mode reg_mode = Pmode;
! int reg_size = UNITS_PER_WORD;
rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 12);
rtx frame_reg_rtx = sp_reg_rtx;
*************** rs6000_emit_epilogue (int sibcall)
*** 11713,11720 ****
int sp_offset = 0;
rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
rtx frame_reg_rtx = sp_reg_rtx;
! enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
! int reg_size = TARGET_POWERPC64 ? 8 : 4;
int i;
info = rs6000_stack_info ();
--- 11817,11824 ----
int sp_offset = 0;
rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
rtx frame_reg_rtx = sp_reg_rtx;
! enum machine_mode reg_mode = Pmode;
! int reg_size = UNITS_PER_WORD;
int i;
info = rs6000_stack_info ();
*************** rs6000_function_value (tree valtype, tre
*** 14839,14844 ****
--- 14965,14985 ----
{
enum machine_mode mode;
unsigned int regno;
+
+ if (TYPE_MODE (valtype) == DImode && TARGET_POWERPC64 && TARGET_32BIT)
+ {
+ /* Long long return value need be split in -mpowerpc64, 32bit ABI. */
+ return gen_rtx (PARALLEL, DImode,
+ gen_rtvec (2,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode, GP_ARG_RETURN),
+ const0_rtx),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 1),
+ gen_rtx_CONST_INT
+ (SImode, 4))));
+ }
if ((INTEGRAL_TYPE_P (valtype)
&& TYPE_PRECISION (valtype) < BITS_PER_WORD)