You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
6.6 KiB
268 lines
6.6 KiB
/* BFD library support routines for the Renesas H8/300 architecture. |
|
Copyright (C) 1990-2014 Free Software Foundation, Inc. |
|
Hacked by Steve Chamberlain of Cygnus Support. |
|
|
|
This file is part of BFD, the Binary File Descriptor library. |
|
|
|
This program is free software; you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation; either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program; if not, write to the Free Software |
|
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
|
MA 02110-1301, USA. */ |
|
|
|
#include "sysdep.h" |
|
#include "bfd.h" |
|
#include "libbfd.h" |
|
|
|
static bfd_boolean |
|
h8300_scan (const struct bfd_arch_info *info, const char *string) |
|
{ |
|
if (*string != 'h' && *string != 'H') |
|
return FALSE; |
|
|
|
string++; |
|
if (*string != '8') |
|
return FALSE; |
|
|
|
string++; |
|
if (*string == '/') |
|
string++; |
|
|
|
if (*string != '3') |
|
return FALSE; |
|
string++; |
|
if (*string != '0') |
|
return FALSE; |
|
string++; |
|
if (*string != '0') |
|
return FALSE; |
|
string++; |
|
if (*string == '-') |
|
string++; |
|
|
|
/* In ELF linker scripts, we typically express the architecture/machine |
|
as architecture:machine. |
|
|
|
So if we've matched so far and encounter a colon, try to match the |
|
string following the colon. */ |
|
if (*string == ':') |
|
{ |
|
string++; |
|
return h8300_scan (info, string); |
|
} |
|
|
|
if (*string == 'h' || *string == 'H') |
|
{ |
|
string++; |
|
if (*string == 'n' || *string == 'N') |
|
return (info->mach == bfd_mach_h8300hn); |
|
|
|
return (info->mach == bfd_mach_h8300h); |
|
} |
|
else if (*string == 's' || *string == 'S') |
|
{ |
|
string++; |
|
if (*string == 'n' || *string == 'N') |
|
return (info->mach == bfd_mach_h8300sn); |
|
|
|
if (*string == 'x' || *string == 'X') |
|
{ |
|
string++; |
|
if (*string == 'n' || *string == 'N') |
|
return (info->mach == bfd_mach_h8300sxn); |
|
|
|
return (info->mach == bfd_mach_h8300sx); |
|
} |
|
|
|
return (info->mach == bfd_mach_h8300s); |
|
} |
|
else |
|
return info->mach == bfd_mach_h8300; |
|
} |
|
|
|
/* This routine is provided two arch_infos and works out the machine |
|
which would be compatible with both and returns a pointer to its |
|
info structure. */ |
|
|
|
static const bfd_arch_info_type * |
|
compatible (const bfd_arch_info_type *in, const bfd_arch_info_type *out) |
|
{ |
|
if (in->arch != out->arch) |
|
return 0; |
|
if (in->mach == bfd_mach_h8300sx && out->mach == bfd_mach_h8300s) |
|
return in; |
|
if (in->mach == bfd_mach_h8300s && out->mach == bfd_mach_h8300sx) |
|
return out; |
|
if (in->mach == bfd_mach_h8300sxn && out->mach == bfd_mach_h8300sn) |
|
return in; |
|
if (in->mach == bfd_mach_h8300sn && out->mach == bfd_mach_h8300sxn) |
|
return out; |
|
/* It's really not a good idea to mix and match modes. */ |
|
if (in->mach != out->mach) |
|
return 0; |
|
else |
|
return in; |
|
} |
|
|
|
static const bfd_arch_info_type h8300sxn_info_struct = |
|
{ |
|
32, /* 32 bits in a word */ |
|
16, /* 16 bits in an address */ |
|
8, /* 8 bits in a byte */ |
|
bfd_arch_h8300, |
|
bfd_mach_h8300sxn, |
|
"h8300sxn", /* arch_name */ |
|
"h8300sxn", /* printable name */ |
|
1, |
|
FALSE, /* the default machine */ |
|
compatible, |
|
h8300_scan, |
|
bfd_arch_default_fill, |
|
0 |
|
}; |
|
|
|
static const bfd_arch_info_type h8300sx_info_struct = |
|
{ |
|
32, /* 32 bits in a word */ |
|
32, /* 32 bits in an address */ |
|
8, /* 8 bits in a byte */ |
|
bfd_arch_h8300, |
|
bfd_mach_h8300sx, |
|
"h8300sx", /* arch_name */ |
|
"h8300sx", /* printable name */ |
|
1, |
|
FALSE, /* the default machine */ |
|
compatible, |
|
h8300_scan, |
|
bfd_arch_default_fill, |
|
&h8300sxn_info_struct |
|
}; |
|
|
|
static const bfd_arch_info_type h8300sn_info_struct = |
|
{ |
|
32, /* 32 bits in a word. */ |
|
16, /* 16 bits in an address. */ |
|
8, /* 8 bits in a byte. */ |
|
bfd_arch_h8300, |
|
bfd_mach_h8300sn, |
|
"h8300sn", /* Architecture name. */ |
|
"h8300sn", /* Printable name. */ |
|
1, |
|
FALSE, /* The default machine. */ |
|
compatible, |
|
h8300_scan, |
|
bfd_arch_default_fill, |
|
&h8300sx_info_struct |
|
}; |
|
|
|
static const bfd_arch_info_type h8300hn_info_struct = |
|
{ |
|
32, /* 32 bits in a word. */ |
|
16, /* 16 bits in an address. */ |
|
8, /* 8 bits in a byte. */ |
|
bfd_arch_h8300, |
|
bfd_mach_h8300hn, |
|
"h8300hn", /* Architecture name. */ |
|
"h8300hn", /* Printable name. */ |
|
1, |
|
FALSE, /* The default machine. */ |
|
compatible, |
|
h8300_scan, |
|
bfd_arch_default_fill, |
|
&h8300sn_info_struct |
|
}; |
|
|
|
static const bfd_arch_info_type h8300s_info_struct = |
|
{ |
|
32, /* 32 bits in a word. */ |
|
32, /* 32 bits in an address. */ |
|
8, /* 8 bits in a byte. */ |
|
bfd_arch_h8300, |
|
bfd_mach_h8300s, |
|
"h8300s", /* Architecture name. */ |
|
"h8300s", /* Printable name. */ |
|
1, |
|
FALSE, /* The default machine. */ |
|
compatible, |
|
h8300_scan, |
|
bfd_arch_default_fill, |
|
& h8300hn_info_struct |
|
}; |
|
|
|
static const bfd_arch_info_type h8300h_info_struct = |
|
{ |
|
32, /* 32 bits in a word. */ |
|
32, /* 32 bits in an address. */ |
|
8, /* 8 bits in a byte. */ |
|
bfd_arch_h8300, |
|
bfd_mach_h8300h, |
|
"h8300h", /* Architecture name. */ |
|
"h8300h", /* Printable name. */ |
|
1, |
|
FALSE, /* The default machine. */ |
|
compatible, |
|
h8300_scan, |
|
bfd_arch_default_fill, |
|
&h8300s_info_struct |
|
}; |
|
|
|
const bfd_arch_info_type bfd_h8300_arch = |
|
{ |
|
16, /* 16 bits in a word. */ |
|
16, /* 16 bits in an address. */ |
|
8, /* 8 bits in a byte. */ |
|
bfd_arch_h8300, |
|
bfd_mach_h8300, |
|
"h8300", /* Architecture name. */ |
|
"h8300", /* Printable name. */ |
|
1, |
|
TRUE, /* The default machine. */ |
|
compatible, |
|
h8300_scan, |
|
bfd_arch_default_fill, |
|
&h8300h_info_struct |
|
}; |
|
|
|
/* Pad the given address to 32 bits, converting 16-bit and 24-bit |
|
addresses into the values they would have had on a h8s target. */ |
|
|
|
bfd_vma |
|
bfd_h8300_pad_address (bfd *abfd, bfd_vma address) |
|
{ |
|
/* Cope with bfd_vma's larger than 32 bits. */ |
|
address &= 0xffffffffu; |
|
|
|
switch (bfd_get_mach (abfd)) |
|
{ |
|
case bfd_mach_h8300: |
|
case bfd_mach_h8300hn: |
|
case bfd_mach_h8300sn: |
|
case bfd_mach_h8300sxn: |
|
/* Sign extend a 16-bit address. */ |
|
if (address >= 0x8000) |
|
return address | 0xffff0000u; |
|
return address; |
|
|
|
case bfd_mach_h8300h: |
|
/* Sign extend a 24-bit address. */ |
|
if (address >= 0x800000) |
|
return address | 0xff000000u; |
|
return address; |
|
|
|
case bfd_mach_h8300s: |
|
case bfd_mach_h8300sx: |
|
return address; |
|
|
|
default: |
|
abort (); |
|
} |
|
}
|
|
|