aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-mips.c100
-rw-r--r--gas/testsuite/ChangeLog5
-rw-r--r--gas/testsuite/gas/mips/elf-rel15.d14
-rw-r--r--gas/testsuite/gas/mips/elf-rel15.s4
-rw-r--r--gas/testsuite/gas/mips/mips.exp2
6 files changed, 56 insertions, 74 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 9df96ef..1a1bb29 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2003-06-12 Richard Sandiford <rsandifo@redhat.com>
+
+ * config/tc-mips.c (append_insn): In a compound relocation, take the
+ field width from the final (outermost) operator.
+
2003-06-11 Richard Henderson <rth@redhat.com>
* dw2gencfi.c (struct cfi_escape_data): New.
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 5d58d40..938148c 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -2154,13 +2154,20 @@ append_insn (place, ip, address_expr, reloc_type)
}
else
{
- reloc_howto_type *howto;
-
need_reloc:
/* Don't generate a reloc if we are writing into a variant frag. */
if (place == NULL)
{
- howto = bfd_reloc_type_lookup (stdoutput, reloc_type[0]);
+ reloc_howto_type *howto;
+ int i;
+
+ /* In a compound relocation, it is the final (outermost)
+ operator that determines the relocated field. */
+ for (i = 1; i < 3; i++)
+ if (reloc_type[i] == BFD_RELOC_UNUSED)
+ break;
+
+ howto = bfd_reloc_type_lookup (stdoutput, reloc_type[i - 1]);
fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal,
bfd_get_reloc_size(howto),
address_expr,
@@ -2207,77 +2214,22 @@ append_insn (place, ip, address_expr, reloc_type)
hi_fixup->seg = now_seg;
}
- if (reloc_type[1] != BFD_RELOC_UNUSED)
- {
- /* FIXME: This symbol can be one of
- RSS_UNDEF, RSS_GP, RSS_GP0, RSS_LOC. */
- address_expr->X_op = O_absent;
- address_expr->X_add_symbol = 0;
- address_expr->X_add_number = 0;
-
- howto = bfd_reloc_type_lookup (stdoutput, reloc_type[1]);
- fixp[1] = fix_new_exp (frag_now, f - frag_now->fr_literal,
- bfd_get_reloc_size(howto),
- address_expr, FALSE, reloc_type[1]);
-
- /* These relocations can have an addend that won't fit in
- 4 octets for 64bit assembly. */
- if (HAVE_64BIT_GPRS
- && ! howto->partial_inplace
- && (reloc_type[1] == BFD_RELOC_16
- || reloc_type[1] == BFD_RELOC_32
- || reloc_type[1] == BFD_RELOC_MIPS_JMP
- || reloc_type[1] == BFD_RELOC_HI16_S
- || reloc_type[1] == BFD_RELOC_LO16
- || reloc_type[1] == BFD_RELOC_GPREL16
- || reloc_type[1] == BFD_RELOC_MIPS_LITERAL
- || reloc_type[1] == BFD_RELOC_GPREL32
- || reloc_type[1] == BFD_RELOC_64
- || reloc_type[1] == BFD_RELOC_CTOR
- || reloc_type[1] == BFD_RELOC_MIPS_SUB
- || reloc_type[1] == BFD_RELOC_MIPS_HIGHEST
- || reloc_type[1] == BFD_RELOC_MIPS_HIGHER
- || reloc_type[1] == BFD_RELOC_MIPS_SCN_DISP
- || reloc_type[1] == BFD_RELOC_MIPS_REL16
- || reloc_type[1] == BFD_RELOC_MIPS_RELGOT))
- fixp[1]->fx_no_overflow = 1;
-
- if (reloc_type[2] != BFD_RELOC_UNUSED)
- {
- address_expr->X_op = O_absent;
- address_expr->X_add_symbol = 0;
- address_expr->X_add_number = 0;
-
- howto = bfd_reloc_type_lookup (stdoutput, reloc_type[2]);
- fixp[2] = fix_new_exp (frag_now,
- f - frag_now->fr_literal,
- bfd_get_reloc_size(howto),
- address_expr, FALSE,
- reloc_type[2]);
-
- /* These relocations can have an addend that won't fit in
- 4 octets for 64bit assembly. */
- if (HAVE_64BIT_GPRS
- && ! howto->partial_inplace
- && (reloc_type[2] == BFD_RELOC_16
- || reloc_type[2] == BFD_RELOC_32
- || reloc_type[2] == BFD_RELOC_MIPS_JMP
- || reloc_type[2] == BFD_RELOC_HI16_S
- || reloc_type[2] == BFD_RELOC_LO16
- || reloc_type[2] == BFD_RELOC_GPREL16
- || reloc_type[2] == BFD_RELOC_MIPS_LITERAL
- || reloc_type[2] == BFD_RELOC_GPREL32
- || reloc_type[2] == BFD_RELOC_64
- || reloc_type[2] == BFD_RELOC_CTOR
- || reloc_type[2] == BFD_RELOC_MIPS_SUB
- || reloc_type[2] == BFD_RELOC_MIPS_HIGHEST
- || reloc_type[2] == BFD_RELOC_MIPS_HIGHER
- || reloc_type[2] == BFD_RELOC_MIPS_SCN_DISP
- || reloc_type[2] == BFD_RELOC_MIPS_REL16
- || reloc_type[2] == BFD_RELOC_MIPS_RELGOT))
- fixp[2]->fx_no_overflow = 1;
- }
- }
+ /* Add fixups for the second and third relocations, if given.
+ Note that the ABI allows the second relocation to be
+ against RSS_UNDEF, RSS_GP, RSS_GP0 or RSS_LOC. At the
+ moment we only use RSS_UNDEF, but we could add support
+ for the others if it ever becomes necessary. */
+ for (i = 1; i < 3; i++)
+ if (reloc_type[i] != BFD_RELOC_UNUSED)
+ {
+ address_expr->X_op = O_absent;
+ address_expr->X_add_symbol = 0;
+ address_expr->X_add_number = 0;
+
+ fixp[i] = fix_new_exp (frag_now, fixp[0]->fx_where,
+ fixp[0]->fx_size, address_expr,
+ FALSE, reloc_type[i]);
+ }
}
}
}
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 1ef04ab..8458294 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-06-12 Richard Sandiford <rsandifo@redhat.com>
+
+ * gas/mips/elf-rel15.[sd]: New test.
+ * gas/mips/mips.exp: Run it.
+
2003-06-11 Richard Henderson <rth@redhat.com>
* gas/cfi/cfi-common-3.[ds]: New.
diff --git a/gas/testsuite/gas/mips/elf-rel15.d b/gas/testsuite/gas/mips/elf-rel15.d
new file mode 100644
index 0000000..7bb7878
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf-rel15.d
@@ -0,0 +1,14 @@
+#objdump: -dr
+#as: -mabi=n32 -mips3
+
+.*: file format .*
+
+Disassembly of section \.text:
+
+00000000 <foo>:
+ 0: 3c020000 lui v0,0x0
+ 0: R_MIPS_GPREL16 \.text
+ 0: R_MIPS_SUB \*ABS\*
+ 0: R_MIPS_HI16 \*ABS\*
+ 4: 23bdffe4 addi sp,sp,-28
+ ...
diff --git a/gas/testsuite/gas/mips/elf-rel15.s b/gas/testsuite/gas/mips/elf-rel15.s
new file mode 100644
index 0000000..c0bc623
--- /dev/null
+++ b/gas/testsuite/gas/mips/elf-rel15.s
@@ -0,0 +1,4 @@
+foo:
+ lui $2,%hi(%neg(%gp_rel(foo)))
+ sub $sp,$sp,28
+ .space 16
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 9bb3772..2330443 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -645,6 +645,8 @@ if { [istarget mips*-*-*] } then {
run_dump_test "elf-rel14"
if $has_newabi {
+ run_dump_test "elf-rel15"
+
run_dump_test "elf-rel-got-n32"
run_dump_test "elf-rel-xgot-n32"
run_dump_test "elf-rel-got-n64"