/* Target-dependent code for the Toshiba MeP for GDB, the GNU debugger.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "frame.h"
mask contains any of the me_module's coprocessor ISAs,
specifically excluding the generic coprocessor register sets. */
- CGEN_CPU_DESC desc = gdbarch_tdep (current_gdbarch)->cpu_desc;
+ CGEN_CPU_DESC desc = gdbarch_tdep (target_gdbarch)->cpu_desc;
const CGEN_HW_ENTRY *hw;
if (me_module == CONFIG_NONE)
static int
-mep_debug_reg_to_regnum (int debug_reg)
+mep_debug_reg_to_regnum (struct gdbarch *gdbarch, int debug_reg)
{
/* The debug info uses the raw register numbers. */
return mep_raw_to_pseudo[debug_reg];
return regval;
}
else
- return gdbarch_tdep (current_gdbarch)->me_module;
+ return gdbarch_tdep (target_gdbarch)->me_module;
}
static const char *
-mep_register_name (int regnr)
+mep_register_name (struct gdbarch *gdbarch, int regnr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* General-purpose registers. */
static const char *gpr_names[] = {
{
/* Filter reserved or unused register numbers. */
{
- const char *name = mep_register_name (regnum);
+ const char *name = mep_register_name (gdbarch, regnum);
if (! name || name[0] == '\0')
return 0;
if (size == 32)
{
if (mep_pseudo_cr_is_float (reg_nr))
- return builtin_type_float;
+ return builtin_type (gdbarch)->builtin_float;
else
return builtin_type_uint32;
}
else if (size == 64)
{
if (mep_pseudo_cr_is_float (reg_nr))
- return builtin_type_double;
+ return builtin_type (gdbarch)->builtin_double;
else
return builtin_type_uint64;
}
/* The mep disassembler needs to know about the section in order to
work correctly. */
-int
+static int
mep_gdb_print_insn (bfd_vma pc, disassemble_info * info)
{
struct obj_section * s = find_pc_section (pc);
/* This structure holds the results of a prologue analysis. */
struct mep_prologue
{
+ /* The architecture for which we generated this prologue info. */
+ struct gdbarch *gdbarch;
+
/* The offset from the frame base to the stack pointer --- always
zero or negative.
- ADDR is a stack slot's address (e.g., relative to the original
value of the SP). */
static int
-is_arg_spill (pv_t value, pv_t addr, struct pv_area *stack)
+is_arg_spill (struct gdbarch *gdbarch, pv_t value, pv_t addr,
+ struct pv_area *stack)
{
return (is_arg_reg (value)
&& pv_is_register (addr, MEP_SP_REGNUM)
- && ! pv_area_find_reg (stack, current_gdbarch, value.reg, 0));
+ && ! pv_area_find_reg (stack, gdbarch, value.reg, 0));
}
if (value.kind == pvk_register
&& value.k == 0
&& pv_is_register (addr, MEP_SP_REGNUM)
- && size == register_size (current_gdbarch, value.reg))
+ && size == register_size (result->gdbarch, value.reg))
result->reg_offset[value.reg] = addr.k;
}
/* Analyze a prologue starting at START_PC, going no further than
LIMIT_PC. Fill in RESULT as appropriate. */
static void
-mep_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+mep_analyze_prologue (struct gdbarch *gdbarch,
+ CORE_ADDR start_pc, CORE_ADDR limit_pc,
struct mep_prologue *result)
{
CORE_ADDR pc;
CORE_ADDR after_last_frame_setup_insn = start_pc;
memset (result, 0, sizeof (*result));
+ result->gdbarch = gdbarch;
for (rn = 0; rn < MEP_NUM_REGS; rn++)
{
if (pv_area_store_would_trash (stack, reg[rm]))
break;
- if (is_arg_spill (reg[rn], reg[rm], stack))
+ if (is_arg_spill (gdbarch, reg[rn], reg[rm], stack))
after_last_frame_setup_insn = next_pc;
pv_area_store (stack, reg[rm], 4, reg[rn]);
if (pv_area_store_would_trash (stack, addr))
break;
- if (is_arg_spill (reg[rn], addr, stack))
+ if (is_arg_spill (gdbarch, reg[rn], addr, stack))
after_last_frame_setup_insn = next_pc;
pv_area_store (stack, addr, 4, reg[rn]);
if (pv_area_store_would_trash (stack, addr))
break;
- if (is_arg_spill (reg[rn], addr, stack))
+ if (is_arg_spill (gdbarch, reg[rn], addr, stack))
after_last_frame_setup_insn = next_pc;
pv_area_store (stack, addr, size, reg[rn]);
static CORE_ADDR
-mep_skip_prologue (CORE_ADDR pc)
+mep_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
char *name;
CORE_ADDR func_addr, func_end;
if (! find_pc_partial_function (pc, &name, &func_addr, &func_end))
return pc;
- mep_analyze_prologue (pc, func_end, &p);
+ mep_analyze_prologue (gdbarch, pc, func_end, &p);
return p.prologue_end;
}
/* Breakpoints. */
static const unsigned char *
-mep_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+mep_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR * pcptr, int *lenptr)
{
static unsigned char breakpoint[] = { 0x70, 0x32 };
*lenptr = sizeof (breakpoint);
static struct mep_prologue *
-mep_analyze_frame_prologue (struct frame_info *next_frame,
+mep_analyze_frame_prologue (struct frame_info *this_frame,
void **this_prologue_cache)
{
if (! *this_prologue_cache)
*this_prologue_cache
= FRAME_OBSTACK_ZALLOC (struct mep_prologue);
- func_start = frame_func_unwind (next_frame, NORMAL_FRAME);
- stop_addr = frame_pc_unwind (next_frame);
+ func_start = get_frame_func (this_frame);
+ stop_addr = get_frame_pc (this_frame);
/* If we couldn't find any function containing the PC, then
just initialize the prologue cache, but don't do anything. */
if (! func_start)
stop_addr = func_start;
- mep_analyze_prologue (func_start, stop_addr, *this_prologue_cache);
+ mep_analyze_prologue (get_frame_arch (this_frame),
+ func_start, stop_addr, *this_prologue_cache);
}
return *this_prologue_cache;
/* Given the next frame and a prologue cache, return this frame's
base. */
static CORE_ADDR
-mep_frame_base (struct frame_info *next_frame,
+mep_frame_base (struct frame_info *this_frame,
void **this_prologue_cache)
{
struct mep_prologue *p
- = mep_analyze_frame_prologue (next_frame, this_prologue_cache);
+ = mep_analyze_frame_prologue (this_frame, this_prologue_cache);
/* In functions that use alloca, the distance between the stack
pointer and the frame base varies dynamically, so we can't use
if (p->has_frame_ptr)
{
CORE_ADDR fp
- = frame_unwind_register_unsigned (next_frame, MEP_FP_REGNUM);
+ = get_frame_register_unsigned (this_frame, MEP_FP_REGNUM);
return fp - p->frame_ptr_offset;
}
else
{
CORE_ADDR sp
- = frame_unwind_register_unsigned (next_frame, MEP_SP_REGNUM);
+ = get_frame_register_unsigned (this_frame, MEP_SP_REGNUM);
return sp - p->frame_size;
}
}
static void
-mep_frame_this_id (struct frame_info *next_frame,
+mep_frame_this_id (struct frame_info *this_frame,
void **this_prologue_cache,
struct frame_id *this_id)
{
- *this_id = frame_id_build (mep_frame_base (next_frame, this_prologue_cache),
- frame_func_unwind (next_frame, NORMAL_FRAME));
+ *this_id = frame_id_build (mep_frame_base (this_frame, this_prologue_cache),
+ get_frame_func (this_frame));
}
-static void
-mep_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 *
+mep_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
{
struct mep_prologue *p
- = mep_analyze_frame_prologue (next_frame, this_prologue_cache);
+ = mep_analyze_frame_prologue (this_frame, this_prologue_cache);
/* There are a number of complications in unwinding registers on the
MeP, having to do with core functions calling VLIW functions and
do this. */
if (regnum == MEP_PC_REGNUM)
{
- mep_frame_prev_register (next_frame, this_prologue_cache, MEP_LP_REGNUM,
- optimizedp, lvalp, addrp, realnump, bufferp);
- store_unsigned_integer (bufferp, MEP_LP_SIZE,
- (extract_unsigned_integer (bufferp, MEP_LP_SIZE)
- & ~1));
- *lvalp = not_lval;
+ struct value *value;
+ CORE_ADDR lp;
+ value = mep_frame_prev_register (this_frame, this_prologue_cache,
+ MEP_LP_REGNUM);
+ lp = value_as_long (value);
+ release_value (value);
+ value_free (value);
+
+ return frame_unwind_got_constant (this_frame, regnum, lp & ~1);
}
else
{
- CORE_ADDR frame_base = mep_frame_base (next_frame, this_prologue_cache);
- int reg_size = register_size (get_frame_arch (next_frame), regnum);
+ CORE_ADDR frame_base = mep_frame_base (this_frame, this_prologue_cache);
+ struct value *value;
/* Our caller's SP is our frame base. */
if (regnum == MEP_SP_REGNUM)
- {
- *optimizedp = 0;
- *lvalp = not_lval;
- *addrp = 0;
- *realnump = -1;
- if (bufferp)
- store_unsigned_integer (bufferp, reg_size, frame_base);
- }
+ return frame_unwind_got_constant (this_frame, regnum, frame_base);
/* If prologue analysis says we saved this register somewhere,
return a description of the stack slot holding it. */
- else if (p->reg_offset[regnum] != 1)
- {
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = frame_base + p->reg_offset[regnum];
- *realnump = -1;
- if (bufferp)
- get_frame_memory (next_frame, *addrp, bufferp, reg_size);
- }
+ if (p->reg_offset[regnum] != 1)
+ value = frame_unwind_got_memory (this_frame, regnum,
+ frame_base + p->reg_offset[regnum]);
/* Otherwise, presume we haven't changed the value of this
register, and get it from the next frame. */
else
- frame_register_unwind (next_frame, regnum,
- optimizedp, lvalp, addrp, realnump, bufferp);
+ value = frame_unwind_got_register (this_frame, regnum, regnum);
/* If we need to toggle the operating mode, do so. */
if (regnum == MEP_PSW_REGNUM)
{
- int lp_optimized;
- enum lval_type lp_lval;
- CORE_ADDR lp_addr;
- int lp_realnum;
- char lp_buffer[MEP_LP_SIZE];
+ CORE_ADDR psw, lp;
+
+ psw = value_as_long (value);
+ release_value (value);
+ value_free (value);
/* Get the LP's value, too. */
- frame_register_unwind (next_frame, MEP_LP_REGNUM,
- &lp_optimized, &lp_lval, &lp_addr,
- &lp_realnum, lp_buffer);
+ value = get_frame_register_value (this_frame, MEP_LP_REGNUM);
+ lp = value_as_long (value);
+ release_value (value);
+ value_free (value);
/* If LP.LTOM is set, then toggle PSW.OM. */
- if (extract_unsigned_integer (lp_buffer, MEP_LP_SIZE) & 0x1)
- store_unsigned_integer
- (bufferp, MEP_PSW_SIZE,
- (extract_unsigned_integer (bufferp, MEP_PSW_SIZE) ^ 0x1000));
- *lvalp = not_lval;
+ if (lp & 0x1)
+ psw ^= 0x1000;
+
+ return frame_unwind_got_constant (this_frame, regnum, psw);
}
+
+ return value;
}
}
static const struct frame_unwind mep_frame_unwind = {
NORMAL_FRAME,
mep_frame_this_id,
- mep_frame_prev_register
+ mep_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-static const struct frame_unwind *
-mep_frame_sniffer (struct frame_info *next_frame)
-{
- return &mep_frame_unwind;
-}
-
-
/* Our general unwinding function can handle unwinding the PC. */
static CORE_ADDR
mep_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
"Try using the 'return' command with no argument.");
}
-enum return_value_convention
-mep_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache, gdb_byte *readbuf,
- const gdb_byte *writebuf)
+static enum return_value_convention
+mep_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ struct type *type, struct regcache *regcache,
+ gdb_byte *readbuf, const gdb_byte *writebuf)
{
if (mep_use_struct_convention (type))
{
static struct frame_id
-mep_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+mep_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
- return frame_id_build (mep_unwind_sp (gdbarch, next_frame),
- frame_pc_unwind (next_frame));
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, MEP_SP_REGNUM);
+ return frame_id_build (sp, get_frame_pc (this_frame));
}
set_gdbarch_skip_prologue (gdbarch, mep_skip_prologue);
/* Frames and frame unwinding. */
- frame_unwind_append_sniffer (gdbarch, mep_frame_sniffer);
+ frame_unwind_append_unwinder (gdbarch, &mep_frame_unwind);
set_gdbarch_unwind_pc (gdbarch, mep_unwind_pc);
set_gdbarch_unwind_sp (gdbarch, mep_unwind_sp);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
/* Inferior function calls. */
set_gdbarch_frame_align (gdbarch, mep_frame_align);
set_gdbarch_push_dummy_call (gdbarch, mep_push_dummy_call);
- set_gdbarch_unwind_dummy_id (gdbarch, mep_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, mep_dummy_id);
return gdbarch;
}
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_mep_tdep;
void
_initialize_mep_tdep (void)