/* Target-dependent code for the Fujitsu FR-V, for GDB, the GNU Debugger.
- Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
+
+ Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "gdb_string.h"
#include "elf-bfd.h"
#include "elf/frv.h"
#include "osabi.h"
+#include "infcall.h"
#include "frv-tdep.h"
extern void _initialize_frv_tdep (void);
-static gdbarch_init_ftype frv_gdbarch_init;
-
-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;
-
-
struct frv_unwind_cache /* was struct frame_extra_info */
{
/* The previous frame's inner-most stack address. Used as this
/* Register names. */
char **register_names;
-
- /* Given NEXT_FRAME, determine the address of register REGNO saved in
- the calling sigtramp frame. */
- CORE_ADDR (*sigcontext_reg_addr) (struct frame_info *next_frame, int regno,
- CORE_ADDR *);
};
#define CURRENT_VARIANT (gdbarch_tdep (current_gdbarch))
return gdbarch_tdep (gdbarch)->frv_abi;
}
-/* Set sigcontext_reg_addr. */
-void
-frv_set_sigcontext_reg_addr (struct gdbarch *gdbarch,
- CORE_ADDR (*sigcontext_reg_addr)
- (struct frame_info *, int, CORE_ADDR *))
-{
- gdbarch_tdep (gdbarch)->sigcontext_reg_addr = sigcontext_reg_addr;
-}
-
/* Fetch the interpreter and executable loadmap addresses (for shared
library support) for the FDPIC ABI. Return 0 if successful, -1 if
not. (E.g, -1 will be returned if the ABI isn't the FDPIC ABI.) */
return -1;
else
{
+ struct regcache *regcache = get_current_regcache ();
+
if (interp_addr != NULL)
{
ULONGEST val;
- regcache_cooked_read_unsigned (current_regcache,
+ regcache_cooked_read_unsigned (regcache,
fdpic_loadmap_interp_regnum, &val);
*interp_addr = val;
}
if (exec_addr != NULL)
{
ULONGEST val;
- regcache_cooked_read_unsigned (current_regcache,
+ regcache_cooked_read_unsigned (regcache,
fdpic_loadmap_exec_regnum, &val);
*exec_addr = val;
}
var->register_names[iacc0l_regnum] = "iacc0l";
var->register_names[iacc0_regnum] = "iacc0";
+ /* fsr0 (Found on FR555 and FR501.) */
+ var->register_names[fsr0_regnum] = "fsr0";
+
+ /* acc0 - acc7. The architecture provides for the possibility of many
+ more (up to 64 total), but we don't want to make that big of a hole
+ in the G packet. If we need more in the future, we'll add them
+ elsewhere. */
+ for (r = acc0_regnum; r <= acc7_regnum; r++)
+ {
+ char *buf;
+ buf = xstrprintf ("acc%d", r - acc0_regnum);
+ var->register_names[r] = buf;
+ }
+
+ /* accg0 - accg7: These are one byte registers. The remote protocol
+ provides the raw values packed four into a slot. accg0123 and
+ accg4567 correspond to accg0 - accg3 and accg4-accg7 respectively.
+ We don't provide names for accg0123 and accg4567 since the user will
+ likely not want to see these raw values. */
+
+ for (r = accg0_regnum; r <= accg7_regnum; r++)
+ {
+ char *buf;
+ buf = xstrprintf ("accg%d", r - accg0_regnum);
+ var->register_names[r] = buf;
+ }
+
+ /* msr0 and msr1. */
+
+ var->register_names[msr0_regnum] = "msr0";
+ var->register_names[msr1_regnum] = "msr1";
+
+ /* gner and fner registers. */
+ var->register_names[gner0_regnum] = "gner0";
+ var->register_names[gner1_regnum] = "gner1";
+ var->register_names[fner0_regnum] = "fner0";
+ var->register_names[fner1_regnum] = "fner1";
+
return var;
}
static void
frv_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
- int reg, void *buffer)
+ int reg, gdb_byte *buffer)
{
if (reg == iacc0_regnum)
{
regcache_raw_read (regcache, iacc0h_regnum, buffer);
regcache_raw_read (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
}
+ else if (accg0_regnum <= reg && reg <= accg7_regnum)
+ {
+ /* The accg raw registers have four values in each slot with the
+ lowest register number occupying the first byte. */
+
+ int raw_regnum = accg0123_regnum + (reg - accg0_regnum) / 4;
+ int byte_num = (reg - accg0_regnum) % 4;
+ bfd_byte buf[4];
+
+ regcache_raw_read (regcache, raw_regnum, buf);
+ memset (buffer, 0, 4);
+ /* FR-V is big endian, so put the requested byte in the first byte
+ of the buffer allocated to hold the pseudo-register. */
+ ((bfd_byte *) buffer)[0] = buf[byte_num];
+ }
}
static void
frv_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
- int reg, const void *buffer)
+ int reg, const gdb_byte *buffer)
{
if (reg == iacc0_regnum)
{
regcache_raw_write (regcache, iacc0h_regnum, buffer);
regcache_raw_write (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
}
+ else if (accg0_regnum <= reg && reg <= accg7_regnum)
+ {
+ /* The accg raw registers have four values in each slot with the
+ lowest register number occupying the first byte. */
+
+ int raw_regnum = accg0123_regnum + (reg - accg0_regnum) / 4;
+ int byte_num = (reg - accg0_regnum) % 4;
+ char buf[4];
+
+ regcache_raw_read (regcache, raw_regnum, buf);
+ buf[byte_num] = ((bfd_byte *) buffer)[0];
+ regcache_raw_write (regcache, raw_regnum, buf);
+ }
}
static int
H_SPR_PSR, /* psr_regnum */
H_SPR_CCR, /* ccr_regnum */
H_SPR_CCCR, /* cccr_regnum */
- -1, /* 132 */
- -1, /* 133 */
+ -1, /* fdpic_loadmap_exec_regnum */
+ -1, /* fdpic_loadmap_interp_regnum */
-1, /* 134 */
H_SPR_TBR, /* tbr_regnum */
H_SPR_BRR, /* brr_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_SCR0, /* scr0_regnum */
+ H_SPR_SCR1, /* scr1_regnum */
+ H_SPR_SCR2, /* scr2_regnum */
+ H_SPR_SCR3, /* scr3_regnum */
H_SPR_LR, /* lr_regnum */
H_SPR_LCR, /* lcr_regnum */
H_SPR_IACC0H, /* iacc0h_regnum */
- H_SPR_IACC0L /* iacc0l_regnum */
+ H_SPR_IACC0L, /* iacc0l_regnum */
+ H_SPR_FSR0, /* fsr0_regnum */
+ /* FIXME: Add infrastructure for fetching/setting ACC and ACCG regs. */
+ -1, /* acc0_regnum */
+ -1, /* acc1_regnum */
+ -1, /* acc2_regnum */
+ -1, /* acc3_regnum */
+ -1, /* acc4_regnum */
+ -1, /* acc5_regnum */
+ -1, /* acc6_regnum */
+ -1, /* acc7_regnum */
+ -1, /* acc0123_regnum */
+ -1, /* acc4567_regnum */
+ H_SPR_MSR0, /* msr0_regnum */
+ H_SPR_MSR1, /* msr1_regnum */
+ H_SPR_GNER0, /* gner0_regnum */
+ H_SPR_GNER1, /* gner1_regnum */
+ H_SPR_FNER0, /* fner0_regnum */
+ H_SPR_FNER1, /* fner1_regnum */
};
- gdb_assert (reg >= 0 && reg < NUM_REGS);
+ gdb_assert (reg >= 0 && reg < gdbarch_num_regs (current_gdbarch));
if (first_gpr_regnum <= reg && reg <= last_gpr_regnum)
return reg - first_gpr_regnum + SIM_FRV_GR0_REGNUM;
return SIM_FRV_SPR0_REGNUM + spr_reg_offset;
}
- internal_error (__FILE__, __LINE__, "Bad register number %d", reg);
+ internal_error (__FILE__, __LINE__, _("Bad register number %d"), reg);
}
static const unsigned char *
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)
+frv_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
{
int count = max_instrs_per_bundle;
CORE_ADDR addr = bpaddr - frv_instr_size;
info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
/* Prologue analysis does the rest... */
- frv_analyze_prologue (frame_func_unwind (next_frame), next_frame, info);
+ frv_analyze_prologue (frame_func_unwind (next_frame, NORMAL_FRAME),
+ next_frame, info);
return info;
}
static void
frv_extract_return_value (struct type *type, struct regcache *regcache,
- void *valbuf)
+ gdb_byte *valbuf)
{
int len = TYPE_LENGTH (type);
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 (struct regcache *regcache)
-{
- ULONGEST addr;
- regcache_cooked_read_unsigned (regcache, struct_return_regnum, &addr);
- return addr;
-}
-
-static void
-frv_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
-{
- write_register (struct_return_regnum, addr);
-}
-
-static int
-frv_frameless_function_invocation (struct frame_info *frame)
-{
- return legacy_frameless_look_for_prologue (frame);
+ internal_error (__FILE__, __LINE__, _("Illegal return value length: %d"), len);
}
static CORE_ADDR
{
CORE_ADDR descr;
char valbuf[4];
+ CORE_ADDR start_addr;
+
+ /* If we can't find the function in the symbol table, then we assume
+ that the function address is already in descriptor form. */
+ if (!find_pc_partial_function (entry_point, NULL, &start_addr, NULL)
+ || entry_point != start_addr)
+ return entry_point;
descr = frv_fdpic_find_canonical_descriptor (entry_point);
}
static CORE_ADDR
-frv_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+frv_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
int stack_space;
int stack_offset;
enum frv_abi abi = frv_abi (gdbarch);
+ CORE_ADDR func_addr = find_function_addr (function, NULL);
#if 0
printf("Push %d args at sp = %x, struct_return=%d (%x)\n",
stack_space = 0;
for (argnum = 0; argnum < nargs; ++argnum)
- stack_space += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])), 4);
+ stack_space += align_up (TYPE_LENGTH (value_type (args[argnum])), 4);
stack_space -= (6 * 4);
if (stack_space > 0)
for (argnum = 0; argnum < nargs; ++argnum)
{
arg = args[argnum];
- arg_type = check_typedef (VALUE_TYPE (arg));
+ arg_type = check_typedef (value_type (arg));
len = TYPE_LENGTH (arg_type);
typecode = TYPE_CODE (arg_type);
store_unsigned_integer
(valbuf, 4,
find_func_descr (gdbarch,
- extract_unsigned_integer (VALUE_CONTENTS (arg),
+ extract_unsigned_integer (value_contents (arg),
4)));
typecode = TYPE_CODE_PTR;
len = 4;
}
else
{
- val = (char *) VALUE_CONTENTS (arg);
+ val = (char *) value_contents (arg);
}
while (len > 0)
static void
frv_store_return_value (struct type *type, struct regcache *regcache,
- const void *valbuf)
+ const gdb_byte *valbuf)
{
int len = TYPE_LENGTH (type);
}
else
internal_error (__FILE__, __LINE__,
- "Don't know how to return a %d-byte value.", len);
+ _("Don't know how to return a %d-byte value."), len);
}
}
-CORE_ADDR
-frv_stopped_data_address (void)
+int
+frv_stopped_data_address (CORE_ADDR *addr_p)
{
+ struct frame_info *frame = get_current_frame ();
CORE_ADDR brr, dbar0, dbar1, dbar2, dbar3;
- brr = read_register (brr_regnum);
- dbar0 = read_register (dbar0_regnum);
- dbar1 = read_register (dbar1_regnum);
- dbar2 = read_register (dbar2_regnum);
- dbar3 = read_register (dbar3_regnum);
+ brr = get_frame_register_unsigned (frame, brr_regnum);
+ dbar0 = get_frame_register_unsigned (frame, dbar0_regnum);
+ dbar1 = get_frame_register_unsigned (frame, dbar1_regnum);
+ dbar2 = get_frame_register_unsigned (frame, dbar2_regnum);
+ dbar3 = get_frame_register_unsigned (frame, dbar3_regnum);
if (brr & (1<<11))
- return dbar0;
+ *addr_p = dbar0;
else if (brr & (1<<10))
- return dbar1;
+ *addr_p = dbar1;
else if (brr & (1<<9))
- return dbar2;
+ *addr_p = dbar2;
else if (brr & (1<<8))
- return dbar3;
+ *addr_p = dbar3;
else
return 0;
+
+ return 1;
+}
+
+int
+frv_have_stopped_data_address (void)
+{
+ CORE_ADDR addr = 0;
+ return frv_stopped_data_address (&addr);
}
static CORE_ADDR
struct frame_id id;
/* The FUNC is easy. */
- func = frame_func_unwind (next_frame);
+ func = frame_func_unwind (next_frame, NORMAL_FRAME);
/* Check if the stack is empty. */
msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL);
return;
id = frame_id_build (base, func);
-
- /* Check that we're not going round in circles with the same frame
- ID (but avoid applying the test to sentinel frames which do go
- round in circles). Can't use frame_id_eq() as that doesn't yet
- compare the frame's PC value. */
- if (frame_relative_level (next_frame) >= 0
- && get_frame_type (next_frame) != DUMMY_FRAME
- && frame_id_eq (get_frame_id (next_frame), id))
- return;
-
(*this_id) = id;
}
void **this_prologue_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *bufferp)
+ int *realnump, gdb_byte *bufferp)
{
struct frv_unwind_cache *info
= frv_frame_unwind_cache (next_frame, this_prologue_cache);
- trad_frame_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, bufferp);
+ trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, bufferp);
}
static const struct frame_unwind frv_frame_unwind = {
frame_pc_unwind (next_frame));
}
-/* Signal trampolines. */
-
-static struct frv_unwind_cache *
-frv_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
-{
- struct frv_unwind_cache *cache;
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- CORE_ADDR addr;
- char buf[4];
- int regno;
- CORE_ADDR sc_addr_cache_val = 0;
-
- if (*this_cache)
- return *this_cache;
-
- cache = FRAME_OBSTACK_ZALLOC (struct frv_unwind_cache);
- cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
-
- frame_unwind_register (next_frame, sp_regnum, buf);
- cache->base = extract_unsigned_integer (buf, sizeof buf);
-
- for (regno = 0; regno < frv_num_regs; regno++)
- {
- cache->saved_regs[regno].addr
- = tdep->sigcontext_reg_addr (next_frame, regno, &sc_addr_cache_val);
- }
-
-
- if (cache->saved_regs[sp_regnum].addr != -1
- && target_read_memory (cache->saved_regs[sp_regnum].addr,
- buf, sizeof buf) == 0)
- {
- cache->prev_sp = extract_unsigned_integer (buf, sizeof buf);
-
- /* Now that we've bothered to read it out of memory, save the
- prev frame's SP value in the cache. */
- trad_frame_set_value (cache->saved_regs, sp_regnum, cache->prev_sp);
- }
- else
- {
- warning ("Can't read SP value from sigtramp frame");
- }
-
- *this_cache = cache;
- return cache;
-}
-
-static void
-frv_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
- struct frame_id *this_id)
-{
- struct frv_unwind_cache *cache =
- frv_sigtramp_frame_cache (next_frame, this_cache);
-
- (*this_id) = frame_id_build (cache->base, frame_pc_unwind (next_frame));
-}
-
-static void
-frv_sigtramp_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
-{
- /* Make sure we've initialized the cache. */
- frv_sigtramp_frame_cache (next_frame, this_cache);
-
- frv_frame_prev_register (next_frame, this_cache, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
-}
-
-static const struct frame_unwind frv_sigtramp_frame_unwind =
-{
- SIGTRAMP_FRAME,
- frv_sigtramp_frame_this_id,
- frv_sigtramp_frame_prev_register
-};
-
-static const struct frame_unwind *
-frv_sigtramp_frame_sniffer (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- char *name;
-
- /* We shouldn't even bother to try if the OSABI didn't register
- a sigcontext_reg_addr handler. */
- if (!gdbarch_tdep (current_gdbarch)->sigcontext_reg_addr)
- return NULL;
-
- find_pc_partial_function (pc, &name, NULL, NULL);
- if (DEPRECATED_PC_IN_SIGTRAMP (pc, name))
- return &frv_sigtramp_frame_unwind;
-
- return NULL;
-}
-
static struct gdbarch *
frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
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_adjust_breakpoint_address
+ (gdbarch, frv_adjust_breakpoint_address);
- set_gdbarch_deprecated_frameless_function_invocation (gdbarch, frv_frameless_function_invocation);
-
- set_gdbarch_use_struct_convention (gdbarch, always_use_struct_convention);
+ set_gdbarch_deprecated_use_struct_convention (gdbarch, always_use_struct_convention);
set_gdbarch_extract_return_value (gdbarch, frv_extract_return_value);
- set_gdbarch_deprecated_store_struct_return (gdbarch, frv_store_struct_return);
set_gdbarch_store_return_value (gdbarch, frv_store_return_value);
- set_gdbarch_deprecated_extract_struct_value_address (gdbarch, frv_extract_struct_value_address);
/* Frame stuff. */
set_gdbarch_unwind_pc (gdbarch, frv_unwind_pc);
/* Settings that should be unnecessary. */
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
-
- set_gdbarch_remote_translate_xfer_address
- (gdbarch, generic_remote_translate_xfer_address);
-
/* Hardware watchpoint / breakpoint support. */
switch (info.bfd_arch_info->mach)
{
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
- /* Set the sigtramp frame sniffer. */
- frame_unwind_append_sniffer (gdbarch, frv_sigtramp_frame_sniffer);
-
/* Set the fallback (prologue based) frame sniffer. */
frame_unwind_append_sniffer (gdbarch, frv_frame_sniffer);
+ /* Enable TLS support. */
+ set_gdbarch_fetch_tls_load_module_address (gdbarch,
+ frv_fetch_objfile_link_map);
+
return gdbarch;
}