#include "frame-base.h"
#include "trad-frame.h"
#include "dis-asm.h"
+#include "gdb_assert.h"
+#include "sim-regno.h"
+#include "gdb/sim-frv.h"
+#include "opcodes/frv-desc.h" /* for the H_SPR_... enums */
extern void _initialize_frv_tdep (void);
static gdbarch_register_name_ftype frv_register_name;
static gdbarch_breakpoint_from_pc_ftype frv_breakpoint_from_pc;
+static gdbarch_adjust_breakpoint_address_ftype frv_gdbarch_adjust_breakpoint_address;
static gdbarch_skip_prologue_ftype frv_skip_prologue;
-static gdbarch_deprecated_extract_return_value_ftype frv_extract_return_value;
-static gdbarch_deprecated_extract_struct_value_address_ftype frv_extract_struct_value_address;
static gdbarch_frameless_function_invocation_ftype frv_frameless_function_invocation;
static gdbarch_deprecated_push_arguments_ftype frv_push_arguments;
static gdbarch_deprecated_saved_pc_after_call_ftype frv_saved_pc_after_call;
-/* Register numbers. You can change these as needed, but don't forget
- to update the simulator accordingly. */
+/* Register numbers. The order in which these appear define the
+ remote protocol, so take care in changing them. */
enum {
- /* The total number of registers we know exist. */
- frv_num_regs = 147,
-
/* Register numbers 0 -- 63 are always reserved for general-purpose
registers. The chip at hand may have less. */
first_gpr_regnum = 0,
first_fpr_regnum = 64,
last_fpr_regnum = 127,
- /* Register numbers 128 on up are always reserved for special-purpose
- registers. */
- first_spr_regnum = 128,
+ /* The PC register. */
pc_regnum = 128,
+
+ /* Register numbers 129 on up are always reserved for special-purpose
+ registers. */
+ first_spr_regnum = 129,
psr_regnum = 129,
ccr_regnum = 130,
cccr_regnum = 131,
dbar3_regnum = 140,
lr_regnum = 145,
lcr_regnum = 146,
- last_spr_regnum = 146
+ iacc0h_regnum = 147,
+ iacc0l_regnum = 148,
+ last_spr_regnum = 148,
+
+ /* The total number of registers we know exist. */
+ frv_num_regs = last_spr_regnum + 1,
+
+ /* Pseudo registers */
+ first_pseudo_regnum = frv_num_regs,
+
+ /* iacc0 - the 64-bit concatenation of iacc0h and iacc0l. */
+ iacc0_regnum = first_pseudo_regnum + 0,
+
+ last_pseudo_regnum = iacc0_regnum,
+ frv_num_pseudo_regs = last_pseudo_regnum - first_pseudo_regnum + 1,
};
static LONGEST frv_call_dummy_words[] =
/* By default, don't supply any general-purpose or floating-point
register names. */
- var->register_names = (char **) xmalloc (frv_num_regs * sizeof (char *));
- for (r = 0; r < frv_num_regs; r++)
+ var->register_names
+ = (char **) xmalloc ((frv_num_regs + frv_num_pseudo_regs)
+ * sizeof (char *));
+ for (r = 0; r < frv_num_regs + frv_num_pseudo_regs; r++)
var->register_names[r] = "";
- /* Do, however, supply default names for the special-purpose
+ /* Do, however, supply default names for the known special-purpose
registers. */
- for (r = first_spr_regnum; r <= last_spr_regnum; ++r)
- {
- sprintf (buf, "x%d", r);
- var->register_names[r] = xstrdup (buf);
- }
var->register_names[pc_regnum] = "pc";
var->register_names[lr_regnum] = "lr";
var->register_names[dbar2_regnum] = "dbar2";
var->register_names[dbar3_regnum] = "dbar3";
+ /* iacc0 (Only found on MB93405.) */
+ var->register_names[iacc0h_regnum] = "iacc0h";
+ var->register_names[iacc0l_regnum] = "iacc0l";
+ var->register_names[iacc0_regnum] = "iacc0";
+
return var;
}
{
if (reg < 0)
return "?toosmall?";
- if (reg >= frv_num_regs)
+ if (reg >= frv_num_regs + frv_num_pseudo_regs)
return "?toolarge?";
return CURRENT_VARIANT->register_names[reg];
}
-static int
-frv_register_raw_size (int reg)
+static struct type *
+frv_register_type (struct gdbarch *gdbarch, int reg)
{
- return 4;
+ if (reg >= first_fpr_regnum && reg <= last_fpr_regnum)
+ return builtin_type_float;
+ else if (reg == iacc0_regnum)
+ return builtin_type_int64;
+ else
+ return builtin_type_int32;
}
-static int
-frv_register_virtual_size (int reg)
+static void
+frv_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg, void *buffer)
{
- return 4;
+ if (reg == iacc0_regnum)
+ {
+ regcache_raw_read (regcache, iacc0h_regnum, buffer);
+ regcache_raw_read (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
+ }
}
-static struct type *
-frv_register_virtual_type (int reg)
+static void
+frv_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int reg, const void *buffer)
{
- if (reg >= 64 && reg <= 127)
- return builtin_type_float;
- else
- return builtin_type_int;
+ if (reg == iacc0_regnum)
+ {
+ regcache_raw_write (regcache, iacc0h_regnum, buffer);
+ regcache_raw_write (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
+ }
}
static int
-frv_register_byte (int reg)
+frv_register_sim_regno (int reg)
{
- return (reg * 4);
+ static const int spr_map[] =
+ {
+ H_SPR_PSR, /* psr_regnum */
+ H_SPR_CCR, /* ccr_regnum */
+ H_SPR_CCCR, /* cccr_regnum */
+ -1, /* 132 */
+ -1, /* 133 */
+ -1, /* 134 */
+ H_SPR_TBR, /* tbr_regnum */
+ H_SPR_BRR, /* brr_regnum */
+ H_SPR_DBAR0, /* dbar0_regnum */
+ H_SPR_DBAR1, /* dbar1_regnum */
+ H_SPR_DBAR2, /* dbar2_regnum */
+ H_SPR_DBAR3, /* dbar3_regnum */
+ -1, /* 141 */
+ -1, /* 142 */
+ -1, /* 143 */
+ -1, /* 144 */
+ H_SPR_LR, /* lr_regnum */
+ H_SPR_LCR, /* lcr_regnum */
+ H_SPR_IACC0H, /* iacc0h_regnum */
+ H_SPR_IACC0L /* iacc0l_regnum */
+ };
+
+ gdb_assert (reg >= 0 && reg < NUM_REGS);
+
+ if (first_gpr_regnum <= reg && reg <= last_gpr_regnum)
+ return reg - first_gpr_regnum + SIM_FRV_GR0_REGNUM;
+ else if (first_fpr_regnum <= reg && reg <= last_fpr_regnum)
+ return reg - first_fpr_regnum + SIM_FRV_FR0_REGNUM;
+ else if (pc_regnum == reg)
+ return SIM_FRV_PC_REGNUM;
+ else if (reg >= first_spr_regnum
+ && reg < first_spr_regnum + sizeof (spr_map) / sizeof (spr_map[0]))
+ {
+ int spr_reg_offset = spr_map[reg - first_spr_regnum];
+
+ if (spr_reg_offset < 0)
+ return SIM_REGNO_DOES_NOT_EXIST;
+ else
+ return SIM_FRV_SPR0_REGNUM + spr_reg_offset;
+ }
+
+ internal_error (__FILE__, __LINE__, "Bad register number %d", reg);
}
static const unsigned char *
return breakpoint;
}
+/* Define the maximum number of instructions which may be packed into a
+ bundle (VLIW instruction). */
+static const int max_instrs_per_bundle = 8;
+
+/* Define the size (in bytes) of an FR-V instruction. */
+static const int frv_instr_size = 4;
+
+/* Adjust a breakpoint's address to account for the FR-V architecture's
+ constraint that a break instruction must not appear as any but the
+ first instruction in the bundle. */
+static CORE_ADDR
+frv_gdbarch_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
+{
+ int count = max_instrs_per_bundle;
+ CORE_ADDR addr = bpaddr - frv_instr_size;
+ CORE_ADDR func_start = get_pc_function_start (bpaddr);
+
+ /* Find the end of the previous packing sequence. This will be indicated
+ by either attempting to access some inaccessible memory or by finding
+ an instruction word whose packing bit is set to one. */
+ while (count-- > 0 && addr >= func_start)
+ {
+ char instr[frv_instr_size];
+ int status;
+
+ status = read_memory_nobpt (addr, instr, sizeof instr);
+
+ if (status != 0)
+ break;
+
+ /* This is a big endian architecture, so byte zero will have most
+ significant byte. The most significant bit of this byte is the
+ packing bit. */
+ if (instr[0] & 0x80)
+ break;
+
+ addr -= frv_instr_size;
+ }
+
+ if (count > 0)
+ bpaddr = addr + frv_instr_size;
+
+ return bpaddr;
+}
+
/* Return true if REG is a caller-saves ("scratch") register,
false otherwise. */
}
static void
-frv_extract_return_value (struct type *type, char *regbuf, char *valbuf)
+frv_extract_return_value (struct type *type, struct regcache *regcache,
+ void *valbuf)
{
- memcpy (valbuf, (regbuf
- + frv_register_byte (8)
- + (TYPE_LENGTH (type) < 4 ? 4 - TYPE_LENGTH (type) : 0)),
- TYPE_LENGTH (type));
+ int len = TYPE_LENGTH (type);
+
+ if (len <= 4)
+ {
+ ULONGEST gpr8_val;
+ regcache_cooked_read_unsigned (regcache, 8, &gpr8_val);
+ store_unsigned_integer (valbuf, len, gpr8_val);
+ }
+ else if (len == 8)
+ {
+ ULONGEST regval;
+ regcache_cooked_read_unsigned (regcache, 8, ®val);
+ store_unsigned_integer (valbuf, 4, regval);
+ regcache_cooked_read_unsigned (regcache, 9, ®val);
+ store_unsigned_integer ((bfd_byte *) valbuf + 4, 4, regval);
+ }
+ else
+ internal_error (__FILE__, __LINE__, "Illegal return value length: %d", len);
}
static CORE_ADDR
-frv_extract_struct_value_address (char *regbuf)
+frv_extract_struct_value_address (struct regcache *regcache)
{
- return extract_unsigned_integer (regbuf +
- frv_register_byte (struct_return_regnum),
- 4);
+ ULONGEST addr;
+ regcache_cooked_read_unsigned (regcache, struct_return_regnum, &addr);
+ return addr;
}
static void
}
static void
-frv_store_return_value (struct type *type, char *valbuf)
+frv_store_return_value (struct type *type, struct regcache *regcache,
+ const void *valbuf)
{
- int length = TYPE_LENGTH (type);
- int reg8_offset = frv_register_byte (8);
-
- if (length <= 4)
- deprecated_write_register_bytes (reg8_offset + (4 - length), valbuf,
- length);
- else if (length == 8)
- deprecated_write_register_bytes (reg8_offset, valbuf, length);
+ int len = TYPE_LENGTH (type);
+
+ if (len <= 4)
+ {
+ bfd_byte val[4];
+ memset (val, 0, sizeof (val));
+ memcpy (val + (4 - len), valbuf, len);
+ regcache_cooked_write (regcache, 8, val);
+ }
+ else if (len == 8)
+ {
+ regcache_cooked_write (regcache, 8, valbuf);
+ regcache_cooked_write (regcache, 9, (bfd_byte *) valbuf + 4);
+ }
else
internal_error (__FILE__, __LINE__,
- "Don't know how to return a %d-byte value.", length);
+ "Don't know how to return a %d-byte value.", len);
}
/* The FUNC is easy. */
func = frame_func_unwind (next_frame);
- /* This is meant to halt the backtrace at "_start". Make sure we
- don't halt it at a generic dummy frame. */
- if (deprecated_inside_entry_file (func))
- return;
-
/* Check if the stack is empty. */
msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL);
if (msym_stack && info->base == SYMBOL_VALUE_ADDRESS (msym_stack))
set_gdbarch_ptr_bit (gdbarch, 32);
set_gdbarch_num_regs (gdbarch, frv_num_regs);
+ set_gdbarch_num_pseudo_regs (gdbarch, frv_num_pseudo_regs);
+
set_gdbarch_sp_regnum (gdbarch, sp_regnum);
set_gdbarch_deprecated_fp_regnum (gdbarch, fp_regnum);
set_gdbarch_pc_regnum (gdbarch, pc_regnum);
set_gdbarch_register_name (gdbarch, frv_register_name);
- set_gdbarch_deprecated_register_size (gdbarch, 4);
- set_gdbarch_deprecated_register_bytes (gdbarch, frv_num_regs * 4);
- set_gdbarch_deprecated_register_byte (gdbarch, frv_register_byte);
- set_gdbarch_deprecated_register_raw_size (gdbarch, frv_register_raw_size);
- set_gdbarch_deprecated_max_register_raw_size (gdbarch, 4);
- set_gdbarch_deprecated_register_virtual_size (gdbarch, frv_register_virtual_size);
- set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 4);
- set_gdbarch_deprecated_register_virtual_type (gdbarch, frv_register_virtual_type);
+ set_gdbarch_register_type (gdbarch, frv_register_type);
+ set_gdbarch_register_sim_regno (gdbarch, frv_register_sim_regno);
+
+ set_gdbarch_pseudo_register_read (gdbarch, frv_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, frv_pseudo_register_write);
set_gdbarch_skip_prologue (gdbarch, frv_skip_prologue);
set_gdbarch_breakpoint_from_pc (gdbarch, frv_breakpoint_from_pc);
+ set_gdbarch_adjust_breakpoint_address (gdbarch, frv_gdbarch_adjust_breakpoint_address);
set_gdbarch_frame_args_skip (gdbarch, 0);
set_gdbarch_frameless_function_invocation (gdbarch, frv_frameless_function_invocation);
set_gdbarch_use_struct_convention (gdbarch, always_use_struct_convention);
- set_gdbarch_deprecated_extract_return_value (gdbarch, frv_extract_return_value);
+ set_gdbarch_extract_return_value (gdbarch, frv_extract_return_value);
set_gdbarch_deprecated_store_struct_return (gdbarch, frv_store_struct_return);
- set_gdbarch_deprecated_store_return_value (gdbarch, frv_store_return_value);
- set_gdbarch_deprecated_extract_struct_value_address (gdbarch, frv_extract_struct_value_address);
+ set_gdbarch_store_return_value (gdbarch, frv_store_return_value);
+ set_gdbarch_extract_struct_value_address (gdbarch, frv_extract_struct_value_address);
/* Frame stuff. */
set_gdbarch_unwind_pc (gdbarch, frv_unwind_pc);