frame_offset = 0;
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN32_SIZE)
{
- unsigned long inst, high_word, low_word;
+ unsigned long inst, high_word;
+ long offset;
int reg;
this_non_prologue_insn = 0;
/* Save some code by pre-extracting some useful fields. */
high_word = (inst >> 16) & 0xffff;
- low_word = inst & 0xffff;
+ offset = ((inst & 0xffff) ^ 0x8000) - 0x8000;
reg = high_word & 0x1f;
if (high_word == 0x27bd /* addiu $sp,$sp,-i */
|| high_word == 0x23bd /* addi $sp,$sp,-i */
|| high_word == 0x67bd) /* daddiu $sp,$sp,-i */
{
- if (low_word & 0x8000) /* Negative stack adjustment? */
- frame_offset += 0x10000 - low_word;
+ if (offset < 0) /* Negative stack adjustment? */
+ frame_offset -= offset;
else
/* Exit loop if a positive stack adjustment is found, which
usually means that the stack cleanup code in the function
else if (((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
&& !regsize_is_64_bits)
{
- set_reg_offset (gdbarch, this_cache, reg, sp + low_word);
+ set_reg_offset (gdbarch, this_cache, reg, sp + offset);
}
else if (((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
&& regsize_is_64_bits)
{
/* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */
- set_reg_offset (gdbarch, this_cache, reg, sp + low_word);
+ set_reg_offset (gdbarch, this_cache, reg, sp + offset);
}
else if (high_word == 0x27be) /* addiu $30,$sp,size */
{
/* Old gcc frame, r30 is virtual frame pointer. */
- if ((long) low_word != frame_offset)
- frame_addr = sp + low_word;
+ if (offset != frame_offset)
+ frame_addr = sp + offset;
else if (this_frame && frame_reg == MIPS_SP_REGNUM)
{
unsigned alloca_adjust;
(this_frame, gdbarch_num_regs (gdbarch) + 30);
frame_offset = 0;
- alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
+ alloca_adjust = (unsigned) (frame_addr - (sp + offset));
if (alloca_adjust > 0)
{
/* FP > SP + frame_size. This may be because of
else if ((high_word & 0xFFE0) == 0xafc0 /* sw reg,offset($30) */
&& !regsize_is_64_bits)
{
- set_reg_offset (gdbarch, this_cache, reg, frame_addr + low_word);
+ set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset);
}
else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */
|| (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */