/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010 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.
#include "dwarf2-frame.h"
#include "user-regs.h"
#include "valprint.h"
+#include "ax.h"
static const struct objfile_data *mips_pdr_data;
return ((addr) & ~(CORE_ADDR) 1);
}
+static CORE_ADDR
+make_mips16_addr (CORE_ADDR addr)
+{
+ return ((addr) | (CORE_ADDR) 1);
+}
+
/* Return the MIPS ABI associated with GDBARCH. */
enum mips_abi
mips_abi (struct gdbarch *gdbarch)
if (((elf_symbol_type *) (sym))->internal_elf_sym.st_other == STO_MIPS16)
{
MSYMBOL_TARGET_FLAG_1 (msym) = 1;
- SYMBOL_VALUE_ADDRESS (msym) |= 1;
}
}
enum mips_abi abi = mips_abi (gdbarch);
/* Map [gdbarch_num_regs .. 2*gdbarch_num_regs) onto the raw registers,
- but then don't make the raw register names visible. */
+ but then don't make the raw register names visible. This (upper)
+ range of user visible register numbers are the pseudo-registers.
+
+ This approach was adopted accommodate the following scenario:
+ It is possible to debug a 64-bit device using a 32-bit
+ programming model. In such instances, the raw registers are
+ configured to be 64-bits wide, while the pseudo registers are
+ configured to be 32-bits wide. The registers that the user
+ sees - the pseudo registers - match the users expectations
+ given the programming model being used. */
int rawnum = regno % gdbarch_num_regs (gdbarch);
if (regno < gdbarch_num_regs (gdbarch))
return "";
else if (register_size (gdbarch, rawnum) >
register_size (gdbarch, cookednum))
{
- if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
- || gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+ if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
else
- regcache_raw_read_part (regcache, rawnum, 4, 4, buf);
+ {
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ LONGEST regval;
+ regcache_raw_read_signed (regcache, rawnum, ®val);
+ store_signed_integer (buf, 4, byte_order, regval);
+ }
}
else
internal_error (__FILE__, __LINE__, _("bad register size"));
else if (register_size (gdbarch, rawnum) >
register_size (gdbarch, cookednum))
{
- if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
- || gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+ if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
regcache_raw_write_part (regcache, rawnum, 0, 4, buf);
else
- regcache_raw_write_part (regcache, rawnum, 4, 4, buf);
+ {
+ /* Sign extend the shortened version of the register prior
+ to placing it in the raw register. This is required for
+ some mips64 parts in order to avoid unpredictable behavior. */
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ LONGEST regval = extract_signed_integer (buf, 4, byte_order);
+ regcache_raw_write_signed (regcache, rawnum, regval);
+ }
}
else
internal_error (__FILE__, __LINE__, _("bad register size"));
}
+static int
+mips_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg)
+{
+ int rawnum = reg % gdbarch_num_regs (gdbarch);
+ gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+ && reg < 2 * gdbarch_num_regs (gdbarch));
+
+ ax_reg_mask (ax, rawnum);
+
+ return 0;
+}
+
+static int
+mips_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg)
+{
+ int rawnum = reg % gdbarch_num_regs (gdbarch);
+ gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+ && reg < 2 * gdbarch_num_regs (gdbarch));
+ if (register_size (gdbarch, rawnum) >= register_size (gdbarch, reg))
+ {
+ ax_reg (ax, rawnum);
+
+ if (register_size (gdbarch, rawnum) > register_size (gdbarch, reg))
+ {
+ if (!gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
+ || gdbarch_byte_order (gdbarch) != BFD_ENDIAN_BIG)
+ {
+ ax_const_l (ax, 32);
+ ax_simple (ax, aop_lsh);
+ }
+ ax_const_l (ax, 32);
+ ax_simple (ax, aop_rsh_signed);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__, _("bad register size"));
+
+ return 0;
+}
+
/* Table to translate MIPS16 register field to actual register number. */
static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
/* Convert to/from a register and the corresponding memory value. */
+/* This predicate tests for the case of an 8 byte floating point
+ value that is being transferred to or from a pair of floating point
+ registers each of which are (or are considered to be) only 4 bytes
+ wide. */
static int
-mips_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
+mips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
+ struct type *type)
{
return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
&& register_size (gdbarch, regnum) == 4
&& TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
}
+/* This predicate tests for the case of a value of less than 8
+ bytes in width that is being transfered to or from an 8 byte
+ general purpose register. */
+static int
+mips_convert_register_gpreg_case_p (struct gdbarch *gdbarch, int regnum,
+ struct type *type)
+{
+ int num_regs = gdbarch_num_regs (gdbarch);
+
+ return (register_size (gdbarch, regnum) == 8
+ && regnum % num_regs > 0 && regnum % num_regs < 32
+ && TYPE_LENGTH (type) < 8);
+}
+
+static int
+mips_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
+{
+ return mips_convert_register_float_case_p (gdbarch, regnum, type)
+ || mips_convert_register_gpreg_case_p (gdbarch, regnum, type);
+}
+
static void
mips_register_to_value (struct frame_info *frame, int regnum,
struct type *type, gdb_byte *to)
{
- get_frame_register (frame, regnum + 0, to + 4);
- get_frame_register (frame, regnum + 1, to + 0);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+
+ if (mips_convert_register_float_case_p (gdbarch, regnum, type))
+ {
+ get_frame_register (frame, regnum + 0, to + 4);
+ get_frame_register (frame, regnum + 1, to + 0);
+ }
+ else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
+ {
+ int len = TYPE_LENGTH (type);
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ get_frame_register_bytes (frame, regnum, 8 - len, len, to);
+ else
+ get_frame_register_bytes (frame, regnum, 0, len, to);
+ }
+ else
+ {
+ internal_error (__FILE__, __LINE__,
+ _("mips_register_to_value: unrecognized case"));
+ }
}
static void
mips_value_to_register (struct frame_info *frame, int regnum,
struct type *type, const gdb_byte *from)
{
- put_frame_register (frame, regnum + 0, from + 4);
- put_frame_register (frame, regnum + 1, from + 0);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+
+ if (mips_convert_register_float_case_p (gdbarch, regnum, type))
+ {
+ put_frame_register (frame, regnum + 0, from + 4);
+ put_frame_register (frame, regnum + 1, from + 0);
+ }
+ else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
+ {
+ gdb_byte fill[8];
+ int len = TYPE_LENGTH (type);
+
+ /* Sign extend values, irrespective of type, that are stored to
+ a 64-bit general purpose register. (32-bit unsigned values
+ are stored as signed quantities within a 64-bit register.
+ When performing an operation, in compiled code, that combines
+ a 32-bit unsigned value with a signed 64-bit value, a type
+ conversion is first performed that zeroes out the high 32 bits.) */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ if (from[0] & 0x80)
+ store_signed_integer (fill, 8, BFD_ENDIAN_BIG, -1);
+ else
+ store_signed_integer (fill, 8, BFD_ENDIAN_BIG, 0);
+ put_frame_register_bytes (frame, regnum, 0, 8 - len, fill);
+ put_frame_register_bytes (frame, regnum, 8 - len, len, from);
+ }
+ else
+ {
+ if (from[len-1] & 0x80)
+ store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, -1);
+ else
+ store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, 0);
+ put_frame_register_bytes (frame, regnum, 0, len, from);
+ put_frame_register_bytes (frame, regnum, len, 8 - len, fill);
+ }
+ }
+ else
+ {
+ internal_error (__FILE__, __LINE__,
+ _("mips_value_to_register: unrecognized case"));
+ }
}
/* Return the GDB type object for the "standard" data type of data in
ULONGEST pc;
int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
regcache_cooked_read_signed (regcache, regnum, &pc);
+ if (is_mips16_addr (pc))
+ pc = unmake_mips16_addr (pc);
return pc;
}
static CORE_ADDR
mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- return frame_unwind_register_signed
- (next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
+ ULONGEST pc;
+
+ pc = frame_unwind_register_signed
+ (next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
+ if (is_mips16_addr (pc))
+ pc = unmake_mips16_addr (pc);
+ return pc;
}
static CORE_ADDR
mips_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
- regcache_cooked_write_unsigned (regcache, regnum, pc);
+ if (mips_pc_is_mips16 (pc))
+ regcache_cooked_write_unsigned (regcache, regnum, make_mips16_addr (pc));
+ else
+ regcache_cooked_write_unsigned (regcache, regnum, pc);
}
/* Fetch and return instruction from the specified location. If the PC
is odd, assume it's a MIPS16 instruction; otherwise MIPS32. */
static ULONGEST
-mips_fetch_instruction (CORE_ADDR addr)
+mips_fetch_instruction (struct gdbarch *gdbarch, CORE_ADDR addr)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[MIPS_INSN32_SIZE];
int instlen;
int status;
status = target_read_memory (addr, buf, instlen);
if (status)
memory_error (status, addr);
- return extract_unsigned_integer (buf, instlen);
+ return extract_unsigned_integer (buf, instlen, byte_order);
}
/* These the fields of 32 bit mips instructions */
static CORE_ADDR
mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
unsigned long inst;
int op;
- inst = mips_fetch_instruction (pc);
+ inst = mips_fetch_instruction (gdbarch, pc);
if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch instruction */
{
if (itype_op (inst) >> 2 == 5)
when the offset is to be used in relative addressing. */
static unsigned int
-fetch_mips_16 (CORE_ADDR pc)
+fetch_mips_16 (struct gdbarch *gdbarch, CORE_ADDR pc)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[8];
pc &= 0xfffffffe; /* clear the low order bit */
target_read_memory (pc, buf, 2);
- return extract_unsigned_integer (buf, 2);
+ return extract_unsigned_integer (buf, 2, byte_order);
}
static void
-unpack_mips16 (CORE_ADDR pc,
+unpack_mips16 (struct gdbarch *gdbarch, CORE_ADDR pc,
unsigned int extension,
unsigned int inst,
enum mips16_inst_fmts insn_format, struct upk_mips16 *upk)
unsigned int nexthalf;
value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f);
value = value << 16;
- nexthalf = mips_fetch_instruction (pc + 2); /* low bit still set */
+ nexthalf = mips_fetch_instruction (gdbarch, pc + 2); /* low bit still set */
value |= nexthalf;
offset = value;
regx = -1;
extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
unsigned int extension, unsigned int insn)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
int op = (insn >> 11);
switch (op)
{
{
CORE_ADDR offset;
struct upk_mips16 upk;
- unpack_mips16 (pc, extension, insn, itype, &upk);
+ unpack_mips16 (gdbarch, pc, extension, insn, itype, &upk);
offset = upk.offset;
if (offset & 0x800)
{
case 3: /* JAL , JALX - Watch out, these are 32 bit instruction */
{
struct upk_mips16 upk;
- unpack_mips16 (pc, extension, insn, jalxtype, &upk);
+ unpack_mips16 (gdbarch, pc, extension, insn, jalxtype, &upk);
pc = add_offset_16 (pc, upk.offset);
if ((insn >> 10) & 0x01) /* Exchange mode */
pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode */
{
struct upk_mips16 upk;
int reg;
- unpack_mips16 (pc, extension, insn, ritype, &upk);
+ unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
reg = get_frame_register_signed (frame, upk.regx);
if (reg == 0)
pc += (upk.offset << 1) + 2;
{
struct upk_mips16 upk;
int reg;
- unpack_mips16 (pc, extension, insn, ritype, &upk);
+ unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
reg = get_frame_register_signed (frame, upk.regx);
if (reg != 0)
pc += (upk.offset << 1) + 2;
{
struct upk_mips16 upk;
int reg;
- unpack_mips16 (pc, extension, insn, i8type, &upk);
+ unpack_mips16 (gdbarch, pc, extension, insn, i8type, &upk);
/* upk.regx contains the opcode */
reg = get_frame_register_signed (frame, 24); /* Test register is 24 */
if (((upk.regx == 0) && (reg == 0)) /* BTEZ */
that. */
{
pc += 2;
- pc = extended_mips16_next_pc (frame, pc, insn, fetch_mips_16 (pc));
+ pc = extended_mips16_next_pc (frame, pc, insn,
+ fetch_mips_16 (gdbarch, pc));
break;
}
default:
static CORE_ADDR
mips16_next_pc (struct frame_info *frame, CORE_ADDR pc)
{
- unsigned int insn = fetch_mips_16 (pc);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ unsigned int insn = fetch_mips_16 (gdbarch, pc);
return extended_mips16_next_pc (frame, pc, 0, insn);
}
Return the address of the first instruction past the prologue. */
static CORE_ADDR
-mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+mips16_scan_prologue (struct gdbarch *gdbarch,
+ CORE_ADDR start_pc, CORE_ADDR limit_pc,
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
int extend_bytes = 0;
int prev_extend_bytes;
CORE_ADDR end_prologue_addr = 0;
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
/* Can be called when there's no process, and hence when there's no
THIS_FRAME. */
prev_inst = inst;
/* Fetch and decode the instruction. */
- inst = (unsigned short) mips_fetch_instruction (cur_pc);
+ inst = (unsigned short) mips_fetch_instruction (gdbarch, cur_pc);
/* Normally we ignore extend instructions. However, if it is
not followed by a valid prologue instruction, then this
static struct mips_frame_cache *
mips_insn16_frame_cache (struct frame_info *this_frame, void **this_cache)
{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct mips_frame_cache *cache;
if ((*this_cache) != NULL)
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
- start_addr = heuristic_proc_start (get_frame_arch (this_frame), pc);
+ start_addr = heuristic_proc_start (gdbarch, pc);
/* We can't analyze the prologue if we couldn't find the begining
of the function. */
if (start_addr == 0)
return cache;
- mips16_scan_prologue (start_addr, pc, this_frame, *this_cache);
+ mips16_scan_prologue (gdbarch, start_addr, pc, this_frame, *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
trad_frame_set_value (cache->saved_regs,
- gdbarch_num_regs (get_frame_arch (this_frame))
- + MIPS_SP_REGNUM,
+ gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
cache->base);
return (*this_cache);
{
struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
this_cache);
+ /* This marks the outermost frame. */
+ if (info->base == 0)
+ return;
(*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
}
Return the address of the first instruction past the prologue. */
static CORE_ADDR
-mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+mips32_scan_prologue (struct gdbarch *gdbarch,
+ CORE_ADDR start_pc, CORE_ADDR limit_pc,
struct frame_info *this_frame,
struct mips_frame_cache *this_cache)
{
int seen_sp_adjust = 0;
int load_immediate_bytes = 0;
int in_delay_slot = 0;
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
/* Can be called when there's no process, and hence when there's no
int reg;
/* Fetch the instruction. */
- inst = (unsigned long) mips_fetch_instruction (cur_pc);
+ inst = (unsigned long) mips_fetch_instruction (gdbarch, cur_pc);
/* Save some code by pre-extracting some useful fields. */
high_word = (inst >> 16) & 0xffff;
static struct mips_frame_cache *
mips_insn32_frame_cache (struct frame_info *this_frame, void **this_cache)
{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct mips_frame_cache *cache;
if ((*this_cache) != NULL)
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
- start_addr = heuristic_proc_start (get_frame_arch (this_frame), pc);
+ start_addr = heuristic_proc_start (gdbarch, pc);
/* We can't analyze the prologue if we couldn't find the begining
of the function. */
if (start_addr == 0)
return cache;
- mips32_scan_prologue (start_addr, pc, this_frame, *this_cache);
+ mips32_scan_prologue (gdbarch, start_addr, pc, this_frame, *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
trad_frame_set_value (cache->saved_regs,
- gdbarch_num_regs (get_frame_arch (this_frame))
- + MIPS_SP_REGNUM,
+ gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
cache->base);
return (*this_cache);
{
struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
this_cache);
+ /* This marks the outermost frame. */
+ if (info->base == 0)
+ return;
(*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
}
mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (is_mips16_addr (addr))
+ addr = unmake_mips16_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
the sequence. */
static int
-deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
+deal_with_atomic_sequence (struct gdbarch *gdbarch,
+ struct address_space *aspace, CORE_ADDR pc)
{
CORE_ADDR breaks[2] = {-1, -1};
CORE_ADDR loc = pc;
if (pc & 0x01)
return 0;
- insn = mips_fetch_instruction (loc);
+ insn = mips_fetch_instruction (gdbarch, loc);
/* Assume all atomic sequences start with a ll/lld instruction. */
if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
return 0;
{
int is_branch = 0;
loc += MIPS_INSN32_SIZE;
- insn = mips_fetch_instruction (loc);
+ insn = mips_fetch_instruction (gdbarch, loc);
/* Assume that there is at most one branch in the atomic
sequence. If a branch is found, put a breakpoint in its
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
- insert_single_step_breakpoint (gdbarch, breaks[index]);
+ insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
return 1;
}
mips_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR pc, next_pc;
pc = get_frame_pc (frame);
- if (deal_with_atomic_sequence (gdbarch, pc))
+ if (deal_with_atomic_sequence (gdbarch, aspace, pc))
return 1;
next_pc = mips_next_pc (frame, pc);
- insert_single_step_breakpoint (gdbarch, next_pc);
+ insert_single_step_breakpoint (gdbarch, aspace, next_pc);
return 1;
}
end of a function. */
static int
-mips_about_to_return (CORE_ADDR pc)
+mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
{
if (mips_pc_is_mips16 (pc))
/* This mips16 case isn't necessarily reliable. Sometimes the compiler
as $a3), then a "jr" using that register. This second case
is almost impossible to distinguish from an indirect jump
used for switch statements, so we don't even try. */
- return mips_fetch_instruction (pc) == 0xe820; /* jr $ra */
+ return mips_fetch_instruction (gdbarch, pc) == 0xe820; /* jr $ra */
else
- return mips_fetch_instruction (pc) == 0x3e00008; /* jr $ra */
+ return mips_fetch_instruction (gdbarch, pc) == 0x3e00008; /* jr $ra */
}
stop_soon, but with this test, at least we
don't print out warnings for every child forked (eg, on
decstation). 22apr93 rich@cygnus.com. */
- if (inf->stop_soon == NO_STOP_QUIETLY)
+ if (inf->control.stop_soon == NO_STOP_QUIETLY)
{
static int blurb_printed = 0;
addiu sp,-n
daddiu sp,-n
extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n' */
- inst = mips_fetch_instruction (start_pc);
+ inst = mips_fetch_instruction (gdbarch, start_pc);
if ((inst & 0xff80) == 0x6480) /* save */
{
if (start_pc - instlen >= fence)
{
- inst = mips_fetch_instruction (start_pc - instlen);
+ inst = mips_fetch_instruction (gdbarch, start_pc - instlen);
if ((inst & 0xf800) == 0xf000) /* extend */
start_pc -= instlen;
}
else
seen_adjsp = 0;
}
- else if (mips_about_to_return (start_pc))
+ else if (mips_about_to_return (gdbarch, start_pc))
{
/* Skip return and its delay slot. */
start_pc += 2 * MIPS_INSN32_SIZE;
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);
"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_mips16 (addr))
+ {
+ store_signed_integer (valbuf, len, byte_order,
+ make_mips16_addr (addr));
+ val = valbuf;
+ }
+ else
+ val = value_contents (arg);
+ }
/* The EABI passes structures that do not fit in a register by
reference. */
- if (len > regsize
+ else if (len > regsize
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
- store_unsigned_integer (valbuf, regsize, value_address (arg));
+ store_unsigned_integer (valbuf, regsize, byte_order,
+ value_address (arg));
typecode = TYPE_CODE_PTR;
len = regsize;
val = valbuf;
{
int low_offset = gdbarch_byte_order (gdbarch)
== BFD_ENDIAN_BIG ? 4 : 0;
- unsigned long regval;
+ long regval;
/* Write the low word of the double to the even register(s). */
- regval = extract_unsigned_integer (val + low_offset, 4);
+ regval = extract_signed_integer (val + low_offset,
+ 4, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, 4));
- regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
+ regcache_cooked_write_signed (regcache, float_argreg++, regval);
/* Write the high word of the double to the odd register(s). */
- regval = extract_unsigned_integer (val + 4 - low_offset, 4);
+ regval = extract_signed_integer (val + 4 - low_offset,
+ 4, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, 4));
- regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
+ regcache_cooked_write_signed (regcache, float_argreg++, regval);
}
else
{
in a single register. */
/* On 32 bit ABI's the float_argreg is further adjusted
above to ensure that it is even register aligned. */
- LONGEST regval = extract_unsigned_integer (val, len);
+ LONGEST regval = extract_signed_integer (val, len, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, len));
- regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
+ regcache_cooked_write_signed (regcache, float_argreg++, regval);
}
}
else
&& !fp_register_arg_p (gdbarch, typecode, arg_type))
{
LONGEST regval =
- extract_unsigned_integer (val, partial_len);
+ extract_signed_integer (val, partial_len, byte_order);
if (mips_debug)
fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
argreg,
phex (regval, regsize));
- regcache_cooked_write_unsigned (regcache, argreg, regval);
+ regcache_cooked_write_signed (regcache, argreg, regval);
argreg++;
}
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 shared libraries, "t9" needs to point at the function
/* This is a floating point value that fits entirely
in a single register or a pair of registers. */
int reglen = (len <= MIPS64_REGSIZE ? len : MIPS64_REGSIZE);
- LONGEST regval = extract_unsigned_integer (val, reglen);
+ LONGEST regval = extract_unsigned_integer (val, reglen, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, reglen));
argreg++;
if (len == 16)
{
- regval = extract_unsigned_integer (val + reglen, reglen);
+ regval = extract_unsigned_integer (val + reglen,
+ reglen, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, reglen));
|| (partial_len < 4
&& typecode == TYPE_CODE_INT
&& !TYPE_UNSIGNED (arg_type)))
- regval = extract_signed_integer (val, partial_len);
+ regval = extract_signed_integer (val, partial_len,
+ byte_order);
else
- regval = extract_unsigned_integer (val, partial_len);
+ regval = extract_unsigned_integer (val, partial_len,
+ byte_order);
/* A non-floating-point argument being passed in a
general register. If a struct or union, and if
(and $f2 if necessary). This is a generalization of the Fortran COMPLEX
case.
- * Any other struct or union results of at most 128 bits are returned in
+ * Any other composite results of at most 128 bits are returned in
$2 (first 64 bits) and $3 (remainder, if necessary).
* Larger composite results are handled by converting the function to a
specific exception to return COMPLEX results in the floating point
registers.] */
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY
- || TYPE_LENGTH (type) > 2 * MIPS64_REGSIZE)
+ if (TYPE_LENGTH (type) > 2 * MIPS64_REGSIZE)
return RETURN_VALUE_STRUCT_CONVENTION;
else if (TYPE_CODE (type) == TYPE_CODE_FLT
&& TYPE_LENGTH (type) == 16
return RETURN_VALUE_REGISTER_CONVENTION;
}
else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION)
+ || TYPE_CODE (type) == TYPE_CODE_UNION
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY)
{
- /* A structure or union. Extract the left justified value,
+ /* A composite type. Extract the left justified value,
regardless of the byte order. I.e. DO NOT USE
mips_xfer_lower. */
int offset;
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 shared libraries, "t9" needs to point at the function
unsigned long regval;
/* Write the low word of the double to the even register(s). */
- regval = extract_unsigned_integer (val + low_offset, 4);
+ regval = extract_unsigned_integer (val + low_offset,
+ 4, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, 4));
regcache_cooked_write_unsigned (regcache, argreg++, regval);
/* Write the high word of the double to the odd register(s). */
- regval = extract_unsigned_integer (val + 4 - low_offset, 4);
+ regval = extract_unsigned_integer (val + 4 - low_offset,
+ 4, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, 4));
in a single register. */
/* On 32 bit ABI's the float_argreg is further adjusted
above to ensure that it is even register aligned. */
- LONGEST regval = extract_unsigned_integer (val, len);
+ LONGEST regval = extract_unsigned_integer (val, len, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, len));
purpose register. */
if (argreg <= MIPS_LAST_ARG_REGNUM (gdbarch))
{
- LONGEST regval = extract_signed_integer (val, partial_len);
+ LONGEST regval = extract_signed_integer (val, partial_len,
+ byte_order);
/* Value may need to be sign extended, because
mips_isa_regsize() != mips_abi_regsize(). */
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 shared libraries, "t9" needs to point at the function
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_mips16 (addr))
+ {
+ store_signed_integer (valbuf, len, byte_order,
+ make_mips16_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 register gets
if (fp_register_arg_p (gdbarch, typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM (gdbarch))
{
- LONGEST regval = extract_unsigned_integer (val, len);
+ LONGEST regval = extract_unsigned_integer (val, len, byte_order);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, len));
purpose register. */
if (argreg <= MIPS_LAST_ARG_REGNUM (gdbarch))
{
- LONGEST regval = extract_signed_integer (val, partial_len);
+ LONGEST regval = extract_signed_integer (val, partial_len,
+ byte_order);
/* Value may need to be sign extended, because
mips_isa_regsize() != mips_abi_regsize(). */
mips_single_step_through_delay (struct gdbarch *gdbarch,
struct frame_info *frame)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc = get_frame_pc (frame);
gdb_byte buf[MIPS_INSN32_SIZE];
if (mips_pc_is_mips16 (pc))
return 0;
- if (!breakpoint_here_p (pc + 4))
+ if (!breakpoint_here_p (get_frame_address_space (frame), pc + 4))
return 0;
if (!safe_frame_unwind_memory (frame, pc, buf, sizeof buf))
/* If error reading memory, guess that it is not a delayed
branch. */
return 0;
- return is_delayed (extract_unsigned_integer (buf, sizeof buf));
+ return is_delayed (extract_unsigned_integer (buf, sizeof buf, byte_order));
}
/* To skip prologues, I use this predicate. Returns either PC itself
limit_pc = pc + 100; /* Magic. */
if (mips_pc_is_mips16 (pc))
- return mips16_scan_prologue (pc, limit_pc, NULL, NULL);
+ return mips16_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL);
else
- return mips32_scan_prologue (pc, limit_pc, NULL, NULL);
+ 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. */
static int
-mips32_in_function_epilogue_p (CORE_ADDR pc)
+mips32_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr = 0, func_end = 0;
unsigned long high_word;
unsigned long inst;
- inst = mips_fetch_instruction (pc);
+ inst = mips_fetch_instruction (gdbarch, pc);
high_word = (inst >> 16) & 0xffff;
if (high_word != 0x27bd /* addiu $sp,$sp,offset */
/* Check whether the PC is in a function epilogue (16-bit version).
This is a helper function for mips_in_function_epilogue_p. */
static int
-mips16_in_function_epilogue_p (CORE_ADDR pc)
+mips16_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr = 0, func_end = 0;
{
unsigned short inst;
- inst = mips_fetch_instruction (pc);
+ inst = mips_fetch_instruction (gdbarch, pc);
if ((inst & 0xf800) == 0xf000) /* extend */
continue;
mips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
if (mips_pc_is_mips16 (pc))
- return mips16_in_function_epilogue_p (pc);
+ return mips16_in_function_epilogue_p (gdbarch, pc);
else
- return mips32_in_function_epilogue_p (pc);
+ return mips32_in_function_epilogue_p (gdbarch, pc);
}
/* Root of all "set mips "/"show mips " commands. This will eventually be
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);
|| 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;
}
static CORE_ADDR
mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
char *name;
CORE_ADDR start_addr;
instructions. FIXME. */
for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSN32_SIZE)
{
- inst = mips_fetch_instruction (target_pc);
+ inst = mips_fetch_instruction (gdbarch, target_pc);
if ((inst & 0xffff0000) == 0x3c010000) /* lui $at */
pc = (inst << 16) & 0xffff0000; /* high word */
else if ((inst & 0xffff0000) == 0x24210000) /* addiu $at */
static CORE_ADDR
mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct minimal_symbol *msym;
int i;
gdb_byte stub_code[16];
if (target_read_memory (pc, stub_code, 16) != 0)
return 0;
for (i = 0; i < 4; i++)
- stub_words[i] = extract_unsigned_integer (stub_code + i * 4, 4);
+ stub_words[i] = extract_unsigned_integer (stub_code + i * 4,
+ 4, byte_order);
/* A stub contains these instructions:
lui t9, %hi(target)
mips_integer_to_address (struct gdbarch *gdbarch,
struct type *type, const gdb_byte *buf)
{
- return (CORE_ADDR) extract_signed_integer (buf, TYPE_LENGTH (type));
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ return extract_signed_integer (buf, TYPE_LENGTH (type), byte_order);
}
/* Dummy virtual frame pointer method. This is no more or less accurate
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_pseudo_register_read (gdbarch, mips_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write);
+ set_gdbarch_ax_pseudo_register_collect (gdbarch,
+ mips_ax_pseudo_register_collect);
+ set_gdbarch_ax_pseudo_register_push_stack
+ (gdbarch, mips_ax_pseudo_register_push_stack);
+
set_gdbarch_elf_make_msymbol_special (gdbarch,
mips_elf_make_msymbol_special);
&mask_address_var, _("\
Set zeroing of upper 32 bits of 64-bit addresses."), _("\
Show zeroing of upper 32 bits of 64-bit addresses."), _("\
-Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to \n\
+Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to\n\
allow GDB to determine the correct value."),
NULL, show_mask_address,
&setmipscmdlist, &showmipscmdlist);