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]

[named-address-space-branch][Patch,committed] Update RTL memory functions for named address support


This update is a checkpoint in my current work.  The main part of the changes
is to update the RTL memory functions (change_address, adjust_address,
offset_address, replace_equiv_address, etc.) and make them namespace aware.  I
did this usually by renaming the function and adding a new argument for the
named address space.

I added support for the backend to say that that two named address pointers
being subtracted might produce a result in a different type than ptrdiff_type.

I added a few execute tests, to test various static initializations.  Most of
the test currently fail.  I also added a hook, which isn't yet used for the
backend to say whether you can initialize something in a given named address
space.  Right now, I'm looking for the place to put this, and I may change some
of the execute tests to compile tests checking for failure, when I resolve the
initialization support.

I updated a few of the files not to use Pmode, but to use the mode of the
memory that they are replacing.

[gcc]
2008-12-16  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* targhooks.c (default_valid_pointer_mode): Move here from
	varasm.c.
	(default_addr_space_pointer_mode): Ditto.
	(default_addr_space_minus_type): New hook to return the type used
	for the difference of two pointers.
	(default_addr_space_memory_address_p): New hook for the named
	address space version of memory_address_p.
	(default_addr_space_strict_memory_address_p): New hook for the
	named address space version of strict_memory_address_p.
	(default_addr_space_legitimize_address): New hook for the named
	address space version of LEGITIMIZE_ADDRESS.
	(default_addr_space_static_init_ok_p): New hook to determine if an
	initialization can take place in another named address space.

	* targhooks.h (default_valid_pointer_mode): Add declaration.
	(default_addr_space_pointer_mode): Ditto.
	(default_addr_space_minus_type): Ditto.
	(default_addr_space_memory_address_p): Ditto.
	(default_addr_space_strict_memory_address_p): Ditto.
	(default_addr_space_legitimize_address): Ditto.
	(default_addr_space_static_init_ok_p): Ditto.

	* target.h (struct addr_space): Add minus_type, memory_address_p,
	strict_memory_address_p, legitimize_address, and static_init_ok_p
	hooks.

	* auto-inc-dec.c (try_merge): Use GET_MODE instead of Pmode for
	the mode of newly created RTL.

	* expr.c (emit_move_insn): Add named address support.
	(expand_expr_real_1): Ditto.

	* expr.h (memory_address_addr_space): Add declaration.
	(memory_address): Define in terms of memory_address_addr_space
	with the generic address space.

	* recog.c (memory_address_addr_space_p): New function, like
	memory_address_p, except it takes an named address space
	identifier.

	* recog.h (memory_address_addr_space_p): Add declaration.
	(strict_memory_address_addr_space_p): Ditto.

	* c-typeck.c (parser_build_binary_op): Use the address space
	minus_type hook to determine what type is used for subtraction of
	two pointers to named address spaces.
	(convert_for_assignment): Shorten a line to under 80 characters.

	* emit-rtl.c (toplevel): Include target.h.
	(change_address_1): Add named address space parameter.  Switch
	validation to be named address space aware.
	(change_address_addr_space): Like change_address, but take the
	address space to change the address to.
	(change_address): Call change_address_addr_space with generic
	address space argument.
	(adjust_address_1): Add support for named address spaces.
	(offset_address): Ditto.
	(replace_equiv_address): Add address space argument.
	(replace_equiv_address_nv): Ditto.

	* explow.c (break_out_memory_refs): Use GET_MODE of the address
	instead of assuming all pointers are Pmode.
	(memory_address_addr_space): Rename from memory_address, add named
	address space argument.  Use named address space legitimize hook
	instead of LEGITIMIZE_ADDRESS for memory addresse spaces other
	than the generic address space.
	(validize_mem): Add named address space support.

	* varasm.c (make_decl_rtl): Reformat code somewhat.
	(default_valid_pointer_mode): Move to targhooks.c.
	(default_addr_space_pointer): Ditto.

	* target-def.h (TARGET_ADDR_SPACE_MINUS_HOOK): New named address
	space hook.
	(TARGET_ADDR_SPACE_MEMORY_ADDRESS_P): Ditto.
	(TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P): Ditto.
	(TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS): Ditto.
	(TARGET_ADDR_SPACE_STATIC_INIT_OK_P): Ditto.
	(TARGET_ADDR_SPACE_HOOKS): Add new hooks.

	* Makefile.in (emit-rtl.o): Add $(TARGET_H) dependencies.

	* config/spu/spu-protos.h (spu_legitimate_address): Add named
	address space argument.
	(spu_legitimize_address): New hook.

	* config/spu/spu.c (EAmode): Move earlier in the file.
	(spu_addr_space_pointer_mode): Rename from spu_ea_pointer_mode for
	consistancy.  Simplify code somewhat.
	(TARGET_ADDR_SPACE_POINTER_MODE): Use spu_addr_space_pointer_mode.
	(spu_addr_space_minus_type): New named address space hook.
	(spu_addr_space_memory_address_p): Ditto.
	(spu_addr_space_strict_memory_address_p): Ditto.
	(spu_addr_space_legitimize_address): Ditto.
	(spu_addr_space_static_init_ok_p): Ditto.
	(TARGET_ADDR_SPACE_MINUS_TYPE): Ditto.
	(TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P): Ditto.
	(TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS): Ditto.
	(TARGET_ADDR_SPACE_STATIC_INIT_OK_P): Ditto.
	(spu_legitimate_address): Add named address space argument.
	(spu_legitimize_address): Ditto.
	(expand_ea_mem): Use change_address_addr_space instead of
	change_address.
	(spu_valid_move): Add assert for being inside function context.

	* config/spu/spu.h (GO_IF_LEGITIMATE_ADDRESS): Add default named
	address space argument.
	(LEGITIMIZE_ADDRESS): Ditto.

[gcc/testsuite]
2008-12-16  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/spu/ea/compile3.c: Add static initializations.
	* gcc.target/spu/ea/errors3.c: Ditto.

	* gcc.target/spu/ea/compile4.c: New file to make sure __ea
	structure references work.

	* gcc.target/spu/ea/execute1.c: New file to make sure various
	static initializations work for -mea32.
	* gcc.target/spu/ea/execute2.c: Ditto.
	* gcc.target/spu/ea/execute3.c: Ditto.
	* gcc.target/spu/ea/execute4.c: Ditto.
	* gcc.target/spu/ea/execute5.c: Ditto.
	* gcc.target/spu/ea/execute6.c: Ditto.

	* gcc.target/spu/ea/execute1-m64.c: New file to make sure various
	static initializations work for -mea64.
	* gcc.target/spu/ea/execute2-m64.c: Ditto.
	* gcc.target/spu/ea/execute3-m64.c: Ditto.
	* gcc.target/spu/ea/execute4-m64.c: Ditto.
	* gcc.target/spu/ea/execute5-m64.c: Ditto.
	* gcc.target/spu/ea/execute6-m64.c: Ditto.
	
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(revision 142610)
+++ gcc/targhooks.c	(working copy)
@@ -712,6 +712,35 @@ default_builtin_vector_alignment_reachab
   return true;
 }
 
+/* Determine whether or not a pointer mode is valid. Assume defaults
+   of ptr_mode or Pmode - can be overridden.  */
+bool
+default_valid_pointer_mode (enum machine_mode mode)
+{
+  return (mode == ptr_mode || mode == Pmode);
+}
+
+/* Return the mode for a pointer to a given ADDRSPACE, defaulting to ptr_mode
+   for the generic address space only.  */
+
+enum machine_mode
+default_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
+{
+  gcc_assert (addrspace == 0);
+  return ptr_mode;
+}
+
+/* Return the integer mode for subtracting two pointers to named address
+   spaces.  */
+
+tree
+default_addr_space_minus_type (addr_space_t as1 ATTRIBUTE_UNUSED,
+			       addr_space_t as2 ATTRIBUTE_UNUSED)
+{
+  gcc_assert (as1 == 0 && as2 == 0);
+  return ptrdiff_type_node;
+}
+
 /* The default hook for TARGET_ADDR_SPACE_NAME.  This hook should
    never be called for targets with only a generic address space.  */
 
