aboutsummaryrefslogtreecommitdiff
path: root/gdb/mips-tdep.c
diff options
context:
space:
mode:
authorMark Alexander <marka@cygnus>1997-02-28 03:00:51 +0000
committerMark Alexander <marka@cygnus>1997-02-28 03:00:51 +0000
commitc1fc09357179094c9c210fffd08bd28c704747b6 (patch)
tree08db609a10cb1f04f679cb2bcaa6570af0249e32 /gdb/mips-tdep.c
parent35a3e78edb9d4a3ef98f975587752325c9be860f (diff)
downloadgdb-c1fc09357179094c9c210fffd08bd28c704747b6.zip
gdb-c1fc09357179094c9c210fffd08bd28c704747b6.tar.gz
gdb-c1fc09357179094c9c210fffd08bd28c704747b6.tar.bz2
* 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.
Diffstat (limited to 'gdb/mips-tdep.c')
-rw-r--r--gdb/mips-tdep.c145
1 files changed, 89 insertions, 56 deletions
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index b63bbf2..1c02ded 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -47,6 +47,12 @@ extern struct obstack frame_cache_obstack;
#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
@@ -409,13 +415,15 @@ mips_find_saved_regs (fci)
unsigned long gen_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 */
- addr &= ~1;
+ instlen = MIPS16_INSTLEN;
+ addr = UNMAKE_MIPS16_ADDR (addr);
}
else
- instlen = MIPS_INSTLEN; /* MIPS32 */
+ instlen = MIPS_INSTLEN;
/* Scan through this function's instructions preceding the current
PC, and look for those that save registers. */
@@ -568,7 +576,7 @@ heuristic_proc_start(pc)
|| 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 */
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;
}
- 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
start of a function:
entry
addiu sp,-n
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 */
|| (inst & 0xff80) == 0x6380 /* addiu 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;
/* 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);
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)
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);
else
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
-find_proc_desc (pc, next_frame)
+non_heuristic_proc_desc (pc, addrptr)
CORE_ADDR pc;
- struct frame_info *next_frame;
+ CORE_ADDR *addrptr;
{
+ CORE_ADDR startaddr;
mips_extra_func_info_t proc_desc;
struct block *b = block_for_pc(pc);
struct symbol *sym;
- CORE_ADDR startaddr;
find_pc_partial_function (pc, NULL, &startaddr, NULL);
+ if (addrptr)
+ *addrptr = startaddr;
if (b == NULL || PC_IN_CALL_DUMMY (pc, 0, 0))
sym = NULL;
else
@@ -950,41 +963,62 @@ find_proc_desc (pc, next_frame)
symbol reading. */
sym = NULL;
else
- sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE,
- 0, NULL);
+ sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL);
}
/* If we never found a PDR for this function in symbol reading, then
examine prologues to find the information. */
- if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1)
- sym = NULL;
-
if (sym)
{
- /* 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.
- */
- proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
- 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;
+ proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
+ if (PROC_FRAME_REG (proc_desc) == -1)
+ return NULL;
+ else
+ return proc_desc;
+ }
+ else
+ return NULL;
+}
+
+
+static mips_extra_func_info_t
+find_proc_desc (pc, next_frame)
+ CORE_ADDR 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) {
- mips_extra_func_info_t found_heuristic =
- heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
- pc, next_frame);
- if (found_heuristic)
- proc_desc = found_heuristic;
+ if (!proc_symbol || pc < val.pc)
+ {
+ mips_extra_func_info_t found_heuristic =
+ heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
+ pc, next_frame);
+ if (found_heuristic)
+ proc_desc = found_heuristic;
}
}
}
@@ -1570,7 +1604,7 @@ mips_step_skips_delay (pc)
char buf[MIPS_INSTLEN];
/* There is no branch delay slot on MIPS16. */
- if (pc & 1)
+ if (IS_MIPS16_ADDR (pc))
return 0;
if (target_read_memory (pc, buf, MIPS_INSTLEN) != 0)
@@ -1724,7 +1758,8 @@ mips16_skip_prologue (pc, lenient)
int prev_extend_bytes;
int i;
- status = read_memory_nobpt (pc & ~1, buf, MIPS16_INSTLEN);
+ status = read_memory_nobpt (UNMAKE_MIPS16_ADDR (pc), buf,
+ MIPS16_INSTLEN);
if (status)
memory_error (status, pc);
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
instructions. */
- if (pc & 1)
+ if (IS_MIPS16_ADDR (pc))
return mips16_skip_prologue (pc, lenient);
else
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,
the search would fail because the symbol table says the function
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
the procedure descriptor exists and the address therein is odd,
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. */
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
- info->mach = memaddr & 1 ? 16 : 0;
+ info->mach = IS_MIPS16_ADDR (memaddr) ? 16 : 0;
- /* 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. */
+ /* Round down the instruction address to the appropriate boundary. */
memaddr &= (info->mach == 16 ? ~1 : ~3);
/* 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 (*pcptr & 1)
+ if (IS_MIPS16_ADDR (*pcptr))
{
static char mips16_big_breakpoint[] = MIPS16_BIG_BREAKPOINT;
- *pcptr &= ~1;
+ *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
*lenptr = sizeof(mips16_big_breakpoint);
return mips16_big_breakpoint;
}
@@ -2099,10 +2132,10 @@ unsigned char *mips_breakpoint_from_pc (pcptr, lenptr)
}
else
{
- if (*pcptr & 1)
+ if (IS_MIPS16_ADDR (*pcptr))
{
static char mips16_little_breakpoint[] = MIPS16_LITTLE_BREAKPOINT;
- *pcptr &= ~1;
+ *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
*lenptr = sizeof(mips16_little_breakpoint);
return mips16_little_breakpoint;
}
@@ -2122,14 +2155,14 @@ int
mips_about_to_return (pc)
CORE_ADDR pc;
{
- if (pc & 1)
+ if (IS_MIPS16_ADDR (pc))
/* This mips16 case isn't necessarily reliable. Sometimes the compiler
generates a "jr $ra"; other times it generates code to load
the return address from the stack to an accessible register (such
as $a3), then a "jr" using that register. This second case
is almost impossible to distinguish from an indirect jump
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
return read_memory_integer (pc, 4) == 0x3e00008; /* jr $ra */
}