summaryrefslogtreecommitdiff
path: root/gdb/arc-xiss.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/arc-xiss.c')
-rwxr-xr-xgdb/arc-xiss.c1787
1 files changed, 1787 insertions, 0 deletions
diff --git a/gdb/arc-xiss.c b/gdb/arc-xiss.c
new file mode 100755
index 00000000000..2319f36d2a2
--- /dev/null
+++ b/gdb/arc-xiss.c
@@ -0,0 +1,1787 @@
+/* Target dependent code for ARC processor family, for GDB, the GNU debugger.
+
+ Copyright 2009 Free Software Foundation, Inc.
+
+ Contributed by ARC International (www.arc.com)
+
+ Authors:
+ 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 creates an instance of a gdb 'target_ops' structure which */
+/* contains information and operations for debugging using the ARC xISS */
+/* (Fast Instruction Set Simulator) as the target. */
+/* */
+/* Instruction Tracing: */
+/* Two different kind of instruction tracing are supported: */
+/* */
+/* 1) a minimal trace which records only the address of each instruction */
+/* which is executed; */
+/* */
+/* 2) a more detailed trace which includes the ordinal number of the */
+/* instruction in the trace, condition code settings, instruction */
+/* address, instruction disassembly, and the values of source and */
+/* destination operands. */
+/* */
+/* The minimal trace is recorded by the xISS in an internal buffer whose */
+/* size may be determined by the gdb user; this buffer wraps around, so */
+/* that only the addresses of the most recently executed instructions are */
+/* held. This data may then be saved to a file for subsequent inspection. */
+/* The trace data is written in an encoding which gives a reduction in */
+/* size of approximately 80% compared to the raw data. */
+/* */
+/* See the manual */
+/* */
+/* ARC GDB-Insight */
+/* GNU Debugger With Insight GUI */
+/* Getting Started */
+/* 6009-001 */
+/* */
+/* for full information on how to use these trace facilities. */
+/* */
+/* Usage: */
+/* The module exports a function _initialize_arc_xiss: the call to this */
+/* function is generated by the gdb build mechanism, so this function */
+/* should not be explicitly called. */
+/* */
+/******************************************************************************/
+
+/* gdb configuration file */
+#include "config.h"
+
+/* This macro should be defined in the configuration file only if the arcint.h
+ file is available. */
+#ifdef HAVE_LIBXISS
+
+/* system header files */
+#include <unistd.h>
+#include <errno.h>
+#include <dlfcn.h>
+
+/* gdb header files */
+#include "defs.h"
+#include "inferior.h"
+#include "disasm.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "libiberty.h"
+#include "completer.h"
+#include "gdb_assert.h"
+
+/* ARC header files */
+#include "config/arc/tm-embed.h"
+#include "arc-xiss.h"
+#include "arc-tdep.h"
+#include "arc-elf32-tdep.h"
+#include "arc-architecture.h"
+#include "arc-inst-tracing.h"
+#include "arc-registers.h"
+
+/* This must be defined before arcint.h is included. */
+#define OEM_USE_OF_DEBUGGER_HEADER_FILES 1
+
+/* This defines the interface by which the xISS is accessed. */
+#include "arcint.h"
+
+
+/* -------------------------------------------------------------------------- */
+/* local types */
+/* -------------------------------------------------------------------------- */
+
+typedef struct ARC* (*ARC_Interface)(void);
+
+typedef enum
+{
+ XISS_HALTED,
+ XISS_STEPPED,
+ XISS_TO_BE_RUN
+} ExecutionStatus;
+
+
+/* N.B. this is taken from arcint.cpp; there must be a better way of doing this! */
+struct ARC
+{
+ ARC_functab *pftp; /* Pointer to interface function table. */
+};
+
+typedef void* WatchpointCookie;
+
+typedef struct _association
+{
+ WatchpointCookie cookie;
+ CORE_ADDR addr;
+ int length;
+ int type;
+} Association;
+
+
+/* -------------------------------------------------------------------------- */
+/* local data */
+/* -------------------------------------------------------------------------- */
+
+#define ARC_TARGET_NAME "arcxiss"
+#define ARC_INTERFACE "get_ARC_interface"
+
+#define SAVE_TRACE_TO_FILE_COMMAND "arc-xiss-save-trace"
+#define EMPTY_TRACE_BUFFER_COMMAND "arc-xiss-empty-trace-buffer"
+#define LIST_TRACE_COMMAND "arc-xiss-list-trace"
+
+#define SAVE_TRACE_TO_FILE_COMMAND_USAGE "Usage: " SAVE_TRACE_TO_FILE_COMMAND " <FILE>\n"
+#define EMPTY_TRACE_BUFFER_COMMAND_USAGE "Usage: " EMPTY_TRACE_BUFFER_COMMAND "\n"
+#define LIST_TRACE_COMMAND_USAGE "Usage: " LIST_TRACE_COMMAND " [ FROM=<VALUE> ] [ TO=<VALUE> ] [ <FILE> ]\n"
+
+
+/* N.B. the xISS does not currently use the context parameter supplied for
+ memory read/write operations, so its value is irrelevant. */
+#define XISS_CONTEXT 0
+
+
+/* The gdb target operations structure for this target. */
+static struct target_ops xISS_target_ops;
+
+/* A set of pointers to operations for reading/writing registers/memory in the
+ xISS target. */
+static TargetOperations operations;
+
+/* Handles for access to the xISS target. */
+static void *xISS_DLL_handle;
+static struct ARC *xiss_instance;
+static ARC_functab *xISS_functions;
+
+/* The status of program execution on the xISS target. */
+static ExecutionStatus xISS_executionStatus;
+
+/* Data for handling instruction tracing. */
+static Boolean xISS_trace_instructions;
+static char *xiss_trace_file;
+static int xiss_trace_buffer_size;
+
+/* This is the table for associating watchpoint details with watchpoint cookies. */
+static Association *associations;
+static unsigned int num_associations;
+
+/* The address of data to which access caused a watchpoint to trigger. */
+static CORE_ADDR stopped_data_address;
+
+
+/* -------------------------------------------------------------------------- */
+/* local macros */
+/* -------------------------------------------------------------------------- */
+
+#define EXTRACT(argument, type, result) \
+{ \
+ struct expression *expr = parse_expression(argument); \
+ struct value *val = evaluate_expression(expr); \
+ struct cleanup *chain = make_cleanup(free_current_contents, &expr); \
+ \
+ result = *(type*) (value_contents (val)); \
+ result ## _specified = TRUE; \
+ do_cleanups (chain); \
+}
+
+/* This macro must cope with the cases:
+ var = value
+ var =value
+ var= value
+ var=value */
+#define GET_PARAMETER(var) \
+ if (strncasecmp(argv[i], #var "=", sizeof(#var)) == 0) \
+ { \
+ if (argv[i][sizeof(#var)] == '\0') \
+ { \
+ i++; \
+ if (argv[i] == NULL) \
+ invalid = TRUE; \
+ else \
+ { \
+ EXTRACT(argv[i], Ordinal, var) \
+ i++; \
+ } \
+ } \
+ else \
+ { \
+ EXTRACT(argv[i] + sizeof(#var), Ordinal, var) \
+ i++; \
+ } \
+ } \
+ else if (strcasecmp(argv[i], #var) == 0) \
+ { \
+ i++; \
+ if (argv[i] == NULL) \
+ invalid = TRUE; \
+ else \
+ { \
+ if (argv[i][0] == '=') \
+ { \
+ if (argv[i][1] == '\0') \
+ { \
+ i++; \
+ if (argv[i] == NULL) \
+ invalid = TRUE; \
+ else \
+ { \
+ EXTRACT(argv[i], Ordinal, var) \
+ i++; \
+ } \
+ } \
+ else \
+ { \
+ EXTRACT(argv[i] + 1, Ordinal, var) \
+ i++; \
+ } \
+ } \
+ else \
+ invalid = TRUE; \
+ } \
+ }
+
+
+#define CHECK_RANGE(source) \
+{ \
+ if (from_specified) \
+ { \
+ if (from < first || from > last) \
+ { \
+ warning(_("%s contains instruction range %llu .. %llu - using %llu as FROM"), \
+ source, first, last, first); \
+ gdb_flush(gdb_stderr); \
+ from = first; \
+ } \
+ } \
+ else \
+ from = first; \
+ \
+ if (to_specified) \
+ { \
+ if (to < first || to > last) \
+ { \
+ warning(_("%s contains instruction range %llu .. %llu - using %llu as TO"), \
+ source, first, last, last); \
+ gdb_flush(gdb_stderr); \
+ to = last; \
+ } \
+ } \
+ else \
+ to = last; \
+}
+
+
+#define XISS_PROPERTY(key,value) xISS_functions->process_property(xiss_instance, key, value)
+
+#define IS_SUPPORTED(flag) ((xISS_functions->supports_feature(xiss_instance) & (flag)) != 0)
+
+#define XISS_AUX_REG(hw_regno) ((ARC_REG_TYPE) hw_regno + (ARC_REG_TYPE) AUX_BASE)
+#define XISS_CORE_REG(hw_regno) ((ARC_REG_TYPE) hw_regno)
+
+
+/* -------------------------------------------------------------------------- */
+/* local functions */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* 1) functions for watchpoint table */
+/* -------------------------------------------------------------------------- */
+
+/* These functions implement a linear lookup table which associate an xISS
+ watchpoint cookie with the watchpoint's address, length and type; this is
+ not very efficient, but is quite sufficient for relatively small numbers of
+ watchpoints. If we should need to handle large numbers of watchpoints
+ efficiently, a more sophisticated data structure may be required. */
+
+
+/* Add an association to the table. */
+
+static void
+associate (WatchpointCookie cookie, CORE_ADDR addr, int length, int type)
+{
+ Association *new = NULL;
+ unsigned int i;
+
+ for (i = 0; i < num_associations; i++)
+ {
+ Association *association = &associations[i];
+
+ if (association->cookie == NULL)
+ {
+ new = association;
+ break;
+ }
+ }
+
+ if (new == NULL)
+ {
+ Association *new_associations = xrealloc(associations, sizeof(Association) * (num_associations + 1));
+
+ if (new_associations == NULL)
+ nomem(0);
+
+ associations = new_associations;
+ new = &new_associations[num_associations];
+ num_associations++;
+ }
+
+ new->cookie = cookie;
+ new->addr = addr;
+ new->length = length;
+ new->type = type;
+}
+
+
+/* Remove an association from the table, returning the cookie. */
+
+static WatchpointCookie
+disassociate (CORE_ADDR addr, int length, int type)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_associations; i++)
+ {
+ Association *association = &associations[i];
+
+ if (association->addr == addr &&
+ association->length == length &&
+ association->type == type)
+ {
+ WatchpointCookie cookie = association->cookie;
+
+ association->cookie = NULL;
+ return cookie;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* Find the address associated with a cookie. */
+
+static CORE_ADDR
+find (WatchpointCookie cookie)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_associations; i++)
+ {
+ Association *association = &associations[i];
+
+ if (association->cookie == cookie)
+ return association->addr;
+ }
+
+ return 0;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 2) functions for reading/writing registers */
+/* -------------------------------------------------------------------------- */
+
+/* N.B. the register contents returned by these functions, or supplied to them,
+ are in host byte order - the arcint.cpp interface to the xISS requires
+ this. */
+
+/* Read a core register on the target.
+
+ Parameters:
+ hw_regno : the ARC hardware number of the register
+ value : set to the contents of the register
+ warn_on_failure: TRUE if a warning should be issued if the read fails
+
+ Result: TRUE if the register contents are read. */
+
+static Boolean
+read_xiss_core_register (ARC_RegisterNumber hw_regno,
+ ARC_RegisterContents *contents,
+ Boolean warn_on_failure)
+{
+ unsigned long value;
+ int result = xISS_functions->read_reg(xiss_instance, XISS_CORE_REG(hw_regno), &value);
+
+ if (result == 1)
+ {
+ *contents = (ARC_RegisterContents) value;
+ DEBUG("Read value 0x%08X from core register %d\n", *contents, hw_regno);
+ return TRUE;
+ }
+
+ if (warn_on_failure)
+ arc_elf32_core_warning(ERROR_ON_READING_REGISTER, hw_regno);
+ return FALSE;
+}
+
+
+/* Write a core register on the target.
+
+ Parameters:
+ hw_regno : the ARC hardware number of the register
+ value : set to the contents of the register
+ warn_on_failure: TRUE if a warning should be issued if the write fails
+
+ Result: TRUE if the register contents are written. */
+
+static Boolean
+write_xiss_core_register (ARC_RegisterNumber hw_regno,
+ ARC_RegisterContents contents,
+ Boolean warn_on_failure)
+{
+ int result = xISS_functions->write_reg(xiss_instance, XISS_CORE_REG(hw_regno), (unsigned long) contents);
+
+ if (result == 1)
+ {
+ DEBUG("Written value 0x%08X to core register %d\n", contents, hw_regno);
+ return TRUE;
+ }
+
+ if (warn_on_failure)
+ arc_elf32_core_warning(ERROR_ON_WRITING_REGISTER, hw_regno);
+ return FALSE;
+}
+
+
+/* Read an auxiliary register on the target.
+
+ Parameters:
+ hw_regno : the ARC hardware number of the register
+ value : set to the contents of the register
+ warn_on_failure: TRUE if a warning should be issued if the read fails
+
+ Result: TRUE if the register contents are read. */
+
+static Boolean
+read_xiss_aux_register (ARC_RegisterNumber hw_regno,
+ ARC_RegisterContents *contents,
+ Boolean warn_on_failure)
+{
+ unsigned long value;
+ int result = xISS_functions->read_reg(xiss_instance, XISS_AUX_REG(hw_regno), &value);
+
+ if (result == 1)
+ {
+ *contents = (ARC_RegisterContents) value;
+ DEBUG("Read value 0x%08X from auxiliary register %d\n", *contents, hw_regno);
+ return TRUE;
+ }
+
+ if (warn_on_failure)
+ arc_elf32_aux_warning(ERROR_ON_READING_REGISTER, hw_regno);
+ return FALSE;
+}
+
+
+/* Write an auxiliary register on the target.
+
+ Parameters:
+ hw_regno : the ARC hardware number of the register
+ value : the contents of the register
+ warn_on_failure: TRUE if a warning should be issued if the write fails
+
+ Result: TRUE if the register contents are written. */
+
+static Boolean
+write_xiss_aux_register (ARC_RegisterNumber hw_regno,
+ ARC_RegisterContents contents,
+ Boolean warn_on_failure)
+{
+ ARC_AuxRegisterDefinition *def = arc_find_aux_register_by_hw_number(hw_regno);
+ int result;
+
+ if (def)
+ contents = arc_write_value(def, contents);
+
+ result = xISS_functions->write_reg(xiss_instance, XISS_AUX_REG(hw_regno), (unsigned long) contents);
+
+ if (result == 1)
+ {
+ DEBUG("Written value 0x%08X to auxiliary register %d\n", contents, hw_regno);
+ return TRUE;
+ }
+
+ if (warn_on_failure)
+ arc_elf32_aux_warning(ERROR_ON_WRITING_REGISTER, hw_regno);
+ return FALSE;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 3) functions for reading/writing memory */
+/* -------------------------------------------------------------------------- */
+
+/* These functions should NOT be used within this module: they are intended
+ purely for use by the arc-memory module for reading/writing multiple words
+ of data at word-aligned addresses. */
+
+static unsigned int
+read_words (ARC_Address address,
+ ARC_Byte *data,
+ unsigned int words)
+{
+ DEBUG("reading %u words from 0x%08X in xISS\n", words, address);
+
+ gdb_assert(IS_WORD_ALIGNED(address));
+
+ return (unsigned int) xISS_functions->read_memory
+ (xiss_instance,
+ (unsigned long) address,
+ data,
+ (unsigned long) words * BYTES_IN_WORD,
+ XISS_CONTEXT);
+}
+
+
+static unsigned int
+write_words (ARC_Address address,
+ ARC_Byte *data,
+ unsigned int words)
+{
+ gdb_assert(IS_WORD_ALIGNED(address));
+
+ DEBUG("writing %u words to 0x%08X in xISS\n", words, address);
+
+ return (unsigned int) xISS_functions->write_memory
+ (xiss_instance,
+ (unsigned long) address,
+ data,
+ (unsigned long) words * BYTES_IN_WORD,
+ XISS_CONTEXT);
+}
+
+
+static unsigned int
+write_pattern (ARC_Address address,
+ ARC_Word pattern,
+ unsigned int words)
+{
+ gdb_assert(IS_WORD_ALIGNED(address));
+
+ DEBUG("writing pattern 0x%08X repeated %u times to 0x%08X in xISS\n", pattern, words, address);
+
+ return (unsigned int) xISS_functions->fill_memory
+ (xiss_instance,
+ (unsigned long) address,
+ &pattern,
+ BYTES_IN_WORD,
+ (unsigned int) words,
+ XISS_CONTEXT);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 4) functions for xISS interface management */
+/* -------------------------------------------------------------------------- */
+
+/* Open the interface to the debug target.
+
+ Parameters:
+ systemfile: the .xis file defining the simulated target
+ from_tty : non-zero if the 'target' command was issued at the terminal
+*/
+
+static Boolean
+open_xISS_interface (const char *systemfile, int from_tty)
+{
+ const char *xiss_home = getenv("XISS_HOME");
+ char library[FILENAME_MAX];
+ ARC_Interface arc_interface;
+
+ if (xiss_home == NULL)
+ error(_("Environment variable XISS_HOME is not set"));
+
+ /* Construct the path to the xISS .so file. */
+ (void) snprintf(library, sizeof(library), "%s/lib/libxiss.so", xiss_home);
+
+ /* Try to dynamically load the shared object library containing the xISS. */
+ xISS_DLL_handle = dlopen(library, RTLD_LAZY);
+
+ if (xISS_DLL_handle == NULL)
+ {
+ const char *diagnostic = dlerror();
+
+ if (strstr(diagnostic, library))
+ error(_("Can not open xISS shared library %s"), diagnostic);
+ else
+ error(_("Can not open xISS shared library %s: %s"), library, diagnostic);
+ }
+
+ /* Find the function in the library which will create an instacne of the xISS. */
+ arc_interface = dlsym(xISS_DLL_handle, ARC_INTERFACE);
+
+ if (arc_interface == NULL)
+ error(_("Can not find function %s in xISS shared library %s"), ARC_INTERFACE, library);
+
+ /* Create an xISS instance. */
+ xiss_instance = arc_interface();
+
+ if (xiss_instance == NULL)
+ error(_("Can not create instance of xISS"));
+
+ /* Get a pointer to the table of functions provided by the interface. */
+ xISS_functions = xiss_instance->pftp;
+
+ DEBUG("xISS interface : %s\n", xISS_functions->id(xiss_instance));
+ DEBUG("xISS interface version: %d\n", xISS_functions->version(xiss_instance));
+
+ /* Tell the xISS what system file to use to define the simulated target. */
+ if (XISS_PROPERTY("xiss_sys", systemfile) != 1)
+ error(_("xISS could not process 'xiss_sys' property"));
+
+ if (IS_SUPPORTED(ARC_FEATURE_fill_memory))
+ operations.fill_memory = write_pattern;
+
+ (void) xISS_functions->prepare_for_new_program(xiss_instance, 1);
+
+ /* This is somewhat inelegant, but commands read from scripts in the gdb
+ testsuite are regarded as though they were being input interactively
+ (i.e. from_tty is 1), and interactive queries may be made (such as
+ asking the user whether the program currently being debugged should be
+ killed first) - and these queries hang the tests!
+
+ So, if the environment variable is set, assume that the gdb test suite is
+ being run, so that no such queries will be made.
+
+ It is not possible to make this check in the top-level command handler
+ loop, as the output from some other commands (e.g. 'file') depend on the
+ from_tty parameter passed to them, and the gdb test scripts expect to get
+ the interactive version of the output! */
+ target_preopen(from_tty && (getenv("ARC_GDB_TEST") == NULL));
+
+ return TRUE;
+}
+
+
+/* Close the JTAG interface to the debug target.
+
+ Parameter:
+ resume: TRUE if program execution on the target should be allowed to resume. */
+
+static void
+close_xISS_interface (Boolean resume)
+{
+ /* If we have a target connected. */
+ if (xiss_instance != NULL)
+ {
+ /* It is meaningless to resume execution of the xISS. */
+ arc_elf32_close(FALSE);
+
+ /* If we are doing instruction tracing. */
+ if (xiss_trace_file)
+ {
+ /* Ensure that the trace file is closed. */
+ if (XISS_PROPERTY("trace_file", "") != 1)
+ error(_("xISS could not process 'trace_file' property"));
+ }
+
+ /* Close the connection. */
+ xISS_functions->destroy(xiss_instance);
+
+ /* Close the library. */
+ if (dlclose(xISS_DLL_handle) != 0)
+ warning(_("error on closing xISS shared library: %s"), dlerror());
+
+ xiss_instance = NULL;
+ xISS_functions = NULL;
+ xISS_DLL_handle = NULL;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 5) functions for starting/stopping the processor */
+/* -------------------------------------------------------------------------- */
+
+/* Run the xISS for whatever quantum of instructions that it executes. */
+static void
+run_processor (void)
+{
+ int result = xISS_functions->run(xiss_instance);
+
+ if (result == 0)
+ warning(_("could not run"));
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 6) local functions called from outside this module (from gdb) */
+/* -------------------------------------------------------------------------- */
+
+/* Connect to the xISS target.
+
+ Parameters:
+ args : user arguments to the 'target' command
+ from_tty: non-zero if the 'target' command was issued at the terminal
+
+ The arguments may be: <XIS_system_file>
+
+ If the name of a system file is not specified, a file 'default.xis' is
+ assumed. */
+
+static void
+arc_xISS_open (char *args, int from_tty)
+{
+ char *systemfile = (args) ? args : "default.xis";
+
+ ENTERARGS("\"%s\" (%d)", (args) ? args : "", from_tty);
+
+ if (access(systemfile, R_OK) != 0)
+ {
+ char *file = getenv("XISS_SYSTEM_FILE");
+
+ if (file == NULL)
+ error(_("Invalid xISS system file '%s': %s"), systemfile, strerror(errno));
+ else
+ if (access(file, R_OK) != 0)
+ error(_("Invalid xISS system file '%s': %s"), file, strerror(errno));
+ else
+ systemfile = file;
+ }
+
+ arc_program_is_loaded = FALSE;
+
+ xISS_trace_instructions = FALSE;
+ xiss_trace_file = NULL;
+ xISS_executionStatus = XISS_HALTED;
+ xiss_trace_buffer_size = 0;
+
+ num_associations = 0;
+ associations = NULL;
+
+ /* Find any well-known aux register numbers that we will need. */
+ arc_elf32_find_register_numbers();
+
+ /* Just to be sure that it is not in the target stack... */
+ (void) unpush_target (&xISS_target_ops);
+
+ /* Now try to open the xISS interface. */
+ if (open_xISS_interface(systemfile, from_tty))
+ {
+ (void) push_target (&xISS_target_ops);
+
+ if (from_tty)
+ printf_filtered (_("Connected to the " ARC_TARGET_NAME " target.\n"));
+ }
+ else
+ error(_("Can not connect to target"));
+}
+
+
+/* Close the connection to the target. */
+
+static void
+arc_xISS_close (int quitting) /* Ignored. */
+{
+ ENTERMSG;
+
+ close_xISS_interface(FALSE);
+
+ xfree(associations);
+ associations = NULL;
+ num_associations = 0;
+}
+
+
+/* Cause the inferior on the debug target to resume execution, sending a signal
+ if necessary.
+
+ Parameters:
+ ptid : the thread id of the thread to be resumed (ignored)
+ step : 1 means single step, 0 run freely.
+ signal: the number of the signal to be sent
+
+ N.B. signals are not supported. */
+
+static void
+arc_xISS_resume (ptid_t ptid, int step, enum target_signal signal)
+{
+ ENTERARGS("%d, %d, %d", ptid.pid, step, signal);
+
+ if (signal != TARGET_SIGNAL_0)
+ error(_("Signals are not supported by the " ARC_TARGET_NAME " target"));
+
+ if (step)
+ {
+ int result = xISS_functions->step(xiss_instance);
+
+ if (result == 0)
+ error(_("Can not single-step"));
+ else
+ xISS_executionStatus = XISS_STEPPED;
+ }
+ else
+ xISS_executionStatus = XISS_TO_BE_RUN;
+
+ LEAVEMSG;
+}
+
+
+/* Wait for execution on the target to halt (for whatever reason).
+
+ Parameters :
+ ptid : ignored
+ status: set to indicate status at end of the wait
+*/
+
+static ptid_t
+arc_xISS_wait (ptid_t ptid, struct target_waitstatus *status)
+{
+ ENTERARGS("xISS execution status: %d", xISS_executionStatus);
+
+ /* What was done the last time that execution was resumed? */
+ switch (xISS_executionStatus)
+ {
+ case XISS_STEPPED:
+ DEBUG("processor has stepped\n");
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+
+ case XISS_TO_BE_RUN:
+ arc_elf32_execute(status,
+ run_processor,
+ NULL,
+ NULL);
+
+ if (status->kind == TARGET_WAITKIND_EXITED)
+ target_mark_exited (&xISS_target_ops);
+ break;
+
+ case XISS_HALTED:
+ break;
+ }
+
+ LEAVEMSG;
+
+ return inferior_ptid;
+}
+
+
+/* This gets called just before store_regs. */
+
+static void
+arc_xISS_prepare_to_store (struct regcache *regcache)
+{
+ ENTERMSG;
+}
+
+
+static void
+arc_xISS_files_info (struct target_ops *target)
+{
+ /* Do nothing. */
+ ENTERMSG;
+}
+
+
+/* Heavy duty arsenal. Kill the process. */
+
+static void
+arc_xISS_kill (void)
+{
+ ENTERMSG;
+
+ target_mourn_inferior ();
+}
+
+
+/* Load the program into memory via the xISS interface. */
+
+static void
+arc_xISS_load (char *args, int from_tty)
+{
+ /* The program will be downloaded to the simulator. */
+ (void) xISS_functions->prepare_for_new_program(xiss_instance, 1);
+
+ arc_elf32_load_program(args, from_tty);
+
+ /* Tell xISS that program is fully loaded. */
+ if (XISS_PROPERTY("download_complete", "1") != 1)
+ error(_("xISS could not process 'download_complete' property"));
+
+ /* We now have a program ready for execution on the target. */
+}
+
+
+/* Create the inferior that will be executed upon the target.
+
+ Parameters :
+ exec_file: the executable file containing the program to be executed
+ args : the command line arguments to be passed to the program
+ env : the environment (name/value pairs) for the program
+ from_tty : ignored
+ */
+
+static void
+arc_xISS_create_inferior (char *exec_file, char *args, char **env, int from_tty)
+{
+ arc_elf32_create_inferior(exec_file, args, env, &xISS_target_ops);
+}
+
+
+/* Mourn the inferior. */
+
+static void
+arc_xISS_mourn_inferior (void)
+{
+ ENTERMSG;
+
+// (void) unpush_target (&xISS_target_ops);
+
+ /* N.B. we must delete all breakpoints from the target here: the gdb core
+ function generic_mourn_inferior marks all breakpoints as not being
+ inserted on the target, with the result that subsequent calls to
+ remove_breakpoints will NOT remove any breakpoints that are set on
+ the target; this means that if target execution is re-started, gdb
+ will attempt to re-insert the breakpoints, which causes a problem
+ with software breakpoints: the target insert_breakpoint function
+ reads the code at the b/p address (which is the s/w b/p instruction)
+ and saves it as the "overwritten" code - so when the breakpoint is
+ subsequently removed, the b/p instruction is written back to the
+ b/p address again! That is not what is desired... */
+ (void) remove_breakpoints();
+ generic_mourn_inferior();
+ current_target.to_has_execution = 0;
+}
+
+
+/* Check whether the given thread is alive. */
+
+static int
+arc_xISS_thread_alive (ptid_t ptid)
+{
+ ENTERMSG;
+
+ /* We only have one thread. */
+ return 1;
+}
+
+
+/* Check whether our debug target is runnable: return 1 if it is, 0 otherwise. */
+
+static int arc_xISS_can_run (void)
+{
+ /* If we are connected to the xISS i/f, and a program is loaded. */
+ return (xiss_instance != NULL) && arc_program_is_loaded;
+}
+
+
+/* We do not support asynchronous execution of the target program (i.e. commands
+ like 'run' or 'continue' or 'step' can not be executed in background mode
+ by appending a '&' to them) so we do not need to implement the target stop
+ operation (called by the 'interrupt' command); interrupting a running program
+ is handled by the Ctrl-C mechanism. */
+
+#if 0
+static void
+arc_xISS_stop (void)
+{
+ ENTERMSG;
+}
+#endif
+
+
+/* Check if we can set a "hardware" watchpoint of type TYPE. TYPE is
+ one of bp_hardware_watchpoint, bp_read_watchpoint, bp_write_watchpoint, or
+ bp_hardware_breakpoint. COUNT is the number of such watchpoints used so far
+ (including this one). OTHERTYPE is the total number of "hardware" breakpoints
+ and watchpoints of other types that are "already" set
+ (0 if type == bp_hardware_breakpoint).
+
+ Result: 0 if hardware watchpoints are not supported
+ -1 if there are not enough hardware watchpoints
+ 1 if there are enough hardware watchpoints
+
+ N.B. this is not what is stated in target.h, but it does conform to the use
+ made of this function's result in breakpoint.c! */
+
+static int
+arc_xISS_can_use_hw_breakpoint (int type, int count, int othertype)
+{
+ ENTERARGS("type %d, count %d", type, count);
+
+ switch (type)
+ {
+ case bp_hardware_watchpoint:
+ case bp_read_watchpoint:
+ case bp_watchpoint: /* This means bp_write_watchpoint. */
+ return 1;
+ case bp_hardware_breakpoint:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+
+/* Insert a "hardware" watchpoint on the target.
+
+ Parameters:
+ addr : the start address of the region of memory to be watched
+ length: the length in bytes of the region of memory
+ type : 0 => write, 1 => read, 2 => read/write
+
+ Returns 0 for success, -1 for failure. */
+
+static int
+arc_xISS_insert_watchpoint (CORE_ADDR addr, int length, int type)
+{
+ WatchpointCookie cookie;
+ unsigned int options;
+
+ ENTERARGS("0x%08X:%d %d", (unsigned int) addr, length, type);
+
+ gdb_assert(length > 0);
+
+ switch (type)
+ {
+ case 0:
+ options = ARC_WATCHPOINT_write;
+ break;
+ case 1:
+ options = ARC_WATCHPOINT_read;
+ break;
+ case 2:
+ options = ARC_WATCHPOINT_read | ARC_WATCHPOINT_write;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, _("invalid watchpoint type: %d"), type);
+ }
+
+ if (xISS_functions->set_mem_watchpoint2(xiss_instance, (unsigned long) addr, length, options, &cookie) == 1)
+ {
+ associate(cookie, addr, length, type);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/* Remove a "hardware" watchpoint from the target.
+
+ Parameters:
+ addr : the start address of the region of memory being watched
+ length: the length in bytes of the region of memory
+ type : 0 => write, 1 => read, 2 => read/write
+
+ Returns 0 for success, non-zero for failure. */
+
+static int
+arc_xISS_remove_watchpoint (CORE_ADDR addr, int length, int type)
+{
+ WatchpointCookie cookie = disassociate(addr, length, type);
+
+ ENTERARGS("0x%x:%d %d", (unsigned int) addr, length, type);
+
+ if (cookie != NULL)
+ return (xISS_functions->remove_watchpoint(xiss_instance, cookie) == 1) ? 0 : 1;
+ return 1;
+}
+
+
+/* Returns non-zero if the execution of the target program has been stopped by
+ the trigger of a "hardware" watchpoint (i.e. on memory read or write), zero
+ otherwise. */
+
+static int
+arc_xISS_stopped_by_watchpoint (void)
+{
+ WatchpointCookie cookie;
+
+ ENTERMSG;
+
+ if (xISS_functions->stopped_at_watchpoint2(xiss_instance, &cookie) == 1)
+ {
+ /* Regrettably, the arcint i/f does not provide a well-defined means for
+ finding out the address of the data which was accessed - to do this
+ we have had to define a special property which returns the required
+ address! */
+ int result = XISS_PROPERTY("watchpoint", "return_hit_address");
+
+ if (result == 0)
+ {
+ DEBUG("xISS could not process 'watchpoint/return_hit_address' property");
+
+ /* The most we can do now is retrieve the start address of the
+ watchpoint which was triggered...
+ N.B. we must retrieve the watchpoint address here, rather than in
+ the arc_xISS_stopped_data_address function, as gdb deletes
+ all breakpoint and watchpoints from the target as soon as
+ execution is halted, which removes the cookie from the table! */
+ stopped_data_address = find(cookie);
+ }
+ else
+ stopped_data_address = (CORE_ADDR) result;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Get the address of the data that was read/written causing a h/w watchpoint to
+ trigger; the address is returned in the '*addr' parameter.
+ Returns 0 for failure, non-zero for success. */
+
+static int
+arc_xISS_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr)
+{
+ ENTERMSG;
+
+ DEBUG("data addr: 0x%08X\n", (unsigned int) stopped_data_address);
+ *addr = stopped_data_address;
+
+ return 1;
+}
+
+
+/* Can a h/w watchpoint 'length' bytes long be set at address 'addr' in target memory? */
+
+static int
+arc_xISS_region_ok_for_hw_watchpoint (CORE_ADDR addr, int length)
+{
+ /* As far as we know, we can set a h/w watchpoint anywhere. */
+ return 1;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 7) functions for instruction tracing */
+/* -------------------------------------------------------------------------- */
+
+/* Display the instruction at the given address and ordinal position in the
+ instruction trace. */
+
+static void
+display_instruction (Ordinal ordinal, unsigned int address)
+{
+ /* N.B. must use fprintf_filtered here, rather than fprintf_unfiltered, as
+ gdb_print_insn calls fprintf_filtered, and if we mix the use of the
+ two we can get garbled output! */
+ fprintf_filtered(gdb_stdout, "<0x%016llX> 0x%08X ", ordinal, address);
+ (void) gdb_print_insn((CORE_ADDR) address, gdb_stdout, NULL);
+ fprintf_filtered(gdb_stdout, "\n");
+}
+
+
+/* Get the ordinal position of the first instruction in the trace buffer in the
+ sequence of executed instructions from the xISS; return 0 if this number cannot
+ be obtained. */
+
+static Ordinal
+get_instruction_trace_start (void)
+{
+ /* N.B. XISS_PROPERTY returns 0 if the property is not handled. */
+ int start_low = XISS_PROPERTY("instruction_trace", "return_start_count_low");
+ int start_high = XISS_PROPERTY("instruction_trace", "return_start_count_high");
+ Ordinal start = ((Ordinal) start_high) << 32 | (Ordinal) start_low;
+
+ DEBUG("get_instruction_trace_start : %llu\n", start);
+
+ return start;
+}
+
+
+/* Encode the instruction trace buffer retrieved from the xISS: the buffer
+ 'trace' contains 'length' entries which are all PC values. The data is
+ recorded in the currently open trace file in a packed format. */
+
+static void
+encode_instruction_trace (unsigned int trace[], int length)
+{
+ unsigned int lastPC = trace[0];
+ int i;
+
+ /* Store the first entry in the buffer as an absolute address. */
+ arc_encode_PC(ABSOLUTE_31_BITS, lastPC / 2);
+
+ /* Look at all the remaining entries, comparing each with the previous one. */
+ for (i = 1; i < length; i++)
+ {
+ unsigned int thisPC = trace[i];
+ int delta = (int) thisPC - (int) lastPC;
+
+ /* Encode the difference in the PC as a relative offset, if possible.
+ Offsets of 0 (branch to current address), 2, 4, 6 and 8 (instruction
+ sizes + optional immediate size) are handled as special cases. */
+
+ if (delta == 0)
+ arc_encode_PC(NO_CHANGE, 0);
+ else if (delta == 2)
+ arc_encode_PC(PLUS_16_BITS, 0);
+ else if (delta == 4)
+ arc_encode_PC(PLUS_32_BITS, 0);
+ else if (delta == 6)
+ arc_encode_PC(PLUS_48_BITS, 0);
+ else if (delta == 8)
+ arc_encode_PC(PLUS_64_BITS, 0);
+ else if (0 < delta && delta <= MAX_DELTA)
+ arc_encode_PC(DELTA_16_BIT_POSITIVE, ENCODE_DELTA(delta));
+ else if (0 > delta && delta >= -MAX_DELTA)
+ arc_encode_PC(DELTA_16_BIT_NEGATIVE, ENCODE_DELTA(-delta));
+ else
+ arc_encode_PC(ABSOLUTE_31_BITS, thisPC / 2);
+
+ lastPC = thisPC;
+ }
+
+ /* Useful tracing code: dump buffer as raw binary. */
+#if 0
+ {
+ int binary = open("trace.binary", O_CREAT | O_WRONLY, 0666);
+
+ if (binary == -1)
+ warning(_("could not open file trace.binary"));
+ else
+ {
+ (void) write(binary, trace, length * sizeof(unsigned int));
+ (void) close(binary);
+ }
+ }
+#endif
+}
+
+
+/* Decode the instruction trace buffer retrieved from a file. This is the inverse
+ of the encoding performed by the 'encode_instruction_trace' function.
+ The instruction at each PC value decoded is disassembled and displayed only if
+ its ordinal position in the trace is in the range given by the 'from' and 'to'
+ parameters. */
+
+static void
+decode_instruction_trace (Ordinal from, Ordinal to, Ordinal ordinal)
+{
+ ARC_ProgramCounterEncoding encoding;
+ unsigned int thisPC = 0;
+ unsigned int lastPC = 0;
+ unsigned int value;
+
+ while (arc_decode_PC(&encoding, &value))
+ {
+ switch (encoding)
+ {
+ case NO_CHANGE:
+ break;
+ case PLUS_16_BITS:
+ thisPC += 2;
+ break;
+ case PLUS_32_BITS:
+ thisPC += 4;
+ break;
+ case PLUS_48_BITS:
+ thisPC += 6;
+ break;
+ case PLUS_64_BITS:
+ thisPC += 8;
+ break;
+ case DELTA_16_BIT_POSITIVE:
+ thisPC += DECODE_DELTA(value);
+ break;
+ case DELTA_16_BIT_NEGATIVE:
+ thisPC -= DECODE_DELTA(value);
+ break;
+ case ABSOLUTE_31_BITS:
+ thisPC = value * 2;
+ break;
+ }
+
+ if (from <= ordinal && ordinal <= to)
+ display_instruction(ordinal, thisPC);
+
+ lastPC = thisPC;
+ ordinal++;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 8) helper routines for added commands */
+/* -------------------------------------------------------------------------- */
+
+/* Check that the xISS target is actually connected. */
+
+static void
+check_connected (void)
+{
+ if (xiss_instance == NULL)
+ error(_("Target " ARC_TARGET_NAME " is not connected"));
+}
+
+
+/* Set the size of the buffer to be used by the xISS for instruction trace data. */
+
+static void
+set_trace_buffer_size (int size)
+{
+ char sz[20];
+
+ (void) snprintf(sz, sizeof(sz), "%d", size);
+
+ if (XISS_PROPERTY("trace_buffer_size", sz) != 1)
+ error(_("xISS could not process 'trace_buffer_size' property"));
+}
+
+
+/* Tell the xISS to switch instruction tracing on or off. */
+
+static void
+set_xiss_trace (char *args,
+ int from_tty,
+ struct cmd_list_element *e)
+{
+ check_connected();
+
+ if (XISS_PROPERTY("trace", (xISS_trace_instructions) ? "on" : "off") != 1)
+ error(_("xISS could not process 'trace' property"));
+}
+
+
+/* Show the status of xISS instruction tracing. */
+
+static void
+show_xiss_trace (struct ui_file *file,
+ int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ /* Value will be either "on" or "off". */
+ fprintf_filtered(file,
+ _("xISS instruction tracing is %s.\n"),
+ value);
+}
+
+
+/* Tell the xISS to write the instruction trace to the file whose name is held
+ in the xiss_trace_file global variable. */
+
+static void
+set_xiss_trace_file (char *args,
+ int from_tty,
+ struct cmd_list_element *e)
+{
+ check_connected();
+
+ if (xiss_trace_file)
+ {
+ if (XISS_PROPERTY("trace_file", xiss_trace_file) != 1)
+ error(_("xISS could not process 'trace_file' property"));
+ }
+}
+
+
+/* Show the name of the trace file (if any) which is currently receiving
+ instruction tracing output from the xISS. */
+
+static void
+show_xiss_trace_file (struct ui_file *file,
+ int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ if (*value == '\0')
+ fprintf_filtered(file,
+ _("No output file is set for xISS instruction tracing.\n"));
+ else
+ fprintf_filtered(file,
+ _("The output file for xISS instruction tracing is '%s'.\n"),
+ value);
+}
+
+
+/* Set the size of the buffer used by the xISS for instruction trace data. */
+
+static void
+set_xiss_trace_buffer_size (char *args,
+ int from_tty,
+ struct cmd_list_element *e)
+{
+ check_connected();
+
+ if (xiss_trace_buffer_size < 0)
+ error(_("Trace buffer size must be non-negative"));
+
+ set_trace_buffer_size(xiss_trace_buffer_size);
+}
+
+
+/* Show the size of the buffer used by the xISS for instruction trace data. */
+
+static void
+show_xiss_trace_buffer_size (struct ui_file *file,
+ int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered(file,
+ _("The buffer size for xISS instruction tracing is %s entries.\n"),
+ value);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 9) local functions implementing commands */
+/* -------------------------------------------------------------------------- */
+
+/* Command: <command> <filename>
+
+ Save the contents of the xISS instruction trace buffer to the named file.
+
+ We should eventually change this to use the ui_out stuff rather than
+ printf_filtered. */
+
+static void
+arc_save_trace_to_file_command (char *arg, int from_tty)
+{
+ int count;
+
+ if (!arg)
+ {
+ printf_filtered (_(SAVE_TRACE_TO_FILE_COMMAND_USAGE));
+ return;
+ }
+
+ check_connected();
+
+ count = xISS_functions->instruction_trace_count(xiss_instance);
+
+ if (count)
+ {
+ unsigned int *buffer;
+
+ if (access(arg, F_OK) == 0)
+ if (!query(_("File already exists. Do you wish to overwrite it?")))
+ return;
+
+ printf_unfiltered(_("%u instructions in trace buffer\n"), count);
+
+ buffer = xmalloc(count * sizeof(unsigned int));
+
+ if (buffer)
+ {
+ Ordinal first = get_instruction_trace_start();
+
+ xISS_functions->get_instruction_traces(xiss_instance, buffer);
+
+ if (arc_start_encoding(arg, first))
+ {
+ encode_instruction_trace(buffer, count);
+ arc_stop_encoding(first + (Ordinal) count - 1);
+ }
+
+ xfree(buffer);
+ }
+ else
+ warning(_("can not allocate buffer to hold instruction trace data"));
+ }
+ else
+ warning(_("no instruction trace data available"));
+}
+
+
+
+/* Command: <command>
+
+ Discard the contents of the xISS instruction trace buffer. */
+
+static void
+arc_empty_trace_buffer (char *arg, int from_tty)
+{
+ if (arg)
+ {
+ printf_filtered (_(EMPTY_TRACE_BUFFER_COMMAND_USAGE));
+ return;
+ }
+
+ check_connected();
+
+ set_trace_buffer_size(0);
+ set_trace_buffer_size(xiss_trace_buffer_size);
+}
+
+
+/* Command: <command> [ FROM=<from> ] [ TO=<to> ] [ <FILE> ]
+
+ Display some or all of the instruction trace, either from the xISS trace
+ buffer or from a named file. */
+
+static void
+arc_list_trace (char *arg, int from_tty)
+{
+ char *file = NULL;
+ Boolean from_specified = FALSE;
+ Boolean to_specified = FALSE;
+ Ordinal from = 0;
+ Ordinal to = 0;
+ Ordinal first;
+ Ordinal last;
+
+ /* Do we have arguments to the command? */
+ if (arg)
+ {
+ char **argv = buildargv (arg);
+ Boolean invalid = FALSE;
+ int i = 0;
+
+ if (argv == NULL)
+ nomem (0);
+
+ while (argv[i] != NULL)
+ {
+// printf("argv[%d] = %s\n", i, argv[i]);
+
+ GET_PARAMETER(from)
+ else
+ GET_PARAMETER(to)
+ else
+ {
+ /* Assume the argument is the file name. */
+ file = xstrdup(argv[i]);
+ i++;
+ }
+ }
+
+ freeargv(argv);
+
+ if (invalid)
+ {
+ printf_filtered (_(LIST_TRACE_COMMAND_USAGE));
+ return;
+ }
+
+ DEBUG("FROM = %llu\n", from);
+ DEBUG("TO = %llu\n", to);
+
+ if (from > to)
+ error("FROM (%lld) > TO (%lld)", from, to);
+ }
+
+ /* If we must get the instruction trace from a file. */
+ if (file)
+ {
+ /* Try to open the named file and start decoding its contents. */
+ if (arc_start_decoding(file, &first, &last))
+ {
+ CHECK_RANGE("file")
+ decode_instruction_trace(from, to, first);
+ arc_stop_decoding();
+ }
+
+ xfree(file);
+ }
+ else
+ {
+ unsigned int count;
+
+ check_connected();
+
+ /* Get the number of entries in the xISS instruction trace buffer. */
+ count = (unsigned int) xISS_functions->instruction_trace_count(xiss_instance);
+
+ if (count > 0)
+ {
+ unsigned int *buffer = xmalloc(count * sizeof(unsigned int));
+
+ if (buffer)
+ {
+ Ordinal i;
+
+ first = get_instruction_trace_start();
+ last = first + (Ordinal) count - 1;
+
+ CHECK_RANGE("trace buffer")
+
+ /* Get the contents of the xISS instruction trace buffer. */
+ xISS_functions->get_instruction_traces(xiss_instance, buffer);
+
+ /* Display the required range of the trace. */
+ for (i = from; i <= to; i++)
+ display_instruction(i, buffer[(int) (i - from)]);
+
+ xfree(buffer);
+ }
+ else
+ warning(_("can not allocate buffer to hold instruction trace data"));
+ }
+ else
+ warning(_("no instruction trace data available"));
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* 10) initialization functions */
+/* -------------------------------------------------------------------------- */
+
+/* Initialize the xISS target operations. */
+
+static void
+initialize_xISS_target_ops (void)
+{
+ ENTERMSG;
+
+ xISS_target_ops.to_data = &operations;
+
+ xISS_target_ops.to_shortname = ARC_TARGET_NAME;
+ xISS_target_ops.to_longname = "xISS debug target (ARC Processors)";
+ xISS_target_ops.to_doc = "xISS (Fast Instruction Set Simulator) debug target (ARC Processors)";
+
+ xISS_target_ops.to_open = arc_xISS_open;
+ xISS_target_ops.to_close = arc_xISS_close;
+ xISS_target_ops.to_resume = arc_xISS_resume;
+ xISS_target_ops.to_wait = arc_xISS_wait;
+
+ xISS_target_ops.to_fetch_registers = arc_elf32_fetch_registers;
+ xISS_target_ops.to_store_registers = arc_elf32_store_registers;
+ xISS_target_ops.to_prepare_to_store = arc_xISS_prepare_to_store;
+ xISS_target_ops.to_xfer_partial = arc_elf32_xfer_partial;
+ xISS_target_ops.to_files_info = arc_xISS_files_info;
+
+ xISS_target_ops.to_can_use_hw_breakpoint = arc_xISS_can_use_hw_breakpoint;
+// xISS_target_ops.to_insert_hw_breakpoint = arc_xISS_insert_hw_breakpoint;
+// xISS_target_ops.to_remove_hw_breakpoint = arc_xISS_remove_hw_breakpoint;
+ xISS_target_ops.to_insert_watchpoint = arc_xISS_insert_watchpoint;
+ xISS_target_ops.to_remove_watchpoint = arc_xISS_remove_watchpoint;
+ xISS_target_ops.to_stopped_by_watchpoint = arc_xISS_stopped_by_watchpoint;
+ xISS_target_ops.to_stopped_data_address = arc_xISS_stopped_data_address;
+ xISS_target_ops.to_region_ok_for_hw_watchpoint = arc_xISS_region_ok_for_hw_watchpoint;
+
+ xISS_target_ops.to_insert_breakpoint = arc_elf32_insert_breakpoint;
+ xISS_target_ops.to_remove_breakpoint = arc_elf32_remove_breakpoint;
+
+ xISS_target_ops.to_kill = arc_xISS_kill;
+ xISS_target_ops.to_load = arc_xISS_load;
+
+ xISS_target_ops.to_create_inferior = arc_xISS_create_inferior;
+ xISS_target_ops.to_mourn_inferior = arc_xISS_mourn_inferior;
+ xISS_target_ops.to_thread_alive = arc_xISS_thread_alive;
+// xISS_target_ops.to_stop = arc_xISS_stop;
+ xISS_target_ops.to_can_run = arc_xISS_can_run;
+ xISS_target_ops.to_terminal_inferior = NULL;
+
+ xISS_target_ops.to_stratum = process_stratum;
+
+ xISS_target_ops.to_has_all_memory = 1;
+ xISS_target_ops.to_has_memory = 1;
+ xISS_target_ops.to_has_stack = 0; /* Defer setting this until the program has been loaded. */
+ xISS_target_ops.to_has_registers = 1;
+ xISS_target_ops.to_has_execution = 0; /* Defer setting this until the program has been started. */
+
+ xISS_target_ops.to_magic = OPS_MAGIC;
+}
+#endif /* HAVE_LIBXISS */
+
+
+/* -------------------------------------------------------------------------- */
+/* externally visible functions */
+/* -------------------------------------------------------------------------- */
+
+/* Initialize the module. This function is called from the gdb core on start-up. */
+
+/* N.B. the initialization function must be defined even if the rest of this
+ module is excluded, as the call to it from the gdb start-up code is
+ generated by the build mechanism without regard to any conditional
+ compilation! */
+
+void
+_initialize_arc_xiss (void)
+{
+#ifdef HAVE_LIBXISS
+ struct cmd_list_element *cmnd;
+
+ ENTERMSG;
+
+ operations.read_core_register = read_xiss_core_register;
+ operations.write_core_register = write_xiss_core_register;
+ operations.read_auxiliary_register = read_xiss_aux_register;
+ operations.write_auxiliary_register = write_xiss_aux_register;
+ operations.read_memory = read_words;
+ operations.write_memory = write_words;
+ operations.fill_memory = NULL;
+
+ initialize_xISS_target_ops ();
+ add_target (&xISS_target_ops);
+
+ /* Register ARC-specific commands with gdb. */
+
+ (void) add_setshow_boolean_cmd
+ ("arc-xiss-trace",
+ class_trace,
+ &xISS_trace_instructions,
+ _("Set whether the xISS should trace instructions.\n"),
+ _("Show whether the xISS should trace instructions.\n"),
+ NULL,
+ set_xiss_trace,
+ show_xiss_trace,
+ &setlist,
+ &showlist);
+
+ add_setshow_optional_filename_cmd
+ ("arc-xiss-trace-file",
+ class_trace,
+ &xiss_trace_file,
+ _("Set the output file for xISS instruction tracing.\n"),
+ _("Show the output file for xISS instruction tracing.\n"),
+ NULL,
+ set_xiss_trace_file,
+ show_xiss_trace_file,
+ &setlist,
+ &showlist);
+
+ (void) add_setshow_zinteger_cmd
+ ("arc-xiss-trace-buffer-size",
+ class_trace,
+ &xiss_trace_buffer_size,
+ _("Set the size of the trace buffer for xISS instruction tracing.\n"),
+ _("Show the size of the trace buffer for xISS instruction tracing.\n"),
+ NULL,
+ set_xiss_trace_buffer_size,
+ show_xiss_trace_buffer_size,
+ &setlist,
+ &showlist);
+
+ cmnd = add_cmd
+ (SAVE_TRACE_TO_FILE_COMMAND,
+ class_trace,
+ arc_save_trace_to_file_command,
+ _("Save the contents of the xISS instruction trace buffer to a file.\n"
+ SAVE_TRACE_TO_FILE_COMMAND_USAGE
+ "<FILE> is a file to hold the xISS instruction trace buffer contents.\n"),
+ &cmdlist);
+ set_cmd_completer (cmnd, filename_completer);
+
+ (void) add_cmd
+ (EMPTY_TRACE_BUFFER_COMMAND,
+ class_trace,
+ arc_empty_trace_buffer,
+ _("Empty xISS instruction trace buffer.\n"
+ EMPTY_TRACE_BUFFER_COMMAND_USAGE),
+ &cmdlist);
+
+ cmnd = add_cmd
+ (LIST_TRACE_COMMAND,
+ class_trace,
+ arc_list_trace,
+ _("Display xISS instruction trace.\n"
+ LIST_TRACE_COMMAND_USAGE),
+ &cmdlist);
+ set_cmd_completer (cmnd, filename_completer);
+
+#endif /* HAVE_LIBXISS */
+}
+
+/******************************************************************************/