xref: /openbsd-src/gnu/usr.bin/binutils/bfd/cpu-h8300.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
1c074d1c9Sdrahn /* BFD library support routines for the Renesas H8/300 architecture.
2c074d1c9Sdrahn    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2000, 2001, 2002, 2003
3b55d4692Sfgsch    Free Software Foundation, Inc.
42159047fSniklas    Hacked by Steve Chamberlain of Cygnus Support.
52159047fSniklas 
62159047fSniklas    This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas 
82159047fSniklas    This program is free software; you can redistribute it and/or modify
92159047fSniklas    it under the terms of the GNU General Public License as published by
102159047fSniklas    the Free Software Foundation; either version 2 of the License, or
112159047fSniklas    (at your option) any later version.
122159047fSniklas 
132159047fSniklas    This program is distributed in the hope that it will be useful,
142159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas    GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas    You should have received a copy of the GNU General Public License
192159047fSniklas    along with this program; if not, write to the Free Software
202159047fSniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas #include "bfd.h"
232159047fSniklas #include "sysdep.h"
242159047fSniklas #include "libbfd.h"
252159047fSniklas 
26c074d1c9Sdrahn static bfd_boolean
h8300_scan(const struct bfd_arch_info * info,const char * string)27*007c2a45Smiod h8300_scan (const struct bfd_arch_info *info, const char *string)
282159047fSniklas {
292159047fSniklas   if (*string != 'h' && *string != 'H')
30c074d1c9Sdrahn     return FALSE;
312159047fSniklas 
322159047fSniklas   string++;
332159047fSniklas   if (*string != '8')
34c074d1c9Sdrahn     return FALSE;
352159047fSniklas 
362159047fSniklas   string++;
372159047fSniklas   if (*string == '/')
382159047fSniklas     string++;
392159047fSniklas 
402159047fSniklas   if (*string != '3')
41c074d1c9Sdrahn     return FALSE;
422159047fSniklas   string++;
432159047fSniklas   if (*string != '0')
44c074d1c9Sdrahn     return FALSE;
452159047fSniklas   string++;
462159047fSniklas   if (*string != '0')
47c074d1c9Sdrahn     return FALSE;
482159047fSniklas   string++;
492159047fSniklas   if (*string == '-')
502159047fSniklas     string++;
51c074d1c9Sdrahn 
52c074d1c9Sdrahn   /* In ELF linker scripts, we typically express the architecture/machine
53c074d1c9Sdrahn      as architecture:machine.
54c074d1c9Sdrahn 
55c074d1c9Sdrahn      So if we've matched so far and encounter a colon, try to match the
56c074d1c9Sdrahn      string following the colon.  */
57c074d1c9Sdrahn   if (*string == ':')
58c074d1c9Sdrahn     {
59c074d1c9Sdrahn       string++;
60c074d1c9Sdrahn       return h8300_scan (info, string);
61c074d1c9Sdrahn     }
62c074d1c9Sdrahn 
632159047fSniklas   if (*string == 'h' || *string == 'H')
642159047fSniklas     {
65c074d1c9Sdrahn       string++;
66c074d1c9Sdrahn       if (*string == 'n' || *string == 'N')
67c074d1c9Sdrahn 	return (info->mach == bfd_mach_h8300hn);
68c074d1c9Sdrahn 
692159047fSniklas       return (info->mach == bfd_mach_h8300h);
702159047fSniklas     }
714361b62eSniklas   else if (*string == 's' || *string == 'S')
724361b62eSniklas     {
73c074d1c9Sdrahn       string++;
74c074d1c9Sdrahn       if (*string == 'n' || *string == 'N')
75c074d1c9Sdrahn 	return (info->mach == bfd_mach_h8300sn);
76c074d1c9Sdrahn 
77*007c2a45Smiod       if (*string == 'x' || *string == 'X')
78*007c2a45Smiod 	{
79*007c2a45Smiod 	  string++;
80*007c2a45Smiod 	  if (*string == 'n' || *string == 'N')
81*007c2a45Smiod 	    return (info->mach == bfd_mach_h8300sxn);
82*007c2a45Smiod 
83*007c2a45Smiod 	  return (info->mach == bfd_mach_h8300sx);
84*007c2a45Smiod 	}
85*007c2a45Smiod 
864361b62eSniklas       return (info->mach == bfd_mach_h8300s);
874361b62eSniklas     }
882159047fSniklas   else
892159047fSniklas     return info->mach == bfd_mach_h8300;
902159047fSniklas }
912159047fSniklas 
92b55d4692Sfgsch /* This routine is provided two arch_infos and works out the machine
93b55d4692Sfgsch    which would be compatible with both and returns a pointer to its
94b55d4692Sfgsch    info structure.  */
952159047fSniklas 
962159047fSniklas static const bfd_arch_info_type *
compatible(const bfd_arch_info_type * in,const bfd_arch_info_type * out)97*007c2a45Smiod compatible (const bfd_arch_info_type *in, const bfd_arch_info_type *out)
982159047fSniklas {
994361b62eSniklas   /* It's really not a good idea to mix and match modes.  */
100c074d1c9Sdrahn   if (in->arch != out->arch || in->mach != out->mach)
1012159047fSniklas     return 0;
1024361b62eSniklas   else
1032159047fSniklas     return in;
1042159047fSniklas }
1052159047fSniklas 
106*007c2a45Smiod static const bfd_arch_info_type h8300sxn_info_struct =
107*007c2a45Smiod {
108*007c2a45Smiod   32,				/* 32 bits in a word */
109*007c2a45Smiod   16,				/* 16 bits in an address */
110*007c2a45Smiod   8,				/* 8 bits in a byte */
111*007c2a45Smiod   bfd_arch_h8300,
112*007c2a45Smiod   bfd_mach_h8300sxn,
113*007c2a45Smiod   "h8300sxn",			/* arch_name  */
114*007c2a45Smiod   "h8300sxn",			/* printable name */
115*007c2a45Smiod   1,
116*007c2a45Smiod   FALSE,			/* the default machine */
117*007c2a45Smiod   compatible,
118*007c2a45Smiod   h8300_scan,
119*007c2a45Smiod   0
120*007c2a45Smiod };
121*007c2a45Smiod 
122*007c2a45Smiod static const bfd_arch_info_type h8300sx_info_struct =
123*007c2a45Smiod {
124*007c2a45Smiod   32,				/* 32 bits in a word */
125*007c2a45Smiod   32,				/* 32 bits in an address */
126*007c2a45Smiod   8,				/* 8 bits in a byte */
127*007c2a45Smiod   bfd_arch_h8300,
128*007c2a45Smiod   bfd_mach_h8300sx,
129*007c2a45Smiod   "h8300sx",			/* arch_name  */
130*007c2a45Smiod   "h8300sx",			/* printable name */
131*007c2a45Smiod   1,
132*007c2a45Smiod   FALSE,			/* the default machine */
133*007c2a45Smiod   compatible,
134*007c2a45Smiod   h8300_scan,
135*007c2a45Smiod   &h8300sxn_info_struct
136*007c2a45Smiod };
137*007c2a45Smiod 
138c074d1c9Sdrahn static const bfd_arch_info_type h8300sn_info_struct =
1392159047fSniklas {
140c074d1c9Sdrahn   32,				/* 32 bits in a word.  */
141*007c2a45Smiod   16,				/* 16 bits in an address.  */
142c074d1c9Sdrahn   8,				/* 8 bits in a byte.  */
1432159047fSniklas   bfd_arch_h8300,
144c074d1c9Sdrahn   bfd_mach_h8300sn,
145c074d1c9Sdrahn   "h8300sn",			/* Architecture name.  */
146c074d1c9Sdrahn   "h8300sn",			/* Printable name.  */
1472159047fSniklas   1,
148c074d1c9Sdrahn   FALSE,			/* The default machine.  */
1492159047fSniklas   compatible,
1502159047fSniklas   h8300_scan,
151*007c2a45Smiod   &h8300sx_info_struct
152c074d1c9Sdrahn };
153c074d1c9Sdrahn 
154c074d1c9Sdrahn static const bfd_arch_info_type h8300hn_info_struct =
155c074d1c9Sdrahn {
156c074d1c9Sdrahn   32,				/* 32 bits in a word.  */
157*007c2a45Smiod   16,				/* 16 bits in an address.  */
158c074d1c9Sdrahn   8,				/* 8 bits in a byte.  */
159c074d1c9Sdrahn   bfd_arch_h8300,
160c074d1c9Sdrahn   bfd_mach_h8300hn,
161c074d1c9Sdrahn   "h8300hn",			/* Architecture name.  */
162c074d1c9Sdrahn   "h8300hn",			/* Printable name.  */
163c074d1c9Sdrahn   1,
164c074d1c9Sdrahn   FALSE,			/* The default machine.  */
165c074d1c9Sdrahn   compatible,
166c074d1c9Sdrahn   h8300_scan,
167c074d1c9Sdrahn   &h8300sn_info_struct
168c074d1c9Sdrahn };
169c074d1c9Sdrahn 
170c074d1c9Sdrahn static const bfd_arch_info_type h8300s_info_struct =
171c074d1c9Sdrahn {
172c074d1c9Sdrahn   32,				/* 32 bits in a word.  */
173c074d1c9Sdrahn   32,				/* 32 bits in an address.  */
174c074d1c9Sdrahn   8,				/* 8 bits in a byte.  */
175c074d1c9Sdrahn   bfd_arch_h8300,
176c074d1c9Sdrahn   bfd_mach_h8300s,
177c074d1c9Sdrahn   "h8300s",			/* Architecture name.  */
178c074d1c9Sdrahn   "h8300s",			/* Printable name.  */
179c074d1c9Sdrahn   1,
180c074d1c9Sdrahn   FALSE,			/* The default machine.  */
181c074d1c9Sdrahn   compatible,
182c074d1c9Sdrahn   h8300_scan,
183c074d1c9Sdrahn   & h8300hn_info_struct
1842159047fSniklas };
1852159047fSniklas 
1864361b62eSniklas static const bfd_arch_info_type h8300h_info_struct =
1872159047fSniklas {
188c074d1c9Sdrahn   32,				/* 32 bits in a word.  */
189c074d1c9Sdrahn   32,				/* 32 bits in an address.  */
190c074d1c9Sdrahn   8,				/* 8 bits in a byte.  */
1912159047fSniklas   bfd_arch_h8300,
1922159047fSniklas   bfd_mach_h8300h,
193c074d1c9Sdrahn   "h8300h",			/* Architecture name.  */
194c074d1c9Sdrahn   "h8300h",			/* Printable name.  */
1952159047fSniklas   1,
196c074d1c9Sdrahn   FALSE,			/* The default machine.  */
1972159047fSniklas   compatible,
1982159047fSniklas   h8300_scan,
199c074d1c9Sdrahn   &h8300s_info_struct
2002159047fSniklas };
2014361b62eSniklas 
2024361b62eSniklas const bfd_arch_info_type bfd_h8300_arch =
2034361b62eSniklas {
204c074d1c9Sdrahn   16,				/* 16 bits in a word.  */
205c074d1c9Sdrahn   16,				/* 16 bits in an address.  */
206c074d1c9Sdrahn   8,				/* 8 bits in a byte.  */
2074361b62eSniklas   bfd_arch_h8300,
208c074d1c9Sdrahn   bfd_mach_h8300,
209c074d1c9Sdrahn   "h8300",			/* Architecture name.  */
210c074d1c9Sdrahn   "h8300",			/* Printable name.  */
2114361b62eSniklas   1,
212c074d1c9Sdrahn   TRUE,				/* The default machine.  */
2134361b62eSniklas   compatible,
2144361b62eSniklas   h8300_scan,
215c074d1c9Sdrahn   &h8300h_info_struct
2164361b62eSniklas };
217*007c2a45Smiod 
218*007c2a45Smiod /* Pad the given address to 32 bits, converting 16-bit and 24-bit
219*007c2a45Smiod    addresses into the values they would have had on a h8s target.  */
220*007c2a45Smiod 
221*007c2a45Smiod bfd_vma
bfd_h8300_pad_address(bfd * abfd,bfd_vma address)222*007c2a45Smiod bfd_h8300_pad_address (bfd *abfd, bfd_vma address)
223*007c2a45Smiod {
224*007c2a45Smiod   /* Cope with bfd_vma's larger than 32 bits.  */
225*007c2a45Smiod   address &= 0xffffffffu;
226*007c2a45Smiod 
227*007c2a45Smiod   switch (bfd_get_mach (abfd))
228*007c2a45Smiod     {
229*007c2a45Smiod     case bfd_mach_h8300:
230*007c2a45Smiod     case bfd_mach_h8300hn:
231*007c2a45Smiod     case bfd_mach_h8300sn:
232*007c2a45Smiod     case bfd_mach_h8300sxn:
233*007c2a45Smiod       /* Sign extend a 16-bit address.  */
234*007c2a45Smiod       if (address >= 0x8000)
235*007c2a45Smiod 	return address | 0xffff0000u;
236*007c2a45Smiod       return address;
237*007c2a45Smiod 
238*007c2a45Smiod     case bfd_mach_h8300h:
239*007c2a45Smiod       /* Sign extend a 24-bit address.  */
240*007c2a45Smiod       if (address >= 0x800000)
241*007c2a45Smiod 	return address | 0xff000000u;
242*007c2a45Smiod       return address;
243*007c2a45Smiod 
244*007c2a45Smiod     case bfd_mach_h8300s:
245*007c2a45Smiod     case bfd_mach_h8300sx:
246*007c2a45Smiod       return address;
247*007c2a45Smiod 
248*007c2a45Smiod     default:
249*007c2a45Smiod       abort ();
250*007c2a45Smiod     }
251*007c2a45Smiod }
252