From 9da4c5d13035754ce8cdd2435b5a763ced2313bb Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 22 Oct 1994 00:51:53 +0000 Subject: [PATCH 1/1] * config/tc-mips.c (md_pseudo_table): If OBJ_ELF, handle .section. (s_elf_section): New static function. * ecoff.c (ecoff_build_symbols): Don't abort if we don't recognize the section when setting the storage class; default to sc_Data. --- gas/ChangeLog | 7 +++++ gas/config/tc-mips.c | 73 +++++++++++++++++++++++++++++++++++++++++--- gas/ecoff.c | 9 ++++-- 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 439d453165..a589c554b9 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +Fri Oct 21 20:42:29 1994 Ian Lance Taylor + + * config/tc-mips.c (md_pseudo_table): If OBJ_ELF, handle .section. + (s_elf_section): New static function. + * ecoff.c (ecoff_build_symbols): Don't abort if we don't recognize + the section when setting the storage class; default to sc_Data. + Thu Oct 20 00:43:38 1994 Jeff Law (law@snake.cs.utah.edu) * config/tc-hppa.c (md_apply_fix): Set new_val to 8 for all diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 5e733e9d34..0fc795d5eb 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -23,6 +23,7 @@ #include "as.h" #include "config.h" +#include "subsegs.h" #include @@ -394,6 +395,9 @@ static void s_loc PARAMS ((int)); static void s_mask PARAMS ((char)); #endif #endif +#ifdef OBJ_ELF +static void s_elf_section PARAMS ((int)); +#endif /* Pseudo-op table. @@ -474,6 +478,11 @@ const pseudo_typeS md_pseudo_table[] = {"verstamp", s_ignore, 0}, #endif +#ifdef OBJ_ELF + /* We need to tweak the ELF ".section" pseudo-op a bit. */ + {"section", s_elf_section, 0}, +#endif + /* Sentinel. */ {NULL} }; @@ -4700,8 +4709,9 @@ mips_ip (str, ip) || offset_expr.X_add_number < -0x8000) && (mips_pic != EMBEDDED_PIC || offset_expr.X_op != O_subtract - || ! S_IS_LOCAL (offset_expr.X_add_symbol) - || ! S_IS_LOCAL (offset_expr.X_op_symbol))) + || now_seg != text_section + || (S_GET_SEGMENT (offset_expr.X_op_symbol) + != text_section))) break; offset_reloc = BFD_RELOC_LO16; @@ -5398,8 +5408,6 @@ md_apply_fix (fixP, valueP) as_warn_where (fixP->fx_file, fixP->fx_line, "Branch to odd address (%lx)", value); value >>= 2; - if (value < -0x8000 || value >= 0x8000) - as_bad_where (fixP->fx_file, fixP->fx_line, "Relocation overflow"); /* update old instruction data */ buf = (unsigned char *) (fixP->fx_where + fixP->fx_frag->fr_literal); @@ -5417,7 +5425,46 @@ md_apply_fix (fixP, valueP) internalError (); return 0; } - insn |= value & 0xFFFF; + + if (value >= -0x8000 && value < 0x8000) + insn |= value & 0xffff; + else + { + /* The branch offset is too large. If this is an + unconditional branch, and we are not generating PIC code, + we can convert it to an absolute jump instruction. */ + if (mips_pic == NO_PIC + && fixP->fx_done + && fixP->fx_frag->fr_address >= text_section->vma + && (fixP->fx_frag->fr_address + < text_section->vma + text_section->_raw_size) + && ((insn & 0xffff0000) == 0x10000000 /* beq $0,$0 */ + || (insn & 0xffff0000) == 0x04010000 /* bgez $0 */ + || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */ + { + if ((insn & 0xffff0000) == 0x04110000) /* bgezal $0 */ + insn = 0x0c000000; /* jal */ + else + insn = 0x08000000; /* j */ + fixP->fx_r_type = BFD_RELOC_MIPS_JMP; + fixP->fx_done = 0; + fixP->fx_addsy = section_symbol (text_section); + fixP->fx_addnumber = (value << 2) + md_pcrel_from (fixP); + } + else + { + /* FIXME. It would be possible in principle to handle + conditional branches which overflow. They could be + transformed into a branch around a jump. This would + require setting up variant frags for each different + branch type. The native MIPS assembler attempts to + handle these cases, but it appears to do it + incorrectly. */ + as_bad_where (fixP->fx_file, fixP->fx_line, + "Relocation overflow"); + } + } + md_number_to_chars ((char *) buf, (valueT) insn, 4); break; @@ -5677,6 +5724,22 @@ s_change_sec (sec) auto_align = 1; } +#ifdef OBJ_ELF + +/* Handle the ELF .section pseudo-op. This is a wrapper around + obj_elf_section. */ + +static void +s_elf_section (x) + int x; +{ + mips_emit_delays (); + obj_elf_section (x); + auto_align = 1; +} + +#endif /* OBJ_ELF */ + static void s_cons (log_size) int log_size; diff --git a/gas/ecoff.c b/gas/ecoff.c index a0644066c8..fbd8683577 100644 --- a/gas/ecoff.c +++ b/gas/ecoff.c @@ -3953,7 +3953,12 @@ ecoff_build_symbols (backend, buf, bufend, offset) else if (seg == &bfd_abs_section) sc = sc_Abs; else - abort (); + { + /* This must be a user named section. + This is not possible in ECOFF, but it + is in ELF. */ + sc = sc_Data; + } sym_ptr->ecoff_sym.asym.st = (int) st; sym_ptr->ecoff_sym.asym.sc = (int) sc; @@ -5153,7 +5158,7 @@ ecoff_generate_asm_lineno (filename, lineno) ecoff_generate_asm_line_stab(filename, lineno); */ - if (strcmp (current_stabs_filename, filename)) + if (current_stabs_filename == (char *)NULL || strcmp (current_stabs_filename, filename)) { add_file (filename, 0); generate_asm_lineno = 1; -- 2.34.1