* mips-tdep.c (mips32_scan_prologue): Merge code from

mips32_skip_prologue.  Now return the address of the first
        instruction past the function prologue.
        (mips32_skip_prologue): Remove.  No longer necessary.
        (mips16_skip_prologue): Add parameter end_pc instead of
        computing it.
        (mips_skip_prologue): Compute the upper limit for the
        prologue scanning. Update call to mips16_skip_prologue.
        Replace call to mips32_skip_prologue by call to
        mips32_scan_prologue.
This commit is contained in:
Joel Brobecker 2004-10-14 22:34:25 +00:00
parent dfaf8edb15
commit 98b4dd9401
2 changed files with 89 additions and 107 deletions

View file

@ -1,3 +1,16 @@
2004-10-14 Joel Brobecker <brobecker@gnat.com>
* mips-tdep.c (mips32_scan_prologue): Merge code from
mips32_skip_prologue. Now return the address of the first
instruction past the function prologue.
(mips32_skip_prologue): Remove. No longer necessary.
(mips16_skip_prologue): Add parameter end_pc instead of
computing it.
(mips_skip_prologue): Compute the upper limit for the
prologue scanning. Update call to mips16_skip_prologue.
Replace call to mips32_skip_prologue by call to
mips32_scan_prologue.
2004-10-14 Mark Kettenis <kettenis@gnu.org>
* hppa-tdep.c (hppa_frame_cache): Add support for OpenBSD and

View file

