| 1 | /* BFD library support routines for the Renesas / SuperH SH architecture. |
| 2 | Copyright (C) 1993-2020 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 | { |
| 112 | int i = 0; |
| 113 | |
| 114 | while (bfd_to_arch_table[i].bfd_mach != 0) |
| 115 | if (bfd_to_arch_table[i].bfd_mach == mach) |
| 116 | return bfd_to_arch_table[i].arch; |
| 117 | else |
| 118 | i++; |
| 119 | |
| 120 | /* Machine not found. */ |
| 121 | BFD_FAIL(); |
| 122 | |
| 123 | return SH_ARCH_UNKNOWN_ARCH; |
| 124 | } |
| 125 | |
| 126 | |
| 127 | /* Convert a BFD mach number into a set of opcodes arch flags |
| 128 | describing all the compatible architectures (i.e. arch_up) |
| 129 | using the table above. */ |
| 130 | |
| 131 | unsigned int |
| 132 | sh_get_arch_up_from_bfd_mach (unsigned long mach) |
| 133 | { |
| 134 | int i = 0; |
| 135 | |
| 136 | while (bfd_to_arch_table[i].bfd_mach != 0) |
| 137 | if (bfd_to_arch_table[i].bfd_mach == mach) |
| 138 | return bfd_to_arch_table[i].arch_up; |
| 139 | else |
| 140 | i++; |
| 141 | |
| 142 | /* Machine not found. */ |
| 143 | BFD_FAIL(); |
| 144 | |
| 145 | return SH_ARCH_UNKNOWN_ARCH; |
| 146 | } |
| 147 | |
| 148 | |
| 149 | /* Convert an arbitary arch_set - not necessarily corresponding |
| 150 | directly to anything in the table above - to the most generic |
| 151 | architecture which supports all the required features, and |
| 152 | return the corresponding BFD mach. */ |
| 153 | |
| 154 | unsigned long |
| 155 | sh_get_bfd_mach_from_arch_set (unsigned int arch_set) |
| 156 | { |
| 157 | unsigned long result = 0; |
| 158 | unsigned int best = ~arch_set; |
| 159 | unsigned int co_mask = ~0; |
| 160 | int i = 0; |
| 161 | |
| 162 | /* If arch_set permits variants with no coprocessor then do not allow |
| 163 | the other irrelevant co-processor bits to influence the choice: |
| 164 | e.g. if dsp is disallowed by arch_set, then the algorithm would |
| 165 | prefer fpu variants over nofpu variants because they also disallow |
| 166 | dsp - even though the nofpu would be the most correct choice. |
| 167 | This assumes that EVERY fpu/dsp variant has a no-coprocessor |
| 168 | counter-part, or their non-fpu/dsp instructions do not have the |
| 169 | no co-processor bit set. */ |
| 170 | if (arch_set & arch_sh_no_co) |
| 171 | co_mask = ~(arch_sh_sp_fpu | arch_sh_dp_fpu | arch_sh_has_dsp); |
| 172 | |
| 173 | while (bfd_to_arch_table[i].bfd_mach != 0) |
| 174 | { |
| 175 | unsigned int try = bfd_to_arch_table[i].arch_up & co_mask; |
| 176 | |
| 177 | /* Conceptually: Find the architecture with the least number |
| 178 | of extra features or, if they have the same number, then |
| 179 | the greatest number of required features. Disregard |
| 180 | architectures where the required features alone do |
| 181 | not describe a valid architecture. */ |
| 182 | if (((try & ~arch_set) < (best & ~arch_set) |
| 183 | || ((try & ~arch_set) == (best & ~arch_set) |
| 184 | && (~try & arch_set) < (~best & arch_set))) |
| 185 | && SH_MERGE_ARCH_SET_VALID (try, arch_set)) |
| 186 | { |
| 187 | result = bfd_to_arch_table[i].bfd_mach; |
| 188 | best = try; |
| 189 | } |
| 190 | |
| 191 | i++; |
| 192 | } |
| 193 | |
| 194 | /* This might happen if a new variant is added to sh-opc.h |
| 195 | but no corresponding entry is added to the table above. */ |
| 196 | BFD_ASSERT (result != 0); |
| 197 | |
| 198 | return result; |
| 199 | } |