2009-06-16 Tristan Gingold <gingold@adacore.com>

* avr-tdep.c (struct gdbarch_tdep): Replace the unused field with
	call_length field.
	(avr_register_name): Add const to register_names.
	(avr_scan_arg_moves): Move inside avr_scan_prologue.
	(avr_scan_prologue): Add pc_end argument.
	Only read prologue bytes that can be read.
	Limit the scan to the known prologue length.
	Makes pattern variables static and const.
	Fix indentation.
	(avr_skip_prologue): Pass func_end argument to avr_scan_prologue.
	Fix indentation.
	(avr_breakpoint_from_pc): Constify avr_break_insn.
	(avr_extract_return_value): Fix function comment.
	(avr_frame_unwind_cache): Fix GNU style violations.
	Pass current_pc argument to avr_scan_prologue to stop prologue
	analysis to the current pc.  This fixes the bug with the 'next'
	command.
	Correctly set the SP register of the previous frame (use call_length).
	(avr_frame_prev_register): Fix indentation.
	Correctly read PC from the stack on avr6 architectures.
	(avr_push_dummy_call): Fix indentation.
	(avr_gdbarch_init): Set call_length according to the architecture.
This commit is contained in:
Tristan Gingold 2009-06-16 09:21:36 +00:00
parent 6db7e006e4
commit 4e99ad6974
2 changed files with 148 additions and 103 deletions

View File

@ -1,3 +1,28 @@
2009-06-16 Tristan Gingold <gingold@adacore.com>
* avr-tdep.c (struct gdbarch_tdep): Replace the unused field with
call_length field.
(avr_register_name): Add const to register_names.
(avr_scan_arg_moves): Move inside avr_scan_prologue.
(avr_scan_prologue): Add pc_end argument.
Only read prologue bytes that can be read.
Limit the scan to the known prologue length.
Makes pattern variables static and const.
Fix indentation.
(avr_skip_prologue): Pass func_end argument to avr_scan_prologue.
Fix indentation.
(avr_breakpoint_from_pc): Constify avr_break_insn.
(avr_extract_return_value): Fix function comment.
(avr_frame_unwind_cache): Fix GNU style violations.
Pass current_pc argument to avr_scan_prologue to stop prologue
analysis to the current pc. This fixes the bug with the 'next'
command.
Correctly set the SP register of the previous frame (use call_length).
(avr_frame_prev_register): Fix indentation.
Correctly read PC from the stack on avr6 architectures.
(avr_push_dummy_call): Fix indentation.
(avr_gdbarch_init): Set call_length according to the architecture.
2009-06-15 Phil Muldoon <pmuldoon@redhat.com> 2009-06-15 Phil Muldoon <pmuldoon@redhat.com>
* infcall.c (show_unwind_on_terminating_exception_p): New * infcall.c (show_unwind_on_terminating_exception_p): New

View File

