/* 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
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"
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];
if (target_has_registers)
{
ULONGEST regval;
- regcache_cooked_read_unsigned (current_regcache,
+ regcache_cooked_read_unsigned (get_current_regcache (),
MEP_MODULE_REGNUM, ®val);
return regval;
}
if (target_has_registers)
{
ULONGEST regval;
- regcache_cooked_read_unsigned (current_regcache,
+ regcache_cooked_read_unsigned (get_current_regcache (),
MEP_OPT_REGNUM, ®val);
return regval;
}
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;
static CORE_ADDR
-mep_read_pc (ptid_t ptid)
+mep_read_pc (struct regcache *regcache)
{
- ptid_t saved_ptid;
- CORE_ADDR pc;
-
- saved_ptid = inferior_ptid;
- inferior_ptid = ptid;
-
- pc = read_register (MEP_PC_REGNUM);
-
- inferior_ptid = saved_ptid;
+ ULONGEST pc;
+ regcache_cooked_read_unsigned (regcache, MEP_PC_REGNUM, &pc);
return pc;
}
static void
-mep_write_pc (CORE_ADDR pc, ptid_t ptid)
+mep_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
- ptid_t saved_ptid;
-
- saved_ptid = inferior_ptid;
- inferior_ptid = ptid;
-
- write_register (MEP_PC_REGNUM, pc);
-
- inferior_ptid = saved_ptid;
+ regcache_cooked_write_unsigned (regcache, MEP_PC_REGNUM, pc);
}
#define MOV_TARGET(i) (FIELD (i, 24, 4))
#define MOV_SOURCE(i) (FIELD (i, 20, 4))
+/* BRA disp12.align2 1011_dddd_dddd_ddd0 xxxx_xxxx_xxxx_xxxx */
+#define IS_BRA(i) (((i) & 0xf0010000) == 0xb0000000)
+#define BRA_DISP(i) (SFIELD (i, 17, 11) << 1)
+
/* This structure holds the results of a prologue analysis. */
struct mep_prologue
reg[rn] = pv_area_fetch (stack, addr, 4);
}
+ else if (IS_BRA (insn) && BRA_DISP (insn) > 0)
+ {
+ /* When a loop appears as the first statement of a function
+ body, gcc 4.x will use a BRA instruction to branch to the
+ loop condition checking code. This BRA instruction is
+ marked as part of the prologue. We therefore set next_pc
+ to this branch target and also stop the prologue scan.
+ The instructions at and beyond the branch target should
+ no longer be associated with the prologue.
+
+ Note that we only consider forward branches here. We
+ presume that a forward branch is being used to skip over
+ a loop body.
+
+ A backwards branch is covered by the default case below.
+ If we were to encounter a backwards branch, that would
+ most likely mean that we've scanned through a loop body.
+ We definitely want to stop the prologue scan when this
+ happens and that is precisely what is done by the default
+ case below. */
+ next_pc = pc + BRA_DISP (insn);
+ after_last_frame_setup_insn = next_pc;
+ break;
+ }
else
/* We've hit some instruction we don't know how to simulate.
Strictly speaking, we should set every value we're
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;
/* 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);