binutils-gdb/bfd/cpu-e2k.c

283 lines
9.8 KiB
C

/* BFD support for the E2K architecture.
Copyright 1992, 1995, 1996, 1998, 2000, 2002, 2005, 2007
Free Software Foundation, Inc.
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"
struct archname_item
{
const char *str;
size_t len;
};
static const char *
canonicalize_arch_name (const char *name, int *pmode)
{
int mode;
size_t len;
const char *pcolon = strchr (name, ':');
if (pcolon != NULL)
{
if (((pcolon[1] == '3' && pcolon[2] == '2' && (mode = 32))
|| (pcolon[1] == '6' && pcolon[2] == '4' && (mode = 64))
|| (pcolon[1] == 'p' && pcolon[2] == 'm' && (mode = 128)))
&& pcolon[3] == '\0')
len = pcolon - name;
else
return NULL;
}
else
{
mode = 64;
len = strlen (name);
}
#define STRNCMP(s1, s2, n) \
((n == sizeof (s2) - 1 && strncmp (s1, s2, n) == 0) ? 0 : 1)
if (STRNCMP (name, "generic", len) == 0
/* FIXME: `ARCH=e2k' is still used within the generated LD scripts for
E2K. Changing it to "generic" would result in a reference to some dummy
`bfd_arch_generic' which is definitely not the thing I need. */
|| STRNCMP (name, "e2k", len) == 0)
name = "generic";
else if (STRNCMP (name, "elbrus-v1", len) == 0
|| STRNCMP (name, "elbrus", len) == 0)
name = "elbrus-v1";
else if (STRNCMP (name, "elbrus-v2", len) == 0
|| STRNCMP (name, "elbrus-2c+", len) == 0
|| STRNCMP (name, "elbrus-2cm", len) == 0)
name = "elbrus-v2";
else if (STRNCMP (name, "elbrus-v3", len) == 0
|| STRNCMP (name, "elbrus-4c", len) == 0)
name = "elbrus-v3";
else if (STRNCMP (name, "elbrus-v4", len) == 0)
name = "elbrus-v4";
else if (STRNCMP (name, "elbrus-8c", len) == 0)
name = "elbrus-8c";
else if (STRNCMP (name, "elbrus-1c+", len) == 0)
name = "elbrus-1c+";
else if (STRNCMP (name, "elbrus-v5", len) == 0
|| STRNCMP (name, "elbrus-8c2", len) == 0)
name = "elbrus-v5";
else if (STRNCMP (name, "elbrus-v6", len) == 0)
name = "elbrus-v6";
else
return NULL;
#undef STRNCMP
*pmode = mode;
return name;
}
static bfd_boolean
e2k_scan (const struct bfd_arch_info *info, const char *string)
{
static const int modes[] = {64, 32, 128};
const char *canon;
int mode;
canon = canonicalize_arch_name (string, &mode);
if (canon != NULL
&& mode == modes[info->mach % 3]
&& strncmp (canon, info->printable_name, strlen (canon)) == 0)
return TRUE;
return FALSE;
}
extern const bfd_arch_info_type bfd_e2k_arch;
static const bfd_arch_info_type *
bfd_e2k_compatible (const bfd_arch_info_type *i, const bfd_arch_info_type *o)
{
if (i->arch != o->arch)
return NULL;
/* Check whether input and output BFDs have the same ABI. */
if (i->mach % 3 != o->mach % 3)
return NULL;
/* Nowadays that we should be able to dynamically choose an output
machine without `-A' (see Bug #58358) any further checks here
are meaningless. They are moved to `_bfd_e2k_merge_private_bfd_data'.
Just return our "generic" arch info in order not to upset
`lang_check ()'. It turns out that a value returned by this function
is not actually used at all except for aforementioned formal(?) check and
. . . GDB's `can_run_code_for ()' which expects us to return the "more
featureful" of the two arches. For it to succeed the returned arch should
coincide with that of the executable, which is the `I' argument of this
function). I think that it's quite reasonable to return `I' for now, since
its arch can't certainly turn out to be "less featureful" than the minimal
arch of the GDB's handler, represented by `O'. But this may very well
change once GDB for E2K gets "non-minimal" handlers!
By the way, why don't they want to let GDB's handler have a more advanced
arch than that of the executable? As far as I remember, this is because a
more "featureful" handler may require registers which aren't provided by
the executable's primitive ABI. */
return i;
}
#define BITS_ADDR_64 64
#define BITS_ADDR_32 32
#define BITS_ADDR_pm 32
#define MACH_64(mach) (3 * (mach))
#define MACH_32(mach) (3 * (mach) + 1)
#define MACH_pm(mach) (3 * (mach) + 2)
#define PRINT_PREFIX_64 "64-bit ABI for "
#define PRINT_PREFIX_32 "32-bit ABI for "
#define PRINT_PREFIX_PM "Protected ABI for "
#define N(ARCH, MODE, PRINT, DEFAULT, NEXT) \
{ \
/* We believe that E2k has 32 bits in a word for all architectures \
in all supported ABIs. I wonder whether it's actually so from \
the point of view of binutils. */ \
32, \
/* Number of bits in an address */ \
BITS_ADDR_##MODE, \
/* We have 8 bits in a byte everywhere. */ \
8, \
bfd_arch_e2k, \
/* Get an actual machine number used inside binutils while \
performing further checks. */ \
MACH_##MODE (ARCH), \
"e2k", \
PRINT ":" #MODE, \
/* Section alignment power. This should probably be \
revisited. */ \
4, \
DEFAULT, \
bfd_e2k_compatible, \
e2k_scan, \
bfd_arch_default_fill, \
NEXT \
}
/* These indices are used to refer to the next arch_info entry. I_generic_64
is not needed here since the corresponding entry is defined apart. */
enum
{
I_generic_32,
I_generic_pm,
I_ev1_64,
I_ev1_32,
I_ev1_pm,
I_ev2_64,
I_ev2_32,
I_ev2_pm,
I_ev3_64,
I_ev3_32,
I_ev3_pm,
I_ev4_64,
I_ev4_32,
I_ev4_pm,
I_ev5_64,
I_ev5_32,
I_ev5_pm,
I_ev6_64,
I_ev6_32,
I_ev6_pm,
I_8c_64,
I_8c_32,
I_8c_pm,
I_1cplus_64,
I_1cplus_32,
I_1cplus_pm,
};
#define NN(index) (&arch_info_struct[(index) + 1])
static const bfd_arch_info_type arch_info_struct[] =
{
/* The two remaining generic entries. */
N (bfd_mach_e2k_generic, 32, "generic", FALSE, NN (I_generic_32)),
N (bfd_mach_e2k_generic, pm, "generic", FALSE, NN (I_generic_pm)),
/* `elbrus-v1' entries. */
N (bfd_mach_e2k_ev1, 64, "elbrus-v1", FALSE, NN (I_ev1_64)),
N (bfd_mach_e2k_ev1, 32, "elbrus-v1", FALSE, NN (I_ev1_32)),
N (bfd_mach_e2k_ev1, pm, "elbrus-v1", FALSE, NN (I_ev1_pm)),
/* `elbrus-v2' entries. */
N (bfd_mach_e2k_ev2, 64, "elbrus-v2", FALSE, NN (I_ev2_64)),
N (bfd_mach_e2k_ev2, 32, "elbrus-v2", FALSE, NN (I_ev2_32)),
N (bfd_mach_e2k_ev2, pm, "elbrus-v2", FALSE, NN (I_ev2_pm)),
/* `elbrus-v3' entries. */
N (bfd_mach_e2k_ev3, 64, "elbrus-v3", FALSE, NN (I_ev3_64)),
N (bfd_mach_e2k_ev3, 32, "elbrus-v3", FALSE, NN (I_ev3_32)),
N (bfd_mach_e2k_ev3, pm, "elbrus-v3", FALSE, NN (I_ev3_pm)),
/* `elbrus-v4' entries. */
N (bfd_mach_e2k_ev4, 64, "elbrus-v4", FALSE, NN (I_ev4_64)),
N (bfd_mach_e2k_ev4, 32, "elbrus-v4", FALSE, NN (I_ev4_32)),
N (bfd_mach_e2k_ev4, pm, "elbrus-v4", FALSE, NN (I_ev4_pm)),
/* `elbrus-v5' entries. */
N (bfd_mach_e2k_ev5, 64, "elbrus-v5", FALSE, NN (I_ev5_64)),
N (bfd_mach_e2k_ev5, 32, "elbrus-v5", FALSE, NN (I_ev5_32)),
N (bfd_mach_e2k_ev5, pm, "elbrus-v5", FALSE, NN (I_ev5_pm)),
/* `elbrus-v6' entries. */
N (bfd_mach_e2k_ev6, 64, "elbrus-v6", FALSE, NN (I_ev6_64)),
N (bfd_mach_e2k_ev6, 32, "elbrus-v6", FALSE, NN (I_ev6_32)),
N (bfd_mach_e2k_ev6, pm, "elbrus-v6", FALSE, NN (I_ev6_pm)),
/* Entries, describing the specific `elbrus-8c' processor also known as
Processor-1 (elbrus-v4). */
N (bfd_mach_e2k_8c, 64, "elbrus-8c", FALSE, NN (I_8c_64)),
N (bfd_mach_e2k_8c, 32, "elbrus-8c", FALSE, NN (I_8c_32)),
N (bfd_mach_e2k_8c, pm, "elbrus-8c", FALSE, NN (I_8c_pm)),
/* Entries, describing the specific `elbrus-1c+' processor also known as
Processor-2 (elbrus-v4). */
N (bfd_mach_e2k_1cplus, 64, "elbrus-1c+", FALSE, NN (I_1cplus_64)),
N (bfd_mach_e2k_1cplus, 32, "elbrus-1c+", FALSE, NN (I_1cplus_32)),
N (bfd_mach_e2k_1cplus, pm, "elbrus-1c+", FALSE, NULL)
};
/* I don't remember for sure what DEFAULT actually means here. We should
probably only one default arch, however. Let it be a 64-bit elbrus
generic arch. */
const bfd_arch_info_type bfd_e2k_arch =
N (bfd_mach_e2k_generic, 64, "generic", TRUE, &arch_info_struct[0]);