/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
- Copyright (C) 1988-2013 Free Software Foundation, Inc.
+ Copyright (C) 1988-2017 Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include "gdb_string.h"
-#include "gdb_assert.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "symcat.h"
#include "sim-regno.h"
#include "dis-asm.h"
+#include "disasm.h"
#include "frame-unwind.h"
#include "frame-base.h"
#include "trad-frame.h"
#include "user-regs.h"
#include "valprint.h"
#include "ax.h"
+#include <algorithm>
static const struct objfile_data *mips_pdr_data;
static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
-static int mips32_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR);
-static int micromips_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR,
- int);
-static int mips16_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR,
- int);
+static int mips32_instruction_has_delay_slot (struct gdbarch *gdbarch,
+ ULONGEST inst);
+static int micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32);
+static int mips16_instruction_has_delay_slot (unsigned short inst,
+ int mustbe32);
+
+static int mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr);
+static int micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32);
+static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32);
+
+static void mips_print_float_info (struct gdbarch *, struct ui_file *,
+ struct frame_info *, const char *);
/* A useful bit in the CP0 status register (MIPS_PS_REGNUM). */
/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */
NULL
};
+/* Enum describing the different kinds of breakpoints. */
+
+enum mips_breakpoint_kind
+{
+ /* 16-bit MIPS16 mode breakpoint. */
+ MIPS_BP_KIND_MIPS16 = 2,
+
+ /* 16-bit microMIPS mode breakpoint. */
+ MIPS_BP_KIND_MICROMIPS16 = 3,
+
+ /* 32-bit standard MIPS mode breakpoint. */
+ MIPS_BP_KIND_MIPS32 = 4,
+
+ /* 32-bit microMIPS mode breakpoint. */
+ MIPS_BP_KIND_MICROMIPS32 = 5,
+};
+
/* For backwards compatibility we default to MIPS16. This flag is
overridden as soon as unambiguous ELF file flags tell us the
compressed ISA encoding used. */
return ((addr) | (CORE_ADDR) 1);
}
+/* Extern version of unmake_compact_addr; we use a separate function
+ so that unmake_compact_addr can be inlined throughout this file. */
+
+CORE_ADDR
+mips_unmake_compact_addr (CORE_ADDR addr)
+{
+ return unmake_compact_addr (addr);
+}
+
/* Functions for setting and testing a bit in a minimal symbol that
marks it as MIPS16 or microMIPS function. The MSB of the minimal
symbol's "info" field is used for this purpose.
return;
if (ELF_ST_IS_MICROMIPS (st_other))
- MSYMBOL_TARGET_FLAG_2 (msym) = 1;
+ {
+ MSYMBOL_TARGET_FLAG_MICROMIPS (msym) = 1;
+ SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1);
+ }
else if (ELF_ST_IS_MIPS16 (st_other))
- MSYMBOL_TARGET_FLAG_1 (msym) = 1;
+ {
+ MSYMBOL_TARGET_FLAG_MIPS16 (msym) = 1;
+ SET_MSYMBOL_VALUE_ADDRESS (msym, MSYMBOL_VALUE_RAW_ADDRESS (msym) | 1);
+ }
}
/* Return one iff MSYM refers to standard ISA code. */
static int
msymbol_is_mips (struct minimal_symbol *msym)
{
- return !(MSYMBOL_TARGET_FLAG_1 (msym) | MSYMBOL_TARGET_FLAG_2 (msym));
+ return !(MSYMBOL_TARGET_FLAG_MIPS16 (msym)
+ | MSYMBOL_TARGET_FLAG_MICROMIPS (msym));
}
/* Return one iff MSYM refers to MIPS16 code. */
static int
msymbol_is_mips16 (struct minimal_symbol *msym)
{
- return MSYMBOL_TARGET_FLAG_1 (msym);
+ return MSYMBOL_TARGET_FLAG_MIPS16 (msym);
}
/* Return one iff MSYM refers to microMIPS code. */
static int
msymbol_is_micromips (struct minimal_symbol *msym)
{
- return MSYMBOL_TARGET_FLAG_2 (msym);
+ return MSYMBOL_TARGET_FLAG_MICROMIPS (msym);
+}
+
+/* Set the ISA bit in the main symbol too, complementing the corresponding
+ minimal symbol setting and reflecting the run-time value of the symbol.
+ The need for comes from the ISA bit having been cleared as code in
+ `_bfd_mips_elf_symbol_processing' separated it into the ELF symbol's
+ `st_other' STO_MIPS16 or STO_MICROMIPS annotation, making the values
+ of symbols referring to compressed code different in GDB to the values
+ used by actual code. That in turn makes them evaluate incorrectly in
+ expressions, producing results different to what the same expressions
+ yield when compiled into the program being debugged. */
+
+static void
+mips_make_symbol_special (struct symbol *sym, struct objfile *objfile)
+{
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* We are in symbol reading so it is OK to cast away constness. */
+ struct block *block = (struct block *) SYMBOL_BLOCK_VALUE (sym);
+ CORE_ADDR compact_block_start;
+ struct bound_minimal_symbol msym;
+
+ compact_block_start = BLOCK_START (block) | 1;
+ msym = lookup_minimal_symbol_by_pc (compact_block_start);
+ if (msym.minsym && !msymbol_is_mips (msym.minsym))
+ {
+ BLOCK_START (block) = compact_block_start;
+ }
+ }
}
/* XFER a value from the big/little/left end of the register.
"fsr", "fir",
};
-/* Names of IDT R3041 registers. */
-
-static const char *mips_r3041_reg_names[] = {
- "sr", "lo", "hi", "bad", "cause", "pc",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "fsr", "fir", "", /*"fp" */ "",
- "", "", "bus", "ccfg", "", "", "", "",
- "", "", "port", "cmp", "", "", "epc", "prid",
-};
-
/* Names of tx39 registers. */
static const char *mips_tx39_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
"", "", "config", "cache", "debug", "depc", "epc",
};
-/* Names of IRIX registers. */
-static const char *mips_irix_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "pc", "cause", "bad", "hi", "lo", "fsr", "fir"
-};
-
/* Names of registers with Linux kernels. */
static const char *mips_linux_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
"sr", "lo", "hi", "bad", "cause", "pc",
if (rawnum == mips_regnum (gdbarch)->fp_control_status
|| rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
return builtin_type (gdbarch)->builtin_int32;
- else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
- && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
+ else if (gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
&& rawnum >= MIPS_FIRST_EMBED_REGNUM
&& rawnum <= MIPS_LAST_EMBED_REGNUM)
/* The pseudo/cooked view of the embedded registers is always
if (TYPE_LENGTH (rawtype) == 0)
return rawtype;
+ /* Present the floating point registers however the hardware did;
+ do not try to convert between FPU layouts. */
if (mips_float_register_p (gdbarch, rawnum))
- /* Present the floating point registers however the hardware did;
- do not try to convert between FPU layouts. */
return rawtype;
+ /* Floating-point control registers are always 32-bit even though for
+ backwards compatibility reasons 64-bit targets will transfer them
+ as 64-bit quantities even if using XML descriptions. */
+ if (rawnum == mips_regnum (gdbarch)->fp_control_status
+ || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+ return builtin_type (gdbarch)->builtin_int32;
+
/* Use pointer types for registers if we can. For n32 we can not,
since we do not have a 64-bit pointer type. */
if (mips_abi_regsize (gdbarch)
&& rawnum < mips_regnum (gdbarch)->dspacc + 6)))
return builtin_type (gdbarch)->builtin_int32;
- if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
- && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
- && rawnum >= MIPS_EMBED_FP0_REGNUM + 32
+ /* The pseudo/cooked view of embedded registers is always
+ 32-bit, even if the target transfers 64-bit values for them.
+ New targets relying on XML descriptions should only transfer
+ the necessary 32 bits, but older versions of GDB expected 64,
+ so allow the target to provide 64 bits without interfering
+ with the displayed type. */
+ if (gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
+ && rawnum >= MIPS_FIRST_EMBED_REGNUM
&& rawnum <= MIPS_LAST_EMBED_REGNUM)
- {
- /* The pseudo/cooked view of embedded registers is always
- 32-bit, even if the target transfers 64-bit values for them.
- New targets relying on XML descriptions should only transfer
- the necessary 32 bits, but older versions of GDB expected 64,
- so allow the target to provide 64 bits without interfering
- with the displayed type. */
- return builtin_type (gdbarch)->builtin_int32;
- }
+ return builtin_type (gdbarch)->builtin_int32;
/* For all other registers, pass through the hardware type. */
return rawtype;
stored by elfread.c in the high bit of the info field. Use this
to decide if the function is standard MIPS. Otherwise if bit 0
of the address is clear, then this is a standard MIPS function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips (sym.minsym);
else
elfread.c in the high bit of the info field. Use this to decide
if the function is MIPS16. Otherwise if bit 0 of the address is
set, then ELF file flags will tell if this is a MIPS16 function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips16 (sym.minsym);
else
if the function is microMIPS. Otherwise if bit 0 of the address
is set, then ELF file flags will tell if this is a microMIPS
function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_micromips (sym.minsym);
else
this to decide if the function is MIPS16 or microMIPS or normal
MIPS. Otherwise if bit 0 of the address is set, then ELF file
flags will tell if this is a MIPS16 or a microMIPS function. */
- sym = lookup_minimal_symbol_by_pc (memaddr);
+ sym = lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
{
if (msymbol_is_micromips (sym.minsym))
}
}
+/* Set the ISA bit correctly in the PC, used by DWARF-2 machinery.
+ The need for comes from the ISA bit having been cleared, making
+ addresses in FDE, range records, etc. referring to compressed code
+ different to those in line information, the symbol table and finally
+ the PC register. That in turn confuses many operations. */
+
+static CORE_ADDR
+mips_adjust_dwarf2_addr (CORE_ADDR pc)
+{
+ pc = unmake_compact_addr (pc);
+ return mips_pc_is_mips (pc) ? pc : make_compact_addr (pc);
+}
+
+/* Recalculate the line record requested so that the resulting PC has
+ the ISA bit set correctly, used by DWARF-2 machinery. The need for
+ this adjustment comes from some records associated with compressed
+ code having the ISA bit cleared, most notably at function prologue
+ ends. The ISA bit is in this context retrieved from the minimal
+ symbol covering the address requested, which in turn has been
+ constructed from the binary's symbol table rather than DWARF-2
+ information. The correct setting of the ISA bit is required for
+ breakpoint addresses to correctly match against the stop PC.
+
+ As line entries can specify relative address adjustments we need to
+ keep track of the absolute value of the last line address recorded
+ in line information, so that we can calculate the actual address to
+ apply the ISA bit adjustment to. We use PC for this tracking and
+ keep the original address there.
+
+ As such relative address adjustments can be odd within compressed
+ code we need to keep track of the last line address with the ISA
+ bit adjustment applied too, as the original address may or may not
+ have had the ISA bit set. We use ADJ_PC for this tracking and keep
+ the adjusted address there.
+
+ For relative address adjustments we then use these variables to
+ calculate the address intended by line information, which will be
+ PC-relative, and return an updated adjustment carrying ISA bit
+ information, which will be ADJ_PC-relative. For absolute address
+ adjustments we just return the same address that we store in ADJ_PC
+ too.
+
+ As the first line entry can be relative to an implied address value
+ of 0 we need to have the initial address set up that we store in PC
+ and ADJ_PC. This is arranged with a call from `dwarf_decode_lines_1'
+ that sets PC to 0 and ADJ_PC accordingly, usually 0 as well. */
+
+static CORE_ADDR
+mips_adjust_dwarf2_line (CORE_ADDR addr, int rel)
+{
+ static CORE_ADDR adj_pc;
+ static CORE_ADDR pc;
+ CORE_ADDR isa_pc;
+
+ pc = rel ? pc + addr : addr;
+ isa_pc = mips_adjust_dwarf2_addr (pc);
+ addr = rel ? isa_pc - adj_pc : isa_pc;
+ adj_pc = isa_pc;
+ return addr;
+}
+
/* Various MIPS16 thunk (aka stub or trampoline) names. */
static const char mips_str_mips16_call_stub[] = "__mips16_call_stub_";
return 0;
/* If the PC is in __mips16_call_stub_*, this is a call/return stub. */
- if (strncmp (name, mips_str_mips16_call_stub,
- strlen (mips_str_mips16_call_stub)) == 0)
+ if (startswith (name, mips_str_mips16_call_stub))
return 1;
/* If the PC is in __call_stub_*, this is a call/return or a call stub. */
- if (strncmp (name, mips_str_call_stub, strlen (mips_str_call_stub)) == 0)
+ if (startswith (name, mips_str_call_stub))
return 1;
/* If the PC is in __fn_stub_*, this is a call stub. */
- if (strncmp (name, mips_str_fn_stub, strlen (mips_str_fn_stub)) == 0)
+ if (startswith (name, mips_str_fn_stub))
return 1;
return 0; /* Not a stub. */
LONGEST pc;
regcache_cooked_read_signed (regcache, regnum, &pc);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
return pc;
}
CORE_ADDR pc;
pc = frame_unwind_register_signed (next_frame, gdbarch_pc_regnum (gdbarch));
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
/* macro/2012-04-20: This hack skips over MIPS16 call thunks as
intermediate frames. In this case we can get the caller's address
from $ra, or if $ra contains an address within a thunk as well, then
{
pc = frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
if (mips_in_frame_stub (pc))
- {
- pc = frame_unwind_register_signed
- (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = frame_unwind_register_signed
+ (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
}
return pc;
}
{
int regnum = gdbarch_pc_regnum (get_regcache_arch (regcache));
- if (mips_pc_is_mips (pc))
- regcache_cooked_write_unsigned (regcache, regnum, pc);
- else
- regcache_cooked_write_unsigned (regcache, regnum, make_compact_addr (pc));
+ regcache_cooked_write_unsigned (regcache, regnum, pc);
}
/* Fetch and return instruction from the specified location. Handle
static ULONGEST
mips_fetch_instruction (struct gdbarch *gdbarch,
- enum mips_isa isa, CORE_ADDR addr, int *statusp)
+ enum mips_isa isa, CORE_ADDR addr, int *errp)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[MIPS_INSN32_SIZE];
int instlen;
- int status;
+ int err;
switch (isa)
{
internal_error (__FILE__, __LINE__, _("invalid ISA"));
break;
}
- status = target_read_memory (addr, buf, instlen);
- if (statusp != NULL)
- *statusp = status;
- if (status)
+ err = target_read_memory (addr, buf, instlen);
+ if (errp != NULL)
+ *errp = err;
+ if (err != 0)
{
- if (statusp == NULL)
- memory_error (status, addr);
+ if (errp == NULL)
+ memory_error (TARGET_XFER_E_IO, addr);
return 0;
}
return extract_unsigned_integer (buf, instlen, byte_order);
switch (isa)
{
case ISA_MICROMIPS:
- if (micromips_op (insn) == 0x1f)
- return 3 * MIPS_INSN16_SIZE;
- else if (((micromips_op (insn) & 0x4) == 0x4)
- || ((micromips_op (insn) & 0x7) == 0x0))
+ if ((micromips_op (insn) & 0x4) == 0x4
+ || (micromips_op (insn) & 0x7) == 0x0)
return 2 * MIPS_INSN16_SIZE;
else
return MIPS_INSN16_SIZE;
number of the floating condition bits tested by the branch. */
static CORE_ADDR
-mips32_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+mips32_bc1_pc (struct gdbarch *gdbarch, struct regcache *regcache,
ULONGEST inst, CORE_ADDR pc, int count)
{
int fcsr = mips_regnum (gdbarch)->fp_control_status;
/* No way to handle; it'll most likely trap anyway. */
return pc;
- fcs = get_frame_register_unsigned (frame, fcsr);
+ fcs = regcache_raw_get_unsigned (regcache, fcsr);
cond = ((fcs >> 24) & 0xfe) | ((fcs >> 23) & 0x01);
if (((cond >> cnum) & mask) != mask * !tf)
branch prediction. */
static CORE_ADDR
-mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
+mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
- struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
unsigned long inst;
int op;
inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
}
else if (op == 17 && itype_rs (inst) == 8)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
- pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 1);
+ pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 1);
else if (op == 17 && itype_rs (inst) == 9
&& (itype_rt (inst) & 2) == 0)
/* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
- pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 2);
+ pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 2);
else if (op == 17 && itype_rs (inst) == 10
&& (itype_rt (inst) & 2) == 0)
/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
- pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4);
+ pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 4);
else if (op == 29)
/* JALX: 011101 */
/* The new PC will be alternate mode. */
if (op == 54 || op == 62)
bit += 32;
- if (((get_frame_register_signed (frame,
- itype_rs (inst)) >> bit) & 1)
+ if (((regcache_raw_get_signed (regcache,
+ itype_rs (inst)) >> bit) & 1)
== branch_if)
pc += mips32_relative_offset (inst) + 4;
else
case 8: /* JR */
case 9: /* JALR */
/* Set PC to that address. */
- pc = get_frame_register_signed (frame, rtype_rs (inst));
+ pc = regcache_raw_get_signed (regcache, rtype_rs (inst));
break;
case 12: /* SYSCALL */
{
struct gdbarch_tdep *tdep;
- tdep = gdbarch_tdep (get_frame_arch (frame));
+ tdep = gdbarch_tdep (gdbarch);
if (tdep->syscall_next_pc != NULL)
- pc = tdep->syscall_next_pc (frame);
+ pc = tdep->syscall_next_pc (get_current_frame ());
else
pc += 4;
}
case 16: /* BLTZAL */
case 18: /* BLTZALL */
less_branch:
- if (get_frame_register_signed (frame, itype_rs (inst)) < 0)
+ if (regcache_raw_get_signed (regcache, itype_rs (inst)) < 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
case 3: /* BGEZL */
case 17: /* BGEZAL */
case 19: /* BGEZALL */
- if (get_frame_register_signed (frame, itype_rs (inst)) >= 0)
+ if (regcache_raw_get_signed (regcache, itype_rs (inst)) >= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
/* No way to handle; it'll most likely trap anyway. */
break;
- if ((get_frame_register_unsigned (frame,
- dspctl) & 0x7f) >= pos)
+ if ((regcache_raw_get_unsigned (regcache,
+ dspctl) & 0x7f) >= pos)
pc += mips32_relative_offset (inst);
else
pc += 4;
break;
case 4: /* BEQ, BEQL */
equal_branch:
- if (get_frame_register_signed (frame, itype_rs (inst)) ==
- get_frame_register_signed (frame, itype_rt (inst)))
+ if (regcache_raw_get_signed (regcache, itype_rs (inst)) ==
+ regcache_raw_get_signed (regcache, itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 5: /* BNE, BNEL */
neq_branch:
- if (get_frame_register_signed (frame, itype_rs (inst)) !=
- get_frame_register_signed (frame, itype_rt (inst)))
+ if (regcache_raw_get_signed (regcache, itype_rs (inst)) !=
+ regcache_raw_get_signed (regcache, itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 6: /* BLEZ, BLEZL */
- if (get_frame_register_signed (frame, itype_rs (inst)) <= 0)
+ if (regcache_raw_get_signed (regcache, itype_rs (inst)) <= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
case 7:
default:
greater_branch: /* BGTZ, BGTZL */
- if (get_frame_register_signed (frame, itype_rs (inst)) > 0)
+ if (regcache_raw_get_signed (regcache, itype_rs (inst)) > 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
examined by the branch. */
static CORE_ADDR
-micromips_bc1_pc (struct gdbarch *gdbarch, struct frame_info *frame,
+micromips_bc1_pc (struct gdbarch *gdbarch, struct regcache *regcache,
ULONGEST insn, CORE_ADDR pc, int count)
{
int fcsr = mips_regnum (gdbarch)->fp_control_status;
/* No way to handle; it'll most likely trap anyway. */
return pc;
- fcs = get_frame_register_unsigned (frame, fcsr);
+ fcs = regcache_raw_get_unsigned (regcache, fcsr);
cond = ((fcs >> 24) & 0xfe) | ((fcs >> 23) & 0x01);
if (((cond >> cnum) & mask) != mask * !tf)
after the instruction at the address PC. */
static CORE_ADDR
-micromips_next_pc (struct frame_info *frame, CORE_ADDR pc)
+micromips_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
- struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
ULONGEST insn;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
pc += MIPS_INSN16_SIZE;
switch (mips_insn_size (ISA_MICROMIPS, insn))
{
- /* 48-bit instructions. */
- case 3 * MIPS_INSN16_SIZE: /* POOL48A: bits 011111 */
- /* No branch or jump instructions in this category. */
- pc += 2 * MIPS_INSN16_SIZE;
- break;
-
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
insn <<= 16;
&& (b6s10_ext (insn) & 0x2bf) == 0x3c)
/* JALR, JALR.HB: 000000 000x111100 111100 */
/* JALRS, JALRS.HB: 000000 010x111100 111100 */
- pc = get_frame_register_signed (frame, b0s5_reg (insn >> 16));
+ pc = regcache_raw_get_signed (regcache, b0s5_reg (insn >> 16));
break;
case 0x10: /* POOL32I: bits 010000 */
case 0x00: /* BLTZ: bits 010000 00000 */
case 0x01: /* BLTZAL: bits 010000 00001 */
case 0x11: /* BLTZALS: bits 010000 10001 */
- if (get_frame_register_signed (frame,
- b0s5_reg (insn >> 16)) < 0)
+ if (regcache_raw_get_signed (regcache,
+ b0s5_reg (insn >> 16)) < 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
case 0x02: /* BGEZ: bits 010000 00010 */
case 0x03: /* BGEZAL: bits 010000 00011 */
case 0x13: /* BGEZALS: bits 010000 10011 */
- if (get_frame_register_signed (frame,
- b0s5_reg (insn >> 16)) >= 0)
+ if (regcache_raw_get_signed (regcache,
+ b0s5_reg (insn >> 16)) >= 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x04: /* BLEZ: bits 010000 00100 */
- if (get_frame_register_signed (frame,
- b0s5_reg (insn >> 16)) <= 0)
+ if (regcache_raw_get_signed (regcache,
+ b0s5_reg (insn >> 16)) <= 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x05: /* BNEZC: bits 010000 00101 */
- if (get_frame_register_signed (frame,
- b0s5_reg (insn >> 16)) != 0)
+ if (regcache_raw_get_signed (regcache,
+ b0s5_reg (insn >> 16)) != 0)
pc += micromips_relative_offset16 (insn);
break;
case 0x06: /* BGTZ: bits 010000 00110 */
- if (get_frame_register_signed (frame,
- b0s5_reg (insn >> 16)) > 0)
+ if (regcache_raw_get_signed (regcache,
+ b0s5_reg (insn >> 16)) > 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x07: /* BEQZC: bits 010000 00111 */
- if (get_frame_register_signed (frame,
- b0s5_reg (insn >> 16)) == 0)
+ if (regcache_raw_get_signed (regcache,
+ b0s5_reg (insn >> 16)) == 0)
pc += micromips_relative_offset16 (insn);
break;
/* No way to handle; it'll most likely trap anyway. */
break;
- if ((get_frame_register_unsigned (frame,
- dspctl) & 0x7f) >= pos)
+ if ((regcache_raw_get_unsigned (regcache,
+ dspctl) & 0x7f) >= pos)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
case 0x1d: /* BC1T: bits 010000 11101 xxx00 */
/* BC1ANY2T: bits 010000 11101 xxx01 */
if (((insn >> 16) & 0x2) == 0x0)
- pc = micromips_bc1_pc (gdbarch, frame, insn, pc,
+ pc = micromips_bc1_pc (gdbarch, regcache, insn, pc,
((insn >> 16) & 0x1) + 1);
break;
case 0x1e: /* BC1ANY4F: bits 010000 11110 xxx01 */
case 0x1f: /* BC1ANY4T: bits 010000 11111 xxx01 */
if (((insn >> 16) & 0x3) == 0x1)
- pc = micromips_bc1_pc (gdbarch, frame, insn, pc, 4);
+ pc = micromips_bc1_pc (gdbarch, regcache, insn, pc, 4);
break;
}
break;
break;
case 0x25: /* BEQ: bits 100101 */
- if (get_frame_register_signed (frame, b0s5_reg (insn >> 16))
- == get_frame_register_signed (frame, b5s5_reg (insn >> 16)))
+ if (regcache_raw_get_signed (regcache, b0s5_reg (insn >> 16))
+ == regcache_raw_get_signed (regcache, b5s5_reg (insn >> 16)))
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x2d: /* BNE: bits 101101 */
- if (get_frame_register_signed (frame, b0s5_reg (insn >> 16))
- != get_frame_register_signed (frame, b5s5_reg (insn >> 16)))
+ if (regcache_raw_get_signed (regcache, b0s5_reg (insn >> 16))
+ != regcache_raw_get_signed (regcache, b5s5_reg (insn >> 16)))
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
case 0x11: /* POOL16C: bits 010001 */
if ((b5s5_op (insn) & 0x1c) == 0xc)
/* JR16, JRC, JALR16, JALRS16: 010001 011xx */
- pc = get_frame_register_signed (frame, b0s5_reg (insn));
+ pc = regcache_raw_get_signed (regcache, b0s5_reg (insn));
else if (b5s5_op (insn) == 0x18)
/* JRADDIUSP: bits 010001 11000 */
- pc = get_frame_register_signed (frame, MIPS_RA_REGNUM);
+ pc = regcache_raw_get_signed (regcache, MIPS_RA_REGNUM);
break;
case 0x23: /* BEQZ16: bits 100011 */
{
int rs = mips_reg3_to_reg[b7s3_reg (insn)];
- if (get_frame_register_signed (frame, rs) == 0)
+ if (regcache_raw_get_signed (regcache, rs) == 0)
pc += micromips_relative_offset7 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
{
int rs = mips_reg3_to_reg[b7s3_reg (insn)];
- if (get_frame_register_signed (frame, rs) != 0)
+ if (regcache_raw_get_signed (regcache, rs) != 0)
pc += micromips_relative_offset7 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
}
+/* Calculate the destination of a branch whose 16-bit opcode word is at PC,
+ and having a signed 16-bit OFFSET. */
+
static CORE_ADDR
add_offset_16 (CORE_ADDR pc, int offset)
{
- return ((offset << 2) | ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)));
+ return pc + (offset << 1) + 2;
}
static CORE_ADDR
-extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
+extended_mips16_next_pc (regcache *regcache, CORE_ADDR pc,
unsigned int extension, unsigned int insn)
{
- struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
int op = (insn >> 11);
switch (op)
{
{
struct upk_mips16 upk;
unpack_mips16 (gdbarch, pc, extension, insn, itype, &upk);
- pc += (upk.offset << 1) + 2;
+ pc = add_offset_16 (pc, upk.offset);
break;
}
case 3: /* JAL , JALX - Watch out, these are 32 bit
{
struct upk_mips16 upk;
unpack_mips16 (gdbarch, pc, extension, insn, jalxtype, &upk);
- pc = add_offset_16 (pc, upk.offset);
+ pc = ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)) | (upk.offset << 2);
if ((insn >> 10) & 0x01) /* Exchange mode */
pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode. */
else
struct upk_mips16 upk;
int reg;
unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
- reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]);
+ reg = regcache_raw_get_signed (regcache, mips_reg3_to_reg[upk.regx]);
if (reg == 0)
- pc += (upk.offset << 1) + 2;
+ pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
struct upk_mips16 upk;
int reg;
unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
- reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]);
+ reg = regcache_raw_get_signed (regcache, mips_reg3_to_reg[upk.regx]);
if (reg != 0)
- pc += (upk.offset << 1) + 2;
+ pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
int reg;
unpack_mips16 (gdbarch, pc, extension, insn, i8type, &upk);
/* upk.regx contains the opcode */
- reg = get_frame_register_signed (frame, 24); /* Test register is 24 */
+ /* Test register is 24 */
+ reg = regcache_raw_get_signed (regcache, 24);
if (((upk.regx == 0) && (reg == 0)) /* BTEZ */
|| ((upk.regx == 1) && (reg != 0))) /* BTNEZ */
- /* pc = add_offset_16(pc,upk.offset) ; */
- pc += (upk.offset << 1) + 2;
+ pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
reg = mips_reg3_to_reg[upk.regx];
else
reg = 31; /* Function return instruction. */
- pc = get_frame_register_signed (frame, reg);
+ pc = regcache_raw_get_signed (regcache, reg);
}
else
pc += 2;
that. */
{
pc += 2;
- pc = extended_mips16_next_pc (frame, pc, insn,
+ pc = extended_mips16_next_pc (regcache, pc, insn,
fetch_mips_16 (gdbarch, pc));
break;
}
}
static CORE_ADDR
-mips16_next_pc (struct frame_info *frame, CORE_ADDR pc)
+mips16_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
- struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
unsigned int insn = fetch_mips_16 (gdbarch, pc);
- return extended_mips16_next_pc (frame, pc, 0, insn);
+ return extended_mips16_next_pc (regcache, pc, 0, insn);
}
/* The mips_next_pc function supports single_step when the remote
branch will go. This isn't hard because all the data is available.
The MIPS32, MIPS16 and microMIPS variants are quite different. */
static CORE_ADDR
-mips_next_pc (struct frame_info *frame, CORE_ADDR pc)
+mips_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
- struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
if (mips_pc_is_mips16 (gdbarch, pc))
- return mips16_next_pc (frame, pc);
+ return mips16_next_pc (regcache, pc);
else if (mips_pc_is_micromips (gdbarch, pc))
- return micromips_next_pc (frame, pc);
+ return micromips_next_pc (regcache, pc);
else
- return mips32_next_pc (frame, pc);
+ return mips32_next_pc (regcache, pc);
+}
+
+/* Return non-zero if the MIPS16 instruction INSN is a compact branch
+ or jump. */
+
+static int
+mips16_instruction_is_compact_branch (unsigned short insn)
+{
+ switch (insn & 0xf800)
+ {
+ case 0xe800:
+ return (insn & 0x009f) == 0x80; /* JALRC/JRC */
+ case 0x6000:
+ return (insn & 0x0600) == 0; /* BTNEZ/BTEQZ */
+ case 0x2800: /* BNEZ */
+ case 0x2000: /* BEQZ */
+ case 0x1000: /* B */
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Return non-zero if the microMIPS instruction INSN is a compact branch
+ or jump. */
+
+static int
+micromips_instruction_is_compact_branch (unsigned short insn)
+{
+ switch (micromips_op (insn))
+ {
+ case 0x11: /* POOL16C: bits 010001 */
+ return (b5s5_op (insn) == 0x18
+ /* JRADDIUSP: bits 010001 11000 */
+ || b5s5_op (insn) == 0xd);
+ /* JRC: bits 010011 01101 */
+ case 0x10: /* POOL32I: bits 010000 */
+ return (b5s5_op (insn) & 0x1d) == 0x5;
+ /* BEQZC/BNEZC: bits 010000 001x1 */
+ default:
+ return 0;
+ }
}
struct mips_frame_cache
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
+ int prev_non_prologue_insn = 0;
+ int this_non_prologue_insn;
+ int non_prologue_insns = 0;
+ CORE_ADDR prev_pc;
CORE_ADDR cur_pc;
CORE_ADDR frame_addr = 0; /* Value of $r17, used as frame pointer. */
CORE_ADDR sp;
unsigned inst = 0; /* current instruction */
unsigned entry_inst = 0; /* the entry instruction */
unsigned save_inst = 0; /* the save instruction */
+ int prev_delay_slot = 0;
+ int in_delay_slot;
int reg, offset;
int extend_bytes = 0;
- int prev_extend_bytes;
- CORE_ADDR end_prologue_addr = 0;
+ int prev_extend_bytes = 0;
+ CORE_ADDR end_prologue_addr;
/* Can be called when there's no process, and hence when there's no
THIS_FRAME. */
if (limit_pc > start_pc + 200)
limit_pc = start_pc + 200;
+ prev_pc = start_pc;
+ /* Permit at most one non-prologue non-control-transfer instruction
+ in the middle which may have been reordered by the compiler for
+ optimisation. */
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN16_SIZE)
{
+ this_non_prologue_insn = 0;
+ in_delay_slot = 0;
+
/* Save the previous instruction. If it's an EXTEND, we'll extract
the immediate offset extension from it in mips16_get_imm. */
prev_inst = inst;
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 */
{
/* This instruction is part of the prologue, but we don't
need to do anything special to handle it. */
}
+ else if (mips16_instruction_has_delay_slot (inst, 0))
+ /* JAL/JALR/JALX/JR */
+ {
+ /* The instruction in the delay slot can be a part
+ of the prologue, so move forward once more. */
+ in_delay_slot = 1;
+ if (mips16_instruction_has_delay_slot (inst, 1))
+ /* JAL/JALX */
+ {
+ prev_extend_bytes = MIPS_INSN16_SIZE;
+ cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
+ }
+ }
else
{
- /* This instruction is not an instruction typically found
- in a prologue, so we must have reached the end of the
- prologue. */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc - prev_extend_bytes;
+ this_non_prologue_insn = 1;
}
+
+ non_prologue_insns += this_non_prologue_insn;
+
+ /* A jump or branch, or enough non-prologue insns seen? If so,
+ then we must have reached the end of the prologue by now. */
+ if (prev_delay_slot || non_prologue_insns > 1
+ || mips16_instruction_is_compact_branch (inst))
+ break;
+
+ prev_non_prologue_insn = this_non_prologue_insn;
+ prev_delay_slot = in_delay_slot;
+ prev_pc = cur_pc - prev_extend_bytes;
}
/* The entry instruction is typically the first instruction in a function,
= this_cache->saved_regs[gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM];
}
- /* If we didn't reach the end of the prologue when scanning the function
- instructions, then set end_prologue_addr to the address of the
- instruction immediately after the last one we scanned. */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc;
+ /* Set end_prologue_addr to the address of the instruction immediately
+ after the last one we scanned. Unless the last one looked like a
+ non-prologue instruction (and we looked ahead), in which case use
+ its address instead. */
+ end_prologue_addr = (prev_non_prologue_insn || prev_delay_slot
+ ? prev_pc : cur_pc - prev_extend_bytes);
return end_prologue_addr;
}
struct mips_frame_cache *cache;
if ((*this_cache) != NULL)
- return (*this_cache);
+ return (struct mips_frame_cache *) (*this_cache);
cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
(*this_cache) = cache;
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
if (start_addr == 0)
return cache;
- mips16_scan_prologue (gdbarch, start_addr, pc, this_frame, *this_cache);
+ mips16_scan_prologue (gdbarch, start_addr, pc, this_frame,
+ (struct mips_frame_cache *) *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
cache->base);
- return (*this_cache);
+ return (struct mips_frame_cache *) (*this_cache);
}
static void
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
- CORE_ADDR end_prologue_addr = 0;
+ CORE_ADDR end_prologue_addr;
int prev_non_prologue_insn = 0;
int frame_reg = MIPS_SP_REGNUM;
int this_non_prologue_insn;
int non_prologue_insns = 0;
long frame_offset = 0; /* Size of stack frame. */
long frame_adjust = 0; /* Offset of FP from SP. */
- CORE_ADDR frame_addr = 0; /* Value of $30, used as frame pointer. */
+ int prev_delay_slot = 0;
+ int in_delay_slot;
CORE_ADDR prev_pc;
CORE_ADDR cur_pc;
ULONGEST insn; /* current instruction */
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += loc)
{
this_non_prologue_insn = 0;
+ in_delay_slot = 0;
sp_adj = 0;
loc = 0;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, cur_pc, NULL);
loc += MIPS_INSN16_SIZE;
switch (mips_insn_size (ISA_MICROMIPS, insn))
{
- /* 48-bit instructions. */
- case 3 * MIPS_INSN16_SIZE:
- /* No prologue instructions in this category. */
- this_non_prologue_insn = 1;
- loc += 2 * MIPS_INSN16_SIZE;
- break;
-
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
insn <<= 16;
&& ((reglist >= 1 && reglist <= 9)
|| (reglist >= 16 && reglist <= 25)))
{
- int sreglist = min(reglist & 0xf, 8);
+ int sreglist = std::min(reglist & 0xf, 8);
s = 4 << ((b12s4_op (insn) & 0x2) == 0x2);
for (i = 0; i < sreglist; i++)
else if (sreg == MIPS_SP_REGNUM && dreg == 30)
/* (D)ADDIU $fp, $sp, imm */
{
- frame_addr = sp + offset;
frame_adjust = offset;
frame_reg = 30;
}
break;
default:
- this_non_prologue_insn = 1;
+ /* The instruction in the delay slot can be a part
+ of the prologue, so move forward once more. */
+ if (micromips_instruction_has_delay_slot (insn, 0))
+ in_delay_slot = 1;
+ else
+ this_non_prologue_insn = 1;
break;
}
+ insn >>= 16;
break;
/* 16-bit instructions. */
dreg = b5s5_reg (insn);
if (sreg == MIPS_SP_REGNUM && dreg == 30)
/* MOVE $fp, $sp */
- {
- frame_addr = sp;
- frame_reg = 30;
- }
+ frame_reg = 30;
else if ((sreg & 0x1c) != 0x4)
/* MOVE reg, $a0-$a3 */
this_non_prologue_insn = 1;
break;
default:
- this_non_prologue_insn = 1;
+ /* The instruction in the delay slot can be a part
+ of the prologue, so move forward once more. */
+ if (micromips_instruction_has_delay_slot (insn << 16, 0))
+ in_delay_slot = 1;
+ else
+ this_non_prologue_insn = 1;
break;
}
break;
frame_offset -= sp_adj;
non_prologue_insns += this_non_prologue_insn;
- /* Enough non-prologue insns seen or positive stack adjustment? */
- if (end_prologue_addr == 0 && (non_prologue_insns > 1 || sp_adj > 0))
- {
- end_prologue_addr = prev_non_prologue_insn ? prev_pc : cur_pc;
- break;
- }
+
+ /* A jump or branch, enough non-prologue insns seen or positive
+ stack adjustment? If so, then we must have reached the end
+ of the prologue by now. */
+ if (prev_delay_slot || non_prologue_insns > 1 || sp_adj > 0
+ || micromips_instruction_is_compact_branch (insn))
+ break;
+
prev_non_prologue_insn = this_non_prologue_insn;
+ prev_delay_slot = in_delay_slot;
prev_pc = cur_pc;
}
= this_cache->saved_regs[gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM];
}
- /* If we didn't reach the end of the prologue when scanning the function
- instructions, then set end_prologue_addr to the address of the
- instruction immediately after the last one we scanned. Unless the
- last one looked like a non-prologue instruction (and we looked ahead),
- in which case use its address instead. */
- if (end_prologue_addr == 0)
- end_prologue_addr = prev_non_prologue_insn ? prev_pc : cur_pc;
+ /* Set end_prologue_addr to the address of the instruction immediately
+ after the last one we scanned. Unless the last one looked like a
+ non-prologue instruction (and we looked ahead), in which case use
+ its address instead. */
+ end_prologue_addr
+ = prev_non_prologue_insn || prev_delay_slot ? prev_pc : cur_pc;
return end_prologue_addr;
}
struct mips_frame_cache *cache;
if ((*this_cache) != NULL)
- return (*this_cache);
+ return (struct mips_frame_cache *) (*this_cache);
cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
(*this_cache) = cache;
if (start_addr == 0)
return cache;
- micromips_scan_prologue (gdbarch, start_addr, pc, this_frame, *this_cache);
+ micromips_scan_prologue (gdbarch, start_addr, pc, this_frame,
+ (struct mips_frame_cache *) *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
cache->base);
- return (*this_cache);
+ return (struct mips_frame_cache *) (*this_cache);
}
static void
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
- CORE_ADDR cur_pc;
+ int prev_non_prologue_insn;
+ int this_non_prologue_insn;
+ int non_prologue_insns;
CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for
frame-pointer. */
+ int prev_delay_slot;
+ CORE_ADDR prev_pc;
+ CORE_ADDR cur_pc;
CORE_ADDR sp;
long frame_offset;
int frame_reg = MIPS_SP_REGNUM;
- CORE_ADDR end_prologue_addr = 0;
+ CORE_ADDR end_prologue_addr;
int seen_sp_adjust = 0;
int load_immediate_bytes = 0;
- int in_delay_slot = 0;
+ int in_delay_slot;
int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
/* Can be called when there's no process, and hence when there's no
limit_pc = start_pc + 200;
restart:
+ prev_non_prologue_insn = 0;
+ non_prologue_insns = 0;
+ prev_delay_slot = 0;
+ prev_pc = start_pc;
+ /* Permit at most one non-prologue non-control-transfer instruction
+ in the middle which may have been reordered by the compiler for
+ optimisation. */
frame_offset = 0;
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN32_SIZE)
{
- unsigned long inst, high_word, low_word;
+ unsigned long inst, high_word;
+ long offset;
int reg;
+ this_non_prologue_insn = 0;
+ in_delay_slot = 0;
+
/* Fetch the instruction. */
inst = (unsigned long) mips_fetch_instruction (gdbarch, ISA_MIPS,
cur_pc, NULL);
/* Save some code by pre-extracting some useful fields. */
high_word = (inst >> 16) & 0xffff;
- low_word = inst & 0xffff;
+ offset = ((inst & 0xffff) ^ 0x8000) - 0x8000;
reg = high_word & 0x1f;
if (high_word == 0x27bd /* addiu $sp,$sp,-i */
|| high_word == 0x23bd /* addi $sp,$sp,-i */
|| high_word == 0x67bd) /* daddiu $sp,$sp,-i */
{
- if (low_word & 0x8000) /* Negative stack adjustment? */
- frame_offset += 0x10000 - low_word;
+ if (offset < 0) /* Negative stack adjustment? */
+ frame_offset -= offset;
else
/* Exit loop if a positive stack adjustment is found, which
usually means that the stack cleanup code in the function
else if (((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
&& !regsize_is_64_bits)
{
- set_reg_offset (gdbarch, this_cache, reg, sp + low_word);
+ set_reg_offset (gdbarch, this_cache, reg, sp + offset);
}
else if (((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
&& regsize_is_64_bits)
{
/* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */
- set_reg_offset (gdbarch, this_cache, reg, sp + low_word);
+ set_reg_offset (gdbarch, this_cache, reg, sp + offset);
}
else if (high_word == 0x27be) /* addiu $30,$sp,size */
{
/* Old gcc frame, r30 is virtual frame pointer. */
- if ((long) low_word != frame_offset)
- frame_addr = sp + low_word;
+ if (offset != frame_offset)
+ frame_addr = sp + offset;
else if (this_frame && frame_reg == MIPS_SP_REGNUM)
{
unsigned alloca_adjust;
(this_frame, gdbarch_num_regs (gdbarch) + 30);
frame_offset = 0;
- alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
+ alloca_adjust = (unsigned) (frame_addr - (sp + offset));
if (alloca_adjust > 0)
{
/* FP > SP + frame_size. This may be because of
else if ((high_word & 0xFFE0) == 0xafc0 /* sw reg,offset($30) */
&& !regsize_is_64_bits)
{
- set_reg_offset (gdbarch, this_cache, reg, frame_addr + low_word);
+ set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset);
}
else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */
|| (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */
initialize a local variable, so we accept them only before
a stack adjustment instruction was seen. */
else if (!seen_sp_adjust
+ && !prev_delay_slot
&& (high_word == 0x3c01 /* lui $at,n */
|| high_word == 0x3c08 /* lui $t0,n */
|| high_word == 0x3421 /* ori $at,$at,n */
|| high_word == 0x3408 /* ori $t0,$zero,n */
))
{
- if (end_prologue_addr == 0)
- load_immediate_bytes += MIPS_INSN32_SIZE; /* FIXME! */
+ load_immediate_bytes += MIPS_INSN32_SIZE; /* FIXME! */
+ }
+ /* Check for branches and jumps. The instruction in the delay
+ slot can be a part of the prologue, so move forward once more. */
+ else if (mips32_instruction_has_delay_slot (gdbarch, inst))
+ {
+ in_delay_slot = 1;
}
+ /* This instruction is not an instruction typically found
+ in a prologue, so we must have reached the end of the
+ prologue. */
else
{
- /* This instruction is not an instruction typically found
- in a prologue, so we must have reached the end of the
- prologue. */
- /* FIXME: brobecker/2004-10-10: Can't we just break out of this
- loop now? Why would we need to continue scanning the function
- instructions? */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc;
-
- /* Check for branches and jumps. For now, only jump to
- register are caught (i.e. returns). */
- if ((itype_op (inst) & 0x07) == 0 && rtype_funct (inst) == 8)
- in_delay_slot = 1;
+ this_non_prologue_insn = 1;
}
- /* If the previous instruction was a jump, we must have reached
- the end of the prologue by now. Stop scanning so that we do
- not go past the function return. */
- if (in_delay_slot)
+ non_prologue_insns += this_non_prologue_insn;
+
+ /* A jump or branch, or enough non-prologue insns seen? If so,
+ then we must have reached the end of the prologue by now. */
+ if (prev_delay_slot || non_prologue_insns > 1)
break;
+
+ prev_non_prologue_insn = this_non_prologue_insn;
+ prev_delay_slot = in_delay_slot;
+ prev_pc = cur_pc;
}
if (this_cache != NULL)
+ MIPS_RA_REGNUM];
}
- /* If we didn't reach the end of the prologue when scanning the function
- instructions, then set end_prologue_addr to the address of the
- instruction immediately after the last one we scanned. */
- /* brobecker/2004-10-10: I don't think this would ever happen, but
- we may as well be careful and do our best if we have a null
- end_prologue_addr. */
- if (end_prologue_addr == 0)
- end_prologue_addr = cur_pc;
+ /* Set end_prologue_addr to the address of the instruction immediately
+ after the last one we scanned. Unless the last one looked like a
+ non-prologue instruction (and we looked ahead), in which case use
+ its address instead. */
+ end_prologue_addr
+ = prev_non_prologue_insn || prev_delay_slot ? prev_pc : cur_pc;
/* In a frameless function, we might have incorrectly
skipped some load immediate instructions. Undo the skipping
struct mips_frame_cache *cache;
if ((*this_cache) != NULL)
- return (*this_cache);
+ return (struct mips_frame_cache *) (*this_cache);
cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
(*this_cache) = cache;
if (start_addr == 0)
return cache;
- mips32_scan_prologue (gdbarch, start_addr, pc, this_frame, *this_cache);
+ mips32_scan_prologue (gdbarch, start_addr, pc, this_frame,
+ (struct mips_frame_cache *) *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
cache->base);
- return (*this_cache);
+ return (struct mips_frame_cache *) (*this_cache);
}
static void
int num_regs = gdbarch_num_regs (gdbarch);
if ((*this_cache) != NULL)
- return (*this_cache);
+ return (struct trad_frame_cache *) (*this_cache);
this_trad_cache = trad_frame_cache_zalloc (this_frame);
(*this_cache) = this_trad_cache;
stub. The stub for foo is named ".pic.foo". */
msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym != NULL
- && SYMBOL_LINKAGE_NAME (msym.minsym) != NULL
- && strncmp (SYMBOL_LINKAGE_NAME (msym.minsym), ".pic.", 5) == 0)
+ && MSYMBOL_LINKAGE_NAME (msym.minsym) != NULL
+ && startswith (MSYMBOL_LINKAGE_NAME (msym.minsym), ".pic."))
return 1;
return 0;
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (is_compact_addr (addr))
- addr = unmake_compact_addr (addr);
-
if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
/* This hack is a work-around for existing boards using PMON, the
simulator, and any other 64-bit targets that doesn't have true
#define SC_OPCODE 0x38
#define SCD_OPCODE 0x3c
-static int
-mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
- struct address_space *aspace, CORE_ADDR pc)
+static VEC (CORE_ADDR) *
+mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR breaks[2] = {-1, -1};
CORE_ADDR loc = pc;
int index;
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
const int atomic_sequence_length = 16; /* Instruction sequence length. */
+ VEC (CORE_ADDR) *next_pcs = NULL;
insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL);
/* Assume all atomic sequences start with a ll/lld instruction. */
if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
- return 0;
+ return NULL;
/* Assume that no atomic sequence is longer than "atomic_sequence_length"
instructions. */
/* Assume that the atomic sequence ends with a sc/scd instruction. */
if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE)
- return 0;
+ return NULL;
loc += MIPS_INSN32_SIZE;
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
- insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
+ VEC_safe_push (CORE_ADDR, next_pcs, breaks[index]);
- return 1;
+ return next_pcs;
}
-static int
+static VEC (CORE_ADDR) *
micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
- struct address_space *aspace,
CORE_ADDR pc)
{
const int atomic_sequence_length = 16; /* Instruction sequence length. */
ULONGEST insn;
int insn_count;
int index;
+ VEC (CORE_ADDR) *next_pcs = NULL;
/* Assume all atomic sequences start with a ll/lld instruction. */
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL);
if (micromips_op (insn) != 0x18) /* POOL32C: bits 011000 */
- return 0;
+ return NULL;
loc += MIPS_INSN16_SIZE;
insn <<= 16;
insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL);
if ((b12s4_op (insn) & 0xb) != 0x3) /* LL, LLD: bits 011000 0x11 */
- return 0;
+ return NULL;
loc += MIPS_INSN16_SIZE;
/* Assume all atomic sequences end with an sc/scd instruction. Assume
its destination address. */
switch (mips_insn_size (ISA_MICROMIPS, insn))
{
- /* 48-bit instructions. */
- case 3 * MIPS_INSN16_SIZE: /* POOL48A: bits 011111 */
- loc += 2 * MIPS_INSN16_SIZE;
- break;
-
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
switch (micromips_op (insn))
&& b5s5_op (insn) != 0x18)
/* JRADDIUSP: bits 010001 11000 */
break;
- return 0; /* Fall back to the standard single-step code. */
+ return NULL; /* Fall back to the standard single-step code. */
case 0x33: /* B16: bits 110011 */
- return 0; /* Fall back to the standard single-step code. */
+ return NULL; /* Fall back to the standard single-step code. */
}
break;
}
if (is_branch)
{
if (last_breakpoint >= 1)
- return 0; /* More than one branch found, fallback to the
+ return NULL; /* More than one branch found, fallback to the
standard single-step code. */
breaks[1] = branch_bp;
last_breakpoint++;
}
}
if (!sc_found)
- return 0;
+ return NULL;
/* Insert a breakpoint right after the end of the atomic sequence. */
breaks[0] = loc;
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
- insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
+ VEC_safe_push (CORE_ADDR, next_pcs, breaks[index]);
- return 1;
+ return next_pcs;
}
-static int
-deal_with_atomic_sequence (struct gdbarch *gdbarch,
- struct address_space *aspace, CORE_ADDR pc)
+static VEC (CORE_ADDR) *
+deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
{
if (mips_pc_is_mips (pc))
- return mips_deal_with_atomic_sequence (gdbarch, aspace, pc);
+ return mips_deal_with_atomic_sequence (gdbarch, pc);
else if (mips_pc_is_micromips (gdbarch, pc))
- return micromips_deal_with_atomic_sequence (gdbarch, aspace, pc);
+ return micromips_deal_with_atomic_sequence (gdbarch, pc);
else
- return 0;
+ return NULL;
}
/* mips_software_single_step() is called just before we want to resume
or kernel single-step support (MIPS on GNU/Linux for example). We find
the target of the coming instruction and breakpoint it. */
-int
-mips_software_single_step (struct frame_info *frame)
+VEC (CORE_ADDR) *
+mips_software_single_step (struct regcache *regcache)
{
- struct gdbarch *gdbarch = get_frame_arch (frame);
- struct address_space *aspace = get_frame_address_space (frame);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
CORE_ADDR pc, next_pc;
+ VEC (CORE_ADDR) *next_pcs;
- pc = get_frame_pc (frame);
- if (deal_with_atomic_sequence (gdbarch, aspace, pc))
- return 1;
+ pc = regcache_read_pc (regcache);
+ next_pcs = deal_with_atomic_sequence (gdbarch, pc);
+ if (next_pcs != NULL)
+ return next_pcs;
- next_pc = mips_next_pc (frame, pc);
+ next_pc = mips_next_pc (regcache, pc);
- insert_single_step_breakpoint (gdbarch, aspace, next_pc);
- return 1;
+ VEC_safe_push (CORE_ADDR, next_pcs, next_pc);
+ return next_pcs;
}
/* Test whether the PC points to the return instruction at the
"mips_eabi_push_dummy_call: %d len=%d type=%d",
argnum + 1, len, (int) typecode);
- /* Function pointer arguments to mips16 code need to be made into
- mips16 pointers. */
- if (typecode == TYPE_CODE_PTR
- && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
- {
- CORE_ADDR addr = extract_signed_integer (value_contents (arg),
- len, byte_order);
- if (mips_pc_is_mips (addr))
- val = value_contents (arg);
- else
- {
- store_signed_integer (valbuf, len, byte_order,
- make_compact_addr (addr));
- val = valbuf;
- }
- }
/* The EABI passes structures that do not fit in a register by
reference. */
- else if (len > regsize
+ if (len > regsize
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
store_unsigned_integer (valbuf, regsize, byte_order,
}
while (len > 0)
{
- /* Remember if the argument was written to the stack. */
- int stack_used_p = 0;
int partial_len = (len < MIPS32_REGSIZE ? len : MIPS32_REGSIZE);
if (mips_debug)
promoted to int before being stored? */
int longword_offset = 0;
CORE_ADDR addr;
- stack_used_p = 1;
if (mips_debug)
{
for (argnum = 0; argnum < nargs; argnum++)
{
const gdb_byte *val;
- gdb_byte valbuf[MAX_REGISTER_SIZE];
struct value *arg = args[argnum];
struct type *arg_type = check_typedef (value_type (arg));
int len = TYPE_LENGTH (arg_type);
val = value_contents (arg);
- /* Function pointer arguments to mips16 code need to be made into
- mips16 pointers. */
- if (typecode == TYPE_CODE_PTR
- && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
- {
- CORE_ADDR addr = extract_signed_integer (value_contents (arg),
- len, byte_order);
- if (!mips_pc_is_mips (addr))
- {
- store_signed_integer (valbuf, len, byte_order,
- make_compact_addr (addr));
- val = valbuf;
- }
- }
-
/* Floating point arguments passed in registers have to be
treated specially. On 32-bit architectures, doubles are
passed in register pairs; the even FP register gets the
&& len % MIPS64_REGSIZE != 0);
while (len > 0)
{
- /* Remember if the argument was written to the stack. */
- int stack_used_p = 0;
int partial_len = (len < MIPS64_REGSIZE ? len : MIPS64_REGSIZE);
if (mips_debug)
promoted to int before being stored? */
int longword_offset = 0;
CORE_ADDR addr;
- stack_used_p = 1;
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
if ((typecode == TYPE_CODE_INT
{
struct gdbarch *gdbarch = get_frame_arch (frame);
int raw_size = register_size (gdbarch, regno);
- gdb_byte *raw_buffer = alloca (raw_size);
+ gdb_byte *raw_buffer = (gdb_byte *) alloca (raw_size);
if (!deprecated_frame_register_read (frame, regno, raw_buffer))
error (_("can't read register %d (%s)"),
double doub, flt1; /* Doubles extracted from raw hex data. */
int inv1, inv2;
- raw_buffer = alloca (2 * register_size (gdbarch,
- mips_regnum (gdbarch)->fp0));
+ raw_buffer
+ = ((gdb_byte *)
+ alloca (2 * register_size (gdbarch, mips_regnum (gdbarch)->fp0)));
fprintf_filtered (file, "%s:", gdbarch_register_name (gdbarch, regnum));
fprintf_filtered (file, "%*s",
}
val = get_frame_register_value (frame, regnum);
- if (value_optimized_out (val))
- {
- fprintf_filtered (file, "%s: [Invalid]",
- gdbarch_register_name (gdbarch, regnum));
- return;
- }
fputs_filtered (gdbarch_register_name (gdbarch, regnum), file);
get_formatted_print_options (&opts, 'x');
val_print_scalar_formatted (value_type (val),
- value_contents_for_printing (val),
value_embedded_offset (val),
val,
&opts, 0, file);
}
+/* Print IEEE exception condition bits in FLAGS. */
+
+static void
+print_fpu_flags (struct ui_file *file, int flags)
+{
+ if (flags & (1 << 0))
+ fputs_filtered (" inexact", file);
+ if (flags & (1 << 1))
+ fputs_filtered (" uflow", file);
+ if (flags & (1 << 2))
+ fputs_filtered (" oflow", file);
+ if (flags & (1 << 3))
+ fputs_filtered (" div0", file);
+ if (flags & (1 << 4))
+ fputs_filtered (" inval", file);
+ if (flags & (1 << 5))
+ fputs_filtered (" unimp", file);
+ fputc_filtered ('\n', file);
+}
+
+/* Print interesting information about the floating point processor
+ (if present) or emulator. */
+
+static void
+mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+ struct frame_info *frame, const char *args)
+{
+ int fcsr = mips_regnum (gdbarch)->fp_control_status;
+ enum mips_fpu_type type = MIPS_FPU_TYPE (gdbarch);
+ ULONGEST fcs = 0;
+ int i;
+
+ if (fcsr == -1 || !read_frame_register_unsigned (frame, fcsr, &fcs))
+ type = MIPS_FPU_NONE;
+
+ fprintf_filtered (file, "fpu type: %s\n",
+ type == MIPS_FPU_DOUBLE ? "double-precision"
+ : type == MIPS_FPU_SINGLE ? "single-precision"
+ : "none / unused");
+
+ if (type == MIPS_FPU_NONE)
+ return;
+
+ fprintf_filtered (file, "reg size: %d bits\n",
+ register_size (gdbarch, mips_regnum (gdbarch)->fp0) * 8);
+
+ fputs_filtered ("cond :", file);
+ if (fcs & (1 << 23))
+ fputs_filtered (" 0", file);
+ for (i = 1; i <= 7; i++)
+ if (fcs & (1 << (24 + i)))
+ fprintf_filtered (file, " %d", i);
+ fputc_filtered ('\n', file);
+
+ fputs_filtered ("cause :", file);
+ print_fpu_flags (file, (fcs >> 12) & 0x3f);
+ fputs ("mask :", stdout);
+ print_fpu_flags (file, (fcs >> 7) & 0x1f);
+ fputs ("flags :", stdout);
+ print_fpu_flags (file, (fcs >> 2) & 0x1f);
+
+ fputs_filtered ("rounding: ", file);
+ switch (fcs & 3)
+ {
+ case 0: fputs_filtered ("nearest\n", file); break;
+ case 1: fputs_filtered ("zero\n", file); break;
+ case 2: fputs_filtered ("+inf\n", file); break;
+ case 3: fputs_filtered ("-inf\n", file); break;
+ }
+
+ fputs_filtered ("flush :", file);
+ if (fcs & (1 << 21))
+ fputs_filtered (" nearest", file);
+ if (fcs & (1 << 22))
+ fputs_filtered (" override", file);
+ if (fcs & (1 << 24))
+ fputs_filtered (" zero", file);
+ if ((fcs & (0xb << 21)) == 0)
+ fputs_filtered (" no", file);
+ fputc_filtered ('\n', file);
+
+ fprintf_filtered (file, "nan2008 : %s\n", fcs & (1 << 18) ? "yes" : "no");
+ fprintf_filtered (file, "abs2008 : %s\n", fcs & (1 << 19) ? "yes" : "no");
+ fputc_filtered ('\n', file);
+
+ default_print_float_info (gdbarch, file, frame, args);
+}
+
/* Replacement for generic do_registers_info.
Print regs in pretty columns. */
int size;
if ((mips_pc_is_mips (pc)
- && !mips32_instruction_has_delay_slot (gdbarch, pc))
+ && !mips32_insn_at_pc_has_delay_slot (gdbarch, pc))
|| (mips_pc_is_micromips (gdbarch, pc)
- && !micromips_instruction_has_delay_slot (gdbarch, pc, 0))
+ && !micromips_insn_at_pc_has_delay_slot (gdbarch, pc, 0))
|| (mips_pc_is_mips16 (gdbarch, pc)
- && !mips16_instruction_has_delay_slot (gdbarch, pc, 0)))
+ && !mips16_insn_at_pc_has_delay_slot (gdbarch, pc, 0)))
return 0;
isa = mips_pc_isa (gdbarch, pc);
CORE_ADDR post_prologue_pc
= skip_prologue_using_sal (gdbarch, func_addr);
if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
+ return std::max (pc, post_prologue_pc);
}
/* Can't determine prologue from the symbol table, need to examine
return mips32_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL);
}
-/* Check whether the PC is in a function epilogue (32-bit version).
- This is a helper function for mips_in_function_epilogue_p. */
+/* Implement the stack_frame_destroyed_p gdbarch method (32-bit version).
+ This is a helper function for mips_stack_frame_destroyed_p. */
+
static int
-mips32_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr = 0, func_end = 0;
return 0;
}
-/* Check whether the PC is in a function epilogue (microMIPS version).
- This is a helper function for mips_in_function_epilogue_p. */
+/* Implement the stack_frame_destroyed_p gdbarch method (microMIPS version).
+ This is a helper function for mips_stack_frame_destroyed_p. */
static int
-micromips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+micromips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr = 0;
CORE_ADDR func_end = 0;
loc += MIPS_INSN16_SIZE;
switch (mips_insn_size (ISA_MICROMIPS, insn))
{
- /* 48-bit instructions. */
- case 3 * MIPS_INSN16_SIZE:
- /* No epilogue instructions in this category. */
- return 0;
-
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
insn <<= 16;
return 1;
}
-/* Check whether the PC is in a function epilogue (16-bit version).
- This is a helper function for mips_in_function_epilogue_p. */
+/* Implement the stack_frame_destroyed_p gdbarch method (16-bit version).
+ This is a helper function for mips_stack_frame_destroyed_p. */
+
static int
-mips16_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+mips16_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr = 0, func_end = 0;
return 0;
}
-/* The epilogue is defined here as the area at the end of a function,
+/* Implement the stack_frame_destroyed_p gdbarch method.
+
+ The epilogue is defined here as the area at the end of a function,
after an instruction which destroys the function's stack frame. */
+
static int
-mips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+mips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
if (mips_pc_is_mips16 (gdbarch, pc))
- return mips16_in_function_epilogue_p (gdbarch, pc);
+ return mips16_stack_frame_destroyed_p (gdbarch, pc);
else if (mips_pc_is_micromips (gdbarch, pc))
- return micromips_in_function_epilogue_p (gdbarch, pc);
+ return micromips_stack_frame_destroyed_p (gdbarch, pc);
else
- return mips32_in_function_epilogue_p (gdbarch, pc);
+ return mips32_stack_frame_destroyed_p (gdbarch, pc);
}
/* Root of all "set mips "/"show mips " commands. This will eventually be
mips_fpu_type_auto = 1;
}
-/* Attempt to identify the particular processor model by reading the
- processor id. NOTE: cagney/2003-11-15: Firstly it isn't clear that
- the relevant processor still exists (it dates back to '94) and
- secondly this is not the way to do this. The processor type should
- be set by forcing an architecture change. */
-
-void
-deprecated_mips_set_processor_regs_hack (void)
-{
- struct regcache *regcache = get_current_regcache ();
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- ULONGEST prid;
-
- regcache_cooked_read_unsigned (regcache, MIPS_PRID_REGNUM, &prid);
- if ((prid & ~0xf) == 0x700)
- tdep->mips_processor_reg_names = mips_r3041_reg_names;
-}
-
/* Just like reinit_frame_cache, but with the right arguments to be
callable as an sfunc. */
static int
gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
{
- struct gdbarch *gdbarch = info->application_data;
+ gdb_disassembler *di
+ = static_cast<gdb_disassembler *>(info->application_data);
+ struct gdbarch *gdbarch = di->arch ();
/* FIXME: cagney/2003-06-26: Is this even necessary? The
disassembler needs to be able to locally determine the ISA, and
return gdb_print_insn_mips (memaddr, info);
}
-/* This function implements gdbarch_breakpoint_from_pc. It uses the
- program counter value to determine whether a 16- or 32-bit breakpoint
- should be used. It returns a pointer to a string of bytes that encode a
- breakpoint instruction, stores the length of the string to *lenptr, and
- adjusts pc (if necessary) to point to the actual memory location where
- the breakpoint should be inserted. */
+/* Implement the breakpoint_kind_from_pc gdbarch method. */
-static const gdb_byte *
-mips_breakpoint_from_pc (struct gdbarch *gdbarch,
- CORE_ADDR *pcptr, int *lenptr)
+static int
+mips_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
{
CORE_ADDR pc = *pcptr;
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ if (mips_pc_is_mips16 (gdbarch, pc))
{
- if (mips_pc_is_mips16 (gdbarch, pc))
- {
- static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
- *pcptr = unmake_compact_addr (pc);
- *lenptr = sizeof (mips16_big_breakpoint);
- return mips16_big_breakpoint;
- }
- else if (mips_pc_is_micromips (gdbarch, pc))
- {
- static gdb_byte micromips16_big_breakpoint[] = { 0x46, 0x85 };
- static gdb_byte micromips32_big_breakpoint[] = { 0, 0x5, 0, 0x7 };
- ULONGEST insn;
- int status;
- int size;
-
- insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
- size = status ? 2
- : mips_insn_size (ISA_MICROMIPS, insn) == 2 ? 2 : 4;
- *pcptr = unmake_compact_addr (pc);
- *lenptr = size;
- return (size == 2) ? micromips16_big_breakpoint
- : micromips32_big_breakpoint;
- }
- else
- {
- /* The IDT board uses an unusual breakpoint value, and
- sometimes gets confused when it sees the usual MIPS
- breakpoint instruction. */
- static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
- static gdb_byte pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
- static gdb_byte idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
- /* Likewise, IRIX appears to expect a different breakpoint,
- although this is not apparent until you try to use pthreads. */
- static gdb_byte irix_big_breakpoint[] = { 0, 0, 0, 0xd };
-
- *lenptr = sizeof (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 if (gdbarch_osabi (gdbarch) == GDB_OSABI_IRIX)
- return irix_big_breakpoint;
- else
- return big_breakpoint;
- }
+ *pcptr = unmake_compact_addr (pc);
+ return MIPS_BP_KIND_MIPS16;
}
- else
+ else if (mips_pc_is_micromips (gdbarch, pc))
{
- if (mips_pc_is_mips16 (gdbarch, pc))
- {
- static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 };
- *pcptr = unmake_compact_addr (pc);
- *lenptr = sizeof (mips16_little_breakpoint);
- return mips16_little_breakpoint;
- }
- else if (mips_pc_is_micromips (gdbarch, pc))
- {
- static gdb_byte micromips16_little_breakpoint[] = { 0x85, 0x46 };
- static gdb_byte micromips32_little_breakpoint[] = { 0x5, 0, 0x7, 0 };
- ULONGEST insn;
- int status;
- int size;
-
- insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
- size = status ? 2
- : mips_insn_size (ISA_MICROMIPS, insn) == 2 ? 2 : 4;
- *pcptr = unmake_compact_addr (pc);
- *lenptr = size;
- return (size == 2) ? micromips16_little_breakpoint
- : micromips32_little_breakpoint;
- }
+ ULONGEST insn;
+ int status;
+
+ *pcptr = unmake_compact_addr (pc);
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
+ if (status || (mips_insn_size (ISA_MICROMIPS, insn) == 2))
+ return MIPS_BP_KIND_MICROMIPS16;
else
- {
- static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
- static gdb_byte pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
- static gdb_byte idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
-
- *lenptr = sizeof (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;
- }
+ return MIPS_BP_KIND_MICROMIPS32;
}
+ else
+ return MIPS_BP_KIND_MIPS32;
}
-/* Determine the remote breakpoint kind suitable for the PC. The following
- kinds are used:
+/* Implement the sw_breakpoint_from_kind gdbarch method. */
- * 2 -- 16-bit MIPS16 mode breakpoint,
+static const gdb_byte *
+mips_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+ enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
- * 3 -- 16-bit microMIPS mode breakpoint,
+ switch (kind)
+ {
+ case MIPS_BP_KIND_MIPS16:
+ {
+ static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
+ static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 };
- * 4 -- 32-bit standard MIPS mode breakpoint,
+ *size = 2;
+ if (byte_order_for_code == BFD_ENDIAN_BIG)
+ return mips16_big_breakpoint;
+ else
+ return mips16_little_breakpoint;
+ }
+ case MIPS_BP_KIND_MICROMIPS16:
+ {
+ static gdb_byte micromips16_big_breakpoint[] = { 0x46, 0x85 };
+ static gdb_byte micromips16_little_breakpoint[] = { 0x85, 0x46 };
- * 5 -- 32-bit microMIPS mode breakpoint. */
+ *size = 2;
-static void
-mips_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
- int *kindptr)
-{
- CORE_ADDR pc = *pcptr;
+ if (byte_order_for_code == BFD_ENDIAN_BIG)
+ return micromips16_big_breakpoint;
+ else
+ return micromips16_little_breakpoint;
+ }
+ case MIPS_BP_KIND_MICROMIPS32:
+ {
+ static gdb_byte micromips32_big_breakpoint[] = { 0, 0x5, 0, 0x7 };
+ static gdb_byte micromips32_little_breakpoint[] = { 0x5, 0, 0x7, 0 };
- if (mips_pc_is_mips16 (gdbarch, pc))
- {
- *pcptr = unmake_compact_addr (pc);
- *kindptr = 2;
- }
- else if (mips_pc_is_micromips (gdbarch, pc))
- {
- ULONGEST insn;
- int status;
- int size;
+ *size = 4;
+ if (byte_order_for_code == BFD_ENDIAN_BIG)
+ return micromips32_big_breakpoint;
+ else
+ return micromips32_little_breakpoint;
+ }
+ case MIPS_BP_KIND_MIPS32:
+ {
+ static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
+ static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
- insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
- size = status ? 2 : mips_insn_size (ISA_MICROMIPS, insn) == 2 ? 2 : 4;
- *pcptr = unmake_compact_addr (pc);
- *kindptr = size | 1;
- }
- else
- *kindptr = 4;
+ *size = 4;
+ if (byte_order_for_code == BFD_ENDIAN_BIG)
+ return big_breakpoint;
+ else
+ return little_breakpoint;
+ }
+ default:
+ gdb_assert_not_reached ("unexpected mips breakpoint kind");
+ };
}
-/* Return non-zero if the ADDR instruction has a branch delay slot
- (i.e. it is a jump or branch instruction). This function is based
- on mips32_next_pc. */
+/* Return non-zero if the standard MIPS instruction INST has a branch
+ delay slot (i.e. it is a jump or branch instruction). This function
+ is based on mips32_next_pc. */
static int
-mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
{
- unsigned long inst;
- int status;
int op;
int rs;
int rt;
- inst = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
- if (status)
- return 0;
-
op = itype_op (inst);
if ((inst & 0xe0000000) != 0)
{
}
}
-/* Return non-zero if the ADDR instruction, which must be a 32-bit
- instruction if MUSTBE32 is set or can be any instruction otherwise,
- has a branch delay slot (i.e. it is a non-compact jump instruction). */
+/* Return non-zero if a standard MIPS instruction at ADDR has a branch
+ delay slot (i.e. it is a jump or branch instruction). */
static int
-micromips_instruction_has_delay_slot (struct gdbarch *gdbarch,
- CORE_ADDR addr, int mustbe32)
+mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
{
ULONGEST insn;
int status;
- insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
+ insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
if (status)
return 0;
- if (!mustbe32) /* 16-bit instructions. */
- return (micromips_op (insn) == 0x11
- /* POOL16C: bits 010001 */
- && (b5s5_op (insn) == 0xc
+ return mips32_instruction_has_delay_slot (gdbarch, insn);
+}
+
+/* Return non-zero if the microMIPS instruction INSN, comprising the
+ 16-bit major opcode word in the high 16 bits and any second word
+ in the low 16 bits, has a branch delay slot (i.e. it is a non-compact
+ jump or branch instruction). The instruction must be 32-bit if
+ MUSTBE32 is set or can be any instruction otherwise. */
+
+static int
+micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32)
+{
+ ULONGEST major = insn >> 16;
+
+ switch (micromips_op (major))
+ {
+ /* 16-bit instructions. */
+ case 0x33: /* B16: bits 110011 */
+ case 0x2b: /* BNEZ16: bits 101011 */
+ case 0x23: /* BEQZ16: bits 100011 */
+ return !mustbe32;
+ case 0x11: /* POOL16C: bits 010001 */
+ return (!mustbe32
+ && ((b5s5_op (major) == 0xc
/* JR16: bits 010001 01100 */
- || (b5s5_op (insn) & 0x1e) == 0xe))
+ || (b5s5_op (major) & 0x1e) == 0xe)));
/* JALR16, JALRS16: bits 010001 0111x */
- || (micromips_op (insn) & 0x37) == 0x23
- /* BEQZ16, BNEZ16: bits 10x011 */
- || micromips_op (insn) == 0x33;
- /* B16: bits 110011 */
-
- /* 32-bit instructions. */
- if (micromips_op (insn) == 0x0)
- /* POOL32A: bits 000000 */
- {
- insn <<= 16;
- insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
- if (status)
- return 0;
- return b0s6_op (insn) == 0x3c
- /* POOL32Axf: bits 000000 ... 111100 */
- && (b6s10_ext (insn) & 0x2bf) == 0x3c;
- /* JALR, JALR.HB: 000000 000x111100 111100 */
- /* JALRS, JALRS.HB: 000000 010x111100 111100 */
- }
-
- return (micromips_op (insn) == 0x10
- /* POOL32I: bits 010000 */
- && ((b5s5_op (insn) & 0x1c) == 0x0
+ /* 32-bit instructions. */
+ case 0x3d: /* JAL: bits 111101 */
+ case 0x3c: /* JALX: bits 111100 */
+ case 0x35: /* J: bits 110101 */
+ case 0x2d: /* BNE: bits 101101 */
+ case 0x25: /* BEQ: bits 100101 */
+ case 0x1d: /* JALS: bits 011101 */
+ return 1;
+ case 0x10: /* POOL32I: bits 010000 */
+ return ((b5s5_op (major) & 0x1c) == 0x0
/* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */
- || (b5s5_op (insn) & 0x1d) == 0x4
+ || (b5s5_op (major) & 0x1d) == 0x4
/* BLEZ, BGTZ: bits 010000 001x0 */
- || (b5s5_op (insn) & 0x1d) == 0x11
+ || (b5s5_op (major) & 0x1d) == 0x11
/* BLTZALS, BGEZALS: bits 010000 100x1 */
- || ((b5s5_op (insn) & 0x1e) == 0x14
- && (insn & 0x3) == 0x0)
+ || ((b5s5_op (major) & 0x1e) == 0x14
+ && (major & 0x3) == 0x0)
/* BC2F, BC2T: bits 010000 1010x xxx00 */
- || (b5s5_op (insn) & 0x1e) == 0x1a
+ || (b5s5_op (major) & 0x1e) == 0x1a
/* BPOSGE64, BPOSGE32: bits 010000 1101x */
- || ((b5s5_op (insn) & 0x1e) == 0x1c
- && (insn & 0x3) == 0x0)
+ || ((b5s5_op (major) & 0x1e) == 0x1c
+ && (major & 0x3) == 0x0)
/* BC1F, BC1T: bits 010000 1110x xxx00 */
- || ((b5s5_op (insn) & 0x1c) == 0x1c
- && (insn & 0x3) == 0x1)))
+ || ((b5s5_op (major) & 0x1c) == 0x1c
+ && (major & 0x3) == 0x1));
/* BC1ANY*: bits 010000 111xx xxx01 */
- || (micromips_op (insn) & 0x1f) == 0x1d
- /* JALS, JAL: bits x11101 */
- || (micromips_op (insn) & 0x37) == 0x25
- /* BEQ, BNE: bits 10x101 */
- || micromips_op (insn) == 0x35
- /* J: bits 110101 */
- || micromips_op (insn) == 0x3c;
- /* JALX: bits 111100 */
+ case 0x0: /* POOL32A: bits 000000 */
+ return (b0s6_op (insn) == 0x3c
+ /* POOL32Axf: bits 000000 ... 111100 */
+ && (b6s10_ext (insn) & 0x2bf) == 0x3c);
+ /* JALR, JALR.HB: 000000 000x111100 111100 */
+ /* JALRS, JALRS.HB: 000000 010x111100 111100 */
+ default:
+ return 0;
+ }
}
+/* Return non-zero if a microMIPS instruction at ADDR has a branch delay
+ slot (i.e. it is a non-compact jump instruction). The instruction
+ must be 32-bit if MUSTBE32 is set or can be any instruction otherwise. */
+
static int
-mips16_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr,
- int mustbe32)
+micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32)
{
- unsigned short inst;
+ ULONGEST insn;
int status;
+ int size;
- inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status);
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
if (status)
return 0;
+ size = mips_insn_size (ISA_MICROMIPS, insn);
+ insn <<= 16;
+ if (size == 2 * MIPS_INSN16_SIZE)
+ {
+ insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
+ if (status)
+ return 0;
+ }
+
+ return micromips_instruction_has_delay_slot (insn, mustbe32);
+}
- if (!mustbe32)
- return (inst & 0xf89f) == 0xe800; /* JR/JALR (16-bit instruction) */
+/* Return non-zero if the MIPS16 instruction INST, which must be
+ a 32-bit instruction if MUSTBE32 is set or can be any instruction
+ otherwise, has a branch delay slot (i.e. it is a non-compact jump
+ instruction). This function is based on mips16_next_pc. */
+
+static int
+mips16_instruction_has_delay_slot (unsigned short inst, int mustbe32)
+{
+ if ((inst & 0xf89f) == 0xe800) /* JR/JALR (16-bit instruction) */
+ return !mustbe32;
return (inst & 0xf800) == 0x1800; /* JAL/JALX (32-bit instruction) */
}
+/* Return non-zero if a MIPS16 instruction at ADDR has a branch delay
+ slot (i.e. it is a non-compact jump instruction). The instruction
+ must be 32-bit if MUSTBE32 is set or can be any instruction otherwise. */
+
+static int
+mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32)
+{
+ unsigned short insn;
+ int status;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status);
+ if (status)
+ return 0;
+
+ return mips16_instruction_has_delay_slot (insn, mustbe32);
+}
+
/* Calculate the starting address of the MIPS memory segment BPADDR is in.
This assumes KSSEG exists. */
/* If the previous instruction has a branch delay slot, we have
to move the breakpoint to the branch instruction. */
prev_addr = bpaddr - 4;
- if (mips32_instruction_has_delay_slot (gdbarch, prev_addr))
+ if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr))
bpaddr = prev_addr;
}
else
{
- int (*instruction_has_delay_slot) (struct gdbarch *, CORE_ADDR, int);
+ int (*insn_at_pc_has_delay_slot) (struct gdbarch *, CORE_ADDR, int);
CORE_ADDR addr, jmpaddr;
int i;
2 bytes, so the idea is the same.
FIXME: We have to assume that bpaddr is not the second half
of an extended instruction. */
- instruction_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr)
- ? micromips_instruction_has_delay_slot
- : mips16_instruction_has_delay_slot);
+ insn_at_pc_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr)
+ ? micromips_insn_at_pc_has_delay_slot
+ : mips16_insn_at_pc_has_delay_slot);
jmpaddr = 0;
addr = bpaddr;
if (unmake_compact_addr (addr) == boundary)
break;
addr -= MIPS_INSN16_SIZE;
- if (i == 1 && instruction_has_delay_slot (gdbarch, addr, 0))
+ if (i == 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 0))
/* Looks like a JR/JALR at [target-1], but it could be
the second word of a previous JAL/JALX, so record it
and check back one more. */
jmpaddr = addr;
- else if (i > 1 && instruction_has_delay_slot (gdbarch, addr, 1))
+ else if (i > 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 1))
{
if (i == 2)
/* Looks like a JAL/JALX at [target-2], but it could also
/* If the PC is in __call_stub_* or __fn_stub*, this is one of the
compiler-generated call or call/return stubs. */
- if (strncmp (name, mips_str_fn_stub, strlen (mips_str_fn_stub)) == 0
- || strncmp (name, mips_str_call_stub, strlen (mips_str_call_stub)) == 0)
+ if (startswith (name, mips_str_fn_stub)
+ || startswith (name, mips_str_call_stub))
{
if (pc == start_addr)
/* This is the 'call' part of a call stub. Call this helper
which jumps to foo. */
msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym == NULL
- || SYMBOL_VALUE_ADDRESS (msym.minsym) != pc
- || SYMBOL_LINKAGE_NAME (msym.minsym) == NULL
- || strncmp (SYMBOL_LINKAGE_NAME (msym.minsym), ".pic.", 5) != 0)
+ || BMSYMBOL_VALUE_ADDRESS (msym) != pc
+ || MSYMBOL_LINKAGE_NAME (msym.minsym) == NULL
+ || !startswith (MSYMBOL_LINKAGE_NAME (msym.minsym), ".pic."))
return 0;
/* A two-instruction header. */
new_pc = mips_skip_mips16_trampoline_code (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;
new_pc = find_solib_trampoline_target (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;
new_pc = mips_skip_pic_trampoline_code (frame, pc);
if (new_pc)
- {
- pc = new_pc;
- if (is_compact_addr (pc))
- pc = unmake_compact_addr (pc);
- }
+ pc = new_pc;
}
while (pc != target_pc);
else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 72 && num < 78)
regnum = num + mips_regnum (gdbarch)->dspacc - 72;
else
- /* This will hopefully (eventually) provoke a warning. Should
- we be calling complaint() here? */
- return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+ return -1;
return gdbarch_num_regs (gdbarch) + regnum;
}
else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 66 && num < 72)
regnum = num + mips_regnum (gdbarch)->dspacc - 66;
else
- /* This will hopefully (eventually) provoke a warning. Should we
- be calling complaint() here? */
- return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+ return -1;
return gdbarch_num_regs (gdbarch) + regnum;
}
if (*abip != MIPS_ABI_UNKNOWN)
return;
- if (strncmp (name, ".mdebug.", 8) != 0)
+ if (!startswith (name, ".mdebug."))
return;
if (strcmp (name, ".mdebug.abi32") == 0)
int *lbp = (int *) obj;
const char *name = bfd_get_section_name (abfd, sect);
- if (strncmp (name, ".gcc_compiled_long32", 20) == 0)
+ if (startswith (name, ".gcc_compiled_long32"))
*lbp = 32;
- else if (strncmp (name, ".gcc_compiled_long64", 20) == 0)
+ else if (startswith (name, ".gcc_compiled_long64"))
*lbp = 64;
- else if (strncmp (name, ".gcc_compiled_long", 18) == 0)
+ else if (startswith (name, ".gcc_compiled_long"))
warning (_("unrecognized .gcc_compiled_longXX"));
}
static struct value *
value_of_mips_user_reg (struct frame_info *frame, const void *baton)
{
- const int *reg_p = baton;
+ const int *reg_p = (const int *) baton;
return value_of_register (*reg_p, frame);
}
int i, num_regs;
enum mips_fpu_type fpu_type;
struct tdesc_arch_data *tdesc_data = NULL;
- int elf_fpu_type = 0;
+ int elf_fpu_type = Val_GNU_MIPS_ABI_FP_ANY;
const char **reg_names;
struct mips_regnum mips_regnum, *regnum;
enum mips_isa mips_isa;
int dspctl;
/* Fill in the OS dependent register numbers and names. */
- if (info.osabi == GDB_OSABI_IRIX)
- {
- mips_regnum.fp0 = 32;
- mips_regnum.pc = 64;
- mips_regnum.cause = 65;
- mips_regnum.badvaddr = 66;
- mips_regnum.hi = 67;
- mips_regnum.lo = 68;
- mips_regnum.fp_control_status = 69;
- mips_regnum.fp_implementation_revision = 70;
- mips_regnum.dspacc = dspacc = -1;
- mips_regnum.dspctl = dspctl = -1;
- num_regs = 71;
- reg_names = mips_irix_reg_names;
- }
- else if (info.osabi == GDB_OSABI_LINUX)
+ if (info.osabi == GDB_OSABI_LINUX)
{
mips_regnum.fp0 = 38;
mips_regnum.pc = 37;
mips_regnum.dspctl = -1;
dspacc = 72;
dspctl = 78;
- num_regs = 79;
+ num_regs = 90;
reg_names = mips_linux_reg_names;
}
else
return NULL;
}
+ num_regs = mips_regnum.fp_implementation_revision + 1;
+
if (dspacc >= 0)
{
feature = tdesc_find_feature (info.target_desc,
mips_regnum.dspacc = dspacc;
mips_regnum.dspctl = dspctl;
+
+ num_regs = mips_regnum.dspctl + 1;
}
}
/* On Irix, ELF64 executables use the N64 ABI. The
pseudo-sections which describe the ABI aren't present
on IRIX. (Even for executables created by gcc.) */
- if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
+ if (info.abfd != NULL
+ && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
&& elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
found_abi = MIPS_ABI_N64;
else
if (!mips_fpu_type_auto)
fpu_type = mips_fpu_type;
- else if (elf_fpu_type != 0)
+ else if (elf_fpu_type != Val_GNU_MIPS_ABI_FP_ANY)
{
switch (elf_fpu_type)
{
- case 1:
+ case Val_GNU_MIPS_ABI_FP_DOUBLE:
fpu_type = MIPS_FPU_DOUBLE;
break;
- case 2:
+ case Val_GNU_MIPS_ABI_FP_SINGLE:
fpu_type = MIPS_FPU_SINGLE;
break;
- case 3:
+ case Val_GNU_MIPS_ABI_FP_SOFT:
default:
/* Soft float or unknown. */
fpu_type = MIPS_FPU_NONE;
arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
- /* MIPS needs to be pedantic about which ABI the object is
- using. */
+ /* MIPS needs to be pedantic about which ABI and the compressed
+ ISA variation the object is using. */
if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags)
continue;
if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
continue;
+ if (gdbarch_tdep (arches->gdbarch)->mips_isa != mips_isa)
+ continue;
/* Need to be pedantic about which register virtual size is
used. */
if (gdbarch_tdep (arches->gdbarch)->mips64_transfers_32bit_regs_p
}
/* Need a new architecture. Fill in a target specific vector. */
- tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+ tdep = XNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
tdep->elf_flags = elf_flags;
tdep->mips64_transfers_32bit_regs_p = mips64_transfers_32bit_regs_p;
tdep->mips_fpu_type = fpu_type;
tdep->register_size_valid_p = 0;
tdep->register_size = 0;
- tdep->gregset = NULL;
- tdep->gregset64 = NULL;
- tdep->fpregset = NULL;
- tdep->fpregset64 = NULL;
if (info.target_desc)
{
set_gdbarch_elf_make_msymbol_special (gdbarch,
mips_elf_make_msymbol_special);
+ set_gdbarch_make_symbol_special (gdbarch, mips_make_symbol_special);
+ set_gdbarch_adjust_dwarf2_addr (gdbarch, mips_adjust_dwarf2_addr);
+ set_gdbarch_adjust_dwarf2_line (gdbarch, mips_adjust_dwarf2_line);
regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum);
*regnum = mips_regnum;
set_gdbarch_push_dummy_code (gdbarch, mips_push_dummy_code);
set_gdbarch_frame_align (gdbarch, mips_frame_align);
+ set_gdbarch_print_float_info (gdbarch, mips_print_float_info);
+
set_gdbarch_convert_register_p (gdbarch, mips_convert_register_p);
set_gdbarch_register_to_value (gdbarch, mips_register_to_value);
set_gdbarch_value_to_register (gdbarch, mips_value_to_register);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
- set_gdbarch_remote_breakpoint_from_pc (gdbarch,
- mips_remote_breakpoint_from_pc);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, mips_breakpoint_kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch, mips_sw_breakpoint_from_kind);
set_gdbarch_adjust_breakpoint_address (gdbarch,
mips_adjust_breakpoint_address);
set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
- set_gdbarch_in_function_epilogue_p (gdbarch, mips_in_function_epilogue_p);
+ set_gdbarch_stack_frame_destroyed_p (gdbarch, mips_stack_frame_destroyed_p);
set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
mips_register_g_packet_guesses (gdbarch);
/* Hook in OS ABI-specific overrides, if they have been registered. */
- info.tdep_info = (void *) tdesc_data;
+ info.tdep_info = tdesc_data;
gdbarch_init_osabi (info, gdbarch);
/* The hook may have adjusted num_regs, fetch the final value and