coff-h8300.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,341 行 · 第 1/3 页
C
1,341 行
if (input_section != last_input_section) last_reloc = NULL; /* Only examine the relocs which might be relaxable. */ switch (reloc->howto->type) { /* This is the 16/24 bit absolute branch which could become an 8 bit pc-relative branch. */ case R_JMP1: case R_JMPL1: /* Get the address of the target of this branch. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* Get the address of the next instruction (not the reloc). */ dot = (input_section->output_section->vma + input_section->output_offset + address); /* Adjust for R_JMP1 vs R_JMPL1. */ dot += (reloc->howto->type == R_JMP1 ? 1 : 2); /* Compute the distance from this insn to the branch target. */ gap = value - dot; /* If the distance is within -128..+128 inclusive, then we can relax this jump. +128 is valid since the target will move two bytes closer if we do relax this branch. */ if ((int)gap >= -128 && (int)gap <= 128 ) { /* It's possible we may be able to eliminate this branch entirely; if the previous instruction is a branch around this instruction, and there's no label at this instruction, then we can reverse the condition on the previous branch and eliminate this jump. original: new: bCC lab1 bCC' lab2 jmp lab2 lab1: lab1: This saves 4 bytes instead of two, and should be relatively common. */ if (gap <= 126 && last_reloc && last_reloc->howto->type == R_PCRBYTE) { bfd_vma last_value; last_value = bfd_coff_reloc16_get_value (last_reloc, link_info, input_section) + 1; if (last_value == dot + 2 && last_reloc->address + 1 == reloc->address && !h8300_symbol_address_p (abfd, input_section, dot - 2)) { reloc->howto = howto_table + 19; last_reloc->howto = howto_table + 18; last_reloc->sym_ptr_ptr = reloc->sym_ptr_ptr; last_reloc->addend = reloc->addend; shrink += 4; bfd_perform_slip (abfd, 4, input_section, address); break; } } /* Change the reloc type. */ reloc->howto = reloc->howto + 1; /* This shrinks this section by two bytes. */ shrink += 2; bfd_perform_slip (abfd, 2, input_section, address); } break; /* This is the 16 bit pc-relative branch which could become an 8 bit pc-relative branch. */ case R_PCRWORD: /* Get the address of the target of this branch, add one to the value because the addend field in PCrel jumps is off by -1. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section) + 1; /* Get the address of the next instruction if we were to relax. */ dot = input_section->output_section->vma + input_section->output_offset + address; /* Compute the distance from this insn to the branch target. */ gap = value - dot; /* If the distance is within -128..+128 inclusive, then we can relax this jump. +128 is valid since the target will move two bytes closer if we do relax this branch. */ if ((int)gap >= -128 && (int)gap <= 128 ) { /* Change the reloc type. */ reloc->howto = howto_table + 15; /* This shrinks this section by two bytes. */ shrink += 2; bfd_perform_slip (abfd, 2, input_section, address); } break; /* This is a 16 bit absolute address in a mov.b insn, which can become an 8 bit absolute address if it's in the right range. */ case R_MOV16B1: /* Get the address of the data referenced by this mov.b insn. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* The address is in 0xff00..0xffff inclusive on the h8300 or 0xffff00..0xffffff inclusive on the h8300h, then we can relax this mov.b */ if ((bfd_get_mach (abfd) == bfd_mach_h8300 && value >= 0xff00 && value <= 0xffff) || ((bfd_get_mach (abfd) == bfd_mach_h8300h || bfd_get_mach (abfd) == bfd_mach_h8300s) && value >= 0xffff00 && value <= 0xffffff)) { /* Change the reloc type. */ reloc->howto = reloc->howto + 1; /* This shrinks this section by two bytes. */ shrink += 2; bfd_perform_slip (abfd, 2, input_section, address); } break; /* Similarly for a 24 bit absolute address in a mov.b. Note that if we can't relax this into an 8 bit absolute, we'll fall through and try to relax it into a 16bit absolute. */ case R_MOV24B1: /* Get the address of the data referenced by this mov.b insn. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* The address is in 0xffff00..0xffffff inclusive on the h8300h, then we can relax this mov.b */ if ((bfd_get_mach (abfd) == bfd_mach_h8300h || bfd_get_mach (abfd) == bfd_mach_h8300s) && value >= 0xffff00 && value <= 0xffffff) { /* Change the reloc type. */ reloc->howto = reloc->howto + 1; /* This shrinks this section by four bytes. */ shrink += 4; bfd_perform_slip (abfd, 4, input_section, address); /* Done with this reloc. */ break; } /* FALLTHROUGH and try to turn the 32/24 bit reloc into a 16 bit reloc. */ /* This is a 24/32 bit absolute address in a mov insn, which can become an 16 bit absolute address if it's in the right range. */ case R_MOVL1: /* Get the address of the data referenced by this mov insn. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* If this address is in 0x0000..0x7fff inclusive or 0xff8000..0xffffff inclusive, then it can be relaxed. */ if (value <= 0x7fff || value >= 0xff8000) { /* Change the reloc type. */ reloc->howto = howto_table + 17; /* This shrinks this section by two bytes. */ shrink += 2; bfd_perform_slip (abfd, 2, input_section, address); } break; /* No other reloc types represent relaxing opportunities. */ default: break; } last_reloc = reloc; last_input_section = input_section; return shrink;}/* Handle relocations for the H8/300, including relocs for relaxed instructions. FIXME: Not all relocations check for overflow! */static voidh8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr) bfd *abfd; struct bfd_link_info *link_info; struct bfd_link_order *link_order; arelent *reloc; bfd_byte *data; unsigned int *src_ptr; unsigned int *dst_ptr;{ unsigned int src_address = *src_ptr; unsigned int dst_address = *dst_ptr; asection *input_section = link_order->u.indirect.section; bfd_vma value; bfd_vma dot; int gap, tmp; switch (reloc->howto->type) { /* Generic 8bit pc-relative relocation. */ case R_PCRBYTE: /* Get the address of the target of this branch. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); dot = (link_order->offset + dst_address + link_order->u.indirect.section->output_section->vma); gap = value - dot; /* Sanity check. */ if (gap < -128 || gap > 126) { if (! ((*link_info->callbacks->reloc_overflow) (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort (); } /* Everything looks OK. Apply the relocation and update the src/dst address appropriately. */ bfd_put_8 (abfd, gap, data + dst_address); dst_address++; src_address++; /* All done. */ break; /* Generic 16bit pc-relative relocation. */ case R_PCRWORD: /* Get the address of the target of this branch. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* Get the address of the instruction (not the reloc). */ dot = (link_order->offset + dst_address + link_order->u.indirect.section->output_section->vma + 1); gap = value - dot; /* Sanity check. */ if (gap > 32766 || gap < -32768) { if (! ((*link_info->callbacks->reloc_overflow) (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort (); } /* Everything looks OK. Apply the relocation and update the src/dst address appropriately. */ bfd_put_16 (abfd, gap, data + dst_address); dst_address += 2; src_address += 2; /* All done. */ break; /* Generic 8bit absolute relocation. */ case R_RELBYTE: /* Get the address of the object referenced by this insn. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* Sanity check. */ if (value <= 0xff || (value >= 0x0000ff00 && value <= 0x0000ffff) || (value >= 0x00ffff00 && value <= 0x00ffffff) || (value >= 0xffffff00 && value <= 0xffffffff)) { /* Everything looks OK. Apply the relocation and update the src/dst address appropriately. */ bfd_put_8 (abfd, value & 0xff, data + dst_address); dst_address += 1; src_address += 1; } else { if (! ((*link_info->callbacks->reloc_overflow) (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort (); } /* All done. */ break; /* Various simple 16bit absolute relocations. */ case R_MOV16B1: case R_JMP1: case R_RELWORD: value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); bfd_put_16 (abfd, value, data + dst_address); dst_address += 2; src_address += 2; break; /* Various simple 24/32bit absolute relocations. */ case R_MOV24B1: case R_MOVL1: case R_RELLONG: /* Get the address of the target of this branch. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); bfd_put_32 (abfd, value, data + dst_address); dst_address += 4; src_address += 4; break; /* Another 24/32bit absolute relocation. */ case R_JMPL1: /* Get the address of the target of this branch. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); value = ((value & 0x00ffffff) | (bfd_get_32 (abfd, data + src_address) & 0xff000000)); bfd_put_32 (abfd, value, data + dst_address); dst_address += 4; src_address += 4; break; /* A 16bit abolute relocation that was formerlly a 24/32bit absolute relocation. */ case R_MOVL2: value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* Sanity check. */ if (value <= 0x7fff || value >= 0xff8000) { /* Insert the 16bit value into the proper location. */ bfd_put_16 (abfd, value, data + dst_address); /* Fix the opcode. For all the move insns, we simply need to turn off bit 0x20 in the previous byte. */ data[dst_address - 1] &= ~0x20; dst_address += 2; src_address += 4; } else { if (! ((*link_info->callbacks->reloc_overflow) (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort (); } break; /* A 16bit absolute branch that is now an 8-bit pc-relative branch. */ case R_JMP2: /* Get the address of the target of this branch. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* Get the address of the next instruction. */ dot = (link_order->offset + dst_address + link_order->u.indirect.section->output_section->vma + 1); gap = value - dot; /* Sanity check. */ if (gap < -128 || gap > 126) { if (! ((*link_info->callbacks->reloc_overflow) (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort (); } /* Now fix the instruction itself. */ switch (data[dst_address - 1]) { case 0x5e: /* jsr -> bsr */ bfd_put_8 (abfd, 0x55, data + dst_address - 1); break; case 0x5a: /* jmp ->bra */ bfd_put_8 (abfd, 0x40, data + dst_address - 1); break; default: abort (); } /* Write out the 8bit value. */ bfd_put_8 (abfd, gap, data + dst_address); dst_address += 1; src_address += 3; break; /* A 16bit pc-relative branch that is now an 8-bit pc-relative branch. */ case R_PCRWORD_B: /* Get the address of the target of this branch. */ value = bfd_coff_reloc16_get_value (reloc, link_info, input_section); /* Get the address of the instruction (not the reloc). */ dot = (link_order->offset + dst_address + link_order->u.indirect.section->output_section->vma - 1); gap = value - dot; /* Sanity check. */ if (gap < -128 || gap > 126) { if (! ((*link_info->callbacks->reloc_overflow) (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr), reloc->howto->name, reloc->addend, input_section->owner, input_section, reloc->address))) abort (); } /* Now fix the instruction. */ switch (data[dst_address - 2]) { case 0x58: /* bCC:16 -> bCC:8 */ /* Get the condition code from the original insn. */ tmp = data[dst_address - 1]; tmp &= 0xf0; tmp >>= 4; /* Now or in the high nibble of the opcode. */ tmp |= 0x40; /* Write it. */ bfd_put_8 (abfd, tmp, data + dst_address - 2); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?