Patchwork [committed] Fix PR target/45250

login
register
mail settings
Submitter John David Anglin
Date Sept. 8, 2010, 11:36 p.m.
Message ID <20100908233648.GA23485@hiauly1.hia.nrc.ca>
Download mbox | patch
Permalink /patch/64244/
State New
Headers show

Comments

John David Anglin - Sept. 8, 2010, 11:36 p.m.
The attached change fixes PR target/45250.  Jakub found the following
in analyzing the failure:

> The problem is that the PA backend has quite lame setup, where
> FRAME_POINTER_REGNUM is the same as HARD_FRAME_POINTER_REGNUM and
> ARG_POINTER_REGNUM, thus the replacements var-tracking is doing in order to
> decrease size of loclists and use DW_OP_fbreg where possible, aren't reliable,
> as the testcase shows, because the same hard register can be used for arbitrary
> other data.  The following patch fixes it by not doing the replacements on PA
> and similar targets at all when doing VALUE based var-tracking.  Ideally PA
> backend would be fixed up to use different (fixed) hard regno, made up and
> always eliminated, for FRAME_POINTER_REGNUM.

The change implements a soft frame pointer.

Tested on hppa64-hp-hpux11.11, hppa2.0w-hp-hpux11.11 and hppa-unknown-linux-gnu.
Committed to trunk.

Dave

Patch

Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md	(revision 163868)
+++ config/pa/pa.md	(working copy)
@@ -7073,10 +7073,10 @@ 
   /* Restore the frame pointer.  The virtual_stack_vars_rtx is saved
      instead of the hard_frame_pointer_rtx in the save area.  As a
      result, an extra instruction is needed to adjust for the offset
-     of the virtual stack variables and the frame pointer.  */
+     of the virtual stack variables and the hard frame pointer.  */
   if (GET_CODE (fp) != REG)
     fp = force_reg (Pmode, fp);
-  emit_move_insn (virtual_stack_vars_rtx, fp);
+  emit_move_insn (hard_frame_pointer_rtx, plus_constant (fp, -8));
 
   emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
 
@@ -8517,15 +8517,10 @@ 
 
   /* Restore the frame pointer.  The virtual_stack_vars_rtx is saved
      instead of the hard_frame_pointer_rtx in the save area.  We need
-     to adjust for the offset between these two values when we have
-     a nonlocal_goto pattern.  When we don't have a nonlocal_goto
-     pattern, the receiver performs the adjustment.  */
-#ifdef HAVE_nonlocal_goto
-  if (HAVE_nonlocal_goto)
-    emit_move_insn (virtual_stack_vars_rtx, force_reg (Pmode, fp));
-  else
-#endif
-    emit_move_insn (hard_frame_pointer_rtx, fp);
+     to adjust for the offset between these two values.  */
+  if (GET_CODE (fp) != REG)
+    fp = force_reg (Pmode, fp);
+  emit_move_insn (hard_frame_pointer_rtx, plus_constant (fp, -8));
 
   /* This bit is the same as expand_builtin_longjmp.  */
   emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
