/* Target-dependent code for Atmel AVR, for GDB.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ 2006, 2007, 2008, 2009 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Contributed by Theodore A. Roth, troth@openavr.org */
#include "trad-frame.h"
#include "gdbcmd.h"
#include "gdbcore.h"
+#include "gdbtypes.h"
#include "inferior.h"
#include "symfile.h"
#include "arch-utils.h"
/* Lookup the name of a register given it's number. */
static const char *
-avr_register_name (int regnum)
+avr_register_name (struct gdbarch *gdbarch, int regnum)
{
static char *register_names[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
if (reg_nr == AVR_PC_REGNUM)
return builtin_type_uint32;
if (reg_nr == AVR_SP_REGNUM)
- return builtin_type_void_data_ptr;
+ return builtin_type (gdbarch)->builtin_data_ptr;
else
return builtin_type_uint8;
}
/* Convert from address to pointer and vice-versa. */
static void
-avr_address_to_pointer (struct type *type, void *buf, CORE_ADDR addr)
+avr_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr)
{
/* Is it a code address? */
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
}
static CORE_ADDR
-avr_pointer_to_address (struct type *type, const void *buf)
+avr_pointer_to_address (struct type *type, const gdb_byte *buf)
{
CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
}
static CORE_ADDR
-avr_read_pc (ptid_t ptid)
+avr_read_pc (struct regcache *regcache)
{
- ptid_t save_ptid;
ULONGEST pc;
- CORE_ADDR retval;
-
- save_ptid = inferior_ptid;
- inferior_ptid = ptid;
- regcache_cooked_read_unsigned (current_regcache, AVR_PC_REGNUM, &pc);
- inferior_ptid = save_ptid;
- retval = avr_make_iaddr (pc);
- return retval;
+ regcache_cooked_read_unsigned (regcache, AVR_PC_REGNUM, &pc);
+ return avr_make_iaddr (pc);
}
static void
-avr_write_pc (CORE_ADDR val, ptid_t ptid)
+avr_write_pc (struct regcache *regcache, CORE_ADDR val)
{
- ptid_t save_ptid;
-
- save_ptid = inferior_ptid;
- inferior_ptid = ptid;
- write_register (AVR_PC_REGNUM, avr_convert_iaddr_to_raw (val));
- inferior_ptid = save_ptid;
-}
-
-static CORE_ADDR
-avr_read_sp (void)
-{
- ULONGEST sp;
-
- regcache_cooked_read_unsigned (current_regcache, AVR_SP_REGNUM, &sp);
- return (avr_make_saddr (sp));
+ regcache_cooked_write_unsigned (regcache, AVR_PC_REGNUM,
+ avr_convert_iaddr_to_raw (val));
}
static int
if (num_pushes > AVR_MAX_PUSHES)
{
- fprintf_unfiltered (gdb_stderr, "Num pushes too large: %d\n",
+ fprintf_unfiltered (gdb_stderr, _("Num pushes too large: %d\n"),
num_pushes);
num_pushes = 0;
}
if (vpc >= AVR_MAX_PROLOGUE_SIZE)
fprintf_unfiltered (gdb_stderr,
- "Hit end of prologue while scanning pushes\n");
+ _("Hit end of prologue while scanning pushes\n"));
/* Second stage of the prologue scanning.
Scan:
}
static CORE_ADDR
-avr_skip_prologue (CORE_ADDR pc)
+avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end;
CORE_ADDR prologue_end = pc;
only target, this shouldn't be a problem (I hope). TRoth/2003-05-14 */
static const unsigned char *
-avr_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+avr_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR * pcptr, int *lenptr)
{
static unsigned char avr_break_insn [] = { 0x98, 0x95 };
*lenptr = sizeof (avr_break_insn);
static void
avr_extract_return_value (struct type *type, struct regcache *regcache,
- void *valbuf)
+ gdb_byte *valbuf)
{
ULONGEST r24, r25;
ULONGEST c;
}
}
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+ should be returned. If it is supposed to be returned in registers,
+ and READBUF is non-zero, read the appropriate value from REGCACHE,
+ and copy it into READBUF. If WRITEBUF is non-zero, write the value
+ from WRITEBUF into REGCACHE. */
+
+static enum return_value_convention
+avr_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)
+ && !(TYPE_LENGTH (valtype) == 1
+ || TYPE_LENGTH (valtype) == 2
+ || TYPE_LENGTH (valtype) == 4
+ || TYPE_LENGTH (valtype) == 8));
+
+ if (writebuf != NULL)
+ {
+ gdb_assert (!struct_return);
+ error (_("Cannot store return value."));
+ }
+
+ if (readbuf != NULL)
+ {
+ gdb_assert (!struct_return);
+ avr_extract_return_value (valtype, regcache, readbuf);
+ }
+
+ if (struct_return)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
+
/* Put here the code to store, into fi->saved_regs, the addresses of
the saved registers of frame described by FRAME_INFO. This
includes special registers such as pc and fp saved in special ways
in the stack frame. sp is even more special: the address we return
for it IS the sp for the next frame. */
-struct avr_unwind_cache *
-avr_frame_unwind_cache (struct frame_info *next_frame,
+static struct avr_unwind_cache *
+avr_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache)
{
CORE_ADDR pc;
info = FRAME_OBSTACK_ZALLOC (struct avr_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);
info->size = 0;
info->prologue_type = AVR_PROLOGUE_NONE;
- pc = frame_func_unwind (next_frame);
+ pc = get_frame_func (this_frame);
- if ((pc > 0) && (pc < frame_pc_unwind (next_frame)))
+ if ((pc > 0) && (pc < get_frame_pc (this_frame)))
avr_scan_prologue (pc, info);
if ((info->prologue_type != AVR_PROLOGUE_NONE)
/* The SP was moved to the FP. This indicates that a new frame
was created. Get THIS frame's FP value by unwinding it from
the next frame. */
- frame_unwind_unsigned_register (next_frame, AVR_FP_REGNUM, &this_base);
- frame_unwind_unsigned_register (next_frame, AVR_FP_REGNUM+1, &high_base);
+ this_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM);
+ high_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM+1);
this_base += (high_base << 8);
/* The FP points at the last saved register. Adjust the FP back
{
/* Assume that the FP is this frame's SP but with that pushed
stack space added back. */
- frame_unwind_unsigned_register (next_frame, AVR_SP_REGNUM, &this_base);
+ this_base = get_frame_register_unsigned (this_frame, AVR_SP_REGNUM);
prev_sp = this_base + info->size;
}
/* Adjust all the saved registers so that they contain addresses and not
offsets. */
- for (i = 0; i < NUM_REGS - 1; i++)
+ for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++)
if (info->saved_regs[i].addr)
{
info->saved_regs[i].addr = (info->prev_sp - info->saved_regs[i].addr);
{
ULONGEST pc;
- frame_unwind_unsigned_register (next_frame, AVR_PC_REGNUM, &pc);
+ pc = frame_unwind_register_unsigned (next_frame, AVR_PC_REGNUM);
return avr_make_iaddr (pc);
}
+static CORE_ADDR
+avr_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ ULONGEST sp;
+
+ sp = frame_unwind_register_unsigned (next_frame, AVR_SP_REGNUM);
+
+ return avr_make_saddr (sp);
+}
+
/* Given a GDB frame, determine the address of the calling function's
frame. This will be used to create a new GDB frame struct. */
static void
-avr_frame_this_id (struct frame_info *next_frame,
+avr_frame_this_id (struct frame_info *this_frame,
void **this_prologue_cache,
struct frame_id *this_id)
{
struct avr_unwind_cache *info
- = avr_frame_unwind_cache (next_frame, this_prologue_cache);
+ = avr_frame_unwind_cache (this_frame, this_prologue_cache);
CORE_ADDR base;
CORE_ADDR func;
struct frame_id id;
/* The FUNC is easy. */
- func = frame_func_unwind (next_frame);
+ func = get_frame_func (this_frame);
/* Hopefully the prologue analysis either correctly determined the
frame's base (which is the SP from the previous frame), or set
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;
}
-static void
-avr_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, void *bufferp)
+static struct value *
+avr_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
{
struct avr_unwind_cache *info
- = avr_frame_unwind_cache (next_frame, this_prologue_cache);
+ = avr_frame_unwind_cache (this_frame, this_prologue_cache);
if (regnum == AVR_PC_REGNUM)
{
if (trad_frame_addr_p (info->saved_regs, regnum))
{
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = info->saved_regs[regnum].addr;
- *realnump = -1;
- if (bufferp != NULL)
- {
- /* Reading the return PC from the PC register is slightly
- abnormal. register_size(AVR_PC_REGNUM) says it is 4 bytes,
- but in reality, only two bytes (3 in upcoming mega256) are
- stored on the stack.
-
- Also, note that the value on the stack is an addr to a word
- not a byte, so we will need to multiply it by two at some
- point.
-
- And to confuse matters even more, the return address stored
- on the stack is in big endian byte order, even though most
- everything else about the avr is little endian. Ick! */
-
- /* FIXME: number of bytes read here will need updated for the
- mega256 when it is available. */
-
- ULONGEST pc;
- unsigned char tmp;
- unsigned char buf[2];
-
- read_memory (info->saved_regs[regnum].addr, buf, 2);
-
- /* Convert the PC read from memory as a big-endian to
- little-endian order. */
- tmp = buf[0];
- buf[0] = buf[1];
- buf[1] = tmp;
-
- pc = (extract_unsigned_integer (buf, 2) * 2);
- store_unsigned_integer (bufferp,
- register_size (current_gdbarch, regnum),
- pc);
- }
+ /* Reading the return PC from the PC register is slightly
+ abnormal. register_size(AVR_PC_REGNUM) says it is 4 bytes,
+ but in reality, only two bytes (3 in upcoming mega256) are
+ stored on the stack.
+
+ Also, note that the value on the stack is an addr to a word
+ not a byte, so we will need to multiply it by two at some
+ point.
+
+ And to confuse matters even more, the return address stored
+ on the stack is in big endian byte order, even though most
+ everything else about the avr is little endian. Ick! */
+
+ /* FIXME: number of bytes read here will need updated for the
+ mega256 when it is available. */
+
+ ULONGEST pc;
+ unsigned char tmp;
+ unsigned char buf[2];
+
+ read_memory (info->saved_regs[regnum].addr, buf, 2);
+
+ /* Convert the PC read from memory as a big-endian to
+ little-endian order. */
+ tmp = buf[0];
+ buf[0] = buf[1];
+ buf[1] = tmp;
+
+ pc = (extract_unsigned_integer (buf, 2) * 2);
+
+ return frame_unwind_got_constant (this_frame, regnum, pc);
}
+
+ return frame_unwind_got_optimized (this_frame, regnum);
}
- else
- trad_frame_prev_register (next_frame, info->saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, bufferp);
+
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
static const struct frame_unwind avr_frame_unwind = {
NORMAL_FRAME,
avr_frame_this_id,
- avr_frame_prev_register
+ avr_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-const struct frame_unwind *
-avr_frame_sniffer (struct frame_info *next_frame)
-{
- return &avr_frame_unwind;
-}
-
static CORE_ADDR
-avr_frame_base_address (struct frame_info *next_frame, void **this_cache)
+avr_frame_base_address (struct frame_info *this_frame, void **this_cache)
{
struct avr_unwind_cache *info
- = avr_frame_unwind_cache (next_frame, this_cache);
+ = avr_frame_unwind_cache (this_frame, this_cache);
return info->base;
}
avr_frame_base_address
};
-/* 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
-avr_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+avr_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
ULONGEST base;
- frame_unwind_unsigned_register (next_frame, AVR_SP_REGNUM, &base);
- return frame_id_build (avr_make_saddr (base), frame_pc_unwind (next_frame));
+ base = get_frame_register_unsigned (this_frame, AVR_SP_REGNUM);
+ return frame_id_build (avr_make_saddr (base), get_frame_pc (this_frame));
}
/* When arguments must be pushed onto the stack, they go on in reverse
void *data;
};
-static struct stack_item *push_stack_item (struct stack_item *prev,
- void *contents, int len);
static struct stack_item *
-push_stack_item (struct stack_item *prev, void *contents, int len)
+push_stack_item (struct stack_item *prev, const bfd_byte *contents, int len)
{
struct stack_item *si;
si = xmalloc (sizeof (struct stack_item));
registers R0 to R2. */
static CORE_ADDR
-avr_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+avr_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)
if (struct_return)
{
fprintf_unfiltered (gdb_stderr, "struct_return: 0x%lx\n", struct_addr);
- write_register (argreg--, struct_addr & 0xff);
- write_register (argreg--, (struct_addr >>8) & 0xff);
+ regcache_cooked_write_unsigned (regcache, argreg--, struct_addr & 0xff);
+ regcache_cooked_write_unsigned (regcache, argreg--, (struct_addr >>8) & 0xff);
}
#endif
int last_regnum;
int j;
struct value *arg = args[i];
- struct type *type = check_typedef (VALUE_TYPE (arg));
- char *contents = VALUE_CONTENTS (arg);
+ struct type *type = check_typedef (value_type (arg));
+ const bfd_byte *contents = value_contents (arg);
int len = TYPE_LENGTH (type);
/* Calculate the potential last register needed. */
set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
- set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
- set_gdbarch_double_format (gdbarch, &floatformat_ieee_single_little);
- set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_single_little);
+ set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
+ set_gdbarch_double_format (gdbarch, floatformats_ieee_single);
+ set_gdbarch_long_double_format (gdbarch, floatformats_ieee_single);
set_gdbarch_read_pc (gdbarch, avr_read_pc);
set_gdbarch_write_pc (gdbarch, avr_write_pc);
- set_gdbarch_read_sp (gdbarch, avr_read_sp);
set_gdbarch_num_regs (gdbarch, AVR_NUM_REGS);
set_gdbarch_register_name (gdbarch, avr_register_name);
set_gdbarch_register_type (gdbarch, avr_register_type);
- set_gdbarch_extract_return_value (gdbarch, avr_extract_return_value);
+ set_gdbarch_return_value (gdbarch, avr_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_avr);
set_gdbarch_push_dummy_call (gdbarch, avr_push_dummy_call);
set_gdbarch_address_to_pointer (gdbarch, avr_address_to_pointer);
set_gdbarch_pointer_to_address (gdbarch, avr_pointer_to_address);
- set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
-
set_gdbarch_skip_prologue (gdbarch, avr_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc);
- set_gdbarch_deprecated_frameless_function_invocation (gdbarch, legacy_frameless_look_for_prologue);
-
- frame_unwind_append_sniffer (gdbarch, avr_frame_sniffer);
+ frame_unwind_append_unwinder (gdbarch, &avr_frame_unwind);
frame_base_set_default (gdbarch, &avr_frame_base);
- set_gdbarch_unwind_dummy_id (gdbarch, avr_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, avr_dummy_id);
set_gdbarch_unwind_pc (gdbarch, avr_unwind_pc);
+ set_gdbarch_unwind_sp (gdbarch, avr_unwind_sp);
return gdbarch;
}
avr_io_reg_read_command (char *args, int from_tty)
{
LONGEST bufsiz = 0;
- char buf[400];
+ gdb_byte *buf;
char query[400];
char *p;
unsigned int nreg = 0;
unsigned int val;
int i, j, k, step;
- /* Just get the maximum buffer size. */
- bufsiz = target_read_partial (¤t_target, TARGET_OBJECT_AVR,
- NULL, NULL, 0, 0);
- if (bufsiz < 0)
- {
- fprintf_unfiltered (gdb_stderr,
- "ERR: info io_registers NOT supported by current "
- "target\n");
- return;
- }
- if (bufsiz > sizeof (buf))
- bufsiz = sizeof (buf);
-
/* Find out how many io registers the target has. */
- strcpy (query, "avr.io_reg");
- target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf, 0,
- bufsiz);
+ bufsiz = target_read_alloc (¤t_target, TARGET_OBJECT_AVR,
+ "avr.io_reg", &buf);
- if (strncmp (buf, "", bufsiz) == 0)
+ if (bufsiz <= 0)
{
fprintf_unfiltered (gdb_stderr,
- "info io_registers NOT supported by target\n");
+ _("ERR: info io_registers NOT supported "
+ "by current target\n"));
return;
}
if (sscanf (buf, "%x", &nreg) != 1)
{
fprintf_unfiltered (gdb_stderr,
- "Error fetching number of io registers\n");
+ _("Error fetching number of io registers\n"));
+ xfree (buf);
return;
}
+ xfree (buf);
+
reinitialize_more_filter ();
- printf_unfiltered ("Target has %u io registers:\n\n", nreg);
+ printf_unfiltered (_("Target has %u io registers:\n\n"), nreg);
/* only fetch up to 8 registers at a time to keep the buffer small */
step = 8;
j = nreg - i; /* last block is less than 8 registers */
snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
- target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf,
- 0, bufsiz);
+ bufsiz = target_read_alloc (¤t_target, TARGET_OBJECT_AVR,
+ query, &buf);
p = buf;
for (k = i; k < (i + j); k++)
break;
}
}
+
+ xfree (buf);
}
}
io_registers' to signify it is not available on other platforms. */
add_cmd ("io_registers", class_info, avr_io_reg_read_command,
- "query remote avr target for io space register values", &infolist);
+ _("query remote avr target for io space register values"),
+ &infolist);
}