aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog4
-rw-r--r--gdb/mn10200-tdep.c207
2 files changed, 199 insertions, 12 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5e83a5e..1aa5fc8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
Wed May 14 08:58:55 1997 Jeffrey A Law (law@cygnus.com)
+ * mn10200-tdep.c (mn10200_analyze_prologue): Update prologue comments
+ to reflect current reality. Gross attempt at handling out of
+ line prologues.
+
* mn10200-tdep.c (mn10200_skip_prologue): Don't look at the debug
symbols to find the end of the prologue.
* mn10300-tdep.c (mn10300_skip_prologue): Likewise.
diff --git a/gdb/mn10200-tdep.c b/gdb/mn10200-tdep.c
index 11fade4..6300373 100644
--- a/gdb/mn10200-tdep.c
+++ b/gdb/mn10200-tdep.c
@@ -38,22 +38,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
mov sp,fp
add <size>,sp
Register saves for d2, d3, a1, a2 as needed. Saves start
- at fp - <size> and work towards higher addresses. Note
- that the saves are actually done off the stack pointer
- in the prologue! This makes for smaller code and easier
- prologue scanning as the displacement fields will never
+ at fp - <size> + <outgoing_args_size> and work towards higher
+ addresses. Note that the saves are actually done off the stack
+ pointer in the prologue! This makes for smaller code and easier
+ prologue scanning as the displacement fields will unlikely
be more than 8 bits!
Without frame pointer:
add <size>,sp
Register saves for d2, d3, a1, a2 as needed. Saves start
- at sp and work towards higher addresses.
+ at sp + <outgoing_args_size> and work towards higher addresses.
+ Out of line prologue:
+ add <local size>,sp -- optional
+ jsr __prologue
+ add <outgoing_size>,sp -- optional
+
+ The stack pointer remains constant throughout the life of most
+ functions. As a result the compiler will usually omit the
+ frame pointer, so we must handle frame pointerless functions. */
- One day we might keep the stack pointer constant, that won't
- change the code for prologues, but it will make the frame
- pointerless case much more common. */
-
/* Analyze the prologue to determine where registers are saved,
the end of the prologue, etc etc. Return the end of the prologue
scanned.
@@ -102,6 +106,7 @@ mn10200_analyze_prologue (fi, pc)
unsigned char buf[4];
int status;
char *name;
+ int out_of_line_prologue = 0;
/* Use the PC in the frame if it's provided to look up the
start of this function. */
@@ -302,10 +307,188 @@ mn10200_analyze_prologue (fi, pc)
return addr;
}
}
- else
+
+ /* Now see if we have a call to __prologue for an out of line
+ prologue. */
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ return addr;
+
+ /* First check for 16bit pc-relative call to __prologue. */
+ if (buf[0] == 0xfd)
{
- if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
- fi->frame = read_sp ();
+ CORE_ADDR temp;
+ status = target_read_memory (addr + 1, buf, 2);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Get the PC this instruction will branch to. */
+ temp = (extract_signed_integer (buf, 2) + addr) & 0xffffff;
+
+ /* Get the name of the function at the target address. */
+ status = find_pc_partial_function (temp, &name, NULL, NULL);
+ if (status == 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Note if it is an out of line prologue. */
+ out_of_line_prologue = (strcmp (name, "__prologue") == 0);
+
+ /* This sucks up 3 bytes of instruction space. */
+ if (out_of_line_prologue)
+ addr += 3;
+
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL)
+ {
+ fi->stack_size -= 16;
+ fi->frame = read_sp () - fi->stack_size;
+ }
+ return addr;
+ }
+ }
+ /* Now check for the 24bit pc-relative call to __prologue. */
+ else if (buf[0] == 0xf4 && buf[1] == 0xe1)
+ {
+ CORE_ADDR temp;
+ status = target_read_memory (addr + 2, buf, 3);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Get the PC this instruction will branch to. */
+ temp = (extract_signed_integer (buf, 3) + addr) & 0xffffff;
+
+ /* Get the name of the function at the target address. */
+ status = find_pc_partial_function (temp, &name, NULL, NULL);
+ if (status == 0)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ fi->frame = read_sp ();
+ return addr;
+ }
+
+ /* Note if it is an out of line prologue. */
+ out_of_line_prologue = (strcmp (name, "__prologue") == 0);
+
+ /* This sucks up 5 bytes of instruction space. */
+ if (out_of_line_prologue)
+ addr += 5;
+
+ if (addr >= stop)
+ {
+ if (fi && fi->next == NULL && (fi->status & MY_FRAME_IN_SP))
+ {
+ fi->stack_size -= 16;
+ fi->frame = read_sp () - fi->stack_size;
+ }
+ return addr;
+ }
+ }
+
+ /* Now actually handle the out of line prologue. */
+ if (out_of_line_prologue)
+ {
+ int outgoing_args_size = 0;
+
+ /* First adjust the stack size for this function. The out of
+ line prologue saves 4 registers (16bytes of data). */
+ if (fi)
+ fi->stack_size -= 16;
+
+ /* Update fi->frame if necessary. */
+ if (fi && fi->next == NULL)
+ fi->frame = read_sp () - fi->stack_size;
+
+ /* After the out of line prologue, there may be another
+ stack adjustment for the outgoing arguments.
+
+ Search for add imm8,a3 (0xd3XX)
+ or add imm16,a3 (0xf70bXXXX)
+ or add imm24,a3 (0xf467XXXXXX). */
+
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ {
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+
+ if (buf[0] == 0xd3)
+ {
+ outgoing_args_size = extract_signed_integer (&buf[1], 1);
+ addr += 2;
+ }
+ else if (buf[0] == 0xf7 && buf[1] == 0x0b)
+ {
+ status = target_read_memory (addr + 2, buf, 2);
+ if (status != 0)
+ {
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+ outgoing_args_size = extract_signed_integer (buf, 2);
+ addr += 4;
+ }
+ else if (buf[0] == 0xf4 && buf[1] == 0x67)
+ {
+ status = target_read_memory (addr + 2, buf, 3);
+ if (status != 0)
+ {
+ if (fi && fi->next == NULL)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ }
+ return addr;
+ }
+ outgoing_args_size = extract_signed_integer (buf, 3);
+ addr += 5;
+ }
+ else
+ outgoing_args_size = 0;
+
+ /* Now that we know the size of the outgoing arguments, fix
+ fi->frame again if this is the innermost frame. */
+ if (fi && fi->next == NULL)
+ fi->frame -= outgoing_args_size;
+
+ /* Note the register save information and update the stack
+ size for this frame too. */
+ if (fi)
+ {
+ fi->fsr.regs[2] = fi->frame + fi->stack_size + 4;
+ fi->fsr.regs[3] = fi->frame + fi->stack_size + 8;
+ fi->fsr.regs[5] = fi->frame + fi->stack_size + 12;
+ fi->fsr.regs[6] = fi->frame + fi->stack_size + 16;
+ fi->stack_size += outgoing_args_size;
+ }
+ /* There can be no more prologue insns, so return now. */
return addr;
}