⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tc-sh.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
struct sh_count_relocs{  /* Symbol we are looking for.  */  symbolS *sym;  /* Count of relocs found.  */  int count;};/* Count the number of fixups in a section which refer to a particular   symbol.  When using BFD_ASSEMBLER, this is called via   bfd_map_over_sections.  */static voidsh_count_relocs (abfd, sec, data)     bfd *abfd ATTRIBUTE_UNUSED;     segT sec;     PTR data;{  struct sh_count_relocs *info = (struct sh_count_relocs *) data;  segment_info_type *seginfo;  symbolS *sym;  fixS *fix;  seginfo = seg_info (sec);  if (seginfo == NULL)    return;  sym = info->sym;  for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)    {      if (fix->fx_addsy == sym)	{	  ++info->count;	  fix->fx_tcbit = 1;	}    }}/* Handle the count relocs for a particular section.  When using   BFD_ASSEMBLER, this is called via bfd_map_over_sections.  */static voidsh_frob_section (abfd, sec, ignore)     bfd *abfd ATTRIBUTE_UNUSED;     segT sec;     PTR ignore ATTRIBUTE_UNUSED;{  segment_info_type *seginfo;  fixS *fix;  seginfo = seg_info (sec);  if (seginfo == NULL)    return;  for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)    {      symbolS *sym;      bfd_vma val;      fixS *fscan;      struct sh_count_relocs info;      if (fix->fx_r_type != BFD_RELOC_SH_USES)	continue;      /* The BFD_RELOC_SH_USES reloc should refer to a defined local	 symbol in the same section.  */      sym = fix->fx_addsy;      if (sym == NULL	  || fix->fx_subsy != NULL	  || fix->fx_addnumber != 0	  || S_GET_SEGMENT (sym) != sec#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF)	  || S_GET_STORAGE_CLASS (sym) == C_EXT#endif	  || S_IS_EXTERNAL (sym))	{	  as_warn_where (fix->fx_file, fix->fx_line,			 _(".uses does not refer to a local symbol in the same section"));	  continue;	}      /* Look through the fixups again, this time looking for one	 at the same location as sym.  */      val = S_GET_VALUE (sym);      for (fscan = seginfo->fix_root;	   fscan != NULL;	   fscan = fscan->fx_next)	if (val == fscan->fx_frag->fr_address + fscan->fx_where	    && fscan->fx_r_type != BFD_RELOC_SH_ALIGN	    && fscan->fx_r_type != BFD_RELOC_SH_CODE	    && fscan->fx_r_type != BFD_RELOC_SH_DATA	    && fscan->fx_r_type != BFD_RELOC_SH_LABEL)	  break;      if (fscan == NULL)	{	  as_warn_where (fix->fx_file, fix->fx_line,			 _("can't find fixup pointed to by .uses"));	  continue;	}      if (fscan->fx_tcbit)	{	  /* We've already done this one.  */	  continue;	}      /* The variable fscan should also be a fixup to a local symbol	 in the same section.  */      sym = fscan->fx_addsy;      if (sym == NULL	  || fscan->fx_subsy != NULL	  || fscan->fx_addnumber != 0	  || S_GET_SEGMENT (sym) != sec#if ! defined (BFD_ASSEMBLER) && defined (OBJ_COFF)	  || S_GET_STORAGE_CLASS (sym) == C_EXT#endif	  || S_IS_EXTERNAL (sym))	{	  as_warn_where (fix->fx_file, fix->fx_line,			 _(".uses target does not refer to a local symbol in the same section"));	  continue;	}      /* Now we look through all the fixups of all the sections,	 counting the number of times we find a reference to sym.  */      info.sym = sym;      info.count = 0;#ifdef BFD_ASSEMBLER      bfd_map_over_sections (stdoutput, sh_count_relocs, (PTR) &info);#else      {	int iscan;	for (iscan = SEG_E0; iscan < SEG_UNKNOWN; iscan++)	  sh_count_relocs ((bfd *) NULL, iscan, (PTR) &info);      }#endif      if (info.count < 1)	abort ();      /* Generate a BFD_RELOC_SH_COUNT fixup at the location of sym.	 We have already adjusted the value of sym to include the	 fragment address, so we undo that adjustment here.  */      subseg_change (sec, 0);      fix_new (symbol_get_frag (sym),	       S_GET_VALUE (sym) - symbol_get_frag (sym)->fr_address,	       4, &abs_symbol, info.count, 0, BFD_RELOC_SH_COUNT);    }}/* This function is called after the symbol table has been completed,   but before the relocs or section contents have been written out.   If we have seen any .uses pseudo-ops, they point to an instruction   which loads a register with the address of a function.  We look   through the fixups to find where the function address is being   loaded from.  We then generate a COUNT reloc giving the number of   times that function address is referred to.  The linker uses this   information when doing relaxing, to decide when it can eliminate   the stored function address entirely.  */voidsh_frob_file (){  if (! sh_relax)    return;#ifdef BFD_ASSEMBLER  bfd_map_over_sections (stdoutput, sh_frob_section, (PTR) NULL);#else  {    int iseg;    for (iseg = SEG_E0; iseg < SEG_UNKNOWN; iseg++)      sh_frob_section ((bfd *) NULL, iseg, (PTR) NULL);  }#endif}/* Called after relaxing.  Set the correct sizes of the fragments, and   create relocs so that md_apply_fix will fill in the correct values.  */voidmd_convert_frag (headers, seg, fragP)#ifdef BFD_ASSEMBLER     bfd *headers ATTRIBUTE_UNUSED;#else     object_headers *headers;#endif     segT seg;     fragS *fragP;{  int donerelax = 0;  switch (fragP->fr_subtype)    {    case C (COND_JUMP, COND8):    case C (COND_JUMP_DELAY, COND8):      subseg_change (seg, 0);      fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,	       1, BFD_RELOC_SH_PCDISP8BY2);      fragP->fr_fix += 2;      fragP->fr_var = 0;      break;    case C (UNCOND_JUMP, UNCOND12):      subseg_change (seg, 0);      fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,	       1, BFD_RELOC_SH_PCDISP12BY2);      fragP->fr_fix += 2;      fragP->fr_var = 0;      break;    case C (UNCOND_JUMP, UNCOND32):    case C (UNCOND_JUMP, UNDEF_WORD_DISP):      if (fragP->fr_symbol == NULL)	as_bad_where (fragP->fr_file, fragP->fr_line,		      _("displacement overflows 12-bit field"));      else if (S_IS_DEFINED (fragP->fr_symbol))	as_bad_where (fragP->fr_file, fragP->fr_line,		      _("displacement to defined symbol %s overflows 12-bit field"),		      S_GET_NAME (fragP->fr_symbol));      else	as_bad_where (fragP->fr_file, fragP->fr_line,		      _("displacement to undefined symbol %s overflows 12-bit field"),		      S_GET_NAME (fragP->fr_symbol));      /* Stabilize this frag, so we don't trip an assert.  */      fragP->fr_fix += fragP->fr_var;      fragP->fr_var = 0;      break;    case C (COND_JUMP, COND12):    case C (COND_JUMP_DELAY, COND12):      /* A bcond won't fit, so turn it into a b!cond; bra disp; nop.  */      /* I found that a relax failure for gcc.c-torture/execute/930628-1.c	 was due to gas incorrectly relaxing an out-of-range conditional	 branch with delay slot.  It turned:                     bf.s    L6              (slot mov.l   r12,@(44,r0))         into:2c:  8f 01 a0 8b     bf.s    32 <_main+32>   (slot bra       L6)30:  00 09           nop32:  10 cb           mov.l   r12,@(44,r0)         Therefore, branches with delay slots have to be handled	 differently from ones without delay slots.  */      {	unsigned char *buffer =	  (unsigned char *) (fragP->fr_fix + fragP->fr_literal);	int highbyte = target_big_endian ? 0 : 1;	int lowbyte = target_big_endian ? 1 : 0;	int delay = fragP->fr_subtype == C (COND_JUMP_DELAY, COND12);	/* Toggle the true/false bit of the bcond.  */	buffer[highbyte] ^= 0x2;	/* If this is a dalayed branch, we may not put the the bra in the	   slot.  So we change it to a non-delayed branch, like that:	   b! cond slot_label; bra disp; slot_label: slot_insn	   ??? We should try if swapping the conditional branch and	   its delay-slot insn already makes the branch reach.  */	/* Build a relocation to six / four bytes farther on.  */	subseg_change (seg, 0);	fix_new (fragP, fragP->fr_fix, 2,#ifdef BFD_ASSEMBLER		 section_symbol (seg),#else		 seg_info (seg)->dot,#endif		 fragP->fr_address + fragP->fr_fix + (delay ? 4 : 6),		 1, BFD_RELOC_SH_PCDISP8BY2);	/* Set up a jump instruction.  */	buffer[highbyte + 2] = 0xa0;	buffer[lowbyte + 2] = 0;	fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol,		 fragP->fr_offset, 1, BFD_RELOC_SH_PCDISP12BY2);	if (delay)	  {	    buffer[highbyte] &= ~0x4; /* Removes delay slot from branch.  */	    fragP->fr_fix += 4;	  }	else	  {	    /* Fill in a NOP instruction.  */	    buffer[highbyte + 4] = 0x0;	    buffer[lowbyte + 4] = 0x9;	    fragP->fr_fix += 6;	  }	fragP->fr_var = 0;	donerelax = 1;      }      break;    case C (COND_JUMP, COND32):    case C (COND_JUMP_DELAY, COND32):    case C (COND_JUMP, UNDEF_WORD_DISP):    case C (COND_JUMP_DELAY, UNDEF_WORD_DISP):      if (fragP->fr_symbol == NULL)	as_bad_where (fragP->fr_file, fragP->fr_line,		      _("displacement overflows 8-bit field"));      else if (S_IS_DEFINED (fragP->fr_symbol))	as_bad_where (fragP->fr_file, fragP->fr_line,		      _("displacement to defined symbol %s overflows 8-bit field"),		      S_GET_NAME (fragP->fr_symbol));      else	as_bad_where (fragP->fr_file, fragP->fr_line,		      _("displacement to undefined symbol %s overflows 8-bit field "),		      S_GET_NAME (fragP->fr_symbol));      /* Stabilize this frag, so we don't trip an assert.  */      fragP->fr_fix += fragP->fr_var;      fragP->fr_var = 0;      break;    default:      abort ();    }  if (donerelax && !sh_relax)    as_warn_where (fragP->fr_file, fragP->fr_line,		   _("overflow in branch to %s; converted into longer instruction sequence"),		   (fragP->fr_symbol != NULL		    ? S_GET_NAME (fragP->fr_symbol)		    : ""));}valueTmd_section_align (seg, size)     segT seg ATTRIBUTE_UNUSED;     valueT size;{#ifdef BFD_ASSEMBLER#ifdef OBJ_ELF  return size;#else /* ! OBJ_ELF */  return ((size + (1 << bfd_get_section_alignment (stdoutput, seg)) - 1)	  & (-1 << bfd_get_section_alignment (stdoutput, seg)));#endif /* ! OBJ_ELF */#else /* ! BFD_ASSEMBLER */  return ((size + (1 << section_alignment[(int) seg]) - 1)	  & (-1 << section_alignment[(int) seg]));#endif /* ! BFD_ASSEMBLER */}/* This static variable is set by s_uacons to tell sh_cons_align that   the expession does not need to be aligned.  */static int sh_no_align_cons = 0;/* This handles the unaligned space allocation pseudo-ops, such as   .uaword.  .uaword is just like .word, but the value does not need   to be aligned.  */static voids_uacons (bytes)     int bytes;{  /* Tell sh_cons_align not to align this value.  */  sh_no_align_cons = 1;  cons (bytes);}/* If a .word, et. al., pseud-op is seen, warn if the value is not   aligned correctly.  Note that this can cause warnings to be issued   when assembling initialized structured which were declared with the   packed attribute.  FIXME: Perhaps we should require an option to   enable this warning?  */voidsh_cons_align (nbytes)     int nbytes;{  int nalign;  char *p;  if (sh_no_align_cons)    {      /* This is an unaligned pseudo-op.  */      sh_no_align_cons = 0;      return;    }  nalign = 0;  while ((nbytes & 1) == 0)    {      ++nalign;      nbytes >>= 1;    }  if (nalign == 0)    return;  if (now_seg == absolute_section)    {      if ((abs_section_offset & ((1 << nalign) - 1)) != 0)	as_warn (_("misaligned data"));      return;    }  p = frag_var (rs_align_test, 1, 1, (relax_substateT) 0,		(symbolS *) NULL, (offsetT) nalign, (char *) NULL);  record_alignment (now_seg, nalign);}/* When relaxing, we need to output a reloc for any .align directive   that requests alignment to a four byte boundary or larger.  This is   also where we check for misaligned data.  */voidsh_handle_align (frag)     fragS *frag;{  int bytes = frag->fr_next->fr_address - frag->fr_address - frag->fr_fix;  if (frag->fr_type == rs_align_code)    {      static const unsigned char big_nop_pattern[] = { 0x00, 0x09 };      static const unsigned char little_nop_pattern[] = { 0x09, 0x00 };      char *p = frag->fr_literal + frag->fr_fix;      if (bytes & 1)	{	  *p++ = 0;	  bytes--;	  frag->fr_fix += 1;	}      if (target_big_endian)	{	  memcpy (p, big_nop_pattern, sizeof big_nop_pattern);	  frag->fr_var = sizeof big_nop_pattern;	}      else	{	  memcpy (p, little_nop_pattern, sizeof little_nop_pattern);	  frag->fr_var = sizeof little_nop_pattern;	}    }  else if (frag->fr_type == rs_align_test)    {      if (bytes != 0)	as_warn_where (frag->fr_file, frag->fr_line, _("misaligned data"));    }  if (sh_relax      && (frag->fr_type == rs_align	  || frag->fr_type == rs_align_code)      && frag->fr_address + frag->fr_fix > 0      && frag->fr_offset > 1      && now_seg != bss_section)    fix_new (frag, frag->fr_fix, 2, &abs_symbol, frag->fr_offset, 0,	     BFD_RELOC_SH_ALIGN);}/* This macro decides whether a particular reloc is an entry in a   switch table.  It is used when relaxing, because the linker needs   to know about all such entries so that it can adjust them if   necessary.  */#ifdef BFD_ASSEMBLER#define SWITCH_TABLE_CONS(fix) (0)#else#define SWITCH_TABLE_CONS(fix)				\  ((fix)->fx_r_type == 0				\   && ((fix)->fx_size == 2				\       || (fix)->fx_size == 1				\       || (fix)->fx_size == 4))#endif#define SWITCH_TABLE(fix)				\  ((fix)->fx_addsy != NULL				\   && (fix)->fx_subsy != NULL				\   && S_GET_SEGMENT ((fix)->fx_addsy) == text_section	\   && S_GET_SEGMENT ((fix)->fx_subsy) == text_section	\   && ((fix)->fx_r_type == BFD_RELOC_32			\       || (fix)->fx_r_type == BFD_RELOC_16		\       || (fix)->fx_r_type == BFD_RELOC_8		\       || SWITCH_TABLE_CONS (fix)))/* See whether we need to force a relocation into the output file.   This is used to force out switch and PC relative relocations when   relaxing.  */intsh_force_relocation (fix)     fixS *fix;{  if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT      || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY      || fix->fx_r_type == BFD_RELOC_SH_LOOP_START      || fix->fx_r_type == BFD_RELOC_SH_LOOP_END)    return 1;  if (! sh_relax)    return 0;  return (fix->fx_pcrel	  || SWITCH_TABLE (fix)	  || fix->fx_r_type == BFD_RELOC_SH_COUNT	  || fix->fx_r_type == BFD_RELOC_SH_ALIGN	  || fix->fx_r_type == BFD_RELOC_SH_CODE	  || fix->fx_r_type == BFD_RELOC_SH_DATA	  || fix->fx_r_type == BFD_RELOC_SH_LABEL);}#ifdef OBJ_ELFbooleansh_fix_adjustable (fixP)   fixS *fixP;{  if (fixP->fx_addsy == NULL)    return 1;  if (fixP->fx_r_type == BFD_RELOC_SH_PCDISP8BY2      || fixP->fx_r_type == BFD_RELOC_SH_PCDISP12BY2      || fixP->fx_r_type == BFD_RELOC_SH_PCRELIMM8BY2      || fixP->fx_r_type == BFD_RELOC_SH_PCRELIMM8BY4      || fixP->fx_r_type == BFD_RELOC_8_PCREL      || fixP->fx_r_type == BFD_RELOC_SH_SWITCH16      || fixP->fx_r_type == BFD_RELOC_SH_SWITCH32)    return 1;  if (! TC_RELOC_RTSYM_LOC_FIXUP (fixP)      || fixP->fx_r_type == BFD_RELOC_32_GOTOFF      || fixP->fx_r_type == BFD_RELOC_RVA)    return 0;  /* We need the symbol name for the VTABLE entries */  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)    return 0;  return 1;}voidsh_elf_final_processing (){  int val;  /* Set file-specific f

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -