mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-27 06:17:47 +08:00
* mips-tdep.c (mips16_scan_prologue): Handle the MIPS16e SAVE
instruction.
This commit is contained in:
@ -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>
|
2007-11-20 Vladimir Prus <vladimir@codesourcery.com>
|
||||||
|
|
||||||
* infrun.c (resume): Clarify logic that
|
* 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 short prev_inst = 0; /* saved copy of previous instruction */
|
||||||
unsigned inst = 0; /* current instruction */
|
unsigned inst = 0; /* current instruction */
|
||||||
unsigned entry_inst = 0; /* the entry instruction */
|
unsigned entry_inst = 0; /* the entry instruction */
|
||||||
|
unsigned save_inst = 0; /* the save instruction */
|
||||||
int reg, offset;
|
int reg, offset;
|
||||||
|
|
||||||
int extend_bytes = 0;
|
int extend_bytes = 0;
|
||||||
@ -1603,6 +1604,12 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
|
|||||||
else if ((inst & 0xf81f) == 0xe809
|
else if ((inst & 0xf81f) == 0xe809
|
||||||
&& (inst & 0x700) != 0x700) /* entry */
|
&& (inst & 0x700) != 0x700) /* entry */
|
||||||
entry_inst = inst; /* save for later processing */
|
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) */
|
else if ((inst & 0xf800) == 0x1800) /* jal(x) */
|
||||||
cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
|
cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
|
||||||
else if ((inst & 0xff1c) == 0x6704) /* move reg,$a0-$a3 */
|
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)
|
if (this_cache != NULL)
|
||||||
{
|
{
|
||||||
this_cache->base =
|
this_cache->base =
|
||||||
|
Reference in New Issue
Block a user