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

📄 elf32-m32r.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
	      if (!((*info->callbacks->warning)		    (info, errmsg, name, input_bfd, input_section,		     offset)))		return false;	      break;	    }	}    }  return ret;}#if 0 /* relaxing not supported yet *//* This function handles relaxing for the m32r.   Relaxing on the m32r is tricky because of instruction alignment   requirements (4 byte instructions must be aligned on 4 byte boundaries).   The following relaxing opportunities are handled:   seth/add3/jl -> bl24 or bl8   seth/add3 -> ld24   It would be nice to handle bl24 -> bl8 but given:   - 4 byte insns must be on 4 byte boundaries   - branch instructions only branch to insns on 4 byte boundaries   this isn't much of a win because the insn in the 2 "deleted" bytes   must become a nop.  With some complexity some real relaxation could be   done but the frequency just wouldn't make it worth it; it's better to   try to do all the code compaction one can elsewhere.   When the chip supports parallel 16 bit insns, things may change.*/static booleanm32r_elf_relax_section (abfd, sec, link_info, again)     bfd *abfd;     asection *sec;     struct bfd_link_info *link_info;     boolean *again;{  Elf_Internal_Shdr *symtab_hdr;  /* The Rela structures are used here because that's what     _bfd_elf32_link_read_relocs uses [for convenience - it sets the addend     field to 0].  */  Elf_Internal_Rela *internal_relocs;  Elf_Internal_Rela *free_relocs = NULL;  Elf_Internal_Rela *irel, *irelend;  bfd_byte *contents = NULL;  bfd_byte *free_contents = NULL;  Elf32_External_Sym *extsyms = NULL;  Elf32_External_Sym *free_extsyms = NULL;  /* Assume nothing changes.  */  *again = false;  /* We don't have to do anything for a relocateable link, if     this section does not have relocs, or if this is not a     code section.  */  if (link_info->relocateable      || (sec->flags & SEC_RELOC) == 0      || sec->reloc_count == 0      || (sec->flags & SEC_CODE) == 0      || 0 /* FIXME: check SHF_M32R_CAN_RELAX */)    return true;  /* If this is the first time we have been called for this section,     initialize the cooked size.  */  if (sec->_cooked_size == 0)    sec->_cooked_size = sec->_raw_size;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  /* Get a copy of the native relocations.  */  internal_relocs = (_bfd_elf32_link_read_relocs		     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,		      link_info->keep_memory));  if (internal_relocs == NULL)    goto error_return;  if (! link_info->keep_memory)    free_relocs = internal_relocs;  /* Walk through them looking for relaxing opportunities.  */  irelend = internal_relocs + sec->reloc_count;  for (irel = internal_relocs; irel < irelend; irel++)    {      bfd_vma symval;      /* If this isn't something that can be relaxed, then ignore	 this reloc.  */      if (ELF32_R_TYPE (irel->r_info) != (int) R_M32R_HI16_SLO)	continue;      /* Get the section contents if we haven't done so already.  */      if (contents == NULL)	{	  /* Get cached copy if it exists.  */	  if (elf_section_data (sec)->this_hdr.contents != NULL)	    contents = elf_section_data (sec)->this_hdr.contents;	  else	    {	      /* Go get them off disk.  */	      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);	      if (contents == NULL)		goto error_return;	      free_contents = contents;	      if (! bfd_get_section_contents (abfd, sec, contents,					      (file_ptr) 0, sec->_raw_size))		goto error_return;	    }	}      /* Read this BFD's symbols if we haven't done so already.  */      if (extsyms == NULL)	{	  /* Get cached copy if it exists.  */	  if (symtab_hdr->contents != NULL)	    extsyms = (Elf32_External_Sym *) symtab_hdr->contents;	  else	    {	      /* Go get them off disk.  */	      extsyms = ((Elf32_External_Sym *)			 bfd_malloc (symtab_hdr->sh_size));	      if (extsyms == NULL)		goto error_return;	      free_extsyms = extsyms;	      if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0		  || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)		      != symtab_hdr->sh_size))		goto error_return;	    }	}      /* Get the value of the symbol referred to by the reloc.  */      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)	{	  Elf_Internal_Sym isym;	  asection *sym_sec;	  /* A local symbol.  */	  bfd_elf32_swap_symbol_in (abfd,				    extsyms + ELF32_R_SYM (irel->r_info),				    &isym);	  sym_sec = bfd_section_from_elf_index (abfd, isym.st_shndx);	  symval = (isym.st_value		    + sym_sec->output_section->vma		    + sym_sec->output_offset);	}      else	{	  unsigned long indx;	  struct elf_link_hash_entry *h;	  /* An external symbol.  */	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;	  h = elf_sym_hashes (abfd)[indx];	  BFD_ASSERT (h != NULL);	  if (h->root.type != bfd_link_hash_defined	      && h->root.type != bfd_link_hash_defweak)	    {	      /* This appears to be a reference to an undefined                 symbol.  Just ignore it--it will be caught by the                 regular reloc processing.  */	      continue;	    }	  symval = (h->root.u.def.value		    + h->root.u.def.section->output_section->vma		    + h->root.u.def.section->output_offset);	}      /* For simplicity of coding, we are going to modify the section	 contents, the section relocs, and the BFD symbol table.  We	 must tell the rest of the code not to free up this	 information.  It would be possible to instead create a table	 of changes which have to be made, as is done in coff-mips.c;	 that would be more work, but would require less memory when	 the linker is run.  */      /* Try to change a seth/add3/jl subroutine call to bl24 or bl8.	 This sequence is generated by the compiler when compiling in	 32 bit mode.  Also look for seth/add3 -> ld24.  */      if (ELF32_R_TYPE (irel->r_info) == (int) R_M32R_HI16_SLO)	{	  Elf_Internal_Rela *nrel;	  bfd_vma pc = (sec->output_section->vma + sec->output_offset			+ irel->r_offset);	  bfd_signed_vma pcrel_value = symval - pc;	  unsigned int code,reg;	  int addend,nop_p,bl8_p,to_delete;	  /* The tests are ordered so that we get out as quickly as possible	     if this isn't something we can relax, taking into account that	     we are looking for two separate possibilities (jl/ld24).  */	  /* Do nothing if no room in the section for this to be what we're	     looking for.  */	  if (irel->r_offset > sec->_cooked_size - 8)	    continue;	  /* Make sure the next relocation applies to the next	     instruction and that it's the add3's reloc.  */	  nrel = irel + 1;	  if (nrel == irelend	      || irel->r_offset + 4 != nrel->r_offset	      || ELF32_R_TYPE (nrel->r_info) != (int) R_M32R_LO16)	    continue;	  /* See if the instructions are seth/add3.  */	  /* FIXME: This is where macros from cgen can come in.  */	  code = bfd_get_16 (abfd, contents + irel->r_offset + 0);	  if ((code & 0xf0ff) != 0xd0c0)	    continue; /* not seth rN,foo */	  reg = (code & 0x0f00) >> 8;	  code = bfd_get_16 (abfd, contents + irel->r_offset + 4);	  if (code != (0x80a0 | reg | (reg << 8)))	    continue; /* not add3 rN,rN,foo */	  /* At this point we've confirmed we have seth/add3.  Now check	     whether the next insn is a jl, in which case try to change this	     to bl24 or bl8.  */	  /* Ensure the branch target is in range.	     The bl24 instruction has a 24 bit operand which is the target	     address right shifted by 2, giving a signed range of 26 bits.	     Note that 4 bytes are added to the high value because the target	     will be at least 4 bytes closer if we can relax.  It'll actually	     be 4 or 8 bytes closer, but we don't know which just yet and	     the difference isn't significant enough to worry about.  */#ifndef USE_REL /* put in for learning purposes */	  pcrel_value += irel->r_addend;#else	  addend = bfd_get_signed_16 (abfd, contents + irel->r_offset + 2);	  pcrel_value += addend;#endif	  if (pcrel_value >= -(1 << 25) && pcrel_value < (1 << 25) + 4	      /* Do nothing if no room in the section for this to be what we're		 looking for.  */	      && (irel->r_offset <= sec->_cooked_size - 12)	      /* Ensure the next insn is "jl rN".  */	      && ((code = bfd_get_16 (abfd, contents + irel->r_offset + 8)),		  code != (0x1ec0 | reg)))	    {	      /* We can relax to bl24/bl8.  */	      /* See if there's a nop following the jl.		 Also see if we can use a bl8 insn.  */	      code = bfd_get_16 (abfd, contents + irel->r_offset + 10);	      nop_p = (code & 0x7fff) == NOP_INSN;	      bl8_p = pcrel_value >= -0x200 && pcrel_value < 0x200;	      if (bl8_p)		{		  /* Change "seth rN,foo" to "bl8 foo || nop".		     We OR in CODE just in case it's not a nop (technically,		     CODE currently must be a nop, but for cleanness we		     allow it to be anything).  */#ifndef USE_REL /* put in for learning purposes */		  code = 0x7e000000 | MAKE_PARALLEL (code);#else		  code = (0x7e000000 + (((addend >> 2) & 0xff) << 16)) | MAKE_PARALLEL (code);#endif		  to_delete = 8;		}	      else		{		  /* Change the seth rN,foo to a bl24 foo.  */#ifndef USE_REL /* put in for learning purposes */		  code = 0xfe000000;#else		  code = 0xfe000000 + ((addend >> 2) & 0xffffff);#endif		  to_delete = nop_p ? 8 : 4;		}	      bfd_put_32 (abfd, code, contents + irel->r_offset);	      /* Set the new reloc type.  */	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info),					   bl8_p ? R_M32R_10_PCREL : R_M32R_26_PCREL);	      /* Delete the add3 reloc by making it a null reloc.  */	      nrel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info),					   R_M32R_NONE);	    }	  else if (addend >= 0		   && symval + addend <= 0xffffff)	    {	      /* We can relax to ld24.  */	      code = 0xe0000000 | (reg << 24) | (addend & 0xffffff);	      bfd_put_32 (abfd, code, contents + irel->r_offset);	      to_delete = 4;	      /* Tell the following code a nop filler isn't needed.  */	      nop_p = 1;	    }	  else	    {	      /* Can't do anything here.  */	      continue;	    }	  /* Note that we've changed the relocs, section contents, etc.  */	  elf_section_data (sec)->relocs = internal_relocs;	  free_relocs = NULL;	  elf_section_data (sec)->this_hdr.contents = contents;	  free_contents = NULL;	  symtab_hdr->contents = (bfd_byte *) extsyms;	  free_extsyms = NULL;	  /* Delete TO_DELETE bytes of data.  */	  if (!m32r_elf_relax_delete_bytes (abfd, sec,					    irel->r_offset + 4, to_delete))	    goto error_return;	  /* Now that the following bytes have been moved into place, see if	     we need to replace the jl with a nop.  This happens when we had	     to use a bl24 insn and the insn following the jl isn't a nop.	     Technically, this situation can't happen (since the insn can	     never be executed) but to be clean we do this.  When the chip	     supports parallel 16 bit insns things may change.	     We don't need to do this in the case of relaxing to ld24,	     and the above code sets nop_p so this isn't done.  */	  if (! nop_p && to_delete == 4)	    bfd_put_16 (abfd, NOP_INSN, contents + irel->r_offset + 4);	  /* That will change things, so we should relax again.	     Note that this is not required, and it may be slow.  */	  *again = true;	  continue;	}      /* loop to try the next reloc */    }  if (free_relocs != NULL)    {      free (free_relocs);      free_relocs = NULL;    }  if (free_contents != NULL)    {      if (! link_info->keep_memory)	free (free_contents);      else	{	  /* Cache the section contents for elf_link_input_bfd.  */	  elf_section_data (sec)->this_hdr.contents = contents;	}      free_contents = NULL;    }  if (free_extsyms != NULL)    {      if (! link_info->keep_memory)	free (free_extsyms);      else	{	  /* Cache the symbols for elf_link_input_bfd.  */	  symtab_hdr->contents = extsyms;	}      free_extsyms = NULL;    }  return true; error_return:  if (free_relocs != NULL)    free (free_relocs);  if (free_contents != NULL)    free (free_contents);  if (free_extsyms != NULL)    free (free_extsyms);  return false;}/* Delete some bytes from a section while relaxing.  */static booleanm32r_elf_relax_delete_bytes (abfd, sec, addr, count)     bfd *abfd;     asection *sec;     bfd_vma addr;     int count;{  Elf_Internal_Shdr *symtab_hdr;  Elf32_External_Sym *extsyms;  int shndx, index;  bfd_byte *contents;  Elf_Internal_Rela *irel, *irelend;  Elf_Internal_Rela *irelalign;  bfd_vma toaddr;  Elf32_External_Sym *esym, *esymend;  struct elf_link_hash_entry *sym_hash;  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;  extsyms = (Elf32_External_Sym *) symtab_hdr->contents;  shndx = _bfd_elf_section_from_bfd_section (abfd, sec);  contents = elf_section_data (sec)->this_hdr.contents;  /* The deletion must stop at the next ALIGN reloc for an aligment     power larger than the number of bytes we are deleting.  */  irelalign = NULL;  toaddr = sec->_cooked_size;  irel = elf_section_data (sec)->relocs;  irelend = irel + sec->reloc_count;  /* Actually delete the bytes.  */  memmove (contents + addr, contents + addr + count, toaddr - addr - count);  sec->_cooked_size -= count;  /* Adjust all the relocs.  */  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)    {

⌨️ 快捷键说明

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