123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- /* BFD library support routines for the Renesas / SuperH SH architecture.
- Copyright (C) 1993-2022 Free Software Foundation, Inc.
- Hacked by Steve Chamberlain of Cygnus Support.
- This file is part of BFD, the Binary File Descriptor library.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
- #include "sysdep.h"
- #include "bfd.h"
- #include "libbfd.h"
- #include "../opcodes/sh-opc.h"
- #define N(NUMBER, PRINT, DEFAULT, NEXT) \
- { \
- 32, /* Bits in a word. */ \
- 32, /* Bits in an address. */ \
- 8, /* Bits in a byte. */ \
- bfd_arch_sh, \
- NUMBER, \
- "sh", \
- PRINT, \
- 1, /* Section alignment power. */ \
- DEFAULT, \
- bfd_default_compatible, \
- bfd_default_scan, \
- bfd_arch_default_fill, \
- NEXT, \
- 0 /* Maximum offset of a reloc from the start of an insn. */ \
- }
- static const bfd_arch_info_type arch_info_struct[] =
- {
- N (bfd_mach_sh2, "sh2", false, arch_info_struct + 1),
- N (bfd_mach_sh2e, "sh2e", false, arch_info_struct + 2),
- N (bfd_mach_sh_dsp, "sh-dsp", false, arch_info_struct + 3),
- N (bfd_mach_sh3, "sh3", false, arch_info_struct + 4),
- N (bfd_mach_sh3_nommu, "sh3-nommu", false, arch_info_struct + 5),
- N (bfd_mach_sh3_dsp, "sh3-dsp", false, arch_info_struct + 6),
- N (bfd_mach_sh3e, "sh3e", false, arch_info_struct + 7),
- N (bfd_mach_sh4, "sh4", false, arch_info_struct + 8),
- N (bfd_mach_sh4a, "sh4a", false, arch_info_struct + 9),
- N (bfd_mach_sh4al_dsp, "sh4al-dsp", false, arch_info_struct + 10),
- N (bfd_mach_sh4_nofpu, "sh4-nofpu", false, arch_info_struct + 11),
- N (bfd_mach_sh4_nommu_nofpu, "sh4-nommu-nofpu", false, arch_info_struct + 12),
- N (bfd_mach_sh4a_nofpu, "sh4a-nofpu", false, arch_info_struct + 13),
- N (bfd_mach_sh2a, "sh2a", false, arch_info_struct + 14),
- N (bfd_mach_sh2a_nofpu, "sh2a-nofpu", false, arch_info_struct + 15),
- N (bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, "sh2a-nofpu-or-sh4-nommu-nofpu", false, arch_info_struct + 16),
- N (bfd_mach_sh2a_nofpu_or_sh3_nommu, "sh2a-nofpu-or-sh3-nommu", false, arch_info_struct + 17),
- N (bfd_mach_sh2a_or_sh4, "sh2a-or-sh4", false, arch_info_struct + 18),
- N (bfd_mach_sh2a_or_sh3e, "sh2a-or-sh3e", false, NULL)
- };
- const bfd_arch_info_type bfd_sh_arch =
- N (bfd_mach_sh, "sh", true, arch_info_struct + 0);
- /* This table defines the mappings from the BFD internal numbering
- system to the opcodes internal flags system.
- It is used by the functions defined below.
- The prototypes for these SH specific functions are found in
- sh-opc.h . */
- static struct { unsigned long bfd_mach, arch, arch_up; } bfd_to_arch_table[] =
- {
- { bfd_mach_sh, arch_sh1, arch_sh_up },
- { bfd_mach_sh2, arch_sh2, arch_sh2_up },
- { bfd_mach_sh2e, arch_sh2e, arch_sh2e_up },
- { bfd_mach_sh_dsp, arch_sh_dsp, arch_sh_dsp_up },
- { bfd_mach_sh2a, arch_sh2a, arch_sh2a_up },
- { bfd_mach_sh2a_nofpu, arch_sh2a_nofpu, arch_sh2a_nofpu_up },
- { bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, arch_sh2a_nofpu_or_sh4_nommu_nofpu, arch_sh2a_nofpu_or_sh4_nommu_nofpu_up },
- { bfd_mach_sh2a_nofpu_or_sh3_nommu, arch_sh2a_nofpu_or_sh3_nommu, arch_sh2a_nofpu_or_sh3_nommu_up },
- { bfd_mach_sh2a_or_sh4, arch_sh2a_or_sh4, arch_sh2a_or_sh4_up },
- { bfd_mach_sh2a_or_sh3e, arch_sh2a_or_sh3e, arch_sh2a_or_sh3e_up },
- { bfd_mach_sh3, arch_sh3, arch_sh3_up },
- { bfd_mach_sh3_nommu, arch_sh3_nommu, arch_sh3_nommu_up },
- { bfd_mach_sh3_dsp, arch_sh3_dsp, arch_sh3_dsp_up },
- { bfd_mach_sh3e, arch_sh3e, arch_sh3e_up },
- { bfd_mach_sh4, arch_sh4, arch_sh4_up },
- { bfd_mach_sh4a, arch_sh4a, arch_sh4a_up },
- { bfd_mach_sh4al_dsp, arch_sh4al_dsp, arch_sh4al_dsp_up },
- { bfd_mach_sh4_nofpu, arch_sh4_nofpu, arch_sh4_nofpu_up },
- { bfd_mach_sh4_nommu_nofpu, arch_sh4_nommu_nofpu, arch_sh4_nommu_nofpu_up },
- { bfd_mach_sh4a_nofpu, arch_sh4a_nofpu, arch_sh4a_nofpu_up },
- { 0, 0, 0 } /* Terminator. */
- };
- /* Convert a BFD mach number into the right opcodes arch flags
- using the table above. */
- unsigned int
- sh_get_arch_from_bfd_mach (unsigned long mach)
- {
- int i = 0;
- while (bfd_to_arch_table[i].bfd_mach != 0)
- if (bfd_to_arch_table[i].bfd_mach == mach)
- return bfd_to_arch_table[i].arch;
- else
- i++;
- /* Machine not found. */
- BFD_FAIL();
- return SH_ARCH_UNKNOWN_ARCH;
- }
- /* Convert a BFD mach number into a set of opcodes arch flags
- describing all the compatible architectures (i.e. arch_up)
- using the table above. */
- unsigned int
- sh_get_arch_up_from_bfd_mach (unsigned long mach)
- {
- int i = 0;
- while (bfd_to_arch_table[i].bfd_mach != 0)
- if (bfd_to_arch_table[i].bfd_mach == mach)
- return bfd_to_arch_table[i].arch_up;
- else
- i++;
- /* Machine not found. */
- BFD_FAIL();
- return SH_ARCH_UNKNOWN_ARCH;
- }
- /* Convert an arbitary arch_set - not necessarily corresponding
- directly to anything in the table above - to the most generic
- architecture which supports all the required features, and
- return the corresponding BFD mach. */
- unsigned long
- sh_get_bfd_mach_from_arch_set (unsigned int arch_set)
- {
- unsigned long result = 0;
- unsigned int best = ~arch_set;
- unsigned int co_mask = ~0;
- int i = 0;
- /* If arch_set permits variants with no coprocessor then do not allow
- the other irrelevant co-processor bits to influence the choice:
- e.g. if dsp is disallowed by arch_set, then the algorithm would
- prefer fpu variants over nofpu variants because they also disallow
- dsp - even though the nofpu would be the most correct choice.
- This assumes that EVERY fpu/dsp variant has a no-coprocessor
- counter-part, or their non-fpu/dsp instructions do not have the
- no co-processor bit set. */
- if (arch_set & arch_sh_no_co)
- co_mask = ~(arch_sh_sp_fpu | arch_sh_dp_fpu | arch_sh_has_dsp);
- while (bfd_to_arch_table[i].bfd_mach != 0)
- {
- unsigned int try = bfd_to_arch_table[i].arch_up & co_mask;
- /* Conceptually: Find the architecture with the least number
- of extra features or, if they have the same number, then
- the greatest number of required features. Disregard
- architectures where the required features alone do
- not describe a valid architecture. */
- if (((try & ~arch_set) < (best & ~arch_set)
- || ((try & ~arch_set) == (best & ~arch_set)
- && (~try & arch_set) < (~best & arch_set)))
- && SH_MERGE_ARCH_SET_VALID (try, arch_set))
- {
- result = bfd_to_arch_table[i].bfd_mach;
- best = try;
- }
- i++;
- }
- /* This might happen if a new variant is added to sh-opc.h
- but no corresponding entry is added to the table above. */
- BFD_ASSERT (result != 0);
- return result;
- }
|