/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
- Copyright (C) 1988-2012 Free Software Foundation, Inc.
+ Copyright (C) 1988-2014 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 <string.h>
#include "gdb_assert.h"
#include "frame.h"
#include "inferior.h"
static int mips_fpu_type_auto = 1;
static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE;
-static int mips_debug = 0;
+static unsigned int mips_debug = 0;
/* Properties (for struct target_desc) describing the g/G packet
layout. */
"special", i.e. refers to a MIPS16 or microMIPS function, and sets
one of the "special" bits in a minimal symbol to mark it accordingly.
The test checks an ELF-private flag that is valid for true function
- symbols only; in particular synthetic symbols such as for PLT stubs
- have no ELF-private part at all.
+ symbols only; for synthetic symbols such as for PLT stubs that have
+ no ELF-private part at all the MIPS BFD backend arranges for this
+ information to be carried in the asymbol's udata field instead.
msymbol_is_mips16 and msymbol_is_micromips test the "special" bit
in a minimal symbol. */
mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym)
{
elf_symbol_type *elfsym = (elf_symbol_type *) sym;
+ unsigned char st_other;
- if ((sym->flags & BSF_SYNTHETIC) != 0)
+ if ((sym->flags & BSF_SYNTHETIC) == 0)
+ st_other = elfsym->internal_elf_sym.st_other;
+ else if ((sym->flags & BSF_FUNCTION) != 0)
+ st_other = sym->udata.i;
+ else
return;
- if (ELF_ST_IS_MICROMIPS (elfsym->internal_elf_sym.st_other))
+ if (ELF_ST_IS_MICROMIPS (st_other))
MSYMBOL_TARGET_FLAG_2 (msym) = 1;
- else if (ELF_ST_IS_MIPS16 (elfsym->internal_elf_sym.st_other))
+ else if (ELF_ST_IS_MIPS16 (st_other))
MSYMBOL_TARGET_FLAG_1 (msym) = 1;
}
time across a 2400 baud serial line. Allows the user to limit this
search. */
-static unsigned int heuristic_fence_post = 0;
+static int heuristic_fence_post = 0;
/* Number of bytes of storage in the actual machine representation for
register N. NOTE: This defines the pseudo register type so need to
mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
const int num_regs = gdbarch_num_regs (gdbarch);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int rawnum = regnum % num_regs;
struct type *rawtype;
show_mask_address (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch ());
deprecated_show_value_hack (file, from_tty, c, value);
switch (mask_address_var)
int
mips_pc_is_mips (CORE_ADDR memaddr)
{
- struct minimal_symbol *sym;
+ struct bound_minimal_symbol sym;
/* Flags indicating that this is a MIPS16 or microMIPS function is
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);
- if (sym)
- return msymbol_is_mips (sym);
+ if (sym.minsym)
+ return msymbol_is_mips (sym.minsym);
else
return is_mips_addr (memaddr);
}
int
mips_pc_is_mips16 (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
- struct minimal_symbol *sym;
+ struct bound_minimal_symbol sym;
/* A flag indicating that this is a MIPS16 function is stored by
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);
- if (sym)
- return msymbol_is_mips16 (sym);
+ if (sym.minsym)
+ return msymbol_is_mips16 (sym.minsym);
else
return is_mips16_addr (gdbarch, memaddr);
}
int
mips_pc_is_micromips (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
- struct minimal_symbol *sym;
+ struct bound_minimal_symbol sym;
/* A flag indicating that this is a microMIPS function is stored by
elfread.c in the high bit of the info field. Use this to decide
is set, then ELF file flags will tell if this is a microMIPS
function. */
sym = lookup_minimal_symbol_by_pc (memaddr);
- if (sym)
- return msymbol_is_micromips (sym);
+ if (sym.minsym)
+ return msymbol_is_micromips (sym.minsym);
else
return is_micromips_addr (gdbarch, memaddr);
}
static enum mips_isa
mips_pc_isa (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
- struct minimal_symbol *sym;
+ struct bound_minimal_symbol sym;
/* A flag indicating that this is a MIPS16 or a microMIPS function
is stored by elfread.c in the high bit of the info field. Use
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);
- if (sym)
+ if (sym.minsym)
{
- if (msymbol_is_micromips (sym))
+ if (msymbol_is_micromips (sym.minsym))
return ISA_MICROMIPS;
- else if (msymbol_is_mips16 (sym))
+ else if (msymbol_is_mips16 (sym.minsym))
return ISA_MIPS16;
else
return ISA_MIPS;
mips_read_pc (struct regcache *regcache)
{
int regnum = gdbarch_pc_regnum (get_regcache_arch (regcache));
- ULONGEST pc;
+ LONGEST pc;
regcache_cooked_read_signed (regcache, regnum, &pc);
if (is_compact_addr (pc))
return pc;
}
+/* Return nonzero if the gdbarch is an Octeon series. */
+
+static int
+is_octeon (struct gdbarch *gdbarch)
+{
+ const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
+
+ return (info->mach == bfd_mach_mips_octeon
+ || info->mach == bfd_mach_mips_octeonp
+ || info->mach == bfd_mach_mips_octeon2);
+}
+
+/* Return true if the OP represents the Octeon's BBIT instruction. */
+
+static int
+is_octeon_bbit_op (int op, struct gdbarch *gdbarch)
+{
+ if (!is_octeon (gdbarch))
+ return 0;
+ /* BBIT0 is encoded as LWC2: 110 010. */
+ /* BBIT032 is encoded as LDC2: 110 110. */
+ /* BBIT1 is encoded as SWC2: 111 010. */
+ /* BBIT132 is encoded as SDC2: 111 110. */
+ if (op == 50 || op == 54 || op == 58 || op == 62)
+ return 1;
+ return 0;
+}
+
+
/* Determine where to set a single step breakpoint while considering
branch prediction. */
+
static CORE_ADDR
mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
{
unsigned long inst;
int op;
inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
+ op = itype_op (inst);
if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch
instruction. */
{
- if (itype_op (inst) >> 2 == 5)
+ if (op >> 2 == 5)
/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
{
- op = (itype_op (inst) & 0x03);
- switch (op)
+ switch (op & 0x03)
{
case 0: /* BEQL */
goto equal_branch;
pc += 4;
}
}
- else if (itype_op (inst) == 17 && itype_rs (inst) == 8)
+ else if (op == 17 && itype_rs (inst) == 8)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 1);
- else if (itype_op (inst) == 17 && itype_rs (inst) == 9
+ 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);
- else if (itype_op (inst) == 17 && itype_rs (inst) == 10
+ 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);
- else if (itype_op (inst) == 29)
+ else if (op == 29)
/* JALX: 011101 */
/* The new PC will be alternate mode. */
{
/* Add 1 to indicate 16-bit mode -- invert ISA mode. */
pc = ((pc + 4) & ~(CORE_ADDR) 0x0fffffff) + reg + 1;
}
+ else if (is_octeon_bbit_op (op, gdbarch))
+ {
+ int bit, branch_if;
+
+ branch_if = op == 58 || op == 62;
+ bit = itype_rt (inst);
+
+ /* Take into account the *32 instructions. */
+ if (op == 54 || op == 62)
+ bit += 32;
+
+ if (((get_frame_register_signed (frame,
+ itype_rs (inst)) >> bit) & 1)
+ == branch_if)
+ pc += mips32_relative_offset (inst) + 4;
+ else
+ pc += 8; /* After the delay slot. */
+ }
+
else
pc += 4; /* Not a branch, next instruction is easy. */
}
{ /* This gets way messy. */
/* Further subdivide into SPECIAL, REGIMM and other. */
- switch (op = itype_op (inst) & 0x07) /* Extract bits 28,27,26. */
+ switch (op & 0x07) /* Extract bits 28,27,26. */
{
case 0: /* SPECIAL */
op = rtype_funct (inst);
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[8];
- pc &= 0xfffffffe; /* Clear the low order bit. */
+
+ pc = unmake_compact_addr (pc); /* Clear the low order bit. */
target_read_memory (pc, buf, 2);
return extract_unsigned_integer (buf, 2, byte_order);
}
/* The mips_next_pc function supports single_step when the remote
target monitor or stub is not developed enough to do a single_step.
It works by decoding the current instruction and predicting where a
- branch will go. This isnt hard because all the data is available.
+ 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)
break;
/* LUI $v1 is used for larger $sp adjustments. */
- /* Discard LUI $gp is used for PIC code. */
+ /* Discard LUI $gp used for PIC code. */
case 0x10: /* POOL32I: bits 010000 */
if (b5s5_op (insn >> 16) == 0xd
/* LUI: bits 010000 001101 */
frame_reg = 30;
frame_addr = get_frame_register_signed
(this_frame, gdbarch_num_regs (gdbarch) + 30);
+ frame_offset = 0;
alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
if (alloca_adjust > 0)
gdb_byte dummy[4];
struct obj_section *s;
CORE_ADDR pc = get_frame_address_in_block (this_frame);
- struct minimal_symbol *msym;
+ struct bound_minimal_symbol msym;
/* Use the stub unwinder for unreadable code. */
if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
return 1;
- if (in_plt_section (pc, NULL))
- return 1;
-
- /* Binutils for MIPS puts lazy resolution stubs into .MIPS.stubs. */
- s = find_pc_section (pc);
-
- if (s != NULL
- && strcmp (bfd_get_section_name (s->objfile->obfd, s->the_bfd_section),
- ".MIPS.stubs") == 0)
+ if (in_plt_section (pc) || in_mips_stubs_section (pc))
return 1;
/* Calling a PIC function from a non-PIC function passes through a
stub. The stub for foo is named ".pic.foo". */
msym = lookup_minimal_symbol_by_pc (pc);
- if (msym != NULL
- && SYMBOL_LINKAGE_NAME (msym) != NULL
- && strncmp (SYMBOL_LINKAGE_NAME (msym), ".pic.", 5) == 0)
+ if (msym.minsym != NULL
+ && SYMBOL_LINKAGE_NAME (msym.minsym) != NULL
+ && strncmp (SYMBOL_LINKAGE_NAME (msym.minsym), ".pic.", 5) == 0)
return 1;
return 0;
const int atomic_sequence_length = 16; /* Instruction sequence length. */
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
CORE_ADDR breaks[2] = {-1, -1};
- CORE_ADDR branch_bp; /* Breakpoint at branch instruction's destination. */
+ CORE_ADDR branch_bp = 0; /* Breakpoint at branch instruction's
+ destination. */
CORE_ADDR loc = pc;
int sc_found = 0;
ULONGEST insn;
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
- insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
+ insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
return 1;
}
if (start_pc == 0)
return 0;
- if (heuristic_fence_post == UINT_MAX || fence < VM_MIN_ADDRESS)
+ if (heuristic_fence_post == -1 || fence < VM_MIN_ADDRESS)
fence = VM_MIN_ADDRESS;
instlen = mips_pc_is_mips (pc) ? MIPS_INSN32_SIZE : MIPS_INSN16_SIZE;
CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
struct regcache *regcache)
{
- CORE_ADDR nop_addr;
static gdb_byte nop_insn[] = { 0, 0, 0, 0 };
+ CORE_ADDR nop_addr;
+ CORE_ADDR bp_slot;
/* Reserve enough room on the stack for our breakpoint instruction. */
- *bp_addr = sp - sizeof (nop_insn);
+ bp_slot = sp - sizeof (nop_insn);
+
+ /* Return to microMIPS mode if calling microMIPS code to avoid
+ triggering an address error exception on processors that only
+ support microMIPS execution. */
+ *bp_addr = (mips_pc_is_micromips (gdbarch, funaddr)
+ ? make_compact_addr (bp_slot) : bp_slot);
/* The breakpoint layer automatically adjusts the address of
breakpoints inserted in a branch delay slot. With enough
trigger the adjustement, and break the function call entirely.
So, we reserve those 4 bytes and write a nop instruction
to prevent that from happening. */
- nop_addr = *bp_addr - sizeof (nop_insn);
+ nop_addr = bp_slot - sizeof (nop_insn);
write_memory (nop_addr, nop_insn, sizeof (nop_insn));
sp = mips_frame_align (gdbarch, nop_addr);
int argnum;
int len = 0;
int stack_offset = 0;
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
int regsize = mips_abi_regsize (gdbarch);
int argnum;
int len = 0;
int stack_offset = 0;
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
int argnum;
int len = 0;
int stack_offset = 0;
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
for (argnum = 0; argnum < nargs; argnum++)
{
struct type *arg_type = check_typedef (value_type (args[argnum]));
- int arglen = TYPE_LENGTH (arg_type);
/* Align to double-word if necessary. */
if (mips_type_needs_double_align (arg_type))
len = align_up (len, MIPS32_REGSIZE * 2);
/* Allocate space on the stack. */
- len += align_up (arglen, MIPS32_REGSIZE);
+ len += align_up (TYPE_LENGTH (arg_type), MIPS32_REGSIZE);
}
sp -= align_up (len, 16);
int argnum;
int len = 0;
int stack_offset = 0;
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR func_addr = find_function_addr (function, NULL);
for (argnum = 0; argnum < nargs; argnum++)
{
struct type *arg_type = check_typedef (value_type (args[argnum]));
- int arglen = TYPE_LENGTH (arg_type);
/* Allocate space on the stack. */
- len += align_up (arglen, MIPS64_REGSIZE);
+ len += align_up (TYPE_LENGTH (arg_type), MIPS64_REGSIZE);
}
sp -= align_up (len, 16);
int raw_size = register_size (gdbarch, regno);
gdb_byte *raw_buffer = alloca (raw_size);
- if (!frame_register_read (frame, regno, raw_buffer))
+ if (!deprecated_frame_register_read (frame, regno, raw_buffer))
error (_("can't read register %d (%s)"),
regno, gdbarch_register_name (gdbarch, regno));
if (raw_size == 8)
{
/* We have a 64-bit value for this register, and we should use
all 64 bits. */
- if (!frame_register_read (frame, regno, rare_buffer))
+ if (!deprecated_frame_register_read (frame, regno, rare_buffer))
error (_("can't read register %d (%s)"),
regno, gdbarch_register_name (gdbarch, regno));
}
break; /* End row: large register. */
/* OK: get the data in raw format. */
- if (!frame_register_read (frame, regnum, raw_buffer))
+ if (!deprecated_frame_register_read (frame, regnum, raw_buffer))
error (_("can't read register %d (%s)"),
regnum, gdbarch_register_name (gdbarch, regnum));
/* pad small registers */
{
char *fpu;
- if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_mips)
+ if (gdbarch_bfd_arch_info (target_gdbarch ())->arch != bfd_arch_mips)
{
printf_unfiltered
("The MIPS floating-point coprocessor is unknown "
return;
}
- switch (MIPS_FPU_TYPE (target_gdbarch))
+ switch (MIPS_FPU_TYPE (target_gdbarch ()))
{
case MIPS_FPU_SINGLE:
fpu = "single-precision";
{
rs = itype_rs (inst);
rt = itype_rt (inst);
- return (op >> 2 == 5 /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
+ return (is_octeon_bbit_op (op, gdbarch)
+ || op >> 2 == 5 /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
|| op == 29 /* JALX: bits 011101 */
|| (op == 17
&& (rs == 8
{
struct gdbarch *gdbarch = get_frame_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct minimal_symbol *msym;
+ struct bound_minimal_symbol msym;
int i;
gdb_byte stub_code[16];
int32_t stub_words[4];
instructions inserted before foo or a three instruction sequence
which jumps to foo. */
msym = lookup_minimal_symbol_by_pc (pc);
- if (msym == NULL
- || SYMBOL_VALUE_ADDRESS (msym) != pc
- || SYMBOL_LINKAGE_NAME (msym) == NULL
- || strncmp (SYMBOL_LINKAGE_NAME (msym), ".pic.", 5) != 0)
+ 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)
return 0;
/* A two-instruction header. */
- if (MSYMBOL_SIZE (msym) == 8)
+ if (MSYMBOL_SIZE (msym.minsym) == 8)
return pc + 8;
/* A three-instruction (plus delay slot) trampoline. */
- if (MSYMBOL_SIZE (msym) == 16)
+ if (MSYMBOL_SIZE (msym.minsym) == 16)
{
if (target_read_memory (pc, stub_code, 16) != 0)
return 0;
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;
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;
struct cmd_list_element *ignored_cmd,
const char *ignored_value)
{
- if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_mips)
+ if (gdbarch_bfd_arch_info (target_gdbarch ())->arch != bfd_arch_mips)
fprintf_filtered
(file,
"The MIPS ABI is unknown because the current architecture "
else
{
enum mips_abi global_abi = global_mips_abi ();
- enum mips_abi actual_abi = mips_abi (target_gdbarch);
+ enum mips_abi actual_abi = mips_abi (target_gdbarch ());
const char *actual_abi_str = mips_abi_strings[actual_abi];
if (global_abi == MIPS_ABI_UNKNOWN)
&setlist, &showlist);
/* Debug this files internals. */
- add_setshow_zinteger_cmd ("mips", class_maintenance,
- &mips_debug, _("\
+ add_setshow_zuinteger_cmd ("mips", class_maintenance,
+ &mips_debug, _("\
Set mips debugging."), _("\
Show mips debugging."), _("\
When non-zero, mips specific debugging is enabled."),
- NULL,
- NULL, /* FIXME: i18n: Mips debugging is
- currently %s. */
- &setdebuglist, &showdebuglist);
+ NULL,
+ NULL, /* FIXME: i18n: Mips debugging is
+ currently %s. */
+ &setdebuglist, &showdebuglist);
}