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]

[Patch]: PR49868: Named address space support for AVR


This patch adds named address space support to read data from flash (aka.
progmem) to target AVR.

The patch has two parts:

The first part is a repost of Ulrich's work from
   http://gcc.gnu.org/ml/gcc/2011-08/msg00131.html
with the needed changes to ./gcc and ./gcc/doc

This patch is needed because the target hooks MODE_CODE_BASE_REG_CLASS and
REGNO_MODE_CODE_OK_FOR_BASE_P don't distinguish between different address
spaces.  Ulrich's patch adds respective support to these hooks.

The second part is the AVR dependent part that adds __pgm as address space
qualifier for address space AS1.

The AVR part is just the worker code.  If there is agreement that AS support
for AVR is okay in principle and Ulrich's work will go into GCC, I will supply
test programs and updates to the user manual, of course.

The major drawbacks of the current AS implementation are:

- It works only for C.
  For C++, a language extension would be needed as indicated in
     ISO/IEC DTR 18037
     Annex F - C++ Compatibility and Migration issues
     F.2 Multiple Address Spaces Support

- Register allocation does not a good job. AS1 can only be addressed
  byte-wise by one single address register (Z) as per *Z or *Z++.

The AVR part does several things:

- It locates data in AS1 into appropriate section, i.e. somewhere in
  .progmem

- It does early sanity checks to ensure that __pgm is always accompanied
  with const so that writing to AS1 in not possible.

- It prints LPM instructions to access flash memory.

Hint on how to proceed with this are appreciated, likewise I'd like to know if
such extension is not appropriate so that I can focus on other stuff or if
there are hints to improve the patch.

Thanks, Johann

	PR target/49868
	* config/avr/avr.h (ADDR_SPACE_PGM): New define for address space AS1.
	(REGISTER_TARGET_PRAGMAS): New define.
	(MODE_CODE_BASE_REG_CLASS): New define.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): New define.
	(BASE_REG_CLASS): Remove define.
	(REGNO_OK_FOR_BASE_P): Remove define.
	(REG_OK_FOR_BASE_NOSTRICT_P): Remove define.
	(REG_OK_FOR_BASE_STRICT_P): Remove define.
	* config/avr/avr-protos.h (avr_mem_pgm_p): New prototype.
	(avr_register_target_pragmas): New prototype.
	(avr_mode_code_base_reg_class): New prototype.
	(avr_regno_mode_code_ok_for_base_p): New prototype.
	(avr_log_t): Add field "progmem".  Order alphabetically.
	* config/avr/avr-log.c (avr_log_set_avr_log): Set avr_log.progmem.
	* config/avr/avr-c.c (avr_register_target_pragmas): New function.
	Register address space AS1 as "__pgm".
	* config/avr/avr.c: Include "c-family/c-common.h".
	(TARGET_LEGITIMATE_ADDRESS_P): Don't define this macro any more.
	(TARGET_LEGITIMIZE_ADDRESS): Don't define this macro any more.
	(TARGET_ADDR_SPACE_SUBSET_P): Define to...
	(avr_addr_space_subset_p): ...this new static function.
	(TARGET_ADDR_SPACE_CONVERT): Define to...
	(avr_addr_space_convert): ...this new static function.
	(TARGET_ADDR_SPACE_ADDRESS_MODE): Define to...
	(avr_addr_space_address_mode): ...this new static function.
	(TARGET_ADDR_SPACE_POINTER_MODE): Define to...
	(avr_addr_space_pointer_mode): ...this new static function.
	(TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P): Define to...
	(avr_addr_space_legitimate_address_p): ...this new static function.
	(TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS): Define to...
	(avr_addr_space_legitimize_address): ...this new static function.
	(avr_mode_code_base_reg_class): New function.
	(avr_regno_mode_code_ok_for_base_p): New function.
	(lpm_addr_reg_rtx, lpm_reg_rtx): New static GTYed variables.
	(avr_decl_pgm_p): New static function.
	(avr_mem_pgm_p): New function.
	(avr_reg_ok_for_addr): New static function.
	(avr_legitimate_address_p): Use it.
	(avr_asm_len): Return "" instead of void.
	(avr_out_lpm_no_lpmx): New static function.
	(avr_out_lpm): New static function.
	(output_movqi, output_movhi, output_movsisf): Call avr_out_lpm to
	handle loads from progmem.
	(avr_progmem_p): Test if decl is in AS1.
	(avr_pgm_pointer_const_p): New static function.
	(avr_pgm_check_var_decl): New static function.
	(avr_insert_attributes): Use it.  Change error message to report
	cause when code wants to write to AS1.
	(avr_section_type_flags): Unset section flag SECTION_BSS for
	data in progmem.
	* config/avr/avr.md (LPM_REGNO): New define_constants.
	(movqi, movhi, movsi, movsf): Skip if code would write to AS1.
	(movmemhi): Ditto.  Propagate address space information to newly
	created MEM.
	(split-lpmx): New split.
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(revision 179594)
+++ config/avr/avr.md	(working copy)
@@ -42,6 +42,7 @@ (define_constants
    (REG_Z	30)
    (REG_W	24)
    (REG_SP	32)
+   (LPM_REGNO	0)	; implicit target register of LPM
    (TMP_REGNO	0)	; temporary register r0
    (ZERO_REGNO	1)	; zero register r1
    
@@ -289,11 +290,17 @@ (define_expand "movqi"
   [(set (match_operand:QI 0 "nonimmediate_operand" "")
 	(match_operand:QI 1 "general_operand" ""))]
   ""
-  "/* One of the ops has to be in a register.  */
-   if (!register_operand(operand0, QImode)
-       && ! (register_operand(operand1, QImode) || const0_rtx == operand1))
-       operands[1] = copy_to_mode_reg(QImode, operand1);
-  ")
+  {
+    if (avr_mem_pgm_p (operands[0]))
+      DONE;
+
+    /* One of the operands has to be in a register.  */
+    if (!register_operand (operands[0], QImode)
+        && !(register_operand (operands[1], QImode) || const0_rtx == operands[1]))
+      {
+        operands[1] = copy_to_mode_reg (QImode, operands[1]);
+      }
+  })
 
 (define_insn "*movqi"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,d,Qm,r,q,r,*r")
@@ -336,15 +343,17 @@ (define_expand "movhi"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
         (match_operand:HI 1 "general_operand"       ""))]
   ""
-  "
-{
-   /* One of the ops has to be in a register.  */
-  if (!register_operand(operand0, HImode)
-      && !(register_operand(operand1, HImode) || const0_rtx == operands[1]))
-    {
-      operands[1] = copy_to_mode_reg(HImode, operand1);
-    }
-}")
+  {
+    if (avr_mem_pgm_p (operands[0]))
+      DONE;
+
+    /* One of the operands has to be in a register.  */
+    if (!register_operand (operands[0], HImode)
+        && !(register_operand (operands[1], HImode) || const0_rtx == operands[1]))
+      {
+        operands[1] = copy_to_mode_reg (HImode, operands[1]);
+      }
+  })
 
 (define_insn "movhi_sp_r_irq_off"
   [(set (match_operand:HI 0 "stack_register_operand" "=q")
@@ -429,6 +438,39 @@ (define_peephole2 ; movw_r
     operands[5] = gen_rtx_REG (HImode, REGNO (operands[3]));
   })
 
+;; For LPM loads from AS1 we split 
+;;    R = *Z
+;; to
+;;    R = *Z++
+;;    Z = Z - sizeof (R)
+;;
+;; so that the second instruction can be optimized out.
+
+(define_split ; "split-lpmx"
+  [(set (match_operand:HISI 0 "register_operand" "")
+        (match_operand:HISI 1 "memory_operand" ""))]
+  "reload_completed
+   && AVR_HAVE_LPMX"
+  [(set (match_dup 0)
+        (match_dup 2))
+   (set (match_dup 3)
+        (plus:HI (match_dup 3)
+                 (match_dup 4)))]
+  {
+     rtx addr = XEXP (operands[1], 0);
+
+     if (ADDR_SPACE_PGM != MEM_ADDR_SPACE (operands[1])
+         || !REG_P (addr)
+         || reg_overlap_mentioned_p (addr, operands[0]))
+       {
+         FAIL;
+       }
+
+    operands[2] = replace_equiv_address (operands[1],
+                                         gen_rtx_POST_INC (Pmode, addr));
+    operands[3] = addr;
+    operands[4] = gen_int_mode (-GET_MODE_SIZE (<MODE>mode), HImode);
+  })
 ;;==========================================================================
 ;; move double word (32 bit)
 
@@ -436,15 +478,17 @@ (define_expand "movsi"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
         (match_operand:SI 1 "general_operand"  ""))]
   ""
-  "
-{
-  /* One of the ops has to be in a register.  */
-  if (!register_operand (operand0, SImode)
-      && !(register_operand (operand1, SImode) || const0_rtx == operand1))
-    {
-      operands[1] = copy_to_mode_reg (SImode, operand1);
-    }
-}")
+  {
+    if (avr_mem_pgm_p (operands[0]))
+      DONE;
+  
+    /* One of the operands has to be in a register.  */
+    if (!register_operand (operands[0], SImode)
+        && !(register_operand (operands[1], SImode) || const0_rtx == operands[1]))
+      {
+        operands[1] = copy_to_mode_reg (SImode, operands[1]);
+      }
+  })
 
 
 
