This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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]

[MIPS PATCH RFA] fix serious problem w/ MIPS .cprestore.


[cc'd people who've touched .cprestore handling in the last few years,
since i assume they care.  8-]

problem:

	.cprestore number->-0x7fff

does ... The Wrong Thing.  (it just stuffs the given number into the
offset field of the generated store/load insns... expecting data
... below the stack pointer ... to keep the right contents ... bad.)

simple test cases include fns which have more than 32kB of locals and
which call other functions.  (i'm planning to submit a test case to
gcc early next week.)

solution: calculate offset in AT, if it won't fit directly in the
insn.  simple enough, and only punishes the fns which need it (> 32kB
of locals).  did it w/ a helper function, because it would be lame to
duplicate the code 3 times.

i think the .cpreturn handling is similarly broken, but it's never
bit me, I don't know how to use it, and there don't seem to be
existing tests for .cpreturn in the testsuite so i don't have anything
to copy!!!


chris
=============================================================================
[ gas/ChangeLog ]
2002-09-13  Chris Demetriou  <cgd@broadcom.com>

	* config/tc-mips.c (IS_SEXT_32BIT_NUM): Move closer to top of file.
	(IS_SEXT_16BIT_NUM): New macro.
	(macro_build_ldst_constoffset): New function, to build a set of
	instructions to do a load or store from a constant offset relative
	to a given register.
	(macro, s_cprestore): Use macro_build_ldst_constoffset to implement
	.cprestore pseudo-op.

[ gas/testsuite/ChangeLog ]
2002-09-13  Chris Demetriou  <cgd@broadcom.com>

	* gas/mips/mips-abi32-pic2.s: New file.
	* gas/mips/mips-abi32-pic2.d: New file.
	* gas/mips/mips.exp: Run new test.

Index: config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.162
diff -u -p -r1.162 tc-mips.c
--- config/tc-mips.c	5 Sep 2002 00:01:18 -0000	1.162
+++ config/tc-mips.c	14 Sep 2002 06:22:13 -0000
@@ -665,6 +665,17 @@ static const unsigned int mips16_to_32_r
 #define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x2000) != 0)
 #define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x2000)
 #define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x2000)
+
+/* Is the given value a sign-extended 32-bit value?  */
+#define IS_SEXT_32BIT_NUM(x)						\
+  (((x) &~ (offsetT) 0x7fffffff) == 0					\
+   || (((x) &~ (offsetT) 0x7fffffff) == ~ (offsetT) 0x7fffffff))
+
+/* Is the given value a sign-extended 16-bit value?  */
+#define IS_SEXT_16BIT_NUM(x)						\
+  (((x) &~ (offsetT) 0x7fff) == 0					\
+   || (((x) &~ (offsetT) 0x7fff) == ~ (offsetT) 0x7fff))
+
 
 /* Prototypes for static functions.  */
 
