diff options
-rw-r--r-- | gas/ChangeLog | 10 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 84 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips-abi32-pic2.d | 74 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips-abi32-pic2.s | 107 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips.exp | 1 |
6 files changed, 268 insertions, 16 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index a959777..7c9871a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,15 @@ 2002-09-18 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. + +2002-09-18 Chris Demetriou <cgd@broadcom.com> + * config/tc-mips.c (md_apply_fix3): Just return for BFD_RELOC_8. 2002-09-18 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de> diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index c102675..ba803d2 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -665,6 +665,17 @@ static const unsigned int mips16_to_32_reg_map[] = #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 ((char *, int *, expressionS *, 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 *)); @@ -3082,6 +3096,52 @@ macro_build_lui (place, counter, ep, regnum) 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. @@ -3196,11 +3256,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. @@ -5063,10 +5118,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); } } } @@ -5196,10 +5250,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); } } } @@ -11863,8 +11916,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 (); } diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 7ab5e58..6ba6567 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,4 +1,10 @@ -2002-09-12 Chris Demetriou <cgd@broadcom.com> +2002-09-18 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. + +2002-09-18 Chris Demetriou <cgd@broadcom.com> * gas/mips/baddata1.s: New file. * gas/mips/baddata1.l: New file. diff --git a/gas/testsuite/gas/mips/mips-abi32-pic2.d b/gas/testsuite/gas/mips/mips-abi32-pic2.d new file mode 100644 index 0000000..1f3811e --- /dev/null +++ b/gas/testsuite/gas/mips/mips-abi32-pic2.d @@ -0,0 +1,74 @@ +#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 <[^>]*> 273900d8 addiu t9,t9,216 + 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 <[^>]*> 0320f809 jalr t9 +0+030 <[^>]*> 00000000 nop +0+034 <[^>]*> 8fbc0008 lw gp,8\(sp\) +0+038 <[^>]*> 3c1c0000 lui gp,0x0 + 38: R_MIPS_HI16 _gp_disp +0+03c <[^>]*> 279c0000 addiu gp,gp,0 + 3c: R_MIPS_LO16 _gp_disp +0+040 <[^>]*> 0399e021 addu gp,gp,t9 +0+044 <[^>]*> 3c010001 lui at,0x1 +0+048 <[^>]*> 003d0821 addu at,at,sp +0+04c <[^>]*> ac3c8000 sw gp,-32768\(at\) +0+050 <[^>]*> 8f990000 lw t9,0\(gp\) + 50: R_MIPS_GOT16 \.text +0+054 <[^>]*> 00000000 nop +0+058 <[^>]*> 273900d8 addiu t9,t9,216 + 58: R_MIPS_LO16 \.text +0+05c <[^>]*> 0320f809 jalr t9 +0+060 <[^>]*> 00000000 nop +0+064 <[^>]*> 3c010001 lui at,0x1 +0+068 <[^>]*> 003d0821 addu at,at,sp +0+06c <[^>]*> 8c3c8000 lw gp,-32768\(at\) +0+070 <[^>]*> 00000000 nop +0+074 <[^>]*> 0320f809 jalr t9 +0+078 <[^>]*> 00000000 nop +0+07c <[^>]*> 3c010001 lui at,0x1 +0+080 <[^>]*> 003d0821 addu at,at,sp +0+084 <[^>]*> 8c3c8000 lw gp,-32768\(at\) +0+088 <[^>]*> 3c1c0000 lui gp,0x0 + 88: R_MIPS_HI16 _gp_disp +0+08c <[^>]*> 279c0000 addiu gp,gp,0 + 8c: R_MIPS_LO16 _gp_disp +0+090 <[^>]*> 0399e021 addu gp,gp,t9 +0+094 <[^>]*> 3c010001 lui at,0x1 +0+098 <[^>]*> 003d0821 addu at,at,sp +0+09c <[^>]*> ac3c0000 sw gp,0\(at\) +0+0a0 <[^>]*> 8f990000 lw t9,0\(gp\) + a0: R_MIPS_GOT16 \.text +0+0a4 <[^>]*> 00000000 nop +0+0a8 <[^>]*> 273900d8 addiu t9,t9,216 + a8: R_MIPS_LO16 \.text +0+0ac <[^>]*> 0320f809 jalr t9 +0+0b0 <[^>]*> 00000000 nop +0+0b4 <[^>]*> 3c010001 lui at,0x1 +0+0b8 <[^>]*> 003d0821 addu at,at,sp +0+0bc <[^>]*> 8c3c0000 lw gp,0\(at\) +0+0c0 <[^>]*> 00000000 nop +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\) + \.\.\. diff --git a/gas/testsuite/gas/mips/mips-abi32-pic2.s b/gas/testsuite/gas/mips/mips-abi32-pic2.s new file mode 100644 index 0000000..3e22e26 --- /dev/null +++ b/gas/testsuite/gas/mips/mips-abi32-pic2.s @@ -0,0 +1,107 @@ + + .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 # 0010 lw t9,got(.text)(gp) + # 0014 nop + # 0018 addiu t9,t9,lo(end) + # 001c jalr t9 + # 0020 nop + # 0024 lw gp,8(sp) + + # Avoid confusion: avoid the 'lw' above being put into the delay + # slot for the jalr below! + .set noreorder + nop # 0028 nop + .set reorder + + jal $25 # 002c jalr t9 + # 0030 nop + # 0034 lw gp,8(sp) + .end func1 + + + .text + .ent func2 +func2: + .frame $sp,0,$31 + .set noreorder + .cpload $25 # 0038 lui gp,hi(_gp_disp) + # 003c addiu gp,gp,lo(_gp_disp) + # 0040 addu gp,gp,t9 + .set reorder + .cprestore 32768 # 0044 lui at,0x1 + # 0048 addu at,at,sp + # 004c sw gp,-32768(at) + + jal end # 0050 lw t9,got(.text)(gp) + # 0054 nop + # 0058 addiu t9,t9,lo(end) + # 005c jalr t9 + # 0060 nop + # 0064 lui at,0x1 + # 0068 addu at,at,sp + # 006c lw gp,-32768(at) + + # Avoid confusion: avoid the 'lw' above being put into the delay + # slot for the jalr below! + .set noreorder + nop # 0070 nop + .set reorder + + jal $25 # 0074 jalr t9 + # 0078 nop + # 007c lui at,0x1 + # 0080 addu at,at,sp + # 0084 lw gp,-32768(at) + .end func2 + + + .text + .ent func3 +func3: + .frame $sp,0,$31 + .set noreorder + .cpload $25 # 0088 lui gp,hi(_gp_disp) + # 008c addiu gp,gp,lo(_gp_disp) + # 0090 addu gp,gp,t9 + .set reorder + .cprestore 65536 # 0094 lui at,0x1 + # 0098 addu at,at,sp + # 009c sw gp,0(at) + + jal end # 00a0 lw t9,got(.text)(gp) + # 00a4 nop + # 00a8 addiu t9,t9,lo(end) + # 00ac jalr t9 + # 00b0 nop + # 00b4 lui at,0x1 + # 00b8 addu at,at,sp + # 00bc lw gp,0(at) + + # Avoid confusion: avoid the 'lw' above being put into the delay + # slot for the jalr below! + .set noreorder + nop # 00c0 nop + .set reorder + + jal $25 # 00c4 jalr t9 + # 00c8 nop + # 00cc lui at,0x1 + # 00d0 addu at,at,sp + # 00d4 lw gp,0(at) + + .end func3 + +end: + +# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ... + .space 8 diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index 12613ea..d23390d 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -193,6 +193,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*-*-*] |