@@ -9528,7 +9523,7 @@ 
     {
       addr = gen_rtx_PLUS (word_mode, stack_pointer_rtx,
 			   GEN_INT (TARGET_64BIT ? -8 : -4));
-      emit_move_insn (gen_rtx_MEM (word_mode, addr), frame_pointer_rtx);
+      emit_move_insn (gen_rtx_MEM (word_mode, addr), hard_frame_pointer_rtx);
     }
   if (!TARGET_64BIT && flag_pic)
     {
Index: config/pa/pa-protos.h
===================================================================
--- config/pa/pa-protos.h	(revision 163868)
+++ config/pa/pa-protos.h	(working copy)
@@ -171,6 +171,7 @@ 
 extern bool pa_cannot_change_mode_class (enum machine_mode, enum machine_mode,
 					 enum reg_class);
 extern bool pa_modes_tieable_p (enum machine_mode, enum machine_mode);
+extern HOST_WIDE_INT pa_initial_elimination_offset (int, int);
 
 extern const int magic_milli[];
 extern int shadd_constant_p (int);
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c	(revision 163868)
+++ config/pa/pa.c	(working copy)
@@ -174,6 +174,8 @@ 
 static rtx pa_trampoline_adjust_address (rtx);
 static rtx pa_delegitimize_address (rtx);
 static bool pa_print_operand_punct_valid_p (unsigned char);
+static rtx pa_internal_arg_pointer (void);
+static bool pa_can_eliminate (const int, const int);
 
 /* The following extra sections are only used for SOM.  */
 static GTY(()) section *som_readonly_data_section;
@@ -360,6 +362,10 @@ 
 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS pa_trampoline_adjust_address
 #undef TARGET_DELEGITIMIZE_ADDRESS
 #define TARGET_DELEGITIMIZE_ADDRESS pa_delegitimize_address
+#undef TARGET_INTERNAL_ARG_POINTER
+#define TARGET_INTERNAL_ARG_POINTER pa_internal_arg_pointer
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE pa_can_eliminate
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -3762,11 +3768,11 @@ 
 	     pointer by actual_fsize bytes.  Two versions, first
 	     handles small (<8k) frames.  The second handles large (>=8k)
 	     frames.  */
-	  insn = emit_move_insn (tmpreg, frame_pointer_rtx);
+	  insn = emit_move_insn (tmpreg, hard_frame_pointer_rtx);
 	  if (DO_FRAME_NOTES)
 	    RTX_FRAME_RELATED_P (insn) = 1;
 
-	  insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+	  insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
 	  if (DO_FRAME_NOTES)
 	    RTX_FRAME_RELATED_P (insn) = 1;
 
@@ -3810,7 +3816,7 @@ 
 				       GEN_INT (TARGET_64BIT ? -8 : -4));
 
 	      emit_move_insn (gen_rtx_MEM (word_mode, addr),
-			      frame_pointer_rtx);
+			      hard_frame_pointer_rtx);
 	    }
 	  else
 	    emit_insn (gen_blockage ());
@@ -3853,7 +3859,7 @@ 
 	      if (regno == INVALID_REGNUM)
 		break;
 
-	      store_reg (regno, offset, FRAME_POINTER_REGNUM);
+	      store_reg (regno, offset, HARD_FRAME_POINTER_REGNUM);
 	      offset += UNITS_PER_WORD;
 	    }
 	}
@@ -3861,7 +3867,7 @@ 
       for (i = 18; i >= 4; i--)
 	if (df_regs_ever_live_p (i) && ! call_used_regs[i])
 	  {
-	    store_reg (i, offset, FRAME_POINTER_REGNUM);
+	    store_reg (i, offset, HARD_FRAME_POINTER_REGNUM);
 	    offset += UNITS_PER_WORD;
 	    gr_saved++;
 	  }
@@ -3950,8 +3956,8 @@ 
 	 save area.  */
       if (frame_pointer_needed)
 	{
-	  set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset, 0);
-	  base = frame_pointer_rtx;
+	  set_reg_plus_d (1, HARD_FRAME_POINTER_REGNUM, offset, 0);
+	  base = hard_frame_pointer_rtx;
 	}
       else
 	{
@@ -4149,7 +4155,7 @@ 
       ret_off = TARGET_64BIT ? -16 : -20;
       if (frame_pointer_needed)
 	{
-	  load_reg (2, ret_off, FRAME_POINTER_REGNUM);
+	  load_reg (2, ret_off, HARD_FRAME_POINTER_REGNUM);
 	  ret_off = 0;
 	}
       else
@@ -4180,7 +4186,7 @@ 
 	      if (regno == INVALID_REGNUM)
 		break;
 
-	      load_reg (regno, offset, FRAME_POINTER_REGNUM);
+	      load_reg (regno, offset, HARD_FRAME_POINTER_REGNUM);
 	      offset += UNITS_PER_WORD;
 	    }
 	}
@@ -4188,7 +4194,7 @@ 
       for (i = 18; i >= 4; i--)
 	if (df_regs_ever_live_p (i) && ! call_used_regs[i])
 	  {
-	    load_reg (i, offset, FRAME_POINTER_REGNUM);
+	    load_reg (i, offset, HARD_FRAME_POINTER_REGNUM);
 	    offset += UNITS_PER_WORD;
 	  }
     }
