From 3b5e81e2f8acf8d99216bffe2dd2a7074e92be81 Mon Sep 17 00:00:00 2001
From: echristo <echristo@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Wed, 6 Feb 2002 02:50:09 +0000
Subject: [PATCH] 2002-02-05  Eric Christopher  <echristo@redhat.com>

	* config/mips/crti.asm: Add changes for mips16. mips16 uses
	register 7 as RA instead of $31.
	* config/mips/crtn.asm: Ditto.
	* config/mips/mips.c (mips_move_2words): Add case for
	TARGET_MIPS16 when HOST_BITS_PER_WIDE_INT >= 64.
	(compute_frame_size): Fix typo.
	(save_restore_insns): Ditto.  Make documentation about using
	register $7 as return register more precise.
	(mips_expand_epilogue): Fix comment. Add code to work around not
	being able to add to the stack pointer directly.
	* config/mips/mips.h (EH_RETURN_DATA_REGNO): Change register number
	to 2 for TARGET_MIPS16 as we need 6 and 7 as clobbers in the
	epilogue.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49535 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/config/mips/crti.asm |  8 +++---
 gcc/config/mips/crtn.asm | 20 ++++++++++++++
 gcc/config/mips/mips.c   | 56 +++++++++++++++++++++++++++++++++-------
 gcc/config/mips/mips.h   |  2 +-
 4 files changed, 71 insertions(+), 15 deletions(-)

diff --git a/gcc/config/mips/crti.asm b/gcc/config/mips/crti.asm
index 6452d1e4b28d..f4bef6ff92b9 100644
--- a/gcc/config/mips/crti.asm
+++ b/gcc/config/mips/crti.asm
@@ -6,10 +6,10 @@
 	.type	_init,@function
 _init:
 #ifdef __mips64
-	dsubu   $sp,$sp,48
+	daddu   $sp,$sp,-48
 	sd      $31,40($sp)
 #else
-	subu	$sp,$sp,32
+	addu	$sp,$sp,-32
 	sw	$31,20($sp)
 #endif
 
@@ -18,9 +18,9 @@ _init:
 	.type	_fini,@function
 _fini:
 #ifdef __mips64
-	dsubu   $sp,$sp,48
+	daddu   $sp,$sp,-48
 	sd      $31,40($sp)
 #else
-	subu	$sp,$sp,32
+	addu	$sp,$sp,-32
 	sw	$31,20($sp)
 #endif
diff --git a/gcc/config/mips/crtn.asm b/gcc/config/mips/crtn.asm
index 4fdd60ab16dc..54f886a216f9 100644
--- a/gcc/config/mips/crtn.asm
+++ b/gcc/config/mips/crtn.asm
@@ -6,17 +6,37 @@
 	ld      $31,40($sp)
 	daddu	$sp,$sp,48
 #else
+#ifndef __mips16
 	lw	$31,20($sp)
 	addu	$sp,$sp,32
+#else
+/* The mips16 uses $7 for a return address. We use that here too.  */
+	lw	$7,20($sp)
+	addu	$sp,$sp,32
+
+	j	$7
 #endif
+#endif
+#ifndef __mips16
 	j	$31
+#endif
 
 	.section .fini,"ax",@progbits
 #ifdef __mips64
 	ld	$31,40($sp)
 	daddu	$sp,$sp,48
 #else
+#ifndef __mips16
 	lw	$31,20($sp)
 	addu	$sp,$sp,32
+#else
+/* The mips16 uses $7 for a return address. We use that here too.  */
+	lw	$7,20($sp)
+	addu	$sp,$sp,32
+
+	j	$7
 #endif
+#endif
+#ifndef __mips16
 	j	$31
+#endif
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 8c19a992459c..01e7dd30c9ce 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -2557,7 +2557,18 @@ mips_move_2words (operands, insn)
 	      operands[2] = GEN_INT (INTVAL (operands[1]) >> 16 >> 16);
 	      operands[1]
 		= GEN_INT (INTVAL (operands[1]) << 16 << 16 >> 16 >> 16);
