aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog10
-rw-r--r--gas/config/tc-mips.c84
-rw-r--r--gas/testsuite/ChangeLog8
-rw-r--r--gas/testsuite/gas/mips/mips-abi32-pic2.d74
-rw-r--r--gas/testsuite/gas/mips/mips-abi32-pic2.s107
-rw-r--r--gas/testsuite/gas/mips/mips.exp1
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*-*-*]