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]

RFD: More flexibility in defining addressing modes


The Blackfin is able to use a larger class of registers in POST_INC addressing modes than in addressing modes involving PLUS. This can't currently be described to GCC, so I came up with the patch below. It adds two new macros, one to the BASE_REG_CLASS, MODE_BASE_REG_CLASS and MODE_BASE_REG_REG_CLASS family, the other one to the REGNO_OK_FOR_BASE_P, REGNO_MODE_OK_FOR_BASE_P and REGNO_MODE_OK_FOR_REG_BASE_P family. Both new macros take additional arguments OUTER_CODE and INDEX_CODE to describe the context the register appears in: for (mem (plus (basereg) (const_int))), OUTER_CODE would be PLUS and INDEX_CODE would be CONST_INT.

To avoid having to use the increasingly unwieldy macro names, I've added some inline functions that encapsulate the mess of target macros. I've also tried to get rid of references to the REG_OK_FOR_BASE_P variants - I just can't seem to be able to figure out why every port needs to define these on top of REGNO_OK_FOR_BASE_P; I just added a REG_OK_STRICT test to my new base_reg_class function. I hope posting the patch for discussion will be the best way to get enlightened by one port maintainer or another :-) (Zack, you're Cc'ed because I remember you were looking at this stuff a while ago).

For now, I'm only posting this for comment; I've tested bfin-elf and sh-elf compilers (the latter appears to produce identical code with or without the patch) but I'd like to do some further testing (and I think there's one or two REG_OK_FOR_INDEX occurrences remaining that I need to convert). Does anyone disagree with the approach taken in this patch? Does anyone have special addressing mode needs that still can't be described to the compiler even with this infrastructure?


Bernd
Index: caller-save.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/caller-save.c,v
retrieving revision 1.74
diff -c -p -r1.74 caller-save.c
*** caller-save.c	25 Jun 2005 01:59:25 -0000	1.74
--- caller-save.c	18 Aug 2005 15:06:50 -0000
*************** Software Foundation, 51 Franklin Street,
*** 25,30 ****
--- 25,31 ----
  #include "tm.h"
  #include "rtl.h"
  #include "regs.h"
+ #include "addresses.h"
  #include "insn-config.h"
  #include "flags.h"
  #include "hard-reg-set.h"
*************** init_caller_save (void)
*** 157,163 ****
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      if (TEST_HARD_REG_BIT
  	(reg_class_contents
! 	 [(int) MODE_BASE_REG_CLASS (regno_save_mode [i][1])], i))
        break;
  
    gcc_assert (i < FIRST_PSEUDO_REGISTER);
--- 158,164 ----
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      if (TEST_HARD_REG_BIT
  	(reg_class_contents
! 	 [(int) base_reg_class (regno_save_mode [i][1], PLUS, CONST_INT)], i))
        break;
  
    gcc_assert (i < FIRST_PSEUDO_REGISTER);
Index: defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.173
diff -c -p -r1.173 defaults.h
*** defaults.h	11 Aug 2005 00:28:03 -0000	1.173
--- defaults.h	18 Aug 2005 15:06:58 -0000
*************** Software Foundation, 51 Franklin Street,
*** 586,625 ****
  #define	TARGET_FLOAT_FORMAT	IEEE_FLOAT_FORMAT
  #endif
  
- /* Some macros can be defined by the backend in either a mode-dependent
-    or mode-independent form.  The compiler proper should only use the
-    mode-dependent form, providing VOIDmode when the mode is unknown.
-    We can't poison the macros because the backend may reference them.  */
- 
- #ifndef REGNO_MODE_OK_FOR_BASE_P
- #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) REGNO_OK_FOR_BASE_P (REGNO)
- #endif
- 
- #ifndef REG_MODE_OK_FOR_BASE_P
- #define REG_MODE_OK_FOR_BASE_P(REG, MODE) REG_OK_FOR_BASE_P (REG)
- #endif
- 
- /* Determine the register class for registers suitable to be the base
-    address register in a MEM.  Allow the choice to be dependent upon
-    the mode of the memory access.  */
- #ifndef MODE_BASE_REG_CLASS
- #define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS
- #endif
- 
- /* Some machines require a different base register class if the index
-    is a register.  By default, assume that a base register is acceptable.  */
- #ifndef MODE_BASE_REG_REG_CLASS
- #define MODE_BASE_REG_REG_CLASS(MODE) MODE_BASE_REG_CLASS(MODE)
- #endif
- 
- #ifndef REGNO_MODE_OK_FOR_REG_BASE_P
- #define REGNO_MODE_OK_FOR_REG_BASE_P(REGNO, MODE) REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE)
- #endif
- 
- #ifndef REG_MODE_OK_FOR_REG_BASE_P
- #define REG_MODE_OK_FOR_REG_BASE_P(REGNO, MODE) REG_MODE_OK_FOR_BASE_P (REGNO, MODE)
- #endif
- 
  #ifndef LARGEST_EXPONENT_IS_NORMAL
  #define LARGEST_EXPONENT_IS_NORMAL(SIZE) 0
  #endif
--- 586,591 ----
Index: recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.226
diff -c -p -r1.226 recog.c
*** recog.c	10 Aug 2005 09:02:48 -0000	1.226
--- recog.c	18 Aug 2005 15:07:02 -0000
*************** Software Foundation, 51 Franklin Street,
*** 31,36 ****
--- 31,37 ----
  #include "hard-reg-set.h"
  #include "recog.h"
  #include "regs.h"
+ #include "addresses.h"
  #include "expr.h"
  #include "function.h"
  #include "flags.h"
*************** preprocess_constraints (void)
*** 2205,2211 ****
  		case 'p':
  		  op_alt[j].is_address = 1;
  		  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
! 		    [(int) MODE_BASE_REG_CLASS (VOIDmode)];
  		  break;
  
  		case 'g':
--- 2206,2212 ----
  		case 'p':
  		  op_alt[j].is_address = 1;
  		  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
*************** preprocess_constraints (void)
*** 2226,2232 ****
  		      op_alt[j].cl
  			= (reg_class_subunion
  			   [(int) op_alt[j].cl]
! 			   [(int) MODE_BASE_REG_CLASS (VOIDmode)]);
  		      break;
  		    }
  
--- 2227,2234 ----
  		      op_alt[j].cl
  			= (reg_class_subunion
  			   [(int) op_alt[j].cl]
! 			   [(int) base_reg_class (VOIDmode, ADDRESS,
! 						  SCRATCH)]);
  		      break;
  		    }
  
Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.206
diff -c -p -r1.206 regclass.c
*** regclass.c	25 Jun 2005 02:00:52 -0000	1.206
--- regclass.c	18 Aug 2005 15:07:04 -0000
*************** Software Foundation, 51 Franklin Street,
*** 36,41 ****
--- 36,42 ----
  #include "flags.h"
  #include "basic-block.h"
  #include "regs.h"
+ #include "addresses.h"
  #include "function.h"
  #include "insn-config.h"
  #include "recog.h"
*************** static void record_reg_classes (int, int
*** 879,885 ****
  				const char **, rtx, struct costs *,
  				struct reg_pref *);
  static int copy_cost (rtx, enum machine_mode, enum reg_class, int);
! static void record_address_regs (rtx, enum reg_class, int);
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  static int auto_inc_dec_reg_p (rtx, enum machine_mode);
  #endif
--- 880,887 ----
  				const char **, rtx, struct costs *,
  				struct reg_pref *);
  static int copy_cost (rtx, enum machine_mode, enum reg_class, int);
! static void record_address_regs (enum machine_mode, rtx, int, enum rtx_code,
! 				 enum rtx_code, int);
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  static int auto_inc_dec_reg_p (rtx, enum machine_mode);
  #endif
*************** record_operand_costs (rtx insn, struct c
*** 985,996 ****
  	recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
  
        if (MEM_P (recog_data.operand[i]))
! 	record_address_regs (XEXP (recog_data.operand[i], 0),
! 			     MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
        else if (constraints[i][0] == 'p'
  	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
! 	record_address_regs (recog_data.operand[i],
! 			     MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
      }
  
    /* Check for commutative in a separate loop so everything will
--- 987,999 ----
  	recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
  
        if (MEM_P (recog_data.operand[i]))
! 	record_address_regs (GET_MODE (recog_data.operand[i]),
! 			     XEXP (recog_data.operand[i], 0),
! 			     0, MEM, SCRATCH, frequency * 2);
        else if (constraints[i][0] == 'p'
  	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
! 	record_address_regs (VOIDmode, recog_data.operand[i], 0, MEM, SCRATCH,
! 			     frequency * 2);
      }
  
    /* Check for commutative in a separate loop so everything will
*************** scan_one_insn (rtx insn, int pass)
*** 1064,1071 ****
  	-= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
  			      GENERAL_REGS, 1)
  	    * frequency);
!       record_address_regs (XEXP (SET_SRC (set), 0),
! 			   MODE_BASE_REG_CLASS (VOIDmode), frequency * 2);
        return insn;
      }
  
--- 1067,1074 ----
  	-= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
  			      GENERAL_REGS, 1)
  	    * frequency);
!       record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0),
! 			   0, MEM, SCRATCH, frequency * 2);
        return insn;
      }
  
*************** init_reg_autoinc (void)
*** 1170,1175 ****
--- 1173,1184 ----
  	if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
  	  {
  	    REGNO (r) = j;
+ 	    enum reg_class baseclass;
+ 	    /* ??? There are two assumptions here; that the base class does not
+ 	       depend on the exact outer code (POST_INC vs. PRE_INC etc.), and
+ 	       that it does not depend on the machine mode of the memory
+ 	       reference.  */
+ 	    baseclass = base_reg_class (VOIDmode, POST_INC, SCRATCH);
  
  	    for (m = VOIDmode; (int) m < (int) MAX_MACHINE_MODE;
  		 m = (enum machine_mode) ((int) m + 1))
*************** init_reg_autoinc (void)
*** 1178,1198 ****
  		  PUT_MODE (r, m);
  
  		  /* If a register is not directly suitable for an
! 		     auto-increment or decrement addressing mode and
! 		     requires secondary reloads, disallow its class from
! 		     being used in such addresses.  */
  
  		  if ((0
  #ifdef SECONDARY_RELOAD_CLASS
! 		       || (SECONDARY_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
  			   != NO_REGS)
  #else
  #ifdef SECONDARY_INPUT_RELOAD_CLASS
! 		       || (SECONDARY_INPUT_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
  			   != NO_REGS)
  #endif
  #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
! 		       || (SECONDARY_OUTPUT_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
  			   != NO_REGS)
  #endif
  #endif
--- 1187,1208 ----
  		  PUT_MODE (r, m);
  
  		  /* If a register is not directly suitable for an
! 		     auto-increment or decrement addressing mode and moving
! 		     it to a proper base register requires secondary reloads,
! 		     disallow its class from being used in such addresses,
! 		     since reload can't handle that case.  */
  
  		  if ((0
  #ifdef SECONDARY_RELOAD_CLASS
! 		       || (SECONDARY_RELOAD_CLASS (baseclass, m, r)
  			   != NO_REGS)
  #else
  #ifdef SECONDARY_INPUT_RELOAD_CLASS
! 		       || (SECONDARY_INPUT_RELOAD_CLASS (baseclass, m, r)
  			   != NO_REGS)
  #endif
  #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
! 		       || (SECONDARY_OUTPUT_RELOAD_CLASS (baseclass, m, r)
  			   != NO_REGS)
  #endif
  #endif
*************** record_reg_classes (int n_alts, int n_op
*** 1579,1585 ****
  		     address, i.e. BASE_REG_CLASS.  */
  		  classes[i]
  		    = reg_class_subunion[(int) classes[i]]
! 		      [(int) MODE_BASE_REG_CLASS (VOIDmode)];
  		  break;
  
  		case 'm':  case 'o':  case 'V':
--- 1589,1595 ----
  		     address, i.e. BASE_REG_CLASS.  */
  		  classes[i]
  		    = reg_class_subunion[(int) classes[i]]
! 		    [(int) base_reg_class (VOIDmode, SCRATCH, SCRATCH)];
  		  break;
  
  		case 'm':  case 'o':  case 'V':
*************** record_reg_classes (int n_alts, int n_op
*** 1693,1699 ****
  			 address, i.e. BASE_REG_CLASS.  */
  		      classes[i]
  			= reg_class_subunion[(int) classes[i]]
! 			  [(int) MODE_BASE_REG_CLASS (VOIDmode)];
  		    }
  #endif
  		  break;
--- 1703,1709 ----
  			 address, i.e. BASE_REG_CLASS.  */
  		      classes[i]
  			= reg_class_subunion[(int) classes[i]]
! 			[(int) base_reg_class (VOIDmode, SCRATCH, SCRATCH)];
  		    }
  #endif
  		  break;
*************** copy_cost (rtx x, enum machine_mode mode
*** 1940,1948 ****
     can represent half-cost adjustments).  */
  
  static void
! record_address_regs (rtx x, enum reg_class class, int scale)
  {
    enum rtx_code code = GET_CODE (x);
  
    switch (code)
      {
--- 1950,1966 ----
     can represent half-cost adjustments).  */
  
  static void
! record_address_regs (enum machine_mode mode, rtx x, int context,
! 		     enum rtx_code outer_code, enum rtx_code index_code,
! 		     int scale)
  {
    enum rtx_code code = GET_CODE (x);
+   enum reg_class class;
+ 
+   if (context == 1)
+     class = INDEX_REG_CLASS;
+   else
+     class = base_reg_class (mode, outer_code, index_code);
  
    switch (code)
      {
*************** record_address_regs (rtx x, enum reg_cla
*** 1983,2013 ****
  	   be in the first operand.  */
  
  	if (MAX_REGS_PER_ADDRESS == 1)
! 	  record_address_regs (arg0, class, scale);
  
  	/* If index and base registers are the same on this machine, just
  	   record registers in any non-constant operands.  We assume here,
  	   as well as in the tests below, that all addresses are in
  	   canonical form.  */
  
! 	else if (INDEX_REG_CLASS == MODE_BASE_REG_CLASS (VOIDmode))
  	  {
! 	    record_address_regs (arg0, class, scale);
  	    if (! CONSTANT_P (arg1))
! 	      record_address_regs (arg1, class, scale);
  	  }
  
  	/* If the second operand is a constant integer, it doesn't change
  	   what class the first operand must be.  */
  
  	else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
! 	  record_address_regs (arg0, class, scale);
  
  	/* If the second operand is a symbolic constant, the first operand
  	   must be an index register.  */
  
  	else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
! 	  record_address_regs (arg0, INDEX_REG_CLASS, scale);
  
  	/* If both operands are registers but one is already a hard register
  	   of index or reg-base class, give the other the class that the
--- 2001,2031 ----
  	   be in the first operand.  */
  
  	if (MAX_REGS_PER_ADDRESS == 1)
! 	  record_address_regs (mode, arg0, 0, PLUS, code1, scale);
  
  	/* If index and base registers are the same on this machine, just
  	   record registers in any non-constant operands.  We assume here,
  	   as well as in the tests below, that all addresses are in
  	   canonical form.  */
  
! 	else if (INDEX_REG_CLASS == base_reg_class (VOIDmode, PLUS, SCRATCH))
  	  {
! 	    record_address_regs (mode, arg0, context, PLUS, code1, scale);
  	    if (! CONSTANT_P (arg1))
! 	      record_address_regs (mode, arg1, context, PLUS, code0, scale);
  	  }
  
  	/* If the second operand is a constant integer, it doesn't change
  	   what class the first operand must be.  */
  
  	else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
! 	  record_address_regs (mode, arg0, context, PLUS, code1, scale);
  
  	/* If the second operand is a symbolic constant, the first operand
  	   must be an index register.  */
  
  	else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
! 	  record_address_regs (mode, arg0, 1, PLUS, code1, scale);
  
  	/* If both operands are registers but one is already a hard register
  	   of index or reg-base class, give the other the class that the
*************** record_address_regs (rtx x, enum reg_cla
*** 2015,2036 ****
  
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
! 		 && (REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode)
  		     || REG_OK_FOR_INDEX_P (arg0)))
! 	  record_address_regs (arg1,
! 			       REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode)
! 			       ? INDEX_REG_CLASS
! 			       : MODE_BASE_REG_REG_CLASS (VOIDmode),
! 			       scale);
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
! 		 && (REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode)
  		     || REG_OK_FOR_INDEX_P (arg1)))
! 	  record_address_regs (arg0,
! 			       REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode)
! 			       ? INDEX_REG_CLASS
! 			       : MODE_BASE_REG_REG_CLASS (VOIDmode),
! 			       scale);
  
  	/* If one operand is known to be a pointer, it must be the base
  	   with the other operand the index.  Likewise if the other operand
--- 2033,2054 ----
  
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
! 		 && (regno_ok_for_base_p (REGNO (arg0), mode, PLUS, REG)
  		     || REG_OK_FOR_INDEX_P (arg0)))
! 	  record_address_regs (mode, arg1,
! 			       regno_ok_for_base_p (REGNO (arg0), mode, PLUS,
! 						    REG)
! 			       ? 1 : 0,
! 			       PLUS, REG, scale);
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
! 		 && (regno_ok_for_base_p (REGNO (arg1), mode, PLUS, REG)
  		     || REG_OK_FOR_INDEX_P (arg1)))
! 	  record_address_regs (mode, arg0,
! 			       regno_ok_for_base_p (REGNO (arg1), mode, PLUS,
! 						    REG)
! 			       ? 1 : 0,
! 			       PLUS, REG, scale);
  
  	/* If one operand is known to be a pointer, it must be the base
  	   with the other operand the index.  Likewise if the other operand
*************** record_address_regs (rtx x, enum reg_cla
*** 2039,2054 ****
  	else if ((code0 == REG && REG_POINTER (arg0))
  		 || code1 == MULT)
  	  {
! 	    record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode),
! 				 scale);
! 	    record_address_regs (arg1, INDEX_REG_CLASS, scale);
  	  }
  	else if ((code1 == REG && REG_POINTER (arg1))
  		 || code0 == MULT)
  	  {
! 	    record_address_regs (arg0, INDEX_REG_CLASS, scale);
! 	    record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode),
! 				 scale);
  	  }
  
  	/* Otherwise, count equal chances that each might be a base
--- 2057,2070 ----
  	else if ((code0 == REG && REG_POINTER (arg0))
  		 || code1 == MULT)
  	  {
! 	    record_address_regs (mode, arg0, 0, PLUS, code1, scale);
! 	    record_address_regs (mode, arg1, 1, PLUS, code0, scale);
  	  }
  	else if ((code1 == REG && REG_POINTER (arg1))
  		 || code0 == MULT)
  	  {
! 	    record_address_regs (mode, arg0, 1, PLUS, code1, scale);
! 	    record_address_regs (mode, arg1, 0, PLUS, code0, scale);
  	  }
  
  	/* Otherwise, count equal chances that each might be a base
*************** record_address_regs (rtx x, enum reg_cla
*** 2056,2067 ****
  
  	else
  	  {
! 	    record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode),
! 				 scale / 2);
! 	    record_address_regs (arg0, INDEX_REG_CLASS, scale / 2);
! 	    record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode),
! 				 scale / 2);
! 	    record_address_regs (arg1, INDEX_REG_CLASS, scale / 2);
  	  }
        }
        break;
--- 2072,2081 ----
  
  	else
  	  {
! 	    record_address_regs (mode, arg0, 0, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, arg0, 1, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, arg1, 0, PLUS, code0, scale / 2);
! 	    record_address_regs (mode, arg1, 1, PLUS, code0, scale / 2);
  	  }
        }
        break;
*************** record_address_regs (rtx x, enum reg_cla
*** 2071,2081 ****
  	 if it ends up in the wrong place.  */
      case POST_MODIFY:
      case PRE_MODIFY:
!       record_address_regs (XEXP (x, 0), MODE_BASE_REG_CLASS (VOIDmode),
! 			   2 * scale);
        if (REG_P (XEXP (XEXP (x, 1), 1)))
! 	record_address_regs (XEXP (XEXP (x, 1), 1),
! 			     INDEX_REG_CLASS, 2 * scale);
        break;
  
      case POST_INC:
--- 2085,2095 ----
  	 if it ends up in the wrong place.  */
      case POST_MODIFY:
      case PRE_MODIFY:
!       record_address_regs (mode, XEXP (x, 0), 0, code,
! 			   GET_CODE (XEXP (XEXP (x, 1), 1)), 2 * scale);
        if (REG_P (XEXP (XEXP (x, 1), 1)))
! 	record_address_regs (mode, XEXP (XEXP (x, 1), 1), 1, code, REG,
! 			     2 * scale);
        break;
  
      case POST_INC:
*************** record_address_regs (rtx x, enum reg_cla
*** 2093,2099 ****
  	in_inc_dec[REGNO (XEXP (x, 0))] = 1;
  #endif
  
!       record_address_regs (XEXP (x, 0), class, 2 * scale);
        break;
  
      case REG:
--- 2107,2113 ----
  	in_inc_dec[REGNO (XEXP (x, 0))] = 1;
  #endif
  
!       record_address_regs (mode, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
        break;
  
      case REG:
*************** record_address_regs (rtx x, enum reg_cla
*** 2114,2120 ****
  	int i;
  	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  	  if (fmt[i] == 'e')
! 	    record_address_regs (XEXP (x, i), class, scale);
        }
      }
  }
--- 2128,2135 ----
  	int i;
  	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  	  if (fmt[i] == 'e')
! 	    record_address_regs (mode, XEXP (x, i), context, code, SCRATCH,
! 				 scale);
        }
      }
  }
Index: regrename.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regrename.c,v
retrieving revision 1.102
diff -c -p -r1.102 regrename.c
*** regrename.c	5 Jul 2005 16:20:13 -0000	1.102
--- regrename.c	18 Aug 2005 15:07:04 -0000
***************
*** 27,32 ****
--- 27,33 ----
  #include "tm_p.h"
  #include "insn-config.h"
  #include "regs.h"
+ #include "addresses.h"
  #include "hard-reg-set.h"
  #include "basic-block.h"
  #include "reload.h"
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 524,530 ****
  	rtx op1 = orig_op1;
  	rtx *locI = NULL;
  	rtx *locB = NULL;
! 	rtx *locB_reg = NULL;
  
  	if (GET_CODE (op0) == SUBREG)
  	  {
--- 525,531 ----
  	rtx op1 = orig_op1;
  	rtx *locI = NULL;
  	rtx *locB = NULL;
! 	enum rtx_code index_code;
  
  	if (GET_CODE (op0) == SUBREG)
  	  {
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 543,601 ****
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
  	  }
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
  	  }
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  locB = &XEXP (x, 1);
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  locB = &XEXP (x, 0);
  	else if (code0 == REG && code1 == REG)
  	  {
  	    int index_op;
  
! 	    if (REG_OK_FOR_INDEX_P (op0)
! 		&& REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
  	      index_op = 0;
! 	    else if (REG_OK_FOR_INDEX_P (op1)
! 		     && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
  	      index_op = 1;
! 	    else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
  	      index_op = 0;
! 	    else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
  	      index_op = 1;
! 	    else if (REG_OK_FOR_INDEX_P (op1))
  	      index_op = 1;
  	    else
  	      index_op = 0;
  
  	    locI = &XEXP (x, index_op);
! 	    locB_reg = &XEXP (x, !index_op);
  	  }
  	else if (code0 == REG)
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
  	  }
  	else if (code1 == REG)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
  	  }
  
  	if (locI)
  	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
  	if (locB)
! 	  scan_rtx_address (insn, locB, MODE_BASE_REG_CLASS (mode), action, mode);
! 	if (locB_reg)
! 	  scan_rtx_address (insn, locB_reg, MODE_BASE_REG_REG_CLASS (mode),
  			    action, mode);
  	return;
        }
  
--- 544,613 ----
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
+ 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
+ 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  {
! 	    locB = &XEXP (x, 1);
! 	    index_code = GET_CODE (XEXP (x, 0));
! 	  }
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  {
! 	    locB = &XEXP (x, 0);
! 	    index_code = GET_CODE (XEXP (x, 1));
! 	  }
  	else if (code0 == REG && code1 == REG)
  	  {
  	    int index_op;
+ 	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
! 	    if (REGNO_OK_FOR_INDEX_P (regno0)
! 		&& regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (REGNO_OK_FOR_INDEX_P (regno1)
! 		     && regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
! 	    else if (REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
  	    else
  	      index_op = 0;
  
  	    locI = &XEXP (x, index_op);
! 	    locB = &XEXP (x, !index_op);
! 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code0 == REG)
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
+ 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code1 == REG)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
+ 	    index_code = GET_CODE (*locI);
  	  }
  
  	if (locI)
  	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
  	if (locB)
! 	  scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code),
  			    action, mode);
+ 
  	return;
        }
  
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 614,620 ****
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			MODE_BASE_REG_CLASS (GET_MODE (x)), action,
  			GET_MODE (x));
        return;
  
--- 626,632 ----
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
  			GET_MODE (x));
        return;
  
*************** scan_rtx (rtx insn, rtx *loc, enum reg_c
*** 665,671 ****
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			MODE_BASE_REG_CLASS (GET_MODE (x)), action,
  			GET_MODE (x));
        return;
  
--- 677,683 ----
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
  			GET_MODE (x));
        return;
  
*************** replace_oldest_value_addr (rtx *loc, enu
*** 1428,1434 ****
  	rtx op1 = orig_op1;
  	rtx *locI = NULL;
  	rtx *locB = NULL;
! 	rtx *locB_reg = NULL;
  
  	if (GET_CODE (op0) == SUBREG)
  	  {
--- 1440,1446 ----
  	rtx op1 = orig_op1;
  	rtx *locI = NULL;
  	rtx *locB = NULL;
! 	enum rtx_code index_code;
  
  	if (GET_CODE (op0) == SUBREG)
  	  {
*************** replace_oldest_value_addr (rtx *loc, enu
*** 1447,1496 ****
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
  	  }
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
  	  }
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  locB = &XEXP (x, 1);
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  locB = &XEXP (x, 0);
  	else if (code0 == REG && code1 == REG)
  	  {
  	    int index_op;
  
! 	    if (REG_OK_FOR_INDEX_P (op0)
! 		&& REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
  	      index_op = 0;
! 	    else if (REG_OK_FOR_INDEX_P (op1)
! 		     && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
  	      index_op = 1;
! 	    else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
  	      index_op = 0;
! 	    else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
  	      index_op = 1;
! 	    else if (REG_OK_FOR_INDEX_P (op1))
  	      index_op = 1;
  	    else
  	      index_op = 0;
  
  	    locI = &XEXP (x, index_op);
! 	    locB_reg = &XEXP (x, !index_op);
  	  }
  	else if (code0 == REG)
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
  	  }
  	else if (code1 == REG)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
  	  }
  
  	if (locI)
--- 1459,1520 ----
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
+ 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
+ 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  {
! 	    locB = &XEXP (x, 1);
! 	    index_code = GET_CODE (XEXP (x, 0));
! 	  }
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  {
! 	    locB = &XEXP (x, 0);
! 	    index_code = GET_CODE (XEXP (x, 1));
! 	  }
  	else if (code0 == REG && code1 == REG)
  	  {
  	    int index_op;
+ 	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
! 	    if (REGNO_OK_FOR_INDEX_P (regno0)
! 		&& regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (REGNO_OK_FOR_INDEX_P (regno1)
! 		     && regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
! 	    else if (REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
  	    else
  	      index_op = 0;
  
  	    locI = &XEXP (x, index_op);
! 	    locB = &XEXP (x, !index_op);
! 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code0 == REG)
  	  {
  	    locI = &XEXP (x, 0);
  	    locB = &XEXP (x, 1);
+ 	    index_code = GET_CODE (*locI);
  	  }
  	else if (code1 == REG)
  	  {
  	    locI = &XEXP (x, 1);
  	    locB = &XEXP (x, 0);
+ 	    index_code = GET_CODE (*locI);
  	  }
  
  	if (locI)
*************** replace_oldest_value_addr (rtx *loc, enu
*** 1498,1508 ****
  						insn, vd);
  	if (locB)
  	  changed |= replace_oldest_value_addr (locB,
! 						MODE_BASE_REG_CLASS (mode),
! 						mode, insn, vd);
! 	if (locB_reg)
! 	  changed |= replace_oldest_value_addr (locB_reg,
! 						MODE_BASE_REG_REG_CLASS (mode),
  						mode, insn, vd);
  	return changed;
        }
--- 1522,1529 ----
  						insn, vd);
  	if (locB)
  	  changed |= replace_oldest_value_addr (locB,
! 						base_reg_class (mode, PLUS,
! 								index_code),
  						mode, insn, vd);
  	return changed;
        }
*************** static bool
*** 1546,1552 ****
  replace_oldest_value_mem (rtx x, rtx insn, struct value_data *vd)
  {
    return replace_oldest_value_addr (&XEXP (x, 0),
! 				    MODE_BASE_REG_CLASS (GET_MODE (x)),
  				    GET_MODE (x), insn, vd);
  }
  
--- 1567,1574 ----
  replace_oldest_value_mem (rtx x, rtx insn, struct value_data *vd)
  {
    return replace_oldest_value_addr (&XEXP (x, 0),
! 				    base_reg_class (GET_MODE (x), MEM,
! 						    SCRATCH),
  				    GET_MODE (x), insn, vd);
  }
  
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.275
diff -c -p -r1.275 reload.c
*** reload.c	5 Aug 2005 16:06:35 -0000	1.275
--- reload.c	18 Aug 2005 15:07:08 -0000
*************** a register with any other reload.  */
*** 99,104 ****
--- 99,105 ----
  #include "recog.h"
  #include "reload.h"
  #include "regs.h"
+ #include "addresses.h"
  #include "hard-reg-set.h"
  #include "flags.h"
  #include "real.h"
*************** static int find_reloads_address (enum ma
*** 270,276 ****
  static rtx subst_reg_equivs (rtx, rtx);
  static rtx subst_indexed_address (rtx);
  static void update_auto_inc_notes (rtx, int, int);
! static int find_reloads_address_1 (enum machine_mode, rtx, int, rtx *,
  				   int, enum reload_type,int, rtx);
  static void find_reloads_address_part (rtx, rtx *, enum reg_class,
  				       enum machine_mode, int,
--- 271,278 ----
  static rtx subst_reg_equivs (rtx, rtx);
  static rtx subst_indexed_address (rtx);
  static void update_auto_inc_notes (rtx, int, int);
! static int find_reloads_address_1 (enum machine_mode, rtx, int,
! 				   enum rtx_code, enum rtx_code, rtx *,
  				   int, enum reload_type,int, rtx);
  static void find_reloads_address_part (rtx, rtx *, enum reg_class,
  				       enum machine_mode, int,
*************** find_reloads (rtx insn, int replace, int
*** 3173,3179 ****
  	      case 'p':
  		/* All necessary reloads for an address_operand
  		   were handled in find_reloads_address.  */
! 		this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
  		win = 1;
  		badop = 0;
  		break;
--- 3175,3182 ----
  	      case 'p':
  		/* All necessary reloads for an address_operand
  		   were handled in find_reloads_address.  */
! 		this_alternative[i]
! 		  = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
  		win = 1;
  		badop = 0;
  		break;
*************** find_reloads (rtx insn, int replace, int
*** 3377,3383 ****
  
  			/* If we didn't already win, we can reload
  			   the address into a base register.  */
! 			this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
  			badop = 0;
  			break;
  		      }
--- 3380,3387 ----
  
  			/* If we didn't already win, we can reload
  			   the address into a base register.  */
! 			this_alternative[i]
! 			  = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
  			badop = 0;
  			break;
  		      }
*************** find_reloads (rtx insn, int replace, int
*** 3880,3886 ****
  	    operand_reloadnum[i]
  	      = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
  			     &XEXP (recog_data.operand[i], 0), (rtx*) 0,
! 			     MODE_BASE_REG_CLASS (VOIDmode),
  			     GET_MODE (XEXP (recog_data.operand[i], 0)),
  			     VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
  	    rld[operand_reloadnum[i]].inc
--- 3884,3890 ----
  	    operand_reloadnum[i]
  	      = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
  			     &XEXP (recog_data.operand[i], 0), (rtx*) 0,
! 			     base_reg_class (VOIDmode, MEM, SCRATCH),
  			     GET_MODE (XEXP (recog_data.operand[i], 0)),
  			     VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
  	    rld[operand_reloadnum[i]].inc
*************** find_reloads_address (enum machine_mode 
*** 4799,4810 ****
  	 subject of a CLOBBER in this insn.  */
  
        else if (regno < FIRST_PSEUDO_REGISTER
! 	       && REGNO_MODE_OK_FOR_BASE_P (regno, mode)
  	       && ! regno_clobbered_p (regno, this_insn, mode, 0))
  	return 0;
  
        /* If we do not have one of the cases above, we must do the reload.  */
!       push_reload (ad, NULL_RTX, loc, (rtx*) 0, MODE_BASE_REG_CLASS (mode),
  		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
        return 1;
      }
--- 4803,4814 ----
  	 subject of a CLOBBER in this insn.  */
  
        else if (regno < FIRST_PSEUDO_REGISTER
! 	       && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
  	       && ! regno_clobbered_p (regno, this_insn, mode, 0))
  	return 0;
  
        /* If we do not have one of the cases above, we must do the reload.  */
!       push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
  		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
        return 1;
      }
*************** find_reloads_address (enum machine_mode 
*** 4905,4911 ****
  	  /* Must use TEM here, not AD, since it is the one that will
  	     have any subexpressions reloaded, if needed.  */
  	  push_reload (tem, NULL_RTX, loc, (rtx*) 0,
! 		       MODE_BASE_REG_CLASS (mode), GET_MODE (tem),
  		       VOIDmode, 0,
  		       0, opnum, type);
  	  return ! removed_and;
--- 4909,4915 ----
  	  /* Must use TEM here, not AD, since it is the one that will
  	     have any subexpressions reloaded, if needed.  */
  	  push_reload (tem, NULL_RTX, loc, (rtx*) 0,
! 		       base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
  		       VOIDmode, 0,
  		       0, opnum, type);
  	  return ! removed_and;
*************** find_reloads_address (enum machine_mode 
*** 4922,4929 ****
    else if (GET_CODE (ad) == PLUS
  	   && REG_P (XEXP (ad, 0))
  	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
! 	   && REG_MODE_OK_FOR_BASE_P (XEXP (ad, 0), mode)
! 	   && GET_CODE (XEXP (ad, 1)) == CONST_INT)
      {
        /* Unshare the MEM rtx so we can safely alter it.  */
        if (memrefloc)
--- 4926,4935 ----
    else if (GET_CODE (ad) == PLUS
  	   && REG_P (XEXP (ad, 0))
  	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
! 	   && GET_CODE (XEXP (ad, 1)) == CONST_INT
! 	   && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
! 				   CONST_INT))
! 
      {
        /* Unshare the MEM rtx so we can safely alter it.  */
        if (memrefloc)
*************** find_reloads_address (enum machine_mode 
*** 4951,4957 ****
  	  /* If the sum of two regs is not necessarily valid,
  	     reload the sum into a base reg.
  	     That will at least work.  */
! 	  find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
  				     Pmode, opnum, type, ind_levels);
  	}
        return ! removed_and;
--- 4957,4964 ----
  	  /* If the sum of two regs is not necessarily valid,
  	     reload the sum into a base reg.
  	     That will at least work.  */
! 	  find_reloads_address_part (ad, loc,
! 				     base_reg_class (mode, MEM, SCRATCH),
  				     Pmode, opnum, type, ind_levels);
  	}
        return ! removed_and;
*************** find_reloads_address (enum machine_mode 
*** 4985,5003 ****
  
    for (op_index = 0; op_index < 2; ++op_index)
      {
!       rtx operand;
  
        if (!(GET_CODE (ad) == PLUS 
  	    && GET_CODE (XEXP (ad, 1)) == CONST_INT
! 	    && (GET_CODE (XEXP (ad, 0)) == PLUS
! 		|| GET_CODE (XEXP (ad, 0)) == LO_SUM)))
  	continue;
  
        operand = XEXP (XEXP (ad, 0), op_index);
        if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
  	continue;
  
!       if ((REG_MODE_OK_FOR_BASE_P (operand, mode)
  	   || operand == frame_pointer_rtx
  #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
  	   || operand == hard_frame_pointer_rtx
--- 4992,5017 ----
  
    for (op_index = 0; op_index < 2; ++op_index)
      {
!       rtx operand, addend;
!       enum rtx_code inner_code;
! 
!       if (GET_CODE (ad) != PLUS)
! 	  continue;
  
+       inner_code = GET_CODE (XEXP (ad, 0));
        if (!(GET_CODE (ad) == PLUS 
  	    && GET_CODE (XEXP (ad, 1)) == CONST_INT
! 	    && (inner_code == PLUS || inner_code == LO_SUM)))
  	continue;
  
        operand = XEXP (XEXP (ad, 0), op_index);
        if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
  	continue;
  
!       addend = XEXP (XEXP (ad, 0), 1 - op_index);
! 
!       if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
! 				GET_CODE (addend))
  	   || operand == frame_pointer_rtx
  #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
  	   || operand == hard_frame_pointer_rtx
*************** find_reloads_address (enum machine_mode 
*** 5010,5020 ****
  				       &XEXP (XEXP (ad, 0), 1 - op_index)))
  	{
  	  rtx offset_reg;
! 	  rtx addend;
  
  	  offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
! 	  addend = XEXP (XEXP (ad, 0), 1 - op_index);
! 	  
  	  /* Form the adjusted address.  */
  	  if (GET_CODE (XEXP (ad, 0)) == PLUS)
  	    ad = gen_rtx_PLUS (GET_MODE (ad), 
--- 5024,5033 ----
  				       &XEXP (XEXP (ad, 0), 1 - op_index)))
  	{
  	  rtx offset_reg;
! 	  enum reg_class cls;
  
  	  offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
! 
  	  /* Form the adjusted address.  */
  	  if (GET_CODE (XEXP (ad, 0)) == PLUS)
  	    ad = gen_rtx_PLUS (GET_MODE (ad), 
*************** find_reloads_address (enum machine_mode 
*** 5026,5037 ****
  				 op_index == 0 ? addend : offset_reg);
  	  *loc = ad;
  
  	  find_reloads_address_part (XEXP (ad, op_index), 
! 				     &XEXP (ad, op_index),
! 				     MODE_BASE_REG_CLASS (mode),
  				     GET_MODE (ad), opnum, type, ind_levels);
! 	  find_reloads_address_1 (mode, 
! 				  XEXP (ad, 1 - op_index), 1, 
  				  &XEXP (ad, 1 - op_index), opnum,
  				  type, 0, insn);
  
--- 5039,5050 ----
  				 op_index == 0 ? addend : offset_reg);
  	  *loc = ad;
  
+ 	  cls = base_reg_class (mode, MEM, GET_CODE (addend));
  	  find_reloads_address_part (XEXP (ad, op_index), 
! 				     &XEXP (ad, op_index), cls,
  				     GET_MODE (ad), opnum, type, ind_levels);
! 	  find_reloads_address_1 (mode,
! 				  XEXP (ad, 1 - op_index), 1, MEM, SCRATCH,
  				  &XEXP (ad, 1 - op_index), opnum,
  				  type, 0, insn);
  
*************** find_reloads_address (enum machine_mode 
*** 5077,5089 ****
  	    loc = &XEXP (*loc, 0);
  	}
  
!       find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
  				 Pmode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
!   return find_reloads_address_1 (mode, ad, 0, loc, opnum, type, ind_levels,
! 				 insn);
  }
  
  /* Find all pseudo regs appearing in AD
--- 5090,5102 ----
  	    loc = &XEXP (*loc, 0);
  	}
  
!       find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
  				 Pmode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
!   return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
! 				 ind_levels, insn);
  }
  
  /* Find all pseudo regs appearing in AD
*************** update_auto_inc_notes (rtx insn ATTRIBUT
*** 5294,5302 ****
     is strictly valid.)
  
     CONTEXT = 1 means we are considering regs as index regs,
!    = 0 means we are considering them as base regs, = 2 means we
!    are considering them as base regs for REG + REG.
! 
     OPNUM and TYPE specify the purpose of any reloads made.
  
     IND_LEVELS says how many levels of indirect addressing are
--- 5307,5318 ----
     is strictly valid.)
  
     CONTEXT = 1 means we are considering regs as index regs,
!    = 0 means we are considering them as base regs.
!    OUTER_CODE is the code of the enclosing RTX, typically a MEM, a PLUS,
!    or an autoinc code.
!    If CONTEXT == 0 and OUTER_CODE is a PLUS or LO_SUM, then INDEX_CODE
!    is the code of the index part of the address.  Otherwise, pass SCRATCH
!    for this argument.
     OPNUM and TYPE specify the purpose of any reloads made.
  
     IND_LEVELS says how many levels of indirect addressing are
*************** update_auto_inc_notes (rtx insn ATTRIBUT
*** 5315,5339 ****
  
  static int
  find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
  			rtx *loc, int opnum, enum reload_type type,
  			int ind_levels, rtx insn)
  {
! #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE)		\
!   ((CONTEXT) == 2					\
!    ? REGNO_MODE_OK_FOR_REG_BASE_P (REGNO, MODE)		\
!    : (CONTEXT) == 1					\
!    ? REGNO_OK_FOR_INDEX_P (REGNO)			\
!    : REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE))
  
    enum reg_class context_reg_class;
    RTX_CODE code = GET_CODE (x);
  
!   if (context == 2)
!     context_reg_class = MODE_BASE_REG_REG_CLASS (mode);
!   else if (context == 1)
      context_reg_class = INDEX_REG_CLASS;
    else
!     context_reg_class = MODE_BASE_REG_CLASS (mode);
  
    switch (code)
      {
--- 5331,5352 ----
  
  static int
  find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
+ 			enum rtx_code outer_code, enum rtx_code index_code,
  			rtx *loc, int opnum, enum reload_type type,
  			int ind_levels, rtx insn)
  {
! #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE)			\
!   ((CONTEXT) == 0							\
!    ? regno_ok_for_base_p (REGNO, MODE, outer_code, index_code) \
!    : REGNO_OK_FOR_INDEX_P (REGNO))					
  
    enum reg_class context_reg_class;
    RTX_CODE code = GET_CODE (x);
  
!   if (context == 1)
      context_reg_class = INDEX_REG_CLASS;
    else
!     context_reg_class = base_reg_class (mode, outer_code, index_code);
  
    switch (code)
      {
*************** find_reloads_address_1 (enum machine_mod
*** 5390,5463 ****
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
  	    || code0 == ZERO_EXTEND || code1 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
! 				    type, ind_levels, insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
! 				    type, ind_levels, insn);
  	  }
  
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
! 				    type, ind_levels, insn);
! 	    find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
! 				    type, ind_levels, insn);
  	  }
  
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
! 				  type, ind_levels, insn);
  
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
! 				  type, ind_levels, insn);
  
  	else if (code0 == REG && code1 == REG)
  	  {
! 	    if (REG_OK_FOR_INDEX_P (op0)
! 		&& REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
  	      return 0;
! 	    else if (REG_OK_FOR_INDEX_P (op1)
! 		     && REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
  	      return 0;
! 	    else if (REG_MODE_OK_FOR_REG_BASE_P (op1, mode))
! 	      find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
! 				      type, ind_levels, insn);
! 	    else if (REG_MODE_OK_FOR_REG_BASE_P (op0, mode))
! 	      find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
! 				      type, ind_levels, insn);
! 	    else if (REG_OK_FOR_INDEX_P (op1))
! 	      find_reloads_address_1 (mode, orig_op0, 2, &XEXP (x, 0), opnum,
! 				      type, ind_levels, insn);
! 	    else if (REG_OK_FOR_INDEX_P (op0))
! 	      find_reloads_address_1 (mode, orig_op1, 2, &XEXP (x, 1), opnum,
! 				      type, ind_levels, insn);
  	    else
  	      {
! 		find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
! 					type, ind_levels, insn);
! 		find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
! 					type, ind_levels, insn);
  	      }
  	  }
  
  	else if (code0 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, &XEXP (x, 0), opnum,
! 				    type, ind_levels, insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, &XEXP (x, 1), opnum,
! 				    type, ind_levels, insn);
  	  }
  
  	else if (code1 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op1, 1, &XEXP (x, 1), opnum,
! 				    type, ind_levels, insn);
! 	    find_reloads_address_1 (mode, orig_op0, 0, &XEXP (x, 0), opnum,
! 				    type, ind_levels, insn);
  	  }
        }
  
--- 5403,5492 ----
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
  	    || code0 == ZERO_EXTEND || code1 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
! 				    &XEXP (x, 0), opnum, type, ind_levels,
! 				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
! 				    &XEXP (x, 1), opnum, type, ind_levels,
! 				    insn);
  	  }
  
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
! 				    &XEXP (x, 0), opnum, type, ind_levels,
! 				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
! 				    &XEXP (x, 1), opnum, type, ind_levels,
! 				    insn);
  	  }
  
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
! 				  &XEXP (x, 1), opnum, type, ind_levels,
! 				  insn);
  
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
! 				  &XEXP (x, 0), opnum, type, ind_levels,
! 				  insn);
  
  	else if (code0 == REG && code1 == REG)
  	  {
! 	    if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
! 		&& regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
  	      return 0;
! 	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
! 		     && regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
  	      return 0;
! 	    else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
! 	      find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
! 				      &XEXP (x, 0), opnum, type, ind_levels,
! 				      insn);
! 	    else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
! 	      find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
! 				      &XEXP (x, 1), opnum, type, ind_levels,
! 				      insn);
! 	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
! 	      find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
! 				      &XEXP (x, 0), opnum, type, ind_levels,
! 				      insn);
! 	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
! 	      find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
! 				      &XEXP (x, 1), opnum, type, ind_levels,
! 				      insn);
  	    else
  	      {
! 		find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
! 					&XEXP (x, 0), opnum, type, ind_levels,
! 					insn);
! 		find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
! 					&XEXP (x, 1), opnum, type, ind_levels,
! 					insn);
  	      }
  	  }
  
  	else if (code0 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
! 				    &XEXP (x, 0), opnum, type, ind_levels,
! 				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
! 				    &XEXP (x, 1), opnum, type, ind_levels,
! 				    insn);
  	  }
  
  	else if (code1 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
! 				    &XEXP (x, 1), opnum, type, ind_levels,
! 				    insn);
! 	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
! 				    &XEXP (x, 0), opnum, type, ind_levels,
! 				    insn);
  	  }
        }
  
*************** find_reloads_address_1 (enum machine_mod
*** 5468,5473 ****
--- 5497,5503 ----
        {
  	rtx op0 = XEXP (x, 0);
  	rtx op1 = XEXP (x, 1);
+ 	enum rtx_code index_code;
  	int regno;
  	int reloadnum;
  
*************** find_reloads_address_1 (enum machine_mod
*** 5486,5497 ****
  	   register with its equivalent constant where applicable.  */
  	if (REG_P (XEXP (op1, 1)))
  	  if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
! 	    find_reloads_address_1 (mode, XEXP (op1, 1), 1, &XEXP (op1, 1),
! 				    opnum, type, ind_levels, insn);
  
  	gcc_assert (REG_P (XEXP (op1, 0)));
  
  	regno = REGNO (XEXP (op1, 0));
  
  	/* A register that is incremented cannot be constant!  */
  	gcc_assert (regno < FIRST_PSEUDO_REGISTER
--- 5516,5529 ----
  	   register with its equivalent constant where applicable.  */
  	if (REG_P (XEXP (op1, 1)))
  	  if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
! 	    find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
! 				    &XEXP (op1, 1), opnum, type, ind_levels,
! 				    insn);
  
  	gcc_assert (REG_P (XEXP (op1, 0)));
  
  	regno = REGNO (XEXP (op1, 0));
+ 	index_code = GET_CODE (XEXP (op1, 1));
  
  	/* A register that is incremented cannot be constant!  */
  	gcc_assert (regno < FIRST_PSEUDO_REGISTER
*************** find_reloads_address_1 (enum machine_mod
*** 5518,5529 ****
  				      ind_levels, insn);
  
  		/* Then reload the memory location into a base
! 		    register.  */
  		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
! 					  &XEXP (op1, 0),
! 					  MODE_BASE_REG_CLASS (mode),
! 					  GET_MODE (x), GET_MODE (x), 0,
! 					  0, opnum, RELOAD_OTHER);
  
  		update_auto_inc_notes (this_insn, regno, reloadnum);
  		return 0;
--- 5550,5562 ----
  				      ind_levels, insn);
  
  		/* Then reload the memory location into a base
! 		   register.  */
  		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
! 					 &XEXP (op1, 0),
! 					 base_reg_class (mode, code,
! 							 index_code),
! 					 GET_MODE (x), GET_MODE (x), 0,
! 					 0, opnum, RELOAD_OTHER);
  
  		update_auto_inc_notes (this_insn, regno, reloadnum);
  		return 0;
*************** find_reloads_address_1 (enum machine_mod
*** 5534,5546 ****
  	  regno = reg_renumber[regno];
  
  	/* We require a base register here...  */
! 	if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
  	  {
  	    reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
! 				      &XEXP (op1, 0), &XEXP (x, 0),
! 				      MODE_BASE_REG_CLASS (mode),
! 				      GET_MODE (x), GET_MODE (x), 0, 0,
! 				      opnum, RELOAD_OTHER);
  
  	    update_auto_inc_notes (this_insn, regno, reloadnum);
  	    return 0;
--- 5567,5579 ----
  	  regno = reg_renumber[regno];
  
  	/* We require a base register here...  */
! 	if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
  	  {
  	    reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
! 				     &XEXP (op1, 0), &XEXP (x, 0),
! 				     base_reg_class (mode, code, index_code),
! 				     GET_MODE (x), GET_MODE (x), 0, 0,
! 				     opnum, RELOAD_OTHER);
  
  	    update_auto_inc_notes (this_insn, regno, reloadnum);
  	    return 0;
*************** find_reloads_address_1 (enum machine_mod
*** 5826,5833 ****
      for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        {
  	if (fmt[i] == 'e')
! 	  find_reloads_address_1 (mode, XEXP (x, i), context, &XEXP (x, i),
! 				  opnum, type, ind_levels, insn);
        }
    }
  
--- 5859,5868 ----
      for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        {
  	if (fmt[i] == 'e')
! 	  /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
! 	     we get here.  */
! 	  find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
! 				  &XEXP (x, i), opnum, type, ind_levels, insn);
        }
    }
  
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.478
diff -c -p -r1.478 reload1.c
*** reload1.c	1 Aug 2005 03:54:47 -0000	1.478
--- reload1.c	18 Aug 2005 15:07:13 -0000
*************** Software Foundation, 51 Franklin Street,
*** 35,40 ****
--- 35,41 ----
  #include "expr.h"
  #include "optabs.h"
  #include "regs.h"
+ #include "addresses.h"
  #include "basic-block.h"
  #include "reload.h"
  #include "recog.h"
*************** maybe_fix_stack_asms (void)
*** 1363,1369 ****
  
  		case 'p':
  		  cls = (int) reg_class_subunion[cls]
! 		    [(int) MODE_BASE_REG_CLASS (VOIDmode)];
  		  break;
  
  		case 'g':
--- 1364,1370 ----
  
  		case 'p':
  		  cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
*************** maybe_fix_stack_asms (void)
*** 1374,1380 ****
  		default:
  		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
  		    cls = (int) reg_class_subunion[cls]
! 		      [(int) MODE_BASE_REG_CLASS (VOIDmode)];
  		  else
  		    cls = (int) reg_class_subunion[cls]
  		      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
--- 1375,1381 ----
  		default:
  		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
  		    cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  else
  		    cls = (int) reg_class_subunion[cls]
  		      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
Index: config/bfin/bfin.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/bfin/bfin.c,v
retrieving revision 1.20
diff -c -p -r1.20 bfin.c
*** config/bfin/bfin.c	9 Aug 2005 09:47:52 -0000	1.20
--- config/bfin/bfin.c	18 Aug 2005 15:07:15 -0000
*************** static e_funkind funkind (tree funtype)
*** 127,133 ****
     necessary.  PICREG is the register holding the pointer to the PIC offset
     table.  */
  
! rtx
  legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
  {
    rtx addr = orig;
--- 127,133 ----
     necessary.  PICREG is the register holding the pointer to the PIC offset
     table.  */
  
! static rtx
  legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
  {
    rtx addr = orig;
*************** bfin_valid_add (enum machine_mode mode, 
*** 2073,2082 ****
  }
  
  static bool
! bfin_valid_reg_p (unsigned int regno, int strict)
  {
!   return ((strict && REGNO_OK_FOR_BASE_STRICT_P (regno))
! 	  || (!strict && REGNO_OK_FOR_BASE_NONSTRICT_P (regno)));
  }
  
  bool
--- 2073,2085 ----
  }
  
  static bool
! bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
! 		  enum rtx_code outer_code)
  {
!   if (strict)
!     return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
!   else
!     return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
  }
  
  bool
*************** bfin_legitimate_address_p (enum machine_
*** 2084,2095 ****
  {
    switch (GET_CODE (x)) {
    case REG:
!     if (bfin_valid_reg_p (REGNO (x), strict))
        return true;
      break;
    case PLUS:
      if (REG_P (XEXP (x, 0))
! 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict)
  	&& (GET_CODE (XEXP (x, 1)) == UNSPEC
  	    || (GET_CODE (XEXP (x, 1)) == CONST_INT
  		&& bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
--- 2087,2098 ----
  {
    switch (GET_CODE (x)) {
    case REG:
!     if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
        return true;
      break;
    case PLUS:
      if (REG_P (XEXP (x, 0))
! 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
  	&& (GET_CODE (XEXP (x, 1)) == UNSPEC
  	    || (GET_CODE (XEXP (x, 1)) == CONST_INT
  		&& bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
*************** bfin_legitimate_address_p (enum machine_
*** 2099,2111 ****
    case POST_DEC:
      if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
  	&& REG_P (XEXP (x, 0))
! 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
        return true;
    case PRE_DEC:
      if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
  	&& XEXP (x, 0) == stack_pointer_rtx
  	&& REG_P (XEXP (x, 0))
! 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
        return true;
      break;
    default:
--- 2102,2114 ----
    case POST_DEC:
      if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
  	&& REG_P (XEXP (x, 0))
! 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
        return true;
    case PRE_DEC:
      if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
  	&& XEXP (x, 0) == stack_pointer_rtx
  	&& REG_P (XEXP (x, 0))
! 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
        return true;
      break;
    default:
Index: config/bfin/bfin.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/bfin/bfin.h,v
retrieving revision 1.13
diff -c -p -r1.13 bfin.h
*** config/bfin/bfin.h	6 Aug 2005 13:26:03 -0000	1.13
--- config/bfin/bfin.h	18 Aug 2005 15:07:16 -0000
*************** extern const char *bfin_library_id_strin
*** 213,221 ****
  
  #define FIRST_PSEUDO_REGISTER 44
  
! #define PREG_P(X) (REG_P (X) && REGNO (X) >= REG_P0 && REGNO (X) <= REG_P7)
  #define ADDRESS_REGNO_P(X) ((X) >= REG_P0 && (X) <= REG_M3)
  #define D_REGNO_P(X) ((X) <= REG_R7)
  
  #define REGISTER_NAMES { \
    "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", \
--- 213,225 ----
  
  #define FIRST_PSEUDO_REGISTER 44
  
! #define PREG_P(X) (REG_P (X) && P_REGNO_P (REGNO (X)))
! #define IREG_P(X) (REG_P (X) && I_REGNO_P (REGNO (X)))
  #define ADDRESS_REGNO_P(X) ((X) >= REG_P0 && (X) <= REG_M3)
  #define D_REGNO_P(X) ((X) <= REG_R7)
+ #define P_REGNO_P(X) ((X) >= REG_P0 && (X) <= REG_P7)
+ #define I_REGNO_P(X) \
+   ((X) == REG_I0 || (X) == REG_I1 || (X) == REG_I2 || (X) == REG_I3)
  
  #define REGISTER_NAMES { \
    "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", \
*************** enum reg_class
*** 342,347 ****
--- 346,352 ----
    DREGS,
    PREGS_CLOBBERED,
    PREGS,
+   IPREGS,
    DPREGS,
    MOST_REGS,
    PROLOGUE_REGS,
*************** enum reg_class
*** 372,377 ****
--- 377,383 ----
     "DREGS",		\
     "PREGS_CLOBBERED",	\
     "PREGS",		\
+    "IPREGS",		\
     "DPREGS",		\
     "MOST_REGS",		\
     "PROLOGUE_REGS",	\
*************** enum reg_class
*** 410,436 ****
      { 0x000000ff,    0 },		/* DREGS */   \
      { 0x00004700,    0x800 },		/* PREGS_CLOBBERED */   \
      { 0x0000ff00,    0x800 },		/* PREGS */   \
      { 0x0000ffff,    0x800 },		/* DPREGS */   \
      { 0xffffffff,    0x800 },		/* MOST_REGS */\
      { 0x00000000,    0x7f8 },		/* PROLOGUE_REGS */\
      { 0xffffffff,    0xff8 },		/* NON_A_CC_REGS */\
      { 0xffffffff,    0xfff }}		/* ALL_REGS */
  
! #define BASE_REG_CLASS          PREGS
  #define INDEX_REG_CLASS         PREGS
  
! #define REGNO_OK_FOR_BASE_STRICT_P(X) (REGNO_REG_CLASS (X) == BASE_REG_CLASS)
! #define REGNO_OK_FOR_BASE_NONSTRICT_P(X)  \
!  (((X) >= FIRST_PSEUDO_REGISTER) || REGNO_REG_CLASS (X) == BASE_REG_CLASS)
  
  #ifdef REG_OK_STRICT
! #define REGNO_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_STRICT_P (X)
  #else
! #define REGNO_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_NONSTRICT_P (X)
  #endif
  
- #define REG_OK_FOR_BASE_P(X)    (REG_P (X) && REGNO_OK_FOR_BASE_P (REGNO (X)))
- #define REG_OK_FOR_INDEX_P(X)   0
  #define REGNO_OK_FOR_INDEX_P(X)   0
  
  /* Get reg_class from a letter such as appears in the machine description.  */
--- 416,455 ----
      { 0x000000ff,    0 },		/* DREGS */   \
      { 0x00004700,    0x800 },		/* PREGS_CLOBBERED */   \
      { 0x0000ff00,    0x800 },		/* PREGS */   \
+     { 0x0249ff00,    0x800 },		/* IPREGS */	\
      { 0x0000ffff,    0x800 },		/* DPREGS */   \
      { 0xffffffff,    0x800 },		/* MOST_REGS */\
      { 0x00000000,    0x7f8 },		/* PROLOGUE_REGS */\
      { 0xffffffff,    0xff8 },		/* NON_A_CC_REGS */\
      { 0xffffffff,    0xfff }}		/* ALL_REGS */
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, OUTER, INDEX) \
!   ((MODE) != QImode \
!    && ((OUTER) == POST_INC || (OUTER) == PRE_INC	     \
!        || (OUTER) == POST_DEC || (OUTER) == PRE_DEC)	     \
!    ? IPREGS : PREGS)
! 
  #define INDEX_REG_CLASS         PREGS
  
! #define REGNO_OK_FOR_BASE_STRICT_P(X, MODE, OUTER, INDEX)	\
!   (P_REGNO_P (X) || (X) == REG_ARGP				\
!    || (((OUTER) == POST_INC || (OUTER) == PRE_INC		\
! 	|| (OUTER) == POST_DEC || (OUTER) == PRE_DEC)		\
!        && (MODE) != QImode					\
!        && I_REGNO_P (X)))
! 
! #define REGNO_OK_FOR_BASE_NONSTRICT_P(X, MODE, OUTER, INDEX)	\
!   ((X) >= FIRST_PSEUDO_REGISTER					\
!    || REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX))
  
  #ifdef REG_OK_STRICT
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \
!   REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX)
  #else
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \
!   REGNO_OK_FOR_BASE_NONSTRICT_P (X, MODE, OUTER, INDEX)
  #endif
  
  #define REGNO_OK_FOR_INDEX_P(X)   0
  
  /* Get reg_class from a letter such as appears in the machine description.  */
*************** enum reg_class
*** 462,468 ****
  #define REGNO_REG_CLASS(REGNO) \
   ((REGNO) < REG_P0 ? DREGS				\
   : (REGNO) < REG_I0 ? PREGS				\
!  : (REGNO) == REG_ARGP ? BASE_REG_CLASS			\
   : (REGNO) >= REG_I0 && (REGNO) <= REG_I3 ? IREGS	\
   : (REGNO) >= REG_L0 && (REGNO) <= REG_L3 ? LREGS	\
   : (REGNO) >= REG_B0 && (REGNO) <= REG_B3 ? BREGS	\
--- 481,487 ----
  #define REGNO_REG_CLASS(REGNO) \
   ((REGNO) < REG_P0 ? DREGS				\
   : (REGNO) < REG_I0 ? PREGS				\
!  : (REGNO) == REG_ARGP ? PREGS				\
   : (REGNO) >= REG_I0 && (REGNO) <= REG_I3 ? IREGS	\
   : (REGNO) >= REG_L0 && (REGNO) <= REG_L3 ? LREGS	\
   : (REGNO) >= REG_B0 && (REGNO) <= REG_B3 ? BREGS	\
--- /dev/null	2005-03-19 20:36:14.000000000 +0100
+++ addresses.h	2005-08-18 15:33:04.000000000 +0200
@@ -0,0 +1,76 @@
+/* Inline functions to test validity of reg classes for addressing modes.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
+
+/* Accessor function to unify target macros MODE_CODE_BASE_REG_CLASS,
+   MODE_BASE_REG_REG_CLASS, MODE_BASE_REG_CLASS and BASE_REG_CLASS.
+   Arguments as for the MODE_CODE_BASE_REG_CLASS macro.  */
+
+static inline enum reg_class
+base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+		enum rtx_code outer_code ATTRIBUTE_UNUSED,
+		enum rtx_code index_code ATTRIBUTE_UNUSED)
+{
+#ifdef MODE_CODE_BASE_REG_CLASS
+  return MODE_CODE_BASE_REG_CLASS (mode, outer_code, index_code);
+#else
+#ifdef MODE_BASE_REG_REG_CLASS
+  if (index_code == REG)
+    return MODE_BASE_REG_REG_CLASS (mode);
+#endif
+#ifdef MODE_BASE_REG_CLASS
+  return MODE_BASE_REG_CLASS (mode);
+#else
+  return BASE_REG_CLASS;
+#endif
+#endif
+}
+
+/* Accessor function to unify target macros REGNO_MODE_CODE_OK_FOR_BASE_P,
+   REGNO_MODE_OK_FOR_REG_BASE_P, REGNO_MODE_OK_FOR_BASE_P and
+   REGNO_OK_FOR_BASE_P.
+   Arguments as for the REGNO_MODE_CODE_OK_FOR_BASE_P macro.  */
+
+static inline bool
+regno_ok_for_base_p (unsigned regno, enum machine_mode mode ATTRIBUTE_UNUSED,
+		     enum rtx_code outer_code ATTRIBUTE_UNUSED,
+		     enum rtx_code index_code ATTRIBUTE_UNUSED)
+{
+#ifndef REG_OK_STRICT
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    return true;
+#endif
+
+  if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
+    regno = reg_renumber[regno];
+
+#ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
+  return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, outer_code, index_code);
+#else
+#ifdef REGNO_MODE_OK_FOR_REG_BASE_P
+  if (index_code == REG)
+    return REGNO_MODE_OK_FOR_REG_BASE_P (regno, mode);
+#endif
+#ifdef REGNO_MODE_OK_FOR_BASE_P
+  return REGNO_MODE_OK_FOR_BASE_P (regno, mode);
+#else
+  return REGNO_OK_FOR_BASE_P (regno);
+#endif
+#endif
+}
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.444
diff -c -p -r1.444 tm.texi
*** doc/tm.texi	6 Aug 2005 13:26:35 -0000	1.444
--- doc/tm.texi	18 Aug 2005 15:23:53 -0000
*************** register address.  You should define thi
*** 2279,2284 ****
--- 2279,2294 ----
  addresses have different requirements than other base register uses.
  @end defmac
  
+ @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{outer_code}, @var{index_code})
+ A C expression whose value is the register class to which a valid
+ base register must belong.  @var{outer_code} and @var{index_code} define the
+ context in which the base register occurs.  @var{outer_code} is the code of
+ the immediately enclosing expression (@code{MEM} for the top level of an
+ address, @code{ADDRESS} for something that occurs in an
+ @code{address_operand}).  @var{index_code} is the code of the corresponding
+ index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise.
+ @end defmac
+ 
  @defmac INDEX_REG_CLASS
  A macro whose definition is the name of the class to which a valid
  index register must belong.  An index register is one used in an
*************** memory in mode @var{mode}.  It may be ei
*** 2339,2344 ****
--- 2349,2367 ----
  pseudo register that has been allocated such a hard register.  You should
  define this macro if base plus index addresses have different requirements
  than other base register uses.
+ 
+ Use of this macro is deprecated; please use the more general
+ @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
+ @end defmac
+ 
+ @defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{outer_code}, @var{index_code})
+ A C expression that is just like @code{REGNO_MODE_OK_FOR_BASE_P}, except that
+ that expression may examine the context in which the register appears in the
+ memory reference.  @var{outer_code} is the code of the immediately enclosing
+ expression (@code{MEM} if at the top level of the address, @code{ADDRESS} for
+ something that occurs in an @code{address_operand}).  @var{index_code} is the
+ code of the corresponding index expression if @var{outer_code} is @code{PLUS};
+ @code{SCRATCH} otherwise.
  @end defmac
  
  @defmac REGNO_OK_FOR_INDEX_P (@var{num})
*************** into the @code{symbol_ref}, and then che
*** 4925,4972 ****
  Format}.
  @end defmac
  
- @defmac REG_OK_FOR_BASE_P (@var{x})
- A C expression that is nonzero if @var{x} (assumed to be a @code{reg}
- RTX) is valid for use as a base register.  For hard registers, it
- should always accept those which the hardware permits and reject the
- others.  Whether the macro accepts or rejects pseudo registers must be
- controlled by @code{REG_OK_STRICT} as described above.  This usually
- requires two variant definitions, of which @code{REG_OK_STRICT}
- controls the one actually used.
- @end defmac
- 
- @defmac REG_MODE_OK_FOR_BASE_P (@var{x}, @var{mode})
- A C expression that is just like @code{REG_OK_FOR_BASE_P}, except that
- that expression may examine the mode of the memory reference in
- @var{mode}.  You should define this macro if the mode of the memory
- reference affects whether a register may be used as a base register.  If
- you define this macro, the compiler will use it instead of
- @code{REG_OK_FOR_BASE_P}.
- @end defmac
- 
- @defmac REG_MODE_OK_FOR_REG_BASE_P (@var{x}, @var{mode})
- A C expression which is nonzero if @var{x} (assumed to be a @code{reg} RTX)
- is suitable for use as a base register in base plus index operand addresses,
- accessing memory in mode @var{mode}.  It may be either a suitable hard
- register or a pseudo register that has been allocated such a hard register.
- You should define this macro if base plus index addresses have different
- requirements than other base register uses.
- @end defmac
- 
- @defmac REG_OK_FOR_INDEX_P (@var{x})
- A C expression that is nonzero if @var{x} (assumed to be a @code{reg}
- RTX) is valid for use as an index register.
- 
- The difference between an index register and a base register is that
- the index register may be scaled.  If an address involves the sum of
- two registers, neither one of them scaled, then either one may be
- labeled the ``base'' and the other the ``index''; but whichever
- labeling is used must fit the machine's constraints of which registers
- may serve in each capacity.  The compiler will try both labelings,
- looking for one that is valid, and will reload one or both registers
- only if neither labeling works.
- @end defmac
- 
  @defmac FIND_BASE_TERM (@var{x})
  A C expression to determine the base term of address @var{x}.
  This macro is used in only one place: `find_base_term' in alias.c.
--- 4948,4953 ----

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