+#include "dis-asm.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "language.h"
+#include "arch-utils.h"
+#include "regcache.h"
+
+#include "floatformat.h"
+#include "sim-d10v.h"
+
+#undef XMALLOC
+#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
+
+struct frame_extra_info
+ {
+ CORE_ADDR return_pc;
+ int frameless;
+ int size;
+ };
+
+struct gdbarch_tdep
+ {
+ int a0_regnum;
+ int nr_dmap_regs;
+ unsigned long (*dmap_register) (int nr);
+ unsigned long (*imap_register) (int nr);
+ };
+
+/* These are the addresses the D10V-EVA board maps data and
+ instruction memory to. */
+
+#define DMEM_START 0x2000000
+#define IMEM_START 0x1000000
+#define STACK_START 0x0007ffe
+
+/* d10v register names. */
+
+enum
+ {
+ R0_REGNUM = 0,
+ LR_REGNUM = 13,
+ PSW_REGNUM = 16,
+ NR_IMAP_REGS = 2,
+ NR_A_REGS = 2
+ };
+#define NR_DMAP_REGS (gdbarch_tdep (current_gdbarch)->nr_dmap_regs)
+#define A0_REGNUM (gdbarch_tdep (current_gdbarch)->a0_regnum)
+
+/* d10v calling convention. */
+
+#define ARG1_REGNUM R0_REGNUM
+#define ARGN_REGNUM 3
+#define RET1_REGNUM R0_REGNUM
+
+/* Local functions */
+
+extern void _initialize_d10v_tdep (void);
+
+static void d10v_eva_prepare_to_trace (void);
+
+static void d10v_eva_get_trace_data (void);
+
+static int prologue_find_regs (unsigned short op, struct frame_info *fi,
+ CORE_ADDR addr);
+
+extern void d10v_frame_init_saved_regs (struct frame_info *);
+
+static void do_d10v_pop_frame (struct frame_info *fi);
+
+int
+d10v_frame_chain_valid (CORE_ADDR chain, struct frame_info *frame)
+{
+ return ((chain) != 0 && (frame) != 0 && (frame)->pc > IMEM_START);
+}
+
+static CORE_ADDR
+d10v_stack_align (CORE_ADDR len)
+{
+ return (len + 1) & ~1;
+}
+
+/* Should we use EXTRACT_STRUCT_VALUE_ADDRESS instead of
+ EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc
+ and TYPE is the type (which is known to be struct, union or array).
+
+ The d10v returns anything less than 8 bytes in size in
+ registers. */
+
+int
+d10v_use_struct_convention (int gcc_p, struct type *type)
+{
+ return (TYPE_LENGTH (type) > 8);
+}
+
+
+unsigned char *
+d10v_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+{
+ static unsigned char breakpoint[] =
+ {0x2f, 0x90, 0x5e, 0x00};
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+}
+
+/* Map the REG_NR onto an ascii name. Return NULL or an empty string
+ when the reg_nr isn't valid. */
+
+enum ts2_regnums
+ {
+ TS2_IMAP0_REGNUM = 32,
+ TS2_DMAP_REGNUM = 34,
+ TS2_NR_DMAP_REGS = 1,
+ TS2_A0_REGNUM = 35
+ };
+
+static char *
+d10v_ts2_register_name (int reg_nr)
+{
+ static char *register_names[] =
+ {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "psw", "bpsw", "pc", "bpc", "cr4", "cr5", "cr6", "rpt_c",
+ "rpt_s", "rpt_e", "mod_s", "mod_e", "cr12", "cr13", "iba", "cr15",
+ "imap0", "imap1", "dmap", "a0", "a1"
+ };
+ if (reg_nr < 0)
+ return NULL;
+ if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
+ return NULL;
+ return register_names[reg_nr];
+}
+
+enum ts3_regnums
+ {
+ TS3_IMAP0_REGNUM = 36,
+ TS3_DMAP0_REGNUM = 38,
+ TS3_NR_DMAP_REGS = 4,
+ TS3_A0_REGNUM = 32
+ };
+
+static char *
+d10v_ts3_register_name (int reg_nr)
+{
+ static char *register_names[] =
+ {
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "psw", "bpsw", "pc", "bpc", "cr4", "cr5", "cr6", "rpt_c",
+ "rpt_s", "rpt_e", "mod_s", "mod_e", "cr12", "cr13", "iba", "cr15",
+ "a0", "a1",
+ "spi", "spu",
+ "imap0", "imap1",
+ "dmap0", "dmap1", "dmap2", "dmap3"
+ };
+ if (reg_nr < 0)
+ return NULL;
+ if (reg_nr >= (sizeof (register_names) / sizeof (*register_names)))
+ return NULL;
+ return register_names[reg_nr];
+}
+
+/* Access the DMAP/IMAP registers in a target independent way. */
+
+static unsigned long
+d10v_ts2_dmap_register (int reg_nr)
+{
+ switch (reg_nr)
+ {
+ case 0:
+ case 1:
+ return 0x2000;
+ case 2:
+ return read_register (TS2_DMAP_REGNUM);
+ default:
+ return 0;
+ }
+}
+
+static unsigned long
+d10v_ts3_dmap_register (int reg_nr)
+{
+ return read_register (TS3_DMAP0_REGNUM + reg_nr);
+}
+
+static unsigned long
+d10v_dmap_register (int reg_nr)
+{
+ return gdbarch_tdep (current_gdbarch)->dmap_register (reg_nr);
+}
+
+static unsigned long
+d10v_ts2_imap_register (int reg_nr)
+{
+ return read_register (TS2_IMAP0_REGNUM + reg_nr);
+}
+
+static unsigned long
+d10v_ts3_imap_register (int reg_nr)
+{
+ return read_register (TS3_IMAP0_REGNUM + reg_nr);
+}
+
+static unsigned long
+d10v_imap_register (int reg_nr)
+{
+ return gdbarch_tdep (current_gdbarch)->imap_register (reg_nr);
+}
+
+/* MAP GDB's internal register numbering (determined by the layout fo
+ the REGISTER_BYTE array) onto the simulator's register
+ numbering. */
+
+static int
+d10v_ts2_register_sim_regno (int nr)
+{
+ if (nr >= TS2_IMAP0_REGNUM
+ && nr < TS2_IMAP0_REGNUM + NR_IMAP_REGS)
+ return nr - TS2_IMAP0_REGNUM + SIM_D10V_IMAP0_REGNUM;
+ if (nr == TS2_DMAP_REGNUM)
+ return nr - TS2_DMAP_REGNUM + SIM_D10V_TS2_DMAP_REGNUM;
+ if (nr >= TS2_A0_REGNUM
+ && nr < TS2_A0_REGNUM + NR_A_REGS)
+ return nr - TS2_A0_REGNUM + SIM_D10V_A0_REGNUM;
+ return nr;
+}
+
+static int
+d10v_ts3_register_sim_regno (int nr)
+{
+ if (nr >= TS3_IMAP0_REGNUM
+ && nr < TS3_IMAP0_REGNUM + NR_IMAP_REGS)
+ return nr - TS3_IMAP0_REGNUM + SIM_D10V_IMAP0_REGNUM;
+ if (nr >= TS3_DMAP0_REGNUM
+ && nr < TS3_DMAP0_REGNUM + TS3_NR_DMAP_REGS)
+ return nr - TS3_DMAP0_REGNUM + SIM_D10V_DMAP0_REGNUM;
+ if (nr >= TS3_A0_REGNUM
+ && nr < TS3_A0_REGNUM + NR_A_REGS)
+ return nr - TS3_A0_REGNUM + SIM_D10V_A0_REGNUM;
+ return nr;
+}
+
+/* Index within `registers' of the first byte of the space for
+ register REG_NR. */
+
+int
+d10v_register_byte (int reg_nr)
+{
+ if (reg_nr < A0_REGNUM)
+ return (reg_nr * 2);
+ else if (reg_nr < (A0_REGNUM + NR_A_REGS))
+ return (A0_REGNUM * 2
+ + (reg_nr - A0_REGNUM) * 8);
+ else
+ return (A0_REGNUM * 2
+ + NR_A_REGS * 8
+ + (reg_nr - A0_REGNUM - NR_A_REGS) * 2);
+}
+
+/* Number of bytes of storage in the actual machine representation for
+ register REG_NR. */
+
+int
+d10v_register_raw_size (int reg_nr)
+{
+ if (reg_nr < A0_REGNUM)
+ return 2;
+ else if (reg_nr < (A0_REGNUM + NR_A_REGS))
+ return 8;
+ else
+ return 2;
+}
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+int
+d10v_register_virtual_size (int reg_nr)
+{
+ return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (reg_nr));
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+struct type *
+d10v_register_virtual_type (int reg_nr)
+{
+ if (reg_nr >= A0_REGNUM
+ && reg_nr < (A0_REGNUM + NR_A_REGS))
+ return builtin_type_int64;
+ else if (reg_nr == PC_REGNUM
+ || reg_nr == SP_REGNUM)
+ return builtin_type_int32;
+ else
+ return builtin_type_int16;
+}
+
+/* convert $pc and $sp to/from virtual addresses */
+int
+d10v_register_convertible (int nr)
+{
+ return ((nr) == PC_REGNUM || (nr) == SP_REGNUM);
+}
+
+void
+d10v_register_convert_to_virtual (int regnum, struct type *type, char *from,
+ char *to)
+{
+ ULONGEST x = extract_unsigned_integer (from, REGISTER_RAW_SIZE (regnum));
+ if (regnum == PC_REGNUM)
+ x = (x << 2) | IMEM_START;
+ else
+ x |= DMEM_START;
+ store_unsigned_integer (to, TYPE_LENGTH (type), x);
+}
+
+void
+d10v_register_convert_to_raw (struct type *type, int regnum, char *from,
+ char *to)
+{
+ ULONGEST x = extract_unsigned_integer (from, TYPE_LENGTH (type));
+ x &= 0x3ffff;
+ if (regnum == PC_REGNUM)
+ x >>= 2;
+ store_unsigned_integer (to, 2, x);
+}
+
+
+CORE_ADDR
+d10v_make_daddr (CORE_ADDR x)
+{
+ return ((x) | DMEM_START);
+}
+
+CORE_ADDR
+d10v_make_iaddr (CORE_ADDR x)
+{
+ return (((x) << 2) | IMEM_START);
+}
+
+int
+d10v_daddr_p (CORE_ADDR x)
+{
+ return (((x) & 0x3000000) == DMEM_START);
+}
+
+int
+d10v_iaddr_p (CORE_ADDR x)
+{
+ return (((x) & 0x3000000) == IMEM_START);
+}