diff options
author | Jeff Law <law@redhat.com> | 1999-12-01 10:14:02 +0000 |
---|---|---|
committer | Jeff Law <law@redhat.com> | 1999-12-01 10:14:02 +0000 |
commit | 31f8dc8fceba2e10cc6d503cc6280db0504dd7f7 (patch) | |
tree | 7bdfca9f665bde18d0afd196bc8cef38505af52b /bfd/elf-m10300.c | |
parent | 0ed4f623e67138e6119a6ec85524f595d2b8306a (diff) | |
download | gdb-31f8dc8fceba2e10cc6d503cc6280db0504dd7f7.zip gdb-31f8dc8fceba2e10cc6d503cc6280db0504dd7f7.tar.gz gdb-31f8dc8fceba2e10cc6d503cc6280db0504dd7f7.tar.bz2 |
* archures.c (bfd_mach_am33): Define.
* bfd-in2.h: Rebuilt.
* cpu-m10300.c (bfd_am33_arch): Add to the mn103 architecture list
* elf-m10300.c (mn10300_elf_relax_section): Handle am33 instructions.
(compute_function_info): Handle additional registers saved by
movm on the am33.
(elf_mn10300_mach): Handle E_MN10300_MACH_AM33.
(_bfd_mn10300_elf_final_write_processing): Handle bfd_mach_am33.
Diffstat (limited to 'bfd/elf-m10300.c')
-rw-r--r-- | bfd/elf-m10300.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c index c46dc0c..5dbd2d6 100644 --- a/bfd/elf-m10300.c +++ b/bfd/elf-m10300.c @@ -1903,6 +1903,79 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) *again = true; } + /* Try to turn a 24 immediate, displacement or absolute address + into a 8 immediate, displacement or absolute address. */ + if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_24) + { + bfd_vma value = symval; + value += irel->r_addend; + + /* See if the value will fit in 8 bits. */ + if ((long)value < 0x7f && (long)value > -0x80) + { + unsigned char code; + + /* AM33 insns which have 24 operands are 6 bytes long and + will have 0xfd as the first byte. */ + + /* Get the first opcode. */ + code = bfd_get_8 (abfd, contents + irel->r_offset - 3); + + if (code == 0xfd) + { + /* Get the second opcode. */ + code = bfd_get_8 (abfd, contents + irel->r_offset - 2); + + /* We can not relax 0x6b, 0x7b, 0x8b, 0x9b as no 24bit + equivalent instructions exists. */ + if (code != 0x6b && code != 0x7b + && code != 0x8b && code != 0x9b + && ((code & 0x0f) == 0x09 || (code & 0x0f) == 0x08 + || (code & 0x0f) == 0x0a || (code & 0x0f) == 0x0b + || (code & 0x0f) == 0x0e)) + { + /* Not safe if the high bit is on as relaxing may + move the value out of high mem and thus not fit + in a signed 8bit value. This is currently over + conservative. */ + if ((value & 0x80) == 0) + { + /* Note that we've changed the relocation 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; + + /* Fix the opcode. */ + bfd_put_8 (abfd, 0xfb, contents + irel->r_offset - 3); + bfd_put_8 (abfd, code, contents + irel->r_offset - 2); + + /* Fix the relocation's type. */ + irel->r_info + = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), + R_MN10300_8); + + /* Delete two bytes of data. */ + if (!mn10300_elf_relax_delete_bytes (abfd, sec, + irel->r_offset + 1, 2)) + goto error_return; + + /* That will change things, so, we should relax + again. Note that this is not required, and it + may be slow. */ + *again = true; + break; + } + } + + } + } + } /* Try to turn a 32bit immediate, displacement or absolute address into a 16bit immediate, displacement or absolute address. */ @@ -1911,6 +1984,74 @@ mn10300_elf_relax_section (abfd, sec, link_info, again) bfd_vma value = symval; value += irel->r_addend; + /* See if the value will fit in 24 bits. + We allow any 16bit match here. We prune those we can't + handle below. */ + if ((long)value < 0x7fffff && (long)value > -0x800000) + { + unsigned char code; + + /* AM33 insns which have 32bit operands are 7 bytes long and + will have 0xfe as the first byte. */ + + /* Get the first opcode. */ + code = bfd_get_8 (abfd, contents + irel->r_offset - 3); + + if (code == 0xfe) + { + /* Get the second opcode. */ + code = bfd_get_8 (abfd, contents + irel->r_offset - 2); + + /* All the am33 32 -> 24 relaxing possibilities. */ + /* We can not relax 0x6b, 0x7b, 0x8b, 0x9b as no 24bit + equivalent instructions exists. */ + if (code != 0x6b && code != 0x7b + && code != 0x8b && code != 0x9b + && ((code & 0x0f) == 0x09 || (code & 0x0f) == 0x08 + || (code & 0x0f) == 0x0a || (code & 0x0f) == 0x0b + || (code & 0x0f) == 0x0e)) + { + /* Not safe if the high bit is on as relaxing may + move the value out of high mem and thus not fit + in a signed 16bit value. This is currently over + conservative. */ + if ((value & 0x8000) == 0) + { + /* Note that we've changed the relocation 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; + + /* Fix the opcode. */ + bfd_put_8 (abfd, 0xfd, contents + irel->r_offset - 3); + bfd_put_8 (abfd, code, contents + irel->r_offset - 2); + + /* Fix the relocation's type. */ + irel->r_info + = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), + R_MN10300_24); + + /* Delete one byte of data. */ + if (!mn10300_elf_relax_delete_bytes (abfd, sec, + irel->r_offset + 3, 1)) + goto error_return; + + /* That will change things, so, we should relax + again. Note that this is not required, and it + may be slow. */ + *again = true; + break; + } + } + + } + } /* See if the value will fit in 16 bits. We allow any 16bit match here. We prune those we can't @@ -2333,6 +2474,20 @@ compute_function_info (abfd, hash, addr, contents) if (hash->movm_args & 0x08) hash->movm_stack_size += 8 * 4; + if (bfd_get_mach (abfd) == bfd_mach_am33) + { + /* "exother" space. e0, e1, mdrq, mcrh, mcrl, mcvf */ + if (hash->movm_args & 0x1) + hash->movm_stack_size += 6 * 4; + + /* exreg1 space. e4, e5, e6, e7 */ + if (hash->movm_args & 0x2) + hash->movm_stack_size += 4 * 4; + + /* exreg0 space. e2, e3 */ + if (hash->movm_args & 0x4) + hash->movm_stack_size += 2 * 4; + } } /* Now look for the two stack adjustment variants. */ @@ -2724,6 +2879,8 @@ elf_mn10300_mach (flags) default: return bfd_mach_mn10300; + case E_MN10300_MACH_AM33: + return bfd_mach_am33; } } @@ -2746,6 +2903,9 @@ _bfd_mn10300_elf_final_write_processing (abfd, linker) val = E_MN10300_MACH_MN10300; break; + case bfd_mach_am33: + val = E_MN10300_MACH_AM33; + break; } elf_elfheader (abfd)->e_flags &= ~ (EF_MN10300_MACH); |