aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-mips.c
diff options
context:
space:
mode:
authorChao-ying Fu <fu@mips.com>2010-01-13 22:30:53 +0000
committerChao-ying Fu <fu@mips.com>2010-01-13 22:30:53 +0000
commit38a7df635ca7d3db1986ed4397ab5bb4b23dc1a2 (patch)
tree00362ebf91b6ffeb0006f66be27c790da08ce56f /bfd/elfxx-mips.c
parent44272192844d2f863f04c7addf39302dca38ef33 (diff)
downloadgdb-38a7df635ca7d3db1986ed4397ab5bb4b23dc1a2.zip
gdb-38a7df635ca7d3db1986ed4397ab5bb4b23dc1a2.tar.gz
gdb-38a7df635ca7d3db1986ed4397ab5bb4b23dc1a2.tar.bz2
2010-01-13 Chao-ying Fu <fu@mips.com>
* elfxx-mips.c (JR_TO_B_P): New define to transform JR to B. It is true for all CPUs. (jal_reloc_p): New function. (mips_elf_calculate_relocation): Rename require_jalxp to cross_mode_jump_p. Update comment for CROSS_MODE_JUMP_P. Set up cross_mode_jump_p based on the mode change. (mips_elf_perform_relocation): Rename require_jalx to cross_mode_jump_p. Update comment for CROSS_MODE_JUMP_P. Test cross_mode_jump_p and jal_reloc_p to turn jal to jalx. Use !cross_mode_jump_p to guard conversion. Convert "jr t9" to "b", if possible. (_bfd_mips_elf_relocate_section): Rename require_jalx to cross_mode_jump_p. Pass &cross_mode_jump_p to call mips_elf_calculate_relocation. Pass cross_mode_jump_p to call mips_elf_perform_relocation.
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r--bfd/elfxx-mips.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index b649278..555f021 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -680,6 +680,11 @@ static bfd *reldyn_sorting_bfd;
all CPUs. */
#define JALR_TO_BAL_P(abfd) 1
+/* True if ABFD is for CPUs that are faster if JR is converted to B.
+ This should be safe for all architectures. We enable this predicate for
+ all CPUs. */
+#define JR_TO_B_P(abfd) 1
+
/* True if ABFD is a PIC object. */
#define PIC_OBJECT_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0)
@@ -1871,6 +1876,12 @@ mips16_call_reloc_p (int r_type)
return r_type == R_MIPS16_26 || r_type == R_MIPS16_CALL16;
}
+static inline bfd_boolean
+jal_reloc_p (int r_type)
+{
+ return r_type == R_MIPS_26 || r_type == R_MIPS16_26;
+}
+
void
_bfd_mips16_elf_reloc_unshuffle (bfd *abfd, int r_type,
bfd_boolean jal_shuffle, bfd_byte *data)
@@ -4771,8 +4782,8 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type)
RELOCATION; RELOCATION->R_ADDEND is ignored.
The result of the relocation calculation is stored in VALUEP.
- REQUIRE_JALXP indicates whether or not the opcode used with this
- relocation must be JALX.
+ On exit, set *CROSS_MODE_JUMP_P to true if the relocation field
+ is a MIPS16 jump to non-MIPS16 code, or vice versa.
This function returns bfd_reloc_continue if the caller need take no
further action regarding this relocation, bfd_reloc_notsupported if
@@ -4787,7 +4798,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
bfd_vma addend, reloc_howto_type *howto,
Elf_Internal_Sym *local_syms,
asection **local_sections, bfd_vma *valuep,
- const char **namep, bfd_boolean *require_jalxp,
+ const char **namep,
+ bfd_boolean *cross_mode_jump_p,
bfd_boolean save_addend)
{
/* The eventual value we will return. */
@@ -5076,10 +5088,11 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
+ h->la25_stub->offset);
/* Calls from 16-bit code to 32-bit code and vice versa require the
- special jalx instruction. */
- *require_jalxp = (!info->relocatable
- && (((r_type == R_MIPS16_26) && !target_is_16_bit_code_p)
- || ((r_type == R_MIPS_26) && target_is_16_bit_code_p)));
+ mode change. */
+ *cross_mode_jump_p = !info->relocatable
+ && ((r_type == R_MIPS16_26 && !target_is_16_bit_code_p)
+ || ((r_type == R_MIPS_26 || r_type == R_MIPS_JALR)
+ && target_is_16_bit_code_p));
local_p = mips_elf_local_relocation_p (input_bfd, relocation,
local_sections, TRUE);
@@ -5533,9 +5546,9 @@ mips_elf_obtain_contents (reloc_howto_type *howto,
/* It has been determined that the result of the RELOCATION is the
VALUE. Use HOWTO to place VALUE into the output file at the
appropriate position. The SECTION is the section to which the
- relocation applies. If REQUIRE_JALX is TRUE, then the opcode used
- for the relocation must be either JAL or JALX, and it is
- unconditionally converted to JALX.
+ relocation applies.
+ CROSS_MODE_JUMP_P is true if the relocation field
+ is a MIPS16 jump to non-MIPS16 code, or vice versa.
Returns FALSE if anything goes wrong. */
@@ -5545,7 +5558,7 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
const Elf_Internal_Rela *relocation,
bfd_vma value, bfd *input_bfd,
asection *input_section, bfd_byte *contents,
- bfd_boolean require_jalx)
+ bfd_boolean cross_mode_jump_p)
{
bfd_vma x;
bfd_byte *location;
@@ -5566,7 +5579,7 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
x |= (value & howto->dst_mask);
/* If required, turn JAL into JALX. */
- if (require_jalx)
+ if (cross_mode_jump_p && jal_reloc_p (r_type))
{
bfd_boolean ok;
bfd_vma opcode = x >> 26;
@@ -5600,15 +5613,19 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
}
- /* Try converting JAL and JALR to BAL, if the target is in range. */
+ /* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in
+ range. */
if (!info->relocatable
- && !require_jalx
+ && !cross_mode_jump_p
&& ((JAL_TO_BAL_P (input_bfd)
&& r_type == R_MIPS_26
&& (x >> 26) == 0x3) /* jal addr */
|| (JALR_TO_BAL_P (input_bfd)
&& r_type == R_MIPS_JALR
- && x == 0x0320f809))) /* jalr t9 */
+ && x == 0x0320f809) /* jalr t9 */
+ || (JR_TO_B_P (input_bfd)
+ && r_type == R_MIPS_JALR
+ && x == 0x03200008))) /* jr t9 */
{
bfd_vma addr;
bfd_vma dest;
@@ -5624,7 +5641,12 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
dest = value;
off = dest - addr;
if (off <= 0x1ffff && off >= -0x20000)
- x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff); /* bal addr */
+ {
+ if (x == 0x03200008) /* jr t9 */
+ x = 0x10000000 | (((bfd_vma) off >> 2) & 0xffff); /* b addr */
+ else
+ x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff); /* bal addr */
+ }
}
/* Put the value into the output. */
@@ -8886,7 +8908,7 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
const char *name;
bfd_vma value = 0;
reloc_howto_type *howto;
- bfd_boolean require_jalx;
+ bfd_boolean cross_mode_jump_p;
/* TRUE if the relocation is a RELA relocation, rather than a
REL relocation. */
bfd_boolean rela_relocation_p = TRUE;
@@ -9086,7 +9108,7 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
input_section, info, rel,
addend, howto, local_syms,
local_sections, &value,
- &name, &require_jalx,
+ &name, &cross_mode_jump_p,
use_saved_addend_p))
{
case bfd_reloc_continue:
@@ -9198,7 +9220,7 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
/* Actually perform the relocation. */
if (! mips_elf_perform_relocation (info, howto, rel, value,
input_bfd, input_section,
- contents, require_jalx))
+ contents, cross_mode_jump_p))
return FALSE;
}