xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/cpu-h8300.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* BFD library support routines for the Renesas H8/300 architecture.
2*e992f068Schristos    Copyright (C) 1990-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"
25012573ebSchristos #include "cpu-h8300.h"
2675fd0b74Schristos 
27*e992f068Schristos static bool
h8300_scan(const struct bfd_arch_info * info,const char * string)2875fd0b74Schristos h8300_scan (const struct bfd_arch_info *info, const char *string)
2975fd0b74Schristos {
3075fd0b74Schristos   if (*string != 'h' && *string != 'H')
31*e992f068Schristos     return false;
3275fd0b74Schristos 
3375fd0b74Schristos   string++;
3475fd0b74Schristos   if (*string != '8')
35*e992f068Schristos     return false;
3675fd0b74Schristos 
3775fd0b74Schristos   string++;
3875fd0b74Schristos   if (*string == '/')
3975fd0b74Schristos     string++;
4075fd0b74Schristos 
4175fd0b74Schristos   if (*string != '3')
42*e992f068Schristos     return false;
4375fd0b74Schristos   string++;
4475fd0b74Schristos   if (*string != '0')
45*e992f068Schristos     return false;
4675fd0b74Schristos   string++;
4775fd0b74Schristos   if (*string != '0')
48*e992f068Schristos     return false;
4975fd0b74Schristos   string++;
5075fd0b74Schristos   if (*string == '-')
5175fd0b74Schristos     string++;
5275fd0b74Schristos 
5375fd0b74Schristos   /* In ELF linker scripts, we typically express the architecture/machine
5475fd0b74Schristos      as architecture:machine.
5575fd0b74Schristos 
5675fd0b74Schristos      So if we've matched so far and encounter a colon, try to match the
5775fd0b74Schristos      string following the colon.  */
5875fd0b74Schristos   if (*string == ':')
5975fd0b74Schristos     {
6075fd0b74Schristos       string++;
6175fd0b74Schristos       return h8300_scan (info, string);
6275fd0b74Schristos     }
6375fd0b74Schristos 
6475fd0b74Schristos   if (*string == 'h' || *string == 'H')
6575fd0b74Schristos     {
6675fd0b74Schristos       string++;
6775fd0b74Schristos       if (*string == 'n' || *string == 'N')
6875fd0b74Schristos 	return (info->mach == bfd_mach_h8300hn);
6975fd0b74Schristos 
7075fd0b74Schristos       return (info->mach == bfd_mach_h8300h);
7175fd0b74Schristos     }
7275fd0b74Schristos   else if (*string == 's' || *string == 'S')
7375fd0b74Schristos     {
7475fd0b74Schristos       string++;
7575fd0b74Schristos       if (*string == 'n' || *string == 'N')
7675fd0b74Schristos 	return (info->mach == bfd_mach_h8300sn);
7775fd0b74Schristos 
7875fd0b74Schristos       if (*string == 'x' || *string == 'X')
7975fd0b74Schristos 	{
8075fd0b74Schristos 	  string++;
8175fd0b74Schristos 	  if (*string == 'n' || *string == 'N')
8275fd0b74Schristos 	    return (info->mach == bfd_mach_h8300sxn);
8375fd0b74Schristos 
8475fd0b74Schristos 	  return (info->mach == bfd_mach_h8300sx);
8575fd0b74Schristos 	}
8675fd0b74Schristos 
8775fd0b74Schristos       return (info->mach == bfd_mach_h8300s);
8875fd0b74Schristos     }
8975fd0b74Schristos   else
9075fd0b74Schristos     return info->mach == bfd_mach_h8300;
9175fd0b74Schristos }
9275fd0b74Schristos 
9375fd0b74Schristos /* This routine is provided two arch_infos and works out the machine
9475fd0b74Schristos    which would be compatible with both and returns a pointer to its
9575fd0b74Schristos    info structure.  */
9675fd0b74Schristos 
9775fd0b74Schristos static const bfd_arch_info_type *
compatible(const bfd_arch_info_type * in,const bfd_arch_info_type * out)9875fd0b74Schristos compatible (const bfd_arch_info_type *in, const bfd_arch_info_type *out)
9975fd0b74Schristos {
10075fd0b74Schristos   if (in->arch != out->arch)
10175fd0b74Schristos     return 0;
10275fd0b74Schristos   if (in->mach == bfd_mach_h8300sx && out->mach == bfd_mach_h8300s)
10375fd0b74Schristos     return in;
10475fd0b74Schristos   if (in->mach == bfd_mach_h8300s && out->mach == bfd_mach_h8300sx)
10575fd0b74Schristos     return out;
10675fd0b74Schristos   if (in->mach == bfd_mach_h8300sxn && out->mach == bfd_mach_h8300sn)
10775fd0b74Schristos     return in;
10875fd0b74Schristos   if (in->mach == bfd_mach_h8300sn && out->mach == bfd_mach_h8300sxn)
10975fd0b74Schristos     return out;
11075fd0b74Schristos   /* It's really not a good idea to mix and match modes.  */
11175fd0b74Schristos   if (in->mach != out->mach)
11275fd0b74Schristos     return 0;
11375fd0b74Schristos   else
11475fd0b74Schristos     return in;
11575fd0b74Schristos }
11675fd0b74Schristos 
117012573ebSchristos #define N(word, addr, number, name, print, default, next)	  \
118012573ebSchristos   { word, addr, 8, bfd_arch_h8300, number, name, print, 1, default, \
119012573ebSchristos     compatible, h8300_scan, bfd_arch_default_fill, next, 0 }
120012573ebSchristos 
12175fd0b74Schristos static const bfd_arch_info_type h8300sxn_info_struct =
122*e992f068Schristos   N (32, 16, bfd_mach_h8300sxn, "h8300sxn", "h8300sxn", false, NULL);
12375fd0b74Schristos 
12475fd0b74Schristos static const bfd_arch_info_type h8300sx_info_struct =
125*e992f068Schristos   N (32, 32, bfd_mach_h8300sx, "h8300sx", "h8300sx", false, &h8300sxn_info_struct);
12675fd0b74Schristos 
12775fd0b74Schristos static const bfd_arch_info_type h8300sn_info_struct =
128*e992f068Schristos   N (32, 16, bfd_mach_h8300sn, "h8300sn", "h8300sn", false, &h8300sx_info_struct);
12975fd0b74Schristos 
13075fd0b74Schristos static const bfd_arch_info_type h8300hn_info_struct =
131*e992f068Schristos   N (32, 16, bfd_mach_h8300hn, "h8300hn", "h8300hn", false, &h8300sn_info_struct);
13275fd0b74Schristos 
13375fd0b74Schristos static const bfd_arch_info_type h8300s_info_struct =
134*e992f068Schristos   N (32, 32, bfd_mach_h8300s, "h8300s", "h8300s", false, & h8300hn_info_struct);
13575fd0b74Schristos 
13675fd0b74Schristos static const bfd_arch_info_type h8300h_info_struct =
137*e992f068Schristos   N (32, 32, bfd_mach_h8300h, "h8300h", "h8300h", false, &h8300s_info_struct);
13875fd0b74Schristos 
13975fd0b74Schristos const bfd_arch_info_type bfd_h8300_arch =
140*e992f068Schristos   N (16, 16, bfd_mach_h8300, "h8300", "h8300", true, &h8300h_info_struct);
14175fd0b74Schristos 
14275fd0b74Schristos /* Pad the given address to 32 bits, converting 16-bit and 24-bit
14375fd0b74Schristos    addresses into the values they would have had on a h8s target.  */
14475fd0b74Schristos 
14575fd0b74Schristos bfd_vma
bfd_h8300_pad_address(bfd * abfd,bfd_vma address)14675fd0b74Schristos bfd_h8300_pad_address (bfd *abfd, bfd_vma address)
14775fd0b74Schristos {
14875fd0b74Schristos   /* Cope with bfd_vma's larger than 32 bits.  */
14975fd0b74Schristos   address &= 0xffffffffu;
15075fd0b74Schristos 
15175fd0b74Schristos   switch (bfd_get_mach (abfd))
15275fd0b74Schristos     {
15375fd0b74Schristos     case bfd_mach_h8300:
15475fd0b74Schristos     case bfd_mach_h8300hn:
15575fd0b74Schristos     case bfd_mach_h8300sn:
15675fd0b74Schristos     case bfd_mach_h8300sxn:
15775fd0b74Schristos       /* Sign extend a 16-bit address.  */
15875fd0b74Schristos       if (address >= 0x8000)
15975fd0b74Schristos 	return address | 0xffff0000u;
16075fd0b74Schristos       return address;
16175fd0b74Schristos 
16275fd0b74Schristos     case bfd_mach_h8300h:
16375fd0b74Schristos       /* Sign extend a 24-bit address.  */
16475fd0b74Schristos       if (address >= 0x800000)
16575fd0b74Schristos 	return address | 0xff000000u;
16675fd0b74Schristos       return address;
16775fd0b74Schristos 
16875fd0b74Schristos     case bfd_mach_h8300s:
16975fd0b74Schristos     case bfd_mach_h8300sx:
17075fd0b74Schristos       return address;
17175fd0b74Schristos 
17275fd0b74Schristos     default:
17375fd0b74Schristos       abort ();
17475fd0b74Schristos     }
17575fd0b74Schristos }
176