@@ -4247,7 +4253,7 @@ 
     {
       /* Adjust the register to index off of.  */
       if (frame_pointer_needed)
-	set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset, 0);
+	set_reg_plus_d (1, HARD_FRAME_POINTER_REGNUM, offset, 0);
       else
 	set_reg_plus_d (1, STACK_POINTER_REGNUM, offset, 0);
 
@@ -4275,8 +4281,9 @@ 
     {
       rtx delta = GEN_INT (-64);
 
-      set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64, 0);
-      emit_insn (gen_pre_load (frame_pointer_rtx, stack_pointer_rtx, delta));
+      set_reg_plus_d (STACK_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM, 64, 0);
+      emit_insn (gen_pre_load (hard_frame_pointer_rtx,
+			       stack_pointer_rtx, delta));
     }
   /* If we were deferring a callee register restore, do it now.  */
   else if (merge_sp_adjust_with_load)
@@ -5920,7 +5927,7 @@ 
 {
   rtx tmp;
 
-  tmp = gen_rtx_PLUS (word_mode, frame_pointer_rtx,
+  tmp = gen_rtx_PLUS (word_mode, hard_frame_pointer_rtx,
 		      TARGET_64BIT ? GEN_INT (-16) : GEN_INT (-20));
   tmp = gen_rtx_MEM (word_mode, tmp);
   tmp->volatil = 1;
@@ -10100,4 +10107,48 @@ 
   return x;
 }
 
+static rtx
+pa_internal_arg_pointer (void)
+{
+  /* The argument pointer and the hard frame pointer are the same in
+     the 32-bit runtime, so we don't need a copy.  */
+  if (TARGET_64BIT)
+    return copy_to_reg (virtual_incoming_args_rtx);
+  else
+    return virtual_incoming_args_rtx;
+}
+
+/* Given FROM and TO register numbers, say whether this elimination is allowed.
+   Frame pointer elimination is automatically handled.  */
+
+static bool
+pa_can_eliminate (const int from, const int to)
+{
+  /* The argument cannot be eliminated in the 64-bit runtime.  */
+  if (TARGET_64BIT && from == ARG_POINTER_REGNUM)
+    return false;
+
+  return (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+          ? ! frame_pointer_needed
+          : true);
+}
+
+/* Define the offset between two registers, FROM to be eliminated and its
+   replacement TO, at the start of a routine.  */
+HOST_WIDE_INT
+pa_initial_elimination_offset (int from, int to)
+{
+  HOST_WIDE_INT offset;
+
+  if ((from == HARD_FRAME_POINTER_REGNUM || from == FRAME_POINTER_REGNUM)
+      && to == STACK_POINTER_REGNUM)
+    offset = -compute_frame_size (get_frame_size (), 0);
+  else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+    offset = 0;
+  else
+    gcc_unreachable ();
+
+  return offset;
+}
+
 #include "gt-pa.h"
Index: config/pa/pa.h
===================================================================
--- config/pa/pa.h	(revision 163868)
+++ config/pa/pa.h	(working copy)
@@ -344,8 +344,11 @@ 
 /* Register to use for pushing function arguments.  */
 #define STACK_POINTER_REGNUM 30
 
+/* Fixed register for local variable access.  Always eliminated.  */
+#define FRAME_POINTER_REGNUM (TARGET_64BIT ? 61 : 89)
+
 /* Base register for access to local variables of the function.  */
-#define FRAME_POINTER_REGNUM 3
+#define HARD_FRAME_POINTER_REGNUM 3
 
 /* Don't allow hard registers to be renamed into r2 unless r2
    is already live or already being saved (due to eh).  */
@@ -353,15 +356,6 @@ 
 #define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
   ((NEW_REG) != 2 || df_regs_ever_live_p (2) || crtl->calls_eh_return)
 
-/* C statement to store the difference between the frame pointer
-   and the stack pointer values immediately after the function prologue.
-
-   Note, we always pretend that this is a leaf function because if
-   it's not, there's no point in trying to eliminate the
-   frame pointer.  If it is a leaf function, we guessed right!  */
-#define INITIAL_FRAME_POINTER_OFFSET(VAR) \
-  do {(VAR) = - compute_frame_size (get_frame_size (), 0);} while (0)
-
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM (TARGET_64BIT ? 29 : 3)
 
@@ -385,6 +379,31 @@ 
    is passed to a function.  */
 #define PA_STRUCT_VALUE_REGNUM 28
 
+/* Definitions for register eliminations.
+
+   We have two registers that can be eliminated.  First, the frame pointer
+   register can often be eliminated in favor of the stack pointer register.
+   Secondly, the argument pointer register can always be eliminated in the
+   32-bit runtimes.  */
+
+/* This is an array of structures.  Each structure initializes one pair
+   of eliminable registers.  The "from" register number is given first,
+   followed by "to".  Eliminations of the same "from" register are listed
+   in order of preference.
+
+   The argument pointer cannot be eliminated in the 64-bit runtime.  It
+   is the same register as the hard frame pointer in the 32-bit runtime.
+   So, it does not need to be listed.  */
+#define ELIMINABLE_REGS                                 \
+{{ HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},    \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},         \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM} }
+
+/* Define the offset between two registers, one to be eliminated,
+   and the other its replacement, at the start of a routine.  */
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+  ((OFFSET) = pa_initial_elimination_offset(FROM, TO))
+
 /* Describe how we implement __builtin_eh_return.  */
 #define EH_RETURN_DATA_REGNO(N)	\
   ((N) < 3 ? (N) + 20 : (N) == 3 ? 31 : INVALID_REGNUM)
