* infrun.c (wait_for_inferior): Mark registers as invalid when
stepping over an instruction that triggered a watchpoint. * remote-mips.c: Numerous changes to support hardware breakpoints and watchpoints on LSI MiniRISC and TinyRISC boards. * mips-tdep.c: Move MIPS16-related macros to config/mips/tm-mips.h. (mips_breakpoint_from_pc): Account for different breakpoint instructions used by PMON and IDT monitor. * config/mips/tm-embed.h: Enable hardware breakpoints on embedded MIPS targets. * config/mips/tm-mips.h: Define breakpoint instructions for PMON and IDT monitor. Move MIPS16-related macros here from mips-tdep.c.
This commit is contained in:
parent
77f3ac77b5
commit
f781fe93a6
5 changed files with 862 additions and 446 deletions
|
@ -1,3 +1,18 @@
|
|||
Mon Jun 16 18:38:28 1997 Mark Alexander <marka@cygnus.com>
|
||||
|
||||
* infrun.c (wait_for_inferior): Mark registers as invalid when
|
||||
stepping over an instruction that triggered a watchpoint.
|
||||
* remote-mips.c: Numerous changes to support hardware breakpoints
|
||||
and watchpoints on LSI MiniRISC and TinyRISC boards.
|
||||
* mips-tdep.c: Move MIPS16-related macros to config/mips/tm-mips.h.
|
||||
(mips_breakpoint_from_pc): Account for different breakpoint
|
||||
instructions used by PMON and IDT monitor.
|
||||
* config/mips/tm-embed.h: Enable hardware breakpoints on embedded
|
||||
MIPS targets.
|
||||
* config/mips/tm-mips.h: Define breakpoint instructions for
|
||||
PMON and IDT monitor. Move MIPS16-related macros here from
|
||||
mips-tdep.c.
|
||||
|
||||
Fri Jun 13 13:44:47 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
|
||||
|
||||
* config/mips/tm-tx39[l].h, tx39[l].mt: change r3900 target to tx39.
|
||||
|
|
|
@ -23,6 +23,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
#undef DEFAULT_MIPS_TYPE
|
||||
#define DEFAULT_MIPS_TYPE "r3051"
|
||||
|
||||
/* Watchpoint support */
|
||||
|
||||
#define TARGET_HAS_HARDWARE_WATCHPOINTS
|
||||
|
||||
/* Use these macros for watchpoint insertion/deletion. */
|
||||
/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
|
||||
|
||||
#define target_insert_watchpoint(addr, len, type) \
|
||||
remote_mips_set_watchpoint (addr, len, type)
|
||||
int remote_mips_set_watchpoint PARAMS ((CORE_ADDR addr, int len, int type));
|
||||
|
||||
#define target_remove_watchpoint(addr, len, type) \
|
||||
remote_mips_remove_watchpoint (addr, len, type)
|
||||
int remote_mips_remove_watchpoint PARAMS ((CORE_ADDR addr, int len, int type));
|
||||
|
||||
/* We need to remove watchpoints when stepping, else we hit them again! */
|
||||
|
||||
#define HAVE_NONSTEPPABLE_WATCHPOINT
|
||||
|
||||
#define STOPPED_BY_WATCHPOINT(w) remote_mips_stopped_by_watchpoint ()
|
||||
|
||||
/* start-sanitize-gm */
|
||||
#ifdef GENERAL_MAGIC
|
||||
|
||||
|
@ -32,29 +53,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
||||
#undef GET_LONGJMP_TARGET
|
||||
|
||||
/* Watchpoint support */
|
||||
|
||||
#define TARGET_HAS_HARDWARE_WATCHPOINTS
|
||||
|
||||
#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
|
||||
(1 == 1) /* We allow all types of hardware watchpoints */
|
||||
|
||||
/* Use these macros for watchpoint insertion/deletion. */
|
||||
/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */
|
||||
|
||||
#define target_insert_watchpoint(addr, len, type) \
|
||||
remote_mips_set_watchpoint (addr, len, type)
|
||||
|
||||
#define target_remove_watchpoint(addr, len, type) \
|
||||
remote_mips_remove_watchpoint (addr, len, type)
|
||||
|
||||
/* We need to remove watchpoints when stepping, else we hit them again! */
|
||||
|
||||
#define HAVE_NONSTEPPABLE_WATCHPOINT
|
||||
|
||||
#define STOPPED_BY_WATCHPOINT(w) remote_mips_stopped_by_watchpoint ()
|
||||
|
||||
#define FLUSH_CACHED_MEMORY() flush_cached_memory()
|
||||
|
||||
#else
|
||||
/* end-sanitize-gm */
|
||||
|
||||
#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
|
||||
remote_mips_can_use_hardware_watchpoint(cnt)
|
||||
int remote_mips_can_use_hardware_watchpoint PARAMS ((int cnt));
|
||||
|
||||
/* start-sanitize-gm */
|
||||
#endif /* GENERAL_MAGIC */
|
||||
/* end-sanitize-gm */
|
||||
|
|
|
@ -115,10 +115,16 @@ extern int in_sigtramp PARAMS ((CORE_ADDR, char *));
|
|||
|
||||
#define BIG_ENDIAN 4321
|
||||
|
||||
/* Old-style breakpoint macros. */
|
||||
/* Old-style breakpoint macros.
|
||||
The IDT board uses an unusual breakpoint value, and sometimes gets
|
||||
confused when it sees the usual MIPS breakpoint instruction. */
|
||||
|
||||
#define BIG_BREAKPOINT {0, 0x5, 0, 0xd}
|
||||
#define LITTLE_BREAKPOINT {0xd, 0, 0x5, 0}
|
||||
#define PMON_BIG_BREAKPOINT {0, 0, 0, 0xd}
|
||||
#define PMON_LITTLE_BREAKPOINT {0xd, 0, 0, 0}
|
||||
#define IDT_BIG_BREAKPOINT {0, 0, 0x0a, 0xd}
|
||||
#define IDT_LITTLE_BREAKPOINT {0xd, 0x0a, 0, 0}
|
||||
#define MIPS16_BIG_BREAKPOINT {0xe8, 0xa5}
|
||||
#define MIPS16_LITTLE_BREAKPOINT {0xa5, 0xe8}
|
||||
|
||||
|
@ -519,4 +525,16 @@ extern int mips_ignore_helper PARAMS ((CORE_ADDR pc));
|
|||
#define TARGET_MIPS
|
||||
#endif
|
||||
|
||||
/* Definitions and declarations used by mips-tdep.c and remote-mips.c */
|
||||
#define MIPS_INSTLEN 4 /* Length of an instruction */
|
||||
#define MIPS16_INSTLEN 2 /* Length of an instruction on MIPS16*/
|
||||
#define MIPS_NUMREGS 32 /* Number of integer or float registers */
|
||||
typedef unsigned long t_inst; /* Integer big enough to hold an instruction */
|
||||
|
||||
/* MIPS16 function addresses are odd (bit 0 is set). Here are some
|
||||
macros to test, set, or clear bit 0 of addresses. */
|
||||
#define IS_MIPS16_ADDR(addr) ((addr) & 1)
|
||||
#define MAKE_MIPS16_ADDR(addr) ((addr) | 1)
|
||||
#define UNMAKE_MIPS16_ADDR(addr) ((addr) & ~1)
|
||||
|
||||
#endif /* TM_MIPS_H */
|
||||
|
|
312
gdb/mips-tdep.c
312
gdb/mips-tdep.c
|
@ -41,18 +41,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
/* FIXME: Put this declaration in frame.h. */
|
||||
extern struct obstack frame_cache_obstack;
|
||||
|
||||
/* FIXME! this code assumes 4-byte instructions. */
|
||||
#define MIPS_INSTLEN 4 /* Length of an instruction */
|
||||
#define MIPS16_INSTLEN 2 /* Length of an instruction on MIPS16*/
|
||||
#define MIPS_NUMREGS 32 /* Number of integer or float registers */
|
||||
typedef unsigned long t_inst; /* Integer big enough to hold an instruction */
|
||||
|
||||
/* MIPS16 function addresses are odd (bit 0 is set). Here are some
|
||||
macros to test, set, or clear bit 0 of addresses. */
|
||||
#define IS_MIPS16_ADDR(addr) ((addr) & 1)
|
||||
#define MAKE_MIPS16_ADDR(addr) ((addr) | 1)
|
||||
#define UNMAKE_MIPS16_ADDR(addr) ((addr) & ~1)
|
||||
|
||||
#if 0
|
||||
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
|
||||
#endif
|
||||
|
@ -545,9 +533,9 @@ mips_addr_bits_remove (addr)
|
|||
{
|
||||
#if GDB_TARGET_IS_MIPS64
|
||||
if ((addr >> 32 == (CORE_ADDR)0xffffffff)
|
||||
&& (strcmp(target_shortname,"pmon")==0
|
||||
|| strcmp(target_shortname,"ddb")==0
|
||||
|| strcmp(target_shortname,"sim")==0))
|
||||
&& (strcmp (target_shortname,"pmon")==0
|
||||
|| strcmp (target_shortname,"ddb")==0
|
||||
|| strcmp (target_shortname,"sim")==0))
|
||||
{
|
||||
/* This hack is a work-around for existing boards using PMON,
|
||||
the simulator, and any other 64-bit targets that doesn't have
|
||||
|
@ -574,6 +562,20 @@ mips_addr_bits_remove (addr)
|
|||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
mips_init_frame_pc_first (fromleaf, prev)
|
||||
int fromleaf;
|
||||
struct frame_info *prev;
|
||||
{
|
||||
CORE_ADDR pc, tmp;
|
||||
|
||||
pc = ((fromleaf) ? SAVED_PC_AFTER_CALL (prev->next) :
|
||||
prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
|
||||
tmp = mips_skip_stub (pc);
|
||||
prev->pc = tmp ? tmp : pc;
|
||||
}
|
||||
|
||||
|
||||
CORE_ADDR
|
||||
mips_frame_saved_pc(frame)
|
||||
struct frame_info *frame;
|
||||
|
@ -637,7 +639,7 @@ heuristic_proc_start(pc)
|
|||
else
|
||||
warning("Hit heuristic-fence-post without finding");
|
||||
|
||||
warning("enclosing function for address 0x%s", paddr (pc));
|
||||
warning("enclosing function for address 0x%s", paddr_nz (pc));
|
||||
if (!blurb_printed)
|
||||
{
|
||||
printf_filtered ("\
|
||||
|
@ -1096,29 +1098,36 @@ CORE_ADDR
|
|||
mips_frame_chain(frame)
|
||||
struct frame_info *frame;
|
||||
{
|
||||
mips_extra_func_info_t proc_desc;
|
||||
CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
|
||||
mips_extra_func_info_t proc_desc;
|
||||
CORE_ADDR tmp;
|
||||
CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
|
||||
|
||||
if (saved_pc == 0 || inside_entry_file (saved_pc))
|
||||
return 0;
|
||||
if (saved_pc == 0 || inside_entry_file (saved_pc))
|
||||
return 0;
|
||||
|
||||
proc_desc = find_proc_desc(saved_pc, frame);
|
||||
if (!proc_desc)
|
||||
return 0;
|
||||
/* Check if the PC is inside a call stub. If it is, fetch the
|
||||
PC of the caller of that stub. */
|
||||
if ((tmp = mips_skip_stub (saved_pc)) != 0)
|
||||
saved_pc = tmp;
|
||||
|
||||
cached_proc_desc = proc_desc;
|
||||
/* Look up the procedure descriptor for this PC. */
|
||||
proc_desc = find_proc_desc(saved_pc, frame);
|
||||
if (!proc_desc)
|
||||
return 0;
|
||||
|
||||
/* If no frame pointer and frame size is zero, we must be at end
|
||||
of stack (or otherwise hosed). If we don't check frame size,
|
||||
we loop forever if we see a zero size frame. */
|
||||
if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
|
||||
&& PROC_FRAME_OFFSET (proc_desc) == 0
|
||||
/* The previous frame from a sigtramp frame might be frameless
|
||||
and have frame size zero. */
|
||||
&& !frame->signal_handler_caller)
|
||||
return 0;
|
||||
else
|
||||
return get_frame_pointer (frame, proc_desc);
|
||||
cached_proc_desc = proc_desc;
|
||||
|
||||
/* If no frame pointer and frame size is zero, we must be at end
|
||||
of stack (or otherwise hosed). If we don't check frame size,
|
||||
we loop forever if we see a zero size frame. */
|
||||
if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
|
||||
&& PROC_FRAME_OFFSET (proc_desc) == 0
|
||||
/* The previous frame from a sigtramp frame might be frameless
|
||||
and have frame size zero. */
|
||||
&& !frame->signal_handler_caller)
|
||||
return 0;
|
||||
else
|
||||
return get_frame_pointer (frame, proc_desc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1540,12 +1549,11 @@ mips_print_register (regnum, all)
|
|||
if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+MIPS_NUMREGS
|
||||
&& !((regnum-FP0_REGNUM) & 1))
|
||||
{
|
||||
char dbuffer[MAX_REGISTER_RAW_SIZE];
|
||||
char dbuffer[2 * MAX_REGISTER_RAW_SIZE];
|
||||
|
||||
/* MIPS doubles are stored in a register pair with the least
|
||||
signficant register in the lower-numbered register. */
|
||||
read_relative_register_raw_bytes (regnum+1, dbuffer);
|
||||
read_relative_register_raw_bytes (regnum, dbuffer+MIPS_REGSIZE);
|
||||
read_relative_register_raw_bytes (regnum, dbuffer);
|
||||
read_relative_register_raw_bytes (regnum+1, dbuffer+MIPS_REGSIZE);
|
||||
REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer);
|
||||
|
||||
printf_filtered ("(d%d: ", regnum-FP0_REGNUM);
|
||||
val_print (builtin_type_double, dbuffer, 0,
|
||||
|
@ -1901,19 +1909,7 @@ mips_extract_return_value (valtype, regbuf, valbuf)
|
|||
if (TYPE_CODE (valtype) == TYPE_CODE_FLT
|
||||
&& (mips_fpu == MIPS_FPU_DOUBLE
|
||||
|| (mips_fpu == MIPS_FPU_SINGLE && len <= MIPS_REGSIZE)))
|
||||
{
|
||||
regnum = FP0_REGNUM;
|
||||
|
||||
/* If this is a double, the odd-numbered register (FP1) contains the
|
||||
high word of the result. Copy that to the buffer before
|
||||
copying the low word in FP0. */
|
||||
if (len > MIPS_REGSIZE)
|
||||
{
|
||||
memcpy (valbuf, regbuf + REGISTER_BYTE (regnum+1), MIPS_REGSIZE);
|
||||
len -= MIPS_REGSIZE;
|
||||
valbuf += MIPS_REGSIZE;
|
||||
}
|
||||
}
|
||||
regnum = FP0_REGNUM;
|
||||
|
||||
if (TARGET_BYTE_ORDER == BIG_ENDIAN
|
||||
&& TYPE_CODE (valtype) != TYPE_CODE_FLT
|
||||
|
@ -1921,6 +1917,7 @@ mips_extract_return_value (valtype, regbuf, valbuf)
|
|||
offset = REGISTER_RAW_SIZE (regnum) - len;
|
||||
|
||||
memcpy (valbuf, regbuf + REGISTER_BYTE (regnum) + offset, len);
|
||||
REGISTER_CONVERT_TO_TYPE (regnum, valtype, valbuf);
|
||||
}
|
||||
|
||||
/* Given a return value in `regbuf' with a type `valtype',
|
||||
|
@ -1940,10 +1937,7 @@ mips_store_return_value (valtype, valbuf)
|
|||
regnum = FP0_REGNUM;
|
||||
|
||||
memcpy(raw_buffer, valbuf, TYPE_LENGTH (valtype));
|
||||
|
||||
#ifdef REGISTER_CONVERT_FROM_TYPE
|
||||
REGISTER_CONVERT_FROM_TYPE(regnum, valtype, raw_buffer);
|
||||
#endif
|
||||
|
||||
write_register_bytes(REGISTER_BYTE (regnum), raw_buffer, TYPE_LENGTH (valtype));
|
||||
}
|
||||
|
@ -2173,8 +2167,19 @@ unsigned char *mips_breakpoint_from_pc (pcptr, lenptr)
|
|||
else
|
||||
{
|
||||
static char big_breakpoint[] = BIG_BREAKPOINT;
|
||||
static char pmon_big_breakpoint[] = PMON_BIG_BREAKPOINT;
|
||||
static char idt_big_breakpoint[] = IDT_BIG_BREAKPOINT;
|
||||
|
||||
*lenptr = sizeof(big_breakpoint);
|
||||
return big_breakpoint;
|
||||
|
||||
if (strcmp (target_shortname, "mips") == 0)
|
||||
return idt_big_breakpoint;
|
||||
else if (strcmp (target_shortname, "ddb") == 0
|
||||
|| strcmp (target_shortname, "pmon") == 0
|
||||
|| strcmp (target_shortname, "lsi") == 0)
|
||||
return pmon_big_breakpoint;
|
||||
else
|
||||
return big_breakpoint;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2189,8 +2194,19 @@ unsigned char *mips_breakpoint_from_pc (pcptr, lenptr)
|
|||
else
|
||||
{
|
||||
static char little_breakpoint[] = LITTLE_BREAKPOINT;
|
||||
static char pmon_little_breakpoint[] = PMON_LITTLE_BREAKPOINT;
|
||||
static char idt_little_breakpoint[] = IDT_LITTLE_BREAKPOINT;
|
||||
|
||||
*lenptr = sizeof(little_breakpoint);
|
||||
return little_breakpoint;
|
||||
|
||||
if (strcmp (target_shortname, "mips") == 0)
|
||||
return idt_little_breakpoint;
|
||||
else if (strcmp (target_shortname, "ddb") == 0
|
||||
|| strcmp (target_shortname, "pmon") == 0
|
||||
|| strcmp (target_shortname, "lsi") == 0)
|
||||
return pmon_little_breakpoint;
|
||||
else
|
||||
return little_breakpoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2215,6 +2231,186 @@ mips_about_to_return (pc)
|
|||
}
|
||||
|
||||
|
||||
/* If PC is in a mips16 call or return stub, return the address of the target
|
||||
PC, which is either the callee or the caller. There are several
|
||||
cases which must be handled:
|
||||
|
||||
* If the PC is in __mips16_ret_{d,s}f, this is a return stub and the
|
||||
target PC is in $31 ($ra).
|
||||
* If the PC is in __mips16_call_stub_{1..10}, this is a call stub
|
||||
and the target PC is in $2.
|
||||
* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
|
||||
before the jal instruction, this is effectively a call stub
|
||||
and the the target PC is in $2. Otherwise this is effectively
|
||||
a return stub and the target PC is in $18.
|
||||
|
||||
See the source code for the stubs in gcc/config/mips/mips16.S for
|
||||
gory details.
|
||||
|
||||
This function implements the SKIP_TRAMPOLINE_CODE macro.
|
||||
*/
|
||||
|
||||
CORE_ADDR
|
||||
mips_skip_stub (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
char *name;
|
||||
CORE_ADDR start_addr;
|
||||
|
||||
/* Find the starting address and name of the function containing the PC. */
|
||||
if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
|
||||
return 0;
|
||||
|
||||
/* If the PC is in __mips16_ret_{d,s}f, this is a return stub and the
|
||||
target PC is in $31 ($ra). */
|
||||
if (strcmp (name, "__mips16_ret_sf") == 0
|
||||
|| strcmp (name, "__mips16_ret_df") == 0)
|
||||
return read_register (RA_REGNUM);
|
||||
|
||||
if (strncmp (name, "__mips16_call_stub_", 19) == 0)
|
||||
{
|
||||
/* If the PC is in __mips16_call_stub_{1..10}, this is a call stub
|
||||
and the target PC is in $2. */
|
||||
if (name[19] >= '0' && name[19] <= '9')
|
||||
return read_register (2);
|
||||
|
||||
/* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
|
||||
before the jal instruction, this is effectively a call stub
|
||||
and the the target PC is in $2. Otherwise this is effectively
|
||||
a return stub and the target PC is in $18. */
|
||||
else if (name[19] == 's' || name[19] == 'd')
|
||||
{
|
||||
if (pc == start_addr)
|
||||
{
|
||||
/* Check if the target of the stub is a compiler-generated
|
||||
stub. Such a stub for a function bar might have a name
|
||||
like __fn_stub_bar, and might look like this:
|
||||
mfc1 $4,$f13
|
||||
mfc1 $5,$f12
|
||||
mfc1 $6,$f15
|
||||
mfc1 $7,$f14
|
||||
la $1,bar (becomes a lui/addiu pair)
|
||||
jr $1
|
||||
So scan down to the lui/addi and extract the target
|
||||
address from those two instructions. */
|
||||
|
||||
CORE_ADDR target_pc = read_register (2);
|
||||
t_inst inst;
|
||||
int i;
|
||||
|
||||
/* See if the name of the target function is __fn_stub_*. */
|
||||
if (find_pc_partial_function (target_pc, &name, NULL, NULL) == 0)
|
||||
return target_pc;
|
||||
if (strncmp (name, "__fn_stub_", 10) != 0
|
||||
&& strcmp (name, "etext") != 0
|
||||
&& strcmp (name, "_etext") != 0)
|
||||
return target_pc;
|
||||
|
||||
/* Scan through this _fn_stub_ code for the lui/addiu pair.
|
||||
The limit on the search is arbitrarily set to 20
|
||||
instructions. FIXME. */
|
||||
for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSTLEN)
|
||||
{
|
||||
inst = mips_fetch_instruction (target_pc);
|
||||
if ((inst & 0xffff0000) == 0x3c010000) /* lui $at */
|
||||
pc = (inst << 16) & 0xffff0000; /* high word */
|
||||
else if ((inst & 0xffff0000) == 0x24210000) /* addiu $at */
|
||||
return pc | (inst & 0xffff); /* low word */
|
||||
}
|
||||
|
||||
/* Couldn't find the lui/addui pair, so return stub address. */
|
||||
return target_pc;
|
||||
}
|
||||
else
|
||||
/* This is the 'return' part of a call stub. The return
|
||||
address is in $r18. */
|
||||
return read_register (18);
|
||||
}
|
||||
}
|
||||
return 0; /* not a stub */
|
||||
}
|
||||
|
||||
|
||||
/* Return non-zero if the PC is inside a call thunk (aka stub or trampoline).
|
||||
This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */
|
||||
|
||||
int
|
||||
mips_in_call_stub (pc, name)
|
||||
CORE_ADDR pc;
|
||||
char *name;
|
||||
{
|
||||
CORE_ADDR start_addr;
|
||||
|
||||
/* Find the starting address of the function containing the PC. If the
|
||||
caller didn't give us a name, look it up at the same time. */
|
||||
if (find_pc_partial_function (pc, name ? NULL : &name, &start_addr, NULL) == 0)
|
||||
return 0;
|
||||
|
||||
if (strncmp (name, "__mips16_call_stub_", 19) == 0)
|
||||
{
|
||||
/* If the PC is in __mips16_call_stub_{1..10}, this is a call stub. */
|
||||
if (name[19] >= '0' && name[19] <= '9')
|
||||
return 1;
|
||||
/* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
|
||||
before the jal instruction, this is effectively a call stub. */
|
||||
else if (name[19] == 's' || name[19] == 'd')
|
||||
return pc == start_addr;
|
||||
}
|
||||
|
||||
return 0; /* not a stub */
|
||||
}
|
||||
|
||||
|
||||
/* Return non-zero if the PC is inside a return thunk (aka stub or trampoline).
|
||||
This implements the IN_SOLIB_RETURN_TRAMPOLINE macro. */
|
||||
|
||||
int
|
||||
mips_in_return_stub (pc, name)
|
||||
CORE_ADDR pc;
|
||||
char *name;
|
||||
{
|
||||
CORE_ADDR start_addr;
|
||||
|
||||
/* Find the starting address of the function containing the PC. */
|
||||
if (find_pc_partial_function (pc, NULL, &start_addr, NULL) == 0)
|
||||
return 0;
|
||||
|
||||
/* If the PC is in __mips16_ret_{d,s}f, this is a return stub. */
|
||||
if (strcmp (name, "__mips16_ret_sf") == 0
|
||||
|| strcmp (name, "__mips16_ret_df") == 0)
|
||||
return 1;
|
||||
|
||||
/* If the PC is in __mips16_call_stub_{s,d}f_{0..10} but not at the start,
|
||||
i.e. after the jal instruction, this is effectively a return stub. */
|
||||
if (strncmp (name, "__mips16_call_stub_", 19) == 0
|
||||
&& (name[19] == 's' || name[19] == 'd')
|
||||
&& pc != start_addr)
|
||||
return 1;
|
||||
|
||||
return 0; /* not a stub */
|
||||
}
|
||||
|
||||
|
||||
/* Return non-zero if the PC is in a library helper function that should
|
||||
be ignored. This implements the IGNORE_HELPER_CALL macro. */
|
||||
|
||||
int
|
||||
mips_ignore_helper (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
char *name;
|
||||
|
||||
/* Find the starting address and name of the function containing the PC. */
|
||||
if (find_pc_partial_function (pc, &name, NULL, NULL) == 0)
|
||||
return 0;
|
||||
|
||||
/* If the PC is in __mips16_ret_{d,s}f, this is a library helper function
|
||||
that we want to ignore. */
|
||||
return (strcmp (name, "__mips16_ret_sf") == 0
|
||||
|| strcmp (name, "__mips16_ret_df") == 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_initialize_mips_tdep ()
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue