From 8efab2c5eafbe0e3d43dccd13cbc57f62a4e672f Mon Sep 17 00:00:00 2001
From: Georg-Johann Lay <avr@gjlay.de>
Date: Tue, 11 Oct 2011 18:34:16 +0000
Subject: [PATCH] avr-protos.h (avr_mode_code_base_reg_class): New prototype.

	* config/avr/avr-protos.h (avr_mode_code_base_reg_class): New prototype.
	(avr_regno_mode_code_ok_for_base_p): New prototype.
	* config/avr/avr.h (BASE_REG_CLASS): Remove.
	(REGNO_OK_FOR_BASE_P): Remove.
	(REG_OK_FOR_BASE_NOSTRICT_P): Remove.
	(REG_OK_FOR_BASE_STRICT_P): Remove.
	(MODE_CODE_BASE_REG_CLASS): New define.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): New define.
	* config/avr/avr.c (avr_mode_code_base_reg_class): New function.
	(avr_regno_mode_code_ok_for_base_p): New function.
	(avr_reg_ok_for_addr_p): New static function.
	(avr_legitimate_address_p): Use it.  Beautify.

From-SVN: r179817
---
 gcc/ChangeLog               |  15 +++++
 gcc/config/avr/avr-protos.h |   2 +
 gcc/config/avr/avr.c        | 116 +++++++++++++++++++++++++++++-------
 gcc/config/avr/avr.h        |  20 ++-----
 4 files changed, 114 insertions(+), 39 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2fabe682c149..29a49a0aac68 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2011-10-11  Georg-Johann Lay  <avr@gjlay.de>
+
+	* config/avr/avr-protos.h (avr_mode_code_base_reg_class): New prototype.
+	(avr_regno_mode_code_ok_for_base_p): New prototype.
+	* config/avr/avr.h (BASE_REG_CLASS): Remove.
+	(REGNO_OK_FOR_BASE_P): Remove.
+	(REG_OK_FOR_BASE_NOSTRICT_P): Remove.
+	(REG_OK_FOR_BASE_STRICT_P): Remove.
+	(MODE_CODE_BASE_REG_CLASS): New define.
+	(REGNO_MODE_CODE_OK_FOR_BASE_P): New define.
+	* config/avr/avr.c (avr_mode_code_base_reg_class): New function.
+	(avr_regno_mode_code_ok_for_base_p): New function.
+	(avr_reg_ok_for_addr_p): New static function.
+	(avr_legitimate_address_p): Use it.  Beautify.
+
 2011-10-11  Georg-Johann Lay  <avr@gjlay.de>
 
 	PR target/50447
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 06e412c96e53..a799fb2a9374 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -106,6 +106,8 @@ extern int avr_simplify_comparison_p (enum machine_mode mode,
 extern RTX_CODE avr_normalize_condition (RTX_CODE condition);
 extern void out_shift_with_cnt (const char *templ, rtx insn,
 				rtx operands[], int *len, int t_len);
+extern reg_class_t avr_mode_code_base_reg_class (enum machine_mode, RTX_CODE, RTX_CODE);
+extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, RTX_CODE, RTX_CODE);
 extern rtx avr_incoming_return_addr_rtx (void);
 extern rtx avr_legitimize_reload_address (rtx, enum machine_mode, int, int, int, int, rtx (*)(rtx,int));
 #endif /* RTX_CODE */
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index afc3d61851c4..751f27abb2ca 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -1202,43 +1202,68 @@ avr_cannot_modify_jumps_p (void)
 }
 
 
+/* Helper function for `avr_legitimate_address_p'.  */
+
+static inline bool
+avr_reg_ok_for_addr_p (rtx reg, addr_space_t as ATTRIBUTE_UNUSED, int strict)
+{
+  return (REG_P (reg)
+          && (avr_regno_mode_code_ok_for_base_p (REGNO (reg),
+                                                 QImode, MEM, UNKNOWN)
+              || (!strict
+                  && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
+}
+
+
 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
    machine for a memory operand of mode MODE.  */
 
-bool
+static bool
 avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
 {
   reg_class_t r = NO_REGS;
   
-  if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
-                    : REG_OK_FOR_BASE_NOSTRICT_P (x)))
-    r = POINTER_REGS;
+  if (REG_P (x)
+      && avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC, strict))
+    {
+      r = POINTER_REGS;
+    }
   else if (CONSTANT_ADDRESS_P (x))
-    r = ALL_REGS;
+    {
+      r = ALL_REGS;
+    }
   else if (GET_CODE (x) == PLUS
            && REG_P (XEXP (x, 0))
-	   && GET_CODE (XEXP (x, 1)) == CONST_INT
-	   && INTVAL (XEXP (x, 1)) >= 0)
+           && CONST_INT_P (XEXP (x, 1))
+           && INTVAL (XEXP (x, 1)) >= 0)
     {
-      int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
+      rtx reg = XEXP (x, 0);
+      bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
+      
       if (fit)
-	{
-	  if (! strict
-	      || REGNO (XEXP (x,0)) == REG_X
-	      || REGNO (XEXP (x,0)) == REG_Y
-	      || REGNO (XEXP (x,0)) == REG_Z)
-	    r = BASE_POINTER_REGS;
-	  if (XEXP (x,0) == frame_pointer_rtx
-	      || XEXP (x,0) == arg_pointer_rtx)
-	    r = BASE_POINTER_REGS;
-	}
-      else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
-	r = POINTER_Y_REGS;
+        {
+          if (! strict
+              || REGNO (reg) == REG_X
+              || REGNO (reg) == REG_Y
+              || REGNO (reg) == REG_Z)
+            {
+              r = BASE_POINTER_REGS;
+            }
+          
+          if (reg == frame_pointer_rtx
+              || reg == arg_pointer_rtx)
+            {
+              r = BASE_POINTER_REGS;
+            }
+        }
+      else if (frame_pointer_needed && reg == frame_pointer_rtx)
+        {
+          r = POINTER_Y_REGS;
+        }
     }
   else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
            && REG_P (XEXP (x, 0))
-           && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
-               : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
+           && avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC, strict))
     {
       r = POINTER_REGS;
     }
@@ -1269,7 +1294,7 @@ avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
 /* Attempts to replace X with a valid
    memory address for an operand of mode MODE  */
 
-rtx
+static rtx
 avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
 {
   bool big_offset_p = false;
@@ -7224,6 +7249,51 @@ avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
 }
 
 
+/* Implement `MODE_CODE_BASE_REG_CLASS'.  */
+
+reg_class_t
+avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+                              RTX_CODE outer_code ATTRIBUTE_UNUSED,
+                              RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+  return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
+}
+
+
+/* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'.  */
+
+bool
+avr_regno_mode_code_ok_for_base_p (int regno,
+                                   enum machine_mode mode ATTRIBUTE_UNUSED,
+                                   RTX_CODE outer_code ATTRIBUTE_UNUSED,
+                                   RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+  if (regno < FIRST_PSEUDO_REGISTER
+      && (regno == REG_X
+          || regno == REG_Y
+          || regno == REG_Z
+          || regno == ARG_POINTER_REGNUM))
+    {
+      return true;
+    }
+
+  if (reg_renumber)
+    {
+      regno = reg_renumber[regno];
+
+      if (regno == REG_X
+          || regno == REG_Y
+          || regno == REG_Z
+          || regno == ARG_POINTER_REGNUM)
+        {
+          return true;
+        }
+    }
+  
+  return false;
+}
+
+
 /* A helper for `output_reload_insisf' and `output_reload_inhi'.  */
 /* Set 32-bit register OP[0] to compile-time constant OP[1].
    CLOBBER_REG is a QI clobber register or NULL_RTX.
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 51bd942cf56e..015f12b5fe51 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -308,21 +308,13 @@ enum reg_class {
 
 #define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
 
-#define BASE_REG_CLASS (reload_completed ? BASE_POINTER_REGS : POINTER_REGS)
+#define MODE_CODE_BASE_REG_CLASS(mode, outer_code, index_code) \
+  avr_mode_code_base_reg_class (mode, outer_code, index_code)
 
 #define INDEX_REG_CLASS NO_REGS
 
-#define REGNO_OK_FOR_BASE_P(r) (((r) < FIRST_PSEUDO_REGISTER		\
-				 && ((r) == REG_X			\
-				     || (r) == REG_Y			\
-				     || (r) == REG_Z			\
-				     || (r) == ARG_POINTER_REGNUM))	\
-				|| (reg_renumber			\
-				    && (reg_renumber[r] == REG_X	\
-					|| reg_renumber[r] == REG_Y	\
-					|| reg_renumber[r] == REG_Z	\
-					|| (reg_renumber[r]		\
-					    == ARG_POINTER_REGNUM))))
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(num, mode, outer_code, index_code) \
+  avr_regno_mode_code_ok_for_base_p (num, mode, outer_code, index_code)
 
 #define REGNO_OK_FOR_INDEX_P(NUM) 0
 
@@ -381,10 +373,6 @@ typedef struct avr_args {
 
 #define MAX_REGS_PER_ADDRESS 1
 
-#define REG_OK_FOR_BASE_NOSTRICT_P(X) \
-  (REGNO (X) >= FIRST_PSEUDO_REGISTER || REG_OK_FOR_BASE_STRICT_P(X))
-
-#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN)          \
   do {                                                                  \
     rtx new_x = avr_legitimize_reload_address (X, MODE, OPNUM, TYPE,    \
-- 
GitLab