1/* BFD library support routines for the Renesas H8/300 architecture.
2   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2000, 2001, 2002,
3   2003, 2004, 2007 Free Software Foundation, Inc.
4   Hacked by Steve Chamberlain of Cygnus Support.
5
6   This file is part of BFD, the Binary File Descriptor library.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21   MA 02110-1301, USA.  */
22
23#include "sysdep.h"
24#include "bfd.h"
25#include "libbfd.h"
26
27static bfd_boolean
28h8300_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
97static const bfd_arch_info_type *
98compatible (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
117static const bfd_arch_info_type h8300sxn_info_struct =
118{
119  32,				/* 32 bits in a word */
120  16,				/* 16 bits in an address */
121  8,				/* 8 bits in a byte */
122  bfd_arch_h8300,
123  bfd_mach_h8300sxn,
124  "h8300sxn",			/* arch_name  */
125  "h8300sxn",			/* printable name */
126  1,
127  FALSE,			/* the default machine */
128  compatible,
129  h8300_scan,
130  0
131};
132
133static const bfd_arch_info_type h8300sx_info_struct =
134{
135  32,				/* 32 bits in a word */
136  32,				/* 32 bits in an address */
137  8,				/* 8 bits in a byte */
138  bfd_arch_h8300,
139  bfd_mach_h8300sx,
140  "h8300sx",			/* arch_name  */
141  "h8300sx",			/* printable name */
142  1,
143  FALSE,			/* the default machine */
144  compatible,
145  h8300_scan,
146  &h8300sxn_info_struct
147};
148
149static const bfd_arch_info_type h8300sn_info_struct =
150{
151  32,				/* 32 bits in a word.  */
152  16,				/* 16 bits in an address.  */
153  8,				/* 8 bits in a byte.  */
154  bfd_arch_h8300,
155  bfd_mach_h8300sn,
156  "h8300sn",			/* Architecture name.  */
157  "h8300sn",			/* Printable name.  */
158  1,
159  FALSE,			/* The default machine.  */
160  compatible,
161  h8300_scan,
162  &h8300sx_info_struct
163};
164
165static const bfd_arch_info_type h8300hn_info_struct =
166{
167  32,				/* 32 bits in a word.  */
168  16,				/* 16 bits in an address.  */
169  8,				/* 8 bits in a byte.  */
170  bfd_arch_h8300,
171  bfd_mach_h8300hn,
172  "h8300hn",			/* Architecture name.  */
173  "h8300hn",			/* Printable name.  */
174  1,
175  FALSE,			/* The default machine.  */
176  compatible,
177  h8300_scan,
178  &h8300sn_info_struct
179};
180
181static const bfd_arch_info_type h8300s_info_struct =
182{
183  32,				/* 32 bits in a word.  */
184  32,				/* 32 bits in an address.  */
185  8,				/* 8 bits in a byte.  */
186  bfd_arch_h8300,
187  bfd_mach_h8300s,
188  "h8300s",			/* Architecture name.  */
189  "h8300s",			/* Printable name.  */
190  1,
191  FALSE,			/* The default machine.  */
192  compatible,
193  h8300_scan,
194  & h8300hn_info_struct
195};
196
197static const bfd_arch_info_type h8300h_info_struct =
198{
199  32,				/* 32 bits in a word.  */
200  32,				/* 32 bits in an address.  */
201  8,				/* 8 bits in a byte.  */
202  bfd_arch_h8300,
203  bfd_mach_h8300h,
204  "h8300h",			/* Architecture name.  */
205  "h8300h",			/* Printable name.  */
206  1,
207  FALSE,			/* The default machine.  */
208  compatible,
209  h8300_scan,
210  &h8300s_info_struct
211};
212
213const bfd_arch_info_type bfd_h8300_arch =
214{
215  16,				/* 16 bits in a word.  */
216  16,				/* 16 bits in an address.  */
217  8,				/* 8 bits in a byte.  */
218  bfd_arch_h8300,
219  bfd_mach_h8300,
220  "h8300",			/* Architecture name.  */
221  "h8300",			/* Printable name.  */
222  1,
223  TRUE,				/* The default machine.  */
224  compatible,
225  h8300_scan,
226  &h8300h_info_struct
227};
228
229/* Pad the given address to 32 bits, converting 16-bit and 24-bit
230   addresses into the values they would have had on a h8s target.  */
231
232bfd_vma
233bfd_h8300_pad_address (bfd *abfd, bfd_vma address)
234{
235  /* Cope with bfd_vma's larger than 32 bits.  */
236  address &= 0xffffffffu;
237
238  switch (bfd_get_mach (abfd))
239    {
240    case bfd_mach_h8300:
241    case bfd_mach_h8300hn:
242    case bfd_mach_h8300sn:
243    case bfd_mach_h8300sxn:
244      /* Sign extend a 16-bit address.  */
245      if (address >= 0x8000)
246	return address | 0xffff0000u;
247      return address;
248
249    case bfd_mach_h8300h:
250      /* Sign extend a 24-bit address.  */
251      if (address >= 0x800000)
252	return address | 0xff000000u;
253      return address;
254
255    case bfd_mach_h8300s:
256    case bfd_mach_h8300sx:
257      return address;
258
259    default:
260      abort ();
261    }
262}
263