mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-01 14:03:56 +08:00
* mips-tdep.c (mips16_scan_prologue): Handle the MIPS16e SAVE
instruction.
This commit is contained in:
parent
cd76b0b7c4
commit
2207132da4
@ -1,3 +1,9 @@
|
||||
2007-11-20 David Ung <davidu@mips.com>
|
||||
Maciej W. Rozycki <macro@mips.com>
|
||||
|
||||
* mips-tdep.c (mips16_scan_prologue): Handle the MIPS16e SAVE
|
||||
instruction.
|
||||
|
||||
2007-11-20 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
* infrun.c (resume): Clarify logic that
|
||||
|
102
gdb/mips-tdep.c
102
gdb/mips-tdep.c
@ -1500,6 +1500,7 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
|
||||
unsigned short prev_inst = 0; /* saved copy of previous instruction */
|
||||
unsigned inst = 0; /* current instruction */
|
||||
unsigned entry_inst = 0; /* the entry instruction */
|
||||
unsigned save_inst = 0; /* the save instruction */
|
||||
int reg, offset;
|
||||
|
||||
int extend_bytes = 0;
|
||||
@ -1603,6 +1604,12 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
|
||||
else if ((inst & 0xf81f) == 0xe809
|
||||
&& (inst & 0x700) != 0x700) /* entry */
|
||||
entry_inst = inst; /* save for later processing */
|
||||
else if ((inst & 0xff80) == 0x6480) /* save */
|
||||
{
|
||||
save_inst = inst; /* save for later processing */
|
||||
if (prev_extend_bytes) /* extend */
|
||||
save_inst |= prev_inst << 16;
|
||||
}
|
||||
else if ((inst & 0xf800) == 0x1800) /* jal(x) */
|
||||
cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
|
||||
else if ((inst & 0xff1c) == 0x6704) /* move reg,$a0-$a3 */
|
||||
@ -1661,6 +1668,101 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
|
||||
}
|
||||
}
|
||||
|
||||
/* The SAVE instruction is similar to ENTRY, except that defined by the
|
||||
MIPS16e ASE of the MIPS Architecture. Unlike with ENTRY though, the
|
||||
size of the frame is specified as an immediate field of instruction
|
||||
and an extended variation exists which lets additional registers and
|
||||
frame space to be specified. The instruction always treats registers
|
||||
as 32-bit so its usefulness for 64-bit ABIs is questionable. */
|
||||
if (save_inst != 0 && mips_abi_regsize (gdbarch) == 4)
|
||||
{
|
||||
static int args_table[16] = {
|
||||
0, 0, 0, 0, 1, 1, 1, 1,
|
||||
2, 2, 2, 0, 3, 3, 4, -1,
|
||||
};
|
||||
static int astatic_table[16] = {
|
||||
0, 1, 2, 3, 0, 1, 2, 3,
|
||||
0, 1, 2, 4, 0, 1, 0, -1,
|
||||
};
|
||||
int aregs = (save_inst >> 16) & 0xf;
|
||||
int xsregs = (save_inst >> 24) & 0x7;
|
||||
int args = args_table[aregs];
|
||||
int astatic = astatic_table[aregs];
|
||||
long frame_size;
|
||||
|
||||
if (args < 0)
|
||||
{
|
||||
warning (_("Invalid number of argument registers encoded in SAVE."));
|
||||
args = 0;
|
||||
}
|
||||
if (astatic < 0)
|
||||
{
|
||||
warning (_("Invalid number of static registers encoded in SAVE."));
|
||||
astatic = 0;
|
||||
}
|
||||
|
||||
/* For standard SAVE the frame size of 0 means 128. */
|
||||
frame_size = ((save_inst >> 16) & 0xf0) | (save_inst & 0xf);
|
||||
if (frame_size == 0 && (save_inst >> 16) == 0)
|
||||
frame_size = 16;
|
||||
frame_size *= 8;
|
||||
frame_offset += frame_size;
|
||||
|
||||
/* Now we can calculate what the SP must have been at the
|
||||
start of the function prologue. */
|
||||
sp += frame_offset;
|
||||
|
||||
/* Check if A0-A3 were saved in the caller's argument save area. */
|
||||
for (reg = MIPS_A0_REGNUM, offset = 0; reg < args + 4; reg++)
|
||||
{
|
||||
set_reg_offset (this_cache, reg, sp + offset);
|
||||
offset += mips_abi_regsize (gdbarch);
|
||||
}
|
||||
|
||||
offset = -4;
|
||||
|
||||
/* Check if the RA register was pushed on the stack. */
|
||||
if (save_inst & 0x40)
|
||||
{
|
||||
set_reg_offset (this_cache, MIPS_RA_REGNUM, sp + offset);
|
||||
offset -= mips_abi_regsize (gdbarch);
|
||||
}
|
||||
|
||||
/* Check if the S8 register was pushed on the stack. */
|
||||
if (xsregs > 6)
|
||||
{
|
||||
set_reg_offset (this_cache, 30, sp + offset);
|
||||
offset -= mips_abi_regsize (gdbarch);
|
||||
xsregs--;
|
||||
}
|
||||
/* Check if S2-S7 were pushed on the stack. */
|
||||
for (reg = 18 + xsregs - 1; reg > 18 - 1; reg--)
|
||||
{
|
||||
set_reg_offset (this_cache, reg, sp + offset);
|
||||
offset -= mips_abi_regsize (gdbarch);
|
||||
}
|
||||
|
||||
/* Check if the S1 register was pushed on the stack. */
|
||||
if (save_inst & 0x10)
|
||||
{
|
||||
set_reg_offset (this_cache, 17, sp + offset);
|
||||
offset -= mips_abi_regsize (gdbarch);
|
||||
}
|
||||
/* Check if the S0 register was pushed on the stack. */
|
||||
if (save_inst & 0x20)
|
||||
{
|
||||
set_reg_offset (this_cache, 16, sp + offset);
|
||||
offset -= mips_abi_regsize (gdbarch);
|
||||
}
|
||||
|
||||
/* Check if A0-A3 were pushed on the stack. */
|
||||
for (reg = MIPS_A0_REGNUM + 3; reg > MIPS_A0_REGNUM + 3 - astatic; reg--)
|
||||
{
|
||||
set_reg_offset (this_cache, reg, sp + offset);
|
||||
offset -= mips_abi_regsize (gdbarch);
|
||||
}
|
||||
}
|
||||
|
||||
if (this_cache != NULL)
|
||||
{
|
||||
this_cache->base =
|
||||
|
Loading…
Reference in New Issue
Block a user