@ -2419,9 +2419,10 @@ reset_saved_regs (struct mips_frame_cache *this_cache)
}
/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
the associated FRAME_CACHE if not null. */
the associated FRAME_CACHE if not null.
Return the address of the first instruction past the prologue. */
static void
static CORE_ADDR
mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR sp,
struct frame_info *next_frame,
struct mips_frame_cache *this_cache)
@ -2431,6 +2432,10 @@ mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR sp,
long frame_offset;
int frame_reg = MIPS_SP_REGNUM;
CORE_ADDR end_prologue_addr = 0;
int seen_sp_adjust = 0;
int load_immediate_bytes = 0;
restart:
frame_offset = 0;
@ -2458,6 +2463,7 @@ restart:
usually means that the stack cleanup code in the function
epilogue is reached. */
break;
seen_sp_adjust = 1;
}
else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
{
@ -2465,8 +2471,7 @@ restart:
}
else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
{
/* Irix 6.2 N32 ABI uses sd instructions for saving $gp and
$ra. */
/* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */
set_reg_offset (this_cache, reg, sp + low_word);
}
else if (high_word == 0x27be) /* addiu $30,$sp,size */
@ -2528,6 +2533,45 @@ restart:
{
set_reg_offset (this_cache, reg, frame_addr + low_word);
}
else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */
|| (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */
|| (inst & 0xFF9F07FF) == 0x00800021 /* move reg,$a0-$a3 */
|| high_word == 0x3c1c /* lui $gp,n */
|| high_word == 0x279c /* addiu $gp,$gp,n */
|| inst == 0x0399e021 /* addu $gp,$gp,$t9 */
|| inst == 0x033ce021 /* addu $gp,$t9,$gp */
)
{
/* These instructions are part of the prologue, but we don't
need to do anything special to handle them. */
}
/* The instructions below load $at or $t0 with an immediate
value in preparation for a stack adjustment via
subu $sp,$sp,[$at,$t0]. These instructions could also
initialize a local variable, so we accept them only before
a stack adjustment instruction was seen. */
else if (!seen_sp_adjust
&& (high_word == 0x3c01 /* lui $at,n */
|| high_word == 0x3c08 /* lui $t0,n */
|| high_word == 0x3421 /* ori $at,$at,n */
|| high_word == 0x3508 /* ori $t0,$t0,n */
|| high_word == 0x3401 /* ori $at,$zero,n */
|| high_word == 0x3408 /* ori $t0,$zero,n */
))
{
load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
}
else
{
/* This instruction is not an instruction typically found
in a prologue, so we must have reached the end of the
prologue. */
/* FIXME: brobecker/2004-10-10: Can't we just break out of this
loop now? Why would we need to continue scanning the function
instructions? */
if (end_prologue_addr == 0)
end_prologue_addr = cur_pc;
}
}
if (this_cache != NULL)
@ -2541,6 +2585,23 @@ restart:
this_cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
= this_cache->saved_regs[NUM_REGS + RA_REGNUM];
}
/* If we didn't reach the end of the prologue when scanning the function
instructions, then set end_prologue_addr to the address of the
instruction immediately after the last one we scanned. */
/* brobecker/2004-10-10: I don't think this would ever happen, but
we may as well be careful and do our best if we have a null
end_prologue_addr. */
if (end_prologue_addr == 0)
end_prologue_addr = cur_pc;
/* In a frameless function, we might have incorrectly
skipped some load immediate instructions. Undo the skipping
if the load immediate was not followed by a stack adjustment. */
if (load_immediate_bytes && !seen_sp_adjust)
end_prologue_addr -= load_immediate_bytes;
return end_prologue_addr;
}
static mips_extra_func_info_t
@ -4860,107 +4921,12 @@ mips_step_skips_delay (CORE_ADDR pc)
extract_unsigned_integer (buf, MIPS_INSTLEN));
}
/* Skip the PC past function prologue instructions (32-bit version).
This is a helper function for mips_skip_prologue. */
static CORE_ADDR
mips32_skip_prologue (CORE_ADDR pc)
{
t_inst inst;
CORE_ADDR end_pc;
int seen_sp_adjust = 0;
int load_immediate_bytes = 0;
/* Find an upper bound on the prologue. */
end_pc = skip_prologue_using_sal (pc);
if (end_pc == 0)
end_pc = pc + 100; /* Magic. */
/* Skip the typical prologue instructions. These are the stack adjustment
instruction and the instructions that save registers on the stack
or in the gcc frame. */
for (; pc < end_pc; pc += MIPS_INSTLEN)
{
unsigned long high_word;
inst = mips_fetch_instruction (pc);
high_word = (inst >> 16) & 0xffff;
if (high_word == 0x27bd /* addiu $sp,$sp,offset */
|| high_word == 0x67bd) /* daddiu $sp,$sp,offset */
seen_sp_adjust = 1;
else if (inst == 0x03a1e823 || /* subu $sp,$sp,$at */
inst == 0x03a8e823) /* subu $sp,$sp,$t0 */
seen_sp_adjust = 1;
else if (((inst & 0xFFE00000) == 0xAFA00000 /* sw reg,n($sp) */
|| (inst & 0xFFE00000) == 0xFFA00000) /* sd reg,n($sp) */
&& (inst & 0x001F0000)) /* reg != $zero */
continue;
else if ((inst & 0xFFE00000) == 0xE7A00000) /* swc1 freg,n($sp) */
continue;
else if ((inst & 0xF3E00000) == 0xA3C00000 && (inst & 0x001F0000))
/* sx reg,n($s8) */
continue; /* reg != $zero */
/* move $s8,$sp. With different versions of gas this will be either
`addu $s8,$sp,$zero' or `or $s8,$sp,$zero' or `daddu s8,sp,$0'.
Accept any one of these. */
else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
continue;
else if ((inst & 0xFF9F07FF) == 0x00800021) /* move reg,$a0-$a3 */
continue;
else if (high_word == 0x3c1c) /* lui $gp,n */
continue;
else if (high_word == 0x279c) /* addiu $gp,$gp,n */
continue;
else if (inst == 0x0399e021 /* addu $gp,$gp,$t9 */
|| inst == 0x033ce021) /* addu $gp,$t9,$gp */
continue;
/* The following instructions load $at or $t0 with an immediate
value in preparation for a stack adjustment via
subu $sp,$sp,[$at,$t0]. These instructions could also initialize
a local variable, so we accept them only before a stack adjustment
instruction was seen. */
else if (!seen_sp_adjust)
{
if (high_word == 0x3c01 || /* lui $at,n */
high_word == 0x3c08) /* lui $t0,n */
{
load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
continue;
}
else if (high_word == 0x3421 || /* ori $at,$at,n */
high_word == 0x3508 || /* ori $t0,$t0,n */
high_word == 0x3401 || /* ori $at,$zero,n */
high_word == 0x3408) /* ori $t0,$zero,n */
{
load_immediate_bytes += MIPS_INSTLEN; /* FIXME!! */
continue;
}
else
break;
}
else
break;
}
/* In a frameless function, we might have incorrectly
skipped some load immediate instructions. Undo the skipping
if the load immediate was not followed by a stack adjustment. */
if (load_immediate_bytes && !seen_sp_adjust)
pc -= load_immediate_bytes;
return pc;
}
/* Skip the PC past function prologue instructions (16-bit version).
This is a helper function for mips_skip_prologue. */
static CORE_ADDR
mips16_skip_prologue (CORE_ADDR pc)
mips16_skip_prologue (CORE_ADDR pc, CORE_ADDR end_pc)
{
CORE_ADDR end_pc;
int extend_bytes = 0;
int prev_extend_bytes;
@ -5009,11 +4975,6 @@ mips16_skip_prologue (CORE_ADDR pc)
0, 0} /* end of table marker */
};
/* Find an upper bound on the prologue. */
end_pc = skip_prologue_using_sal (pc);
if (end_pc == 0)
end_pc = pc + 100; /* Magic. */
/* Skip the typical prologue instructions. These are the stack adjustment
instruction and the instructions that save registers on the stack
or in the gcc frame. */
@ -5070,6 +5031,7 @@ mips_skip_prologue (CORE_ADDR pc)
is greater. */
CORE_ADDR post_prologue_pc = after_prologue (pc);
CORE_ADDR limit_pc;
if (post_prologue_pc != 0)
return max (pc, post_prologue_pc);
@ -5077,10 +5039,17 @@ mips_skip_prologue (CORE_ADDR pc)
/* Can't determine prologue from the symbol table, need to examine
instructions. */
/* Find an upper limit on the function prologue using the debug
information. If the debug information could not be used to provide
that bound, then use an arbitrary large number as the upper bound. */
limit_pc = skip_prologue_using_sal (pc);
if (limit_pc == 0)
limit_pc = pc + 100; /* Magic. */
if (pc_is_mips16 (pc))
return mips16_skip_prologue (pc);
return mips16_skip_prologue (pc, limit_pc);
else
return mips32_skip_prologue (pc);
return mips32_scan_prologue (pc, limit_pc, 0, NULL, NULL);
}
/* Root of all "set mips "/"show mips " commands. This will eventually be