@@ -721,6 +750,41 @@ default_addr_space_name (addr_space_t ad
   gcc_unreachable ();
 }
 
+/* Named address space version of memory_address_p.  */
+
+bool
+default_addr_space_memory_address_p (enum machine_mode mode, rtx mem,
+				     addr_space_t as)
+{
+  if (!as)
+    return memory_address_p (mode, mem);
+
+  gcc_unreachable ();
+}
+
+/* Named address space version of strict_memory_address_p.  */
+
+bool
+default_addr_space_strict_memory_address_p (enum machine_mode mode, rtx mem,
+					    addr_space_t as)
+{
+  if (!as)
+    return strict_memory_address_p (mode, mem);
+
+  gcc_unreachable ();
+}
+
+/* Named address space version of LEGITIMIZE_ADDRESS.  */
+
+rtx
+default_addr_space_legitimize_address (rtx x ATTRIBUTE_UNUSED,
+				       rtx oldx ATTRIBUTE_UNUSED,
+				       enum machine_mode mode ATTRIBUTE_UNUSED,
+				       addr_space_t as ATTRIBUTE_UNUSED)
+{
+  return NULL_RTX;
+}
+
 /* The default hook for determining whether you can convert from one address
    space to another.  */
 
@@ -782,6 +846,18 @@ default_addr_space_section_name (addr_sp
   gcc_unreachable ();
 }
 
+/* The default hook for determining if a static initialization is ok.  For the
+   default case, only assume static initializations in the generic address
+   space are ok.  */
+
+bool
+default_addr_space_static_init_ok_p (tree value ATTRIBUTE_UNUSED,
+				     addr_space_t var_as,
+				     addr_space_t element_as)
+{
+  return (var_as == 0) && (element_as == 0);
+}
+
 bool
 default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED)
 {
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h	(revision 142610)
+++ gcc/targhooks.h	(working copy)
@@ -104,11 +104,22 @@ extern bool default_hard_regno_scratch_o
 extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
 extern bool default_target_option_pragma_parse (tree, tree);
 extern bool default_target_option_can_inline_p (tree, tree);
+extern bool default_valid_pointer_mode (enum machine_mode);
+extern enum machine_mode default_addr_space_pointer_mode (addr_space_t);
+extern tree default_addr_space_minus_type (addr_space_t, addr_space_t);
 extern const char *default_addr_space_name (addr_space_t);
 extern rtx default_addr_space_convert (rtx, enum machine_mode, addr_space_t,
 				       addr_space_t);
+extern bool default_addr_space_memory_address_p (enum machine_mode, rtx,
+						 addr_space_t);
+extern bool default_addr_space_strict_memory_address_p (enum machine_mode, rtx,
+							addr_space_t);
+extern rtx default_addr_space_legitimize_address (rtx, rtx, enum machine_mode,
+						  addr_space_t);
 extern bool default_addr_space_can_convert_p (addr_space_t, addr_space_t);
 extern bool default_addr_space_nop_convert_p (addr_space_t, addr_space_t);
 extern bool default_addr_space_subset_p (addr_space_t, addr_space_t,
 					 addr_space_t *);
 extern tree default_addr_space_section_name (addr_space_t);
+extern bool default_addr_space_static_init_ok_p (tree, addr_space_t,
+						 addr_space_t);
Index: gcc/target.h
===================================================================
--- gcc/target.h	(revision 142610)
+++ gcc/target.h	(working copy)
@@ -667,15 +667,31 @@ struct gcc_target
     /* MODE to use for a pointer into another address space.  */
     enum machine_mode (* pointer_mode) (addr_space_t);
 
+    /* Tree type to use for pointer subtraction.  */
+    tree (* minus_type) (addr_space_t, addr_space_t);
+
     /* Function to map an address space to a descriptive string.  */
     const char * (* name) (addr_space_t);
 
+    /* True if an addrress is a valid memory address to a given named address
+       space for a given mode.  */
+    bool (* memory_address_p) (enum machine_mode, rtx, addr_space_t);
+
+    /* True if an addrress is a valid memory address for use after register
+       allocation to a given named address space for a given mode.  */
+    bool (* strict_memory_address_p) (enum machine_mode, rtx, addr_space_t);
+
+    /* Return an updated address to convert an invalid pointer to a named
+       address space to a valid one.  If NULL_RTX is returned use machine
+       independent methods to make the address valid.  */
+    rtx (* legitimize_address) (rtx, rtx, enum machine_mode, addr_space_t);
+
     /* True if it is legal to convert a pointer of one address space to
        another.  */
     bool (* can_convert_p) (addr_space_t, addr_space_t);
 
     /* True if converting a pointer of one address space to another is just a
-       NOP.  */
+       NOP and can be optimized away by the compiler.  */
     bool (* nop_convert_p) (addr_space_t, addr_space_t);
 
     /* True if one named address space is a subset of another and if so, which
@@ -688,6 +704,11 @@ struct gcc_target
 
     /* Section name to use for a named address space.  */
     tree (* section_name) (addr_space_t);
+
+    /* Return whether static initialization of a pointer to a named address
+       space is allowed.  */
+    bool (* static_init_ok_p) (tree, addr_space_t, addr_space_t);
+
   } addr_space;
 
   /* True if MODE is valid for the target.  By "valid", we mean able to
Index: gcc/auto-inc-dec.c
===================================================================
--- gcc/auto-inc-dec.c	(revision 142610)
+++ gcc/auto-inc-dec.c	(working copy)
@@ -651,6 +651,7 @@ try_merge (void)
   /* The width of the mem being accessed.  */
   int size = GET_MODE_SIZE (GET_MODE (mem));
   rtx last_insn = NULL;
