aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2007-06-25 10:13:57 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2007-06-25 10:13:57 +0000
commitb314ec0eae7a778810550ccf87cd92eda7feaf2a (patch)
tree7c95af55b8663108c70d89bc4eb432cd3d5b4b47
parentb6fd0dfb46df6f46eace51d68b9de8318ebe3842 (diff)
downloadfsf-binutils-gdb-b314ec0eae7a778810550ccf87cd92eda7feaf2a.zip
fsf-binutils-gdb-b314ec0eae7a778810550ccf87cd92eda7feaf2a.tar.gz
fsf-binutils-gdb-b314ec0eae7a778810550ccf87cd92eda7feaf2a.tar.bz2
bfd/
* 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.
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elfxx-mips.c3
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/config/tc-mips.c52
-rw-r--r--gas/config/tc-mips.h3
-rw-r--r--ld/testsuite/ChangeLog6
-rw-r--r--ld/testsuite/ld-mips-elf/mips-elf.exp2
-rw-r--r--ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d114
-rw-r--r--ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s49
9 files changed, 235 insertions, 6 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 258fd6f..6b396db 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 1bccb33..dafd607 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -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))
diff --git a/gas/ChangeLog b/gas/ChangeLog
index c713436..19a28fa 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 47a4b3c..39f681e 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -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
diff --git a/gas/config/tc-mips.h b/gas/config/tc-mips.h
index 5a1e830..117417c 100644
--- a/gas/config/tc-mips.h
+++ b/gas/config/tc-mips.h
@@ -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
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 9cd711a..e3e557e 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index d022c8d..eab8678 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -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
index 0000000..9990493
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.d
@@ -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
index 0000000..9904402
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/mips16-local-stubs-1.s
@@ -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