diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 53a29c4326c56519cbf00e05c83ffbcb9b282098..967ff8450003bfa29c26ab36e27413e0eba8fa4c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2005-10-19  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+	* config/s390/s390-protos.h (s390_hard_regno_rename_ok): Add prototype.
+	* config/s390/s390.c (s390_hard_regno_rename_ok): New function.
+	(s390_can_eliminate): Handle BASE_REGNUM elimination.
+	(s390_initial_elimination_offset): Likewise.
+	(s390_conditional_register_usage): BASE_REGNUM is no longer a fixed
+	register on TARGET_ZARCH targets.
+	* config/s390/s390.h (HARD_REGNO_RENAME_OK): Define
+	(INITIAL_FRAME_POINTER_OFFSET): Remove.
+	(REG_ALLOC_ORDER): Move BASE_REGNUM lower.
+	(ELIMINABLE_REGS): Add BASE_REGNUM elimination rule.
+
 2005-10-19  Andreas Krebbel  <krebbel1@de.ibm.com>
 
 	* config/s390/s390.md: Comment describing output modifiers updated.
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 7bafcf3f404cb621ee4a9ed6f6bbcb571c0529d0..b18e1d13f07ba143154291db87ceb800e6f4cebd 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -30,6 +30,7 @@ extern void s390_emit_epilogue (bool);
 extern void s390_function_profiler (FILE *, int);
 extern void s390_conditional_register_usage (void);
 extern void s390_set_has_landing_pad_p (bool);
+extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
 
 #ifdef RTX_CODE
 extern int s390_extra_constraint_str (rtx, int, const char *);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 94584260b36149b054ec4a7b5d17eedeb0462002..445f4e1a10dec394ca55ea49bd4f82e34f40a643 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6243,11 +6243,46 @@ s390_update_frame_layout (void)
     regs_ever_live[REGNO (cfun->machine->base_reg)] = 1;
 }
 
+/* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
+
+bool
+s390_hard_regno_rename_ok (unsigned int old_reg, unsigned int new_reg)
+{
+   /* Once we've decided upon a register to use as base register, it must
+      no longer be used for any other purpose.  */
+  if (cfun->machine->base_reg)
+    if (REGNO (cfun->machine->base_reg) == old_reg
+	|| REGNO (cfun->machine->base_reg) == new_reg)
+      return false;
+
+  return true;
+}
+
 /* Return true if register FROM can be eliminated via register TO.  */
 
 bool
 s390_can_eliminate (int from, int to)
 {
+  /* On zSeries machines, we have not marked the base register as fixed.
+     Instead, we have an elimination rule BASE_REGNUM -> BASE_REGNUM.
+     If a function requires the base register, we say here that this
+     elimination cannot be performed.  This will cause reload to free
+     up the base register (as if it were fixed).  On the other hand,
+     if the current function does *not* require the base register, we
+     say here the elimination succeeds, which in turn allows reload
+     to allocate the base register for any other purpose.  */
+  if (from == BASE_REGNUM && to == BASE_REGNUM)
+    {
+      if (TARGET_CPU_ZARCH)
+	{
+	  s390_init_frame_layout ();
+	  return cfun->machine->base_reg == NULL_RTX;
+	}
+
+      return false;
+    }
+
+  /* Everything else must point into the stack frame.  */
   gcc_assert (to == STACK_POINTER_REGNUM
 	      || to == HARD_FRAME_POINTER_REGNUM);
 
@@ -6298,6 +6333,10 @@ s390_initial_elimination_offset (int from, int to)
       offset += index * UNITS_PER_WORD;
       break;
 
+    case BASE_REGNUM:
+      offset = 0;
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -8263,6 +8302,8 @@ s390_conditional_register_usage (void)
     }
   if (TARGET_CPU_ZARCH)
     {
+      fixed_regs[BASE_REGNUM] = 0;
+      call_used_regs[BASE_REGNUM] = 0;
       fixed_regs[RETURN_REGNUM] = 0;
       call_used_regs[RETURN_REGNUM] = 0;
     }
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index af740baa8740c1fabf143750ec9400497b3ab496..d8d1d1990d0761b49a24cffe026325f8ae766546 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -318,7 +318,7 @@ if (INTEGRAL_MODE_P (MODE) &&	        	    	\
 
 /* Preferred register allocation order.  */
 #define REG_ALLOC_ORDER                                         \
-{  1, 2, 3, 4, 5, 0, 13, 12, 11, 10, 9, 8, 7, 6, 14,            \
+{  1, 2, 3, 4, 5, 0, 12, 11, 10, 9, 8, 7, 6, 14, 13,            \
    16, 17, 18, 19, 20, 21, 22, 23,                              \
    24, 25, 26, 27, 28, 29, 30, 31,                              \
    15, 32, 33, 34, 35, 36, 37 }
@@ -365,6 +365,9 @@ if (INTEGRAL_MODE_P (MODE) &&	        	    	\
       && (HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1))) :  \
    0)
 
+#define HARD_REGNO_RENAME_OK(FROM, TO) \
+  s390_hard_regno_rename_ok (FROM, TO)
+
 #define MODES_TIEABLE_P(MODE1, MODE2)		\
    (((MODE1) == SFmode || (MODE1) == DFmode)	\
    == ((MODE2) == SFmode || (MODE2) == DFmode))
@@ -605,15 +608,14 @@ extern int current_function_outgoing_args_size;
 
 #define FRAME_POINTER_REQUIRED 0
 
-#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = 0
-
-#define ELIMINABLE_REGS				             \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},	             \
- { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},         \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},	             \
- { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},           \
- { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},     \
- { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+#define ELIMINABLE_REGS						\
+{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM },		\
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM },		\
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },			\
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM },		\
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM },	\
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM },	\
+ { BASE_REGNUM, BASE_REGNUM }}
 
 #define CAN_ELIMINATE(FROM, TO) \
   s390_can_eliminate ((FROM), (TO))