+  enum machine_mode reg_mode = GET_MODE (inc_reg);
 
   switch (inc_insn.form)
     {
@@ -705,33 +706,33 @@ try_merge (void)
     case SIMPLE_PRE_INC:     /* ++size  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_PRE_INC\n");
-      return attempt_change (gen_rtx_PRE_INC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_PRE_INC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_INC:    /* size++  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_POST_INC\n");
-      return attempt_change (gen_rtx_POST_INC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_POST_INC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_PRE_DEC:     /* --size  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_PRE_DEC\n");
-      return attempt_change (gen_rtx_PRE_DEC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_PRE_DEC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_DEC:    /* size--  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_POST_DEC\n");
-      return attempt_change (gen_rtx_POST_DEC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_POST_DEC (reg_mode, inc_reg), inc_reg);
       break;
       
     case DISP_PRE:           /* ++con   */
       if (dump_file)
 	fprintf (dump_file, "trying DISP_PRE\n");
-      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_PRE_MODIFY (reg_mode, 
 						 inc_reg,
-						 gen_rtx_PLUS (Pmode,
+						 gen_rtx_PLUS (reg_mode,
 							       inc_reg,
 							       inc_insn.reg1)),
 			     inc_reg);
@@ -740,9 +741,9 @@ try_merge (void)
     case DISP_POST:          /* con++   */
       if (dump_file)
 	fprintf (dump_file, "trying POST_DISP\n");
-      return attempt_change (gen_rtx_POST_MODIFY (Pmode,
+      return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
 						  inc_reg,
-						  gen_rtx_PLUS (Pmode,
+						  gen_rtx_PLUS (reg_mode,
 								inc_reg,
 								inc_insn.reg1)),
 			     inc_reg);
@@ -751,9 +752,9 @@ try_merge (void)
     case REG_PRE:            /* ++reg   */
       if (dump_file)
 	fprintf (dump_file, "trying PRE_REG\n");
-      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_PRE_MODIFY (reg_mode, 
 						 inc_reg,
-						 gen_rtx_PLUS (Pmode,
+						 gen_rtx_PLUS (reg_mode,
 							       inc_reg,
 							       inc_insn.reg1)),
 			     inc_reg);
@@ -762,9 +763,9 @@ try_merge (void)
     case REG_POST:            /* reg++   */
       if (dump_file)
 	fprintf (dump_file, "trying POST_REG\n");
-      return attempt_change (gen_rtx_POST_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_POST_MODIFY (reg_mode, 
 						  inc_reg,
-						  gen_rtx_PLUS (Pmode,
+						  gen_rtx_PLUS (reg_mode,
 								inc_reg,
 								inc_insn.reg1)),
 			     inc_reg);
@@ -1127,7 +1128,7 @@ find_inc (bool first_try)
 		     we are going to increment the result of the add insn.
 		     For this trick to be correct, the result reg of
 		     the inc must be a valid addressing reg.  */
-		  if (GET_MODE (inc_insn.reg_res) != Pmode)
+		  if (targetm.valid_pointer_mode (GET_MODE (inc_insn.reg_res)))
 		    {
 		      if (dump_file)
 			fprintf (dump_file, "base reg mode failure.\n");
@@ -1176,7 +1177,7 @@ find_inc (bool first_try)
 	{
 	  /* For this trick to be correct, the result reg of the inc
 	     must be a valid addressing reg.  */
-	  if (GET_MODE (inc_insn.reg_res) != Pmode)
+	  if (targetm.valid_pointer_mode (GET_MODE (inc_insn.reg_res)))
 	    {
 	      if (dump_file)
 		fprintf (dump_file, "base reg mode failure.\n");
Index: gcc/testsuite/gcc.target/spu/ea/errors3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/errors3.c	(revision 142610)
+++ gcc/testsuite/gcc.target/spu/ea/errors3.c	(working copy)
@@ -4,8 +4,17 @@
 /* This is the same as compile3.c except it should generate errors where
    pointers are mixed.  If you modify this code, please modify compile3.c as
    well.  */
+
+#define __lm
+
+__ea int ea_var = 1;
+__lm int lm_var = 2;
+
 typedef __ea int *ea_ptr_t;
-typedef      int *lm_ptr_t;
+typedef __lm int *lm_ptr_t;
+
+typedef __ea char *ea_cptr_t;
+typedef __lm char *lm_cptr_t;
 
 ea_ptr_t ea, ea2;
 lm_ptr_t lm, lm2;
@@ -42,3 +51,12 @@ int if_lm_with_cast (int test) { return 
 
 void void_ea (void) { ea = (void *)0; }
 void void_lm (void) { lm = (__ea void *)0; }
+
+ea_ptr_t ea_init = &lm_var;				/* { dg-error "initialization of a pointer to an incompatible address space" } */
+lm_ptr_t lm_init = &ea_var;				/* { dg-error "initialization of a pointer to an incompatible address space" } */
+
+ea_ptr_t ea_init2 = (ea_ptr_t)&lm_var;
+lm_ptr_t lm_init2 = (lm_ptr_t)&ea_var;
+
+ea_cptr_t ea_str = "abc";				/* { dg-error "initialization of a pointer to an incompatible address space" } */
+ea_cptr_t ea_str2 = (ea_cptr_t)"def";
Index: gcc/testsuite/gcc.target/spu/ea/compile3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/compile3.c	(revision 142610)
+++ gcc/testsuite/gcc.target/spu/ea/compile3.c	(working copy)
@@ -3,8 +3,17 @@
 
 /* This is the same as errors3.c except it should not generate any errors.
    If you modify this code, please modify errors3.c as well.  */
+
+#define __lm
+
+__ea int ea_var = 1;
+__lm int lm_var = 2;
+
 typedef __ea int *ea_ptr_t;
-typedef      int *lm_ptr_t;
+typedef __lm int *lm_ptr_t;
+
+typedef __ea char *ea_cptr_t;
+typedef __lm char *lm_cptr_t;
 
 ea_ptr_t ea, ea2;
 lm_ptr_t lm, lm2;
@@ -40,3 +49,12 @@ int if_lm_with_cast (int test) { return 
 
 void void_ea (void) { ea = (void *)0; }
 void void_lm (void) { lm = (__ea void *)0; }
+
+ea_ptr_t ea_init = &lm_var;
+lm_ptr_t lm_init = &ea_var;
+
+ea_ptr_t ea_init2 = (ea_ptr_t)&lm_var;
+lm_ptr_t lm_init2 = (lm_ptr_t)&ea_var;
+
+ea_cptr_t ea_str = "abc";
+ea_cptr_t ea_str2 = (ea_cptr_t)"def";
Index: gcc/testsuite/gcc.target/spu/ea/compile4.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/compile4.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/compile4.c	(revision 0)
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99 -pedantic-errors -mea64" } */
+/* Make sure __ea structure references work.  */
+
+typedef unsigned long int uintptr_t;
+
+struct tostruct
+{
+  uintptr_t selfpc;
+  long count;
+  unsigned short link;
+};
+
+/* froms are indexing tos */
+static __ea unsigned short *froms;
+static __ea struct tostruct *tos = 0;
+
+void
+foo (uintptr_t frompc, uintptr_t selfpc)
+{
+  __ea unsigned short *frompcindex;
+
+  frompcindex = &froms[(frompc) / (4 * sizeof (*froms))];
+  *frompcindex = tos[0].link;
+
+  return;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute1.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute1.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute1.c	(revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+__ea char *p = "abc";
+
+int
+main (void)
+{
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute2.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute2.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute2.c	(revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+__ea char *p = str;
+
+int
+main (void)
+{
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute3.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute3.c	(revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+__ea char *p = (__ea char *)str;
+
+int
+main (void)
+{
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute4.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute4.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute4.c	(revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+
+int
+main (void)
+{
+  __ea char *p = str;
+
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute1-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute1-m64.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute1-m64.c	(revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+__ea char *p = "abc";
+
+int
+main (void)
+{
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute5.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute5.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute5.c	(revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+
+int
+main (void)
+{
+  __ea char *p = (__ea char *)str;
+
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute2-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute2-m64.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute2-m64.c	(revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+__ea char *p = str;
+
+int
+main (void)
+{
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute6.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute6.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute6.c	(revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+int
+main (void)
+{
+  __ea char *p = (__ea char *)"abc";
+
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute3-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute3-m64.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute3-m64.c	(revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+__ea char *p = (__ea char *)str;
+
+int
+main (void)
+{
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute4-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute4-m64.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute4-m64.c	(revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+
+int
+main (void)
+{
+  __ea char *p = str;
+
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute5-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute5-m64.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute5-m64.c	(revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+
+int
+main (void)
+{
+  __ea char *p = (__ea char *)str;
+
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute6-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute6-m64.c	(revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute6-m64.c	(revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+int
+main (void)
+{
+  __ea char *p = (__ea char *)"abc";
+
+  if (*p++ != 'a')
+    abort ();
+
+  if (*p++ != 'b')
+    abort ();
+
+  if (*p++ != 'c')
+    abort ();
+
+  if (*p++ != '\0')
+    abort ();
+
+  return 0;
+}
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 142610)
+++ gcc/expr.c	(working copy)
@@ -3430,12 +3430,14 @@ emit_move_insn (rtx x, rtx y)
   /* If X or Y are memory references, verify that their addresses are valid
      for the machine.  */
   if (MEM_P (x)
-      && (! memory_address_p (GET_MODE (x), XEXP (x, 0))
+      && (! memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
+					 MEM_ADDR_SPACE (x))
 	  && ! push_operand (x, GET_MODE (x))))
     x = validize_mem (x);
 
   if (MEM_P (y)
-      && ! memory_address_p (GET_MODE (y), XEXP (y, 0)))
+      && ! memory_address_addr_space_p (GET_MODE (y), XEXP (y, 0),
+					MEM_ADDR_SPACE (y)))
     y = validize_mem (y);
 
   gcc_assert (mode != BLKmode);
@@ -7340,7 +7342,9 @@ expand_expr_real_1 (tree exp, rtx target
 	  decl_rtl = use_anchored_address (decl_rtl);
 	  if (modifier != EXPAND_CONST_ADDRESS
 	      && modifier != EXPAND_SUM
-	      && !memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0)))
+	      && !memory_address_addr_space_p (DECL_MODE (exp),
+					       XEXP (decl_rtl, 0),
+					       MEM_ADDR_SPACE (decl_rtl)))
 	    temp = replace_equiv_address (decl_rtl,
 					  copy_rtx (XEXP (decl_rtl, 0)));
 	}
@@ -7462,7 +7466,8 @@ expand_expr_real_1 (tree exp, rtx target
       if (modifier != EXPAND_CONST_ADDRESS
 	  && modifier != EXPAND_INITIALIZER
 	  && modifier != EXPAND_SUM
-	  && ! memory_address_p (mode, XEXP (temp, 0)))
+	  && ! memory_address_addr_space_p (mode, XEXP (temp, 0),
+					    MEM_ADDR_SPACE (temp)))
 	return replace_equiv_address (temp,
 				      copy_rtx (XEXP (temp, 0)));
       return temp;
@@ -7522,6 +7527,8 @@ expand_expr_real_1 (tree exp, rtx target
     case INDIRECT_REF:
       {
 	tree exp1 = TREE_OPERAND (exp, 0);
+	addr_space_t as = 0;
+	enum machine_mode mem_Pmode = Pmode;
 
 	if (modifier != EXPAND_WRITE)
 	  {
@@ -7532,20 +7539,30 @@ expand_expr_real_1 (tree exp, rtx target
 	      return expand_expr (t, target, tmode, modifier);
 	  }
 
+	if (POINTER_TYPE_P (TREE_TYPE (exp1)))
+	  {
+	    as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
+	    if (as)
+	      mem_Pmode = targetm.addr_space.pointer_mode (as);
+	  }
+
 	op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
-	op0 = memory_address (mode, op0);
+	op0 = memory_address_addr_space (mode, op0, as);
 
 	if (code == ALIGN_INDIRECT_REF)
 	  {
 	    int align = TYPE_ALIGN_UNIT (type);
-	    op0 = gen_rtx_AND (Pmode, op0, GEN_INT (-align));
-	    op0 = memory_address (mode, op0);
+	    op0 = gen_rtx_AND (mem_Pmode, op0, GEN_INT (-align));
+	    op0 = memory_address_addr_space (mode, op0, as);
 	  }
 
 	temp = gen_rtx_MEM (mode, op0);
 
 	set_mem_attributes (temp, exp, 0);
 
+	if (as)
+	  set_mem_addr_space (temp, as);
+
 	/* Resolve the misalignment now, so that we don't have to remember
 	   to resolve it later.  Of course, this only works for reads.  */
 	/* ??? When we get around to supporting writes, we'll have to handle
Index: gcc/expr.h
===================================================================
--- gcc/expr.h	(revision 142610)
+++ gcc/expr.h	(working copy)
@@ -634,9 +634,14 @@ extern rtx force_label_rtx (tree);
    The constant terms are added and stored via a second arg.  */
 extern rtx eliminate_constant_term (rtx, rtx *);
 
-/* Convert arg to a valid memory address for specified machine mode,
-   by emitting insns to perform arithmetic if nec.  */
-extern rtx memory_address (enum machine_mode, rtx);
+/* Convert arg to a valid memory address for specified machine mode that points
+   to a specific named address space, by emitting insns to perform arithmetic
+   if necessary.  */
+extern rtx memory_address_addr_space (enum machine_mode, rtx, addr_space_t);
+
+/* Like memory_address_addr_space, except assume the memory address points to
+   the generic named address space.  */
+#define memory_address(MODE,RTX) memory_address_addr_space (MODE, RTX, 0)
 
 /* Return a memory reference like MEMREF, but with its mode changed
    to MODE and its address changed to ADDR.
@@ -644,6 +649,11 @@ extern rtx memory_address (enum machine_
    NULL for ADDR means don't change the address.)  */
 extern rtx change_address (rtx, enum machine_mode, rtx);
 
+/* Like change_address, except we change the address space of the memory
+   returned.  */
+extern rtx change_address_addr_space (rtx, enum machine_mode, rtx,
+				      addr_space_t);
+
 /* Return a memory reference like MEMREF, but with its mode changed
    to MODE and its address offset by OFFSET bytes.  */
 #define adjust_address(MEMREF, MODE, OFFSET) \
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	(revision 142610)
+++ gcc/recog.c	(working copy)
@@ -1253,6 +1253,17 @@ memory_address_p (enum machine_mode mode
   return 1;
 }
 
+/* Like memory_address_p, expect for a distinct named address space.  */
+
+int
+memory_address_addr_space_p (enum machine_mode mode, rtx addr, addr_space_t as)
+{
+  if (!as)
+    return memory_address_p (mode, addr);
+  else
+    return targetm.addr_space.memory_address_p (mode, addr, as);
+}
+
 /* Return 1 if OP is a valid memory reference with mode MODE,
    including a valid address.
 
Index: gcc/recog.h
===================================================================
--- gcc/recog.h	(revision 142610)
+++ gcc/recog.h	(working copy)
@@ -85,7 +85,10 @@ extern void cancel_changes (int);
 extern int constrain_operands (int);
 extern int constrain_operands_cached (int);
 extern int memory_address_p (enum machine_mode, rtx);
+extern int memory_address_addr_space_p (enum machine_mode, rtx, addr_space_t);
 extern int strict_memory_address_p (enum machine_mode, rtx);
+extern int strict_memory_address_addr_space_p (enum machine_mode, rtx,
+					       addr_space_t);
 extern int validate_replace_rtx (rtx, rtx, rtx);
 extern int validate_replace_rtx_part (rtx, rtx, rtx *, rtx);
 extern int validate_replace_rtx_part_nosimplify (rtx, rtx, rtx *, rtx);
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 142610)
+++ gcc/c-typeck.c	(working copy)
@@ -2868,7 +2868,11 @@ parser_build_binary_op (location_t locat
 static tree
 pointer_diff (tree op0, tree op1)
 {
-  tree restype = ptrdiff_type_node;
+  addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
+  addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
+  tree restype = ((as0 == 0 && as1 == 0)
+		  ? ptrdiff_type_node
+		  : targetm.addr_space.minus_type (as0, as1));
 
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
   tree con0, con1, lit0, lit1;
@@ -4390,8 +4394,8 @@ convert_for_assignment (tree type, tree 
 		     "space");
 	      break;
 	    case ic_init:
-	      error ("initialization of a pointer to an incompatible space"
-		     "address space");
+	      error ("initialization of a pointer to an incompatible address "
+		     "space");
 	      break;
 	    case ic_return:
 	      error ("return of a pointer to an incompatible address space");
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	(revision 142610)
+++ gcc/emit-rtl.c	(working copy)
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.  
 #include "langhooks.h"
 #include "tree-pass.h"
 #include "df.h"
+#include "target.h"
 
 /* Commonly used modes.  */
 
@@ -179,7 +180,7 @@ static GTY ((if_marked ("ggc_marked_p"),
 #define first_label_num (crtl->emit.x_first_label_num)
 
 static rtx make_call_insn_raw (rtx);
-static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
+static rtx change_address_1 (rtx, enum machine_mode, rtx, int, addr_space_t);
 static void set_used_decls (tree);
 static void mark_label_nuses (rtx);
 static hashval_t const_int_htab_hash (const void *);
@@ -1862,7 +1863,8 @@ set_mem_size (rtx mem, rtx size)
    attributes are not changed.  */
 
 static rtx
-change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
+change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate,
+		  addr_space_t as)
 {
   rtx new_rtx;
 
@@ -1872,15 +1874,15 @@ change_address_1 (rtx memref, enum machi
   if (addr == 0)
     addr = XEXP (memref, 0);
   if (mode == GET_MODE (memref) && addr == XEXP (memref, 0)
-      && (!validate || memory_address_p (mode, addr)))
+      && (!validate || memory_address_addr_space_p (mode, addr, as)))
     return memref;
 
   if (validate)
     {
       if (reload_in_progress || reload_completed)
-	gcc_assert (memory_address_p (mode, addr));
+	gcc_assert (memory_address_addr_space_p (mode, addr, as));
       else
-	addr = memory_address (mode, addr);
+	addr = memory_address_addr_space (mode, addr, as);
     }
 
   if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
@@ -1888,16 +1890,23 @@ change_address_1 (rtx memref, enum machi
 
   new_rtx = gen_rtx_MEM (mode, addr);
   MEM_COPY_ATTRIBUTES (new_rtx, memref);
+
+  if (as != MEM_ADDR_SPACE (memref))
+    set_mem_addr_space (new_rtx, as);
+
   return new_rtx;
 }
 
-/* Like change_address_1 with VALIDATE nonzero, but we are not saying in what
-   way we are changing MEMREF, so we only preserve the alias set.  */
+/* Like change_address_1 with VALIDATE nonzero, and the address space set, but
+   we are not saying in what way we are changing MEMREF, so we only preserve
+   the alias set.  */
 
 rtx
-change_address (rtx memref, enum machine_mode mode, rtx addr)
+change_address_addr_space (rtx memref, enum machine_mode mode, rtx addr,
+			   addr_space_t as)
 {
-  rtx new_rtx = change_address_1 (memref, mode, addr, 1), size;
+  rtx new_rtx = change_address_1 (memref, mode, addr, 1, as);
+  rtx size;
   enum machine_mode mmode = GET_MODE (new_rtx);
   unsigned int align;
 
@@ -1911,19 +1920,33 @@ change_address (rtx memref, enum machine
 	  || (MEM_EXPR (memref) == NULL
 	      && MEM_OFFSET (memref) == NULL
 	      && MEM_SIZE (memref) == size
+	      && MEM_ADDR_SPACE (memref) == as
 	      && MEM_ALIGN (memref) == align))
 	return new_rtx;
 
       new_rtx = gen_rtx_MEM (mmode, XEXP (memref, 0));
       MEM_COPY_ATTRIBUTES (new_rtx, memref);
+
+      if (as != MEM_ADDR_SPACE (new_rtx))
+	set_mem_addr_space (new_rtx, as);
     }
 
   MEM_ATTRS (new_rtx)
-    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, MEM_ADDR_SPACE (memref), mmode);
+    = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, as, mmode);
 
   return new_rtx;
 }
 
+/* Like change_address_addr_space, except we don't change the named address
+   space.  */
+
+rtx
+change_address (rtx memref, enum machine_mode mode, rtx addr)
+{
+  return change_address_addr_space (memref, mode, addr,
+				    MEM_ADDR_SPACE (memref));
+}
+
 /* Return a memory reference like MEMREF, but with its mode changed
    to MODE and its address offset by OFFSET bytes.  If VALIDATE is
    nonzero, the memory address is forced to be valid.
@@ -1939,10 +1962,14 @@ adjust_address_1 (rtx memref, enum machi
   rtx memoffset = MEM_OFFSET (memref);
   rtx size = 0;
   unsigned int memalign = MEM_ALIGN (memref);
+  addr_space_t as = MEM_ADDR_SPACE (memref);
+  enum machine_mode mem_Pmode = (!as
+				 ? Pmode
+				 : targetm.addr_space.pointer_mode (as));
 
   /* If there are no changes, just return the original memory reference.  */
   if (mode == GET_MODE (memref) && !offset
-      && (!validate || memory_address_p (mode, addr)))
+      && (!validate || memory_address_addr_space_p (mode, addr, as)))
     return memref;
 
   /* ??? Prefer to create garbage instead of creating shared rtl.
@@ -1958,13 +1985,13 @@ adjust_address_1 (rtx memref, enum machi
 	  && offset >= 0
 	  && (unsigned HOST_WIDE_INT) offset
 	      < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
-	addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0),
+	addr = gen_rtx_LO_SUM (mem_Pmode, XEXP (addr, 0),
 			       plus_constant (XEXP (addr, 1), offset));
       else
 	addr = plus_constant (addr, offset);
     }
 
-  new_rtx = change_address_1 (memref, mode, addr, validate);
+  new_rtx = change_address_1 (memref, mode, addr, validate, as);
 
   /* Compute the new values of the memory attributes due to this adjustment.
      We add the offsets and update the alignment.  */
@@ -1986,8 +2013,8 @@ adjust_address_1 (rtx memref, enum machi
     size = plus_constant (MEM_SIZE (memref), -offset);
 
   MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
-				   memoffset, size, memalign, MEM_ADDR_SPACE (memref),
-				   GET_MODE (new_rtx));
+				       memoffset, size, memalign, as,
+				       GET_MODE (new_rtx));
 
   /* At some point, we should validate that this offset is within the object,
      if all the appropriate values are known.  */
@@ -2003,7 +2030,8 @@ rtx
 adjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr,
 			     HOST_WIDE_INT offset, int validate)
 {
-  memref = change_address_1 (memref, VOIDmode, addr, validate);
+  memref = change_address_1 (memref, VOIDmode, addr, validate,
+			     MEM_ADDR_SPACE (memref));
   return adjust_address_1 (memref, mode, offset, validate, 0);
 }
 
@@ -2015,8 +2043,12 @@ rtx
 offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
 {
   rtx new_rtx, addr = XEXP (memref, 0);
+  addr_space_t as = MEM_ADDR_SPACE (memref);
+  enum machine_mode mem_Pmode = (!as
+				 ? Pmode
+				 : targetm.addr_space.pointer_mode (as));
 
-  new_rtx = simplify_gen_binary (PLUS, Pmode, addr, offset);
+  new_rtx = simplify_gen_binary (PLUS, mem_Pmode, addr, offset);
 
   /* At this point we don't know _why_ the address is invalid.  It
      could have secondary memory references, multiplies or anything.
@@ -2025,16 +2057,17 @@ offset_address (rtx memref, rtx offset, 
      being able to recognize the magic around pic_offset_table_rtx.
      This stuff is fragile, and is yet another example of why it is
      bad to expose PIC machinery too early.  */
-  if (! memory_address_p (GET_MODE (memref), new_rtx)
+  if (! memory_address_addr_space_p (GET_MODE (memref), new_rtx, as)
       && GET_CODE (addr) == PLUS
       && XEXP (addr, 0) == pic_offset_table_rtx)
     {
       addr = force_reg (GET_MODE (addr), addr);
-      new_rtx = simplify_gen_binary (PLUS, Pmode, addr, offset);
+      new_rtx = simplify_gen_binary (PLUS, mem_Pmode, addr, offset);
     }
 
   update_temp_slot_address (XEXP (memref, 0), new_rtx);
-  new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1);
+  new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1,
+			      MEM_ADDR_SPACE (memref));
 
   /* If there are no changes, just return the original memory reference.  */
   if (new_rtx == memref)
@@ -2045,7 +2078,7 @@ offset_address (rtx memref, rtx offset, 
   MEM_ATTRS (new_rtx)
     = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
 		     MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
-		     MEM_ADDR_SPACE (memref), GET_MODE (new_rtx));
+		     as, GET_MODE (new_rtx));
   return new_rtx;
 }
 
@@ -2060,7 +2093,8 @@ replace_equiv_address (rtx memref, rtx a
   /* change_address_1 copies the memory attribute structure without change
      and that's exactly what we want here.  */
   update_temp_slot_address (XEXP (memref, 0), addr);
-  return change_address_1 (memref, VOIDmode, addr, 1);
+  return change_address_1 (memref, VOIDmode, addr, 1,
+			   MEM_ADDR_SPACE (memref));
 }
 
 /* Likewise, but the reference is not required to be valid.  */
@@ -2068,7 +2102,7 @@ replace_equiv_address (rtx memref, rtx a
 rtx
 replace_equiv_address_nv (rtx memref, rtx addr)
 {
-  return change_address_1 (memref, VOIDmode, addr, 0);
+  return change_address_1 (memref, VOIDmode, addr, 0, MEM_ADDR_SPACE (memref));
 }
 
 /* Return a memory reference like MEMREF, but with its mode widened to
Index: gcc/explow.c
===================================================================
--- gcc/explow.c	(revision 142610)
+++ gcc/explow.c	(working copy)
@@ -306,7 +306,7 @@ break_out_memory_refs (rtx x)
       rtx op1 = break_out_memory_refs (XEXP (x, 1));
 
       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
-	x = simplify_gen_binary (GET_CODE (x), Pmode, op0, op1);
+	x = simplify_gen_binary (GET_CODE (x), GET_MODE (x), op0, op1);
     }
 
   return x;
@@ -405,22 +405,25 @@ convert_memory_address (enum machine_mod
 #endif /* defined(POINTERS_EXTEND_UNSIGNED) */
 }
 
-/* Return something equivalent to X but valid as a memory address
-   for something of mode MODE.  When X is not itself valid, this
-   works by copying X or subexpressions of it into registers.  */
+/* Return something equivalent to X but valid as a memory address for something
+   of mode MODE in the named address space AS.  When X is not itself valid,
+   this works by copying X or subexpressions of it into registers.  */
 
 rtx
-memory_address (enum machine_mode mode, rtx x)
+memory_address_addr_space (enum machine_mode mode, rtx x, addr_space_t as)
 {
   rtx oldx = x;
+  enum machine_mode mem_Pmode = ((!as)
+				 ? Pmode
+				 : targetm.addr_space.pointer_mode (as));
 
-  if (MEM_P (x) && !targetm.valid_pointer_mode (GET_MODE (x)))
-    x = convert_memory_address (Pmode, x);
+  if (MEM_P (x) && GET_MODE (x) != mem_Pmode)
+    x = convert_memory_address (mem_Pmode, x);
 
   /* By passing constant addresses through registers
      we get a chance to cse them.  */
   if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
-    x = force_reg (Pmode, x);
+    x = force_reg (mem_Pmode, x);
 
   /* We get better cse by rejecting indirect addressing at this stage.
      Let the combiner create indirect addresses where appropriate.
@@ -432,12 +435,12 @@ memory_address (enum machine_mode mode, 
 	x = break_out_memory_refs (x);
 
       /* At this point, any valid address is accepted.  */
-      if (memory_address_p (mode, x))
+      if (memory_address_addr_space_p (mode, x, as))
 	goto done;
 
       /* If it was valid before but breaking out memory refs invalidated it,
 	 use it the old way.  */
-      if (memory_address_p (mode, oldx))
+      if (memory_address_addr_space_p (mode, oldx, as))
 	{
 	  x = oldx;
 	  goto done;
@@ -447,7 +450,19 @@ memory_address (enum machine_mode mode, 
 	 in certain cases.  This is not necessary since the code
 	 below can handle all possible cases, but machine-dependent
 	 transformations can make better code.  */
-      LEGITIMIZE_ADDRESS (x, oldx, mode, done);
+      if (!as)
+	{
+	  LEGITIMIZE_ADDRESS (x, oldx, mode, done);
+	}
+      else
+	{
+	  rtx y = targetm.addr_space.legitimize_address (x, oldx, mode, as);
+	  if (y)
+	    {
+	      x = y;
+	      goto done;
+	    }
+	}
 
       /* PLUS and MULT can appear in special ways
 	 as the result of attempts to make an address usable for indexing.
@@ -463,12 +478,12 @@ memory_address (enum machine_mode mode, 
 	  rtx constant_term = const0_rtx;
 	  rtx y = eliminate_constant_term (x, &constant_term);
 	  if (constant_term == const0_rtx
-	      || ! memory_address_p (mode, y))
+	      || ! memory_address_addr_space_p (mode, y, as))
 	    x = force_operand (x, NULL_RTX);
 	  else
 	    {
 	      y = gen_rtx_PLUS (GET_MODE (x), copy_to_reg (y), constant_term);
-	      if (! memory_address_p (mode, y))
+	      if (! memory_address_addr_space_p (mode, y, as))
 		x = force_operand (x, NULL_RTX);
 	      else
 		x = y;
@@ -485,15 +500,12 @@ memory_address (enum machine_mode mode, 
 
       /* Last resort: copy the value to a register, since
 	 the register is a valid address.  */
-      else if (targetm.valid_pointer_mode (GET_MODE (x)))
-	x = force_reg (GET_MODE (x), x);
-      else
-	x = force_reg (Pmode, x);
+      x = force_reg (mem_Pmode, x);
     }
 
  done:
 
-  gcc_assert (memory_address_p (mode, x));
+  gcc_assert (memory_address_addr_space_p (mode, x, as));
   /* If we didn't change the address, we are done.  Otherwise, mark
      a reg as a pointer if we have REG or REG + CONST_INT.  */
   if (oldx == x)
@@ -518,14 +530,21 @@ memory_address (enum machine_mode mode, 
 rtx
 validize_mem (rtx ref)
 {
+  addr_space_t as;
+  enum machine_mode mode;
+  rtx mem;
+
   if (!MEM_P (ref))
     return ref;
   ref = use_anchored_address (ref);
-  if (memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
+  mode = GET_MODE (ref);
+  mem = XEXP (ref, 0);
+  as = MEM_ADDR_SPACE (ref);
+  if (memory_address_addr_space_p (mode, mem, as))
     return ref;
 
   /* Don't alter REF itself, since that is probably a stack slot.  */
-  return replace_equiv_address (ref, XEXP (ref, 0));
+  return replace_equiv_address (ref, mem);
 }
 
 /* If X is a memory reference to a member of an object block, try rewriting
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 142610)
+++ gcc/varasm.c	(working copy)
@@ -1430,10 +1430,16 @@ make_decl_rtl (tree decl)
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
   else
     {
-      addrmode = (TREE_TYPE (decl) == error_mark_node)
-	? Pmode
-	: targetm.addr_space.pointer_mode
-	(TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+      if (TREE_TYPE (decl) == error_mark_node)
+	addrmode = Pmode;
+      else
+	{
+	  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
+	  addrmode = ((as == 0)
+		      ? Pmode
+		      : targetm.addr_space.pointer_mode (as));
+	}
+
       x = gen_rtx_SYMBOL_REF (addrmode, name);
     }
   SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
@@ -6336,23 +6342,6 @@ default_binds_local_p_1 (const_tree exp,
   return local_p;
 }
 
-/* Determine whether or not a pointer mode is valid. Assume defaults
-   of ptr_mode or Pmode - can be overridden.  */
-bool
-default_valid_pointer_mode (enum machine_mode mode)
-{
-  return (mode == ptr_mode || mode == Pmode);
-}
-
-/* Return the pointer mode for a given ADDRSPACE, defaulting to
-   ptr_mode for the generic address space only.  */
-enum machine_mode
-default_addr_space_pointer_mode (addr_space_t addrspace)
-{
-  gcc_assert (addrspace == 0);
-  return ptr_mode;
-}
-
 /* Default function to output code that will globalize a label.  A
    target must define GLOBAL_ASM_OP or provide its own function to
    globalize a label.  */
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h	(revision 142610)
+++ gcc/target-def.h	(working copy)
@@ -461,10 +461,28 @@
 #define TARGET_ADDR_SPACE_POINTER_MODE default_addr_space_pointer_mode
 #endif
 
+#ifndef TARGET_ADDR_SPACE_MINUS_TYPE
+#define TARGET_ADDR_SPACE_MINUS_TYPE default_addr_space_minus_type
+#endif
+
 #ifndef TARGET_ADDR_SPACE_NAME
 #define TARGET_ADDR_SPACE_NAME default_addr_space_name
 #endif
 
+#ifndef TARGET_ADDR_SPACE_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_MEMORY_ADDRESS_P default_addr_space_memory_address_p
+#endif
+
+#ifndef TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P \
+  default_addr_space_strict_memory_address_p
+#endif
+
+#ifndef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
+#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS \
+  default_addr_space_legitimize_address
+#endif
+
 #ifndef TARGET_ADDR_SPACE_CAN_CONVERT_P
 #define TARGET_ADDR_SPACE_CAN_CONVERT_P default_addr_space_can_convert_p
 #endif
@@ -485,15 +503,24 @@
 #define TARGET_ADDR_SPACE_SECTION_NAME default_addr_space_section_name
 #endif
 
+#ifndef TARGET_ADDR_SPACE_STATIC_INIT_OK_P
+#define TARGET_ADDR_SPACE_STATIC_INIT_OK_P default_addr_space_static_init_ok_p
+#endif
+
 #define TARGET_ADDR_SPACE_HOOKS			\
   {						\
     TARGET_ADDR_SPACE_POINTER_MODE,		\
+    TARGET_ADDR_SPACE_MINUS_TYPE,		\
     TARGET_ADDR_SPACE_NAME,			\
+    TARGET_ADDR_SPACE_MEMORY_ADDRESS_P,		\
+    TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P,	\
+    TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS,	\
     TARGET_ADDR_SPACE_CAN_CONVERT_P,		\
     TARGET_ADDR_SPACE_NOP_CONVERT_P,		\
     TARGET_ADDR_SPACE_SUBSET_P,			\
     TARGET_ADDR_SPACE_CONVERT,			\
     TARGET_ADDR_SPACE_SECTION_NAME,		\
+    TARGET_ADDR_SPACE_STATIC_INIT_OK_P,		\
   }
 
 #ifndef TARGET_SCALAR_MODE_SUPPORTED_P
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 142610)
+++ gcc/Makefile.in	(working copy)
@@ -2574,7 +2574,7 @@ emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SY
    $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \
    $(GGC_H) $(EXPR_H) hard-reg-set.h $(BITMAP_H) $(TOPLEV_H) $(BASIC_BLOCK_H) \
    $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h tree-pass.h gt-emit-rtl.h \
-   $(REAL_H) $(DF_H)
+   $(REAL_H) $(DF_H) $(TARGET_H)
 real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(TOPLEV_H) $(TM_P_H) $(REAL_H) dfp.h
 dfp.o : dfp.c dfp.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)	$(TREE_H) \
Index: gcc/config/spu/spu-protos.h
===================================================================
--- gcc/config/spu/spu-protos.h	(revision 142610)
+++ gcc/config/spu/spu-protos.h	(working copy)
@@ -54,8 +54,9 @@ extern int arith_immediate_p (rtx op, en
 extern int spu_constant_address_p (rtx x);
 extern int spu_legitimate_constant_p (rtx x);
 extern int spu_legitimate_address (enum machine_mode mode, rtx x,
-				   int reg_ok_strict);
-extern rtx spu_legitimize_address (rtx x, rtx oldx, enum machine_mode mode);
+				   int reg_ok_strict, addr_space_t);
+extern rtx spu_legitimize_address (rtx x, rtx oldx, enum machine_mode mode,
+				   addr_space_t);
 extern int spu_initial_elimination_offset (int from, int to);
 extern rtx spu_function_value (const_tree type, const_tree func);
 extern rtx spu_function_arg (int cum, enum machine_mode mode, tree type,
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c	(revision 142610)
+++ gcc/config/spu/spu.c	(working copy)
@@ -203,17 +203,38 @@ spu_libgcc_shift_count_mode (void);
 
 /* Built in types.  */
 tree spu_builtin_types[SPU_BTI_MAX];
+
+/* Pointer mode for __ea references.  */
+#define EAmode (spu_ea_model != 32 ? DImode : SImode)
 
 /*  TARGET overrides.  */
 
-static enum machine_mode spu_ea_pointer_mode (addr_space_t);
+static enum machine_mode spu_addr_space_pointer_mode (addr_space_t);
 #undef TARGET_ADDR_SPACE_POINTER_MODE
-#define TARGET_ADDR_SPACE_POINTER_MODE spu_ea_pointer_mode
+#define TARGET_ADDR_SPACE_POINTER_MODE spu_addr_space_pointer_mode
+
+static tree spu_addr_space_minus_type (addr_space_t, addr_space_t);
+#undef TARGET_ADDR_SPACE_MINUS_TYPE
+#define TARGET_ADDR_SPACE_MINUS_TYPE spu_addr_space_minus_type
 
 static const char *spu_addr_space_name (addr_space_t);
 #undef TARGET_ADDR_SPACE_NAME
 #define TARGET_ADDR_SPACE_NAME spu_addr_space_name
 
+static bool spu_addr_space_memory_address_p (enum machine_mode, rtx,
+					     addr_space_t);
+#undef TARGET_ADDR_SPACE_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_MEMORY_ADDRESS_P spu_addr_space_memory_address_p
+
+static bool spu_addr_space_strict_memory_address_p (enum machine_mode, rtx,
+						    addr_space_t);
+#undef TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P \
+  spu_addr_space_strict_memory_address_p
+
+#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
+#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS spu_legitimize_address
+
 static bool spu_addr_space_can_convert_p (addr_space_t, addr_space_t);
 #undef TARGET_ADDR_SPACE_CAN_CONVERT_P
 #define TARGET_ADDR_SPACE_CAN_CONVERT_P spu_addr_space_can_convert_p
@@ -236,6 +257,10 @@ static tree spu_addr_space_section_name 
 #undef TARGET_ADDR_SPACE_SECTION_NAME
 #define TARGET_ADDR_SPACE_SECTION_NAME spu_addr_space_section_name
 
+static bool spu_addr_space_static_init_ok_p (tree, addr_space_t, addr_space_t);
+#undef TARGET_ADDR_SPACE_STATIC_INIT_OK_P
+#define TARGET_ADDR_SPACE_STATIC_INIT_OK_P spu_addr_space_static_init_ok_p
+
 static unsigned int spu_section_type_flags (tree, const char *, int);
 #undef TARGET_SECTION_TYPE_FLAGS
 #define TARGET_SECTION_TYPE_FLAGS spu_section_type_flags
@@ -3530,8 +3555,15 @@ spu_legitimate_constant_p (rtx x)
   preferable to allow any alignment and fix it up when splitting.) */
 int
 spu_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED,
-			rtx x, int reg_ok_strict)
+			rtx x, int reg_ok_strict,
+			addr_space_t as)
 {
+  if (as == ADDR_SPACE_EA)
+    return (REG_P (x) && (GET_MODE (x) == EAmode));
+
+  else if (as != ADDR_SPACE_GENERIC)
+    gcc_unreachable ();
+
   if (mode == TImode && GET_CODE (x) == AND
       && GET_CODE (XEXP (x, 1)) == CONST_INT
       && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) -16)
@@ -3613,9 +3645,13 @@ spu_legitimate_address (enum machine_mod
    register.  */
 rtx
 spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-			enum machine_mode mode)
+			enum machine_mode mode, addr_space_t as)
 {
   rtx op0, op1;
+				 
+  if (as != ADDR_SPACE_GENERIC)
+    return NULL_RTX;
+
   /* Make sure both operands are registers.  */
   if (GET_CODE (x) == PLUS)
     {
@@ -3636,7 +3672,7 @@ spu_legitimize_address (rtx x, rtx oldx 
       else if (GET_CODE (op1) != REG)
 	op1 = force_reg (Pmode, op1);
       x = gen_rtx_PLUS (Pmode, op0, op1);
-      if (spu_legitimate_address (mode, x, 0))
+      if (spu_legitimate_address (mode, x, 0, as))
 	return x;
     }
   return NULL_RTX;
@@ -4169,9 +4205,6 @@ store_with_one_insn_p (rtx mem)
   return 0;
 }
 
-/* Pointer mode for __ea references.  */
-#define EAmode (spu_ea_model != 32 ? DImode : SImode)
-
 static GTY(()) rtx cache_fetch;		  /* __cache_fetch function */
 static GTY(()) rtx cache_fetch_dirty;	  /* __cache_fetch_dirty function */
 static alias_set_type ea_alias_set = -1;  /* alias set for __ea memory */
@@ -4388,7 +4421,8 @@ expand_ea_mem (rtx mem, bool is_store)
   if (ea_alias_set == -1)
     ea_alias_set = new_alias_set ();
 
-  new_mem = change_address (mem, VOIDmode, data_addr);
+  new_mem = change_address_addr_space (mem, VOIDmode, data_addr,
+				       ADDR_SPACE_GENERIC);
 
   /* We can't just change the alias set directly to ea_alias_set, because the
      --enable-checking code may complain that the alias sets don't conflict */
@@ -4829,6 +4863,7 @@ spu_valid_move (rtx * ops)
      the direct_load[] and direct_store[] arrays.  We always want to
      consider those loads and stores valid.  init_expr_once is called in
      the context of a dummy function which does not have a decl. */
+  gcc_assert (cfun);
   if (cfun->decl == 0)
     return 1;
 
@@ -6459,26 +6494,12 @@ spu_vector_alignment_reachable (const_tr
   return true;
 }
 
-/* Return the appropriate mode for a named address pointer.  */
-static enum machine_mode
-spu_ea_pointer_mode (addr_space_t addrspace)
-{
-  switch (addrspace)
-    {
-    case ADDR_SPACE_GENERIC:
-      return ptr_mode;
-    case ADDR_SPACE_EA:
-      return (spu_ea_model == 64 ? DImode : ptr_mode);
-    default:
-      gcc_unreachable ();
-    }
-}
-
 /* Return valid pointer modes.  */
 static bool
 spu_valid_pointer_mode (enum machine_mode mode)
 {
-  return (mode == ptr_mode || mode == Pmode || mode == spu_ea_pointer_mode (1));
+  return (mode == ptr_mode || mode == Pmode ||
+	  (spu_ea_model != 32 && mode == DImode));
 }
 
 /* Adjust section flags for the __ea section.  */
@@ -6603,6 +6624,38 @@ spu_libgcc_shift_count_mode (void)
   return SImode;
 }
 
+/* Return the appropriate mode for a named address pointer.  */
+static enum machine_mode
+spu_addr_space_pointer_mode (addr_space_t addrspace)
+{
+  switch (addrspace)
+    {
+    case ADDR_SPACE_GENERIC:
+      return ptr_mode;
+    case ADDR_SPACE_EA:
+      return (EAmode);
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Return the appropriate type for subtracting two pointers.  */
+static tree
+spu_addr_space_minus_type (addr_space_t as1, addr_space_t as2)
+{
+  gcc_assert (as1 == ADDR_SPACE_GENERIC || as1 == ADDR_SPACE_EA);
+  gcc_assert (as2 == ADDR_SPACE_GENERIC || as2 == ADDR_SPACE_EA);
+
+  if (as1 == ADDR_SPACE_GENERIC && as2 == ADDR_SPACE_GENERIC)
+    return ptrdiff_type_node;
+
+  else if (spu_ea_model == 32)
+    return ptrdiff_type_node;
+
+  else
+    return unsigned_intDI_type_node;
+}
+
 /* Map an address space number into a name.  */
 static const char *
 spu_addr_space_name (addr_space_t addrspace)
@@ -6613,6 +6666,28 @@ spu_addr_space_name (addr_space_t addrsp
   gcc_unreachable ();
 }
 
+/* Return if an address is valid for a given mode that points to a given named
+   address space.  */
+
+static bool
+spu_addr_space_memory_address_p (enum machine_mode mode, rtx x,
+				 addr_space_t as)
+{
+  gcc_assert (as == ADDR_SPACE_GENERIC || as == ADDR_SPACE_EA);
+  return spu_legitimate_address (mode, x, 0, as);
+}
+
+/* Return if an address is valid for a given mode that points to a given named
+   address space after register allocation has been done.  */
+
+static bool
+spu_addr_space_strict_memory_address_p (enum machine_mode mode, rtx x,
+					addr_space_t as)
+{
+  gcc_assert (as == ADDR_SPACE_GENERIC || as == ADDR_SPACE_EA);
+  return spu_legitimate_address (mode, x, 1, as);
+}
+
 /* Determine if you can convert one address to another.  */
 
 static bool
@@ -6720,6 +6795,27 @@ spu_addr_space_section_name (addr_space_
   return spu_ea_name;
 }
 
+static bool
+spu_addr_space_static_init_ok_p (tree ARG_UNUSED (value),
+				 addr_space_t asl,
+				 addr_space_t asr)
+{
+  gcc_assert (asl == ADDR_SPACE_GENERIC || asl == ADDR_SPACE_EA);
+  gcc_assert (asr == ADDR_SPACE_GENERIC || asr == ADDR_SPACE_EA);
+
+#if 0
+  fprintf (stderr, "\nInitialize asl = %s, asr = %s:\n",
+	   (asl) ? "generic" : "__ea",
+	   (asr) ? "generic" : "__ea");
+
+  debug_tree (value);
+#endif
+
+  if (asl == ADDR_SPACE_GENERIC && asr == ADDR_SPACE_GENERIC)
+    return true;
+
+  return false;
+}
 
 /* An early place to adjust some flags after GCC has finished processing
  * them. */
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h	(revision 142610)
+++ gcc/config/spu/spu.h	(working copy)
@@ -423,12 +423,14 @@ targetm.resolve_overloaded_builtin = spu
 #endif
 
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)			\
-    { if (spu_legitimate_address (MODE, X, REG_OK_STRICT_FLAG))	\
+    { if (spu_legitimate_address (MODE, X, REG_OK_STRICT_FLAG,	\
+				  ADDR_SPACE_GENERIC))		\
 	goto ADDR;						\
     }
 
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
-  {  rtx result = spu_legitimize_address (X, OLDX, MODE);	\
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)			\
+  {  rtx result = spu_legitimize_address (X, OLDX, MODE,	\
+					  ADDR_SPACE_GENERIC);	\
      if (result != NULL_RTX)					\
        {							\
 	 (X) = result;						\

-- 
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com


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