* config/tc-mips.c (append_insn): In a compound relocation, take the
authorRichard Sandiford <rdsandiford@googlemail.com>
Thu, 12 Jun 2003 05:45:50 +0000 (05:45 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Thu, 12 Jun 2003 05:45:50 +0000 (05:45 +0000)
field width from the final (outermost) operator.

gas/ChangeLog
gas/config/tc-mips.c
gas/testsuite/ChangeLog
gas/testsuite/gas/mips/elf-rel15.d [new file with mode: 0644]
gas/testsuite/gas/mips/elf-rel15.s [new file with mode: 0644]
gas/testsuite/gas/mips/mips.exp

index 9df96ef..1a1bb29 100644 (file)
@@ -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.
index 5d58d40..938148c 100644 (file)
@@ -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]);
+                 }
            }
        }
     }
index 1ef04ab..8458294 100644 (file)
@@ -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 (file)
index 0000000..7bb7878
--- /dev/null
@@ -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 (file)
index 0000000..c0bc623
--- /dev/null
@@ -0,0 +1,4 @@
+foo:
+       lui     $2,%hi(%neg(%gp_rel(foo)))
+       sub     $sp,$sp,28
+       .space  16
index 9bb3772..2330443 100644 (file)
@@ -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"