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]

powerpc patch 5 of 9



This patch allows use of _savef* and _restf* for ABI_V4, and fixes
a bug in the vrsave code which could have trashed frame_reg_rtx.  Now
that r11 is being used (to match the ABI for _savef*), we sidestep
that particular problem.

	* config/rs6000/rs6000.c (rs6000_emit_allocate_stack): Copy to
	r11 instead of r12.
	(rs6000_emit_prologue): Use r11 for frame_ptr_rtx, and always
	use frame_ptr_rtx if ABI_V4 and !saving_FPRs_inline.  Emit a USE
	for frame_reg_rtx when !saving_FPRs_inline.
	(rs6000_emit_epilogue): If ABI_V4 and !saving_FPRs_inline, set up
	r11 for _restf, delay loading lr, and set up the call to _restf
	before adjusting the stack.
	* config/rs6000/rs6000.md (save_fpregs_si, save_fpregs_di): Tweak
	for extra USE.
	(rest_fpregs_si, rest_fpregs_di): New.

Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.286
diff -u -p -r1.286 rs6000.c
--- rs6000.c	2002/02/19 02:53:36	1.286
+++ rs6000.c	2002/02/20 01:35:44
@@ -8391,13 +8427,13 @@ rs6000_emit_stack_tie ()
 }
 
 /* Emit the correct code for allocating stack space, as insns.
-   If COPY_R12, make sure a copy of the old frame is left in r12.
+   If COPY_R11, make sure a copy of the old frame is left in r11.
    The generated code may use hard register 0 as a temporary.  */
 
 static void
-rs6000_emit_allocate_stack (size, copy_r12)
+rs6000_emit_allocate_stack (size, copy_r11)
      HOST_WIDE_INT size;
-     int copy_r12;
+     int copy_r11;
 {
   rtx insn;
   rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
@@ -8439,8 +8475,8 @@ rs6000_emit_allocate_stack (size, copy_r
 	warning ("stack limit expression is not supported");
     }
 
-  if (copy_r12 || ! TARGET_UPDATE)
-    emit_move_insn (gen_rtx_REG (Pmode, 12), stack_reg);
+  if (copy_r11 || ! TARGET_UPDATE)
+    emit_move_insn (gen_rtx_REG (Pmode, 11), stack_reg);
 
   if (TARGET_UPDATE)
     {
@@ -8468,7 +8504,7 @@ rs6000_emit_allocate_stack (size, copy_r
       else
 	insn = emit_insn (gen_adddi3 (stack_reg, stack_reg, todec));
       emit_move_insn (gen_rtx_MEM (Pmode, stack_reg),
-		      gen_rtx_REG (Pmode, 12));
+		      gen_rtx_REG (Pmode, 11));
     }
   
   RTX_FRAME_RELATED_P (insn) = 1;
@@ -8656,7 +8692,7 @@ rs6000_emit_prologue ()
   enum machine_mode reg_mode = TARGET_POWERPC64 ? DImode : SImode;
   int reg_size = TARGET_POWERPC64 ? 8 : 4;
   rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
-  rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 12);
+  rtx frame_ptr_rtx = gen_rtx_REG (Pmode, 11);
   rtx frame_reg_rtx = sp_reg_rtx;
   rtx cr_save_rtx = NULL;
   rtx insn;
@@ -8672,7 +8708,7 @@ rs6000_emit_prologue ()
   /* For V.4, update stack before we do any saving and set back pointer.  */
   if (info->push_p && DEFAULT_ABI == ABI_V4)
     {
-      if (info->total_size < 32767)
+      if (info->total_size < 32767 && saving_FPRs_inline)
 	sp_offset = info->total_size;
       else
 	frame_reg_rtx = frame_ptr_rtx;
@@ -8757,7 +8793,7 @@ rs6000_emit_prologue ()
 		    gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
 
   /* If we need to save CR, put it into r12.  */
-  if (info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
+  if (info->cr_save_p)
     {
       cr_save_rtx = gen_rtx_REG (SImode, 12);
       emit_insn (gen_movesi_from_cr (cr_save_rtx));
@@ -8792,15 +8828,16 @@ rs6000_emit_prologue ()
       char rname[30];
       const char *alloc_rname;
       rtvec p;
-      p = rtvec_alloc (2 + 64 - info->first_fp_reg_save);
+      p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
       
       RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode, 
 					  gen_rtx_REG (Pmode, 
 						       LINK_REGISTER_REGNUM));
+      RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, frame_reg_rtx);
       sprintf (rname, "%s%d%s", SAVE_FP_PREFIX,
 	       info->first_fp_reg_save - 32, SAVE_FP_SUFFIX);
       alloc_rname = ggc_strdup (rname);
-      RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
+      RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
 				      gen_rtx_SYMBOL_REF (Pmode,
 							  alloc_rname));
       for (i = 0; i < 64 - info->first_fp_reg_save; i++)
