1 /* BFD library support routines for the Renesas H8/300 architecture. 2 Copyright (C) 1990-2022 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 "cpu-h8300.h" 26 27 static bool 28 h8300_scan (const struct bfd_arch_info *info, const char *string) 29 { 30 if (*string != 'h' && *string != 'H') 31 return false; 32 33 string++; 34 if (*string != '8') 35 return false; 36 37 string++; 38 if (*string == '/') 39 string++; 40 41 if (*string != '3') 42 return false; 43 string++; 44 if (*string != '0') 45 return false; 46 string++; 47 if (*string != '0') 48 return false; 49 string++; 50 if (*string == '-') 51 string++; 52 53 /* In ELF linker scripts, we typically express the architecture/machine 54 as architecture:machine. 55 56 So if we've matched so far and encounter a colon, try to match the 57 string following the colon. */ 58 if (*string == ':') 59 { 60 string++; 61 return h8300_scan (info, string); 62 } 63 64 if (*string == 'h' || *string == 'H') 65 { 66 string++; 67 if (*string == 'n' || *string == 'N') 68 return (info->mach == bfd_mach_h8300hn); 69 70 return (info->mach == bfd_mach_h8300h); 71 } 72 else if (*string == 's' || *string == 'S') 73 { 74 string++; 75 if (*string == 'n' || *string == 'N') 76 return (info->mach == bfd_mach_h8300sn); 77 78 if (*string == 'x' || *string == 'X') 79 { 80 string++; 81 if (*string == 'n' || *string == 'N') 82 return (info->mach == bfd_mach_h8300sxn); 83 84 return (info->mach == bfd_mach_h8300sx); 85 } 86 87 return (info->mach == bfd_mach_h8300s); 88 } 89 else 90 return info->mach == bfd_mach_h8300; 91 } 92 93 /* This routine is provided two arch_infos and works out the machine 94 which would be compatible with both and returns a pointer to its 95 info structure. */ 96 97 static const bfd_arch_info_type * 98 compatible (const bfd_arch_info_type *in, const bfd_arch_info_type *out) 99 { 100 if (in->arch != out->arch) 101 return 0; 102 if (in->mach == bfd_mach_h8300sx && out->mach == bfd_mach_h8300s) 103 return in; 104 if (in->mach == bfd_mach_h8300s && out->mach == bfd_mach_h8300sx) 105 return out; 106 if (in->mach == bfd_mach_h8300sxn && out->mach == bfd_mach_h8300sn) 107 return in; 108 if (in->mach == bfd_mach_h8300sn && out->mach == bfd_mach_h8300sxn) 109 return out; 110 /* It's really not a good idea to mix and match modes. */ 111 if (in->mach != out->mach) 112 return 0; 113 else 114 return in; 115 } 116 117 #define N(word, addr, number, name, print, default, next) \ 118 { word, addr, 8, bfd_arch_h8300, number, name, print, 1, default, \ 119 compatible, h8300_scan, bfd_arch_default_fill, next, 0 } 120 121 static const bfd_arch_info_type h8300sxn_info_struct = 122 N (32, 16, bfd_mach_h8300sxn, "h8300sxn", "h8300sxn", false, NULL); 123 124 static const bfd_arch_info_type h8300sx_info_struct = 125 N (32, 32, bfd_mach_h8300sx, "h8300sx", "h8300sx", false, &h8300sxn_info_struct); 126 127 static const bfd_arch_info_type h8300sn_info_struct = 128 N (32, 16, bfd_mach_h8300sn, "h8300sn", "h8300sn", false, &h8300sx_info_struct); 129 130 static const bfd_arch_info_type h8300hn_info_struct = 131 N (32, 16, bfd_mach_h8300hn, "h8300hn", "h8300hn", false, &h8300sn_info_struct); 132 133 static const bfd_arch_info_type h8300s_info_struct = 134 N (32, 32, bfd_mach_h8300s, "h8300s", "h8300s", false, & h8300hn_info_struct); 135 136 static const bfd_arch_info_type h8300h_info_struct = 137 N (32, 32, bfd_mach_h8300h, "h8300h", "h8300h", false, &h8300s_info_struct); 138 139 const bfd_arch_info_type bfd_h8300_arch = 140 N (16, 16, bfd_mach_h8300, "h8300", "h8300", true, &h8300h_info_struct); 141 142 /* Pad the given address to 32 bits, converting 16-bit and 24-bit 143 addresses into the values they would have had on a h8s target. */ 144 145 bfd_vma 146 bfd_h8300_pad_address (bfd *abfd, bfd_vma address) 147 { 148 /* Cope with bfd_vma's larger than 32 bits. */ 149 address &= 0xffffffffu; 150 151 switch (bfd_get_mach (abfd)) 152 { 153 case bfd_mach_h8300: 154 case bfd_mach_h8300hn: 155 case bfd_mach_h8300sn: 156 case bfd_mach_h8300sxn: 157 /* Sign extend a 16-bit address. */ 158 if (address >= 0x8000) 159 return address | 0xffff0000u; 160 return address; 161 162 case bfd_mach_h8300h: 163 /* Sign extend a 24-bit address. */ 164 if (address >= 0x800000) 165 return address | 0xff000000u; 166 return address; 167 168 case bfd_mach_h8300s: 169 case bfd_mach_h8300sx: 170 return address; 171 172 default: 173 abort (); 174 } 175 } 176