-	      ret = "li\t%M0,%2\n\tli\t%L0,%1";
+	      if (TARGET_MIPS16)
+		{
+		  if (INTVAL (op1) >= 0 && INTVAL (op1) <= 0xffff)
+		    ret = "li\t%M0,%2\n\tli\t%L0,%1";
+		  else if (INTVAL (op1) < 0 && INTVAL (op1) >= -0xffff)
+		    {
+		      operands[2] = GEN_INT (1);
+		      ret = "li\t%M0,%2\n\tneg\t%M0\n\tli\t%L0,%n1\n\tneg\t%L0";
+		    }
+		}
+	      else
+		ret = "li\t%M0,%2\n\tli\t%L0,%1";
 	    }
 	}
 
@@ -6445,7 +6456,7 @@ compute_frame_size (size)
     }
 
   /* This loop must iterate over the same space as its companion in
-     save_restore_regs.  */
+     save_restore_insns.  */
   for (regno = (FP_REG_LAST - fp_inc + 1);
        regno >= FP_REG_FIRST;
        regno -= fp_inc)
@@ -6673,7 +6684,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
   if (! store_p
       && TARGET_ABICALLS
       && (mips_abi == ABI_32 || mips_abi == ABI_O64))
-    mask &= ~(1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST));
+    mask &= ~(1L << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST));
 
   if (mask == 0 && fmask == 0)
     return;
@@ -6767,7 +6778,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
 
 		/* The mips16 does not have an instruction to load
                    $31, so we load $7 instead, and work things out
-                   in the caller.  */
+                   in mips_expand_epilogue.  */
 		if (TARGET_MIPS16 && ! store_p && regno == GP_REG_FIRST + 31)
 		  reg_rtx = gen_rtx (REG, gpr_mode, GP_REG_FIRST + 7);
 		/* The mips16 sometimes needs to save $18.  */
@@ -7653,7 +7664,7 @@ mips_expand_epilogue ()
 	    {
 	      tsize -= current_function_outgoing_args_size;
 
-	      /* If we have a large frame, it's easier to add to $17
+	      /* If we have a large frame, it's easier to add to $6
                  than to $sp, since the mips16 has no instruction to
                  add a register to $sp.  */
 	      if (orig_tsize > 32767)
@@ -7713,12 +7724,37 @@ mips_expand_epilogue ()
 
       if (tsize != 0 || current_function_calls_eh_return)
 	{
-	  if (Pmode == DImode)
-	    emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
-				   tsize_rtx));
+	  if (!TARGET_MIPS16)
+	    {
+	      if (Pmode == DImode)
+		emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+				       tsize_rtx));
+	      else
+		emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				       tsize_rtx));
+	    }
 	  else
-	    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-				   tsize_rtx));
+	    {
+	      /* We need to work around not being able to add a register
+		 to the stack pointer directly. Use register $6 as an
+		 intermediate step.  */
+
+	      rtx g6_rtx = gen_rtx (REG, Pmode, GP_REG_FIRST + 6);
+
+	      if (Pmode == DImode)
+		{
+		  emit_insn (gen_movdi (g6_rtx, stack_pointer_rtx));
+		  emit_insn (gen_adddi3 (g6_rtx, g6_rtx, tsize_rtx));
+		  emit_insn (gen_movdi (stack_pointer_rtx, g6_rtx));
+		}
+	      else
+		{
+		  emit_insn (gen_movsi (g6_rtx, stack_pointer_rtx));
+		  emit_insn (gen_addsi3 (g6_rtx, g6_rtx, tsize_rtx));
+		  emit_insn (gen_movsi (stack_pointer_rtx, g6_rtx));
+		}
+	    }
+
 	}
     }
 
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 64ddf58e7158..7a5482cc927c 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1369,7 +1369,7 @@ extern int mips_abi;
 #define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31)
 
 /* Describe how we implement __builtin_eh_return.  */
-#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
+#define EH_RETURN_DATA_REGNO(N) ((N) < (TARGET_MIPS16 ? 2 : 4) ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
 #define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
 
 /* Offsets recorded in opcodes are a multiple of this alignment factor.
-- 
GitLab