@@ -8809,11 +8846,12 @@ rs6000_emit_prologue ()
 	  reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
 	  addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
 			       GEN_INT (info->fp_save_offset 
-					+ sp_offset + 8*i));
+					+ sp_offset
+					+ 8 * i));
 	  mem = gen_rtx_MEM (DFmode, addr);
 	  set_mem_alias_set (mem, rs6000_sr_alias_set);
 
-	  RTVEC_ELT (p, i + 2) = gen_rtx_SET (VOIDmode, mem, reg);
+	  RTVEC_ELT (p, i + 3) = gen_rtx_SET (VOIDmode, mem, reg);
 	}
       insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
       rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, 
@@ -8921,13 +8959,6 @@ rs6000_emit_prologue ()
 
       set_mem_alias_set (mem, rs6000_sr_alias_set);
 
-      /* If r12 was used to hold the original sp, copy cr into r0 now
-	 that it's free.  */
-      if (REGNO (frame_reg_rtx) == 12)
-	{
-	  cr_save_rtx = gen_rtx_REG (SImode, 0);
-	  emit_insn (gen_movesi_from_cr (cr_save_rtx));
-	}
       insn = emit_move_insn (mem, cr_save_rtx);
 
       /* Now, there's no way that dwarf2out_frame_debug_expr is going
@@ -9093,6 +9124,17 @@ rs6000_emit_epilogue (sibcall)
 		      gen_rtx_MEM (Pmode, sp_reg_rtx));
       
     }
+  else if (!restoring_FPRs_inline
+	   && info->first_fp_reg_save != 64
+	   && DEFAULT_ABI == ABI_V4)
+    {
+      frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+      emit_insn (TARGET_32BIT
+		 ? gen_addsi3 (frame_reg_rtx, sp_reg_rtx,
+			       GEN_INT (info->total_size))
+		 : gen_adddi3 (frame_reg_rtx, sp_reg_rtx,
+			       GEN_INT (info->total_size)));
+    }
   else if (info->push_p)
     {
       if (DEFAULT_ABI == ABI_V4)
@@ -9172,7 +9214,9 @@ rs6000_emit_epilogue (sibcall)
     }
   
   /* Set LR here to try to overlap restores below.  */
-  if (info->lr_save_p)
+  if (info->lr_save_p
+      && (restoring_FPRs_inline
+	  || ! (info->first_fp_reg_save != 64 && DEFAULT_ABI == ABI_V4)))
     emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
 		    gen_rtx_REG (Pmode, 0));
   
@@ -9245,22 +9289,64 @@ rs6000_emit_epilogue (sibcall)
 
   /* Restore fpr's if we need to do it without calling a function.  */
   if (restoring_FPRs_inline)
-    for (i = 0; i < 64 - info->first_fp_reg_save; i++)
-      if ((regs_ever_live[info->first_fp_reg_save+i] 
-	   && ! call_used_regs[info->first_fp_reg_save+i]))
+    {
+      for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+	if ((regs_ever_live[info->first_fp_reg_save+i] 
+	     && ! call_used_regs[info->first_fp_reg_save+i]))
+	  {
+	    rtx addr, mem;
+	    addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+				 GEN_INT (info->fp_save_offset 
+					  + sp_offset 
+					  + 8 * i));
+	    mem = gen_rtx_MEM (DFmode, addr);
+	    set_mem_alias_set (mem, rs6000_sr_alias_set);
+
+	    emit_move_insn (gen_rtx_REG (DFmode, 
+					 info->first_fp_reg_save + i),
+			    mem);
+	  }
+    }
+  /* If we have to restore more than two FP registers, and we're using
+     the sysv4 abi, call the restore function.  */
+  else if (info->first_fp_reg_save != 64 && DEFAULT_ABI == ABI_V4)
+    {
+      int i;
+      char rname[30];
+      const char *alloc_rname;
+      rtvec p;
+
+      p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
+      RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode, 
+					  gen_rtx_REG (Pmode, 
+						       LINK_REGISTER_REGNUM));
+      RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, frame_reg_rtx);
+      sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX,
+	       info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
+      alloc_rname = ggc_strdup (rname);
+      RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
+				      gen_rtx_SYMBOL_REF (Pmode,
+							  alloc_rname));
+
+      for (i = 0; i < 64 - info->first_fp_reg_save; i++)
 	{
-	  rtx addr, mem;
+	  rtx addr, reg, mem;
+	  reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
 	  addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
 			       GEN_INT (info->fp_save_offset 
-					+ sp_offset 
+					+ sp_offset
 					+ 8 * i));
 	  mem = gen_rtx_MEM (DFmode, addr);
 	  set_mem_alias_set (mem, rs6000_sr_alias_set);
 
-	  emit_move_insn (gen_rtx_REG (DFmode, 
-				       info->first_fp_reg_save + i),
-			  mem);
+	  RTVEC_ELT (p, i + 3) = gen_rtx_SET (VOIDmode, reg, mem);
 	}
