This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[MIPS PATCH RFA] fix serious problem w/ MIPS .cprestore.
- From: cgd at broadcom dot com
- To: binutils at sources dot redhat dot com
- Cc: echristo at redhat dot com,seufer at csv dot ica dot uni-stuttgart dot de,drow at mvista dot com
- Date: 13 Sep 2002 23:32:00 -0700
- Subject: [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