/src/binutils-gdb/bfd/cpu-sh.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* BFD library support routines for the Renesas / SuperH SH architecture. |
2 | | Copyright (C) 1993-2025 Free Software Foundation, Inc. |
3 | | Hacked by Steve Chamberlain of Cygnus Support. |
4 | | |
5 | | This file is part of BFD, the Binary File Descriptor library. |
6 | | |
7 | | This program is free software; you can redistribute it and/or modify |
8 | | it under the terms of the GNU General Public License as published by |
9 | | the Free Software Foundation; either version 3 of the License, or |
10 | | (at your option) any later version. |
11 | | |
12 | | This program is distributed in the hope that it will be useful, |
13 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | GNU General Public License for more details. |
16 | | |
17 | | You should have received a copy of the GNU General Public License |
18 | | along with this program; if not, write to the Free Software |
19 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
20 | | MA 02110-1301, USA. */ |
21 | | |
22 | | #include "sysdep.h" |
23 | | #include "bfd.h" |
24 | | #include "libbfd.h" |
25 | | #include "../opcodes/sh-opc.h" |
26 | | |
27 | | |
28 | | #define N(NUMBER, PRINT, DEFAULT, NEXT) \ |
29 | | { \ |
30 | | 32, /* Bits in a word. */ \ |
31 | | 32, /* Bits in an address. */ \ |
32 | | 8, /* Bits in a byte. */ \ |
33 | | bfd_arch_sh, \ |
34 | | NUMBER, \ |
35 | | "sh", \ |
36 | | PRINT, \ |
37 | | 1, /* Section alignment power. */ \ |
38 | | DEFAULT, \ |
39 | | bfd_default_compatible, \ |
40 | | bfd_default_scan, \ |
41 | | bfd_arch_default_fill, \ |
42 | | NEXT, \ |
43 | | 0 /* Maximum offset of a reloc from the start of an insn. */ \ |
44 | | } |
45 | | |
46 | | static const bfd_arch_info_type arch_info_struct[] = |
47 | | { |
48 | | N (bfd_mach_sh2, "sh2", false, arch_info_struct + 1), |
49 | | N (bfd_mach_sh2e, "sh2e", false, arch_info_struct + 2), |
50 | | N (bfd_mach_sh_dsp, "sh-dsp", false, arch_info_struct + 3), |
51 | | N (bfd_mach_sh3, "sh3", false, arch_info_struct + 4), |
52 | | N (bfd_mach_sh3_nommu, "sh3-nommu", false, arch_info_struct + 5), |
53 | | N (bfd_mach_sh3_dsp, "sh3-dsp", false, arch_info_struct + 6), |
54 | | N (bfd_mach_sh3e, "sh3e", false, arch_info_struct + 7), |
55 | | N (bfd_mach_sh4, "sh4", false, arch_info_struct + 8), |
56 | | N (bfd_mach_sh4a, "sh4a", false, arch_info_struct + 9), |
57 | | N (bfd_mach_sh4al_dsp, "sh4al-dsp", false, arch_info_struct + 10), |
58 | | N (bfd_mach_sh4_nofpu, "sh4-nofpu", false, arch_info_struct + 11), |
59 | | N (bfd_mach_sh4_nommu_nofpu, "sh4-nommu-nofpu", false, arch_info_struct + 12), |
60 | | N (bfd_mach_sh4a_nofpu, "sh4a-nofpu", false, arch_info_struct + 13), |
61 | | N (bfd_mach_sh2a, "sh2a", false, arch_info_struct + 14), |
62 | | N (bfd_mach_sh2a_nofpu, "sh2a-nofpu", false, arch_info_struct + 15), |
63 | | N (bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, "sh2a-nofpu-or-sh4-nommu-nofpu", false, arch_info_struct + 16), |
64 | | N (bfd_mach_sh2a_nofpu_or_sh3_nommu, "sh2a-nofpu-or-sh3-nommu", false, arch_info_struct + 17), |
65 | | N (bfd_mach_sh2a_or_sh4, "sh2a-or-sh4", false, arch_info_struct + 18), |
66 | | N (bfd_mach_sh2a_or_sh3e, "sh2a-or-sh3e", false, NULL) |
67 | | }; |
68 | | |
69 | | const bfd_arch_info_type bfd_sh_arch = |
70 | | N (bfd_mach_sh, "sh", true, arch_info_struct + 0); |
71 | | |
72 | | /* This table defines the mappings from the BFD internal numbering |
73 | | system to the opcodes internal flags system. |
74 | | It is used by the functions defined below. |
75 | | The prototypes for these SH specific functions are found in |
76 | | sh-opc.h . */ |
77 | | |
78 | | static struct { unsigned long bfd_mach, arch, arch_up; } bfd_to_arch_table[] = |
79 | | { |
80 | | { bfd_mach_sh, arch_sh1, arch_sh_up }, |
81 | | { bfd_mach_sh2, arch_sh2, arch_sh2_up }, |
82 | | { bfd_mach_sh2e, arch_sh2e, arch_sh2e_up }, |
83 | | { bfd_mach_sh_dsp, arch_sh_dsp, arch_sh_dsp_up }, |
84 | | { bfd_mach_sh2a, arch_sh2a, arch_sh2a_up }, |
85 | | { bfd_mach_sh2a_nofpu, arch_sh2a_nofpu, arch_sh2a_nofpu_up }, |
86 | | |
87 | | { bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu, arch_sh2a_nofpu_or_sh4_nommu_nofpu, arch_sh2a_nofpu_or_sh4_nommu_nofpu_up }, |
88 | | { bfd_mach_sh2a_nofpu_or_sh3_nommu, arch_sh2a_nofpu_or_sh3_nommu, arch_sh2a_nofpu_or_sh3_nommu_up }, |
89 | | { bfd_mach_sh2a_or_sh4, arch_sh2a_or_sh4, arch_sh2a_or_sh4_up }, |
90 | | { bfd_mach_sh2a_or_sh3e, arch_sh2a_or_sh3e, arch_sh2a_or_sh3e_up }, |
91 | | |
92 | | { bfd_mach_sh3, arch_sh3, arch_sh3_up }, |
93 | | { bfd_mach_sh3_nommu, arch_sh3_nommu, arch_sh3_nommu_up }, |
94 | | { bfd_mach_sh3_dsp, arch_sh3_dsp, arch_sh3_dsp_up }, |
95 | | { bfd_mach_sh3e, arch_sh3e, arch_sh3e_up }, |
96 | | { bfd_mach_sh4, arch_sh4, arch_sh4_up }, |
97 | | { bfd_mach_sh4a, arch_sh4a, arch_sh4a_up }, |
98 | | { bfd_mach_sh4al_dsp, arch_sh4al_dsp, arch_sh4al_dsp_up }, |
99 | | { bfd_mach_sh4_nofpu, arch_sh4_nofpu, arch_sh4_nofpu_up }, |
100 | | { bfd_mach_sh4_nommu_nofpu, arch_sh4_nommu_nofpu, arch_sh4_nommu_nofpu_up }, |
101 | | { bfd_mach_sh4a_nofpu, arch_sh4a_nofpu, arch_sh4a_nofpu_up }, |
102 | | { 0, 0, 0 } /* Terminator. */ |
103 | | }; |
104 | | |
105 | | |
106 | | /* Convert a BFD mach number into the right opcodes arch flags |
107 | | using the table above. */ |
108 | | |
109 | | unsigned int |
110 | | sh_get_arch_from_bfd_mach (unsigned long mach) |
111 | 4.01M | { |
112 | 4.01M | int i = 0; |
113 | | |
114 | 30.4M | while (bfd_to_arch_table[i].bfd_mach != 0) |
115 | 30.0M | if (bfd_to_arch_table[i].bfd_mach == mach) |
116 | 3.65M | return bfd_to_arch_table[i].arch; |
117 | 26.4M | else |
118 | 26.4M | i++; |
119 | | |
120 | 365k | return SH_ARCH_UNKNOWN_ARCH; |
121 | 4.01M | } |
122 | | |
123 | | |
124 | | /* Convert a BFD mach number into a set of opcodes arch flags |
125 | | describing all the compatible architectures (i.e. arch_up) |
126 | | using the table above. */ |
127 | | |
128 | | unsigned int |
129 | | sh_get_arch_up_from_bfd_mach (unsigned long mach) |
130 | 0 | { |
131 | 0 | int i = 0; |
132 | |
|
133 | 0 | while (bfd_to_arch_table[i].bfd_mach != 0) |
134 | 0 | if (bfd_to_arch_table[i].bfd_mach == mach) |
135 | 0 | return bfd_to_arch_table[i].arch_up; |
136 | 0 | else |
137 | 0 | i++; |
138 | | |
139 | 0 | return SH_ARCH_UNKNOWN_ARCH; |
140 | 0 | } |
141 | | |
142 | | |
143 | | /* Convert an arbitary arch_set - not necessarily corresponding |
144 | | directly to anything in the table above - to the most generic |
145 | | architecture which supports all the required features, and |
146 | | return the corresponding BFD mach. */ |
147 | | |
148 | | unsigned long |
149 | | sh_get_bfd_mach_from_arch_set (unsigned int arch_set) |
150 | 0 | { |
151 | 0 | unsigned long result = 0; |
152 | 0 | unsigned int best = ~arch_set; |
153 | 0 | unsigned int co_mask = ~0; |
154 | 0 | int i = 0; |
155 | | |
156 | | /* If arch_set permits variants with no coprocessor then do not allow |
157 | | the other irrelevant co-processor bits to influence the choice: |
158 | | e.g. if dsp is disallowed by arch_set, then the algorithm would |
159 | | prefer fpu variants over nofpu variants because they also disallow |
160 | | dsp - even though the nofpu would be the most correct choice. |
161 | | This assumes that EVERY fpu/dsp variant has a no-coprocessor |
162 | | counter-part, or their non-fpu/dsp instructions do not have the |
163 | | no co-processor bit set. */ |
164 | 0 | if (arch_set & arch_sh_no_co) |
165 | 0 | co_mask = ~(arch_sh_sp_fpu | arch_sh_dp_fpu | arch_sh_has_dsp); |
166 | |
|
167 | 0 | while (bfd_to_arch_table[i].bfd_mach != 0) |
168 | 0 | { |
169 | 0 | unsigned int try = bfd_to_arch_table[i].arch_up & co_mask; |
170 | | |
171 | | /* Conceptually: Find the architecture with the least number |
172 | | of extra features or, if they have the same number, then |
173 | | the greatest number of required features. Disregard |
174 | | architectures where the required features alone do |
175 | | not describe a valid architecture. */ |
176 | 0 | if (((try & ~arch_set) < (best & ~arch_set) |
177 | 0 | || ((try & ~arch_set) == (best & ~arch_set) |
178 | 0 | && (~try & arch_set) < (~best & arch_set))) |
179 | 0 | && SH_MERGE_ARCH_SET_VALID (try, arch_set)) |
180 | 0 | { |
181 | 0 | result = bfd_to_arch_table[i].bfd_mach; |
182 | 0 | best = try; |
183 | 0 | } |
184 | |
|
185 | 0 | i++; |
186 | 0 | } |
187 | | |
188 | | /* This might happen if a new variant is added to sh-opc.h |
189 | | but no corresponding entry is added to the table above. */ |
190 | 0 | BFD_ASSERT (result != 0); |
191 | |
|
192 | 0 | return result; |
193 | 0 | } |