- bfd_vma first = addr;
- bfd_vma last;
- boolean relaxed = true;
-
- /* On the final pass we must check if *all* entries in the
- dispatch table are relaxed. If *any* are not relaxed
- then we must unrelax *all* the entries in the dispach
- table and also unrelax the dispatch table prologue. */
-
- /* Note the 1st PAGE/JMP instructions are part of the
- prologue and can safely be relaxed. */
-
- code0 = bfd_get_8 (abfd, misc->contents + first);
- code1 = bfd_get_8 (abfd, misc->contents + first + 1);
-
- if (IS_PAGE_OPCODE (code0, code1))
- {
- first += 2;
- code0 = bfd_get_8 (abfd, misc->contents + first);
- code1 = bfd_get_8 (abfd, misc->contents + first + 1);
- }
-
- if (! IS_JMP_OPCODE (code0, code1))
- /* Something has gone wrong. */
- return false;
-
- first += 2;
- last = first;
-
- /* Find the last entry in the dispach table. */
- while (last < sec->_cooked_size)
- {
- code0 = bfd_get_8 (abfd, misc->contents + last);
- code1 = bfd_get_8 (abfd, misc->contents + last + 1);
-
- if (IS_PAGE_OPCODE (code0, code1))
- relaxed = false;
- else if (! IS_JMP_OPCODE (code0, code1))
- break;
-
- last += 2;
- }
-
- /* We should have found the end of the dispatch table
- before reaching the end of the section. If we have
- reached the end of the section then fail the
- relaxation. */
- if (last >= sec->_cooked_size)
- return false;
-
- /* If we found an unrelaxed entry then
- unrelax all the switch table entries. */
- if (! relaxed)
- {
- if (! unrelax_dispatch_table_entries (abfd, sec, first,
- last, changed, misc))
- return false;
-
- if (! is_switch_256_dispatch_table_p (abfd, addr, true, misc))
- return false;
-
- /* Unrelax the prologue. */
-
- /* Insert an INC 1(SP) insnstruction. */
- if (! ip2k_elf_relax_add_bytes (abfd, sec,
- addr - 6,
- inc_1_sp_opcode,
- sizeof (inc_1_sp_opcode),
- 0))
- return false;
-
- /* Insert an SNC insnstruction. */
- if (! ip2k_elf_relax_add_bytes (abfd, sec,
- addr - 6,
- snc_opcode,
- sizeof (snc_opcode),
- 0))
- return false;
-
- /* Insert an ADD W,WREG insnstruction. */
- if (! ip2k_elf_relax_add_bytes (abfd, sec,
- addr - 6,
- add_w_wreg_opcode,
- sizeof (add_w_wreg_opcode),
- 0))
- return false;
- }
-
- return true;
- }
- }
-
- return true;
-}
-
-/* This function handles relaxing for the ip2k. */
-
-static boolean
-ip2k_elf_relax_section (abfd, sec, link_info, again)
- bfd *abfd;
- asection *sec;
- struct bfd_link_info *link_info;
- boolean *again;
-{
- Elf_External_Sym_Shndx *shndx_buf;
- Elf_Internal_Shdr *shndx_hdr;
- static asection * first_section = NULL;
- static asection * last_section = NULL;
- static boolean changed = false;
- static boolean final_pass = false;
- static unsigned int pass = 0;
- struct misc misc;
- asection *stab;
-
- /* Assume nothing changes. */
- *again = false;
-
- if (first_section == NULL)
- first_section = sec;
-
- if (first_section == sec)
- {
- changed = false;
- pass++;
- }
-
- /* If we make too many passes then it's a sign that
- something is wrong and we fail the relaxation.
- Note if everything is working correctly then the
- relaxation should converge reasonably quickly. */
- if (pass == 4096)
- return false;
-
- /* We don't have to do anything for a relocatable 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)
- return true;
-
- if (pass == 1)
- last_section = sec;
-
- misc.symtab_hdr = NULL;
- misc.irelbase = NULL;
- misc.contents = NULL;
- misc.free_contents = NULL;
- misc.extsyms = NULL;
- misc.free_extsyms = NULL;
- misc.free_relocs = NULL;
-
- /* If this is the first time we have been called
- for this section, initialise the cooked size. */
- if (sec->_cooked_size == 0)
- sec->_cooked_size = sec->_raw_size;
-
- misc.symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-
- misc.irelbase = _bfd_elf32_link_read_relocs (abfd, sec, NULL,
- (Elf_Internal_Rela *)NULL,
- link_info->keep_memory);
- if (misc.irelbase == NULL)
- {
- tidyup_after_error (&misc);
- return false;
- }
-
- if (! link_info->keep_memory)
- misc.free_relocs = misc.irelbase;
-
- /* Make sure the stac.rela stuff gets read in. */
- stab = bfd_get_section_by_name (abfd, ".stab");
-
- if (stab)
- {
- /* So stab does exits. */
- Elf_Internal_Rela * irelbase;
-
- irelbase = _bfd_elf32_link_read_relocs (abfd, stab, NULL,
- (Elf_Internal_Rela *)NULL,
- link_info->keep_memory);
- }
-
- /* Get section contents cached copy if it exists. */
- if (elf_section_data (sec)->this_hdr.contents != NULL)
- misc.contents = elf_section_data (sec)->this_hdr.contents;
- else
- {
- /* Go get them of disk. */
- misc.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
- if (misc.contents == NULL)
- {
- tidyup_after_error (&misc);
- return false;
- }
-
- misc.free_contents = misc.contents;
- if (! bfd_get_section_contents (abfd, sec, misc.contents,
- (file_ptr)0,
- sec->_raw_size))
- {
- tidyup_after_error (&misc);
- return false;
- }
- }
-
- /* Read this BFD's symbols cached copy if it exists. */
- if (misc.symtab_hdr->contents != NULL)
- misc.extsyms = (Elf32_External_Sym *) misc.symtab_hdr->contents;
- else
- {
- /* Go get them off disk. */
- misc.extsyms = ((Elf32_External_Sym *)bfd_malloc (misc.symtab_hdr->sh_size));
- if (misc.extsyms == NULL)
- {
- tidyup_after_error (&misc);
- return false;
- }
-
- misc.free_extsyms = misc.extsyms;
- if (bfd_seek (abfd, misc.symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (misc.extsyms, 1, misc.symtab_hdr->sh_size, abfd)
- != misc.symtab_hdr->sh_size))
- {
- tidyup_after_error (&misc);
- return false;
- }
- }
-
- if (shndx_hdr->sh_size != 0)
- {
- bfd_size_type amt;
-
- amt = misc.symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
- shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
- if (shndx_buf == NULL)
- {
- tidyup_after_error (&misc);
- return false;
- }
- if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
- {
- tidyup_after_error (&misc);
- return false;
- }
- shndx_hdr->contents = (PTR) shndx_buf;
- }
-
- /* This is where all the relaxation actually get done. */
-
- if (pass == 1)
- {
- /* On the first pass we remove *all* page instructions and
- relax the prolog for switch dispatch tables. This gets
- us to the starting point for subsequent passes where
- we add page instructions back in as needed. */
-
- if (! ip2k_elf_relax_section_pass1 (abfd, sec, again, &misc))
- {
- tidyup_after_error (&misc);
- return false;