@@ -492,15 +536,17 @@ (define_expand "movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand" "")
         (match_operand:SF 1 "general_operand"  ""))]
   ""
-  "
-{
-  /* One of the ops has to be in a register.  */
-  if (!register_operand (operand1, SFmode)
-      && !register_operand (operand0, SFmode))
-    {
-      operands[1] = copy_to_mode_reg (SFmode, operand1);
-    }
-}")
+  {
+    if (avr_mem_pgm_p (operands[0]))
+      DONE;
+
+    /* One of the operands has to be in a register.  */
+    if (!register_operand (operands[1], SFmode)
+        && !register_operand (operands[0], SFmode))
+      {
+        operands[1] = copy_to_mode_reg (SFmode, operands[1]);
+      }
+  })
 
 (define_insn "*movsf"
   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,Qm,!d,r")
@@ -555,7 +601,7 @@ (define_expand "movmemhi"
   enum machine_mode mode;
   rtx label = gen_label_rtx ();
   rtx loop_reg;
-  rtx jump;
+  rtx jump, src;
 
   /* Copy pointers into new psuedos - they will be changed.  */
   rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
@@ -564,6 +610,9 @@ (define_expand "movmemhi"
   /* Create rtx for tmp register - we use this as scratch.  */
   rtx tmp_reg_rtx  = gen_rtx_REG (QImode, TMP_REGNO);
 
+  if (avr_mem_pgm_p (operands[0]))
+    DONE;
+
   if (GET_CODE (operands[2]) != CONST_INT)
     FAIL;
 
@@ -584,7 +633,9 @@ (define_expand "movmemhi"
   emit_label (label);
 
   /* Move one byte into scratch and inc pointer.  */
-  emit_move_insn (tmp_reg_rtx, gen_rtx_MEM (QImode, addr1));
+  src = gen_rtx_MEM (QImode, addr1);
+  set_mem_addr_space (src, MEM_ADDR_SPACE (operands[1]));
+  emit_move_insn (tmp_reg_rtx, src);
   emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
 
   /* Move to mem and inc pointer.  */
Index: config/avr/avr-log.c
===================================================================
--- config/avr/avr-log.c	(revision 179594)
+++ config/avr/avr-log.c	(working copy)
@@ -318,12 +318,13 @@ avr_log_set_avr_log (void)
                    || NULL != strstr (str, "," #S ",")                  \
                    || NULL != strstr (str, ",all,"))
 
-      SET_DUMP_DETAIL (rtx_costs);
+      SET_DUMP_DETAIL (address_cost);
+      SET_DUMP_DETAIL (constraints);
       SET_DUMP_DETAIL (legitimate_address_p);
       SET_DUMP_DETAIL (legitimize_address);
       SET_DUMP_DETAIL (legitimize_reload_address);
-      SET_DUMP_DETAIL (constraints);
-      SET_DUMP_DETAIL (address_cost);
+      SET_DUMP_DETAIL (progmem);
+      SET_DUMP_DETAIL (rtx_costs);
 
 #undef SET_DUMP_DETAIL
     }
Index: config/avr/avr-c.c
===================================================================
--- config/avr/avr-c.c	(revision 179594)
+++ config/avr/avr-c.c	(working copy)
@@ -18,6 +18,7 @@
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
+/* Not included in avr.c since this requires C front end.  */
 
 #include "config.h"
 #include "system.h"
@@ -28,7 +29,15 @@
 #include "tree.h"
 #include "c-family/c-common.h"
 
-/* Not included in avr.c since this requires C front end.  */
+
+/* Implement `REGISTER_TARGET_PRAGMAS'.  */
+
+void
+avr_register_target_pragmas (void)
+{
+  c_register_addr_space ("__pgm", ADDR_SPACE_PGM);
+}
+
 
 /* Worker function for TARGET_CPU_CPP_BUILTINS.  */
 
Index: config/avr/avr-protos.h
===================================================================
--- config/avr/avr-protos.h	(revision 179594)
+++ config/avr/avr-protos.h	(working copy)
@@ -32,6 +32,7 @@ extern int avr_initial_elimination_offse
 extern int avr_simple_epilogue (void);
 extern int avr_hard_regno_rename_ok (unsigned int, unsigned int);
 extern rtx avr_return_addr_rtx (int count, rtx tem);
+extern void avr_register_target_pragmas (void);
 
 #ifdef TREE_CODE
 extern void avr_asm_output_aligned_decl_common (FILE*, const_tree, const char*, unsigned HOST_WIDE_INT, unsigned int, bool);
@@ -106,8 +107,11 @@ extern int avr_simplify_comparison_p (en
 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, addr_space_t, RTX_CODE, RTX_CODE);
+extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, addr_space_t, 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));
+extern bool avr_mem_pgm_p (rtx);
 #endif /* RTX_CODE */
 
 #ifdef REAL_VALUE_TYPE
@@ -126,12 +130,13 @@ extern void avr_log_set_avr_log (void);
 
 typedef struct
 {
-  unsigned rtx_costs :1;
+  unsigned address_cost :1;
+  unsigned constraints :1;
   unsigned legitimate_address_p :1;
   unsigned legitimize_address :1;
   unsigned legitimize_reload_address :1;
-  unsigned constraints :1;
-  unsigned address_cost :1;
+  unsigned progmem :1;
+  unsigned rtx_costs :1;
 } avr_log_t;
 
 extern avr_log_t avr_log;
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 179594)
+++ config/avr/avr.c	(working copy)
@@ -35,6 +35,7 @@
 #include "tree.h"
 #include "output.h"
 #include "expr.h"
+#include "c-family/c-common.h"
 #include "diagnostic-core.h"
 #include "obstack.h"
 #include "function.h"
@@ -69,14 +70,12 @@ static const char *ptrreg_to_str (int);
 static const char *cond_string (enum rtx_code);
 static int avr_num_arg_regs (enum machine_mode, const_tree);
 
-static rtx avr_legitimize_address (rtx, rtx, enum machine_mode);
 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
 static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *);
 static bool avr_assemble_integer (rtx, unsigned int, int);
 static void avr_file_start (void);
 static void avr_file_end (void);
-static bool avr_legitimate_address_p (enum machine_mode, rtx, bool);
 static void avr_asm_function_end_prologue (FILE *);
 static void avr_asm_function_begin_epilogue (FILE *);
 static bool avr_cannot_modify_jumps_p (void);
@@ -112,6 +111,13 @@ static void avr_function_arg_advance (cu
 				      const_tree, bool);
 static bool avr_function_ok_for_sibcall (tree, tree);
 static void avr_asm_named_section (const char *name, unsigned int flags, tree decl);
+static enum machine_mode avr_addr_space_address_mode (addr_space_t);
+static enum machine_mode avr_addr_space_pointer_mode (addr_space_t);
+static bool avr_reg_ok_for_pgm_addr (rtx, bool);
+static bool avr_addr_space_legitimate_address_p (enum machine_mode mode, rtx, bool, addr_space_t);
+static rtx avr_addr_space_legitimize_address (rtx, rtx, enum machine_mode, addr_space_t);
+static rtx avr_addr_space_convert (rtx, tree, tree);
+static bool avr_addr_space_subset_p (addr_space_t, addr_space_t);
 static void avr_encode_section_info (tree, rtx, int);
 static section* avr_asm_function_rodata_section (tree);
 static section* avr_asm_select_section (tree, int, unsigned HOST_WIDE_INT);
@@ -119,6 +125,12 @@ static section* avr_asm_select_section (
 /* Allocate registers from r25 to r8 for parameters for function calls.  */
 #define FIRST_CUM_REG 26
 
+/* Implicit target register of LPM instruction (R0) */
+static GTY(()) rtx lpm_reg_rtx;
+
+/* Implicit address register of LPM instruction (R31:R30 = Z) */
+static GTY(()) rtx lpm_addr_reg_rtx;
+
 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
 static GTY(()) rtx tmp_reg_rtx;
 
@@ -228,9 +240,6 @@ static const struct attribute_spec avr_a
 #undef TARGET_FUNCTION_ARG_ADVANCE
 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
 
-#undef TARGET_LEGITIMIZE_ADDRESS
-#define TARGET_LEGITIMIZE_ADDRESS avr_legitimize_address
-
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
 
@@ -245,9 +254,6 @@ static const struct attribute_spec avr_a
 #undef TARGET_CASE_VALUES_THRESHOLD
 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
 
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P avr_legitimate_address_p
-
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
 #undef TARGET_CAN_ELIMINATE
@@ -274,6 +280,24 @@ static const struct attribute_spec avr_a
 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
 #define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
 
+#undef  TARGET_ADDR_SPACE_SUBSET_P
+#define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
+
+#undef  TARGET_ADDR_SPACE_CONVERT
+#define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
+
+#undef  TARGET_ADDR_SPACE_ADDRESS_MODE
+#define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
+
+#undef  TARGET_ADDR_SPACE_POINTER_MODE
+#define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
+
+#undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
+#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P avr_addr_space_legitimate_address_p
+
+#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
+#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -355,6 +379,8 @@ avr_option_override (void)
   avr_current_arch = &avr_arch_types[avr_current_device->arch];
   avr_extra_arch_macro = avr_current_device->macro;
 
+  lpm_addr_reg_rtx = gen_rtx_REG (Pmode, REG_Z);
+  lpm_reg_rtx  = gen_rtx_REG (QImode, LPM_REGNO);
   tmp_reg_rtx  = gen_rtx_REG (QImode, TMP_REGNO);
   zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
 
@@ -405,6 +431,30 @@ avr_regno_reg_class (int r)
   return ALL_REGS;
 }
 
+
+/* Return TRUE if DECL is a VAR_DECL which is located in AS1
+   and FALSE, otherwise.  */
+
+static bool
+avr_decl_pgm_p (tree decl)
+{
+  if (TREE_CODE (decl) != VAR_DECL)
+    return false;
+
+  return (ADDR_SPACE_PGM == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+}
+
+
+/* Return TRUE if X is a MEM rtx located in AS1 and FALSE, otherwise.  */
+
+bool
+avr_mem_pgm_p (rtx x)
+{
+  return (MEM_P (x)
+          && ADDR_SPACE_PGM == MEM_ADDR_SPACE (x));
+}
+
+
 /* A helper for the subsequent function attribute used to dig for
    attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
 
@@ -1187,17 +1237,32 @@ avr_cannot_modify_jumps_p (void)
 }
 
 
-/* Return nonzero if X (an RTX) is a legitimate memory address on the target
-   machine for a memory operand of mode MODE.  */
+/* Helper function for `avr_legitimate_address_p'.  */
 
-bool
+static inline int
+avr_reg_ok_for_addr (rtx reg, addr_space_t as, int strict)
+{
+  return (REG_P (reg)
+          && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), as,
+                                                 QImode, MEM, UNKNOWN)
+              || (!strict
+                  && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
+}
+
+
+/* Former implementation of TARGET_LEGITIMATE_ADDRESS_P,
+   now only a helper for avr_addr_space_legitimate_address_p.  */
+
+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 (x, ADDR_SPACE_GENERIC, strict))
+    {
+      r = POINTER_REGS;
+    }
   else if (CONSTANT_ADDRESS_P (x))
     r = ALL_REGS;
   else if (GET_CODE (x) == PLUS
@@ -1222,8 +1287,7 @@ avr_legitimate_address_p (enum machine_m
     }
   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 (XEXP (x, 0), ADDR_SPACE_GENERIC, strict))
     {
       r = POINTER_REGS;
     }
@@ -1251,10 +1315,13 @@ avr_legitimate_address_p (enum machine_m
   return r == NO_REGS ? 0 : (int)r;
 }
 
+
+/* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
+   now only a helper for avr_addr_space_legitimize_address.  */
 /* 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;
@@ -1372,7 +1439,7 @@ avr_legitimize_reload_address (rtx x, en
 
 
 /* Helper function to print assembler resp. track instruction
-   sequence lengths.
+   sequence lengths.  Always returns "".
    
    If PLEN == NULL:
        Output assembler code from template TPL with operands supplied
@@ -1384,7 +1451,7 @@ avr_legitimize_reload_address (rtx x, en
        Don't output anything.
 */
 
-static void
+static const char*
 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
 {
   if (NULL == plen)
@@ -1398,6 +1465,8 @@ avr_asm_len (const char* tpl, rtx* opera
       else
         *plen += n_words;
     }
+
+  return "";
 }
 
 
