mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-08-06 14:49:38 +08:00
* avr-tdep.c (avr_scan_prologue): Update comment describing the various
prologue types. Properly scan prologues generated by gcc with the -mcall-prologues option. Add code to scan -mcall-prologues for mega devices.
This commit is contained in:
@ -1,3 +1,11 @@
|
|||||||
|
2003-06-15 Theodore A. Roth <troth@openavr.org>
|
||||||
|
|
||||||
|
* avr-tdep.c (avr_scan_prologue): Update comment describing the various
|
||||||
|
prologue types.
|
||||||
|
Properly scan prologues generated by gcc with the -mcall-prologues
|
||||||
|
option.
|
||||||
|
Add code to scan -mcall-prologues for mega devices.
|
||||||
|
|
||||||
2003-06-15 Theodore A. Roth <troth@openavr.org>
|
2003-06-15 Theodore A. Roth <troth@openavr.org>
|
||||||
|
|
||||||
* avr-tdep.c (avr_register_byte): Delete function.
|
* avr-tdep.c (avr_register_byte): Delete function.
|
||||||
|
151
gdb/avr-tdep.c
151
gdb/avr-tdep.c
@ -359,26 +359,81 @@ avr_read_fp (void)
|
|||||||
3) the offsets of saved regs
|
3) the offsets of saved regs
|
||||||
This information is stored in the "extra_info" field of the frame_info.
|
This information is stored in the "extra_info" field of the frame_info.
|
||||||
|
|
||||||
A typical AVR function prologue might look like this:
|
Some devices lack the sbiw instruction, so on those replace this:
|
||||||
push rXX
|
sbiw r28, XX
|
||||||
push r28
|
with this:
|
||||||
push r29
|
subi r28,lo8(XX)
|
||||||
in r28,__SP_L__
|
sbci r29,hi8(XX)
|
||||||
in r29,__SP_H__
|
|
||||||
sbiw r28,<LOCALS_SIZE>
|
|
||||||
in __tmp_reg__,__SREG__
|
|
||||||
cli
|
|
||||||
out __SP_L__,r28
|
|
||||||
out __SREG__,__tmp_reg__
|
|
||||||
out __SP_H__,r29
|
|
||||||
|
|
||||||
A `-mcall-prologues' prologue look like this:
|
A typical AVR function prologue with a frame pointer might look like this:
|
||||||
ldi r26,<LOCALS_SIZE>
|
push rXX ; saved regs
|
||||||
ldi r27,<LOCALS_SIZE>/265
|
...
|
||||||
ldi r30,pm_lo8(.L_foo_body)
|
push r28
|
||||||
ldi r31,pm_hi8(.L_foo_body)
|
push r29
|
||||||
rjmp __prologue_saves__+RRR
|
in r28,__SP_L__
|
||||||
.L_foo_body: */
|
in r29,__SP_H__
|
||||||
|
sbiw r28,<LOCALS_SIZE>
|
||||||
|
in __tmp_reg__,__SREG__
|
||||||
|
cli
|
||||||
|
out __SP_L__,r28
|
||||||
|
out __SREG__,__tmp_reg__
|
||||||
|
out __SP_H__,r29
|
||||||
|
|
||||||
|
A typical AVR function prologue without a frame pointer might look like
|
||||||
|
this:
|
||||||
|
push rXX ; saved regs
|
||||||
|
...
|
||||||
|
|
||||||
|
A main function prologue looks like this:
|
||||||
|
ldi r28,lo8(<RAM_ADDR> - <LOCALS_SIZE>)
|
||||||
|
ldi r29,hi8(<RAM_ADDR> - <LOCALS_SIZE>)
|
||||||
|
out __SP_H__,r29
|
||||||
|
out __SP_L__,r28
|
||||||
|
|
||||||
|
A signal handler prologue looks like this:
|
||||||
|
push __zero_reg__
|
||||||
|
push __tmp_reg__
|
||||||
|
in __tmp_reg__, __SREG__
|
||||||
|
push __tmp_reg__
|
||||||
|
clr __zero_reg__
|
||||||
|
push rXX ; save registers r18:r27, r30:r31
|
||||||
|
...
|
||||||
|
push r28 ; save frame pointer
|
||||||
|
push r29
|
||||||
|
in r28, __SP_L__
|
||||||
|
in r29, __SP_H__
|
||||||
|
sbiw r28, <LOCALS_SIZE>
|
||||||
|
out __SP_H__, r29
|
||||||
|
out __SP_L__, r28
|
||||||
|
|
||||||
|
A interrupt handler prologue looks like this:
|
||||||
|
sei
|
||||||
|
push __zero_reg__
|
||||||
|
push __tmp_reg__
|
||||||
|
in __tmp_reg__, __SREG__
|
||||||
|
push __tmp_reg__
|
||||||
|
clr __zero_reg__
|
||||||
|
push rXX ; save registers r18:r27, r30:r31
|
||||||
|
...
|
||||||
|
push r28 ; save frame pointer
|
||||||
|
push r29
|
||||||
|
in r28, __SP_L__
|
||||||
|
in r29, __SP_H__
|
||||||
|
sbiw r28, <LOCALS_SIZE>
|
||||||
|
cli
|
||||||
|
out __SP_H__, r29
|
||||||
|
sei
|
||||||
|
out __SP_L__, r28
|
||||||
|
|
||||||
|
A `-mcall-prologues' prologue looks like this (Note that the megas use a
|
||||||
|
jmp instead of a rjmp, thus the prologue is one word larger since jmp is a
|
||||||
|
32 bit insn and rjmp is a 16 bit insn):
|
||||||
|
ldi r26,lo8(<LOCALS_SIZE>)
|
||||||
|
ldi r27,hi8(<LOCALS_SIZE>)
|
||||||
|
ldi r30,pm_lo8(.L_foo_body)
|
||||||
|
ldi r31,pm_hi8(.L_foo_body)
|
||||||
|
rjmp __prologue_saves__+RRR
|
||||||
|
.L_foo_body: */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
avr_scan_prologue (struct frame_info *fi)
|
avr_scan_prologue (struct frame_info *fi)
|
||||||
@ -457,10 +512,9 @@ avr_scan_prologue (struct frame_info *fi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scanning `-mcall-prologues' prologue
|
/* Scanning `-mcall-prologues' prologue */
|
||||||
FIXME: mega prologue have a 12 bytes long */
|
|
||||||
|
|
||||||
while (prologue_len <= 12) /* I'm use while to avoit many goto's */
|
while (1) /* Using a while to avoid many goto's */
|
||||||
{
|
{
|
||||||
int loc_size;
|
int loc_size;
|
||||||
int body_addr;
|
int body_addr;
|
||||||
@ -490,9 +544,6 @@ avr_scan_prologue (struct frame_info *fi)
|
|||||||
break;
|
break;
|
||||||
body_addr |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
|
body_addr |= ((insn & 0xf) | ((insn & 0x0f00) >> 4)) << 8;
|
||||||
|
|
||||||
if (body_addr != (prologue_start + 10) / 2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
msymbol = lookup_minimal_symbol ("__prologue_saves__", NULL, NULL);
|
msymbol = lookup_minimal_symbol ("__prologue_saves__", NULL, NULL);
|
||||||
if (!msymbol)
|
if (!msymbol)
|
||||||
break;
|
break;
|
||||||
@ -500,15 +551,33 @@ avr_scan_prologue (struct frame_info *fi)
|
|||||||
/* FIXME: prologue for mega have a JMP instead of RJMP */
|
/* FIXME: prologue for mega have a JMP instead of RJMP */
|
||||||
insn = EXTRACT_INSN (&prologue[vpc + 8]);
|
insn = EXTRACT_INSN (&prologue[vpc + 8]);
|
||||||
/* rjmp __prologue_saves__+RRR */
|
/* rjmp __prologue_saves__+RRR */
|
||||||
if ((insn & 0xf000) != 0xc000)
|
if ((insn & 0xf000) == 0xc000)
|
||||||
break;
|
{
|
||||||
|
/* Extract PC relative offset from RJMP */
|
||||||
|
i = (insn & 0xfff) | (insn & 0x800 ? (-1 ^ 0xfff) : 0);
|
||||||
|
/* Convert offset to byte addressable mode */
|
||||||
|
i *= 2;
|
||||||
|
/* Destination address */
|
||||||
|
i += prologue_start + 10;
|
||||||
|
|
||||||
|
if (body_addr != (prologue_start + 10) / 2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* jmp __prologue_saves__+RRR */
|
||||||
|
else if ((insn & 0xfe0e) == 0x940c)
|
||||||
|
{
|
||||||
|
/* Extract absolute PC address from JMP */
|
||||||
|
i = (((insn & 0x1) | ((insn & 0x1f0) >> 3) << 16)
|
||||||
|
| (EXTRACT_INSN (&prologue[vpc + 10]) & 0xffff));
|
||||||
|
/* Convert address to byte addressable mode */
|
||||||
|
i *= 2;
|
||||||
|
|
||||||
|
if (body_addr != (prologue_start + 12)/2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
/* Extract PC relative offset from RJMP */
|
|
||||||
i = (insn & 0xfff) | (insn & 0x800 ? (-1 ^ 0xfff) : 0);
|
|
||||||
/* Convert offset to byte addressable mode */
|
|
||||||
i *= 2;
|
|
||||||
/* Destination address */
|
|
||||||
i += vpc + prologue_start + 10;
|
|
||||||
/* Resovle offset (in words) from __prologue_saves__ symbol.
|
/* Resovle offset (in words) from __prologue_saves__ symbol.
|
||||||
Which is a pushes count in `-mcall-prologues' mode */
|
Which is a pushes count in `-mcall-prologues' mode */
|
||||||
num_pushes = AVR_MAX_PUSHES - (i - SYMBOL_VALUE_ADDRESS (msymbol)) / 2;
|
num_pushes = AVR_MAX_PUSHES - (i - SYMBOL_VALUE_ADDRESS (msymbol)) / 2;
|
||||||
@ -606,9 +675,9 @@ avr_scan_prologue (struct frame_info *fi)
|
|||||||
sbci r29,hi8(XX)
|
sbci r29,hi8(XX)
|
||||||
in __tmp_reg__,__SREG__
|
in __tmp_reg__,__SREG__
|
||||||
cli
|
cli
|
||||||
out __SP_L__,r28
|
out __SP_H__,r29
|
||||||
out __SREG__,__tmp_reg__
|
out __SREG__,__tmp_reg__
|
||||||
out __SP_H__,r29 */
|
out __SP_L__,r28 */
|
||||||
|
|
||||||
if (scan_stage == 2 && vpc + 12 <= prologue_len)
|
if (scan_stage == 2 && vpc + 12 <= prologue_len)
|
||||||
{
|
{
|
||||||
@ -616,19 +685,19 @@ avr_scan_prologue (struct frame_info *fi)
|
|||||||
unsigned char img[] = {
|
unsigned char img[] = {
|
||||||
0x0f, 0xb6, /* in r0,0x3f */
|
0x0f, 0xb6, /* in r0,0x3f */
|
||||||
0xf8, 0x94, /* cli */
|
0xf8, 0x94, /* cli */
|
||||||
0xcd, 0xbf, /* out 0x3d,r28 ; SPL */
|
0xde, 0xbf, /* out 0x3e,r29 ; SPH */
|
||||||
0x0f, 0xbe, /* out 0x3f,r0 ; SREG */
|
0x0f, 0xbe, /* out 0x3f,r0 ; SREG */
|
||||||
0xde, 0xbf /* out 0x3e,r29 ; SPH */
|
0xcd, 0xbf /* out 0x3d,r28 ; SPL */
|
||||||
};
|
};
|
||||||
unsigned char img_sig[] = {
|
unsigned char img_sig[] = {
|
||||||
0xcd, 0xbf, /* out 0x3d,r28 ; SPL */
|
0xde, 0xbf, /* out 0x3e,r29 ; SPH */
|
||||||
0xde, 0xbf /* out 0x3e,r29 ; SPH */
|
0xcd, 0xbf /* out 0x3d,r28 ; SPL */
|
||||||
};
|
};
|
||||||
unsigned char img_int[] = {
|
unsigned char img_int[] = {
|
||||||
0xf8, 0x94, /* cli */
|
0xf8, 0x94, /* cli */
|
||||||
0xcd, 0xbf, /* out 0x3d,r28 ; SPL */
|
0xde, 0xbf, /* out 0x3e,r29 ; SPH */
|
||||||
0x78, 0x94, /* sei */
|
0x78, 0x94, /* sei */
|
||||||
0xde, 0xbf /* out 0x3e,r29 ; SPH */
|
0xcd, 0xbf /* out 0x3d,r28 ; SPL */
|
||||||
};
|
};
|
||||||
|
|
||||||
insn = EXTRACT_INSN (&prologue[vpc]);
|
insn = EXTRACT_INSN (&prologue[vpc]);
|
||||||
|
Reference in New Issue
Block a user