From bccbc0aa84e92cb7d48e8221552bd4edcb876811 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 16 May 1996 19:57:12 +0000 Subject: [PATCH] * config/tc-sh.h (struct sh_segment_info_type): Define. (TC_SEGMENT_INFO_TYPE): Define. (sh_frob_label): Declare. (tc_frob_label): Define. (sh_flush_pending_output): Declare. (md_flush_pending_output): Define. * config/tc-sh.c (md_assemble): If relaxing, emit a R_SH_CODE reloc before the instruction if necessary. (sh_frob_label): New function. (sh_flush_pending_output): New function. (sh_coff_frob_file): Ignore ALIGN, CODE, DATA, and LABEL relocs when looking for the reloc for the target of .uses. (md_convert_frag): Fix printf format (%0xlx to 0x%lx). (sh_force_relocation): Force CODE, DATA, and LABEL relocs to be emitted. (md_apply_fix): Ignore CODE, DATA, and LABEL relocs. (sh_coff_reloc_mangle): Force CODE, DATA, and LABEL relocs to use the absolute symbol. --- gas/config/tc-sh.c | 60 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index 7a849a070e..9a406a6e8c 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -900,6 +900,15 @@ md_assemble (str) return; } + if (sh_relax + && ! seg_info (now_seg)->tc_segment_info_data.in_code) + { + /* Output a CODE reloc to tell the linker that the following + bytes are instructions, not data. */ + fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_CODE); + seg_info (now_seg)->tc_segment_info_data.in_code = 1; + } + if (opcode->arg[0] == A_BDISP12 || opcode->arg[0] == A_BDISP8) { @@ -930,6 +939,31 @@ md_assemble (str) } +/* This routine is called each time a label definition is seen. It + emits a R_SH_LABEL reloc if necessary. */ + +void +sh_frob_label () +{ + if (sh_relax + && seg_info (now_seg)->tc_segment_info_data.in_code) + fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_LABEL); +} + +/* This routine is called when the assembler is about to output some + data. It emits a R_SH_DATA reloc if necessary. */ + +void +sh_flush_pending_output () +{ + if (sh_relax + && seg_info (now_seg)->tc_segment_info_data.in_code) + { + fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_DATA); + seg_info (now_seg)->tc_segment_info_data.in_code = 0; + } +} + void DEFUN (tc_crawl_symbol_chain, (headers), object_headers * headers) @@ -1166,7 +1200,11 @@ sh_coff_frob_file () for (fscan = segment_info[iseg].fix_root; fscan != NULL; fscan = fscan->fx_next) - if (val == fscan->fx_frag->fr_address + fscan->fx_where) + if (val == fscan->fx_frag->fr_address + fscan->fx_where + && fscan->fx_r_type != R_SH_ALIGN + && fscan->fx_r_type != R_SH_CODE + && fscan->fx_r_type != R_SH_DATA + && fscan->fx_r_type != R_SH_LABEL) break; if (fscan == NULL) { @@ -1344,7 +1382,7 @@ md_convert_frag (headers, seg, fragP) case C (COND_JUMP, COND32): case C (COND_JUMP, UNDEF_WORD_DISP): if (fragP->fr_symbol == NULL) - as_bad ("at %0xlx, displacement overflows 8-bit field", + as_bad ("at 0x%lx, displacement overflows 8-bit field", (unsigned long) fragP->fr_address); else as_bad ("at 0x%lx, displacement to %sdefined symbol %s overflows 8-bit field ", @@ -1462,7 +1500,10 @@ sh_force_relocation (fix) return (fix->fx_pcrel || SWITCH_TABLE (fix) || fix->fx_r_type == R_SH_COUNT - || fix->fx_r_type == R_SH_ALIGN); + || fix->fx_r_type == R_SH_ALIGN + || fix->fx_r_type == R_SH_CODE + || fix->fx_r_type == R_SH_DATA + || fix->fx_r_type == R_SH_LABEL); } /* Apply a fixup to the object file. */ @@ -1593,6 +1634,9 @@ md_apply_fix (fixP, val) case R_SH_COUNT: case R_SH_ALIGN: + case R_SH_CODE: + case R_SH_DATA: + case R_SH_LABEL: /* Nothing to do here. */ break; @@ -1705,7 +1749,8 @@ sh_do_align (n, fill, len) #ifdef BFD_ASSEMBLER || (now_seg->flags & SEC_CODE) != 0 #endif - || strcmp (obj_segment_name (now_seg), ".init") == 0)) + || strcmp (obj_segment_name (now_seg), ".init") == 0) + && n > 1) { static const unsigned char big_nop_pattern[] = { 0x00, 0x09 }; static const unsigned char little_nop_pattern[] = { 0x09, 0x00 }; @@ -1804,6 +1849,13 @@ sh_coff_reloc_mangle (seg, fix, intr, paddr) /* This reloc is always absolute. */ symbol_ptr = NULL; } + else if (fix->fx_r_type == R_SH_CODE + || fix->fx_r_type == R_SH_DATA + || fix->fx_r_type == R_SH_LABEL) + { + /* These relocs are always absolute. */ + symbol_ptr = NULL; + } /* Turn the segment of the symbol into an offset. */ if (symbol_ptr != NULL) -- 2.34.1