/* Target-dependent code for Atmel AVR, for GDB.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GDB.
#include "arch-utils.h"
#include "regcache.h"
#include "gdb_string.h"
+#include "dis-asm.h"
/* AVR Background:
return ((x) | AVR_IMEM_START);
}
-static int
-avr_iaddr_p (CORE_ADDR x)
-{
- return (((x) & AVR_MEM_MASK) == AVR_IMEM_START);
-}
-
/* FIXME: TRoth: Really need to use a larger mask for instructions. Some
devices are already up to 128KBytes of flash space.
return ((x) | AVR_SMEM_START);
}
-static int
-avr_saddr_p (CORE_ADDR x)
-{
- return (((x) & AVR_MEM_MASK) == AVR_SMEM_START);
-}
-
static CORE_ADDR
avr_convert_saddr_to_raw (CORE_ADDR x)
{
avr_read_pc (ptid_t ptid)
{
ptid_t save_ptid;
- CORE_ADDR pc;
+ ULONGEST pc;
CORE_ADDR retval;
save_ptid = inferior_ptid;
inferior_ptid = ptid;
- pc = (int) read_register (AVR_PC_REGNUM);
+ regcache_cooked_read_unsigned (current_regcache, AVR_PC_REGNUM, &pc);
inferior_ptid = save_ptid;
retval = avr_make_iaddr (pc);
return retval;
static CORE_ADDR
avr_read_sp (void)
{
- return (avr_make_saddr (read_register (AVR_SP_REGNUM)));
+ ULONGEST sp;
+
+ regcache_cooked_read_unsigned (current_regcache, AVR_SP_REGNUM, &sp);
+ return (avr_make_saddr (sp));
}
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:
return pc + avr_scan_arg_moves (vpc, prologue);;
}
-/* Returns the return address for a dummy. */
-
-static CORE_ADDR
-avr_call_dummy_address (void)
-{
- return entry_point_address ();
-}
-
static CORE_ADDR
avr_skip_prologue (CORE_ADDR pc)
{
prologue_end = avr_scan_prologue (pc, &info);
- if (info.prologue_type != AVR_PROLOGUE_NONE)
+ if (info.prologue_type == AVR_PROLOGUE_NONE)
+ return pc;
+ else
{
sal = find_pc_line (func_addr, 0);
return prologue_end;
}
-static CORE_ADDR
-avr_frame_address (struct frame_info *fi)
-{
- return avr_make_saddr (get_frame_base (fi));
-}
-
/* Not all avr devices support the BREAK insn. Those that don't should treat
it as a NOP. Thus, it should be ok. Since the avr is currently a remote
only target, this shouldn't be a problem (I hope). TRoth/2003-05-14 */
{
regcache_cooked_read (regcache, lsb_reg + i,
(bfd_byte *) valbuf + i);
- fprintf_unfiltered (gdb_stderr, "reg = %d (0x%02x)\n",
- lsb_reg+i, *((unsigned char *)valbuf+i));
- }
- }
-}
-
-static void
-avr_saved_regs_unwinder (struct frame_info *next_frame,
- struct trad_frame_saved_reg *this_saved_regs,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *bufferp)
-{
- if (this_saved_regs[regnum].addr != 0)
- {
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = this_saved_regs[regnum].addr;
- *realnump = -1;
- if (bufferp != NULL)
- {
- /* Read the value in from memory. */
-
- if (regnum == AVR_PC_REGNUM)
- {
- /* 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 (this_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);
- }
- else
- {
- read_memory (this_saved_regs[regnum].addr, bufferp,
- register_size (current_gdbarch, regnum));
- }
}
-
- return;
}
-
- /* No luck, assume this and the next frame have the same register
- value. If a value is needed, pass the request on down the chain;
- otherwise just return an indication that the value is in the same
- register as the next frame. */
- frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp,
- realnump, bufferp);
}
/* Put here the code to store, into fi->saved_regs, the addresses of
if ((pc > 0) && (pc < frame_pc_unwind (next_frame)))
avr_scan_prologue (pc, info);
- if (info->prologue_type != AVR_PROLOGUE_NONE)
+ if ((info->prologue_type != AVR_PROLOGUE_NONE)
+ && (info->prologue_type != AVR_PROLOGUE_MAIN))
{
ULONGEST high_base; /* High byte of FP */
info->base = avr_make_saddr (this_base);
/* Adjust all the saved registers so that they contain addresses and not
- offsets. We need to add one to the addresses since push ops are post
- decrement on the avr. */
+ offsets. */
for (i = 0; i < NUM_REGS - 1; i++)
if (info->saved_regs[i].addr)
{
info->saved_regs[AVR_PC_REGNUM].addr = info->prev_sp;
}
+ /* The previous frame's SP needed to be computed. Save the computed
+ value. */
+ trad_frame_set_value (info->saved_regs, AVR_SP_REGNUM, info->prev_sp+1);
+
return info;
}
/* The FUNC is easy. */
func = frame_func_unwind (next_frame);
- /* This is meant to halt the backtrace at "_start". Make sure we
- don't halt it at a generic dummy frame. */
- if (inside_entry_file (func))
- return;
-
/* Hopefully the prologue analysis either correctly determined the
frame's base (which is the SP from the previous frame), or set
that base to "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;
}
struct avr_unwind_cache *info
= avr_frame_unwind_cache (next_frame, this_prologue_cache);
- avr_saved_regs_unwinder (next_frame, info->saved_regs, regnum, optimizedp,
- lvalp, addrp, realnump, bufferp);
+ 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);
+ }
+ }
+ }
+ else
+ trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, bufferp);
}
static const struct frame_unwind avr_frame_unwind = {
};
const struct frame_unwind *
-avr_frame_p (CORE_ADDR pc)
+avr_frame_sniffer (struct frame_info *next_frame)
{
return &avr_frame_unwind;
}
return frame_id_build (avr_make_saddr (base), frame_pc_unwind (next_frame));
}
-static CORE_ADDR
-avr_push_dummy_code (struct gdbarch *gdbarch,
- CORE_ADDR sp, CORE_ADDR funaddr, int using_gcc,
- struct value **args, int nargs,
- struct type *value_type,
- CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
-{
- fprintf_unfiltered (gdb_stderr, " ----->>>> push_dummy_code\n");
-}
-
/* When arguments must be pushed onto the stack, they go on in reverse
order. The below implements a FILO (stack) to do this. */
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)
int last_regnum;
int j;
struct value *arg = args[i];
- struct type *type = check_typedef (VALUE_TYPE (arg));
+ struct type *type = check_typedef (value_type (arg));
char *contents = VALUE_CONTENTS (arg);
int len = TYPE_LENGTH (type);
set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 32);
- set_gdbarch_bfd_vma_bit (gdbarch, 32); /* FIXME: TRoth/2002-02-18: Is this needed? */
set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_extract_return_value (gdbarch, avr_extract_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_avr);
- set_gdbarch_call_dummy_address (gdbarch, avr_call_dummy_address);
set_gdbarch_push_dummy_call (gdbarch, avr_push_dummy_call);
- set_gdbarch_push_dummy_code (gdbarch, avr_push_dummy_code);
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_decr_pc_after_break (gdbarch, 0);
set_gdbarch_breakpoint_from_pc (gdbarch, avr_breakpoint_from_pc);
- set_gdbarch_function_start_offset (gdbarch, 0);
-
- set_gdbarch_frame_args_skip (gdbarch, 0);
- set_gdbarch_frameless_function_invocation (gdbarch,
- frameless_look_for_prologue);
- set_gdbarch_frame_args_address (gdbarch, avr_frame_address);
- set_gdbarch_frame_locals_address (gdbarch, avr_frame_address);
-
- frame_unwind_append_predicate (gdbarch, avr_frame_p);
+ frame_unwind_append_sniffer (gdbarch, avr_frame_sniffer);
frame_base_set_default (gdbarch, &avr_frame_base);
set_gdbarch_unwind_dummy_id (gdbarch, avr_unwind_dummy_id);
static void
avr_io_reg_read_command (char *args, int from_tty)
{
- int bufsiz = 0;
+ LONGEST bufsiz = 0;
char buf[400];
char query[400];
char *p;
unsigned int val;
int i, j, k, step;
- if (!current_target.to_query)
+ /* 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");
+ _("ERR: info io_registers NOT supported "
+ "by current target\n"));
return;
}
-
- /* Just get the maximum buffer size. */
- target_query ((int) 'R', 0, 0, &bufsiz);
if (bufsiz > sizeof (buf))
bufsiz = sizeof (buf);
/* Find out how many io registers the target has. */
strcpy (query, "avr.io_reg");
- target_query ((int) 'R', query, buf, &bufsiz);
+ target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf, 0,
+ bufsiz);
if (strncmp (buf, "", bufsiz) == 0)
{
fprintf_unfiltered (gdb_stderr,
- "info io_registers NOT supported by target\n");
+ _("info io_registers NOT supported by 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"));
return;
}
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_query ((int) 'R', query, buf, &bufsiz);
+ target_read_partial (¤t_target, TARGET_OBJECT_AVR, query, buf,
+ 0, bufsiz);
p = buf;
for (k = i; k < (i + j); k++)
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);
}