xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/cpu-sh.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* BFD library support routines for the Renesas / SuperH SH architecture.
2*e992f068Schristos    Copyright (C) 1993-2022 Free Software Foundation, Inc.
375fd0b74Schristos    Hacked by Steve Chamberlain of Cygnus Support.
475fd0b74Schristos 
575fd0b74Schristos    This file is part of BFD, the Binary File Descriptor library.
675fd0b74Schristos 
775fd0b74Schristos    This program is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or
1075fd0b74Schristos    (at your option) any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    This program is distributed in the hope that it will be useful,
1375fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1475fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1575fd0b74Schristos    GNU General Public License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this program; if not, write to the Free Software
1975fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
2075fd0b74Schristos    MA 02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos #include "sysdep.h"
2375fd0b74Schristos #include "bfd.h"
2475fd0b74Schristos #include "libbfd.h"
2575fd0b74Schristos #include "../opcodes/sh-opc.h"
2675fd0b74Schristos 
27012573ebSchristos 
28012573ebSchristos #define N(NUMBER, PRINT, DEFAULT, NEXT)			\
29012573ebSchristos   {							\
30012573ebSchristos     32,     /* Bits in a word.  */			\
31012573ebSchristos     32,     /* Bits in an address.  */			\
32012573ebSchristos     8,	    /* Bits in a byte.  */			\
33012573ebSchristos     bfd_arch_sh,					\
34012573ebSchristos     NUMBER,						\
35012573ebSchristos     "sh",						\
36012573ebSchristos     PRINT,						\
37012573ebSchristos     1,		/* Section alignment power.  */		\
38012573ebSchristos     DEFAULT,						\
39012573ebSchristos     bfd_default_compatible,				\
40012573ebSchristos     bfd_default_scan,					\
41012573ebSchristos     bfd_arch_default_fill,				\
42012573ebSchristos     NEXT,						\
43012573ebSchristos     0 /* Maximum offset of a reloc from the start of an insn.  */ \
44012573ebSchristos   }
4575fd0b74Schristos 
4675fd0b74Schristos static const bfd_arch_info_type arch_info_struct[] =
4775fd0b74Schristos {
48*e992f068Schristos   N (bfd_mach_sh2,          "sh2",       false, arch_info_struct + 1),
49*e992f068Schristos   N (bfd_mach_sh2e,         "sh2e",      false, arch_info_struct + 2),
50*e992f068Schristos   N (bfd_mach_sh_dsp,       "sh-dsp",    false, arch_info_struct + 3),
51*e992f068Schristos   N (bfd_mach_sh3,          "sh3",       false, arch_info_struct + 4),
52*e992f068Schristos   N (bfd_mach_sh3_nommu,    "sh3-nommu", false, arch_info_struct + 5),
53*e992f068Schristos   N (bfd_mach_sh3_dsp,      "sh3-dsp",   false, arch_info_struct + 6),
54*e992f068Schristos   N (bfd_mach_sh3e,         "sh3e",      false, arch_info_struct + 7),
55*e992f068Schristos   N (bfd_mach_sh4,          "sh4",       false, arch_info_struct + 8),
56*e992f068Schristos   N (bfd_mach_sh4a,         "sh4a",      false, arch_info_struct + 9),
57*e992f068Schristos   N (bfd_mach_sh4al_dsp,    "sh4al-dsp", false, arch_info_struct + 10),
58*e992f068Schristos   N (bfd_mach_sh4_nofpu,    "sh4-nofpu", false, arch_info_struct + 11),
59*e992f068Schristos   N (bfd_mach_sh4_nommu_nofpu, "sh4-nommu-nofpu", false, arch_info_struct + 12),
60*e992f068Schristos   N (bfd_mach_sh4a_nofpu,   "sh4a-nofpu", false, arch_info_struct + 13),
61*e992f068Schristos   N (bfd_mach_sh2a,         "sh2a",       false, arch_info_struct + 14),
62*e992f068Schristos   N (bfd_mach_sh2a_nofpu,   "sh2a-nofpu", false, arch_info_struct + 15),
63*e992f068Schristos   N (bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, "sh2a-nofpu-or-sh4-nommu-nofpu", false, arch_info_struct + 16),
64*e992f068Schristos   N (bfd_mach_sh2a_nofpu_or_sh3_nommu, "sh2a-nofpu-or-sh3-nommu", false, arch_info_struct + 17),
65*e992f068Schristos   N (bfd_mach_sh2a_or_sh4,  "sh2a-or-sh4",  false, arch_info_struct + 18),
66*e992f068Schristos   N (bfd_mach_sh2a_or_sh3e, "sh2a-or-sh3e", false, NULL)
6775fd0b74Schristos };
6875fd0b74Schristos 
6975fd0b74Schristos const bfd_arch_info_type bfd_sh_arch =
70*e992f068Schristos   N (bfd_mach_sh, "sh", true, arch_info_struct + 0);
7175fd0b74Schristos 
7275fd0b74Schristos /* This table defines the mappings from the BFD internal numbering
7375fd0b74Schristos    system to the opcodes internal flags system.
7475fd0b74Schristos    It is used by the functions defined below.
7575fd0b74Schristos    The prototypes for these SH specific functions are found in
7675fd0b74Schristos    sh-opc.h .  */
7775fd0b74Schristos 
7875fd0b74Schristos static struct { unsigned long bfd_mach, arch, arch_up; } bfd_to_arch_table[] =
7975fd0b74Schristos {
8075fd0b74Schristos   { bfd_mach_sh,	      arch_sh1,		    arch_sh_up },
8175fd0b74Schristos   { bfd_mach_sh2,	      arch_sh2,		    arch_sh2_up },
8275fd0b74Schristos   { bfd_mach_sh2e,	      arch_sh2e,	    arch_sh2e_up },
8375fd0b74Schristos   { bfd_mach_sh_dsp,	      arch_sh_dsp,	    arch_sh_dsp_up },
8475fd0b74Schristos   { bfd_mach_sh2a,	      arch_sh2a,	    arch_sh2a_up },
8575fd0b74Schristos   { bfd_mach_sh2a_nofpu,      arch_sh2a_nofpu,	    arch_sh2a_nofpu_up },
8675fd0b74Schristos 
8775fd0b74Schristos   { bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu,	    arch_sh2a_nofpu_or_sh4_nommu_nofpu,	  arch_sh2a_nofpu_or_sh4_nommu_nofpu_up },
8875fd0b74Schristos   { bfd_mach_sh2a_nofpu_or_sh3_nommu,		    arch_sh2a_nofpu_or_sh3_nommu,	  arch_sh2a_nofpu_or_sh3_nommu_up },
8975fd0b74Schristos   { bfd_mach_sh2a_or_sh4,     arch_sh2a_or_sh4,	    arch_sh2a_or_sh4_up },
9075fd0b74Schristos   { bfd_mach_sh2a_or_sh3e,    arch_sh2a_or_sh3e,    arch_sh2a_or_sh3e_up },
9175fd0b74Schristos 
9275fd0b74Schristos   { bfd_mach_sh3,	      arch_sh3,		    arch_sh3_up },
9375fd0b74Schristos   { bfd_mach_sh3_nommu,	      arch_sh3_nommu,	    arch_sh3_nommu_up },
9475fd0b74Schristos   { bfd_mach_sh3_dsp,	      arch_sh3_dsp,	    arch_sh3_dsp_up },
9575fd0b74Schristos   { bfd_mach_sh3e,	      arch_sh3e,	    arch_sh3e_up },
9675fd0b74Schristos   { bfd_mach_sh4,	      arch_sh4,		    arch_sh4_up },
9775fd0b74Schristos   { bfd_mach_sh4a,	      arch_sh4a,	    arch_sh4a_up },
9875fd0b74Schristos   { bfd_mach_sh4al_dsp,	      arch_sh4al_dsp,	    arch_sh4al_dsp_up },
9975fd0b74Schristos   { bfd_mach_sh4_nofpu,	      arch_sh4_nofpu,	    arch_sh4_nofpu_up },
10075fd0b74Schristos   { bfd_mach_sh4_nommu_nofpu, arch_sh4_nommu_nofpu, arch_sh4_nommu_nofpu_up },
10175fd0b74Schristos   { bfd_mach_sh4a_nofpu,      arch_sh4a_nofpu,	    arch_sh4a_nofpu_up },
10275fd0b74Schristos   { 0, 0, 0 }	/* Terminator.  */
10375fd0b74Schristos };
10475fd0b74Schristos 
10575fd0b74Schristos 
10675fd0b74Schristos /* Convert a BFD mach number into the right opcodes arch flags
10775fd0b74Schristos    using the table above.  */
10875fd0b74Schristos 
10975fd0b74Schristos unsigned int
sh_get_arch_from_bfd_mach(unsigned long mach)11075fd0b74Schristos sh_get_arch_from_bfd_mach (unsigned long mach)
11175fd0b74Schristos {
11275fd0b74Schristos   int i = 0;
11375fd0b74Schristos 
11475fd0b74Schristos   while (bfd_to_arch_table[i].bfd_mach != 0)
11575fd0b74Schristos     if (bfd_to_arch_table[i].bfd_mach == mach)
11675fd0b74Schristos       return bfd_to_arch_table[i].arch;
11775fd0b74Schristos     else
11875fd0b74Schristos       i++;
11975fd0b74Schristos 
12075fd0b74Schristos   /* Machine not found.   */
12175fd0b74Schristos   BFD_FAIL();
12275fd0b74Schristos 
12375fd0b74Schristos   return SH_ARCH_UNKNOWN_ARCH;
12475fd0b74Schristos }
12575fd0b74Schristos 
12675fd0b74Schristos 
12775fd0b74Schristos /* Convert a BFD mach number into a set of opcodes arch flags
12875fd0b74Schristos    describing all the compatible architectures (i.e. arch_up)
12975fd0b74Schristos    using the table above.  */
13075fd0b74Schristos 
13175fd0b74Schristos unsigned int
sh_get_arch_up_from_bfd_mach(unsigned long mach)13275fd0b74Schristos sh_get_arch_up_from_bfd_mach (unsigned long mach)
13375fd0b74Schristos {
13475fd0b74Schristos   int i = 0;
13575fd0b74Schristos 
13675fd0b74Schristos   while (bfd_to_arch_table[i].bfd_mach != 0)
13775fd0b74Schristos     if (bfd_to_arch_table[i].bfd_mach == mach)
13875fd0b74Schristos       return bfd_to_arch_table[i].arch_up;
13975fd0b74Schristos     else
14075fd0b74Schristos       i++;
14175fd0b74Schristos 
14275fd0b74Schristos   /* Machine not found.  */
14375fd0b74Schristos   BFD_FAIL();
14475fd0b74Schristos 
14575fd0b74Schristos   return SH_ARCH_UNKNOWN_ARCH;
14675fd0b74Schristos }
14775fd0b74Schristos 
14875fd0b74Schristos 
14975fd0b74Schristos /* Convert an arbitary arch_set - not necessarily corresponding
15075fd0b74Schristos    directly to anything in the table above - to the most generic
15175fd0b74Schristos    architecture which supports all the required features, and
15275fd0b74Schristos    return the corresponding BFD mach.  */
15375fd0b74Schristos 
15475fd0b74Schristos unsigned long
sh_get_bfd_mach_from_arch_set(unsigned int arch_set)15575fd0b74Schristos sh_get_bfd_mach_from_arch_set (unsigned int arch_set)
15675fd0b74Schristos {
15775fd0b74Schristos   unsigned long result = 0;
15875fd0b74Schristos   unsigned int best = ~arch_set;
15975fd0b74Schristos   unsigned int co_mask = ~0;
16075fd0b74Schristos   int i = 0;
16175fd0b74Schristos 
16275fd0b74Schristos   /* If arch_set permits variants with no coprocessor then do not allow
16375fd0b74Schristos      the other irrelevant co-processor bits to influence the choice:
16475fd0b74Schristos        e.g. if dsp is disallowed by arch_set, then the algorithm would
16575fd0b74Schristos        prefer fpu variants over nofpu variants because they also disallow
16675fd0b74Schristos        dsp - even though the nofpu would be the most correct choice.
16775fd0b74Schristos      This assumes that EVERY fpu/dsp variant has a no-coprocessor
16875fd0b74Schristos      counter-part, or their non-fpu/dsp instructions do not have the
16975fd0b74Schristos      no co-processor bit set.  */
17075fd0b74Schristos   if (arch_set & arch_sh_no_co)
17175fd0b74Schristos     co_mask = ~(arch_sh_sp_fpu | arch_sh_dp_fpu | arch_sh_has_dsp);
17275fd0b74Schristos 
17375fd0b74Schristos   while (bfd_to_arch_table[i].bfd_mach != 0)
17475fd0b74Schristos     {
17575fd0b74Schristos       unsigned int try = bfd_to_arch_table[i].arch_up & co_mask;
17675fd0b74Schristos 
17775fd0b74Schristos       /* Conceptually: Find the architecture with the least number
17875fd0b74Schristos 	 of extra features or, if they have the same number, then
17975fd0b74Schristos 	 the greatest number of required features.  Disregard
18075fd0b74Schristos 	 architectures where the required features alone do
18175fd0b74Schristos 	 not describe a valid architecture.  */
18275fd0b74Schristos       if (((try & ~arch_set) < (best & ~arch_set)
18375fd0b74Schristos 	   || ((try & ~arch_set) == (best & ~arch_set)
18475fd0b74Schristos 	       && (~try & arch_set) < (~best & arch_set)))
18575fd0b74Schristos 	  && SH_MERGE_ARCH_SET_VALID (try, arch_set))
18675fd0b74Schristos 	{
18775fd0b74Schristos 	  result = bfd_to_arch_table[i].bfd_mach;
18875fd0b74Schristos 	  best = try;
18975fd0b74Schristos 	}
19075fd0b74Schristos 
19175fd0b74Schristos       i++;
19275fd0b74Schristos     }
19375fd0b74Schristos 
19475fd0b74Schristos   /* This might happen if a new variant is added to sh-opc.h
19575fd0b74Schristos      but no corresponding entry is added to the table above.  */
19675fd0b74Schristos   BFD_ASSERT (result != 0);
19775fd0b74Schristos 
19875fd0b74Schristos   return result;
19975fd0b74Schristos }
200