diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2005-02-15 19:57:54 +0000 |
---|---|---|
committer | Maciej W. Rozycki <macro@linux-mips.org> | 2005-02-15 19:57:54 +0000 |
commit | d6f165938798bf2f7b13505700dd70894ba4ce17 (patch) | |
tree | 478fac8075303061d4ce0c9162ef372ddab2e977 /gas/config/tc-mips.c | |
parent | 77ef991de16155506c1057b349e482a86c376df8 (diff) | |
download | fsf-binutils-gdb-d6f165938798bf2f7b13505700dd70894ba4ce17.zip fsf-binutils-gdb-d6f165938798bf2f7b13505700dd70894ba4ce17.tar.gz fsf-binutils-gdb-d6f165938798bf2f7b13505700dd70894ba4ce17.tar.bz2 |
bfd/:
2005-02-15 Nigel Stephens <nigel@mips.com>
Maciej W. Rozycki <macro@mips.com>
* elf32-mips.c (elf_mips16_howto_table_rel): New array for MIPS16
reloc howtos. Add R_MIPS16_HI16 and R_MIPS16_LO16 relocs and
R_MIPS16_GOT16 and R_MIPS16_CALL16 placeholders.
(elf_mips16_jump_howto): Move into elf_mips16_howto_table_rel.
(elf_mips16_gprel_howto): Likewise. Redefine src_mask and
dst_mask.
(mips16_gprel_reloc): Remove bit shuffling; call
_bfd_mips16_elf_reloc_unshuffle(), _bfd_mips_elf_gprel16_with_gp()
and _bfd_mips16_elf_reloc_shuffle() instead.
(mips16_reloc_map): New reloc map for MIPS16 relocs.
(bfd_elf32_bfd_reloc_type_lookup): Use mips16_reloc_map for MIPS16
relocs.
(mips_elf32_rtype_to_howto): Fetch MIPS16 howtos from
elf_mips16_howto_table_rel.
* elf64-mips.c (mips16_elf64_howto_table_rel): New array for
MIPS16 REL reloc howtos. Add R_MIPS16_HI16 and R_MIPS16_LO16
relocs and R_MIPS16_GOT16 and R_MIPS16_CALL16 placeholders.
(elf_mips16_jump_howto): Move into mips16_elf64_howto_table_rel.
(elf_mips16_gprel_howto): Likewise. Redefine src_mask and
dst_mask.
(mips16_elf64_howto_table_rela): New array for MIPS16 RELA
reloc howtos. Add R_MIPS16_26, R_MIPS16_GPREL, R_MIPS16_HI16 and
R_MIPS16_LO16 relocs and R_MIPS16_GOT16 and R_MIPS16_CALL16
placeholders.
(mips16_gprel_reloc): Remove bit shuffling; call
_bfd_mips16_elf_reloc_unshuffle(), _bfd_mips_elf_gprel16_with_gp()
and _bfd_mips16_elf_reloc_shuffle() instead.
(mips16_reloc_map): New reloc map for MIPS16 relocs.
(bfd_elf64_bfd_reloc_type_lookup): Use mips16_reloc_map for MIPS16
relocs.
(mips_elf64_rtype_to_howto): Fetch MIPS16 howtos from
mips16_elf64_howto_table_rela or mips16_elf64_howto_table_rel.
* elfn32-mips.c (elf_mips16_howto_table_rel): New array for MIPS16
REL reloc howtos. Add R_MIPS16_HI16 and R_MIPS16_LO16 relocs and
R_MIPS16_GOT16 and R_MIPS16_CALL16 placeholders.
(elf_mips16_jump_howto): Move into elf_mips16_howto_table_rel.
(elf_mips16_gprel_howto): Likewise. Redefine src_mask and
dst_mask.
(mips16_gprel_reloc): Remove bit shuffling; call
_bfd_mips16_elf_reloc_unshuffle(), _bfd_mips_elf_gprel16_with_gp()
and _bfd_mips16_elf_reloc_shuffle() instead.
(mips16_reloc_map): New reloc map for MIPS16 relocs.
(bfd_elf32_bfd_reloc_type_lookup): Use mips16_reloc_map for MIPS16
relocs.
(mips_elf_n32_rtype_to_howto): Fetch MIPS16 howtos from
elf_mips16_howto_table_rela or elf_mips16_howto_table_rel.
* elfxx-mips.c (_bfd_mips16_elf_reloc_unshuffle): New function to
handle bit shuffling for MIPS16 relocs.
(_bfd_mips16_elf_reloc_shuffle): Likewise.
(_bfd_mips_elf_lo16_reloc): Use _bfd_mips16_elf_reloc_unshuffle()
and _bfd_mips16_elf_reloc_shuffle().
(_bfd_mips_elf_generic_reloc): Likewise.
(mips_elf_calculate_relocation): Likewise. Handle R_MIPS16_HI16
and R_MIPS16_LO16.
(mips_elf_obtain_contents): Remove bit shuffling.
(mips_elf_perform_relocation): Likewise; call
_bfd_mips16_elf_reloc_unshuffle() and _bfd_mips16_elf_reloc_shuffle()
instead.
(_bfd_mips_elf_relocate_section): Likewise. Handle R_MIPS16_HI16
and R_MIPS16_LO16.
* elfxx-mips.h (_bfd_mips16_elf_reloc_unshuffle): Declare.
(_bfd_mips16_elf_reloc_shuffle): Likewise.
* reloc.c (BFD_RELOC_MIPS16_HI16): New reloc.
(BFD_RELOC_MIPS16_HI16_S): Likewise.
(BFD_RELOC_MIPS16_LO16): Likewise.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/:
2005-02-15 Nigel Stephens <nigel@mips.com>
Maciej W. Rozycki <macro@mips.com>
* config/tc-mips.c (reloc_needs_lo_p): Handle
BFD_RELOC_MIPS16_HI16_S.
(fixup_has_matching_lo_p): Handle BFD_RELOC_MIPS16_LO16.
(append_insn): Add BFD_RELOC_MIPS16_GPREL, BFD_RELOC_MIPS16_HI16_S
and BFD_RELOC_MIPS16_LO16 to relocs to suppress overflow
complaints on.
(mips16_ip): Resolve BFD_RELOC_MIPS16_HI16_S,
BFD_RELOC_MIPS16_HI16 and BFD_RELOC_MIPS16_LO16 for constants.
Call my_getSmallExpression() to parse percent operators.
(percent_op_match, mips_percent_op): Separate definitions.
(mips16_percent_op): Define percent operators for the MIPS16 mode.
(parse_relocation): Handle the MIPS16 mode using
mips16_percent_op.
(md_apply_fix3): Handle BFD_RELOC_MIPS16_HI16,
BFD_RELOC_MIPS16_HI16_S and BFD_RELOC_MIPS16_LO16.
gas/testsuite/:
2005-02-15 Nigel Stephens <nigel@mips.com>
Maciej W. Rozycki <macro@mips.com>
* gas/mips/mips16-hilo.d: New test for the R_MIPS16_HI16 and
R_MIPS16_LO16 relocs.
* gas/mips/mips16-hilo-n32.d: Likewise, for the n32 ABI.
* gas/mips/mips16-hilo.s: Source for the new tests.
* gas/mips/mips.exp: Run the new tests.
include/:
2005-02-15 Nigel Stephens <nigel@mips.com>
Maciej W. Rozycki <macro@mips.com>
* elf/mips.h (R_MIPS16_GOT16): New reloc code.
(R_MIPS16_CALL16): Likewise.
(R_MIPS16_HI16): Likewise.
(R_MIPS16_LO16): Likewise.
(R_MIPS16_min): New fake reloc code.
(R_MIPS16_max): Likewise.
ld/testsuite/:
2005-02-15 Nigel Stephens <nigel@mips.com>
Maciej W. Rozycki <macro@mips.com>
* ld-mips-elf/mips16-hilo.d: New test for the R_MIPS16_HI16 and
R_MIPS16_LO16 relocs.
* ld-mips-elf/mips16-hilo-n32.d: Likewise, for the n32 ABI.
* ld-mips-elf/mips16-hilo.s: Auxiliary source for the new tests.
* ld-mips-elf/mips-elf.exp: Run the new tests.
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r-- | gas/config/tc-mips.c | 116 |
1 files changed, 84 insertions, 32 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index d3cf055..834ecd9 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -1407,7 +1407,8 @@ reloc_needs_lo_p (bfd_reloc_code_real_type reloc) { return (HAVE_IN_PLACE_ADDENDS && (reloc == BFD_RELOC_HI16_S - || reloc == BFD_RELOC_MIPS_GOT16)); + || reloc == BFD_RELOC_MIPS_GOT16 + || reloc == BFD_RELOC_MIPS16_HI16_S)); } /* Return true if the given fixup is followed by a matching R_MIPS_LO16 @@ -1417,7 +1418,8 @@ static inline bfd_boolean fixup_has_matching_lo_p (fixS *fixp) { return (fixp->fx_next != NULL - && fixp->fx_next->fx_r_type == BFD_RELOC_LO16 + && (fixp->fx_next->fx_r_type == BFD_RELOC_LO16 + || fixp->fx_next->fx_r_type == BFD_RELOC_MIPS16_LO16) && fixp->fx_addsy == fixp->fx_next->fx_addsy && fixp->fx_offset == fixp->fx_next->fx_offset); } @@ -2194,7 +2196,10 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, || reloc_type[0] == BFD_RELOC_MIPS_HIGHER || reloc_type[0] == BFD_RELOC_MIPS_SCN_DISP || reloc_type[0] == BFD_RELOC_MIPS_REL16 - || reloc_type[0] == BFD_RELOC_MIPS_RELGOT)) + || reloc_type[0] == BFD_RELOC_MIPS_RELGOT + || reloc_type[0] == BFD_RELOC_MIPS16_GPREL + || reloc_type[0] == BFD_RELOC_MIPS16_HI16_S + || reloc_type[0] == BFD_RELOC_MIPS16_LO16)) fixp[0]->fx_no_overflow = 1; if (mips_relax.sequence) @@ -9097,6 +9102,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip) unsigned int regno; unsigned int lastregno = 0; char *s_reset; + size_t i; insn_error = NULL; @@ -9183,8 +9189,34 @@ mips16_ip (char *str, struct mips_cl_insn *ip) && *imm_reloc > BFD_RELOC_UNUSED && insn->pinfo != INSN_MACRO) { + valueT tmp; + + switch (*offset_reloc) + { + case BFD_RELOC_MIPS16_HI16_S: + tmp = (imm_expr.X_add_number + 0x8000) >> 16; + break; + + case BFD_RELOC_MIPS16_HI16: + tmp = imm_expr.X_add_number >> 16; + break; + + case BFD_RELOC_MIPS16_LO16: + tmp = ((imm_expr.X_add_number + 0x8000) & 0xffff) + - 0x8000; + break; + + case BFD_RELOC_UNUSED: + tmp = imm_expr.X_add_number; + break; + + default: + internalError (); + } + *offset_reloc = BFD_RELOC_UNUSED; + mips16_immed (NULL, 0, *imm_reloc - BFD_RELOC_UNUSED, - imm_expr.X_add_number, TRUE, mips16_small, + tmp, TRUE, mips16_small, mips16_ext, &ip->insn_opcode, &ip->use_extend, &ip->extend); imm_expr.X_op = O_absent; @@ -9395,47 +9427,43 @@ mips16_ip (char *str, struct mips_cl_insn *ip) } break; - case '<': - case '>': - case '[': - case ']': - case '4': case '5': case 'H': case 'W': case 'D': case 'j': - case '8': case 'V': case 'C': case 'U': case 'k': case 'K': - if (s[0] == '%' - && strncmp (s + 1, "gprel(", sizeof "gprel(" - 1) == 0) + i = my_getSmallExpression (&imm_expr, imm_reloc, s); + if (i > 0) { - /* This is %gprel(SYMBOL). We need to read SYMBOL, - and generate the appropriate reloc. If the text - inside %gprel is not a symbol name with an - optional offset, then we generate a normal reloc - and will probably fail later. */ - my_getExpression (&imm_expr, s + sizeof "%gprel" - 1); - if (imm_expr.X_op == O_symbol) + if (imm_expr.X_op != O_constant) { mips16_ext = TRUE; - *imm_reloc = BFD_RELOC_MIPS16_GPREL; - s = expr_end; ip->use_extend = TRUE; ip->extend = 0; - continue; } + else + { + /* We need to relax this instruction. */ + *offset_reloc = *imm_reloc; + *imm_reloc = (int) BFD_RELOC_UNUSED + c; + } + s = expr_end; + continue; } - else - { - /* Just pick up a normal expression. */ - my_getExpression (&imm_expr, s); - } - + *imm_reloc = BFD_RELOC_UNUSED; + /* Fall through. */ + case '<': + case '>': + case '[': + case ']': + case '4': + case '8': + my_getExpression (&imm_expr, s); if (imm_expr.X_op == O_register) { /* What we thought was an expression turned out to @@ -9797,11 +9825,13 @@ mips16_immed (char *file, unsigned int line, int type, offsetT val, } } -static const struct percent_op_match +struct percent_op_match { const char *str; bfd_reloc_code_real_type reloc; -} percent_op[] = +}; + +static const struct percent_op_match mips_percent_op[] = { {"%lo", BFD_RELOC_LO16}, #ifdef OBJ_ELF @@ -9823,6 +9853,13 @@ static const struct percent_op_match {"%hi", BFD_RELOC_HI16_S} }; +static const struct percent_op_match mips16_percent_op[] = +{ + {"%lo", BFD_RELOC_MIPS16_LO16}, + {"%gprel", BFD_RELOC_MIPS16_GPREL}, + {"%hi", BFD_RELOC_MIPS16_HI16_S} +}; + /* Return true if *STR points to a relocation operator. When returning true, move *STR over the operator and store its relocation code in *RELOC. @@ -9831,9 +9868,21 @@ static const struct percent_op_match static bfd_boolean parse_relocation (char **str, bfd_reloc_code_real_type *reloc) { - size_t i; + const struct percent_op_match *percent_op; + size_t limit, i; + + if (mips_opts.mips16) + { + percent_op = mips16_percent_op; + limit = ARRAY_SIZE (mips16_percent_op); + } + else + { + percent_op = mips_percent_op; + limit = ARRAY_SIZE (mips_percent_op); + } - for (i = 0; i < ARRAY_SIZE (percent_op); i++) + for (i = 0; i < limit; i++) if (strncasecmp (*str, percent_op[i].str, strlen (percent_op[i].str)) == 0) { *str += strlen (percent_op[i].str); @@ -11000,6 +11049,8 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_MIPS_CALL_HI16: case BFD_RELOC_MIPS_CALL_LO16: case BFD_RELOC_MIPS16_GPREL: + case BFD_RELOC_MIPS16_HI16: + case BFD_RELOC_MIPS16_HI16_S: assert (! fixP->fx_pcrel); /* Nothing needed to do. The value comes from the reloc entry */ break; @@ -11051,6 +11102,7 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_LO16: + case BFD_RELOC_MIPS16_LO16: /* FIXME: Now that embedded-PIC is gone, some of this code/comment may be safe to remove, but if so it's not obvious. */ /* When handling an embedded PIC switch statement, we can wind |