@@ -701,6 +712,9 @@ static void mips16_macro_build PARAMS ((
 static void macro_build_jalr PARAMS ((int, expressionS *));
 static void macro_build_lui PARAMS ((char *place, int *counter,
 				     expressionS * ep, int regnum));
+static void macro_build_ldst_constoffset PARAMS ((char *place, int *counter,
+						  expressionS * ep, const char *op,
+						  int valreg, int breg));
 static void set_at PARAMS ((int *counter, int reg, int unsignedp));
 static void check_absolute_expr PARAMS ((struct mips_cl_insn * ip,
 					 expressionS *));
@@ -3079,6 +3093,52 @@ macro_build_lui (place, counter, ep, reg
     append_insn (place, &insn, &high_expr, r, false);
 }
 
+/* Generate a sequence of instructions to do a load or store from a constant
+   offset off of a base register (breg) into/from a target register (treg),
+   using AT if necessary.  */
+static void
+macro_build_ldst_constoffset (place, counter, ep, op, treg, breg)
+     char *place;
+     int *counter;
+     expressionS *ep;
+     const char *op;
+     int treg, breg;
+{
+  assert (ep->X_op == O_constant);
+
+  /* Right now, this routine can only handle signed 32-bit contants.  */
+  if (! IS_SEXT_32BIT_NUM(ep->X_add_number))
+    as_warn (_("operand overflow"));
+
+  if (IS_SEXT_16BIT_NUM(ep->X_add_number))
+    {
+      /* Signed 16-bit offset will fit in the op.  Easy!  */
+      macro_build (place, counter, ep, op, "t,o(b)", treg,
+		   (int) BFD_RELOC_LO16, breg);
+    }
+  else
+    {
+      /* 32-bit offset, need multiple instructions and AT, like:
+	   lui      $tempreg,const_hi       (BFD_RELOC_HI16_S)
+	   addu     $tempreg,$tempreg,$breg
+           <op>     $treg,const_lo($tempreg)   (BFD_RELOC_LO16)
+         to handle the complete offset.  */
+      macro_build_lui (place, counter, ep, AT);
+      if (place != NULL)
+	place += 4;
+      macro_build (place, counter, (expressionS *) NULL,
+		   HAVE_32BIT_ADDRESSES ? "addu" : "daddu",
+		   "d,v,t", AT, AT, breg);
+      if (place != NULL)
+	place += 4;
+      macro_build (place, counter, ep, op, "t,o(b)", treg,
+		   (int) BFD_RELOC_LO16, AT);
+
+      if (mips_opts.noat)
+	as_warn (_("Macro used $at after \".set noat\""));
+    }
+}
+
 /*			set_at()
  * Generates code to set the $at register to true (one)
  * if reg is less than the immediate expression.
@@ -3193,11 +3253,6 @@ check_absolute_expr (ip, ex)
            ? 1                          \
            : 0)
 
-/* Is the given value a sign-extended 32-bit value?  */
-#define IS_SEXT_32BIT_NUM(x)						\
-  (((x) &~ (offsetT) 0x7fffffff) == 0					\
-   || (((x) &~ (offsetT) 0x7fffffff) == ~ (offsetT) 0x7fffffff))
-
 /*			load_register()
  *  This routine generates the least number of instructions neccessary to load
  *  an absolute expression value into a register.
@@ -5048,10 +5103,9 @@ macro (ip)
 		      mips_cprestore_valid = 1;
 		    }
 		  expr1.X_add_number = mips_cprestore_offset;
-		  macro_build ((char *) NULL, &icnt, &expr1,
-			       HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
-			       mips_gp_register, (int) BFD_RELOC_LO16,
-			       mips_frame_reg);
+  		  macro_build_ldst_constoffset ((char *) NULL, &icnt, &expr1,
+					        HAVE_32BIT_ADDRESSES ? "lw" : "ld",
+					        mips_gp_register, mips_frame_reg);
 		}
 	    }
 	}
@@ -5181,10 +5235,9 @@ macro (ip)
 		    macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
 				 "nop", "");
 		  expr1.X_add_number = mips_cprestore_offset;
-		  macro_build ((char *) NULL, &icnt, &expr1,
-			       HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
-			       mips_gp_register, (int) BFD_RELOC_LO16,
-			       mips_frame_reg);
+  		  macro_build_ldst_constoffset ((char *) NULL, &icnt, &expr1,
+					        HAVE_32BIT_ADDRESSES ? "lw" : "ld",
+					        mips_gp_register, mips_frame_reg);
 		}
 	    }
 	}
@@ -11835,8 +11892,9 @@ s_cprestore (ignore)
   ex.X_op_symbol = NULL;
   ex.X_add_number = mips_cprestore_offset;
 
-  macro_build ((char *) NULL, &icnt, &ex, HAVE_32BIT_ADDRESSES ? "sw" : "sd",
-	       "t,o(b)", mips_gp_register, (int) BFD_RELOC_LO16, SP);
+  macro_build_ldst_constoffset ((char *) NULL, &icnt, &ex,
+				HAVE_32BIT_ADDRESSES ? "sw" : "sd",
+				mips_gp_register, SP);
 
   demand_empty_rest_of_line ();
 }
Index: testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.40
diff -u -p -r1.40 mips.exp
--- testsuite/gas/mips/mips.exp	12 Aug 2002 08:30:50 -0000	1.40
+++ testsuite/gas/mips/mips.exp	14 Sep 2002 06:22:13 -0000
@@ -190,6 +194,7 @@ if { [istarget mips*-*-*] } then {
 
   	run_dump_test "mips-abi32"
   	run_dump_test "mips-abi32-pic"
+  	run_dump_test "mips-abi32-pic2"
 
 	run_dump_test "elf${el}-rel"
 	if {[istarget mips64*-*-*] || [istarget mipsisa32*-*-*]
Index: testsuite/gas/mips/mips-abi32-pic2.d
===================================================================
RCS file: testsuite/gas/mips/mips-abi32-pic2.d
diff -N testsuite/gas/mips/mips-abi32-pic2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/mips/mips-abi32-pic2.d	14 Sep 2002 06:22:13 -0000
@@ -0,0 +1,89 @@
+#objdump: -d -mmips:8000 -r --prefix-addresses --show-raw-insn
+#as: -march=8000 -EB -mabi=32 -KPIC
+#name: MIPS -mabi=32 test 2 (SVR4 PIC)
+
+.*: +file format.*
+
+Disassembly of section \.text:
+0+000 <[^>]*> 3c1c0000 	lui	gp,0x0
+			0: R_MIPS_HI16	_gp_disp
+0+004 <[^>]*> 279c0000 	addiu	gp,gp,0
+			4: R_MIPS_LO16	_gp_disp
+0+008 <[^>]*> 0399e021 	addu	gp,gp,t9
+0+00c <[^>]*> afbc0008 	sw	gp,8\(sp\)
+0+010 <[^>]*> 8f990000 	lw	t9,0\(gp\)
+			10: R_MIPS_GOT16	\.text
+0+014 <[^>]*> 00000000 	nop
+0+018 <[^>]*> 273900fc 	addiu	t9,t9,252
+			18: R_MIPS_LO16	\.text
+0+01c <[^>]*> 0320f809 	jalr	t9
+0+020 <[^>]*> 00000000 	nop
+0+024 <[^>]*> 8fbc0008 	lw	gp,8\(sp\)
+0+028 <[^>]*> 00000000 	nop
+0+02c <[^>]*> 8f990000 	lw	t9,0\(gp\)
+			2c: R_MIPS_GOT16	\.text
+0+030 <[^>]*> 00000000 	nop
+0+034 <[^>]*> 273900fc 	addiu	t9,t9,252
+			34: R_MIPS_LO16	\.text
+0+038 <[^>]*> 0320f809 	jalr	t9
+0+03c <[^>]*> 00000000 	nop
+0+040 <[^>]*> 8fbc0008 	lw	gp,8\(sp\)
+0+044 <[^>]*> 3c1c0000 	lui	gp,0x0
+			44: R_MIPS_HI16	_gp_disp
+0+048 <[^>]*> 279c0000 	addiu	gp,gp,0
+			48: R_MIPS_LO16	_gp_disp
+0+04c <[^>]*> 0399e021 	addu	gp,gp,t9
+0+050 <[^>]*> 3c010001 	lui	at,0x1
+0+054 <[^>]*> 003d0821 	addu	at,at,sp
+0+058 <[^>]*> ac3c8000 	sw	gp,-32768\(at\)
+0+05c <[^>]*> 8f990000 	lw	t9,0\(gp\)
+			5c: R_MIPS_GOT16	\.text
+0+060 <[^>]*> 00000000 	nop
+0+064 <[^>]*> 273900fc 	addiu	t9,t9,252
+			64: R_MIPS_LO16	\.text
+0+068 <[^>]*> 0320f809 	jalr	t9
+0+06c <[^>]*> 00000000 	nop
+0+070 <[^>]*> 3c010001 	lui	at,0x1
+0+074 <[^>]*> 003d0821 	addu	at,at,sp
+0+078 <[^>]*> 8c3c8000 	lw	gp,-32768\(at\)
+0+07c <[^>]*> 00000000 	nop
+0+080 <[^>]*> 8f990000 	lw	t9,0\(gp\)
+			80: R_MIPS_GOT16	\.text
+0+084 <[^>]*> 00000000 	nop
+0+088 <[^>]*> 273900fc 	addiu	t9,t9,252
+			88: R_MIPS_LO16	\.text
+0+08c <[^>]*> 0320f809 	jalr	t9
+0+090 <[^>]*> 00000000 	nop
+0+094 <[^>]*> 3c010001 	lui	at,0x1
+0+098 <[^>]*> 003d0821 	addu	at,at,sp
+0+09c <[^>]*> 8c3c8000 	lw	gp,-32768\(at\)
+0+0a0 <[^>]*> 3c1c0000 	lui	gp,0x0
+			a0: R_MIPS_HI16	_gp_disp
+0+0a4 <[^>]*> 279c0000 	addiu	gp,gp,0
+			a4: R_MIPS_LO16	_gp_disp
+0+0a8 <[^>]*> 0399e021 	addu	gp,gp,t9
+0+0ac <[^>]*> 3c010001 	lui	at,0x1
+0+0b0 <[^>]*> 003d0821 	addu	at,at,sp
+0+0b4 <[^>]*> ac3c0000 	sw	gp,0\(at\)
+0+0b8 <[^>]*> 8f990000 	lw	t9,0\(gp\)
+			b8: R_MIPS_GOT16	\.text
+0+0bc <[^>]*> 00000000 	nop
+0+0c0 <[^>]*> 273900fc 	addiu	t9,t9,252
+			c0: R_MIPS_LO16	\.text
+0+0c4 <[^>]*> 0320f809 	jalr	t9
+0+0c8 <[^>]*> 00000000 	nop
+0+0cc <[^>]*> 3c010001 	lui	at,0x1
+0+0d0 <[^>]*> 003d0821 	addu	at,at,sp
+0+0d4 <[^>]*> 8c3c0000 	lw	gp,0\(at\)
+0+0d8 <[^>]*> 00000000 	nop
+0+0dc <[^>]*> 8f990000 	lw	t9,0\(gp\)
+			dc: R_MIPS_GOT16	\.text
+0+0e0 <[^>]*> 00000000 	nop
+0+0e4 <[^>]*> 273900fc 	addiu	t9,t9,252
+			e4: R_MIPS_LO16	\.text
+0+0e8 <[^>]*> 0320f809 	jalr	t9
+0+0ec <[^>]*> 00000000 	nop
+0+0f0 <[^>]*> 3c010001 	lui	at,0x1
+0+0f4 <[^>]*> 003d0821 	addu	at,at,sp
+0+0f8 <[^>]*> 8c3c0000 	lw	gp,0\(at\)
+	\.\.\.
Index: testsuite/gas/mips/mips-abi32-pic2.s
===================================================================
RCS file: testsuite/gas/mips/mips-abi32-pic2.s
diff -N testsuite/gas/mips/mips-abi32-pic2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gas/mips/mips-abi32-pic2.s	14 Sep 2002 06:22:13 -0000
@@ -0,0 +1,89 @@
+
+	.text
+	.ent	func1
+func1:
+	.frame $sp,0,$31
+	.set noreorder
+	.cpload $25		# 0000 lui	gp,hi(_gp_disp)
+				# 0004 addiu	gp,gp,lo(_gp_disp)
+				# 0008 addu	gp,gp,t9
+	.set reorder
+	.cprestore 8		# 000c sw	gp,8(sp)
+
+	jal	end		# 0048 lw	t9,got(.text)(gp)
+				# 004c nop
+				# 0050 addiu	t9,t9,lo(end)
+				# 0054 jalr	t9
+				# 0058 nop
+				# 005c lw	gp,8(sp)
+
+	# avoid confusion: without something here, the lw above might be
+	# put into the delay slot for the jalr below!
+	nop
+
+	jal	end		# 0054 jalr	t9
+				# 0058 nop
+				# 005c lw	gp,8(sp)
+	.end	func1
+
+
+	.text
+	.ent	func2
+func2:
+	.frame $sp,0,$31
+	.set noreorder
+	.cpload $25		# 0000 lui	gp,hi(_gp_disp)
+				# 0004 addiu	gp,gp,lo(_gp_disp)
+				# 0008 addu	gp,gp,t9
+	.set reorder
+	.cprestore 32768	# 000c sw	gp,8(sp)
+
+	jal	end		# 0048 lw	t9,got(.text)(gp)
+				# 004c nop
+				# 0050 addiu	t9,t9,lo(end)
+				# 0054 jalr	t9
+				# 0058 nop
+				# 005c lw	gp,8(sp)
+
+	# avoid confusion: without something here, the lw above might be
+	# put into the delay slot for the jalr below!
+	nop
+
+	jal	end		# 0054 jalr	t9
+				# 0058 nop
+				# 005c lw	gp,8(sp)
+	.end	func2
+
+
+	.text
+	.ent	func3
+func3:
+	.frame $sp,0,$31
+	.set noreorder
+	.cpload $25		# 0000 lui	gp,hi(_gp_disp)
+				# 0004 addiu	gp,gp,lo(_gp_disp)
+				# 0008 addu	gp,gp,t9
+	.set reorder
+	.cprestore 65536	# 000c sw	gp,8(sp)
+
+	jal	end		# 0048 lw	t9,got(.text)(gp)
+				# 004c nop
+				# 0050 addiu	t9,t9,lo(end)
+				# 0054 jalr	t9
+				# 0058 nop
+				# 005c lw	gp,8(sp)
+
+	# avoid confusion: without something here, the lw above might be
+	# put into the delay slot for the jalr below!
+	nop
+
+	jal	end		# 0054 jalr	t9
+				# 0058 nop
+				# 005c lw	gp,8(sp)
+
+	.end	func3
+
+end:
+
+# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.space	8


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