#include "defs.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "inferior.h"
#include "symfile.h"
#include "arch-utils.h"
#include "regcache.h"
#include "gdb_string.h"
#undef XMALLOC
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
#undef EXTRACT_INSN
#define EXTRACT_INSN(addr) extract_unsigned_integer(addr,2)
enum
{
AVR_REG_W = 24,
AVR_REG_X = 26,
AVR_REG_Y = 28,
AVR_FP_REGNUM = 28,
AVR_REG_Z = 30,
AVR_SREG_REGNUM = 32,
AVR_SP_REGNUM = 33,
AVR_PC_REGNUM = 34,
AVR_NUM_REGS = 32 + 1 + 1 + 1 ,
AVR_NUM_REG_BYTES = 32 + 1 + 2 + 4 ,
AVR_PC_REG_INDEX = 35,
AVR_MAX_PROLOGUE_SIZE = 56,
AVR_MAX_PUSHES = 18,
AVR_LAST_PUSHED_REGNUM = 17,
AVR_IMEM_START = 0x00000000,
AVR_SMEM_START = 0x00800000,
#if 1
AVR_MEM_MASK = 0x00f00000,
#else
AVR_EMEM_START = 0x00810000,
AVR_MEM_MASK = 0x00ff0000,
#endif
};
struct frame_extra_info
{
CORE_ADDR return_pc;
CORE_ADDR args_pointer;
int locals_size;
int framereg;
int framesize;
int is_main;
};
struct gdbarch_tdep
{
int foo;
};
static const char *
avr_register_name (int regnum)
{
static char *register_names[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
"SREG", "SP", "PC"
};
if (regnum < 0)
return NULL;
if (regnum >= (sizeof (register_names) / sizeof (*register_names)))
return NULL;
return register_names[regnum];
}
static int
avr_register_byte (int regnum)
{
if (regnum < AVR_PC_REGNUM)
return regnum;
else
return AVR_PC_REG_INDEX;
}
static int
avr_register_raw_size (int regnum)
{
switch (regnum)
{
case AVR_PC_REGNUM:
return 4;
case AVR_SP_REGNUM:
case AVR_FP_REGNUM:
return 2;
default:
return 1;
}
}
static int
avr_register_virtual_size (int regnum)
{
return TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (regnum));
}
static struct type *
avr_register_virtual_type (int regnum)
{
switch (regnum)
{
case AVR_PC_REGNUM:
return builtin_type_unsigned_long;
case AVR_SP_REGNUM:
return builtin_type_unsigned_short;
default:
return builtin_type_unsigned_char;
}
}
static CORE_ADDR
avr_make_iaddr (CORE_ADDR x)
{
return ((x) | AVR_IMEM_START);
}
static int
avr_iaddr_p (CORE_ADDR x)
{
return (((x) & AVR_MEM_MASK) == AVR_IMEM_START);
}
static CORE_ADDR
avr_convert_iaddr_to_raw (CORE_ADDR x)
{
return ((x) & 0xffffffff);
}
static CORE_ADDR
avr_make_saddr (CORE_ADDR x)
{
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)
{
return ((x) & 0xffffffff);
}
static void
avr_address_to_pointer (struct type *type, void *buf, CORE_ADDR addr)
{
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
|| TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD)
{
store_unsigned_integer (buf, TYPE_LENGTH (type),
avr_convert_iaddr_to_raw (addr));
}
else
{
store_unsigned_integer (buf, TYPE_LENGTH (type),
avr_convert_saddr_to_raw (addr));
}
}
static CORE_ADDR
avr_pointer_to_address (struct type *type, void *buf)
{
CORE_ADDR addr = extract_address (buf, TYPE_LENGTH (type));
if (TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
{
fprintf_unfiltered (gdb_stderr, "CODE_SPACE ---->> ptr->addr: 0x%lx\n",
addr);
fprintf_unfiltered (gdb_stderr,
"+++ If you see this, please send me an email <troth@verinet.com>\n");
}
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
|| TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD
|| TYPE_CODE_SPACE (TYPE_TARGET_TYPE (type)))
return avr_make_iaddr (addr);
else
return avr_make_saddr (addr);
}
static CORE_ADDR
avr_read_pc (ptid_t ptid)
{
ptid_t save_ptid;
CORE_ADDR pc;
CORE_ADDR retval;
save_ptid = inferior_ptid;
inferior_ptid = ptid;
pc = (int) read_register (AVR_PC_REGNUM);
inferior_ptid = save_ptid;
retval = avr_make_iaddr (pc);
return retval;
}
static void
avr_write_pc (CORE_ADDR val, ptid_t ptid)
{
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)
{
return (avr_make_saddr (read_register (AVR_SP_REGNUM)));
}
static void
avr_write_sp (CORE_ADDR val)
{
write_register (AVR_SP_REGNUM, avr_convert_saddr_to_raw (val));
}
static CORE_ADDR
avr_read_fp (void)
{
return (avr_make_saddr (read_register (AVR_FP_REGNUM)));
}
static void
avr_remote_translate_xfer_address (CORE_ADDR memaddr, int nr_bytes,
CORE_ADDR *targ_addr, int *targ_len)
{
long out_addr;
long out_len;
*targ_addr = memaddr;
*targ_len = nr_bytes;
}
static CORE_ADDR
avr_convert_from_func_ptr_addr (CORE_ADDR addr)
{
return addr * 2;
}
static void
avr_scan_prologue (struct frame_info *fi)
{
CORE_ADDR prologue_start;
CORE_ADDR prologue_end;
int i;
unsigned short insn;
int regno;
int scan_stage = 0;
char *name;
struct minimal_symbol *msymbol;
int prologue_len;
unsigned char prologue[AVR_MAX_PROLOGUE_SIZE];
int vpc = 0;
fi->extra_info->framereg = AVR_SP_REGNUM;
if (find_pc_partial_function
(fi->pc, &name, &prologue_start, &prologue_end))
{
struct symtab_and_line sal = find_pc_line (prologue_start, 0);
if (sal.line == 0)
prologue_end = fi->pc;
else if (sal.end < prologue_end)
prologue_end = sal.end;
}
else
prologue_end = prologue_start + AVR_MAX_PROLOGUE_SIZE;
prologue_end = min (prologue_end, fi->pc);
fi->extra_info->framesize = 0;
prologue_len = prologue_end - prologue_start;
read_memory (prologue_start, prologue, prologue_len);
if (name && strcmp ("main", name) == 0 && prologue_len == 8)
{
CORE_ADDR locals;
unsigned char img[] = {
0xde, 0xbf,
0xcd, 0xbf
};
fi->extra_info->framereg = AVR_FP_REGNUM;
insn = EXTRACT_INSN (&prologue[vpc]);
if ((insn & 0xf0f0) == 0xe0c0)
{
locals = (insn & 0xf) | ((insn & 0x0f00) >> 4);
insn = EXTRACT_INSN (&prologue[vpc + 2]);
if ((insn & 0xf0f0) == 0xe0d0)
{
locals |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
if (memcmp (prologue + vpc + 4, img, sizeof (img)) == 0)
{
fi->frame = locals;
fi->extra_info->is_main = 1;
return;
}
}
}
}
while (prologue_len <= 12)
{
int loc_size;
int body_addr;
unsigned num_pushes;
insn = EXTRACT_INSN (&prologue[vpc]);
if ((insn & 0xf0f0) != 0xe0a0)
break;
loc_size = (insn & 0xf) | ((insn & 0x0f00) >> 4);
insn = EXTRACT_INSN (&prologue[vpc + 2]);
if ((insn & 0xf0f0) != 0xe0b0)
break;
loc_size |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
insn = EXTRACT_INSN (&prologue[vpc + 4]);
if ((insn & 0xf0f0) != 0xe0e0)
break;
body_addr = (insn & 0xf) | ((insn & 0x0f00) >> 4);
insn = EXTRACT_INSN (&prologue[vpc + 6]);
if ((insn & 0xf0f0) != 0xe0f0)
break;
body_addr |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
if (body_addr != (prologue_start + 10) / 2)
break;
msymbol = lookup_minimal_symbol ("__prologue_saves__", NULL, NULL);
if (!msymbol)
break;
insn = EXTRACT_INSN (&prologue[vpc + 8]);
if ((insn & 0xf000) != 0xc000)
break;
i = (insn & 0xfff) | (insn & 0x800 ? (-1 ^ 0xfff) : 0);
i *= 2;
i += vpc + prologue_start + 10;
num_pushes = AVR_MAX_PUSHES - (i - SYMBOL_VALUE_ADDRESS (msymbol)) / 2;
if (num_pushes > AVR_MAX_PUSHES)
num_pushes = 0;
if (num_pushes)
{
int from;
fi->saved_regs[AVR_FP_REGNUM + 1] = num_pushes;
if (num_pushes >= 2)
fi->saved_regs[AVR_FP_REGNUM] = num_pushes - 1;
i = 0;
for (from = AVR_LAST_PUSHED_REGNUM + 1 - (num_pushes - 2);
from <= AVR_LAST_PUSHED_REGNUM; ++from)
fi->saved_regs[from] = ++i;
}
fi->extra_info->locals_size = loc_size;
fi->extra_info->framesize = loc_size + num_pushes;
fi->extra_info->framereg = AVR_FP_REGNUM;
return;
}
if (prologue_len >= 12)
{
unsigned char img[] = {
0x78, 0x94,
0x1f, 0x92,
0x0f, 0x92,
0x0f, 0xb6,
0x0f, 0x92,
0x11, 0x24
};
if (memcmp (prologue, img, sizeof (img)) == 0)
{
vpc += sizeof (img);
fi->saved_regs[0] = 2;
fi->saved_regs[1] = 1;
fi->extra_info->framesize += 3;
}
else if (memcmp (img + 1, prologue, sizeof (img) - 1) == 0)
{
vpc += sizeof (img) - 1;
fi->saved_regs[0] = 2;
fi->saved_regs[1] = 1;
fi->extra_info->framesize += 3;
}
}
for (; vpc <= prologue_len; vpc += 2)
{
insn = EXTRACT_INSN (&prologue[vpc]);
if ((insn & 0xfe0f) == 0x920f)
{
regno = (insn & 0x1f0) >> 4;
++fi->extra_info->framesize;
fi->saved_regs[regno] = fi->extra_info->framesize;
scan_stage = 1;
}
else
break;
}
if (scan_stage == 1 && vpc + 4 <= prologue_len)
{
unsigned char img[] = {
0xcd, 0xb7,
0xde, 0xb7
};
unsigned short insn1;
if (memcmp (prologue + vpc, img, sizeof (img)) == 0)
{
vpc += 4;
fi->extra_info->framereg = AVR_FP_REGNUM;
scan_stage = 2;
}
}
if (scan_stage == 2 && vpc + 12 <= prologue_len)
{
int locals_size = 0;
unsigned char img[] = {
0x0f, 0xb6,
0xf8, 0x94,
0xcd, 0xbf,
0x0f, 0xbe,
0xde, 0xbf
};
unsigned char img_sig[] = {
0xcd, 0xbf,
0xde, 0xbf
};
unsigned char img_int[] = {
0xf8, 0x94,
0xcd, 0xbf,
0x78, 0x94,
0xde, 0xbf
};
insn = EXTRACT_INSN (&prologue[vpc]);
vpc += 2;
if ((insn & 0xff30) == 0x9720)
locals_size = (insn & 0xf) | ((insn & 0xc0) >> 2);
else if ((insn & 0xf0f0) == 0x50c0)
{
locals_size = (insn & 0xf) | ((insn & 0xf00) >> 4);
insn = EXTRACT_INSN (&prologue[vpc]);
vpc += 2;
locals_size += ((insn & 0xf) | ((insn & 0xf00) >> 4) << 8);
}
else
return;
fi->extra_info->locals_size = locals_size;
fi->extra_info->framesize += locals_size;
}
}
static void
avr_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
int reg;
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
fi->extra_info = (struct frame_extra_info *)
frame_obstack_alloc (sizeof (struct frame_extra_info));
frame_saved_regs_zalloc (fi);
fi->extra_info->return_pc = 0;
fi->extra_info->args_pointer = 0;
fi->extra_info->locals_size = 0;
fi->extra_info->framereg = 0;
fi->extra_info->framesize = 0;
fi->extra_info->is_main = 0;
avr_scan_prologue (fi);
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
{
fi->frame = deprecated_read_register_dummy (fi->pc, fi->frame,
AVR_PC_REGNUM);
}
else if (!fi->next)
fi->frame = read_register (fi->extra_info->framereg);
else if (fi->extra_info->is_main != 1)
{
struct frame_info *next_fi = fi->next;
if (fi->extra_info->framereg == AVR_SP_REGNUM)
fi->frame =
next_fi->frame + 2 + next_fi->extra_info->framesize;
else
{
CORE_ADDR fp = 0;
CORE_ADDR fp1 = 0;
unsigned int fp_low, fp_high;
for (; next_fi; next_fi = next_fi->next)
{
if (next_fi->saved_regs[AVR_FP_REGNUM] && !fp)
fp = next_fi->saved_regs[AVR_FP_REGNUM];
if (next_fi->saved_regs[AVR_FP_REGNUM + 1] && !fp1)
fp1 = next_fi->saved_regs[AVR_FP_REGNUM + 1];
}
fp_low = (fp ? read_memory_unsigned_integer (avr_make_saddr (fp), 1)
: read_register (AVR_FP_REGNUM)) & 0xff;
fp_high =
(fp1 ? read_memory_unsigned_integer (avr_make_saddr (fp1), 1) :
read_register (AVR_FP_REGNUM + 1)) & 0xff;
fi->frame = fp_low | (fp_high << 8);
}
}
if ((fi->pc) && (fi->extra_info->is_main == 0))
{
CORE_ADDR addr;
int i;
addr = fi->frame + fi->extra_info->framesize + 1;
fi->extra_info->return_pc =
read_memory_unsigned_integer (avr_make_saddr (addr), 1) << 8;
fi->extra_info->return_pc |=
read_memory_unsigned_integer (avr_make_saddr (addr + 1), 1);
fi->extra_info->return_pc *= 2;
for (i = 0; i < NUM_REGS; i++)
{
if (fi->saved_regs[i])
fi->saved_regs[i] = addr - fi->saved_regs[i];
}
}
}
static void
avr_pop_frame (void)
{
unsigned regnum;
CORE_ADDR saddr;
struct frame_info *frame = get_current_frame ();
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
{
generic_pop_dummy_frame ();
}
else
{
for (regnum = 0; regnum < 8; regnum++)
{
if (frame->saved_regs[regnum] && regnum != AVR_SP_REGNUM)
{
saddr = avr_make_saddr (frame->saved_regs[regnum]);
write_register (regnum,
read_memory_unsigned_integer (saddr, 1));
}
else if (frame->saved_regs[regnum] && regnum == AVR_SP_REGNUM)
write_register (regnum, frame->frame + 2);
}
write_pc (frame->extra_info->return_pc);
}
flush_cached_frames ();
}
static CORE_ADDR
avr_frame_saved_pc (struct frame_info *frame)
{
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
return deprecated_read_register_dummy (frame->pc, frame->frame,
AVR_PC_REGNUM);
else
return frame->extra_info->return_pc;
}
static CORE_ADDR
avr_saved_pc_after_call (struct frame_info *frame)
{
unsigned char m1, m2;
unsigned int sp = read_register (AVR_SP_REGNUM);
m1 = read_memory_unsigned_integer (avr_make_saddr (sp + 1), 1);
m2 = read_memory_unsigned_integer (avr_make_saddr (sp + 2), 1);
return (m2 | (m1 << 8)) * 2;
}
static void
avr_extract_return_value (struct type *type, char *regbuf, char *valbuf)
{
int wordsize, len;
wordsize = 2;
len = TYPE_LENGTH (type);
switch (len)
{
case 1:
case 2:
memcpy (valbuf, regbuf + REGISTER_BYTE (24), 2);
break;
case 4:
memcpy (valbuf, regbuf + REGISTER_BYTE (22), 4);
break;
case 8:
error ("I don't know how a double is returned.");
break;
}
}
static CORE_ADDR
avr_call_dummy_address (void)
{
return entry_point_address ();
}
static void
avr_store_return_value (struct type *type, char *valbuf)
{
int wordsize, len, regval;
wordsize = 2;
len = TYPE_LENGTH (type);
switch (len)
{
case 1:
case 2:
regval = extract_address (valbuf, len);
write_register (0, regval);
break;
case 4:
regval = extract_address (valbuf, len);
write_register (0, regval >> 16);
write_register (1, regval & 0xffff);
break;
case 8:
error ("I don't know how to return a double.");
break;
}
}
static CORE_ADDR
avr_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
unsigned char buf[2];
int wordsize = 2;
#if 0
struct minimal_symbol *msymbol;
CORE_ADDR mon_brk;
#endif
buf[0] = 0;
buf[1] = 0;
sp -= wordsize;
write_memory (sp + 1, buf, 2);
#if 0
if ((strcmp (target_shortname, "avr-mon") == 0)
&& (msymbol = lookup_minimal_symbol ("gdb_break", NULL, NULL)))
{
mon_brk = SYMBOL_VALUE_ADDRESS (msymbol);
store_unsigned_integer (buf, wordsize, mon_brk / 2);
sp -= wordsize;
write_memory (sp + 1, buf + 1, 1);
write_memory (sp + 2, buf, 1);
}
#endif
return sp;
}
static CORE_ADDR
avr_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR func_addr, func_end;
struct symtab_and_line sal;
if (find_pc_partial_function (pc, NULL, &func_addr, &func_end))
{
sal = find_pc_line (func_addr, 0);
if (sal.line != 0 && sal.end < (func_end-2))
return sal.end;
}
return pc;
}
static CORE_ADDR
avr_frame_address (struct frame_info *fi)
{
return avr_make_saddr (fi->frame);
}
static CORE_ADDR
avr_frame_chain (struct frame_info *frame)
{
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
{
frame->extra_info->return_pc
= deprecated_read_register_dummy (frame->pc, frame->frame,
AVR_PC_REGNUM);
return frame->frame;
}
return (frame->extra_info->is_main ? 0
: frame->frame + frame->extra_info->framesize + 2 );
}
static void
avr_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
write_register (0, addr);
}
static CORE_ADDR
avr_extract_struct_value_address (char *regbuf)
{
return (extract_address ((regbuf) + REGISTER_BYTE (0),
REGISTER_RAW_SIZE (0)) | AVR_SMEM_START);
}
static CORE_ADDR
avr_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
int stack_alloc, stack_offset;
int wordsize;
int argreg;
int argnum;
struct type *type;
CORE_ADDR regval;
char *val;
char valbuf[4];
int len;
wordsize = 1;
#if 0
for (argnum = 0, stack_alloc = 0; argnum < nargs; argnum++)
stack_alloc += TYPE_LENGTH (VALUE_TYPE (args[argnum]));
sp -= stack_alloc;
#endif
argreg = 25;
if (struct_return)
{
write_register (--argreg, struct_addr);
}
for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
{
type = VALUE_TYPE (args[argnum]);
len = TYPE_LENGTH (type);
val = (char *) VALUE_CONTENTS (args[argnum]);
while (len > 0)
{
len -= wordsize;
regval = extract_address (val + len, wordsize);
write_register (argreg--, regval);
}
}
return sp;
}
static struct gdbarch *
avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
static LONGEST avr_call_dummy_words[] = { 0 };
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
return arches->gdbarch;
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
switch (info.bfd_arch_info->mach)
{
case bfd_mach_avr1:
case bfd_mach_avr2:
case bfd_mach_avr3:
case bfd_mach_avr4:
case bfd_mach_avr5:
break;
}
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
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);
set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
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_read_pc (gdbarch, avr_read_pc);
set_gdbarch_write_pc (gdbarch, avr_write_pc);
set_gdbarch_read_fp (gdbarch, avr_read_fp);
set_gdbarch_read_sp (gdbarch, avr_read_sp);
set_gdbarch_write_sp (gdbarch, avr_write_sp);
set_gdbarch_num_regs (gdbarch, AVR_NUM_REGS);
set_gdbarch_sp_regnum (gdbarch, AVR_SP_REGNUM);
set_gdbarch_fp_regnum (gdbarch, AVR_FP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, AVR_PC_REGNUM);
set_gdbarch_register_name (gdbarch, avr_register_name);
set_gdbarch_register_size (gdbarch, 1);
set_gdbarch_register_bytes (gdbarch, AVR_NUM_REG_BYTES);
set_gdbarch_register_byte (gdbarch, avr_register_byte);
set_gdbarch_register_raw_size (gdbarch, avr_register_raw_size);
set_gdbarch_max_register_raw_size (gdbarch, 4);
set_gdbarch_register_virtual_size (gdbarch, avr_register_virtual_size);
set_gdbarch_max_register_virtual_size (gdbarch, 4);
set_gdbarch_register_virtual_type (gdbarch, avr_register_virtual_type);
set_gdbarch_get_saved_register (gdbarch, generic_unwind_get_saved_register);
set_gdbarch_print_insn (gdbarch, print_insn_avr);
set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
set_gdbarch_call_dummy_address (gdbarch, avr_call_dummy_address);
set_gdbarch_call_dummy_start_offset (gdbarch, 0);
set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);
set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
set_gdbarch_call_dummy_p (gdbarch, 1);
set_gdbarch_call_dummy_words (gdbarch, avr_call_dummy_words);
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
set_gdbarch_address_to_pointer (gdbarch, avr_address_to_pointer);
set_gdbarch_pointer_to_address (gdbarch, avr_pointer_to_address);
set_gdbarch_deprecated_extract_return_value (gdbarch, avr_extract_return_value);
set_gdbarch_push_arguments (gdbarch, avr_push_arguments);
set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
set_gdbarch_push_return_address (gdbarch, avr_push_return_address);
set_gdbarch_pop_frame (gdbarch, avr_pop_frame);
set_gdbarch_deprecated_store_return_value (gdbarch, avr_store_return_value);
set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
set_gdbarch_store_struct_return (gdbarch, avr_store_struct_return);
set_gdbarch_deprecated_extract_struct_value_address
(gdbarch, avr_extract_struct_value_address);
set_gdbarch_frame_init_saved_regs (gdbarch, avr_scan_prologue);
set_gdbarch_init_extra_frame_info (gdbarch, avr_init_extra_frame_info);
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_function_start_offset (gdbarch, 0);
set_gdbarch_remote_translate_xfer_address (gdbarch,
avr_remote_translate_xfer_address);
set_gdbarch_frame_args_skip (gdbarch, 0);
set_gdbarch_frameless_function_invocation (gdbarch, frameless_look_for_prologue);
set_gdbarch_frame_chain (gdbarch, avr_frame_chain);
set_gdbarch_frame_chain_valid (gdbarch, generic_func_frame_chain_valid);
set_gdbarch_frame_saved_pc (gdbarch, avr_frame_saved_pc);
set_gdbarch_frame_args_address (gdbarch, avr_frame_address);
set_gdbarch_frame_locals_address (gdbarch, avr_frame_address);
set_gdbarch_saved_pc_after_call (gdbarch, avr_saved_pc_after_call);
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
set_gdbarch_convert_from_func_ptr_addr (gdbarch,
avr_convert_from_func_ptr_addr);
return gdbarch;
}
static void
avr_io_reg_read_command (char *args, int from_tty)
{
int bufsiz = 0;
char buf[400];
char query[400];
char *p;
unsigned int nreg = 0;
unsigned int val;
int i, j, k, step;
if (!current_target.to_query)
{
fprintf_unfiltered (gdb_stderr,
"ERR: info io_registers NOT supported by current target\n");
return;
}
target_query ((int) 'R', 0, 0, &bufsiz);
if (bufsiz > sizeof (buf))
bufsiz = sizeof (buf);
strcpy (query, "avr.io_reg");
target_query ((int) 'R', query, buf, &bufsiz);
if (strncmp (buf, "", bufsiz) == 0)
{
fprintf_unfiltered (gdb_stderr,
"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");
return;
}
reinitialize_more_filter ();
printf_unfiltered ("Target has %u io registers:\n\n", nreg);
step = 8;
for (i = 0; i < nreg; i += step)
{
j = step - (nreg % step);
snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
target_query ((int) 'R', query, buf, &bufsiz);
p = buf;
for (k = i; k < (i + j); k++)
{
if (sscanf (p, "%[^,],%x;", query, &val) == 2)
{
printf_filtered ("[%02x] %-15s : %02x\n", k, query, val);
while ((*p != ';') && (*p != '\0'))
p++;
p++;
if (*p == '\0')
break;
}
}
}
}
void
_initialize_avr_tdep (void)
{
register_gdbarch_init (bfd_arch_avr, avr_gdbarch_init);
add_cmd ("io_registers", class_info, avr_io_reg_read_command,
"query remote avr target for io space register values", &infolist);
}