diff options
Diffstat (limited to 'gdb/arc-architecture.c')
-rwxr-xr-x | gdb/arc-architecture.c | 502 |
1 files changed, 502 insertions, 0 deletions
diff --git a/gdb/arc-architecture.c b/gdb/arc-architecture.c new file mode 100755 index 0000000..f520d61 --- /dev/null +++ b/gdb/arc-architecture.c @@ -0,0 +1,502 @@ +/* Target dependent code for ARC processor family, for GDB, the GNU debugger. + + Copyright 2008, 2009 Free Software Foundation, Inc. + + Contributed by ARC International (www.arc.com) + + Author: + Richard Stuckey <richard.stuckey@arc.com> + + This file is part of GDB. + + 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, see <http://www.gnu.org/licenses/>. */ + +/******************************************************************************/ +/* */ +/* Outline: */ +/* This module provides support for handling the architectural version of */ +/* of the ARC target processor. */ +/* */ +/* Architectural Checks: */ +/* Checks upon architectural consistency are (currently) performed at */ +/* these points: */ +/* */ +/* 1) after connection to target */ +/* 2) after reading (non-default) XML file */ +/* 3) after blasting JTAG target FPGA */ +/* 4) after attaching to JTAG target */ +/* 5) after selecting executable file */ +/* 6) before downloading program to target */ +/* */ +/******************************************************************************/ + +/* gdb header files. */ +#include "defs.h" +#include "objfiles.h" +#include "arch-utils.h" +#include "gdb-events.h" +#include "gdb_assert.h" + +/* ARC header files. */ +#include "arc-architecture.h" +#include "arc-elf32-tdep.h" + + +/* -------------------------------------------------------------------------- */ +/* local types */ +/* -------------------------------------------------------------------------- */ + +typedef enum +{ + DEFAULT_SIMULATOR_WITH_NO_AUXILIARY_REGISTERS, + DEFAULT_SIMULATOR_WITH_AUXILIARY_REGISTERS, + SELECTED_SIMULATOR_WITH_NO_AUXILIARY_REGISTERS, + SELECTED_SIMULATOR_WITH_AUXILIARY_REGISTERS, + TARGET_WITH_NO_AUXILIARY_REGISTERS, + TARGET_WITH_AUXILIARY_REGISTERS, + EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS, + EXECUTABLE_WITH_AUXILIARY_REGISTERS, + DEFAULT_SIMULATOR_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS, + DEFAULT_SIMULATOR_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS, + SELECTED_SIMULATOR_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS, + SELECTED_SIMULATOR_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS, + TARGET_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS, + TARGET_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS, + NO_ERROR +} Diagnostic; + + +/* -------------------------------------------------------------------------- */ +/* local data */ +/* -------------------------------------------------------------------------- */ + +/* N.B. the messages MUST correspond to the values in the Diagnostic enumeration + type above, as a value of that type is used to index the array. */ + +static const char *messages[] = +{ + "default simulator architecture is %s but auxiliary registers are not defined", + "default simulator architecture is %s but auxiliary registers are defined for %s", + "selected simulator architecture is %s but auxiliary registers are not defined", + "selected simulator architecture is %s but auxiliary registers are defined for %s", + "target architecture is %s but auxiliary registers are not defined", + "target architecture is %s but auxiliary registers are defined for %s", + "executable file %s is built for %s but auxiliary registers are not defined", + "executable file %s is built for %s but auxiliary registers are defined for %s", + "default simulator architecture is %s, executable file %s is built for %s but auxiliary registers are not defined", + "default simulator architecture is %s, executable file %s is built for %s and auxiliary registers are defined for %s", + "selected simulator is %s, executable file %s is built for %s but auxiliary registers are not defined", + "selected simulator is %s, executable file %s is built for %s and auxiliary registers are defined for %s", + "target architecture is %s, executable file %s is built for %s but auxiliary registers are not defined", + "target architecture is %s, executable file %s is built for %s and auxiliary registers are defined for %s" +}; + + +/* This is the architecture of the current target. */ +static ARC_ProcessorVersion ARC_processor = NO_ARCHITECTURE; + + +/* -------------------------------------------------------------------------- */ +/* local functions */ +/* -------------------------------------------------------------------------- */ + +/* Map the BFD architerctural type onto the ARC processor type. */ + +static ARC_ProcessorVersion +architecture (const bfd_arch_info_type *arch) +{ + switch (arch->mach) + { + case bfd_mach_arc_a5 : return A5; + case bfd_mach_arc_arc600: return ARC600; + case bfd_mach_arc_arc700: return ARC700; + default : return UNSUPPORTED_ARCHITECTURE; + } +} + + +/* This function performs the architectural consistency check. + + Parameters: + target : the architectural version of the target + auxregs : the architectural version of the auxiliary registers + program : the architectural version of the executable program + is_builtin_simulator: TRUE if the target is the built-in simulator + is_default : TRUE if built-in simulator's version is the default + objfile_bfd : a pointer to the BFD for the object file + + If the check fails, an appropriate warning message is output. */ + +static void +perform_check (ARC_ProcessorVersion target, + ARC_ProcessorVersion auxregs, + ARC_ProcessorVersion program, + Boolean is_builtin_simulator, + bfd_boolean is_default, + bfd *objfile_bfd) +{ + Diagnostic diagnostic = NO_ERROR; + + /* If we do not yet have an object file (and hence we do not know the + program's architecture). */ + if (program == NO_ARCHITECTURE) + { + if (target != auxregs) + { + if (is_builtin_simulator) + { + if (is_default) + { + if (auxregs == NO_ARCHITECTURE) + diagnostic = DEFAULT_SIMULATOR_WITH_NO_AUXILIARY_REGISTERS; + else + diagnostic = DEFAULT_SIMULATOR_WITH_AUXILIARY_REGISTERS; + } + else + { + if (auxregs == NO_ARCHITECTURE) + diagnostic = SELECTED_SIMULATOR_WITH_NO_AUXILIARY_REGISTERS; + else + diagnostic = SELECTED_SIMULATOR_WITH_AUXILIARY_REGISTERS; + } + } + else + if (auxregs == NO_ARCHITECTURE) + diagnostic = TARGET_WITH_NO_AUXILIARY_REGISTERS; + else + diagnostic = TARGET_WITH_AUXILIARY_REGISTERS; + } + } + else + { + if (program != target || program != auxregs) + { + if (is_builtin_simulator) + { + if (target == program) + { + if (auxregs == NO_ARCHITECTURE) + diagnostic = EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS; + else + diagnostic = EXECUTABLE_WITH_AUXILIARY_REGISTERS; + } + else + { + if (is_default) + { + if (auxregs == NO_ARCHITECTURE) + diagnostic = DEFAULT_SIMULATOR_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS; + else + diagnostic = DEFAULT_SIMULATOR_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS; + } + else + { + if (auxregs == NO_ARCHITECTURE) + diagnostic = SELECTED_SIMULATOR_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS; + else + diagnostic = SELECTED_SIMULATOR_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS; + } + } + } + else + if (auxregs == NO_ARCHITECTURE) + diagnostic = TARGET_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS; + else + diagnostic = TARGET_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS; + } + } + + if (diagnostic != NO_ERROR) + { + const char *message = messages[diagnostic]; + + switch (diagnostic) + { + case DEFAULT_SIMULATOR_WITH_NO_AUXILIARY_REGISTERS: + case SELECTED_SIMULATOR_WITH_NO_AUXILIARY_REGISTERS: + case TARGET_WITH_NO_AUXILIARY_REGISTERS: + warning(message, arc_version_image(target)); + break; + + case DEFAULT_SIMULATOR_WITH_AUXILIARY_REGISTERS: + case SELECTED_SIMULATOR_WITH_AUXILIARY_REGISTERS: + case TARGET_WITH_AUXILIARY_REGISTERS: + warning(message, arc_version_image(target), arc_version_image(auxregs)); + break; + + case EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS: + warning(message, objfile_bfd->filename, arc_version_image(program)); + break; + + case EXECUTABLE_WITH_AUXILIARY_REGISTERS: + warning(message, objfile_bfd->filename, arc_version_image(program), arc_version_image(auxregs)); + break; + + case DEFAULT_SIMULATOR_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS: + case SELECTED_SIMULATOR_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS: + case TARGET_AND_EXECUTABLE_WITH_NO_AUXILIARY_REGISTERS: + warning(message, arc_version_image(target), objfile_bfd->filename, arc_version_image(program)); + break; + + case DEFAULT_SIMULATOR_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS: + case SELECTED_SIMULATOR_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS: + case TARGET_AND_EXECUTABLE_WITH_AUXILIARY_REGISTERS: + warning(message, arc_version_image(target), objfile_bfd->filename, arc_version_image(program), arc_version_image(auxregs)); + break; + + default: + break; + } + } +} + + +/* -------------------------------------------------------------------------- */ +/* externally visible functions */ +/* -------------------------------------------------------------------------- */ + +/* Set the architectural version of the target processor as being unknown. */ + +void +arc_architecture_is_unknown (void) +{ + ARC_processor = NO_ARCHITECTURE; +} + + +/* Return the processor variant that is connected. */ + +ARC_ProcessorVersion +arc_get_architecture (ReadRegisterFunction read_aux_register) +{ + ENTERMSG; + + if (ARC_processor == NO_ARCHITECTURE) + { + ARC_RegisterNumber identity_regnum = arc_aux_find_register_number("IDENTITY", ARC_HW_IDENTITY_REGNUM); + ARC_RegisterContents value; + + if (read_aux_register(identity_regnum, &value, TRUE)) + { + DEBUG("IDENTITY = 0x%X\n", value); + + /* Get the processor version number. */ + value &= IDENTITY_ARCVER; + + if ((value >= 0x30) && (value <= 0x3f)) + ARC_processor = ARC700; + else if ((value >= 0x20) && (value <= 0x2f)) + ARC_processor = ARC600; + else if ((value >= 0x10) && (value <= 0x1f)) + ARC_processor = A5; + else if (value <= 0x0f) + ARC_processor = A4; + else + warning(_("unsupported processor version 0x%x"), value); + + DEBUG("target (from IDENTITY) is %s\n", arc_version_image(ARC_processor)); + } + } + + return ARC_processor; +} + + +/* Get the target processor architecture, check that is it supported, and + * update any architecture-related information that gdb requires. */ + +void +arc_update_architecture (ReadRegisterFunction read_register) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + ARC_ProcessorVersion version = arc_get_architecture(read_register); + + /* Record the target processor architecture in the targt-dependent + * variant information. */ + tdep->processor_variant_info->processor_version = version; + + switch (version) + { + case NO_ARCHITECTURE: + break; + case ARC700: + set_gdbarch_decr_pc_after_break (current_gdbarch, 0); + break; + case ARC600: + set_gdbarch_decr_pc_after_break (current_gdbarch, 2); + break; + case A5: + warning(_("A5 debugging is unsupported and may be unreliable.")); + break; + case A4: + /* N.B. this will not return. */ + error(_("A4 debugging is unsupported.")); + break; + case UNSUPPORTED_ARCHITECTURE: + break; + } +} + + +/* This function checks for architectural consistency; there are three possible + architectures to be considered: + + 1) the architecture for which the program to be debugged has been built + 2) the architecture of the target upon which the program is to be debugged + 3) the architecture for which we have a description of the auxiliary registers + + The 'gdbarch' parameter to this function corresponds to 2). + + A hardware target (such as an ARCangel) has a fixed architecture (e.g. that + defined by the XBF file used to configure it; and the xISS simulator's + architecture is defined by the simulator definition (.xis) file; however, + if the target is the built-in simulator, the architecture depends upon how + the simulator instance is created: if the instance is created by use of the + commands + + file <program_file> + target sim + + then the simulator architecture is taken from the program file; if it is + created by the commands + + set endian big | little + set architecture <name> + target sim + + then the architecture is the named one; if it is created by the commands + + set endian big | little + target sim + + the architecture is the default ARC architecture as defined in bfd/cpu-arc.c, + and this is indicated by the 'the_default' flag in the 'bfd_arch_info' struct + being TRUE. */ + +void +arc_check_architecture (struct gdbarch *gdbarch, bfd *objfile_bfd, + const char* file, const char* function) +{ + ARC_ProcessorVersion target = gdbarch_tdep (gdbarch)->processor_variant_info->processor_version; + ARC_ProcessorVersion auxregs = arc_aux_architecture(gdbarch); + ARC_ProcessorVersion program = NO_ARCHITECTURE; + bfd_boolean is_default = FALSE; + Boolean is_builtin_simulator = FALSE; + + ENTERARGS("current target = %s (%sconnected), objfile = %s", + current_target.to_shortname, + (arc_target_is_connected) ? "" : "not ", + (objfile_bfd) ? bfd_get_filename(objfile_bfd) : "<none>"); + + DEBUG("architectural check in function '%s' in file '%s'\n", function, file); + + /* If the target is the built-in simulator. */ + if (strcmp(current_target.to_shortname, "sim") == 0) + { + const char *name = selected_architecture_name(); + const bfd_arch_info_type *arch; + + if (name) + arch = bfd_scan_arch(name); + else + arch = gdbarch_bfd_arch_info(gdbarch); + + is_default = arch->the_default; + is_builtin_simulator = TRUE; + } + + if (objfile_bfd) + program = architecture(objfile_bfd->arch_info); + else + program = NO_ARCHITECTURE; + + DEBUG("target = %s\n", arc_version_image(target)); + DEBUG("auxregs = %s\n", arc_version_image(auxregs)); + DEBUG("program = %s\n", arc_version_image(program)); + + /* If we are connected to a target, we should know its architecture; if we + are not connected, if we don't know both the program and aux registers + architectures then there is no point in checking anything (this situation + could occur if a 'file <program>' or 'arc-reg-read-file <xmlfile>' + command has been issued before the connection is made). */ + if (arc_target_is_connected) + gdb_assert(target != NO_ARCHITECTURE); + else + if (program == NO_ARCHITECTURE || auxregs == NO_ARCHITECTURE) + return; + + /* Check that the architectures are the same. */ + perform_check(target, + auxregs, + program, + is_builtin_simulator, + is_default, + objfile_bfd); + + /* Unfortunately, this event can not be sent at the point that it is known + that the register architecture has changed, as at that point the global + variable current_gdbarch may have the value NULL, and that could cause + an error elsewhere where gdbarch_num_regs or gdbarch_num_pseudo_regs is + used (e.g. in setup_architecture_data in gdbtk/generic/gdbtk-register.c). */ + if (arc_pending_register_architecture_change_event) + { + DEBUG("sending register architecture changed event\n"); + arc_pending_register_architecture_change_event = FALSE; + reg_architecture_changed_event(); + } +} + + +/* Get the ARC architectural version from a string. */ + +ARC_ProcessorVersion +arc_version (const char *arch) +{ + ARC_ProcessorVersion version; + +#define ARCH_IS(ident) (strcmp(arch, ident) == 0) + + if (ARCH_IS("ARC700")) + version = ARC700; + else if (ARCH_IS("ARC600")) + version = ARC600; + else if (ARCH_IS("A5")) + version = A5; + else if (ARCH_IS("A4")) + version = A4; + else + version = UNSUPPORTED_ARCHITECTURE; + + return version; +} + + +/* Return a string representation of the ARC architectural version. */ + +const char* +arc_version_image (ARC_ProcessorVersion version) +{ + switch (version) + { + case NO_ARCHITECTURE : return _("NONE"); + case ARC700 : return _("ARC700"); + case ARC600 : return _("ARC600"); + case A5 : return _("A5"); + case A4 : return _("A4"); + case UNSUPPORTED_ARCHITECTURE: return _("UNSUPPORTED"); + default : return _("???"); + } +} + +/******************************************************************************/ |