mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 18:08:24 +08:00
* mips-tdep.c (IS_MIPS16_ADDR, MAKE_MIPS16_ADDR, UNMAKE_MIPS16_ADDR):
New macros for testing, setting, and clearing bit 0 of addresses. Change numerous bits of code where bit 0 was being manipulated to use these macros.
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
Thu Feb 27 18:54:11 1997 Mark Alexander <marka@cygnus.com>
|
||||||
|
|
||||||
|
* mips-tdep.c (IS_MIPS16_ADDR, MAKE_MIPS16_ADDR, UNMAKE_MIPS16_ADDR):
|
||||||
|
New macros for testing, setting, and clearing bit 0 of addresses.
|
||||||
|
Change numerous bits of code where bit 0 was being manipulated
|
||||||
|
to use these macros.
|
||||||
|
|
||||||
Thu Feb 27 14:12:41 1997 Mark Alexander <marka@cygnus.com>
|
Thu Feb 27 14:12:41 1997 Mark Alexander <marka@cygnus.com>
|
||||||
|
|
||||||
* remote-mips.c: Put back the form feeds.
|
* remote-mips.c: Put back the form feeds.
|
||||||
|
143
gdb/mips-tdep.c
143
gdb/mips-tdep.c
@ -47,6 +47,12 @@ extern struct obstack frame_cache_obstack;
|
|||||||
#define MIPS_NUMREGS 32 /* Number of integer or float registers */
|
#define MIPS_NUMREGS 32 /* Number of integer or float registers */
|
||||||
typedef unsigned long t_inst; /* Integer big enough to hold an instruction */
|
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
|
#if 0
|
||||||
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
|
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
|
||||||
#endif
|
#endif
|
||||||
@ -409,13 +415,15 @@ mips_find_saved_regs (fci)
|
|||||||
unsigned long gen_save_found = 0;
|
unsigned long gen_save_found = 0;
|
||||||
unsigned long float_save_found = 0;
|
unsigned long float_save_found = 0;
|
||||||
|
|
||||||
if ((addr = PROC_LOW_ADDR (proc_desc)) & 1)
|
/* If the address is odd, assume this is MIPS16 code. */
|
||||||
|
addr = PROC_LOW_ADDR (proc_desc);
|
||||||
|
if (IS_MIPS16_ADDR (addr))
|
||||||
{
|
{
|
||||||
instlen = MIPS16_INSTLEN; /* MIPS16 */
|
instlen = MIPS16_INSTLEN;
|
||||||
addr &= ~1;
|
addr = UNMAKE_MIPS16_ADDR (addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
instlen = MIPS_INSTLEN; /* MIPS32 */
|
instlen = MIPS_INSTLEN;
|
||||||
|
|
||||||
/* Scan through this function's instructions preceding the current
|
/* Scan through this function's instructions preceding the current
|
||||||
PC, and look for those that save registers. */
|
PC, and look for those that save registers. */
|
||||||
@ -568,7 +576,7 @@ heuristic_proc_start(pc)
|
|||||||
|| fence < VM_MIN_ADDRESS)
|
|| fence < VM_MIN_ADDRESS)
|
||||||
fence = VM_MIN_ADDRESS;
|
fence = VM_MIN_ADDRESS;
|
||||||
|
|
||||||
instlen = pc & 1 ? MIPS16_INSTLEN : MIPS_INSTLEN;
|
instlen = IS_MIPS16_ADDR (pc) ? MIPS16_INSTLEN : MIPS_INSTLEN;
|
||||||
|
|
||||||
/* search back for previous return */
|
/* search back for previous return */
|
||||||
for (start_pc -= instlen; ; start_pc -= instlen)
|
for (start_pc -= instlen; ; start_pc -= instlen)
|
||||||
@ -603,15 +611,17 @@ Otherwise, you told GDB there was a function where there isn't one, or\n\
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (start_pc & 1)
|
else if (IS_MIPS16_ADDR (start_pc))
|
||||||
{
|
{
|
||||||
|
unsigned short inst;
|
||||||
|
|
||||||
/* On MIPS16, any one of the following is likely to be the
|
/* On MIPS16, any one of the following is likely to be the
|
||||||
start of a function:
|
start of a function:
|
||||||
entry
|
entry
|
||||||
addiu sp,-n
|
addiu sp,-n
|
||||||
daddiu sp,-n
|
daddiu sp,-n
|
||||||
extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n' */
|
extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n' */
|
||||||
unsigned short inst = read_memory_integer (start_pc & ~1, 2);
|
inst = read_memory_integer (UNMAKE_MIPS16_ADDR (start_pc), 2);
|
||||||
if (((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700) /* entry */
|
if (((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700) /* entry */
|
||||||
|| (inst & 0xff80) == 0x6380 /* addiu sp,-n */
|
|| (inst & 0xff80) == 0x6380 /* addiu sp,-n */
|
||||||
|| (inst & 0xff80) == 0xfb80 /* daddiu sp,-n */
|
|| (inst & 0xff80) == 0xfb80 /* daddiu sp,-n */
|
||||||
@ -699,7 +709,8 @@ mips16_heuristic_proc_desc(start_pc, limit_pc, next_frame, sp)
|
|||||||
prev_inst = inst;
|
prev_inst = inst;
|
||||||
|
|
||||||
/* Fetch the instruction. */
|
/* Fetch the instruction. */
|
||||||
status = read_memory_nobpt (cur_pc & ~1, buf, MIPS16_INSTLEN);
|
status = read_memory_nobpt (UNMAKE_MIPS16_ADDR (cur_pc), buf,
|
||||||
|
MIPS16_INSTLEN);
|
||||||
if (status) memory_error (status, cur_pc);
|
if (status) memory_error (status, cur_pc);
|
||||||
inst = (unsigned short) extract_unsigned_integer (buf, MIPS16_INSTLEN);
|
inst = (unsigned short) extract_unsigned_integer (buf, MIPS16_INSTLEN);
|
||||||
|
|
||||||
@ -922,7 +933,7 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
|
|||||||
|
|
||||||
if (start_pc + 200 < limit_pc)
|
if (start_pc + 200 < limit_pc)
|
||||||
limit_pc = start_pc + 200;
|
limit_pc = start_pc + 200;
|
||||||
if (start_pc & 1)
|
if (IS_MIPS16_ADDR (start_pc))
|
||||||
mips16_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
|
mips16_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
|
||||||
else
|
else
|
||||||
mips32_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
|
mips32_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
|
||||||
@ -930,16 +941,18 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static mips_extra_func_info_t
|
static mips_extra_func_info_t
|
||||||
find_proc_desc (pc, next_frame)
|
non_heuristic_proc_desc (pc, addrptr)
|
||||||
CORE_ADDR pc;
|
CORE_ADDR pc;
|
||||||
struct frame_info *next_frame;
|
CORE_ADDR *addrptr;
|
||||||
{
|
{
|
||||||
|
CORE_ADDR startaddr;
|
||||||
mips_extra_func_info_t proc_desc;
|
mips_extra_func_info_t proc_desc;
|
||||||
struct block *b = block_for_pc(pc);
|
struct block *b = block_for_pc(pc);
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
CORE_ADDR startaddr;
|
|
||||||
|
|
||||||
find_pc_partial_function (pc, NULL, &startaddr, NULL);
|
find_pc_partial_function (pc, NULL, &startaddr, NULL);
|
||||||
|
if (addrptr)
|
||||||
|
*addrptr = startaddr;
|
||||||
if (b == NULL || PC_IN_CALL_DUMMY (pc, 0, 0))
|
if (b == NULL || PC_IN_CALL_DUMMY (pc, 0, 0))
|
||||||
sym = NULL;
|
sym = NULL;
|
||||||
else
|
else
|
||||||
@ -950,41 +963,62 @@ find_proc_desc (pc, next_frame)
|
|||||||
symbol reading. */
|
symbol reading. */
|
||||||
sym = NULL;
|
sym = NULL;
|
||||||
else
|
else
|
||||||
sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE,
|
sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL);
|
||||||
0, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we never found a PDR for this function in symbol reading, then
|
/* If we never found a PDR for this function in symbol reading, then
|
||||||
examine prologues to find the information. */
|
examine prologues to find the information. */
|
||||||
if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1)
|
|
||||||
sym = NULL;
|
|
||||||
|
|
||||||
if (sym)
|
if (sym)
|
||||||
{
|
{
|
||||||
/* IF this is the topmost frame AND
|
proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
|
||||||
* (this proc does not have debugging information OR
|
if (PROC_FRAME_REG (proc_desc) == -1)
|
||||||
* the PC is in the procedure prologue)
|
return NULL;
|
||||||
* THEN create a "heuristic" proc_desc (by analyzing
|
else
|
||||||
* the actual code) to replace the "official" proc_desc.
|
return proc_desc;
|
||||||
*/
|
}
|
||||||
proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
|
else
|
||||||
if (next_frame == NULL) {
|
return NULL;
|
||||||
struct symtab_and_line val;
|
}
|
||||||
struct symbol *proc_symbol =
|
|
||||||
PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc);
|
|
||||||
|
|
||||||
if (proc_symbol) {
|
|
||||||
val = find_pc_line (BLOCK_START
|
static mips_extra_func_info_t
|
||||||
(SYMBOL_BLOCK_VALUE(proc_symbol)),
|
find_proc_desc (pc, next_frame)
|
||||||
0);
|
CORE_ADDR pc;
|
||||||
val.pc = val.end ? val.end : pc;
|
struct frame_info *next_frame;
|
||||||
|
{
|
||||||
|
mips_extra_func_info_t proc_desc;
|
||||||
|
CORE_ADDR startaddr;
|
||||||
|
|
||||||
|
proc_desc = non_heuristic_proc_desc (pc, &startaddr);
|
||||||
|
|
||||||
|
if (proc_desc)
|
||||||
|
{
|
||||||
|
/* IF this is the topmost frame AND
|
||||||
|
* (this proc does not have debugging information OR
|
||||||
|
* the PC is in the procedure prologue)
|
||||||
|
* THEN create a "heuristic" proc_desc (by analyzing
|
||||||
|
* the actual code) to replace the "official" proc_desc.
|
||||||
|
*/
|
||||||
|
if (next_frame == NULL)
|
||||||
|
{
|
||||||
|
struct symtab_and_line val;
|
||||||
|
struct symbol *proc_symbol =
|
||||||
|
PROC_DESC_IS_DUMMY(proc_desc) ? 0 : PROC_SYMBOL(proc_desc);
|
||||||
|
|
||||||
|
if (proc_symbol)
|
||||||
|
{
|
||||||
|
val = find_pc_line (BLOCK_START
|
||||||
|
(SYMBOL_BLOCK_VALUE(proc_symbol)),
|
||||||
|
0);
|
||||||
|
val.pc = val.end ? val.end : pc;
|
||||||
}
|
}
|
||||||
if (!proc_symbol || pc < val.pc) {
|
if (!proc_symbol || pc < val.pc)
|
||||||
mips_extra_func_info_t found_heuristic =
|
{
|
||||||
heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
|
mips_extra_func_info_t found_heuristic =
|
||||||
pc, next_frame);
|
heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
|
||||||
if (found_heuristic)
|
pc, next_frame);
|
||||||
proc_desc = found_heuristic;
|
if (found_heuristic)
|
||||||
|
proc_desc = found_heuristic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1570,7 +1604,7 @@ mips_step_skips_delay (pc)
|
|||||||
char buf[MIPS_INSTLEN];
|
char buf[MIPS_INSTLEN];
|
||||||
|
|
||||||
/* There is no branch delay slot on MIPS16. */
|
/* There is no branch delay slot on MIPS16. */
|
||||||
if (pc & 1)
|
if (IS_MIPS16_ADDR (pc))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (target_read_memory (pc, buf, MIPS_INSTLEN) != 0)
|
if (target_read_memory (pc, buf, MIPS_INSTLEN) != 0)
|
||||||
@ -1724,7 +1758,8 @@ mips16_skip_prologue (pc, lenient)
|
|||||||
int prev_extend_bytes;
|
int prev_extend_bytes;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
status = read_memory_nobpt (pc & ~1, buf, MIPS16_INSTLEN);
|
status = read_memory_nobpt (UNMAKE_MIPS16_ADDR (pc), buf,
|
||||||
|
MIPS16_INSTLEN);
|
||||||
if (status)
|
if (status)
|
||||||
memory_error (status, pc);
|
memory_error (status, pc);
|
||||||
inst = (unsigned long)extract_unsigned_integer (buf, MIPS16_INSTLEN);
|
inst = (unsigned long)extract_unsigned_integer (buf, MIPS16_INSTLEN);
|
||||||
@ -1788,7 +1823,7 @@ mips_skip_prologue (pc, lenient)
|
|||||||
/* Can't determine prologue from the symbol table, need to examine
|
/* Can't determine prologue from the symbol table, need to examine
|
||||||
instructions. */
|
instructions. */
|
||||||
|
|
||||||
if (pc & 1)
|
if (IS_MIPS16_ADDR (pc))
|
||||||
return mips16_skip_prologue (pc, lenient);
|
return mips16_skip_prologue (pc, lenient);
|
||||||
else
|
else
|
||||||
return mips32_skip_prologue (pc, lenient);
|
return mips32_skip_prologue (pc, lenient);
|
||||||
@ -2046,21 +2081,19 @@ gdb_print_insn_mips (memaddr, info)
|
|||||||
that is the start of a 16-bit function. If we didn't do this,
|
that is the start of a 16-bit function. If we didn't do this,
|
||||||
the search would fail because the symbol table says the function
|
the search would fail because the symbol table says the function
|
||||||
starts at an odd address, i.e. 1 byte past the given address. */
|
starts at an odd address, i.e. 1 byte past the given address. */
|
||||||
proc_desc = find_proc_desc (memaddr | 1, NULL);
|
memaddr = ADDR_BITS_REMOVE (memaddr);
|
||||||
|
proc_desc = non_heuristic_proc_desc (MAKE_MIPS16_ADDR (memaddr), NULL);
|
||||||
|
|
||||||
/* Make an attempt to determine if this is a 16-bit function. If
|
/* Make an attempt to determine if this is a 16-bit function. If
|
||||||
the procedure descriptor exists and the address therein is odd,
|
the procedure descriptor exists and the address therein is odd,
|
||||||
it's definitely a 16-bit function. Otherwise, we have to just
|
it's definitely a 16-bit function. Otherwise, we have to just
|
||||||
guess that if the address passed in is odd, it's 16-bits. */
|
guess that if the address passed in is odd, it's 16-bits. */
|
||||||
if (proc_desc)
|
if (proc_desc)
|
||||||
info->mach = PROC_LOW_ADDR (proc_desc) & 1 ? 16 : 0;
|
info->mach = IS_MIPS16_ADDR (PROC_LOW_ADDR (proc_desc)) ? 16 : 0;
|
||||||
else
|
else
|
||||||
info->mach = memaddr & 1 ? 16 : 0;
|
info->mach = IS_MIPS16_ADDR (memaddr) ? 16 : 0;
|
||||||
|
|
||||||
/* Round down the instruction address to the appropriate boundary.
|
/* Round down the instruction address to the appropriate boundary. */
|
||||||
Save the amount rounded down and subtract it from the returned size of
|
|
||||||
the instruction so that the next time through the address won't
|
|
||||||
look bogus. */
|
|
||||||
memaddr &= (info->mach == 16 ? ~1 : ~3);
|
memaddr &= (info->mach == 16 ? ~1 : ~3);
|
||||||
|
|
||||||
/* Call the appropriate disassembler based on the target endian-ness. */
|
/* Call the appropriate disassembler based on the target endian-ness. */
|
||||||
@ -2083,10 +2116,10 @@ unsigned char *mips_breakpoint_from_pc (pcptr, lenptr)
|
|||||||
{
|
{
|
||||||
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
|
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
|
||||||
{
|
{
|
||||||
if (*pcptr & 1)
|
if (IS_MIPS16_ADDR (*pcptr))
|
||||||
{
|
{
|
||||||
static char mips16_big_breakpoint[] = MIPS16_BIG_BREAKPOINT;
|
static char mips16_big_breakpoint[] = MIPS16_BIG_BREAKPOINT;
|
||||||
*pcptr &= ~1;
|
*pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
|
||||||
*lenptr = sizeof(mips16_big_breakpoint);
|
*lenptr = sizeof(mips16_big_breakpoint);
|
||||||
return mips16_big_breakpoint;
|
return mips16_big_breakpoint;
|
||||||
}
|
}
|
||||||
@ -2099,10 +2132,10 @@ unsigned char *mips_breakpoint_from_pc (pcptr, lenptr)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (*pcptr & 1)
|
if (IS_MIPS16_ADDR (*pcptr))
|
||||||
{
|
{
|
||||||
static char mips16_little_breakpoint[] = MIPS16_LITTLE_BREAKPOINT;
|
static char mips16_little_breakpoint[] = MIPS16_LITTLE_BREAKPOINT;
|
||||||
*pcptr &= ~1;
|
*pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
|
||||||
*lenptr = sizeof(mips16_little_breakpoint);
|
*lenptr = sizeof(mips16_little_breakpoint);
|
||||||
return mips16_little_breakpoint;
|
return mips16_little_breakpoint;
|
||||||
}
|
}
|
||||||
@ -2122,14 +2155,14 @@ int
|
|||||||
mips_about_to_return (pc)
|
mips_about_to_return (pc)
|
||||||
CORE_ADDR pc;
|
CORE_ADDR pc;
|
||||||
{
|
{
|
||||||
if (pc & 1)
|
if (IS_MIPS16_ADDR (pc))
|
||||||
/* This mips16 case isn't necessarily reliable. Sometimes the compiler
|
/* This mips16 case isn't necessarily reliable. Sometimes the compiler
|
||||||
generates a "jr $ra"; other times it generates code to load
|
generates a "jr $ra"; other times it generates code to load
|
||||||
the return address from the stack to an accessible register (such
|
the return address from the stack to an accessible register (such
|
||||||
as $a3), then a "jr" using that register. This second case
|
as $a3), then a "jr" using that register. This second case
|
||||||
is almost impossible to distinguish from an indirect jump
|
is almost impossible to distinguish from an indirect jump
|
||||||
used for switch statements, so we don't even try. */
|
used for switch statements, so we don't even try. */
|
||||||
return read_memory_integer (pc & ~1, 2) == 0xe820; /* jr $ra */
|
return read_memory_integer (UNMAKE_MIPS16_ADDR (pc), 2) == 0xe820; /* jr $ra */
|
||||||
else
|
else
|
||||||
return read_memory_integer (pc, 4) == 0x3e00008; /* jr $ra */
|
return read_memory_integer (pc, 4) == 0x3e00008; /* jr $ra */
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user