@@ -2004,6 +2073,263 @@ avr_function_ok_for_sibcall (tree decl_c
 /***********************************************************************
   Functions for outputting various mov's for a various modes
 ************************************************************************/
+
+
+/* Helper function for the next function in the case where only restricted
+   version of LPM instruction is available.  */
+
+static const char*
+avr_out_lpm_no_lpmx (rtx insn, rtx *xop, int *plen)
+{
+  rtx dest = xop[0];
+  rtx src = xop[1];
+  rtx addr;
+  int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
+  int regno_dest;
+
+  addr = XEXP (src, 0);
+  regno_dest = REGNO (dest);
+
+  /* The implicit target register of LPM.  */
+  xop[3] = lpm_reg_rtx;
+
+  switch (GET_CODE (addr))
+    {
+    default:
+      gcc_unreachable();
+
+    case REG:
+
+      gcc_assert (REG_Z == REGNO (addr));
+
+      switch (n_bytes)
+        {
+        default:
+          gcc_unreachable();
+
+        case 1:
+          return avr_asm_len ("lpm" CR_TAB
+                              "mov %0,%3", xop, plen, -2);
+
+        case 2:
+          if (REGNO (dest) == REG_Z)
+            return avr_asm_len ("lpm"        CR_TAB
+                                "push %3"    CR_TAB
+                                "adiw %2,1"  CR_TAB
+                                "lpm"        CR_TAB
+                                "mov %B0,%3" CR_TAB
+                                "pop %A0", xop, plen, -6);
+          else
+            {
+              avr_asm_len ("lpm"        CR_TAB
+                           "mov %A0,%3" CR_TAB
+                           "adiw %2,1"  CR_TAB
+                           "lpm"        CR_TAB
+                           "mov %B0,%3", xop, plen, -5);
+                
+              if (!reg_unused_after (insn, addr))
+                avr_asm_len ("sbiw %2,1", xop, plen, 1);
+            }
+          
+          break; /* 2 */
+
+        case 4:
+          avr_asm_len ("lpm"        CR_TAB
+                       "mov %A0,%3" CR_TAB
+                       "adiw %2,1"  CR_TAB
+                       "lpm"        CR_TAB
+                       "mov %B0,%3" CR_TAB
+                       "adiw %2,1", xop, plen, -6);
+          
+          if (REGNO (dest) == REG_Z - 2)
+            return avr_asm_len ("lpm"        CR_TAB
+                                "push %3"    CR_TAB
+                                "adiw %2,1"  CR_TAB
+                                "lpm"        CR_TAB
+                                "mov %D0,%3" CR_TAB
+                                "pop %C0", xop, plen, 6);
+          else
+            {
+              avr_asm_len ("lpm"        CR_TAB
+                           "mov %C0,%3" CR_TAB
+                           "adiw %2,1"  CR_TAB
+                           "lpm"        CR_TAB
+                           "mov %D0,%3", xop, plen, 5);
+                
+              if (!reg_unused_after (insn, addr))
+                avr_asm_len ("sbiw %2,3", xop, plen, 1);
+            }
+
+          break; /* 4 */
+        }
+      
+      break; /* REG */
+
+    case POST_INC:
+
+      gcc_assert (REG_Z == REGNO (XEXP (addr, 0)));
+      
+      switch (n_bytes)
+        {
+        default:
+          gcc_unreachable();
+
+        case 1:
+          return avr_asm_len ("lpm"        CR_TAB
+                              "mov %A0,%3" CR_TAB
+                              "adiw %2,1", xop, plen, -3);
+          
+        case 2:
+          return avr_asm_len ("lpm"        CR_TAB
+                              "mov %A0,%3" CR_TAB
+                              "adiw %2,1"  CR_TAB
+                              "lpm"        CR_TAB
+                              "mov %B0,%3" CR_TAB
+                              "adiw %2,1", xop, plen, -6);
+          
+        case 4:
+          return avr_asm_len ("lpm"        CR_TAB
+                              "mov %A0,%3" CR_TAB
+                              "adiw %2,1"  CR_TAB
+                              "lpm"        CR_TAB
+                              "mov %B0,%3" CR_TAB
+                              "adiw %2,1"  CR_TAB
+                              "lpm"        CR_TAB
+                              "mov %C0,%3" CR_TAB
+                              "adiw %2,1"  CR_TAB
+                              "lpm"        CR_TAB
+                              "mov %D0,%3" CR_TAB
+                              "adiw %2,1", xop, plen, -12);
+        } /* switch (n_bytes) */
+    } /* switch CODE (addr) */
+      
+  return "";
+}
+
+
+/* If PLEN == NULL: Ouput instructions to load a value from a memory location
+   OP[1] in AS1 to register OP[0].
+   If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
+   Return "".  */
+
+static const char*
+avr_out_lpm (rtx insn, rtx *op, int *plen)
+{
+  rtx xop[4];
+  rtx dest = op[0];
+  rtx src = op[1];
+  rtx addr;
+  int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
+  int regno_dest;
+
+  if (plen)
+    *plen = 0;
+  
+  if (MEM_P (dest))
+    {
+      warning (0, "writing to address space %qs not supported",
+               c_addr_space_name (ADDR_SPACE_PGM));
+      
+      return "";
+    }
+
+  gcc_assert (REG_P (dest)
+              && avr_mem_pgm_p (src));
+
+  xop[0] = op[0];
+  xop[1] = op[1];
+  xop[2] = lpm_addr_reg_rtx;
+
+  if (!AVR_HAVE_LPMX)
+    return avr_out_lpm_no_lpmx (insn, xop, plen);
+
+  addr = XEXP (src, 0);
+  regno_dest = REGNO (dest);
+
+  switch (GET_CODE (addr))
+    {
+    default:
+      gcc_unreachable();
+
+    case REG:
+
+      gcc_assert (REG_Z == REGNO (addr));
+
+      switch (n_bytes)
+        {
+        default:
+          gcc_unreachable();
+
+        case 1:
+          return avr_asm_len ("lpm %0,%a2", xop, plen, -1);
+
+        case 2:
+          if (REGNO (dest) == REG_Z)
+            return avr_asm_len ("lpm __tmp_reg__,%a2+" CR_TAB
+                                "lpm %B0,%a2"          CR_TAB
+                                "mov %A0,__tmp_reg__", xop, plen, -3);
+          else
+            {
+              avr_asm_len ("lpm %A0,%a2+" CR_TAB
+                           "lpm %B0,%a2", xop, plen, -2);
+                
+              if (!reg_unused_after (insn, addr))
+                avr_asm_len ("sbiw %2,1", xop, plen, 1);
+            }
+          
+          break; /* 2 */
+
+        case 4:
+
+          avr_asm_len ("lpm %A0,%a2+" CR_TAB
+                       "lpm %B0,%a2+", xop, plen, -2);
+          
+          if (REGNO (dest) == REG_Z - 2)
+            return avr_asm_len ("lpm __tmp_reg__,%a2+" CR_TAB
+                                "lpm %C0,%a2"          CR_TAB
+                                "mov %D0,__tmp_reg__", xop, plen, 3);
+          else
+            {
+              avr_asm_len ("lpm %C0,%a2+" CR_TAB
+                           "lpm %D0,%a2", xop, plen, 2);
+                
+              if (!reg_unused_after (insn, addr))
+                avr_asm_len ("sbiw %2,3", xop, plen, 1);
+            }
+
+          break; /* 4 */
+        }
+      
+      break; /* REG */
+
+    case POST_INC:
+
+      gcc_assert (REG_Z == REGNO (XEXP (addr, 0)));
+      
+      switch (n_bytes)
+        {
+        default:
+          gcc_unreachable();
+
+        case 1:
+          return avr_asm_len ("lpm %A0,%a2+", xop, plen, -1);
+          
+        case 2:
+          return avr_asm_len ("lpm %A0,%a2+" CR_TAB
+                              "lpm %B0,%a2+", xop, plen, -2);
+          
+        case 4:
+          return avr_asm_len ("lpm %A0,%a2+" CR_TAB
+                              "lpm %B0,%a2+" CR_TAB
+                              "lpm %C0,%a2+" CR_TAB
+                              "lpm %D0,%a2+", xop, plen, -4);
+        } /* switch (n_bytes) */
+    } /* switch CODE (addr) */
+      
+  return "";
+}
+
+
 const char *
 output_movqi (rtx insn, rtx operands[], int *l)
 {
@@ -2012,6 +2338,12 @@ output_movqi (rtx insn, rtx operands[],
   rtx src = operands[1];
   int *real_l = l;
   
+  if (avr_mem_pgm_p (src)
+      || avr_mem_pgm_p (dest))
+    {
+      return avr_out_lpm (insn, operands, real_l);
+    }
+
   if (!l)
     l = &dummy;
 
@@ -2104,6 +2436,12 @@ output_movhi (rtx insn, rtx operands[],
   rtx src = operands[1];
   int *real_l = l;
   
+  if (avr_mem_pgm_p (src)
+      || avr_mem_pgm_p (dest))
+    {
+      return avr_out_lpm (insn, operands, real_l);
+    }
+
   if (!l)
     l = &dummy;
   
@@ -2717,6 +3055,12 @@ output_movsisf (rtx insn, rtx operands[]
   rtx src = operands[1];
   int *real_l = l;
   
+  if (avr_mem_pgm_p (src)
+      || avr_mem_pgm_p (dest))
+    {
+      return avr_out_lpm (insn, operands, real_l);
+    }
+
   if (!l)
     l = &dummy;
   
@@ -5483,8 +5827,10 @@ avr_handle_fntype_attribute (tree *node,
   return NULL_TREE;
 }
 
-/* Look for attribute `progmem' in DECL
-   if found return 1, otherwise 0.  */
+
+/* Return 2 if DECL is located in address space AS1.
+   Return 1 if attribute `progmem' occurs in DECL or ATTRIBUTES.
+   Return 0, otherwise.  */
 
 int
 avr_progmem_p (tree decl, tree attributes)
@@ -5494,6 +5840,9 @@ avr_progmem_p (tree decl, tree attribute
   if (TREE_CODE (decl) != VAR_DECL)
     return 0;
 
+  if (avr_decl_pgm_p (decl))
+    return 2;
+
   if (NULL_TREE
       != lookup_attribute ("progmem", attributes))
     return 1;
@@ -5512,11 +5861,104 @@ avr_progmem_p (tree decl, tree attribute
   return 0;
 }
 
+
+/* Scan type TYP for pointer references to address space AS1.
+   Return TRUE if all pointers targeting AS1 are also declared
+   to be CONST and FALSE, otherwise.  */
+   
+static bool
+avr_pgm_pointer_const_p (tree typ)
+{
+  while (ARRAY_TYPE == TREE_CODE (typ))
+    typ = TREE_TYPE (typ);
+
+  if (POINTER_TYPE_P (typ))
+    {
+      tree target = TREE_TYPE (typ);
+
+      /* Pointer to function: Test the function's return type.  */
+      
+      if (FUNCTION_TYPE == TREE_CODE (target))
+        return avr_pgm_pointer_const_p (TREE_TYPE (target));
+
+      /* "Ordinary" pointers... */
+      
+      return ((/* ...must point to generic address space...  */
+               ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (target))
+               /* ...or point to read-only locations.  */
+               || TYPE_READONLY (target))
+              /* Scan pointer's target type.  */
+              && avr_pgm_pointer_const_p (target));
+    }
+
+  return true;
+}
+
+
+/* Sanity check NODE so that all pointers targeting address space AS1
+   go along with CONST qualifier.  Writing to this address space should
+   be detected and complained about as early as possible.  */
+
+static bool
+avr_pgm_check_var_decl (tree node)
+{
+  const char *reason = NULL;
+  
+  if (avr_log.progmem)
+    avr_edump ("%?: %t\n", node);
+  
+  switch (TREE_CODE (node))
+    {
+    default:
+      break;
+
+    case VAR_DECL:
+      if (!avr_pgm_pointer_const_p (TREE_TYPE (node)))
+        reason = "variable";
+      break;
+
+    case PARM_DECL:
+      if (!avr_pgm_pointer_const_p (TREE_TYPE (node)))
+        reason = "function parameter";
+      break;
+        
+    case FIELD_DECL:
+      if (!avr_pgm_pointer_const_p (TREE_TYPE (node)))
+        reason = "structure field";
+      break;
+        
+    case FUNCTION_DECL:
+      if (!avr_pgm_pointer_const_p (TREE_TYPE (TREE_TYPE (node))))
+        reason = "return type of function";
+      break;
+
+    case POINTER_TYPE:
+      if (!avr_pgm_pointer_const_p (node))
+        reason = "pointer";
+      break;
+    }
+
+  if (reason)
+    {
+      if (TYPE_P (node))
+        error ("pointer targeting address space %qs must be const in %qT",
+               c_addr_space_name (ADDR_SPACE_PGM), node);
+      else
+        error ("pointer targeting address space %qs must be const in %s %q+D",
+               c_addr_space_name (ADDR_SPACE_PGM), reason, node);
+    }
+
+  return reason == NULL;
+}
+
+
 /* Add the section attribute if the variable is in progmem.  */
 
 static void
 avr_insert_attributes (tree node, tree *attributes)
 {
+  avr_pgm_check_var_decl (node);
+
   if (TREE_CODE (node) == VAR_DECL
       && (TREE_STATIC (node) || DECL_EXTERNAL (node))
       && avr_progmem_p (node, *attributes))
@@ -5533,11 +5975,20 @@ avr_insert_attributes (tree node, tree *
       if (error_mark_node == node0)
         return;
       
-      if (!TYPE_READONLY (node0))
+      if (!TYPE_READONLY (node0)
+          && !TREE_READONLY (node))
         {
+          addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (node));
+          const char *reason = "__attribute__((progmem))";
+
+          if (!ADDR_SPACE_GENERIC_P (as))
+            reason = c_addr_space_name (as);
+          
+          if (avr_log.progmem)
+            avr_edump ("\n%?: %t\n%t\n", node, node0);
+          
           error ("variable %q+D must be const in order to be put into"
-                 " read-only section by means of %<__attribute__((progmem))%>",
-                 node);
+                 " read-only section by means of %qs", node, reason);
         }
     }
 }
@@ -5734,6 +6185,7 @@ avr_section_type_flags (tree decl, const
       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
     {
       flags &= ~SECTION_WRITE;
+      flags &= ~SECTION_BSS;
       flags |= AVR_SECTION_PROGMEM;
     }
   
@@ -7155,6 +7607,79 @@ avr_hard_regno_mode_ok (int regno, enum
 }
 
 
+/* Implement `MODE_CODE_BASE_REG_CLASS'.  */
+
+reg_class_t
+avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+                              addr_space_t as,
+                              RTX_CODE outer_code ATTRIBUTE_UNUSED,
+                              RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+  if (ADDR_SPACE_PGM == as)
+    {
+      return POINTER_Z_REGS;
+    }
+  
+  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,
+                                   addr_space_t as,
+                                   RTX_CODE outer_code ATTRIBUTE_UNUSED,
+                                   RTX_CODE index_code ATTRIBUTE_UNUSED)
+{
+  if (ADDR_SPACE_PGM == as)
+    {
+      if (regno < FIRST_PSEUDO_REGISTER
+          && regno == REG_Z)
+        {
+          return true;
+        }
+      
+      if (reg_renumber)
+        {
+          regno = reg_renumber[regno];
+          
+          if (regno == REG_Z)
+            {
+              return true;
+            }
+        }
+
+      return false;
+    }
+
+  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.
@@ -7649,6 +8174,140 @@ unsigned int avr_case_values_threshold (
   return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
 }
 
+
+/* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'.  */
+
+static enum machine_mode
+avr_addr_space_address_mode (addr_space_t as ATTRIBUTE_UNUSED)
+{
+  return Pmode;
+}
+
+
+/* Implement `'.  */
+
+static enum machine_mode
+avr_addr_space_pointer_mode (addr_space_t as ATTRIBUTE_UNUSED)
+{
+  return Pmode;
+}
+
+
+/* Helper for following function.  */
+
+static bool
+avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
+{
+  gcc_assert (REG_P (reg));
+
+  if (strict)
+    {
+      return REGNO (reg) == REG_Z;
+    }
+  
+  /* Avoid combine to propagate hard regs.  */
+  
+  if ((!reload_completed || !reload_in_progress)
+      && REGNO (reg) < REG_Z)
+    {
+      return false;
+    }
+  
+  return true;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
+
+static bool
+avr_addr_space_legitimate_address_p (enum machine_mode mode, rtx x,
+                                     bool strict, addr_space_t as)
+{
+  bool ok = false;
+  
+  if (ADDR_SPACE_GENERIC_P (as))
+    return avr_legitimate_address_p (mode, x, strict);
+
+  gcc_assert (ADDR_SPACE_PGM == as);
+
+  switch (GET_CODE (x))
+    {
+    case REG:
+      ok = avr_reg_ok_for_pgm_addr (x, strict);
+      break;
+
+    case POST_INC:
+      ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
+      break;
+
+    default:
+      break;
+    }
+
+  if (avr_log.legitimate_address_p)
+    {
+      avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
+                 "reload_completed=%d reload_in_progress=%d %s:",
+                 ok, mode, strict, reload_completed, reload_in_progress,
+                 reg_renumber ? "(reg_renumber)" : "");
+      
+      if (GET_CODE (x) == PLUS
+          && REG_P (XEXP (x, 0))
+          && CONST_INT_P (XEXP (x, 1))
+          && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
+          && reg_renumber)
+        {
+          avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
+                     true_regnum (XEXP (x, 0)));
+        }
+      
+      avr_edump ("\n%r\n", x);
+    }
+
+  return ok;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'.  */
+
+static rtx
+avr_addr_space_legitimize_address (rtx x, rtx old_x,
+                                   enum machine_mode mode, addr_space_t as)
+{
+  if (ADDR_SPACE_GENERIC_P (as))
+    return avr_legitimize_address (x, old_x, mode);
+
+  if (avr_log.legitimize_address)
+    {
+      avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
+    }
+
+  return old_x;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_CONVERT'.  */
+
+static rtx
+avr_addr_space_convert (rtx op, tree from_type ATTRIBUTE_UNUSED,
+                        tree to_type ATTRIBUTE_UNUSED)
+{
+  if (avr_log.progmem)
+    avr_edump ("\n%?: op=%r\nfrom=%t\nto=%t\n", op, from_type, to_type);
+  return op;
+}
+
+
+/* Implement `TARGET_ADDR_SPACE_SUBSET_P'.  */
+
+static bool
+avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
+                         addr_space_t superset ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
+
 /* Helper for __builtin_avr_delay_cycles */
 
 static void
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h	(revision 179594)
+++ config/avr/avr.h	(working copy)
@@ -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, address_space, outer_code, index_code) \
+  avr_mode_code_base_reg_class (mode, address_space, 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, address_space, outer_code, index_code) \
+  avr_regno_mode_code_ok_for_base_p (num, mode, address_space, 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,    \
@@ -403,6 +391,14 @@ typedef struct avr_args {
 
 #define NO_FUNCTION_CSE
 
+
+#define ADDR_SPACE_PGM	1
+
+#define REGISTER_TARGET_PRAGMAS()                                       \
+  do {                                                                  \
+    avr_register_target_pragmas();                                      \
+  }while (0);
+
 #define TEXT_SECTION_ASM_OP "\t.text"
 
 #define DATA_SECTION_ASM_OP "\t.data"
Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 179594)
+++ doc/tm.texi	(working copy)
@@ -2453,12 +2453,13 @@ register address.  You should define thi
 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})
+@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @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
+base register for a memory reference in mode @var{mode} to address
+space @var{address_space} 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
@@ -2498,8 +2499,11 @@ Use of this macro is deprecated; please
 @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
+@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
+A C expression which is nonzero if register number @var{num} is
+suitable for use as a base register in operand addresses, accessing
+memory in mode @var{mode} in address space @var{address_space}.
+This is similar to @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
Index: doc/tm.texi.in
===================================================================
--- doc/tm.texi.in	(revision 179594)
+++ doc/tm.texi.in	(working copy)
@@ -2441,12 +2441,13 @@ register address.  You should define thi
 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})
+@defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @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
+base register for a memory reference in mode @var{mode} to address
+space @var{address_space} 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
@@ -2486,8 +2487,11 @@ Use of this macro is deprecated; please
 @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
+@defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
+A C expression which is nonzero if register number @var{num} is
+suitable for use as a base register in operand addresses, accessing
+memory in mode @var{mode} in address space @var{address_space}.
+This is similar to @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
Index: caller-save.c
===================================================================
--- caller-save.c	(revision 179594)
+++ caller-save.c	(working copy)
@@ -231,7 +231,8 @@ init_caller_save (void)
   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))
+	 [(int) base_reg_class (regno_save_mode[i][1], ADDR_SPACE_GENERIC,
+				PLUS, CONST_INT)], i))
       break;
 
   gcc_assert (i < FIRST_PSEUDO_REGISTER);
Index: ira-conflicts.c
===================================================================
--- ira-conflicts.c	(revision 179594)
+++ ira-conflicts.c	(working copy)
@@ -845,6 +845,7 @@ ira_debug_conflicts (bool reg_p)
 void
 ira_build_conflicts (void)
 {
+  enum reg_class base;
   ira_allocno_t a;
   ira_allocno_iterator ai;
   HARD_REG_SET temp_hard_reg_set;
@@ -874,13 +875,12 @@ ira_build_conflicts (void)
 	  ira_free (conflicts);
 	}
     }
-  if (! targetm.class_likely_spilled_p (base_reg_class (VOIDmode, ADDRESS,
-							SCRATCH)))
+  base = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH);
+  if (! targetm.class_likely_spilled_p (base))
     CLEAR_HARD_REG_SET (temp_hard_reg_set);
   else
     {
-      COPY_HARD_REG_SET (temp_hard_reg_set,
-			 reg_class_contents[base_reg_class (VOIDmode, ADDRESS, SCRATCH)]);
+      COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[base]);
       AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
       AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
     }
Index: ira-costs.c
===================================================================
--- ira-costs.c	(revision 179594)
+++ ira-costs.c	(working copy)
@@ -637,7 +637,8 @@ record_reg_classes (int n_alts, int n_op
 		     base of an address, i.e. BASE_REG_CLASS.  */
 		  classes[i]
 		    = ira_reg_class_subunion[classes[i]]
-		      [base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+		      [base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+				       ADDRESS, SCRATCH)];
 		  break;
 
 		case 'm':  case 'o':  case 'V':
@@ -752,7 +753,8 @@ record_reg_classes (int n_alts, int n_op
 			 i.e. BASE_REG_CLASS.  */
 		      classes[i]
 			= ira_reg_class_subunion[classes[i]]
-			  [base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+			  [base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+					   ADDRESS, SCRATCH)];
 		    }
 #endif
 		  break;
@@ -996,14 +998,14 @@ ok_for_index_p_nonstrict (rtx reg)
    pseudo-registers should count as OK.  Arguments as for
    regno_ok_for_base_p.  */
 static inline bool
-ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode,
+ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode, addr_space_t as,
 			 enum rtx_code outer_code, enum rtx_code index_code)
 {
   unsigned regno = REGNO (reg);
 
   if (regno >= FIRST_PSEUDO_REGISTER)
     return true;
-  return ok_for_base_p_1 (regno, mode, outer_code, index_code);
+  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
 }
 
 /* Record the pseudo registers we must reload into hard registers in a
@@ -1012,16 +1014,16 @@ ok_for_base_p_nonstrict (rtx reg, enum m
    If CONTEXT is 0, we are looking at the base part of an address,
    otherwise we are looking at the index part.
 
-   MODE is the mode of the memory reference; OUTER_CODE and INDEX_CODE
-   give the context that the rtx appears in.  These three arguments
-   are passed down to base_reg_class.
+   MODE and AS are the mode and address space of the memory reference;
+   OUTER_CODE and INDEX_CODE give the context that the rtx appears in.
+   These four arguments are passed down to base_reg_class.
 
    SCALE is twice the amount to multiply the cost by (it is twice so
    we 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)
+record_address_regs (enum machine_mode mode, addr_space_t as, 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 rclass;
@@ -1029,7 +1031,7 @@ record_address_regs (enum machine_mode m
   if (context == 1)
     rclass = INDEX_REG_CLASS;
   else
-    rclass = base_reg_class (mode, outer_code, index_code);
+    rclass = base_reg_class (mode, as, outer_code, index_code);
 
   switch (code)
     {
@@ -1068,67 +1070,68 @@ record_address_regs (enum machine_mode m
 	/* If this machine only allows one register per address, it
 	   must be in the first operand.  */
 	if (MAX_REGS_PER_ADDRESS == 1)
-	  record_address_regs (mode, arg0, 0, PLUS, code1, scale);
+	  record_address_regs (mode, as, 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))
+	else if (INDEX_REG_CLASS
+		 == base_reg_class (VOIDmode, as, PLUS, SCRATCH))
 	  {
-	    record_address_regs (mode, arg0, context, PLUS, code1, scale);
+	    record_address_regs (mode, as, arg0, context, PLUS, code1, scale);
 	    if (! CONSTANT_P (arg1))
-	      record_address_regs (mode, arg1, context, PLUS, code0, scale);
+	      record_address_regs (mode, as, 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);
+	  record_address_regs (mode, as, 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);
+	  record_address_regs (mode, as, 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 hard register is not.  */
 	else if (code0 == REG && code1 == REG
 		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
-		 && (ok_for_base_p_nonstrict (arg0, mode, PLUS, REG)
+		 && (ok_for_base_p_nonstrict (arg0, mode, as, PLUS, REG)
 		     || ok_for_index_p_nonstrict (arg0)))
-	  record_address_regs (mode, arg1,
-			       ok_for_base_p_nonstrict (arg0, mode, PLUS, REG)
-			       ? 1 : 0,
+	  record_address_regs (mode, as, arg1,
+			       ok_for_base_p_nonstrict (arg0, mode, as,
+							PLUS, REG) ? 1 : 0,
 			       PLUS, REG, scale);
 	else if (code0 == REG && code1 == REG
 		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
-		 && (ok_for_base_p_nonstrict (arg1, mode, PLUS, REG)
+		 && (ok_for_base_p_nonstrict (arg1, mode, as, PLUS, REG)
 		     || ok_for_index_p_nonstrict (arg1)))
-	  record_address_regs (mode, arg0,
-			       ok_for_base_p_nonstrict (arg1, mode, PLUS, REG)
-			       ? 1 : 0,
+	  record_address_regs (mode, as, arg0,
+			       ok_for_base_p_nonstrict (arg1, mode, as,
+							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 is a MULT.  */
 	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);
+	    record_address_regs (mode, as, arg0, 0, PLUS, code1, scale);
+	    record_address_regs (mode, as, 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);
+	    record_address_regs (mode, as, arg0, 1, PLUS, code1, scale);
+	    record_address_regs (mode, as, arg1, 0, PLUS, code0, scale);
 	  }
 	/* Otherwise, count equal chances that each might be a base or
 	   index register.  This case should be rare.  */
 	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);
+	    record_address_regs (mode, as, arg0, 0, PLUS, code1, scale / 2);
+	    record_address_regs (mode, as, arg0, 1, PLUS, code1, scale / 2);
+	    record_address_regs (mode, as, arg1, 0, PLUS, code0, scale / 2);
+	    record_address_regs (mode, as, arg1, 1, PLUS, code0, scale / 2);
 	  }
       }
       break;
@@ -1138,10 +1141,10 @@ record_address_regs (enum machine_mode m
 	 up in the wrong place.  */
     case POST_MODIFY:
     case PRE_MODIFY:
-      record_address_regs (mode, XEXP (x, 0), 0, code,
+      record_address_regs (mode, as, 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,
+	record_address_regs (mode, as, XEXP (XEXP (x, 1), 1), 1, code, REG,
 			     2 * scale);
       break;
 
@@ -1152,7 +1155,7 @@ record_address_regs (enum machine_mode m
       /* Double the importance of an allocno that is incremented or
 	 decremented, since it would take two extra insns if it ends
 	 up in the wrong place.  */
-      record_address_regs (mode, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
+      record_address_regs (mode, as, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
       break;
 
     case REG:
@@ -1200,7 +1203,7 @@ record_address_regs (enum machine_mode m
 	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,
+	    record_address_regs (mode, as, XEXP (x, i), context, code, SCRATCH,
 				 scale);
       }
     }
@@ -1236,13 +1239,15 @@ record_operand_costs (rtx insn, enum reg
 
       if (MEM_P (recog_data.operand[i]))
 	record_address_regs (GET_MODE (recog_data.operand[i]),
+			     MEM_ADDR_SPACE (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, ADDRESS,
-			     SCRATCH, frequency * 2);
+	record_address_regs (VOIDmode, ADDR_SPACE_GENERIC,
+			     recog_data.operand[i], 0, ADDRESS, SCRATCH,
+			     frequency * 2);
     }
   
   /* Check for commutative in a separate loop so everything will have
@@ -1316,8 +1321,10 @@ scan_one_insn (rtx insn)
 
       COSTS (costs, num)->mem_cost
 	-= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency;
-      record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0),
-			   0, MEM, SCRATCH, frequency * 2);
+      record_address_regs (GET_MODE (SET_SRC (set)),
+			   MEM_ADDR_SPACE (SET_SRC (set)),
+			   XEXP (SET_SRC (set), 0), 0, MEM, SCRATCH,
+			   frequency * 2);
       counted_mem = true;
     }
 
Index: recog.c
===================================================================
--- recog.c	(revision 179594)
+++ recog.c	(working copy)
@@ -2281,7 +2281,8 @@ preprocess_constraints (void)
 		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)];
+		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+					     ADDRESS, SCRATCH)];
 		  break;
 
 		case 'g':
@@ -2302,8 +2303,8 @@ preprocess_constraints (void)
 		      op_alt[j].cl
 			= (reg_class_subunion
 			   [(int) op_alt[j].cl]
-			   [(int) base_reg_class (VOIDmode, ADDRESS,
-						  SCRATCH)]);
+			   [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+						  ADDRESS, SCRATCH)]);
 		      break;
 		    }
 
Index: regcprop.c
===================================================================
--- regcprop.c	(revision 179594)
+++ regcprop.c	(working copy)
@@ -98,7 +98,7 @@ static rtx find_oldest_value_reg (enum r
 static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx,
 				      struct value_data *);
 static bool replace_oldest_value_addr (rtx *, enum reg_class,
-				       enum machine_mode, rtx,
+				       enum machine_mode, addr_space_t, rtx,
 				       struct value_data *);
 static bool replace_oldest_value_mem (rtx, rtx, struct value_data *);
 static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
@@ -515,8 +515,8 @@ replace_oldest_value_reg (rtx *loc, enum
 
 static bool
 replace_oldest_value_addr (rtx *loc, enum reg_class cl,
-			   enum machine_mode mode, rtx insn,
-			   struct value_data *vd)
+			   enum machine_mode mode, addr_space_t as,
+			   rtx insn, struct value_data *vd)
 {
   rtx x = *loc;
   RTX_CODE code = GET_CODE (x);
@@ -585,15 +585,15 @@ replace_oldest_value_addr (rtx *loc, enu
 	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
 
 	    if (REGNO_OK_FOR_INDEX_P (regno1)
-		&& regno_ok_for_base_p (regno0, mode, PLUS, REG))
+		&& regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
 	      index_op = 1;
 	    else if (REGNO_OK_FOR_INDEX_P (regno0)
-		     && regno_ok_for_base_p (regno1, mode, PLUS, REG))
+		     && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
 	      index_op = 0;
-	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)
+	    else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
 		     || REGNO_OK_FOR_INDEX_P (regno1))
 	      index_op = 1;
-	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
+	    else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
 	      index_op = 0;
 	    else
 	      index_op = 1;
@@ -616,13 +616,13 @@ replace_oldest_value_addr (rtx *loc, enu
 	  }
 
 	if (locI)
-	  changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS, mode,
-						insn, vd);
+	  changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS,
+						mode, as, insn, vd);
 	if (locB)
 	  changed |= replace_oldest_value_addr (locB,
-						base_reg_class (mode, PLUS,
+						base_reg_class (mode, as, PLUS,
 								index_code),
-						mode, insn, vd);
+						mode, as, insn, vd);
 	return changed;
       }
 
@@ -648,12 +648,12 @@ replace_oldest_value_addr (rtx *loc, enu
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-	changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode,
+	changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode, as,
 					      insn, vd);
       else if (fmt[i] == 'E')
 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
 	  changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
-						mode, insn, vd);
+						mode, as, insn, vd);
     }
 
   return changed;
@@ -669,10 +669,11 @@ replace_oldest_value_mem (rtx x, rtx ins
   if (DEBUG_INSN_P (insn))
     cl = ALL_REGS;
   else
-    cl = base_reg_class (GET_MODE (x), MEM, SCRATCH);
+    cl = base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x), MEM, SCRATCH);
 
   return replace_oldest_value_addr (&XEXP (x, 0), cl,
-				    GET_MODE (x), insn, vd);
+				    GET_MODE (x), MEM_ADDR_SPACE (x),
+				    insn, vd);
 }
 
 /* Apply all queued updates for DEBUG_INSNs that change some reg to
@@ -751,7 +752,7 @@ copyprop_hardreg_forward_1 (basic_block
 	      if (!VAR_LOC_UNKNOWN_P (loc))
 		replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
 					   ALL_REGS, GET_MODE (loc),
-					   insn, vd);
+					   ADDR_SPACE_GENERIC, insn, vd);
 	    }
 
 	  if (insn == BB_END (bb))
@@ -893,7 +894,8 @@ copyprop_hardreg_forward_1 (basic_block
 		replaced[i]
 		  = replace_oldest_value_addr (recog_data.operand_loc[i],
 					       recog_op_alt[i][alt].cl,
-					       VOIDmode, insn, vd);
+					       VOIDmode, ADDR_SPACE_GENERIC,
+					       insn, vd);
 	      else if (REG_P (recog_data.operand[i]))
 		replaced[i]
 		  = replace_oldest_value_reg (recog_data.operand_loc[i],
Index: regrename.c
===================================================================
--- regrename.c	(revision 179594)
+++ regrename.c	(working copy)
@@ -145,6 +145,11 @@ static int this_tick = 0;
 static struct obstack rename_obstack;
 
 static void do_replace (struct du_head *, int);
+static void scan_rtx_reg (rtx, rtx *, enum reg_class,
+			  enum scan_actions, enum op_type);
+static void scan_rtx_address (rtx, rtx *, enum reg_class,
+			      enum scan_actions, enum machine_mode,
+			      addr_space_t);
 static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
 		      enum op_type);
 static bool build_def_use (basic_block);
@@ -1177,7 +1182,8 @@ scan_rtx_reg (rtx insn, rtx *loc, enum r
 
 static void
 scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
-		  enum scan_actions action, enum machine_mode mode)
+		  enum scan_actions action, enum machine_mode mode,
+		  addr_space_t as)
 {
   rtx x = *loc;
   RTX_CODE code = GET_CODE (x);
@@ -1245,15 +1251,15 @@ scan_rtx_address (rtx insn, rtx *loc, en
 	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
 
 	    if (REGNO_OK_FOR_INDEX_P (regno1)
-		&& regno_ok_for_base_p (regno0, mode, PLUS, REG))
+		&& regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
 	      index_op = 1;
 	    else if (REGNO_OK_FOR_INDEX_P (regno0)
-		     && regno_ok_for_base_p (regno1, mode, PLUS, REG))
+		     && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
 	      index_op = 0;
-	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)
+	    else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
 		     || REGNO_OK_FOR_INDEX_P (regno1))
 	      index_op = 1;
-	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
+	    else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
 	      index_op = 0;
 	    else
 	      index_op = 1;
@@ -1276,10 +1282,11 @@ scan_rtx_address (rtx insn, rtx *loc, en
 	  }
 
 	if (locI)
-	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
+	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode, as);
 	if (locB)
-	  scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code),
-			    action, mode);
+	  scan_rtx_address (insn, locB,
+			    base_reg_class (mode, as, PLUS, index_code),
+			    action, mode, as);
 
 	return;
       }
@@ -1299,8 +1306,9 @@ scan_rtx_address (rtx insn, rtx *loc, en
 
     case MEM:
       scan_rtx_address (insn, &XEXP (x, 0),
-			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
-			GET_MODE (x));
+			base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
+					MEM, SCRATCH),
+			action, GET_MODE (x), MEM_ADDR_SPACE (x));
       return;
 
     case REG:
@@ -1315,10 +1323,10 @@ scan_rtx_address (rtx insn, rtx *loc, en
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode);
+	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode, as);
       else if (fmt[i] == 'E')
 	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode);
+	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode, as);
     }
 }
 
@@ -1351,8 +1359,9 @@ scan_rtx (rtx insn, rtx *loc, enum reg_c
 
     case MEM:
       scan_rtx_address (insn, &XEXP (x, 0),
-			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
-			GET_MODE (x));
+			base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
+					MEM, SCRATCH),
+			action, GET_MODE (x), MEM_ADDR_SPACE (x));
       return;
 
     case SET:
@@ -1675,7 +1684,8 @@ build_def_use (basic_block bb)
 		continue;
 
 	      if (recog_op_alt[opn][alt].is_address)
-		scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
+		scan_rtx_address (insn, loc, cl, mark_read,
+				  VOIDmode, ADDR_SPACE_GENERIC);
 	      else
 		scan_rtx (insn, loc, cl, mark_read, type);
 	    }
Index: reload1.c
===================================================================
--- reload1.c	(revision 179594)
+++ reload1.c	(working copy)
@@ -1422,7 +1422,8 @@ maybe_fix_stack_asms (void)
 
 		case 'p':
 		  cls = (int) reg_class_subunion[cls]
-		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+					     ADDRESS, SCRATCH)];
 		  break;
 
 		case 'g':
@@ -1433,7 +1434,8 @@ maybe_fix_stack_asms (void)
 		default:
 		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
 		    cls = (int) reg_class_subunion[cls]
-		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+					     ADDRESS, SCRATCH)];
 		  else
 		    cls = (int) reg_class_subunion[cls]
 		      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
Index: reload.c
===================================================================
--- reload.c	(revision 179594)
+++ reload.c	(working copy)
@@ -278,7 +278,7 @@ static int find_reloads_address (enum ma
 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,
+static int find_reloads_address_1 (enum machine_mode, addr_space_t, 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,
@@ -3242,8 +3242,9 @@ find_reloads (rtx insn, int replace, int
 	      case 'p':
 		/* All necessary reloads for an address_operand
 		   were handled in find_reloads_address.  */
-		this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
-						      SCRATCH);
+		this_alternative[i]
+		  = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+				    ADDRESS, SCRATCH);
 		win = 1;
 		badop = 0;
 		break;
@@ -3448,9 +3449,9 @@ find_reloads (rtx insn, int replace, int
 
 			/* If we didn't already win, we can reload
 			   the address into a base register.  */
-			this_alternative[i] = base_reg_class (VOIDmode,
-							      ADDRESS,
-							      SCRATCH);
+			this_alternative[i]
+			  = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+					    ADDRESS, SCRATCH);
 			badop = 0;
 			break;
 		      }
@@ -3980,18 +3981,16 @@ find_reloads (rtx insn, int replace, int
 	    /* If the address to be reloaded is a VOIDmode constant,
 	       use the default address mode as mode of the reload register,
 	       as would have been done by find_reloads_address.  */
+	    addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
 	    enum machine_mode address_mode;
 	    address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
 	    if (address_mode == VOIDmode)
-	      {
-		addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
-		address_mode = targetm.addr_space.address_mode (as);
-	      }
+	      address_mode = targetm.addr_space.address_mode (as);
 
 	    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),
+			     base_reg_class (VOIDmode, as, MEM, SCRATCH),
 			     address_mode,
 			     VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
 	    rld[operand_reloadnum[i]].inc
@@ -4888,7 +4887,7 @@ find_reloads_address (enum machine_mode
       if (reg_equiv_constant (regno) != 0)
 	{
 	  find_reloads_address_part (reg_equiv_constant (regno), loc,
-				     base_reg_class (mode, MEM, SCRATCH),
+				     base_reg_class (mode, as, MEM, SCRATCH),
 				     GET_MODE (ad), opnum, type, ind_levels);
 	  return 1;
 	}
@@ -4951,12 +4950,13 @@ find_reloads_address (enum machine_mode
 	 subject of a CLOBBER in this insn.  */
 
       else if (regno < FIRST_PSEUDO_REGISTER
-	       && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
+	       && regno_ok_for_base_p (regno, mode, as, 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),
+      push_reload (ad, NULL_RTX, loc, (rtx*) 0,
+		   base_reg_class (mode, as, MEM, SCRATCH),
 		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
       return 1;
     }
@@ -5057,7 +5057,7 @@ find_reloads_address (enum machine_mode
 	  /* 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),
+		       base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (tem),
 		       VOIDmode, 0,
 		       0, opnum, type);
 	  return ! removed_and;
@@ -5075,7 +5075,7 @@ find_reloads_address (enum machine_mode
 	   && REG_P (XEXP (ad, 0))
 	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
 	   && CONST_INT_P (XEXP (ad, 1))
-	   && (regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
+	   && (regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as, PLUS,
 				    CONST_INT)
 	       /* Similarly, if we were to reload the base register and the
 		  mem+offset address is still invalid, then we want to reload
@@ -5094,7 +5094,7 @@ find_reloads_address (enum machine_mode
 	}
 
       if (double_reg_address_ok
-	  && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode,
+	  && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as,
 				  PLUS, CONST_INT))
 	{
 	  /* Unshare the sum as well.  */
@@ -5113,7 +5113,7 @@ find_reloads_address (enum machine_mode
 	     reload the sum into a base reg.
 	     That will at least work.  */
 	  find_reloads_address_part (ad, loc,
-				     base_reg_class (mode, MEM, SCRATCH),
+				     base_reg_class (mode, as, MEM, SCRATCH),
 				     GET_MODE (ad), opnum, type, ind_levels);
 	}
       return ! removed_and;
@@ -5165,7 +5165,7 @@ find_reloads_address (enum machine_mode
 
       addend = XEXP (XEXP (ad, 0), 1 - op_index);
 
-      if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
+      if ((regno_ok_for_base_p (REGNO (operand), mode, as, inner_code,
 				GET_CODE (addend))
 	   || operand == frame_pointer_rtx
 #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
@@ -5194,11 +5194,11 @@ find_reloads_address (enum machine_mode
 				 op_index == 0 ? addend : offset_reg);
 	  *loc = ad;
 
-	  cls = base_reg_class (mode, MEM, GET_CODE (addend));
+	  cls = base_reg_class (mode, as, 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,
+	  find_reloads_address_1 (mode, as,
 				  XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
 				  GET_CODE (XEXP (ad, op_index)),
 				  &XEXP (ad, 1 - op_index), opnum,
@@ -5251,13 +5251,14 @@ find_reloads_address (enum machine_mode
 	    loc = &XEXP (*loc, 0);
 	}
 
-      find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
+      find_reloads_address_part (ad, loc,
+				 base_reg_class (mode, as, MEM, SCRATCH),
 				 address_mode, opnum, type, ind_levels);
       return ! removed_and;
     }
 
-  return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
-				 ind_levels, insn);
+  return find_reloads_address_1 (mode, as, ad, 0, MEM, SCRATCH, loc,
+				 opnum, type, ind_levels, insn);
 }
 
 /* Find all pseudo regs appearing in AD
@@ -5490,14 +5491,15 @@ update_auto_inc_notes (rtx insn ATTRIBUT
    handles those cases gracefully.  */
 
 static int
-find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
+find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
+			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, OUTER, INDEX)		\
+#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX)	\
   ((CONTEXT) == 0							\
-   ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX)			\
+   ? regno_ok_for_base_p (REGNO, MODE, AS, OUTER, INDEX)		\
    : REGNO_OK_FOR_INDEX_P (REGNO))
 
   enum reg_class context_reg_class;
@@ -5506,7 +5508,7 @@ find_reloads_address_1 (enum machine_mod
   if (context == 1)
     context_reg_class = INDEX_REG_CLASS;
   else
-    context_reg_class = base_reg_class (mode, outer_code, index_code);
+    context_reg_class = base_reg_class (mode, as, outer_code, index_code);
 
   switch (code)
     {
@@ -5563,10 +5565,10 @@ find_reloads_address_1 (enum machine_mod
 	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
 	    || code0 == ZERO_EXTEND || code1 == MEM)
 	  {
-	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+	    find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
 				    &XEXP (x, 0), opnum, type, ind_levels,
 				    insn);
-	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
+	    find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
 				    &XEXP (x, 1), opnum, type, ind_levels,
 				    insn);
 	  }
@@ -5574,56 +5576,56 @@ find_reloads_address_1 (enum machine_mod
 	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
 		 || code1 == ZERO_EXTEND || code0 == MEM)
 	  {
-	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
+	    find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
 				    &XEXP (x, 0), opnum, type, ind_levels,
 				    insn);
-	    find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+	    find_reloads_address_1 (mode, as, 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,
+	  find_reloads_address_1 (mode, as, 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,
+	  find_reloads_address_1 (mode, as, 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 (op1))
-		&& regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
+		&& regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
 	      return 0;
 	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
-		     && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
+		     && regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
 	      return 0;
-	    else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
-	      find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+	    else if (regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
+	      find_reloads_address_1 (mode, as, 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,
+	      find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
 				      &XEXP (x, 0), opnum, type, ind_levels,
 				      insn);
-	    else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
-	      find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+	    else if (regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
+	      find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
 				      &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,
+	      find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
 				      &XEXP (x, 1), opnum, type, ind_levels,
 				      insn);
 	    else
 	      {
-		find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+		find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
 					&XEXP (x, 0), opnum, type, ind_levels,
 					insn);
-		find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
+		find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
 					&XEXP (x, 1), opnum, type, ind_levels,
 					insn);
 	      }
@@ -5631,20 +5633,20 @@ find_reloads_address_1 (enum machine_mod
 
 	else if (code0 == REG)
 	  {
-	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
+	    find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
 				    &XEXP (x, 0), opnum, type, ind_levels,
 				    insn);
-	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
+	    find_reloads_address_1 (mode, as, 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,
+	    find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
 				    &XEXP (x, 1), opnum, type, ind_levels,
 				    insn);
-	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
+	    find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
 				    &XEXP (x, 0), opnum, type, ind_levels,
 				    insn);
 	  }
@@ -5686,7 +5688,7 @@ find_reloads_address_1 (enum machine_mod
 	if ((REG_P (XEXP (op1, 1))
 	     && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
 	    || GET_CODE (XEXP (op1, 1)) == PLUS)
-	  find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
+	  find_reloads_address_1 (mode, as, XEXP (op1, 1), 1, code, SCRATCH,
 				  &XEXP (op1, 1), opnum, RELOAD_OTHER,
 				  ind_levels, insn);
 
@@ -5728,8 +5730,8 @@ find_reloads_address_1 (enum machine_mod
 		   register.  */
 		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
 					 &XEXP (op1, 0),
-					 base_reg_class (mode, code,
-							 index_code),
+					 base_reg_class (mode, as,
+							 code, index_code),
 					 GET_MODE (x), GET_MODE (x), 0,
 					 0, opnum, RELOAD_OTHER);
 
@@ -5742,11 +5744,12 @@ find_reloads_address_1 (enum machine_mod
 	  regno = reg_renumber[regno];
 
 	/* We require a base register here...  */
-	if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
+	if (!regno_ok_for_base_p (regno, GET_MODE (x), as, 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),
+				     base_reg_class (mode, as,
+						     code, index_code),
 				     GET_MODE (x), GET_MODE (x), 0, 0,
 				     opnum, RELOAD_OTHER);
 
@@ -5812,7 +5815,7 @@ find_reloads_address_1 (enum machine_mod
 	  if (reg_renumber[regno] >= 0)
 	    regno = reg_renumber[regno];
 	  if (regno >= FIRST_PSEUDO_REGISTER
-	      || !REG_OK_FOR_CONTEXT (context, regno, mode, code,
+	      || !REG_OK_FOR_CONTEXT (context, regno, mode, as, code,
 				      index_code))
 	    {
 	      int reloadnum;
@@ -5881,7 +5884,7 @@ find_reloads_address_1 (enum machine_mod
 	 reloaded.  Targets that are better off reloading just either part
 	 (or perhaps even a different part of an outer expression), should
 	 define LEGITIMIZE_RELOAD_ADDRESS.  */
-      find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0),
+      find_reloads_address_1 (GET_MODE (XEXP (x, 0)), as, XEXP (x, 0),
 			      context, code, SCRATCH, &XEXP (x, 0), opnum,
 			      type, ind_levels, insn);
       push_reload (x, NULL_RTX, loc, (rtx*) 0,
@@ -5952,7 +5955,7 @@ find_reloads_address_1 (enum machine_mod
 	  regno = reg_renumber[regno];
 
 	if (regno >= FIRST_PSEUDO_REGISTER
-	    || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+	    || !REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
 				    index_code))
 	  {
 	    push_reload (x, NULL_RTX, loc, (rtx*) 0,
@@ -5985,7 +5988,7 @@ find_reloads_address_1 (enum machine_mod
 	    {
 	      int regno ATTRIBUTE_UNUSED = subreg_regno (x);
 
-	      if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
+	      if (!REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
 				       index_code))
 		{
 		  push_reload (x, NULL_RTX, loc, (rtx*) 0,
@@ -6026,8 +6029,9 @@ find_reloads_address_1 (enum machine_mod
 	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);
+	  find_reloads_address_1 (mode, as, XEXP (x, i), context,
+				  code, SCRATCH, &XEXP (x, i),
+				  opnum, type, ind_levels, insn);
       }
   }
 
@@ -6204,7 +6208,9 @@ find_reloads_subreg_address (rtx x, int
 			 MEM_ADDR_SPACE (reg_equiv_mem (regno))))
 		{
 		  push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
-			       base_reg_class (GET_MODE (tem), MEM, SCRATCH),
+			       base_reg_class (GET_MODE (tem),
+					       MEM_ADDR_SPACE (tem),
+					       MEM, SCRATCH),
 			       GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
 			       opnum, type);
 		  reloaded = 1;
Index: addresses.h
===================================================================
--- addresses.h	(revision 179594)
+++ addresses.h	(working copy)
@@ -23,11 +23,12 @@ along with GCC; see the file COPYING3.
 
 static inline enum reg_class
 base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+		addr_space_t as 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);
+  return MODE_CODE_BASE_REG_CLASS (mode, as, outer_code, index_code);
 #else
 #ifdef MODE_BASE_REG_REG_CLASS
   if (index_code == REG)
@@ -49,11 +50,13 @@ base_reg_class (enum machine_mode mode A
 static inline bool
 ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
 		 enum machine_mode mode ATTRIBUTE_UNUSED,
+		 addr_space_t as ATTRIBUTE_UNUSED,
 		 enum rtx_code outer_code ATTRIBUTE_UNUSED,
 		 enum rtx_code index_code ATTRIBUTE_UNUSED)
 {
 #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
-  return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, outer_code, index_code);
+  return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, as,
+					outer_code, index_code);
 #else
 #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
   if (index_code == REG)
@@ -71,11 +74,11 @@ ok_for_base_p_1 (unsigned regno ATTRIBUT
    complete.  Arguments as for the called function.  */
 
 static inline bool
-regno_ok_for_base_p (unsigned regno, enum machine_mode mode,
+regno_ok_for_base_p (unsigned regno, enum machine_mode mode, addr_space_t as,
 		     enum rtx_code outer_code, enum rtx_code index_code)
 {
   if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
     regno = reg_renumber[regno];
 
-  return ok_for_base_p_1 (regno, mode, outer_code, index_code);
+  return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
 }

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