/* Target dependent code for GDB on TI C6x systems.
- Copyright (C) 2010-2015 Free Software Foundation, Inc.
+ Copyright (C) 2010-2018 Free Software Foundation, Inc.
Contributed by Andrew Jenner <andrew@codesourcery.com>
Contributed by Yao Qi <yao@codesourcery.com>
#include "server.h"
#include "linux-low.h"
+#include "arch/tic6x.h"
+#include "tdesc.h"
#include "nat/gdb_ptrace.h"
#include <endian.h>
return (const gdb_byte *) &tic6x_breakpoint;
}
-/* Forward definition. */
-static struct usrregs_info tic6x_usrregs_info;
+static struct usrregs_info tic6x_usrregs_info =
+ {
+ TIC6X_NUM_REGS,
+ NULL, /* Set in tic6x_read_description. */
+ };
static const struct target_desc *
-tic6x_read_description (void)
+tic6x_read_description (enum c6x_feature feature)
{
- register unsigned int csr asm ("B2");
- unsigned int cpuid;
- const struct target_desc *tdesc;
+ static target_desc *tdescs[C6X_LAST] = { };
+ struct target_desc **tdesc = &tdescs[feature];
- /* Determine the CPU we're running on to find the register order. */
- __asm__ ("MVC .S2 CSR,%0" : "=r" (csr) :);
- cpuid = csr >> 24;
- switch (cpuid)
+ if (*tdesc == NULL)
{
- case 0x00: /* C62x */
- case 0x02: /* C67x */
- tic6x_regmap = tic6x_regmap_c62x;
- tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
- tdesc = tdesc_tic6x_c62x_linux;
- break;
- case 0x03: /* C67x+ */
- tic6x_regmap = tic6x_regmap_c64x;
- tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
- tdesc = tdesc_tic6x_c64x_linux;
- break;
- case 0x0c: /* C64x */
- tic6x_regmap = tic6x_regmap_c64x;
- tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
- tdesc = tdesc_tic6x_c64x_linux;
- break;
- case 0x10: /* C64x+ */
- case 0x14: /* C674x */
- case 0x15: /* C66x */
- tic6x_regmap = tic6x_regmap_c64xp;
- tic6x_breakpoint = 0x56454314; /* illegal opcode */
- tdesc = tdesc_tic6x_c64xp_linux;
- break;
- default:
- error ("Unknown CPU ID 0x%02x", cpuid);
+ *tdesc = tic6x_create_target_description (feature);
+ static const char *expedite_regs[] = { "A15", "PC", NULL };
+ init_target_desc (*tdesc, expedite_regs);
}
- tic6x_usrregs_info.regmap = tic6x_regmap;
- return tdesc;
+
+ return *tdesc;
}
static int
/* Fetch the thread-local storage pointer for libthread_db. */
ps_err_e
-ps_get_thread_area (const struct ps_prochandle *ph,
+ps_get_thread_area (struct ps_prochandle *ph,
lwpid_t lwpid, int idx, void **base)
{
if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
static void
tic6x_fill_gregset (struct regcache *regcache, void *buf)
{
- union tic6x_register *regset = buf;
+ auto regset = static_cast<union tic6x_register *> (buf);
int i;
for (i = 0; i < TIC6X_NUM_REGS; i++)
static void
tic6x_store_gregset (struct regcache *regcache, const void *buf)
{
- const union tic6x_register *regset = buf;
+ const auto regset = static_cast<const union tic6x_register *> (buf);
int i;
for (i = 0; i < TIC6X_NUM_REGS; i++)
static void
tic6x_arch_setup (void)
{
- current_process ()->tdesc = tic6x_read_description ();
+ register unsigned int csr asm ("B2");
+ unsigned int cpuid;
+ enum c6x_feature feature = C6X_CORE;
+
+ /* Determine the CPU we're running on to find the register order. */
+ __asm__ ("MVC .S2 CSR,%0" : "=r" (csr) :);
+ cpuid = csr >> 24;
+ switch (cpuid)
+ {
+ case 0x00: /* C62x */
+ case 0x02: /* C67x */
+ tic6x_regmap = tic6x_regmap_c62x;
+ tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
+ feature = C6X_CORE;
+ break;
+ case 0x03: /* C67x+ */
+ tic6x_regmap = tic6x_regmap_c64x;
+ tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
+ feature = C6X_GP;
+ break;
+ case 0x0c: /* C64x */
+ tic6x_regmap = tic6x_regmap_c64x;
+ tic6x_breakpoint = 0x0000a122; /* BNOP .S2 0,5 */
+ feature = C6X_GP;
+ break;
+ case 0x10: /* C64x+ */
+ case 0x14: /* C674x */
+ case 0x15: /* C66x */
+ tic6x_regmap = tic6x_regmap_c64xp;
+ tic6x_breakpoint = 0x56454314; /* illegal opcode */
+ feature = C6X_C6XP;
+ break;
+ default:
+ error ("Unknown CPU ID 0x%02x", cpuid);
+ }
+ tic6x_usrregs_info.regmap = tic6x_regmap;
+
+ current_process ()->tdesc = tic6x_read_description (feature);
+}
+
+/* Support for hardware single step. */
+
+static int
+tic6x_supports_hardware_single_step (void)
+{
+ return 1;
}
static struct regsets_info tic6x_regsets_info =
NULL, /* disabled_regsets */
};
-static struct usrregs_info tic6x_usrregs_info =
- {
- TIC6X_NUM_REGS,
- NULL, /* Set in tic6x_read_description. */
- };
-
static struct regs_info regs_info =
{
NULL, /* regset_bitmap */
NULL,
0,
tic6x_breakpoint_at,
+ NULL, /* supports_z_point_type */
+ NULL, /* insert_point */
+ NULL, /* remove_point */
+ NULL, /* stopped_by_watchpoint */
+ NULL, /* stopped_data_address */
+ NULL, /* collect_ptrace_register */
+ NULL, /* supply_ptrace_register */
+ NULL, /* siginfo_fixup */
+ NULL, /* new_process */
+ NULL, /* delete_process */
+ NULL, /* new_thread */
+ NULL, /* delete_thread */
+ NULL, /* new_fork */
+ NULL, /* prepare_to_resume */
+ NULL, /* process_qsupported */
+ NULL, /* supports_tracepoints */
+ NULL, /* get_thread_area */
+ NULL, /* install_fast_tracepoint_jump_pad */
+ NULL, /* emit_ops */
+ NULL, /* get_min_fast_tracepoint_insn_len */
+ NULL, /* supports_range_stepping */
+ NULL, /* breakpoint_kind_from_current_state */
+ tic6x_supports_hardware_single_step,
};
+#if GDB_SELF_TEST
+#include "common/selftest.h"
+
+namespace selftests {
+namespace tdesc {
+static void
+tic6x_tdesc_test ()
+{
+ SELF_CHECK (*tdesc_tic6x_c62x_linux == *tic6x_read_description (C6X_CORE));
+ SELF_CHECK (*tdesc_tic6x_c64x_linux == *tic6x_read_description (C6X_GP));
+ SELF_CHECK (*tdesc_tic6x_c64xp_linux == *tic6x_read_description (C6X_C6XP));
+}
+}
+}
+#endif
+
void
initialize_low_arch (void)
{
+#if GDB_SELF_TEST
/* Initialize the Linux target descriptions. */
init_registers_tic6x_c64xp_linux ();
init_registers_tic6x_c64x_linux ();
init_registers_tic6x_c62x_linux ();
+ selftests::register_test ("tic6x-tdesc", selftests::tdesc::tic6x_tdesc_test);
+#endif
+
initialize_regsets_info (&tic6x_regsets_info);
}