* arm-tdep.c (arm_scan_prologue): Don't require "mov ip, sp"

to be the first instruction in the prologue.  Also, revise
	the way the frame offset is computed for frameless functions.
This commit is contained in:
Kevin Buettner
2001-12-20 21:56:56 +00:00
parent f079148d61
commit d4473757f1
2 changed files with 79 additions and 69 deletions

View File

@ -8,6 +8,10 @@
is no longer needed now that the frame info is being properly is no longer needed now that the frame info is being properly
initialized. initialized.
* arm-tdep.c (arm_scan_prologue): Don't require "mov ip, sp"
to be the first instruction in the prologue. Also, revise
the way the frame offset is computed for frameless functions.
2001-12-20 Michael Snyder <msnyder@redhat.com> 2001-12-20 Michael Snyder <msnyder@redhat.com>
* maint.c (maintenance_info_sections): Pass string argument to * maint.c (maintenance_info_sections): Pass string argument to

View File

@ -812,98 +812,104 @@ arm_scan_prologue (struct frame_info *fi)
traceback. traceback.
In the APCS, the prologue should start with "mov ip, sp" so In the APCS, the prologue should start with "mov ip, sp" so
if we don't see this as the first insn, we will stop. */ if we don't see this as the first insn, we will stop. [Note:
This doesn't seem to be true any longer, so it's now an optional
part of the prologue. - Kevin Buettner, 2001-11-20] */
sp_offset = fp_offset = 0; sp_offset = fp_offset = 0;
if (read_memory_unsigned_integer (prologue_start, 4) if (read_memory_unsigned_integer (prologue_start, 4)
== 0xe1a0c00d) /* mov ip, sp */ == 0xe1a0c00d) /* mov ip, sp */
current_pc = prologue_start + 4;
else
current_pc = prologue_start;
for (; current_pc < prologue_end; current_pc += 4)
{ {
for (current_pc = prologue_start + 4; current_pc < prologue_end; unsigned int insn = read_memory_unsigned_integer (current_pc, 4);
current_pc += 4)
if ((insn & 0xffff0000) == 0xe92d0000)
/* stmfd sp!, {..., fp, ip, lr, pc}
or
stmfd sp!, {a1, a2, a3, a4} */
{ {
unsigned int insn = read_memory_unsigned_integer (current_pc, 4); int mask = insn & 0xffff;
if ((insn & 0xffff0000) == 0xe92d0000) /* Calculate offsets of saved registers. */
/* stmfd sp!, {..., fp, ip, lr, pc} for (regno = PC_REGNUM; regno >= 0; regno--)
or if (mask & (1 << regno))
stmfd sp!, {a1, a2, a3, a4} */ {
{ sp_offset -= 4;
int mask = insn & 0xffff; fi->fsr.regs[regno] = sp_offset;
}
}
else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
{
unsigned imm = insn & 0xff; /* immediate value */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
fp_offset = -imm;
fi->framereg = FP_REGNUM;
}
else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */
{
unsigned imm = insn & 0xff; /* immediate value */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */
imm = (imm >> rot) | (imm << (32 - rot));
sp_offset -= imm;
}
else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
{
sp_offset -= 12;
regno = F0_REGNUM + ((insn >> 12) & 0x07);
fi->fsr.regs[regno] = sp_offset;
}
else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
{
int n_saved_fp_regs;
unsigned int fp_start_reg, fp_bound_reg;
/* Calculate offsets of saved registers. */ if ((insn & 0x800) == 0x800) /* N0 is set */
for (regno = PC_REGNUM; regno >= 0; regno--)
if (mask & (1 << regno))
{
sp_offset -= 4;
fi->fsr.regs[regno] = sp_offset;
}
}
else if ((insn & 0xfffff000) == 0xe24cb000) /* sub fp, ip #n */
{ {
unsigned imm = insn & 0xff; /* immediate value */ if ((insn & 0x40000) == 0x40000) /* N1 is set */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */ n_saved_fp_regs = 3;
imm = (imm >> rot) | (imm << (32 - rot)); else
fp_offset = -imm; n_saved_fp_regs = 1;
fi->framereg = FP_REGNUM;
} }
else if ((insn & 0xfffff000) == 0xe24dd000) /* sub sp, sp #n */ else
{ {
unsigned imm = insn & 0xff; /* immediate value */ if ((insn & 0x40000) == 0x40000) /* N1 is set */
unsigned rot = (insn & 0xf00) >> 7; /* rotate amount */ n_saved_fp_regs = 2;
imm = (imm >> rot) | (imm << (32 - rot)); else
sp_offset -= imm; n_saved_fp_regs = 4;
} }
else if ((insn & 0xffff7fff) == 0xed6d0103) /* stfe f?, [sp, -#c]! */
fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7);
fp_bound_reg = fp_start_reg + n_saved_fp_regs;
for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
{ {
sp_offset -= 12; sp_offset -= 12;
regno = F0_REGNUM + ((insn >> 12) & 0x07); fi->fsr.regs[fp_start_reg++] = sp_offset;
fi->fsr.regs[regno] = sp_offset;
} }
else if ((insn & 0xffbf0fff) == 0xec2d0200) /* sfmfd f0, 4, [sp!] */
{
int n_saved_fp_regs;
unsigned int fp_start_reg, fp_bound_reg;
if ((insn & 0x800) == 0x800) /* N0 is set */
{
if ((insn & 0x40000) == 0x40000) /* N1 is set */
n_saved_fp_regs = 3;
else
n_saved_fp_regs = 1;
}
else
{
if ((insn & 0x40000) == 0x40000) /* N1 is set */
n_saved_fp_regs = 2;
else
n_saved_fp_regs = 4;
}
fp_start_reg = F0_REGNUM + ((insn >> 12) & 0x7);
fp_bound_reg = fp_start_reg + n_saved_fp_regs;
for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
{
sp_offset -= 12;
fi->fsr.regs[fp_start_reg++] = sp_offset;
}
}
else if ((insn & 0xf0000000) != 0xe0000000)
break; /* Condition not true, exit early */
else if ((insn & 0xfe200000) == 0xe8200000) /* ldm? */
break; /* Don't scan past a block load */
else
/* The optimizer might shove anything into the prologue,
so we just skip what we don't recognize. */
continue;
} }
else if ((insn & 0xf0000000) != 0xe0000000)
break; /* Condition not true, exit early */
else if ((insn & 0xfe200000) == 0xe8200000) /* ldm? */
break; /* Don't scan past a block load */
else
/* The optimizer might shove anything into the prologue,
so we just skip what we don't recognize. */
continue;
} }
/* The frame size is just the negative of the offset (from the original SP) /* The frame size is just the negative of the offset (from the original SP)
of the last thing thing we pushed on the stack. The frame offset is of the last thing thing we pushed on the stack. The frame offset is
[new FP] - [new SP]. */ [new FP] - [new SP]. */
fi->framesize = -sp_offset; fi->framesize = -sp_offset;
fi->frameoffset = fp_offset - sp_offset; if (fi->framereg == FP_REGNUM)
fi->frameoffset = fp_offset - sp_offset;
else
fi->frameoffset = 0;
save_prologue_cache (fi); save_prologue_cache (fi);
} }