+      emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+      if (info->lr_save_p)
+	emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM),
+			gen_rtx_REG (Pmode, 0));
+    }
 
   /* If we saved cr, restore it here.  Just those that were used.  */
   if (info->cr_save_p)
@@ -9346,7 +9432,7 @@ rs6000_emit_epilogue (sibcall)
   if (!sibcall)
     {
       rtvec p;
-      if (! restoring_FPRs_inline)
+      if (! (restoring_FPRs_inline || DEFAULT_ABI == ABI_V4))
 	p = rtvec_alloc (3 + 64 - info->first_fp_reg_save);
       else
 	p = rtvec_alloc (2);
@@ -9358,7 +9444,7 @@ rs6000_emit_epilogue (sibcall)
 
       /* If we have to restore more than two FP registers, branch to the
 	 restore function.  It will return to our caller.  */
-      if (! restoring_FPRs_inline)
+      if (! (restoring_FPRs_inline || DEFAULT_ABI == ABI_V4))
 	{
 	  int i;
 	  char rname[30];
@@ -9373,16 +9459,14 @@ rs6000_emit_epilogue (sibcall)
 
 	  for (i = 0; i < 64 - info->first_fp_reg_save; i++)
 	    {
-	      rtx addr, mem;
+	      rtx addr, mem, reg;
+	      reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
 	      addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
-				   GEN_INT (info->fp_save_offset + 8*i));
+				   GEN_INT (info->fp_save_offset + 8 * i));
 	      mem = gen_rtx_MEM (DFmode, addr);
 	      set_mem_alias_set (mem, rs6000_sr_alias_set);
 
-	      RTVEC_ELT (p, i+3) = 
-		gen_rtx_SET (VOIDmode,
-			     gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
-			     mem);
+	      RTVEC_ELT (p, i+3) = gen_rtx_SET (VOIDmode, reg, mem);
 	    }
 	}
       
Index: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.168
diff -u -p -r1.168 rs6000.md
--- rs6000.md	2002/02/19 02:53:37	1.168
+++ rs6000.md	2002/02/20 01:35:54
@@ -13669,20 +13741,42 @@
 (define_insn "*save_fpregs_si"
  [(match_parallel 0 "any_operand"
                   [(clobber (match_operand:SI 1 "register_operand" "=l"))
-		   (use (match_operand:SI 2 "call_operand" "s"))
-		   (set (match_operand:DF 3 "memory_operand" "=m")
-			(match_operand:DF 4 "gpc_reg_operand" "f"))])]
+		   (use (match_operand:SI 2 "gpc_reg_operand" "r"))
+		   (use (match_operand:SI 3 "call_operand" "s"))
+		   (set (match_operand:DF 4 "memory_operand" "=m")
+			(match_operand:DF 5 "gpc_reg_operand" "f"))])]
  "TARGET_32BIT"
- "bl %z2")
+ "bl %z3")
 
 (define_insn "*save_fpregs_di"
  [(match_parallel 0 "any_operand"
+                  [(clobber (match_operand:DI 1 "register_operand" "=l"))
+		   (use (match_operand:DI 2 "gpc_reg_operand" "r"))
+		   (use (match_operand:DI 3 "call_operand" "s"))
+		   (set (match_operand:DF 4 "memory_operand" "=m")
+			(match_operand:DF 5 "gpc_reg_operand" "f"))])]
+ "TARGET_64BIT"
+ "bl %z3")
+
+(define_insn "*rest_fpregs_si"
+ [(match_parallel 0 "any_operand"
+                  [(clobber (match_operand:SI 1 "register_operand" "=l"))
+		   (use (match_operand:SI 2 "gpc_reg_operand" "r"))
+		   (use (match_operand:SI 3 "call_operand" "s"))
+		   (set (match_operand:DF 4 "gpc_reg_operand" "=f")
+			(match_operand:DF 5 "memory_operand" "m"))])]
+ "TARGET_32BIT"
+ "bl %z3")
+
+(define_insn "*rest_fpregs_di"
+ [(match_parallel 0 "any_operand"
                   [(clobber (match_operand:DI 1 "register_operand" "=l"))
-		   (use (match_operand:DI 2 "call_operand" "s"))
-		   (set (match_operand:DF 3 "memory_operand" "=m")
-			(match_operand:DF 4 "gpc_reg_operand" "f"))])]
+		   (use (match_operand:DI 2 "gpc_reg_operand" "r"))
+		   (use (match_operand:DI 3 "call_operand" "s"))
+		   (set (match_operand:DF 4 "gpc_reg_operand" "=f")
+			(match_operand:DF 5 "memory_operand" "m"))])]
  "TARGET_64BIT"
- "bl %z2")
+ "bl %z3")
 
 ; These are to explain that changes to the stack pointer should
 ; not be moved over stores to stack memory.
-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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