bfd/
authorRichard Sandiford <rdsandiford@googlemail.com>
Mon, 25 Jun 2007 10:13:57 +0000 (10:13 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Mon, 25 Jun 2007 10:13:57 +0000 (10:13 +0000)
* elfxx-mips.c (mips_elf_calculate_relocation): Allow local stubs
to be used for calls from MIPS16 code.

gas/
* config/tc-mips.h (TC_SYMFIELD_TYPE): New.
* config/tc-mips.c (append_insn): Record which symbols have
R_MIPS16_26 relocations against them.
(mips_fix_adjustable): Don't reduce relocations against such symbols.

ld/testsuite/
* ld-mips-elf/mips16-local-stubs-1.s,
* ld-mips-elf/mips16-local-stubs-1.d: New tests.
* ld-mips-elf/mips-elf.exp: Run them.

bfd/ChangeLog
bfd/elfxx-mips.c
gas/ChangeLog
gas/config/tc-mips.c
gas/config/tc-mips.h
ld/testsuite/ChangeLog
ld/testsuite/ld-mips-elf/mips-elf.exp
ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s [new file with mode: 0644]

index 258fd6f..6b396db 100644 (file)
@@ -1,3 +1,8 @@
+2007-06-25  Richard Sandiford  <richard@codesourcery.com>
+
+       * elfxx-mips.c (mips_elf_calculate_relocation): Allow local stubs
+       to be used for calls from MIPS16 code.
+
 2007-06-23  Andreas Schwab  <schwab@suse.de>
 
        * configure.in (--with-separate-debug-dir): New option.
index 1bccb33..dafd607 100644 (file)
@@ -4092,8 +4092,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   /* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
      need to redirect the call to the stub.  */
   else if (r_type == R_MIPS16_26 && !info->relocatable
-          && h != NULL
-          && ((h->call_stub != NULL || h->call_fp_stub != NULL)
+          && ((h != NULL && (h->call_stub != NULL || h->call_fp_stub != NULL))
               || (local_p
                   && elf_tdata (input_bfd)->local_call_stubs != NULL
                   && elf_tdata (input_bfd)->local_call_stubs[r_symndx] != NULL))
index c713436..19a28fa 100644 (file)
@@ -1,3 +1,10 @@
+2007-06-25  Richard Sandiford  <richard@codesourcery.com>
+
+       * config/tc-mips.h (TC_SYMFIELD_TYPE): New.
+       * config/tc-mips.c (append_insn): Record which symbols have
+       R_MIPS16_26 relocations against them.
+       (mips_fix_adjustable): Don't reduce relocations against such symbols.
+
 2007-06-22  Sterling Augustine  <sterling@tensilica.com>
 
        * config/tc-xtensa.c (xg_assembly_relax): Comment termination rules.
index 47a4b3c..39f681e 100644 (file)
@@ -2792,6 +2792,11 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
                                     reloc_type[0] == BFD_RELOC_16_PCREL_S2,
                                     reloc_type[0]);
 
+         /* Tag symbols that have a R_MIPS16_26 relocation against them.  */
+         if (reloc_type[0] == BFD_RELOC_MIPS16_JMP
+             && ip->fixp[0]->fx_addsy)
+           *symbol_get_tc (ip->fixp[0]->fx_addsy) = 1;
+
          /* These relocations can have an addend that won't fit in
             4 octets for 64bit assembly.  */
          if (HAVE_64BIT_GPRS
@@ -13612,11 +13617,50 @@ mips_fix_adjustable (fixS *fixp)
     return 0;
 
 #ifdef OBJ_ELF
-  /* Don't adjust relocations against mips16 symbols, so that the linker
-     can find them if it needs to set up a stub.  */
+  /* R_MIPS16_26 relocations against non-MIPS16 functions might resolve
+     to a floating-point stub.  The same is true for non-R_MIPS16_26
+     relocations against MIPS16 functions; in this case, the stub becomes
+     the function's canonical address.
+
+     Floating-point stubs are stored in unique .mips16.call.* or
+     .mips16.fn.* sections.  If a stub T for function F is in section S,
+     the first relocation in section S must be against F; this is how the
+     linker determines the target function.  All relocations that might
+     resolve to T must also be against F.  We therefore have the following
+     restrictions, which are given in an intentionally-redundant way:
+
+       1. We cannot reduce R_MIPS16_26 relocations against non-MIPS16
+         symbols.
+
+       2. We cannot reduce a stub's relocations against non-MIPS16 symbols
+         if that stub might be used.
+
+       3. We cannot reduce non-R_MIPS16_26 relocations against MIPS16
+         symbols.
+
+       4. We cannot reduce a stub's relocations against MIPS16 symbols if
+         that stub might be used.
+
+     There is a further restriction:
+
+       5. We cannot reduce R_MIPS16_26 relocations against MIPS16 symbols
+         on targets with in-place addends; the relocation field cannot
+         encode the low bit.
+
+     For simplicity, we deal with (3)-(5) by not reducing _any_ relocation
+     against a MIPS16 symbol.
+
+     We deal with (1)-(2) by saying that, if there's a R_MIPS16_26
+     relocation against some symbol R, no relocation against R may be
+     reduced.  (Note that this deals with (2) as well as (1) because
+     relocations against global symbols will never be reduced on ELF
+     targets.)  This approach is a little simpler than trying to detect
+     stub sections, and gives the "all or nothing" per-symbol consistency
+     that we have for MIPS16 symbols.  */
   if (IS_ELF
-      && S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16
-      && fixp->fx_subsy == NULL)
+      && fixp->fx_subsy == NULL
+      && (S_GET_OTHER (fixp->fx_addsy) == STO_MIPS16
+         || *symbol_get_tc (fixp->fx_addsy)))
     return 0;
 #endif
 
index 5a1e830..117417c 100644 (file)
@@ -61,6 +61,9 @@ extern void mips_handle_align (struct frag *);
 struct insn_label_list;
 #define TC_SEGMENT_INFO_TYPE struct insn_label_list *
 
+/* This field is nonzero if the symbol is the target of a MIPS16 jump.  */
+#define TC_SYMFIELD_TYPE int
+
 /* Tell assembler that we have an itbl_mips.h header file to include.  */
 #define HAVE_ITBL_CPU
 
index 9cd711a..e3e557e 100644 (file)
@@ -1,3 +1,9 @@
+2007-06-25  Richard Sandiford  <richard@codesourcery.com>
+
+       * ld-mips-elf/mips16-local-stubs-1.s,
+       * ld-mips-elf/mips16-local-stubs-1.d: New tests.
+       * ld-mips-elf/mips-elf.exp: Run them.
+
 2007-06-19  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/4590
index d022c8d..eab8678 100644 (file)
@@ -269,3 +269,5 @@ set mips16_intermix_test {
 }
 
 run_ld_link_tests $mips16_intermix_test
+
+run_dump_test "mips16-local-stubs-1"
diff --git a/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d
new file mode 100644 (file)
index 0000000..9990493
--- /dev/null
@@ -0,0 +1,114 @@
+#name: MIPS16 interlinking for local functions 1
+#source: mips16-local-stubs-1.s
+#as: -mips4
+#ld: -Ttext 0x20000000 -e caller1
+#objdump: -dr
+#...
+Disassembly of section \.text:
+
+20000000 <f1>:
+20000000:      03e00008        jr      ra
+20000004:      00000000        nop
+
+20000008 <g1>:
+20000008:      03e00008        jr      ra
+2000000c:      00000000        nop
+
+20000010 <h1>:
+20000010:      e820            jr      ra
+20000012:      6500            nop
+
+20000014 <f2>:
+20000014:      03e00008        jr      ra
+20000018:      00000000        nop
+
+2000001c <g2>:
+2000001c:      03e00008        jr      ra
+20000020:      00000000        nop
+
+20000024 <h2>:
+20000024:      e820            jr      ra
+20000026:      6500            nop
+
+20000028 <f3>:
+20000028:      03e00008        jr      ra
+2000002c:      00000000        nop
+
+20000030 <g3>:
+20000030:      03e00008        jr      ra
+20000034:      00000000        nop
+
+20000038 <h3>:
+20000038:      e820            jr      ra
+2000003a:      6500            nop
+
+2000003c <caller1>:
+2000003c:      0c000000        jal     20000000 <f1>
+20000040:      00000000        nop
+20000044:      0c000005        jal     20000014 <f2>
+20000048:      00000000        nop
+2000004c:      0c000002        jal     20000008 <g1>
+20000050:      00000000        nop
+20000054:      0c000007        jal     2000001c <g2>
+20000058:      00000000        nop
+2000005c:      0c000024        jal     20000090 <stub_for_h1>
+20000060:      00000000        nop
+20000064:      0c000028        jal     200000a0 <stub_for_h2>
+20000068:      00000000        nop
+
+2000006c <caller2>:
+2000006c:      1c00 0030       jalx    200000c0 <stub_for_f1>
+20000070:      6500            nop
+20000072:      1c00 0038       jalx    200000e0 <stub_for_f2>
+20000076:      6500            nop
+20000078:      1c00 0034       jalx    200000d0 <stub_for_g1>
+2000007c:      6500            nop
+2000007e:      1c00 003c       jalx    200000f0 <stub_for_g2>
+20000082:      6500            nop
+20000084:      1800 0004       jal     20000010 <h1>
+20000088:      6500            nop
+2000008a:      1800 0009       jal     20000024 <h2>
+2000008e:      6500            nop
+
+20000090 <stub_for_h1>:
+20000090:      3c012000        lui     at,0x2000
+20000094:      24210011        addiu   at,at,17
+20000098:      00200008        jr      at
+2000009c:      00000000        nop
+
+200000a0 <stub_for_h2>:
+200000a0:      3c012000        lui     at,0x2000
+200000a4:      24210025        addiu   at,at,37
+200000a8:      00200008        jr      at
+200000ac:      00000000        nop
+
+# This isn't actually called, but is referenced from the .pdr section.
+200000b0 <stub_for_h3>:
+200000b0:      3c012000        lui     at,0x2000
+200000b4:      24210039        addiu   at,at,57
+200000b8:      00200008        jr      at
+200000bc:      00000000        nop
+
+200000c0 <stub_for_f1>:
+200000c0:      3c012000        lui     at,0x2000
+200000c4:      24210000        addiu   at,at,0
+200000c8:      00200008        jr      at
+200000cc:      00000000        nop
+
+200000d0 <stub_for_g1>:
+200000d0:      3c012000        lui     at,0x2000
+200000d4:      24210008        addiu   at,at,8
+200000d8:      00200008        jr      at
+200000dc:      00000000        nop
+
+200000e0 <stub_for_f2>:
+200000e0:      3c012000        lui     at,0x2000
+200000e4:      24210014        addiu   at,at,20
+200000e8:      00200008        jr      at
+200000ec:      00000000        nop
+
+200000f0 <stub_for_g2>:
+200000f0:      3c012000        lui     at,0x2000
+200000f4:      2421001c        addiu   at,at,28
+200000f8:      00200008        jr      at
+200000fc:      00000000        nop
diff --git a/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s
new file mode 100644 (file)
index 0000000..9904402
--- /dev/null
@@ -0,0 +1,49 @@
+       .macro  makestub,type,func,section
+       .text
+       .set    \type
+       .type   \func,@function
+       .ent    \func
+\func:
+       jr      $31
+       .end    \func
+
+       .section \section,"ax",@progbits
+       .set    nomips16
+       .type   stub_for_\func,@function
+       .ent    stub_for_\func
+stub_for_\func:
+       .set    noat
+       la      $1,\func
+       jr      $1
+       .set    at
+       .end    stub_for_\func
+       .endm
+
+       .macro  makestubs,id
+       makestub nomips16,f\id,.mips16.call.F\id
+       makestub nomips16,g\id,.mips16.call.fp.G\id
+       makestub mips16,h\id,.mips16.fn.H\id
+       .endm
+
+       .macro  makecaller,type,func
+       .text
+       .set    \type
+       .globl  \func
+       .type   \func,@function
+       .ent    \func
+\func:
+       jal     f1
+       jal     f2
+       jal     g1
+       jal     g2
+       jal     h1
+       jal     h2
+       .end    \func
+       .endm
+
+       makestubs 1
+       makestubs 2
+       makestubs 3
+
+       makecaller nomips16,caller1
+       makecaller mips16,caller2