diff options
Diffstat (limited to 'contrib/binutils/gas/config/tc-mips.c')
| -rw-r--r-- | contrib/binutils/gas/config/tc-mips.c | 121 |
1 files changed, 106 insertions, 15 deletions
diff --git a/contrib/binutils/gas/config/tc-mips.c b/contrib/binutils/gas/config/tc-mips.c index b8ef69eea3411..dc5ff68e3ec74 100644 --- a/contrib/binutils/gas/config/tc-mips.c +++ b/contrib/binutils/gas/config/tc-mips.c @@ -1216,6 +1216,12 @@ mips_target_format (void) case bfd_target_coff_flavour: return "pe-mips"; case bfd_target_elf_flavour: +#ifdef TE_VXWORKS + if (!HAVE_64BIT_OBJECTS && !HAVE_NEWABI) + return (target_big_endian + ? "elf32-bigmips-vxworks" + : "elf32-littlemips-vxworks"); +#endif #ifdef TE_TMIPS /* This is traditional mips. */ return (target_big_endian @@ -1556,9 +1562,9 @@ md_begin (void) if (OUTPUT_FLAVOR == bfd_target_elf_flavour) { - /* On a native system, sections must be aligned to 16 byte - boundaries. When configured for an embedded ELF target, we - don't bother. */ + /* On a native system other than VxWorks, sections must be aligned + to 16 byte boundaries. When configured for an embedded ELF + target, we don't bother. */ if (strcmp (TARGET_OS, "elf") != 0 && strcmp (TARGET_OS, "vxworks") != 0) { @@ -1719,8 +1725,12 @@ md_assemble (char *str) static inline bfd_boolean reloc_needs_lo_p (bfd_reloc_code_real_type reloc) { - return (reloc == BFD_RELOC_HI16_S - || reloc == BFD_RELOC_MIPS_GOT16); + return (HAVE_IN_PLACE_ADDENDS + && (reloc == BFD_RELOC_HI16_S + || reloc == BFD_RELOC_MIPS16_HI16_S + /* VxWorks R_MIPS_GOT16 relocs never need a matching %lo(); + all GOT16 relocations evaluate to "G". */ + || (reloc == BFD_RELOC_MIPS_GOT16 && mips_pic != VXWORKS_PIC))); } /* Return true if the given fixup is followed by a matching R_MIPS_LO16 @@ -1730,7 +1740,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); } @@ -2487,7 +2498,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)) ip->fixp[0]->fx_no_overflow = 1; if (mips_relax.sequence) @@ -5687,6 +5701,8 @@ macro (struct mips_cl_insn *ip) } } } + else if (mips_pic == VXWORKS_PIC) + as_bad (_("Non-PIC jump used in PIC library")); else abort (); @@ -9726,10 +9742,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; @@ -10537,10 +10577,25 @@ static const struct percent_op_match mips_percent_op[] = {"%highest", BFD_RELOC_MIPS_HIGHEST}, {"%higher", BFD_RELOC_MIPS_HIGHER}, {"%neg", BFD_RELOC_MIPS_SUB}, + {"%tlsgd", BFD_RELOC_MIPS_TLS_GD}, + {"%tlsldm", BFD_RELOC_MIPS_TLS_LDM}, + {"%dtprel_hi", BFD_RELOC_MIPS_TLS_DTPREL_HI16}, + {"%dtprel_lo", BFD_RELOC_MIPS_TLS_DTPREL_LO16}, + {"%tprel_hi", BFD_RELOC_MIPS_TLS_TPREL_HI16}, + {"%tprel_lo", BFD_RELOC_MIPS_TLS_TPREL_LO16}, + {"%gottprel", BFD_RELOC_MIPS_TLS_GOTTPREL}, #endif {"%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. Leave both *STR and *RELOC alone when returning false. */ @@ -10551,8 +10606,16 @@ parse_relocation (char **str, bfd_reloc_code_real_type *reloc) const struct percent_op_match *percent_op; size_t limit, i; - percent_op = mips_percent_op; - limit = ARRAY_SIZE (mips_percent_op); + 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 < limit; i++) if (strncasecmp (*str, percent_op[i].str, strlen (percent_op[i].str)) == 0) @@ -10902,6 +10965,8 @@ struct option md_longopts[] = {"mpdr", no_argument, NULL, OPTION_PDR}, #define OPTION_NO_PDR (OPTION_ELF_BASE + 10) {"mno-pdr", no_argument, NULL, OPTION_NO_PDR}, +#define OPTION_MVXWORKS_PIC (OPTION_ELF_BASE + 11) + {"mvxworks-pic", no_argument, NULL, OPTION_MVXWORKS_PIC}, #endif /* OBJ_ELF */ #define OPTION_MOCTEON_UNSUPPORTED (OPTION_MISC_BASE + 28) @@ -11297,6 +11362,10 @@ md_parse_option (int c, char *arg) case OPTION_NO_PDR: mips_flag_pdr = FALSE; break; + + case OPTION_MVXWORKS_PIC: + mips_pic = VXWORKS_PIC; + break; #endif /* OBJ_ELF */ default: @@ -11509,7 +11578,7 @@ mips_frob_file_before_adjust (void) } /* Sort any unmatched HI16 and GOT16 relocs so that they immediately precede - the corresponding LO16 reloc. This is called before md_apply_fix3 and + the corresponding LO16 reloc. This is called before md_apply_fix and tc_gen_reloc. Unmatched relocs can only be generated by use of explicit relocation operators. @@ -11594,7 +11663,8 @@ mips_frob_file (void) if (*pos == l->fixp) hi_pos = pos; - if ((*pos)->fx_r_type == BFD_RELOC_LO16 + if (((*pos)->fx_r_type == BFD_RELOC_LO16 + || (*pos)->fx_r_type == BFD_RELOC_MIPS16_LO16) && (*pos)->fx_addsy == l->fixp->fx_addsy && (*pos)->fx_offset >= l->fixp->fx_offset && (lo_pos == NULL @@ -11650,7 +11720,7 @@ mips_force_relocation (fixS *fixp) /* Apply a fixup to the object file. */ void -md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) +md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { bfd_byte *buf; long insn; @@ -11688,6 +11758,16 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) switch (fixP->fx_r_type) { + case BFD_RELOC_MIPS_TLS_GD: + case BFD_RELOC_MIPS_TLS_LDM: + case BFD_RELOC_MIPS_TLS_DTPREL_HI16: + case BFD_RELOC_MIPS_TLS_DTPREL_LO16: + case BFD_RELOC_MIPS_TLS_GOTTPREL: + case BFD_RELOC_MIPS_TLS_TPREL_HI16: + case BFD_RELOC_MIPS_TLS_TPREL_LO16: + S_SET_THREAD_LOCAL (fixP->fx_addsy); + /* fall through */ + case BFD_RELOC_MIPS_JMP: case BFD_RELOC_MIPS_SHIFT5: case BFD_RELOC_MIPS_SHIFT6: @@ -11716,6 +11796,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: /* Nothing needed to do. The value comes from the reloc entry */ break; @@ -11766,6 +11848,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 @@ -11809,7 +11892,7 @@ md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) && fixP->fx_done && fixP->fx_frag->fr_address >= text_section->vma && (fixP->fx_frag->fr_address - < text_section->vma + text_section->_raw_size) + < text_section->vma + bfd_get_section_size (text_section)) && ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */ || (insn & 0xffff0000) == 0x04010000 /* bgez $0 */ || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */ @@ -13423,6 +13506,9 @@ md_estimate_size_before_relax (fragS *fragp, asection *segtype) change = nopic_need_relax (fragp->fr_symbol, 0); else if (mips_pic == SVR4_PIC) change = pic_need_relax (fragp->fr_symbol, segtype); + else if (mips_pic == VXWORKS_PIC) + /* For vxworks, GOT16 relocations never have a corresponding LO16. */ + change = 0; else abort (); @@ -13468,6 +13554,7 @@ mips_fix_adjustable (fixS *fixp) this, it seems better not to force the issue, and instead keep the original symbol. This will work with either linker behavior. */ if ((fixp->fx_r_type == BFD_RELOC_LO16 + || fixp->fx_r_type == BFD_RELOC_MIPS16_LO16 || reloc_needs_lo_p (fixp->fx_r_type)) && HAVE_IN_PLACE_ADDENDS && (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) != 0) @@ -13988,6 +14075,10 @@ mips_define_label (symbolS *sym) l->label = sym; l->next = insn_labels; insn_labels = l; + +#ifdef OBJ_ELF + dwarf2_emit_label (sym); +#endif } #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) @@ -14218,7 +14309,7 @@ s_mips_file (int x ATTRIBUTE_UNUSED) if (filename != NULL && ! first_file_directive) { (void) new_logical_line (filename, -1); - s_app_file_string (filename); + s_app_file_string (filename, 0); } first_file_directive = 1; } |