@@ -394,6 +413,10 @@ 
 /* Offset from the frame pointer register value to the top of stack.  */
 #define FRAME_POINTER_CFA_OFFSET(FNDECL) 0
 
+/* The maximum number of hard registers that can be saved in the call
+   frame.  The soft frame pointer is not included.  */
+#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER - 1)
+
 /* A C expression whose value is RTL representing the location of the
    incoming return address at the beginning of any function, before the
    prologue.  You only need to define this macro if you want to support
@@ -408,7 +431,7 @@ 
 
    Column 0 is not used but unfortunately its register size is set to
    4 bytes (sizeof CCmode) so it can't be used on 64-bit targets.  */
-#define DWARF_ALT_FRAME_RETURN_COLUMN FIRST_PSEUDO_REGISTER
+#define DWARF_ALT_FRAME_RETURN_COLUMN (FIRST_PSEUDO_REGISTER - 1)
 
 /* This macro chooses the encoding of pointers embedded in the exception
    handling sections.  If at all possible, this should be defined such
@@ -777,12 +800,14 @@ 
 
 #define REGNO_OK_FOR_INDEX_P(X) \
   ((X) && ((X) < 32							\
-   || (X >= FIRST_PSEUDO_REGISTER					\
+   || ((X) == FRAME_POINTER_REGNUM)					\
+   || ((X) >= FIRST_PSEUDO_REGISTER					\
        && reg_renumber							\
        && (unsigned) reg_renumber[X] < 32)))
 #define REGNO_OK_FOR_BASE_P(X) \
   ((X) && ((X) < 32							\
-   || (X >= FIRST_PSEUDO_REGISTER					\
+   || ((X) == FRAME_POINTER_REGNUM)					\
+   || ((X) >= FIRST_PSEUDO_REGISTER					\
        && reg_renumber							\
        && (unsigned) reg_renumber[X] < 32)))
 #define REGNO_OK_FOR_FP_P(X) \
@@ -931,12 +956,16 @@ 
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_INDEX_P(X) \
-  (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+  (REGNO (X) && (REGNO (X) < 32 				\
+   || REGNO (X) == FRAME_POINTER_REGNUM				\
+   || REGNO (X) >= FIRST_PSEUDO_REGISTER))
 
 /* Nonzero if X is a hard reg that can be used as a base reg
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X) \
-  (REGNO (X) && (REGNO (X) < 32 || REGNO (X) >= FIRST_PSEUDO_REGISTER))
+  (REGNO (X) && (REGNO (X) < 32 				\
+   || REGNO (X) == FRAME_POINTER_REGNUM				\
+   || REGNO (X) >= FIRST_PSEUDO_REGISTER))
 
 #else
 
Index: config/pa/pa32-regs.h
===================================================================
--- config/pa/pa32-regs.h	(revision 163868)
+++ config/pa/pa32-regs.h	(working copy)
@@ -1,5 +1,5 @@ 
 /* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008 Free Software Foundation, Inc.
+   2008, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -43,8 +43,8 @@ 
    has different fp units: define separate register sets for the 1.0
    and 1.1 fp units.  */
 
-#define FIRST_PSEUDO_REGISTER 89  /* 32 general regs + 56 fp regs +
-				     + 1 shift reg */
+#define FIRST_PSEUDO_REGISTER 90  /* 32 general regs + 56 fp regs +
+				     + 1 shift reg + frame pointer */
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -96,7 +96,8 @@ 
   0, 0, 0, 0, 0, 0, 0, 0, \
   0, 0, 0, 0, 0, 0, 0, 0, \
   0, 0, 0, 0, 0, 0, 0, 0, \
-  0}
+  /* shift register and soft frame pointer */ \
+  0, 1}
 
 /* 1 for registers not available across function calls.
    These must include the FIXED_REGISTERS and also any
@@ -117,7 +118,8 @@ 
   0, 0, 0, 0, 1, 1, 1, 1, \
   1, 1, 1, 1, 1, 1, 1, 1, \
   1, 1, 1, 1, 1, 1, 1, 1, \
-  1}
+  /* shift register and soft frame pointer */ \
+  1, 1}
 
 #define CONDITIONAL_REGISTER_USAGE \
 {						\
@@ -172,7 +174,7 @@ 
    3,  4,  5,  6,  7,  8,  9, 10, 	\
   11, 12, 13, 14, 15, 16, 17, 18,	\
   /* special registers.  */		\
-   1, 30,  0, 88}
+   1, 30,  0, 88, 89}
 
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
@@ -304,12 +306,12 @@ 
 #define REG_CLASS_CONTENTS	\
  {{0x00000000, 0x00000000, 0x00000000},	/* NO_REGS */			\
   {0x00000002, 0x00000000, 0x00000000},	/* R1_REGS */			\
-  {0xfffffffe, 0x00000000, 0x00000000},	/* GENERAL_REGS */		\
+  {0xfffffffe, 0x00000000, 0x02000000},	/* GENERAL_REGS */		\
   {0x00000000, 0xff000000, 0x00ffffff},	/* FPUPPER_REGS */		\
   {0x00000000, 0xffffffff, 0x00ffffff},	/* FP_REGS */			\
-  {0xfffffffe, 0xffffffff, 0x00ffffff},	/* GENERAL_OR_FP_REGS */	\
+  {0xfffffffe, 0xffffffff, 0x02ffffff},	/* GENERAL_OR_FP_REGS */	\
   {0x00000000, 0x00000000, 0x01000000},	/* SHIFT_REGS */		\
-  {0xfffffffe, 0xffffffff, 0x01ffffff}}	/* ALL_REGS */
+  {0xfffffffe, 0xffffffff, 0x03ffffff}}	/* ALL_REGS */
 
 /* The following macro defines cover classes for Integrated Register
    Allocator.  Cover classes is a set of non-intersected register
@@ -336,7 +338,7 @@ 
 #define REGNO_REG_CLASS(REGNO)						\
   ((REGNO) == 0 ? NO_REGS 						\
    : (REGNO) == 1 ? R1_REGS						\
-   : (REGNO) < 32 ? GENERAL_REGS					\
+   : (REGNO) < 32 || (REGNO) == 89 ? GENERAL_REGS			\
    : (REGNO) < 56 ? FP_REGS						\
    : (REGNO) < 88 ? FPUPPER_REGS					\
    : SHIFT_REGS)
@@ -370,7 +372,7 @@ 
  "%fr20", "%fr20R", "%fr21", "%fr21R", "%fr22", "%fr22R", "%fr23", "%fr23R", \
  "%fr24", "%fr24R", "%fr25", "%fr25R", "%fr26", "%fr26R", "%fr27", "%fr27R", \
  "%fr28", "%fr28R", "%fr29", "%fr29R", "%fr30", "%fr30R", "%fr31", "%fr31R", \
- "SAR"}
+ "SAR",   "sfp"}
 
 #define ADDITIONAL_REGISTER_NAMES \
 {{"%fr4L",32}, {"%fr5L",34}, {"%fr6L",36}, {"%fr7L",38},		\
Index: config/pa/pa64-regs.h
===================================================================
--- config/pa/pa64-regs.h	(revision 163868)
+++ config/pa/pa64-regs.h	(working copy)
@@ -1,5 +1,5 @@ 
 /* Configuration for GCC-compiler for PA-RISC.
-   Copyright (C) 1999, 2000, 2003, 2004, 2007, 2008
+   Copyright (C) 1999, 2000, 2003, 2004, 2007, 2008, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -38,8 +38,8 @@ 
    issue as using the halves independently triggers false dependency stalls
    anyway.  */
 
-#define FIRST_PSEUDO_REGISTER 61  /* 32 general regs + 28 fp regs +
-				     + 1 shift reg */
+#define FIRST_PSEUDO_REGISTER 62  /* 32 general regs + 28 fp regs +
+				     + 1 shift reg + frame pointer */
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -79,8 +79,8 @@ 
   0, 0, 0, 0, 0, 0, 0, 0, \
   0, 0, 0, 0, 0, 0, 0, 0, \
   0, 0, 0, 0,		  \
-  /* shift register */	  \
-  0}
+  /* shift register and soft frame pointer */	  \
+  0, 1}
 
 /* 1 for registers not available across function calls.
    These must include the FIXED_REGISTERS and also any
@@ -98,8 +98,8 @@ 
   0, 0, 0, 0, 0, 0, 0, 0, \
   0, 0, 1, 1, 1, 1, 1, 1, \
   1, 1, 1, 1, 		  \
-  /* shift register */    \
-  1}
+  /* shift register and soft frame pointer */    \
+  1, 1}
 
 #define CONDITIONAL_REGISTER_USAGE \
 {						\
@@ -137,7 +137,7 @@ 
    3,  4,  5,  6,  7,  8,  9, 10, 	\
   11, 12, 13, 14, 15, 16, 17, 18,	\
   /* special registers.  */		\
-   1, 27, 30,  0, 60}
+   1, 27, 30,  0, 60, 61}
 
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
@@ -235,12 +235,12 @@ 
 #define REG_CLASS_CONTENTS	\
  {{0x00000000, 0x00000000},	/* NO_REGS */			\
   {0x00000002, 0x00000000},	/* R1_REGS */			\
-  {0xfffffffe, 0x00000000},	/* GENERAL_REGS */		\
+  {0xfffffffe, 0x20000000},	/* GENERAL_REGS */		\
   {0x00000000, 0x00000000},	/* FPUPPER_REGS */		\
   {0x00000000, 0x0fffffff},	/* FP_REGS */			\
-  {0xfffffffe, 0x0fffffff},	/* GENERAL_OR_FP_REGS */	\
+  {0xfffffffe, 0x2fffffff},	/* GENERAL_OR_FP_REGS */	\
   {0x00000000, 0x10000000},	/* SHIFT_REGS */		\
-  {0xfffffffe, 0x1fffffff}}	/* ALL_REGS */
+  {0xfffffffe, 0x3fffffff}}	/* ALL_REGS */
 
 /* The following macro defines cover classes for Integrated Register
    Allocator.  Cover classes is a set of non-intersected register
@@ -267,7 +267,7 @@ 
 #define REGNO_REG_CLASS(REGNO)						\
   ((REGNO) == 0 ? NO_REGS 						\
    : (REGNO) == 1 ? R1_REGS						\
-   : (REGNO) < 32 ? GENERAL_REGS					\
+   : (REGNO) < 32 || (REGNO) == 61 ? GENERAL_REGS			\
    : (REGNO) < 60 ? FP_REGS						\
    : SHIFT_REGS)
 
@@ -293,7 +293,7 @@ 
  "%fr4",  "%fr5",   "%fr6",  "%fr7",   "%fr8",  "%fr9",   "%fr10", "%fr11",  \
  "%fr12", "%fr13",  "%fr14", "%fr15",  "%fr16", "%fr17",  "%fr18", "%fr19",  \
  "%fr20", "%fr21",  "%fr22", "%fr23",  "%fr24", "%fr25",  "%fr26", "%fr27",  \
- "%fr28", "%fr29",  "%fr30", "%fr31", "SAR"}
+ "%fr28", "%fr29",  "%fr30", "%fr31",  "SAR",   "sfp"}
 
 #define ADDITIONAL_REGISTER_NAMES \
  {{"%cr11",60}}