/* Target-dependent code for the Fujitsu FR-V, for GDB, the GNU Debugger.
- Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008
+ Free Software Foundation, Inc.
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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "gdb_string.h"
#include "elf/frv.h"
#include "osabi.h"
#include "infcall.h"
+#include "solib.h"
#include "frv-tdep.h"
extern void _initialize_frv_tdep (void);
char **register_names;
};
-#define CURRENT_VARIANT (gdbarch_tdep (current_gdbarch))
-
/* Return the FR-V ABI associated with GDBARCH. */
enum frv_abi
frv_abi (struct gdbarch *gdbarch)
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;
}
}
static const char *
-frv_register_name (int reg)
+frv_register_name (struct gdbarch *gdbarch, int reg)
{
if (reg < 0)
return "?toosmall?";
if (reg >= frv_num_regs + frv_num_pseudo_regs)
return "?toolarge?";
- return CURRENT_VARIANT->register_names[reg];
+ return gdbarch_tdep (gdbarch)->register_names[reg];
}
}
static int
-frv_register_sim_regno (int reg)
+frv_register_sim_regno (struct gdbarch *gdbarch, int reg)
{
static const int spr_map[] =
{
H_SPR_FNER1, /* fner1_regnum */
};
- gdb_assert (reg >= 0 && reg < gdbarch_num_regs (current_gdbarch));
+ gdb_assert (reg >= 0 && reg < gdbarch_num_regs (gdbarch));
if (first_gpr_regnum <= reg && reg <= last_gpr_regnum)
return reg - first_gpr_regnum + SIM_FRV_GR0_REGNUM;
}
static const unsigned char *
-frv_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenp)
+frv_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenp)
{
static unsigned char breakpoint[] = {0xc0, 0x70, 0x00, 0x01};
*lenp = sizeof (breakpoint);
char instr[frv_instr_size];
int status;
- status = read_memory_nobpt (addr, instr, sizeof instr);
+ status = target_read_memory (addr, instr, sizeof instr);
if (status != 0)
break;
arguments in any frame but the top, you'll need to do this serious
prologue analysis. */
static CORE_ADDR
-frv_analyze_prologue (CORE_ADDR pc, struct frame_info *next_frame,
+frv_analyze_prologue (CORE_ADDR pc, struct frame_info *this_frame,
struct frv_unwind_cache *info)
{
/* When writing out instruction bitpatterns, we use the following
/* If we have a frame, we don't want to scan past the frame's pc. This
will catch those cases where the pc is in the prologue. */
- if (next_frame)
+ if (this_frame)
{
- CORE_ADDR frame_pc = frame_pc_unwind (next_frame);
+ CORE_ADDR frame_pc = get_frame_pc (this_frame);
if (frame_pc < lim_pc)
lim_pc = frame_pc;
}
pc = next_pc;
}
- if (next_frame && info)
+ if (this_frame && info)
{
int i;
ULONGEST this_base;
because instructions may save relative to the SP, but we need
their addresses relative to the FP. */
if (fp_set)
- frame_unwind_unsigned_register (next_frame, fp_regnum, &this_base);
+ this_base = get_frame_register_unsigned (this_frame, fp_regnum);
else
- frame_unwind_unsigned_register (next_frame, sp_regnum, &this_base);
+ this_base = get_frame_register_unsigned (this_frame, sp_regnum);
for (i = 0; i < 64; i++)
if (gr_saved[i])
static CORE_ADDR
-frv_skip_prologue (CORE_ADDR pc)
+frv_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end, new_pc;
static struct frv_unwind_cache *
-frv_frame_unwind_cache (struct frame_info *next_frame,
+frv_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache)
{
- struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
CORE_ADDR pc;
ULONGEST this_base;
struct frv_unwind_cache *info;
info = FRAME_OBSTACK_ZALLOC (struct frv_unwind_cache);
(*this_prologue_cache) = info;
- info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+ info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
/* Prologue analysis does the rest... */
- frv_analyze_prologue (frame_func_unwind (next_frame, NORMAL_FRAME),
- next_frame, info);
+ frv_analyze_prologue (get_frame_func (this_frame), this_frame, info);
return info;
}
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 CORE_ADDR
frv_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
{
_("Don't know how to return a %d-byte value."), len);
}
+enum return_value_convention
+frv_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *valtype, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+ int struct_return = TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+ || TYPE_CODE (valtype) == TYPE_CODE_UNION
+ || TYPE_CODE (valtype) == TYPE_CODE_ARRAY;
+
+ if (writebuf != NULL)
+ {
+ gdb_assert (!struct_return);
+ frv_store_return_value (valtype, regcache, writebuf);
+ }
+
+ if (readbuf != NULL)
+ {
+ gdb_assert (!struct_return);
+ frv_extract_return_value (valtype, regcache, readbuf);
+ }
+
+ if (struct_return)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
/* Hardware watchpoint / breakpoint support for the FR500
and FR400. */
int
-frv_check_watch_resources (int type, int cnt, int ot)
+frv_check_watch_resources (struct gdbarch *gdbarch, int type, int cnt, int ot)
{
- struct gdbarch_tdep *var = CURRENT_VARIANT;
+ struct gdbarch_tdep *var = gdbarch_tdep (gdbarch);
/* Watchpoints not supported on simulator. */
if (strcmp (target_shortname, "sim") == 0)
frame. This will be used to create a new GDB frame struct. */
static void
-frv_frame_this_id (struct frame_info *next_frame,
+frv_frame_this_id (struct frame_info *this_frame,
void **this_prologue_cache, struct frame_id *this_id)
{
struct frv_unwind_cache *info
- = frv_frame_unwind_cache (next_frame, this_prologue_cache);
+ = frv_frame_unwind_cache (this_frame, this_prologue_cache);
CORE_ADDR base;
CORE_ADDR func;
struct minimal_symbol *msym_stack;
struct frame_id id;
/* The FUNC is easy. */
- func = frame_func_unwind (next_frame, NORMAL_FRAME);
+ func = get_frame_func (this_frame);
/* Check if the stack is empty. */
msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL);
(*this_id) = id;
}
-static void
-frv_frame_prev_register (struct frame_info *next_frame,
- void **this_prologue_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, gdb_byte *bufferp)
+static struct value *
+frv_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
{
struct frv_unwind_cache *info
- = frv_frame_unwind_cache (next_frame, this_prologue_cache);
- trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, bufferp);
+ = frv_frame_unwind_cache (this_frame, this_prologue_cache);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
static const struct frame_unwind frv_frame_unwind = {
NORMAL_FRAME,
frv_frame_this_id,
- frv_frame_prev_register
+ frv_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-static const struct frame_unwind *
-frv_frame_sniffer (struct frame_info *next_frame)
-{
- return &frv_frame_unwind;
-}
-
static CORE_ADDR
-frv_frame_base_address (struct frame_info *next_frame, void **this_cache)
+frv_frame_base_address (struct frame_info *this_frame, void **this_cache)
{
struct frv_unwind_cache *info
- = frv_frame_unwind_cache (next_frame, this_cache);
+ = frv_frame_unwind_cache (this_frame, this_cache);
return info->base;
}
}
-/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
- dummy frame. The frame ID's base needs to match the TOS value
- saved by save_dummy_frame_tos(), and the PC match the dummy frame's
- breakpoint. */
+/* Assuming THIS_FRAME is a dummy, return the frame ID of that dummy
+ frame. The frame ID's base needs to match the TOS value saved by
+ save_dummy_frame_tos(), and the PC match the dummy frame's breakpoint. */
static struct frame_id
-frv_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+frv_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
- return frame_id_build (frv_unwind_sp (gdbarch, next_frame),
- frame_pc_unwind (next_frame));
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, sp_regnum);
+ return frame_id_build (sp, get_frame_pc (this_frame));
}
static struct gdbarch *
set_gdbarch_adjust_breakpoint_address
(gdbarch, frv_adjust_breakpoint_address);
- set_gdbarch_deprecated_use_struct_convention (gdbarch, always_use_struct_convention);
- set_gdbarch_extract_return_value (gdbarch, frv_extract_return_value);
-
- set_gdbarch_store_return_value (gdbarch, frv_store_return_value);
- set_gdbarch_deprecated_extract_struct_value_address (gdbarch, frv_extract_struct_value_address);
+ set_gdbarch_return_value (gdbarch, frv_return_value);
/* Frame stuff. */
set_gdbarch_unwind_pc (gdbarch, frv_unwind_pc);
/* Settings for calling functions in the inferior. */
set_gdbarch_push_dummy_call (gdbarch, frv_push_dummy_call);
- set_gdbarch_unwind_dummy_id (gdbarch, frv_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, frv_dummy_id);
/* Settings that should be unnecessary. */
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
-
/* Hardware watchpoint / breakpoint support. */
switch (info.bfd_arch_info->mach)
{
set_gdbarch_convert_from_func_ptr_addr (gdbarch,
frv_convert_from_func_ptr_addr);
+ set_solib_ops (gdbarch, &frv_so_ops);
+
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
/* Set the fallback (prologue based) frame sniffer. */
- frame_unwind_append_sniffer (gdbarch, frv_frame_sniffer);
+ frame_unwind_append_unwinder (gdbarch, &frv_frame_unwind);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,