@ -181,8 +181,9 @@ struct avr_unwind_cache
struct gdbarch_tdep struct gdbarch_tdep
{ {
/* FIXME: TRoth: is there anything to put here? */ /* Number of bytes stored to the stack by call instructions.
int foo; 2 bytes for avr1-5, 3 bytes for avr6. */
int call_length;
}; };
/* Lookup the name of a register given it's number. */ /* Lookup the name of a register given it's number. */
@ -190,7 +191,7 @@ struct gdbarch_tdep
static const char * static const char *
avr_register_name (struct gdbarch *gdbarch, int regnum) avr_register_name (struct gdbarch *gdbarch, int regnum)
{ {
static char *register_names[] = { static const char * const register_names[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
@ -324,25 +325,6 @@ avr_write_pc (struct regcache *regcache, CORE_ADDR val)
avr_convert_iaddr_to_raw (val)); avr_convert_iaddr_to_raw (val));
} }
static int
avr_scan_arg_moves (int vpc, unsigned char *prologue)
{
unsigned short insn;
for (; vpc < AVR_MAX_PROLOGUE_SIZE; vpc += 2)
{
insn = EXTRACT_INSN (&prologue[vpc]);
if ((insn & 0xff00) == 0x0100) /* movw rXX, rYY */
continue;
else if ((insn & 0xfc00) == 0x2c00) /* mov rXX, rYY */
continue;
else
break;
}
return vpc;
}
/* Function: avr_scan_prologue /* Function: avr_scan_prologue
This function decodes an AVR function prologue to determine: This function decodes an AVR function prologue to determine:
@ -439,7 +421,8 @@ avr_scan_arg_moves (int vpc, unsigned char *prologue)
types. */ types. */
static CORE_ADDR static CORE_ADDR
avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info) avr_scan_prologue (CORE_ADDR pc_beg, CORE_ADDR pc_end,
struct avr_unwind_cache *info)
{ {
int i; int i;
unsigned short insn; unsigned short insn;
@ -447,12 +430,17 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
struct minimal_symbol *msymbol; struct minimal_symbol *msymbol;
unsigned char prologue[AVR_MAX_PROLOGUE_SIZE]; unsigned char prologue[AVR_MAX_PROLOGUE_SIZE];
int vpc = 0; int vpc = 0;
int len;
len = pc_end - pc_beg;
if (len > AVR_MAX_PROLOGUE_SIZE)
len = AVR_MAX_PROLOGUE_SIZE;
/* FIXME: TRoth/2003-06-11: This could be made more efficient by only /* FIXME: TRoth/2003-06-11: This could be made more efficient by only
reading in the bytes of the prologue. The problem is that the figuring reading in the bytes of the prologue. The problem is that the figuring
out where the end of the prologue is is a bit difficult. The old code out where the end of the prologue is is a bit difficult. The old code
tried to do that, but failed quite often. */ tried to do that, but failed quite often. */
read_memory (pc, prologue, AVR_MAX_PROLOGUE_SIZE); read_memory (pc_beg, prologue, len);
/* Scanning main()'s prologue /* Scanning main()'s prologue
ldi r28,lo8(<RAM_ADDR> - <LOCALS_SIZE>) ldi r28,lo8(<RAM_ADDR> - <LOCALS_SIZE>)
@ -460,10 +448,10 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
out __SP_H__,r29 out __SP_H__,r29
out __SP_L__,r28 */ out __SP_L__,r28 */
if (1) if (len >= 4)
{ {
CORE_ADDR locals; CORE_ADDR locals;
unsigned char img[] = { static const unsigned char img[] = {
0xde, 0xbf, /* out __SP_H__,r29 */ 0xde, 0xbf, /* out __SP_H__,r29 */
0xcd, 0xbf /* out __SP_L__,r28 */ 0xcd, 0xbf /* out __SP_L__,r28 */
}; };
@ -478,11 +466,12 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
if ((insn & 0xf0f0) == 0xe0d0) if ((insn & 0xf0f0) == 0xe0d0)
{ {
locals |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8; locals |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
if (memcmp (prologue + vpc + 4, img, sizeof (img)) == 0) if (vpc + 4 + sizeof (img) < len
&& memcmp (prologue + vpc + 4, img, sizeof (img)) == 0)
{ {
info->prologue_type = AVR_PROLOGUE_MAIN; info->prologue_type = AVR_PROLOGUE_MAIN;
info->base = locals; info->base = locals;
return pc + 4; return pc_beg + 4;
} }
} }
} }
@ -498,6 +487,11 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
unsigned num_pushes; unsigned num_pushes;
int pc_offset = 0; int pc_offset = 0;
/* At least the fifth instruction must have been executed to
modify frame shape. */
if (len < 10)
break;
insn = EXTRACT_INSN (&prologue[vpc]); insn = EXTRACT_INSN (&prologue[vpc]);
/* ldi r26,<LOCALS_SIZE> */ /* ldi r26,<LOCALS_SIZE> */
if ((insn & 0xf0f0) != 0xe0a0) if ((insn & 0xf0f0) != 0xe0a0)
@ -539,9 +533,9 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
/* Convert offset to byte addressable mode */ /* Convert offset to byte addressable mode */
i *= 2; i *= 2;
/* Destination address */ /* Destination address */
i += pc + 10; i += pc_beg + 10;
if (body_addr != (pc + 10)/2) if (body_addr != (pc_beg + 10)/2)
break; break;
pc_offset += 2; pc_offset += 2;
@ -554,7 +548,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
/* Convert address to byte addressable mode */ /* Convert address to byte addressable mode */
i *= 2; i *= 2;
if (body_addr != (pc + 12)/2) if (body_addr != (pc_beg + 12)/2)
break; break;
pc_offset += 4; pc_offset += 4;
@ -589,7 +583,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
info->size = loc_size + num_pushes; info->size = loc_size + num_pushes;
info->prologue_type = AVR_PROLOGUE_CALL; info->prologue_type = AVR_PROLOGUE_CALL;
return pc + pc_offset; return pc_beg + pc_offset;
} }
/* Scan for the beginning of the prologue for an interrupt or signal /* Scan for the beginning of the prologue for an interrupt or signal
@ -599,7 +593,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
if (1) if (1)
{ {
unsigned char img[] = { static const unsigned char img[] = {
0x78, 0x94, /* sei */ 0x78, 0x94, /* sei */
0x1f, 0x92, /* push r1 */ 0x1f, 0x92, /* push r1 */
0x0f, 0x92, /* push r0 */ 0x0f, 0x92, /* push r0 */
@ -607,7 +601,8 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
0x0f, 0x92, /* push r0 */ 0x0f, 0x92, /* push r0 */
0x11, 0x24 /* clr r1 */ 0x11, 0x24 /* clr r1 */
}; };
if (memcmp (prologue, img, sizeof (img)) == 0) if (len >= sizeof (img)
&& memcmp (prologue, img, sizeof (img)) == 0)
{ {
info->prologue_type = AVR_PROLOGUE_INTR; info->prologue_type = AVR_PROLOGUE_INTR;
vpc += sizeof (img); vpc += sizeof (img);
@ -616,7 +611,8 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
info->saved_regs[1].addr = 1; info->saved_regs[1].addr = 1;
info->size += 3; info->size += 3;
} }
else if (memcmp (img + 2, prologue, sizeof (img) - 2) == 0) else if (len >= sizeof (img) - 2
&& memcmp (img + 2, prologue, sizeof (img) - 2) == 0)
{ {
info->prologue_type = AVR_PROLOGUE_SIG; info->prologue_type = AVR_PROLOGUE_SIG;
vpc += sizeof (img) - 2; vpc += sizeof (img) - 2;
@ -630,7 +626,7 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
/* First stage of the prologue scanning. /* First stage of the prologue scanning.
Scan pushes (saved registers) */ Scan pushes (saved registers) */
for (; vpc < AVR_MAX_PROLOGUE_SIZE; vpc += 2) for (; vpc < len; vpc += 2)
{ {
insn = EXTRACT_INSN (&prologue[vpc]); insn = EXTRACT_INSN (&prologue[vpc]);
if ((insn & 0xfe0f) == 0x920f) /* push rXX */ if ((insn & 0xfe0f) == 0x920f) /* push rXX */
@ -654,15 +650,16 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
in r28,__SP_L__ in r28,__SP_L__
in r29,__SP_H__ */ in r29,__SP_H__ */
if (scan_stage == 1 && vpc < AVR_MAX_PROLOGUE_SIZE) if (scan_stage == 1 && vpc < len)
{ {
unsigned char img[] = { static const unsigned char img[] = {
0xcd, 0xb7, /* in r28,__SP_L__ */ 0xcd, 0xb7, /* in r28,__SP_L__ */
0xde, 0xb7 /* in r29,__SP_H__ */ 0xde, 0xb7 /* in r29,__SP_H__ */
}; };
unsigned short insn1; unsigned short insn1;
if (memcmp (prologue + vpc, img, sizeof (img)) == 0) if (vpc + sizeof (img) < len
&& memcmp (prologue + vpc, img, sizeof (img)) == 0)
{ {
vpc += 4; vpc += 4;
scan_stage = 2; scan_stage = 2;
@ -679,21 +676,21 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
out __SREG__,__tmp_reg__ out __SREG__,__tmp_reg__
out __SP_L__,r28 */ out __SP_L__,r28 */
if (scan_stage == 2 && vpc < AVR_MAX_PROLOGUE_SIZE) if (scan_stage == 2 && vpc < len)
{ {
int locals_size = 0; int locals_size = 0;
unsigned char img[] = { static const unsigned char img[] = {
0x0f, 0xb6, /* in r0,0x3f */ 0x0f, 0xb6, /* in r0,0x3f */
0xf8, 0x94, /* cli */ 0xf8, 0x94, /* cli */
0xde, 0xbf, /* out 0x3e,r29 ; SPH */ 0xde, 0xbf, /* out 0x3e,r29 ; SPH */
0x0f, 0xbe, /* out 0x3f,r0 ; SREG */ 0x0f, 0xbe, /* out 0x3f,r0 ; SREG */
0xcd, 0xbf /* out 0x3d,r28 ; SPL */ 0xcd, 0xbf /* out 0x3d,r28 ; SPL */
}; };
unsigned char img_sig[] = { static const unsigned char img_sig[] = {
0xde, 0xbf, /* out 0x3e,r29 ; SPH */ 0xde, 0xbf, /* out 0x3e,r29 ; SPH */
0xcd, 0xbf /* out 0x3d,r28 ; SPL */ 0xcd, 0xbf /* out 0x3d,r28 ; SPL */
}; };
unsigned char img_int[] = { static const unsigned char img_int[] = {
0xf8, 0x94, /* cli */ 0xf8, 0x94, /* cli */
0xde, 0xbf, /* out 0x3e,r29 ; SPH */ 0xde, 0xbf, /* out 0x3e,r29 ; SPH */
0x78, 0x94, /* sei */ 0x78, 0x94, /* sei */
@ -712,21 +709,24 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
locals_size += ((insn & 0xf) | ((insn & 0xf00) >> 4) << 8); locals_size += ((insn & 0xf) | ((insn & 0xf00) >> 4) << 8);
} }
else else
return pc + vpc; return pc_beg + vpc;
/* Scan the last part of the prologue. May not be present for interrupt /* Scan the last part of the prologue. May not be present for interrupt
or signal handler functions, which is why we set the prologue type or signal handler functions, which is why we set the prologue type
when we saw the beginning of the prologue previously. */ when we saw the beginning of the prologue previously. */
if (memcmp (prologue + vpc, img_sig, sizeof (img_sig)) == 0) if (vpc + sizeof (img_sig) < len
&& memcmp (prologue + vpc, img_sig, sizeof (img_sig)) == 0)
{ {
vpc += sizeof (img_sig); vpc += sizeof (img_sig);
} }
else if (memcmp (prologue + vpc, img_int, sizeof (img_int)) == 0) else if (vpc + sizeof (img_int) < len
&& memcmp (prologue + vpc, img_int, sizeof (img_int)) == 0)
{ {
vpc += sizeof (img_int); vpc += sizeof (img_int);
} }
if (memcmp (prologue + vpc, img, sizeof (img)) == 0) if (vpc + sizeof (img) < len
&& memcmp (prologue + vpc, img, sizeof (img)) == 0)
{ {
info->prologue_type = AVR_PROLOGUE_NORMAL; info->prologue_type = AVR_PROLOGUE_NORMAL;
vpc += sizeof (img); vpc += sizeof (img);
@ -734,13 +734,24 @@ avr_scan_prologue (CORE_ADDR pc, struct avr_unwind_cache *info)
info->size += locals_size; info->size += locals_size;
return pc + avr_scan_arg_moves (vpc, prologue); /* Fall through. */
} }
/* If we got this far, we could not scan the prologue, so just return the pc /* If we got this far, we could not scan the prologue, so just return the pc
of the frame plus an adjustment for argument move insns. */ of the frame plus an adjustment for argument move insns. */
return pc + avr_scan_arg_moves (vpc, prologue);; for (; vpc < len; vpc += 2)
{
insn = EXTRACT_INSN (&prologue[vpc]);
if ((insn & 0xff00) == 0x0100) /* movw rXX, rYY */
continue;
else if ((insn & 0xfc00) == 0x2c00) /* mov rXX, rYY */
continue;
else
break;
}
return pc_beg + vpc;
} }
static CORE_ADDR static CORE_ADDR
@ -763,7 +774,7 @@ avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
prologue and possibly skip over moving arguments passed via registers prologue and possibly skip over moving arguments passed via registers
to other registers. */ to other registers. */
prologue_end = avr_scan_prologue (pc, &info); prologue_end = avr_scan_prologue (func_addr, func_end, &info);
if (info.prologue_type == AVR_PROLOGUE_NONE) if (info.prologue_type == AVR_PROLOGUE_NONE)
return pc; return pc;
@ -776,7 +787,7 @@ avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
} }
} }
/* Either we didn't find the start of this function (nothing we can do), /* Either we didn't find the start of this function (nothing we can do),
or there's no line info, or the line after the prologue is after or there's no line info, or the line after the prologue is after
the end of the function (there probably isn't a prologue). */ the end of the function (there probably isn't a prologue). */
@ -790,12 +801,12 @@ avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
static const unsigned char * static const unsigned char *
avr_breakpoint_from_pc (struct gdbarch *gdbarch, 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 }; static const unsigned char avr_break_insn [] = { 0x98, 0x95 };
*lenptr = sizeof (avr_break_insn); *lenptr = sizeof (avr_break_insn);
return avr_break_insn; return avr_break_insn;
} }
/* Given a return value in `regbuf' with a type `valtype', /* Given a return value in `regcache' with a type `type',
extract and copy its value into `valbuf'. extract and copy its value into `valbuf'.
Return values are always passed via registers r25:r24:... */ Return values are always passed via registers r25:r24:... */
@ -875,26 +886,28 @@ static struct avr_unwind_cache *
avr_frame_unwind_cache (struct frame_info *this_frame, avr_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache) void **this_prologue_cache)
{ {
CORE_ADDR pc; CORE_ADDR start_pc, current_pc;
ULONGEST prev_sp; ULONGEST prev_sp;
ULONGEST this_base; ULONGEST this_base;
struct avr_unwind_cache *info; struct avr_unwind_cache *info;
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
int i; int i;
if ((*this_prologue_cache)) if (*this_prologue_cache)
return (*this_prologue_cache); return *this_prologue_cache;
info = FRAME_OBSTACK_ZALLOC (struct avr_unwind_cache); info = FRAME_OBSTACK_ZALLOC (struct avr_unwind_cache);
(*this_prologue_cache) = info; *this_prologue_cache = info;
info->saved_regs = trad_frame_alloc_saved_regs (this_frame); info->saved_regs = trad_frame_alloc_saved_regs (this_frame);
info->size = 0; info->size = 0;
info->prologue_type = AVR_PROLOGUE_NONE; info->prologue_type = AVR_PROLOGUE_NONE;
pc = get_frame_func (this_frame); start_pc = get_frame_func (this_frame);
current_pc = get_frame_pc (this_frame);
if ((pc > 0) && (pc < get_frame_pc (this_frame))) if ((start_pc > 0) && (start_pc <= current_pc))
avr_scan_prologue (pc, info); avr_scan_prologue (start_pc, current_pc, info);
if ((info->prologue_type != AVR_PROLOGUE_NONE) if ((info->prologue_type != AVR_PROLOGUE_NONE)
&& (info->prologue_type != AVR_PROLOGUE_MAIN)) && (info->prologue_type != AVR_PROLOGUE_MAIN))
@ -905,7 +918,7 @@ avr_frame_unwind_cache (struct frame_info *this_frame,
was created. Get THIS frame's FP value by unwinding it from was created. Get THIS frame's FP value by unwinding it from
the next frame. */ the next frame. */
this_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM); this_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM);
high_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM+1); high_base = get_frame_register_unsigned (this_frame, AVR_FP_REGNUM + 1);
this_base += (high_base << 8); this_base += (high_base << 8);
/* The FP points at the last saved register. Adjust the FP back /* The FP points at the last saved register. Adjust the FP back
@ -922,29 +935,28 @@ avr_frame_unwind_cache (struct frame_info *this_frame,
/* Add 1 here to adjust for the post-decrement nature of the push /* Add 1 here to adjust for the post-decrement nature of the push
instruction.*/ instruction.*/
info->prev_sp = avr_make_saddr (prev_sp+1); info->prev_sp = avr_make_saddr (prev_sp + 1);
info->base = avr_make_saddr (this_base); info->base = avr_make_saddr (this_base);
gdbarch = get_frame_arch (this_frame);
/* Adjust all the saved registers so that they contain addresses and not /* Adjust all the saved registers so that they contain addresses and not
offsets. */ offsets. */
for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++) for (i = 0; i < gdbarch_num_regs (gdbarch) - 1; i++)
if (info->saved_regs[i].addr) if (info->saved_regs[i].addr > 0)
{ info->saved_regs[i].addr = info->prev_sp - info->saved_regs[i].addr;
info->saved_regs[i].addr = (info->prev_sp - info->saved_regs[i].addr);
}
/* Except for the main and startup code, the return PC is always saved on /* Except for the main and startup code, the return PC is always saved on
the stack and is at the base of the frame. */ the stack and is at the base of the frame. */
if (info->prologue_type != AVR_PROLOGUE_MAIN) if (info->prologue_type != AVR_PROLOGUE_MAIN)
{
info->saved_regs[AVR_PC_REGNUM].addr = info->prev_sp; info->saved_regs[AVR_PC_REGNUM].addr = info->prev_sp;
}
/* The previous frame's SP needed to be computed. Save the computed /* The previous frame's SP needed to be computed. Save the computed
value. */ value. */
trad_frame_set_value (info->saved_regs, AVR_SP_REGNUM, info->prev_sp+1); tdep = gdbarch_tdep (gdbarch);
trad_frame_set_value (info->saved_regs, AVR_SP_REGNUM,
info->prev_sp - 1 + tdep->call_length);
return info; return info;
} }
@ -1020,25 +1032,20 @@ avr_frame_prev_register (struct frame_info *this_frame,
And to confuse matters even more, the return address stored And to confuse matters even more, the return address stored
on the stack is in big endian byte order, even though most on the stack is in big endian byte order, even though most
everything else about the avr is little endian. Ick! */ 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; ULONGEST pc;
unsigned char tmp; int i;
unsigned char buf[2]; unsigned char buf[3];
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
read_memory (info->saved_regs[regnum].addr, buf, 2); read_memory (info->saved_regs[regnum].addr, buf, tdep->call_length);
/* Convert the PC read from memory as a big-endian to /* Extract the PC read from memory as a big-endian. */
little-endian order. */ pc = 0;
tmp = buf[0]; for (i = 0; i < tdep->call_length; i++)
buf[0] = buf[1]; pc = (pc << 8) | buf[i];
buf[1] = tmp;
pc = (extract_unsigned_integer (buf, 2) * 2); return frame_unwind_got_constant (this_frame, regnum, pc << 1);
return frame_unwind_got_constant (this_frame, regnum, pc);
} }
return frame_unwind_got_optimized (this_frame, regnum); return frame_unwind_got_optimized (this_frame, regnum);
@ -1220,7 +1227,7 @@ avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
{ {
sp -= si->len; sp -= si->len;
/* Add 1 to sp here to account for post decr nature of pushes. */ /* Add 1 to sp here to account for post decr nature of pushes. */
write_memory (sp+1, si->data, si->len); write_memory (sp + 1, si->data, si->len);
si = pop_stack_item (si); si = pop_stack_item (si);
} }
@ -1231,7 +1238,7 @@ avr_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
buf[1] = return_pc & 0xff; buf[1] = return_pc & 0xff;
sp -= 2; sp -= 2;
write_memory (sp+1, buf, 2); /* Add one since pushes are post decr ops. */ write_memory (sp + 1, buf, 2); /* Add one since pushes are post decr ops. */
/* Finally, update the SP register. */ /* Finally, update the SP register. */
regcache_cooked_write_unsigned (regcache, AVR_SP_REGNUM, regcache_cooked_write_unsigned (regcache, AVR_SP_REGNUM,
@ -1247,17 +1254,10 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{ {
struct gdbarch *gdbarch; struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep; struct gdbarch_tdep *tdep;
struct gdbarch_list *best_arch;
int call_length;
/* Find a candidate among the list of pre-declared architectures. */ /* Avr-6 call instructions save 3 bytes. */
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
return arches->gdbarch;
/* None found, create a new architecture from the information provided. */
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
/* If we ever need to differentiate the device types, do it here. */
switch (info.bfd_arch_info->mach) switch (info.bfd_arch_info->mach)
{ {
case bfd_mach_avr1: case bfd_mach_avr1:
@ -1265,9 +1265,29 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
case bfd_mach_avr3: case bfd_mach_avr3:
case bfd_mach_avr4: case bfd_mach_avr4:
case bfd_mach_avr5: case bfd_mach_avr5:
default:
call_length = 2;
break;
case bfd_mach_avr6:
call_length = 3;
break; break;
} }
/* If there is already a candidate, use it. */
for (best_arch = gdbarch_list_lookup_by_info (arches, &info);
best_arch != NULL;
best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info))
{
if (gdbarch_tdep (best_arch->gdbarch)->call_length == call_length)
return best_arch->gdbarch;
}
/* None found, create a new architecture from the information provided. */
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
tdep->call_length = call_length;
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT); set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_int_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_bit (gdbarch, 4 * TARGET_CHAR_BIT);