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]

Re: [PATCH] - Use of powerpc 64bit instructions in 32bit ABI


	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)


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