12a6b7db3Sskrll /* BFD library support routines for the Renesas / SuperH SH architecture.
2*cb63e24eSchristos Copyright (C) 1993-2024 Free Software Foundation, Inc.
32a6b7db3Sskrll Hacked by Steve Chamberlain of Cygnus Support.
42a6b7db3Sskrll
52a6b7db3Sskrll This file is part of BFD, the Binary File Descriptor library.
62a6b7db3Sskrll
72a6b7db3Sskrll This program is free software; you can redistribute it and/or modify
82a6b7db3Sskrll it under the terms of the GNU General Public License as published by
92a6b7db3Sskrll the Free Software Foundation; either version 3 of the License, or
102a6b7db3Sskrll (at your option) any later version.
112a6b7db3Sskrll
122a6b7db3Sskrll This program is distributed in the hope that it will be useful,
132a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of
142a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152a6b7db3Sskrll GNU General Public License for more details.
162a6b7db3Sskrll
172a6b7db3Sskrll You should have received a copy of the GNU General Public License
182a6b7db3Sskrll along with this program; if not, write to the Free Software
192a6b7db3Sskrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
202a6b7db3Sskrll MA 02110-1301, USA. */
212a6b7db3Sskrll
222a6b7db3Sskrll #include "sysdep.h"
232a6b7db3Sskrll #include "bfd.h"
242a6b7db3Sskrll #include "libbfd.h"
252a6b7db3Sskrll #include "../opcodes/sh-opc.h"
262a6b7db3Sskrll
276f4ced0bSchristos
286f4ced0bSchristos #define N(NUMBER, PRINT, DEFAULT, NEXT) \
296f4ced0bSchristos { \
306f4ced0bSchristos 32, /* Bits in a word. */ \
316f4ced0bSchristos 32, /* Bits in an address. */ \
326f4ced0bSchristos 8, /* Bits in a byte. */ \
336f4ced0bSchristos bfd_arch_sh, \
346f4ced0bSchristos NUMBER, \
356f4ced0bSchristos "sh", \
366f4ced0bSchristos PRINT, \
376f4ced0bSchristos 1, /* Section alignment power. */ \
386f4ced0bSchristos DEFAULT, \
396f4ced0bSchristos bfd_default_compatible, \
406f4ced0bSchristos bfd_default_scan, \
416f4ced0bSchristos bfd_arch_default_fill, \
426f4ced0bSchristos NEXT, \
436f4ced0bSchristos 0 /* Maximum offset of a reloc from the start of an insn. */ \
446f4ced0bSchristos }
452a6b7db3Sskrll
462a6b7db3Sskrll static const bfd_arch_info_type arch_info_struct[] =
472a6b7db3Sskrll {
484f645668Schristos N (bfd_mach_sh2, "sh2", false, arch_info_struct + 1),
494f645668Schristos N (bfd_mach_sh2e, "sh2e", false, arch_info_struct + 2),
504f645668Schristos N (bfd_mach_sh_dsp, "sh-dsp", false, arch_info_struct + 3),
514f645668Schristos N (bfd_mach_sh3, "sh3", false, arch_info_struct + 4),
524f645668Schristos N (bfd_mach_sh3_nommu, "sh3-nommu", false, arch_info_struct + 5),
534f645668Schristos N (bfd_mach_sh3_dsp, "sh3-dsp", false, arch_info_struct + 6),
544f645668Schristos N (bfd_mach_sh3e, "sh3e", false, arch_info_struct + 7),
554f645668Schristos N (bfd_mach_sh4, "sh4", false, arch_info_struct + 8),
564f645668Schristos N (bfd_mach_sh4a, "sh4a", false, arch_info_struct + 9),
574f645668Schristos N (bfd_mach_sh4al_dsp, "sh4al-dsp", false, arch_info_struct + 10),
584f645668Schristos N (bfd_mach_sh4_nofpu, "sh4-nofpu", false, arch_info_struct + 11),
594f645668Schristos N (bfd_mach_sh4_nommu_nofpu, "sh4-nommu-nofpu", false, arch_info_struct + 12),
604f645668Schristos N (bfd_mach_sh4a_nofpu, "sh4a-nofpu", false, arch_info_struct + 13),
614f645668Schristos N (bfd_mach_sh2a, "sh2a", false, arch_info_struct + 14),
624f645668Schristos N (bfd_mach_sh2a_nofpu, "sh2a-nofpu", false, arch_info_struct + 15),
634f645668Schristos N (bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, "sh2a-nofpu-or-sh4-nommu-nofpu", false, arch_info_struct + 16),
644f645668Schristos N (bfd_mach_sh2a_nofpu_or_sh3_nommu, "sh2a-nofpu-or-sh3-nommu", false, arch_info_struct + 17),
654f645668Schristos N (bfd_mach_sh2a_or_sh4, "sh2a-or-sh4", false, arch_info_struct + 18),
664f645668Schristos N (bfd_mach_sh2a_or_sh3e, "sh2a-or-sh3e", false, NULL)
672a6b7db3Sskrll };
682a6b7db3Sskrll
692a6b7db3Sskrll const bfd_arch_info_type bfd_sh_arch =
704f645668Schristos N (bfd_mach_sh, "sh", true, arch_info_struct + 0);
712a6b7db3Sskrll
722a6b7db3Sskrll /* This table defines the mappings from the BFD internal numbering
732a6b7db3Sskrll system to the opcodes internal flags system.
742a6b7db3Sskrll It is used by the functions defined below.
752a6b7db3Sskrll The prototypes for these SH specific functions are found in
762a6b7db3Sskrll sh-opc.h . */
772a6b7db3Sskrll
782a6b7db3Sskrll static struct { unsigned long bfd_mach, arch, arch_up; } bfd_to_arch_table[] =
792a6b7db3Sskrll {
802a6b7db3Sskrll { bfd_mach_sh, arch_sh1, arch_sh_up },
812a6b7db3Sskrll { bfd_mach_sh2, arch_sh2, arch_sh2_up },
822a6b7db3Sskrll { bfd_mach_sh2e, arch_sh2e, arch_sh2e_up },
832a6b7db3Sskrll { bfd_mach_sh_dsp, arch_sh_dsp, arch_sh_dsp_up },
842a6b7db3Sskrll { bfd_mach_sh2a, arch_sh2a, arch_sh2a_up },
852a6b7db3Sskrll { bfd_mach_sh2a_nofpu, arch_sh2a_nofpu, arch_sh2a_nofpu_up },
862a6b7db3Sskrll
872a6b7db3Sskrll { bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, arch_sh2a_nofpu_or_sh4_nommu_nofpu, arch_sh2a_nofpu_or_sh4_nommu_nofpu_up },
882a6b7db3Sskrll { bfd_mach_sh2a_nofpu_or_sh3_nommu, arch_sh2a_nofpu_or_sh3_nommu, arch_sh2a_nofpu_or_sh3_nommu_up },
892a6b7db3Sskrll { bfd_mach_sh2a_or_sh4, arch_sh2a_or_sh4, arch_sh2a_or_sh4_up },
902a6b7db3Sskrll { bfd_mach_sh2a_or_sh3e, arch_sh2a_or_sh3e, arch_sh2a_or_sh3e_up },
912a6b7db3Sskrll
922a6b7db3Sskrll { bfd_mach_sh3, arch_sh3, arch_sh3_up },
932a6b7db3Sskrll { bfd_mach_sh3_nommu, arch_sh3_nommu, arch_sh3_nommu_up },
942a6b7db3Sskrll { bfd_mach_sh3_dsp, arch_sh3_dsp, arch_sh3_dsp_up },
952a6b7db3Sskrll { bfd_mach_sh3e, arch_sh3e, arch_sh3e_up },
962a6b7db3Sskrll { bfd_mach_sh4, arch_sh4, arch_sh4_up },
972a6b7db3Sskrll { bfd_mach_sh4a, arch_sh4a, arch_sh4a_up },
982a6b7db3Sskrll { bfd_mach_sh4al_dsp, arch_sh4al_dsp, arch_sh4al_dsp_up },
992a6b7db3Sskrll { bfd_mach_sh4_nofpu, arch_sh4_nofpu, arch_sh4_nofpu_up },
1002a6b7db3Sskrll { bfd_mach_sh4_nommu_nofpu, arch_sh4_nommu_nofpu, arch_sh4_nommu_nofpu_up },
1012a6b7db3Sskrll { bfd_mach_sh4a_nofpu, arch_sh4a_nofpu, arch_sh4a_nofpu_up },
1022a6b7db3Sskrll { 0, 0, 0 } /* Terminator. */
1032a6b7db3Sskrll };
1042a6b7db3Sskrll
1052a6b7db3Sskrll
1062a6b7db3Sskrll /* Convert a BFD mach number into the right opcodes arch flags
1072a6b7db3Sskrll using the table above. */
1082a6b7db3Sskrll
1092a6b7db3Sskrll unsigned int
sh_get_arch_from_bfd_mach(unsigned long mach)1102a6b7db3Sskrll sh_get_arch_from_bfd_mach (unsigned long mach)
1112a6b7db3Sskrll {
1122a6b7db3Sskrll int i = 0;
1132a6b7db3Sskrll
1142a6b7db3Sskrll while (bfd_to_arch_table[i].bfd_mach != 0)
1152a6b7db3Sskrll if (bfd_to_arch_table[i].bfd_mach == mach)
1162a6b7db3Sskrll return bfd_to_arch_table[i].arch;
1172a6b7db3Sskrll else
1182a6b7db3Sskrll i++;
1192a6b7db3Sskrll
1202a6b7db3Sskrll return SH_ARCH_UNKNOWN_ARCH;
1212a6b7db3Sskrll }
1222a6b7db3Sskrll
1232a6b7db3Sskrll
1242a6b7db3Sskrll /* Convert a BFD mach number into a set of opcodes arch flags
1252a6b7db3Sskrll describing all the compatible architectures (i.e. arch_up)
1262a6b7db3Sskrll using the table above. */
1272a6b7db3Sskrll
1282a6b7db3Sskrll unsigned int
sh_get_arch_up_from_bfd_mach(unsigned long mach)1292a6b7db3Sskrll sh_get_arch_up_from_bfd_mach (unsigned long mach)
1302a6b7db3Sskrll {
1312a6b7db3Sskrll int i = 0;
1322a6b7db3Sskrll
1332a6b7db3Sskrll while (bfd_to_arch_table[i].bfd_mach != 0)
1342a6b7db3Sskrll if (bfd_to_arch_table[i].bfd_mach == mach)
1352a6b7db3Sskrll return bfd_to_arch_table[i].arch_up;
1362a6b7db3Sskrll else
1372a6b7db3Sskrll i++;
1382a6b7db3Sskrll
1392a6b7db3Sskrll return SH_ARCH_UNKNOWN_ARCH;
1402a6b7db3Sskrll }
1412a6b7db3Sskrll
1422a6b7db3Sskrll
1432a6b7db3Sskrll /* Convert an arbitary arch_set - not necessarily corresponding
1442a6b7db3Sskrll directly to anything in the table above - to the most generic
1452a6b7db3Sskrll architecture which supports all the required features, and
1462a6b7db3Sskrll return the corresponding BFD mach. */
1472a6b7db3Sskrll
1482a6b7db3Sskrll unsigned long
sh_get_bfd_mach_from_arch_set(unsigned int arch_set)1492a6b7db3Sskrll sh_get_bfd_mach_from_arch_set (unsigned int arch_set)
1502a6b7db3Sskrll {
1512a6b7db3Sskrll unsigned long result = 0;
1522a6b7db3Sskrll unsigned int best = ~arch_set;
1532a6b7db3Sskrll unsigned int co_mask = ~0;
1542a6b7db3Sskrll int i = 0;
1552a6b7db3Sskrll
1562a6b7db3Sskrll /* If arch_set permits variants with no coprocessor then do not allow
1572a6b7db3Sskrll the other irrelevant co-processor bits to influence the choice:
1582a6b7db3Sskrll e.g. if dsp is disallowed by arch_set, then the algorithm would
1592a6b7db3Sskrll prefer fpu variants over nofpu variants because they also disallow
1602a6b7db3Sskrll dsp - even though the nofpu would be the most correct choice.
1612a6b7db3Sskrll This assumes that EVERY fpu/dsp variant has a no-coprocessor
1622a6b7db3Sskrll counter-part, or their non-fpu/dsp instructions do not have the
1632a6b7db3Sskrll no co-processor bit set. */
1642a6b7db3Sskrll if (arch_set & arch_sh_no_co)
1652a6b7db3Sskrll co_mask = ~(arch_sh_sp_fpu | arch_sh_dp_fpu | arch_sh_has_dsp);
1662a6b7db3Sskrll
1672a6b7db3Sskrll while (bfd_to_arch_table[i].bfd_mach != 0)
1682a6b7db3Sskrll {
1692a6b7db3Sskrll unsigned int try = bfd_to_arch_table[i].arch_up & co_mask;
1702a6b7db3Sskrll
1712a6b7db3Sskrll /* Conceptually: Find the architecture with the least number
1722a6b7db3Sskrll of extra features or, if they have the same number, then
1732a6b7db3Sskrll the greatest number of required features. Disregard
1742a6b7db3Sskrll architectures where the required features alone do
1752a6b7db3Sskrll not describe a valid architecture. */
1762a6b7db3Sskrll if (((try & ~arch_set) < (best & ~arch_set)
1772a6b7db3Sskrll || ((try & ~arch_set) == (best & ~arch_set)
1782a6b7db3Sskrll && (~try & arch_set) < (~best & arch_set)))
1792a6b7db3Sskrll && SH_MERGE_ARCH_SET_VALID (try, arch_set))
1802a6b7db3Sskrll {
1812a6b7db3Sskrll result = bfd_to_arch_table[i].bfd_mach;
1822a6b7db3Sskrll best = try;
1832a6b7db3Sskrll }
1842a6b7db3Sskrll
1852a6b7db3Sskrll i++;
1862a6b7db3Sskrll }
1872a6b7db3Sskrll
1882a6b7db3Sskrll /* This might happen if a new variant is added to sh-opc.h
1892a6b7db3Sskrll but no corresponding entry is added to the table above. */
1902a6b7db3Sskrll BFD_ASSERT (result != 0);
1912a6b7db3Sskrll
1922a6b7db3Sskrll return result;
1932a6b7db3Sskrll }
194