(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.
+ 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)
{
if (opcode->arg[0] == A_BDISP12
|| opcode->arg[0] == A_BDISP8)
{
+/* 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)
void
DEFUN (tc_crawl_symbol_chain, (headers),
object_headers * headers)
for (fscan = segment_info[iseg].fix_root;
fscan != NULL;
fscan = fscan->fx_next)
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)
{
break;
if (fscan == NULL)
{
case C (COND_JUMP, COND32):
case C (COND_JUMP, UNDEF_WORD_DISP):
if (fragP->fr_symbol == NULL)
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 ",
(unsigned long) fragP->fr_address);
else
as_bad ("at 0x%lx, displacement to %sdefined symbol %s overflows 8-bit field ",
return (fix->fx_pcrel
|| SWITCH_TABLE (fix)
|| fix->fx_r_type == R_SH_COUNT
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. */
}
/* Apply a fixup to the object file. */
case R_SH_COUNT:
case R_SH_ALIGN:
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;
/* Nothing to do here. */
break;
#ifdef BFD_ASSEMBLER
|| (now_seg->flags & SEC_CODE) != 0
#endif
#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 };
{
static const unsigned char big_nop_pattern[] = { 0x00, 0x09 };
static const unsigned char little_nop_pattern[] = { 0x09, 0x00 };
/* This reloc is always absolute. */
symbol_ptr = NULL;
}
/* 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)
/* Turn the segment of the symbol into an offset. */
if (symbol_ptr != NULL)