/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
- Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, Free Software Foundation, Inc.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001 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 "gdbtypes.h"
#include "target.h"
#include "arch-utils.h"
+#include "regcache.h"
#include "opcode/mips.h"
#include "elf/mips.h"
int elf_flags;
/* mips options */
enum mips_abi mips_abi;
+ const char *mips_abi_string;
enum mips_fpu_type mips_fpu_type;
int mips_last_arg_regnum;
int mips_last_fp_arg_regnum;
int mips_regs_have_home_p;
int mips_default_stack_argsize;
int gdb_target_is_mips64;
+ int default_mask_address_p;
};
#if GDB_MULTI_ARCH
#define MIPS_SAVED_REGSIZE (mips_saved_regsize())
static unsigned int
-mips_saved_regsize ()
+mips_saved_regsize (void)
{
if (mips_saved_regsize_string == size_auto)
return MIPS_DEFAULT_SAVED_REGSIZE;
#define GDB_TARGET_IS_MIPS64 (gdbarch_tdep (current_gdbarch)->gdb_target_is_mips64 + 0)
#endif
-#define VM_MIN_ADDRESS (CORE_ADDR)0x400000
-
-#if 0
-static int mips_in_lenient_prologue (CORE_ADDR, CORE_ADDR);
+#if GDB_MULTI_ARCH
+#undef MIPS_DEFAULT_MASK_ADDRESS_P
+#define MIPS_DEFAULT_MASK_ADDRESS_P (gdbarch_tdep (current_gdbarch)->default_mask_address_p)
+#elif !defined (MIPS_DEFAULT_MASK_ADDRESS_P)
+#define MIPS_DEFAULT_MASK_ADDRESS_P (0)
#endif
+#define VM_MIN_ADDRESS (CORE_ADDR)0x400000
+
int gdb_print_insn_mips (bfd_vma, disassemble_info *);
static void mips_print_register (int, int);
char *tmp_mips_processor_type;
+/* The list of available "set mips " and "show mips " commands */
+
+static struct cmd_list_element *setmipscmdlist = NULL;
+static struct cmd_list_element *showmipscmdlist = NULL;
+
/* A set of original names, to be used when restoring back to generic
registers from a specific set. */
char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES;
char **mips_processor_reg_names = mips_generic_reg_names;
-/* The list of available "set mips " and "show mips " commands */
-static struct cmd_list_element *setmipscmdlist = NULL;
-static struct cmd_list_element *showmipscmdlist = NULL;
-
char *
-mips_register_name (i)
- int i;
+mips_register_name (int i)
{
return mips_processor_reg_names[i];
}
*linked_proc_desc_table = NULL;
void
-mips_print_extra_frame_info (fi)
- struct frame_info *fi;
+mips_print_extra_frame_info (struct frame_info *fi)
{
if (fi
&& fi->extra_info
static int mips64_transfers_32bit_regs_p = 0;
int
-mips_register_raw_size (reg_nr)
- int reg_nr;
+mips_register_raw_size (int reg_nr)
{
if (mips64_transfers_32bit_regs_p)
return REGISTER_VIRTUAL_SIZE (reg_nr);
+ else if (reg_nr >= FP0_REGNUM && reg_nr < FP0_REGNUM + 32
+ && FP_REGISTER_DOUBLE)
+ /* For MIPS_ABI_N32 (for example) we need 8 byte floating point
+ registers. */
+ return 8;
else
return MIPS_REGSIZE;
}
int
-mips_register_convertible (reg_nr)
- int reg_nr;
+mips_register_convertible (int reg_nr)
{
if (mips64_transfers_32bit_regs_p)
return 0;
}
void
-mips_register_convert_to_virtual (n, virtual_type, raw_buf, virt_buf)
- int n;
- struct type *virtual_type;
- char *raw_buf;
- char *virt_buf;
+mips_register_convert_to_virtual (int n, struct type *virtual_type,
+ char *raw_buf, char *virt_buf)
{
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
memcpy (virt_buf,
}
void
-mips_register_convert_to_raw (virtual_type, n, virt_buf, raw_buf)
- struct type *virtual_type;
- int n;
- char *virt_buf;
- char *raw_buf;
+mips_register_convert_to_raw (struct type *virtual_type, int n,
+ char *virt_buf, char *raw_buf)
{
memset (raw_buf, 0, REGISTER_RAW_SIZE (n));
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
}
/* Should the upper word of 64-bit addresses be zeroed? */
-static int mask_address_p = 1;
+enum cmd_auto_boolean mask_address_var = CMD_AUTO_BOOLEAN_AUTO;
+
+static int
+mips_mask_address_p (void)
+{
+ switch (mask_address_var)
+ {
+ case CMD_AUTO_BOOLEAN_TRUE:
+ return 1;
+ case CMD_AUTO_BOOLEAN_FALSE:
+ return 0;
+ break;
+ case CMD_AUTO_BOOLEAN_AUTO:
+ return MIPS_DEFAULT_MASK_ADDRESS_P;
+ default:
+ internal_error (__FILE__, __LINE__,
+ "mips_mask_address_p: bad switch");
+ return -1;
+ }
+}
+
+static void
+show_mask_address (char *cmd, int from_tty)
+{
+ switch (mask_address_var)
+ {
+ case CMD_AUTO_BOOLEAN_TRUE:
+ printf_filtered ("The 32 bit mips address mask is enabled\n");
+ break;
+ case CMD_AUTO_BOOLEAN_FALSE:
+ printf_filtered ("The 32 bit mips address mask is disabled\n");
+ break;
+ case CMD_AUTO_BOOLEAN_AUTO:
+ printf_filtered ("The 32 bit address mask is set automatically. Currently %s\n",
+ mips_mask_address_p () ? "enabled" : "disabled");
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ "show_mask_address: bad switch");
+ break;
+ }
+}
/* Should call_function allocate stack space for a struct return? */
int
-mips_use_struct_convention (gcc_p, type)
- int gcc_p;
- struct type *type;
+mips_use_struct_convention (int gcc_p, struct type *type)
{
if (MIPS_EABI)
return (TYPE_LENGTH (type) > 2 * MIPS_SAVED_REGSIZE);
return 0;
}
+/* MIPS believes that the PC has a sign extended value. Perhaphs the
+ all registers should be sign extended for simplicity? */
+
+static CORE_ADDR
+mips_read_pc (ptid_t ptid)
+{
+ return read_signed_register_pid (PC_REGNUM, ptid);
+}
/* This returns the PC of the first inst after the prologue. If we can't
find the prologue, then return 0. */
static CORE_ADDR
-after_prologue (pc, proc_desc)
- CORE_ADDR pc;
- mips_extra_func_info_t proc_desc;
+after_prologue (CORE_ADDR pc,
+ mips_extra_func_info_t proc_desc)
{
struct symtab_and_line sal;
CORE_ADDR func_addr, func_end;
for mips_find_saved_regs. */
static void
-mips32_decode_reg_save (inst, gen_mask, float_mask)
- t_inst inst;
- unsigned long *gen_mask;
- unsigned long *float_mask;
+mips32_decode_reg_save (t_inst inst, unsigned long *gen_mask,
+ unsigned long *float_mask)
{
int reg;
for mips_find_saved_regs. */
static void
-mips16_decode_reg_save (inst, gen_mask)
- t_inst inst;
- unsigned long *gen_mask;
+mips16_decode_reg_save (t_inst inst, unsigned long *gen_mask)
{
if ((inst & 0xf800) == 0xd000) /* sw reg,n($sp) */
{
is odd, assume it's a MIPS16 instruction; otherwise MIPS32. */
static t_inst
-mips_fetch_instruction (addr)
- CORE_ADDR addr;
+mips_fetch_instruction (CORE_ADDR addr)
{
char buf[MIPS_INSTLEN];
int instlen;
/* These the fields of 32 bit mips instructions */
-#define mips32_op(x) (x >> 25)
-#define itype_op(x) (x >> 25)
-#define itype_rs(x) ((x >> 21)& 0x1f)
+#define mips32_op(x) (x >> 26)
+#define itype_op(x) (x >> 26)
+#define itype_rs(x) ((x >> 21) & 0x1f)
#define itype_rt(x) ((x >> 16) & 0x1f)
-#define itype_immediate(x) ( x & 0xffff)
+#define itype_immediate(x) (x & 0xffff)
-#define jtype_op(x) (x >> 25)
-#define jtype_target(x) ( x & 0x03fffff)
+#define jtype_op(x) (x >> 26)
+#define jtype_target(x) (x & 0x03ffffff)
-#define rtype_op(x) (x >>25)
-#define rtype_rs(x) ((x>>21) & 0x1f)
-#define rtype_rt(x) ((x>>16) & 0x1f)
-#define rtype_rd(x) ((x>>11) & 0x1f)
-#define rtype_shamt(x) ((x>>6) & 0x1f)
-#define rtype_funct(x) (x & 0x3f )
+#define rtype_op(x) (x >> 26)
+#define rtype_rs(x) ((x >> 21) & 0x1f)
+#define rtype_rt(x) ((x >> 16) & 0x1f)
+#define rtype_rd(x) ((x >> 11) & 0x1f)
+#define rtype_shamt(x) ((x >> 6) & 0x1f)
+#define rtype_funct(x) (x & 0x3f)
static CORE_ADDR
mips32_relative_offset (unsigned long inst)
unsigned long inst;
int op;
inst = mips_fetch_instruction (pc);
- if ((inst & 0xe0000000) != 0) /* Not a special, junp or branch instruction */
+ if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch instruction */
{
- if ((inst >> 27) == 5) /* BEQL BNEZ BLEZL BGTZE , bits 0101xx */
+ if (itype_op (inst) >> 2 == 5)
+ /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
{
- op = ((inst >> 25) & 0x03);
+ op = (itype_op (inst) & 0x03);
switch (op)
{
- case 0:
- goto equal_branch; /* BEQL */
- case 1:
- goto neq_branch; /* BNEZ */
- case 2:
- goto less_branch; /* BLEZ */
- case 3:
- goto greater_branch; /* BGTZ */
+ case 0: /* BEQL */
+ goto equal_branch;
+ case 1: /* BNEL */
+ goto neq_branch;
+ case 2: /* BLEZL */
+ goto less_branch;
+ case 3: /* BGTZ */
+ goto greater_branch;
default:
pc += 4;
}
}
+ else if (itype_op (inst) == 17 && itype_rs (inst) == 8)
+ /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
+ {
+ int tf = itype_rt (inst) & 0x01;
+ int cnum = itype_rt (inst) >> 2;
+ int fcrcs = read_signed_register (FCRCS_REGNUM);
+ int cond = ((fcrcs >> 24) & 0x0e) | ((fcrcs >> 23) & 0x01);
+
+ if (((cond >> cnum) & 0x01) == tf)
+ pc += mips32_relative_offset (inst) + 4;
+ else
+ pc += 8;
+ }
else
pc += 4; /* Not a branch, next instruction is easy */
}
{ /* This gets way messy */
/* Further subdivide into SPECIAL, REGIMM and other */
- switch (op = ((inst >> 26) & 0x07)) /* extract bits 28,27,26 */
+ switch (op = itype_op (inst) & 0x07) /* extract bits 28,27,26 */
{
case 0: /* SPECIAL */
op = rtype_funct (inst);
{
case 8: /* JR */
case 9: /* JALR */
- pc = read_register (rtype_rs (inst)); /* Set PC to that address */
+ /* Set PC to that address */
+ pc = read_signed_register (rtype_rs (inst));
break;
default:
pc += 4;
}
- break; /* end special */
+ break; /* end SPECIAL */
case 1: /* REGIMM */
{
- op = jtype_op (inst); /* branch condition */
- switch (jtype_op (inst))
+ op = itype_rt (inst); /* branch condition */
+ switch (op)
{
case 0: /* BLTZ */
- case 2: /* BLTXL */
- case 16: /* BLTZALL */
+ case 2: /* BLTZL */
+ case 16: /* BLTZAL */
case 18: /* BLTZALL */
less_branch:
- if (read_register (itype_rs (inst)) < 0)
+ if (read_signed_register (itype_rs (inst)) < 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
break;
- case 1: /* GEZ */
+ case 1: /* BGEZ */
case 3: /* BGEZL */
case 17: /* BGEZAL */
case 19: /* BGEZALL */
greater_equal_branch:
- if (read_register (itype_rs (inst)) >= 0)
+ if (read_signed_register (itype_rs (inst)) >= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
break;
- /* All of the other intructions in the REGIMM catagory */
+ /* All of the other instructions in the REGIMM category */
default:
pc += 4;
}
}
- break; /* end REGIMM */
+ break; /* end REGIMM */
case 2: /* J */
case 3: /* JAL */
{
unsigned long reg;
reg = jtype_target (inst) << 2;
+ /* Upper four bits get never changed... */
pc = reg + ((pc + 4) & 0xf0000000);
- /* Whats this mysterious 0xf000000 adjustment ??? */
}
break;
/* FIXME case JALX : */
/* Add 1 to indicate 16 bit mode - Invert ISA mode */
}
break; /* The new PC will be alternate mode */
- case 4: /* BEQ , BEQL */
+ case 4: /* BEQ, BEQL */
equal_branch:
- if (read_register (itype_rs (inst)) ==
- read_register (itype_rt (inst)))
+ if (read_signed_register (itype_rs (inst)) ==
+ read_signed_register (itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
- case 5: /* BNE , BNEL */
+ case 5: /* BNE, BNEL */
neq_branch:
- if (read_register (itype_rs (inst)) !=
- read_register (itype_rs (inst)))
+ if (read_signed_register (itype_rs (inst)) !=
+ read_signed_register (itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
- case 6: /* BLEZ , BLEZL */
+ case 6: /* BLEZ, BLEZL */
less_zero_branch:
- if (read_register (itype_rs (inst) <= 0))
+ if (read_signed_register (itype_rs (inst) <= 0))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 7:
- greater_branch: /* BGTZ BGTZL */
- if (read_register (itype_rs (inst) > 0))
+ default:
+ greater_branch: /* BGTZ, BGTZL */
+ if (read_signed_register (itype_rs (inst) > 0))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
- default:
- pc += 8;
} /* switch */
} /* else */
return pc;
} /* mips32_next_pc */
/* Decoding the next place to set a breakpoint is irregular for the
- mips 16 variant, but fortunatly, there fewer instructions. We have to cope
+ mips 16 variant, but fortunately, there fewer instructions. We have to cope
ith extensions for 16 bit instructions and a pair of actual 32 bit instructions.
We dont want to set a single step instruction on the extend instruction
either.
extRi64type, /* 20 5,6,5,5,3,3,5 */
extshift64type /* 21 5,5,1,1,1,1,1,1,5,1,1,1,3,5 */
};
-/* I am heaping all the fields of the formats into one structure and then,
- only the fields which are involved in instruction extension */
+/* I am heaping all the fields of the formats into one structure and
+ then, only the fields which are involved in instruction extension */
struct upk_mips16
{
- unsigned short inst;
- enum mips16_inst_fmts fmt;
- unsigned long offset;
+ CORE_ADDR offset;
unsigned int regx; /* Function in i8 type */
unsigned int regy;
};
+/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same format
+ for the bits which make up the immediatate extension. */
-static void
-print_unpack (char *comment,
- struct upk_mips16 *u)
-{
- printf ("%s %04x ,f(%d) off(%s) (x(%x) y(%x)\n",
- comment, u->inst, u->fmt, paddr (u->offset), u->regx, u->regy);
-}
-
-/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same
- format for the bits which make up the immediatate extension.
- */
-static unsigned long
-extended_offset (unsigned long extension)
+static CORE_ADDR
+extended_offset (unsigned int extension)
{
- unsigned long value;
+ CORE_ADDR value;
value = (extension >> 21) & 0x3f; /* * extract 15:11 */
value = value << 6;
value |= (extension >> 16) & 0x1f; /* extrace 10:5 */
when the offset is to be used in relative addressing */
-static unsigned short
+static unsigned int
fetch_mips_16 (CORE_ADDR pc)
{
char buf[8];
static void
unpack_mips16 (CORE_ADDR pc,
+ unsigned int extension,
+ unsigned int inst,
+ enum mips16_inst_fmts insn_format,
struct upk_mips16 *upk)
{
- CORE_ADDR extpc;
- unsigned long extension;
- int extended;
- extpc = (pc - 4) & ~0x01; /* Extensions are 32 bit instructions */
- /* Decrement to previous address and loose the 16bit mode flag */
- /* return if the instruction was extendable, but not actually extended */
- extended = ((mips32_op (extension) == 30) ? 1 : 0);
- if (extended)
- {
- extension = mips_fetch_instruction (extpc);
- }
- switch (upk->fmt)
+ CORE_ADDR offset;
+ int regx;
+ int regy;
+ switch (insn_format)
{
case itype:
{
- unsigned long value;
- if (extended)
+ CORE_ADDR value;
+ if (extension)
{
value = extended_offset (extension);
value = value << 11; /* rom for the original value */
- value |= upk->inst & 0x7ff; /* eleven bits from instruction */
+ value |= inst & 0x7ff; /* eleven bits from instruction */
}
else
{
- value = upk->inst & 0x7ff;
+ value = inst & 0x7ff;
/* FIXME : Consider sign extension */
}
- upk->offset = value;
+ offset = value;
+ regx = -1;
+ regy = -1;
}
break;
case ritype:
{ /* A register identifier and an offset */
/* Most of the fields are the same as I type but the
immediate value is of a different length */
- unsigned long value;
- if (extended)
+ CORE_ADDR value;
+ if (extension)
{
value = extended_offset (extension);
value = value << 8; /* from the original instruction */
- value |= upk->inst & 0xff; /* eleven bits from instruction */
- upk->regx = (extension >> 8) & 0x07; /* or i8 funct */
+ value |= inst & 0xff; /* eleven bits from instruction */
+ regx = (extension >> 8) & 0x07; /* or i8 funct */
if (value & 0x4000) /* test the sign bit , bit 26 */
{
value &= ~0x3fff; /* remove the sign bit */
}
else
{
- value = upk->inst & 0xff; /* 8 bits */
- upk->regx = (upk->inst >> 8) & 0x07; /* or i8 funct */
+ value = inst & 0xff; /* 8 bits */
+ regx = (inst >> 8) & 0x07; /* or i8 funct */
/* FIXME: Do sign extension , this format needs it */
if (value & 0x80) /* THIS CONFUSES ME */
{
value &= 0xef; /* remove the sign bit */
value = -value;
}
-
}
- upk->offset = value;
+ offset = value;
+ regy = -1;
break;
}
case jalxtype:
{
unsigned long value;
- unsigned short nexthalf;
- value = ((upk->inst & 0x1f) << 5) | ((upk->inst >> 5) & 0x1f);
+ unsigned int nexthalf;
+ value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f);
value = value << 16;
nexthalf = mips_fetch_instruction (pc + 2); /* low bit still set */
value |= nexthalf;
- upk->offset = value;
+ offset = value;
+ regx = -1;
+ regy = -1;
break;
}
default:
- printf_filtered ("Decoding unimplemented instruction format type\n");
- break;
+ internal_error (__FILE__, __LINE__,
+ "bad switch");
}
- /* print_unpack("UPK",upk) ; */
+ upk->offset = offset;
+ upk->regx = regx;
+ upk->regy = regy;
}
-#define mips16_op(x) (x >> 11)
-
-/* This is a map of the opcodes which ae known to perform branches */
-static unsigned char map16[32] =
-{0, 0, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0
-};
-
static CORE_ADDR
add_offset_16 (CORE_ADDR pc, int offset)
{
}
-
-
-static struct upk_mips16 upk;
-
-CORE_ADDR
-mips16_next_pc (CORE_ADDR pc)
+static CORE_ADDR
+extended_mips16_next_pc (CORE_ADDR pc,
+ unsigned int extension,
+ unsigned int insn)
{
- int op;
- t_inst inst;
- /* inst = mips_fetch_instruction(pc) ; - This doesnt always work */
- inst = fetch_mips_16 (pc);
- upk.inst = inst;
- op = mips16_op (upk.inst);
- if (map16[op])
+ int op = (insn >> 11);
+ switch (op)
{
- int reg;
- switch (op)
- {
- case 2: /* Branch */
- upk.fmt = itype;
- unpack_mips16 (pc, &upk);
+ case 2: /* Branch */
+ {
+ CORE_ADDR offset;
+ struct upk_mips16 upk;
+ unpack_mips16 (pc, extension, insn, itype, &upk);
+ offset = upk.offset;
+ if (offset & 0x800)
+ {
+ offset &= 0xeff;
+ offset = -offset;
+ }
+ pc += (offset << 1) + 2;
+ break;
+ }
+ case 3: /* JAL , JALX - Watch out, these are 32 bit instruction */
+ {
+ struct upk_mips16 upk;
+ unpack_mips16 (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 */
+ else
+ pc |= 0x01;
+ break;
+ }
+ case 4: /* beqz */
+ {
+ struct upk_mips16 upk;
+ int reg;
+ unpack_mips16 (pc, extension, insn, ritype, &upk);
+ reg = read_signed_register (upk.regx);
+ if (reg == 0)
+ pc += (upk.offset << 1) + 2;
+ else
+ pc += 2;
+ break;
+ }
+ case 5: /* bnez */
+ {
+ struct upk_mips16 upk;
+ int reg;
+ unpack_mips16 (pc, extension, insn, ritype, &upk);
+ reg = read_signed_register (upk.regx);
+ if (reg != 0)
+ pc += (upk.offset << 1) + 2;
+ else
+ pc += 2;
+ break;
+ }
+ case 12: /* I8 Formats btez btnez */
+ {
+ struct upk_mips16 upk;
+ int reg;
+ unpack_mips16 (pc, extension, insn, i8type, &upk);
+ /* upk.regx contains the opcode */
+ reg = read_signed_register (24); /* Test register is 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;
+ else
+ pc += 2;
+ break;
+ }
+ case 29: /* RR Formats JR, JALR, JALR-RA */
+ {
+ struct upk_mips16 upk;
+ /* upk.fmt = rrtype; */
+ op = insn & 0x1f;
+ if (op == 0)
{
- long offset;
- offset = upk.offset;
- if (offset & 0x800)
+ int reg;
+ upk.regx = (insn >> 8) & 0x07;
+ upk.regy = (insn >> 5) & 0x07;
+ switch (upk.regy)
{
- offset &= 0xeff;
- offset = -offset;
+ case 0:
+ reg = upk.regx;
+ break;
+ case 1:
+ reg = 31;
+ break; /* Function return instruction */
+ case 2:
+ reg = upk.regx;
+ break;
+ default:
+ reg = 31;
+ break; /* BOGUS Guess */
}
- pc += (offset << 1) + 2;
+ pc = read_signed_register (reg);
}
- break;
- case 3: /* JAL , JALX - Watch out, these are 32 bit instruction */
- upk.fmt = jalxtype;
- unpack_mips16 (pc, &upk);
- pc = add_offset_16 (pc, upk.offset);
- if ((upk.inst >> 10) & 0x01) /* Exchange mode */
- pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode */
- else
- pc |= 0x01;
- break;
- case 4: /* beqz */
- upk.fmt = ritype;
- unpack_mips16 (pc, &upk);
- reg = read_register (upk.regx);
- if (reg == 0)
- pc += (upk.offset << 1) + 2;
- else
- pc += 2;
- break;
- case 5: /* bnez */
- upk.fmt = ritype;
- unpack_mips16 (pc, &upk);
- reg = read_register (upk.regx);
- if (reg != 0)
- pc += (upk.offset << 1) + 2;
- else
- pc += 2;
- break;
- case 12: /* I8 Formats btez btnez */
- upk.fmt = i8type;
- unpack_mips16 (pc, &upk);
- /* upk.regx contains the opcode */
- reg = read_register (24); /* Test register is 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;
- else
- pc += 2;
- break;
- case 29: /* RR Formats JR, JALR, JALR-RA */
- upk.fmt = rrtype;
- op = upk.inst & 0x1f;
- if (op == 0)
- {
- upk.regx = (upk.inst >> 8) & 0x07;
- upk.regy = (upk.inst >> 5) & 0x07;
- switch (upk.regy)
- {
- case 0:
- reg = upk.regx;
- break;
- case 1:
- reg = 31;
- break; /* Function return instruction */
- case 2:
- reg = upk.regx;
- break;
- default:
- reg = 31;
- break; /* BOGUS Guess */
- }
- pc = read_register (reg);
- }
- else
- pc += 2;
- break;
- case 30: /* This is an extend instruction */
- pc += 4; /* Dont be setting breakpints on the second half */
- break;
- default:
- printf ("Filtered - next PC probably incorrrect due to jump inst\n");
+ else
pc += 2;
- break;
- }
+ break;
+ }
+ case 30:
+ /* This is an instruction extension. Fetch the real instruction
+ (which follows the extension) and decode things based on
+ that. */
+ {
+ pc += 2;
+ pc = extended_mips16_next_pc (pc, insn, fetch_mips_16 (pc));
+ break;
+ }
+ default:
+ {
+ pc += 2;
+ break;
+ }
}
- else
- pc += 2; /* just a good old instruction */
- /* See if we CAN actually break on the next instruction */
- /* printf("NXTm16PC %08x\n",(unsigned long)pc) ; */
return pc;
-} /* mips16_next_pc */
+}
-/* The mips_next_pc function supports single_tep when the remote target monitor or
- stub is not developed enough to so 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.
- The MIPS32 and MIPS16 variants are quite different
- */
+CORE_ADDR
+mips16_next_pc (CORE_ADDR pc)
+{
+ unsigned int insn = fetch_mips_16 (pc);
+ return extended_mips16_next_pc (pc, 0, insn);
+}
+
+/* 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.
+ The MIPS32 and MIPS16 variants are quite different */
CORE_ADDR
mips_next_pc (CORE_ADDR pc)
{
- t_inst inst;
- /* inst = mips_fetch_instruction(pc) ; */
- /* if (pc_is_mips16) <----- This is failing */
if (pc & 0x01)
return mips16_next_pc (pc);
else
return mips32_next_pc (pc);
-} /* mips_next_pc */
+}
/* Guaranteed to set fci->saved_regs to some values (it never leaves it
NULL). */
void
-mips_find_saved_regs (fci)
- struct frame_info *fci;
+mips_find_saved_regs (struct frame_info *fci)
{
int ireg;
CORE_ADDR reg_position;
}
static CORE_ADDR
-read_next_frame_reg (fi, regno)
- struct frame_info *fi;
- int regno;
+read_next_frame_reg (struct frame_info *fi, int regno)
{
for (; fi; fi = fi->next)
{
return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), MIPS_SAVED_REGSIZE);
}
}
- return read_register (regno);
+ return read_signed_register (regno);
}
/* mips_addr_bits_remove - remove useless address bits */
-CORE_ADDR
-mips_addr_bits_remove (addr)
- CORE_ADDR addr;
+static CORE_ADDR
+mips_addr_bits_remove (CORE_ADDR addr)
{
if (GDB_TARGET_IS_MIPS64)
{
- if (mask_address_p && (addr >> 32 == (CORE_ADDR) 0xffffffff))
+ if (mips_mask_address_p () && (addr >> 32 == (CORE_ADDR) 0xffffffff))
{
/* This hack is a work-around for existing boards using
PMON, the simulator, and any other 64-bit targets that
hardware. Thus, the PC or SP are likely to have been
sign extended to all 1s by instruction sequences that
load 32-bit addresses. For example, a typical piece of
- code that loads an address is this: lui $r2, <upper 16
- bits> ori $r2, <lower 16 bits> But the lui sign-extends
- the value such that the upper 32 bits may be all 1s. The
- workaround is simply to mask off these bits. In the
- future, gcc may be changed to support true 64-bit
- addressing, and this masking will have to be disabled. */
+ code that loads an address is this:
+ lui $r2, <upper 16 bits>
+ ori $r2, <lower 16 bits>
+ But the lui sign-extends the value such that the upper 32
+ bits may be all 1s. The workaround is simply to mask off
+ these bits. In the future, gcc may be changed to support
+ true 64-bit addressing, and this masking will have to be
+ disabled. */
addr &= (CORE_ADDR) 0xffffffff;
}
}
- else
+ else if (mips_mask_address_p ())
{
+ /* FIXME: This is wrong! mips_addr_bits_remove() shouldn't be
+ masking off bits, instead, the actual target should be asking
+ for the address to be converted to a valid pointer. */
/* Even when GDB is configured for some 32-bit targets
(e.g. mips-elf), BFD is configured to handle 64-bit targets,
so CORE_ADDR is 64 bits. So we still have to mask off
return addr;
}
+/* mips_software_single_step() is called just before we want to resume
+ the inferior, if we want to single-step it but there is no hardware
+ or kernel single-step support (MIPS on Linux for example). We find
+ the target of the coming instruction and breakpoint it.
+
+ single_step is also called just after the inferior stops. If we had
+ set up a simulated single-step, we undo our damage. */
+
void
-mips_init_frame_pc_first (fromleaf, prev)
- int fromleaf;
- struct frame_info *prev;
+mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+{
+ static CORE_ADDR next_pc;
+ typedef char binsn_quantum[BREAKPOINT_MAX];
+ static binsn_quantum break_mem;
+ CORE_ADDR pc;
+
+ if (insert_breakpoints_p)
+ {
+ pc = read_register (PC_REGNUM);
+ next_pc = mips_next_pc (pc);
+
+ target_insert_breakpoint (next_pc, break_mem);
+ }
+ else
+ target_remove_breakpoint (next_pc, break_mem);
+}
+
+static void
+mips_init_frame_pc_first (int fromleaf, struct frame_info *prev)
{
CORE_ADDR pc, tmp;
CORE_ADDR
-mips_frame_saved_pc (frame)
- struct frame_info *frame;
+mips_frame_saved_pc (struct frame_info *frame)
{
CORE_ADDR saved_pc;
mips_extra_func_info_t proc_desc = frame->extra_info->proc_desc;
This is a helper function for mips{16,32}_heuristic_proc_desc. */
static void
-set_reg_offset (regno, offset)
- int regno;
- CORE_ADDR offset;
+set_reg_offset (int regno, CORE_ADDR offset)
{
if (temp_saved_regs[regno] == 0)
temp_saved_regs[regno] = offset;
end of a function. */
static int
-mips_about_to_return (pc)
- CORE_ADDR pc;
+mips_about_to_return (CORE_ADDR pc)
{
if (pc_is_mips16 (pc))
/* This mips16 case isn't necessarily reliable. Sometimes the compiler
lines. */
static CORE_ADDR
-heuristic_proc_start (pc)
- CORE_ADDR pc;
+heuristic_proc_start (CORE_ADDR pc)
{
CORE_ADDR start_pc;
CORE_ADDR fence;
break;
}
-#if 0
- /* skip nops (usually 1) 0 - is this */
- while (start_pc < pc && read_memory_integer (start_pc, MIPS_INSTLEN) == 0)
- start_pc += MIPS_INSTLEN;
-#endif
return start_pc;
}
for mips16_heuristic_proc_desc. */
static int
-mips16_get_imm (prev_inst, inst, nbits, scale, is_signed)
- unsigned short prev_inst; /* previous instruction */
- unsigned short inst; /* current instruction */
- int nbits; /* number of bits in imm field */
- int scale; /* scale factor to be applied to imm */
- int is_signed; /* is the imm field signed? */
+mips16_get_imm (unsigned short prev_inst, /* previous instruction */
+ unsigned short inst, /* current instruction */
+ int nbits, /* number of bits in imm field */
+ int scale, /* scale factor to be applied to imm */
+ int is_signed) /* is the imm field signed? */
{
int offset;
stream from start_pc to limit_pc. */
static void
-mips16_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp)
- CORE_ADDR start_pc, limit_pc;
- struct frame_info *next_frame;
- CORE_ADDR sp;
+mips16_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+ struct frame_info *next_frame, CORE_ADDR sp)
{
CORE_ADDR cur_pc;
CORE_ADDR frame_addr = 0; /* Value of $r17, used as frame pointer */
}
static void
-mips32_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp)
- CORE_ADDR start_pc, limit_pc;
- struct frame_info *next_frame;
- CORE_ADDR sp;
+mips32_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+ struct frame_info *next_frame, CORE_ADDR sp)
{
CORE_ADDR cur_pc;
CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer */
}
static mips_extra_func_info_t
-heuristic_proc_desc (start_pc, limit_pc, next_frame)
- CORE_ADDR start_pc, limit_pc;
- struct frame_info *next_frame;
+heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+ struct frame_info *next_frame)
{
CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
}
static mips_extra_func_info_t
-non_heuristic_proc_desc (pc, addrptr)
- CORE_ADDR pc;
- CORE_ADDR *addrptr;
+non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
{
CORE_ADDR startaddr;
mips_extra_func_info_t proc_desc;
static mips_extra_func_info_t
-find_proc_desc (pc, next_frame)
- CORE_ADDR pc;
- struct frame_info *next_frame;
+find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
{
mips_extra_func_info_t proc_desc;
CORE_ADDR startaddr;
}
static CORE_ADDR
-get_frame_pointer (frame, proc_desc)
- struct frame_info *frame;
- mips_extra_func_info_t proc_desc;
+get_frame_pointer (struct frame_info *frame,
+ mips_extra_func_info_t proc_desc)
{
return ADDR_BITS_REMOVE (
read_next_frame_reg (frame, PROC_FRAME_REG (proc_desc)) +
mips_extra_func_info_t cached_proc_desc;
CORE_ADDR
-mips_frame_chain (frame)
- struct frame_info *frame;
+mips_frame_chain (struct frame_info *frame)
{
mips_extra_func_info_t proc_desc;
CORE_ADDR tmp;
}
void
-mips_init_extra_frame_info (fromleaf, fci)
- int fromleaf;
- struct frame_info *fci;
+mips_init_extra_frame_info (int fromleaf, struct frame_info *fci)
{
int regnum;
arguments without difficulty. */
struct frame_info *
-setup_arbitrary_frame (argc, argv)
- int argc;
- CORE_ADDR *argv;
+setup_arbitrary_frame (int argc, CORE_ADDR *argv)
{
if (argc != 2)
error ("MIPS frame specifications require two arguments: sp and pc");
&& MIPS_FPU_TYPE != MIPS_FPU_NONE);
}
+/* On o32, argument passing in GPRs depends on the alignment of the type being
+ passed. Return 1 if this type must be aligned to a doubleword boundary. */
+
+static int
+mips_type_needs_double_align (struct type *type)
+{
+ enum type_code typecode = TYPE_CODE (type);
+
+ if (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
+ return 1;
+ else if (typecode == TYPE_CODE_STRUCT)
+ {
+ if (TYPE_NFIELDS (type) < 1)
+ return 0;
+ return mips_type_needs_double_align (TYPE_FIELD_TYPE (type, 0));
+ }
+ else if (typecode == TYPE_CODE_UNION)
+ {
+ int i, n;
+
+ n = TYPE_NFIELDS (type);
+ for (i = 0; i < n; i++)
+ if (mips_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
+ return 1;
+ return 0;
+ }
+ return 0;
+}
+
CORE_ADDR
-mips_push_arguments (nargs, args, sp, struct_return, struct_addr)
- int nargs;
- value_ptr *args;
- CORE_ADDR sp;
- int struct_return;
- CORE_ADDR struct_addr;
+mips_push_arguments (int nargs,
+ struct value **args,
+ CORE_ADDR sp,
+ int struct_return,
+ CORE_ADDR struct_addr)
{
int argreg;
int float_argreg;
On at least one MIPS variant, stack frames need to be 128-bit
aligned, so we round to this widest known alignment. */
sp = ROUND_DOWN (sp, 16);
- struct_addr = ROUND_DOWN (struct_addr, MIPS_SAVED_REGSIZE);
+ struct_addr = ROUND_DOWN (struct_addr, 16);
/* Now make space on the stack for the args. We allocate more
than necessary for EABI, because the first few arguments are
passed in registers, but that's OK. */
for (argnum = 0; argnum < nargs; argnum++)
- len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), MIPS_SAVED_REGSIZE);
+ len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), MIPS_STACK_ARGSIZE);
sp -= ROUND_UP (len, 16);
if (mips_debug)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
- "mips_push_arguments: struct_return at r%d 0x%lx\n",
+ "mips_push_arguments: struct_return reg=%d 0x%lx\n",
argreg, (long) struct_addr);
write_register (argreg++, struct_addr);
+ if (MIPS_REGS_HAVE_HOME_P)
+ stack_offset += MIPS_STACK_ARGSIZE;
}
/* Now load as many as possible of the first arguments into
{
char *val;
char valbuf[MAX_REGISTER_RAW_SIZE];
- value_ptr arg = args[argnum];
+ struct value *arg = args[argnum];
struct type *arg_type = check_typedef (VALUE_TYPE (arg));
int len = TYPE_LENGTH (arg_type);
enum type_code typecode = TYPE_CODE (arg_type);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
"mips_push_arguments: %d len=%d type=%d",
- argnum, len, (int) typecode);
+ argnum + 1, len, (int) typecode);
/* The EABI passes structures that do not fit in a register by
reference. In all other cases, pass the structure by value. */
val = (char *) VALUE_CONTENTS (arg);
/* 32-bit ABIs always start floating point arguments in an
- even-numbered floating point register. */
- if (!FP_REGISTER_DOUBLE && typecode == TYPE_CODE_FLT
- && (float_argreg & 1))
- float_argreg++;
+ even-numbered floating point register. Round the FP register
+ up before the check to see if there are any FP registers
+ left. Non MIPS_EABI targets also pass the FP in the integer
+ registers so also round up normal registers. */
+ if (!FP_REGISTER_DOUBLE
+ && fp_register_arg_p (typecode, arg_type))
+ {
+ if ((float_argreg & 1))
+ float_argreg++;
+ }
/* Floating point arguments passed in registers have to be
treated specially. On 32-bit architectures, doubles
don't use float registers for arguments. This duplication of
arguments in general registers can't hurt non-MIPS16 functions
because those registers are normally skipped. */
- /* MIPS_EABI squeeses a struct that contains a single floating
- point value into an FP register instead of pusing it onto the
+ /* MIPS_EABI squeezes a struct that contains a single floating
+ point value into an FP register instead of pushing it onto the
stack. */
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
/* Write the low word of the double to the even register(s). */
regval = extract_unsigned_integer (val + low_offset, 4);
if (mips_debug)
- fprintf_unfiltered (gdb_stdlog, " fpreg=%d val=%s",
+ fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, 4));
write_register (float_argreg++, regval);
if (!MIPS_EABI)
{
if (mips_debug)
- fprintf_unfiltered (gdb_stdlog, " reg=%d val=%s",
+ fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
argreg, phex (regval, 4));
write_register (argreg++, regval);
}
/* Write the high word of the double to the odd register(s). */
regval = extract_unsigned_integer (val + 4 - low_offset, 4);
if (mips_debug)
- fprintf_unfiltered (gdb_stdlog, " fpreg=%d val=%s",
+ fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, 4));
write_register (float_argreg++, regval);
if (!MIPS_EABI)
{
if (mips_debug)
- fprintf_unfiltered (gdb_stdlog, " reg=%d val=%s",
+ fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
argreg, phex (regval, 4));
write_register (argreg++, regval);
}
above to ensure that it is even register aligned. */
LONGEST regval = extract_unsigned_integer (val, len);
if (mips_debug)
- fprintf_unfiltered (gdb_stdlog, " fpreg=%d val=%s",
+ fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, len));
write_register (float_argreg++, regval);
if (!MIPS_EABI)
guess) to ensure that the corresponding integer
register has reserved the same space. */
if (mips_debug)
- fprintf_unfiltered (gdb_stdlog, " reg=%d val=%s",
+ fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
argreg, phex (regval, len));
write_register (argreg, regval);
argreg += FP_REGISTER_DOUBLE ? 1 : 2;
}
}
+ /* Reserve space for the FP register. */
+ if (MIPS_REGS_HAVE_HOME_P)
+ stack_offset += ROUND_UP (len, MIPS_STACK_ARGSIZE);
}
else
{
compatibility, we will put them in both places. */
int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) &&
(len % MIPS_SAVED_REGSIZE != 0));
+ /* Structures should be aligned to eight bytes (even arg registers)
+ on MIPS_ABI_O32 if their first member has double precision. */
+ if (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_O32
+ && mips_type_needs_double_align (arg_type))
+ {
+ if ((argreg & 1))
+ argreg++;
+ }
/* Note: Floating-point values that didn't fit into an FP
register are only written to memory. */
while (len > 0)
int stack_used_p = 0;
int partial_len = len < MIPS_SAVED_REGSIZE ? len : MIPS_SAVED_REGSIZE;
+ if (mips_debug)
+ fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
+ partial_len);
+
/* Write this portion of the argument to the stack. */
if (argreg > MIPS_LAST_ARG_REGNUM
|| odd_sized_struct
if (mips_debug)
{
- fprintf_unfiltered (gdb_stdlog, " stack_offset=0x%lx",
+ fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%lx",
(long) stack_offset);
fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%lx",
(long) longword_offset);
same for integral types.
Also don't do this adjustment on EABI and O64
- binaries. */
+ binaries.
+
+ cagney/2001-07-23: gdb/179: Also, GCC, when
+ outputting LE O32 with sizeof (struct) <
+ MIPS_SAVED_REGSIZE, generates a left shift as
+ part of storing the argument in a register a
+ register (the left shift isn't generated when
+ sizeof (struct) >= MIPS_SAVED_REGSIZE). Since it
+ is quite possible that this is GCC contradicting
+ the LE/O32 ABI, GDB has not been adjusted to
+ accommodate this. Either someone needs to
+ demonstrate that the LE/O32 ABI specifies such a
+ left shift OR this new ABI gets identified as
+ such and GDB gets tweaked accordingly. */
if (!MIPS_EABI
&& MIPS_SAVED_REGSIZE < 8
TARGET_CHAR_BIT);
if (mips_debug)
- fprintf_filtered (gdb_stdlog, " reg=%d val=%s",
+ fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
argreg,
phex (regval, MIPS_SAVED_REGSIZE));
write_register (argreg, regval);
}
CORE_ADDR
-mips_push_return_address (pc, sp)
- CORE_ADDR pc;
- CORE_ADDR sp;
+mips_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
/* Set the return address register to point to the entry
point of the program, where a breakpoint lies in wait. */
#define MASK(i,j) (((1 << ((j)+1))-1) ^ ((1 << (i))-1))
void
-mips_push_dummy_frame ()
+mips_push_dummy_frame (void)
{
int ireg;
struct linked_proc_info *link = (struct linked_proc_info *)
xmalloc (sizeof (struct linked_proc_info));
mips_extra_func_info_t proc_desc = &link->info;
- CORE_ADDR sp = ADDR_BITS_REMOVE (read_register (SP_REGNUM));
+ CORE_ADDR sp = ADDR_BITS_REMOVE (read_signed_register (SP_REGNUM));
CORE_ADDR old_sp = sp;
link->next = linked_proc_desc_table;
linked_proc_desc_table = link;
}
void
-mips_pop_frame ()
+mips_pop_frame (void)
{
register int regnum;
struct frame_info *frame = get_current_frame ();
else
linked_proc_desc_table = pi_ptr->next;
- free (pi_ptr);
+ xfree (pi_ptr);
write_register (HI_REGNUM,
read_memory_integer (new_sp - 2 * MIPS_SAVED_REGSIZE,
}
static void
-mips_print_register (regnum, all)
- int regnum, all;
+mips_print_register (int regnum, int all)
{
char raw_buffer[MAX_REGISTER_RAW_SIZE];
Print regs in pretty columns. */
static int
-do_fp_register_row (regnum)
- int regnum;
+do_fp_register_row (int regnum)
{ /* do values for FP (float) regs */
char *raw_buffer[2];
char *dbl_buffer;
flt2 = unpack_double (builtin_type_float, raw_buffer[LO], &inv2);
doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
- printf_filtered (inv1 ? " %-5s: <invalid float>" :
- " %-5s%-17.9g", REGISTER_NAME (regnum), flt1);
- printf_filtered (inv2 ? " %-5s: <invalid float>" :
- " %-5s%-17.9g", REGISTER_NAME (regnum + 1), flt2);
- printf_filtered (inv3 ? " dbl: <invalid double>\n" :
- " dbl: %-24.17g\n", doub);
+ printf_filtered (" %-5s", REGISTER_NAME (regnum));
+ if (inv1)
+ printf_filtered (": <invalid float>");
+ else
+ printf_filtered ("%-17.9g", flt1);
+
+ printf_filtered (" %-5s", REGISTER_NAME (regnum + 1));
+ if (inv2)
+ printf_filtered (": <invalid float>");
+ else
+ printf_filtered ("%-17.9g", flt2);
+
+ printf_filtered (" dbl: ");
+ if (inv3)
+ printf_filtered ("<invalid double>");
+ else
+ printf_filtered ("%-24.17g", doub);
+ printf_filtered ("\n");
+
/* may want to do hex display here (future enhancement) */
regnum += 2;
}
&raw_buffer[HI][offset], &inv1);
doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
- printf_filtered (inv1 ? " %-5s: <invalid float>" :
- " %-5s flt: %-17.9g", REGISTER_NAME (regnum), flt1);
- printf_filtered (inv3 ? " dbl: <invalid double>\n" :
- " dbl: %-24.17g\n", doub);
+ printf_filtered (" %-5s: ", REGISTER_NAME (regnum));
+ if (inv1)
+ printf_filtered ("<invalid float>");
+ else
+ printf_filtered ("flt: %-17.9g", flt1);
+
+ printf_filtered (" dbl: ");
+ if (inv3)
+ printf_filtered ("<invalid double>");
+ else
+ printf_filtered ("%-24.17g", doub);
+
+ printf_filtered ("\n");
/* may want to do hex display here (future enhancement) */
regnum++;
}
/* Print a row's worth of GP (int) registers, with name labels above */
static int
-do_gp_register_row (regnum)
- int regnum;
+do_gp_register_row (int regnum)
{
/* do values for GP (int) regs */
char raw_buffer[MAX_REGISTER_RAW_SIZE];
/* MIPS_DO_REGISTERS_INFO(): called by "info register" command */
void
-mips_do_registers_info (regnum, fpregs)
- int regnum;
- int fpregs;
+mips_do_registers_info (int regnum, int fpregs)
{
if (regnum != -1) /* do one specified register */
{
Can return -1, meaning no way to tell. */
int
-mips_frame_num_args (frame)
- struct frame_info *frame;
+mips_frame_num_args (struct frame_info *frame)
{
-#if 0 /* FIXME Use or lose this! */
- struct chain_info_t *p;
-
- p = mips_find_cached_frame (FRAME_FP (frame));
- if (p->valid)
- return p->the_info.numargs;
-#endif
return -1;
}
static int is_delayed (unsigned long);
static int
-is_delayed (insn)
- unsigned long insn;
+is_delayed (unsigned long insn)
{
int i;
for (i = 0; i < NUMOPCODES; ++i)
}
int
-mips_step_skips_delay (pc)
- CORE_ADDR pc;
+mips_step_skips_delay (CORE_ADDR pc)
{
char buf[MIPS_INSTLEN];
inst = mips_fetch_instruction (pc);
high_word = (inst >> 16) & 0xffff;
-#if 0
- if (lenient && is_delayed (inst))
- continue;
-#endif
-
if (high_word == 0x27bd /* addiu $sp,$sp,offset */
|| high_word == 0x67bd) /* daddiu $sp,$sp,offset */
seen_sp_adjust = 1;
int buf_offset;
};
-static void return_value_location (struct type *, struct return_value_word *,
- struct return_value_word *);
-
static void
-return_value_location (valtype, hi, lo)
- struct type *valtype;
- struct return_value_word *hi;
- struct return_value_word *lo;
+return_value_location (struct type *valtype,
+ struct return_value_word *hi,
+ struct return_value_word *lo)
{
int len = TYPE_LENGTH (valtype);
copy its value into `valbuf'. */
void
-mips_extract_return_value (valtype, regbuf, valbuf)
- struct type *valtype;
- char regbuf[REGISTER_BYTES];
- char *valbuf;
+mips_extract_return_value (struct type *valtype,
+ char regbuf[REGISTER_BYTES],
+ char *valbuf)
{
struct return_value_word lo;
struct return_value_word hi;
- return_value_location (valtype, &lo, &hi);
+ return_value_location (valtype, &hi, &lo);
memcpy (valbuf + lo.buf_offset,
regbuf + REGISTER_BYTE (lo.reg) + lo.reg_offset,
memcpy (valbuf + hi.buf_offset,
regbuf + REGISTER_BYTE (hi.reg) + hi.reg_offset,
hi.len);
-
-#if 0
- int regnum;
- int offset = 0;
- int len = TYPE_LENGTH (valtype);
-
- regnum = 2;
- if (TYPE_CODE (valtype) == TYPE_CODE_FLT
- && (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE
- || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE
- && len <= MIPS_FPU_SINGLE_REGSIZE)))
- regnum = FP0_REGNUM;
-
- if (TARGET_BYTE_ORDER == BIG_ENDIAN)
- { /* "un-left-justify" the value from the register */
- if (len < REGISTER_RAW_SIZE (regnum))
- offset = REGISTER_RAW_SIZE (regnum) - len;
- if (len > REGISTER_RAW_SIZE (regnum) && /* odd-size structs */
- len < REGISTER_RAW_SIZE (regnum) * 2 &&
- (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
- TYPE_CODE (valtype) == TYPE_CODE_UNION))
- offset = 2 * REGISTER_RAW_SIZE (regnum) - len;
- }
- memcpy (valbuf, regbuf + REGISTER_BYTE (regnum) + offset, len);
- REGISTER_CONVERT_TO_TYPE (regnum, valtype, valbuf);
-#endif
}
/* Given a return value in `valbuf' with a type `valtype', write it's
value into the appropriate register. */
void
-mips_store_return_value (valtype, valbuf)
- struct type *valtype;
- char *valbuf;
+mips_store_return_value (struct type *valtype, char *valbuf)
{
char raw_buffer[MAX_REGISTER_RAW_SIZE];
struct return_value_word lo;
struct return_value_word hi;
- return_value_location (valtype, &lo, &hi);
+ return_value_location (valtype, &hi, &lo);
memset (raw_buffer, 0, sizeof (raw_buffer));
memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len);
raw_buffer,
REGISTER_RAW_SIZE (hi.reg));
}
-
-#if 0
- int regnum;
- int offset = 0;
- int len = TYPE_LENGTH (valtype);
- char raw_buffer[MAX_REGISTER_RAW_SIZE];
-
- regnum = 2;
- if (TYPE_CODE (valtype) == TYPE_CODE_FLT
- && (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE
- || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE
- && len <= MIPS_REGSIZE)))
- regnum = FP0_REGNUM;
-
- if (TARGET_BYTE_ORDER == BIG_ENDIAN)
- { /* "left-justify" the value in the register */
- if (len < REGISTER_RAW_SIZE (regnum))
- offset = REGISTER_RAW_SIZE (regnum) - len;
- if (len > REGISTER_RAW_SIZE (regnum) && /* odd-size structs */
- len < REGISTER_RAW_SIZE (regnum) * 2 &&
- (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
- TYPE_CODE (valtype) == TYPE_CODE_UNION))
- offset = 2 * REGISTER_RAW_SIZE (regnum) - len;
- }
- memcpy (raw_buffer + offset, valbuf, len);
- REGISTER_CONVERT_FROM_TYPE (regnum, valtype, raw_buffer);
- write_register_bytes (REGISTER_BYTE (regnum), raw_buffer,
- len > REGISTER_RAW_SIZE (regnum) ?
- len : REGISTER_RAW_SIZE (regnum));
-#endif
}
/* Exported procedure: Is PC in the signal trampoline code */
int
-in_sigtramp (pc, ignore)
- CORE_ADDR pc;
- char *ignore; /* function name */
+in_sigtramp (CORE_ADDR pc, char *ignore)
{
if (sigtramp_address == 0)
fixup_sigtramp ();
/* Root of all "set mips "/"show mips " commands. This will eventually be
used for all MIPS-specific commands. */
-static void show_mips_command (char *, int);
static void
-show_mips_command (args, from_tty)
- char *args;
- int from_tty;
+show_mips_command (char *args, int from_tty)
{
help_list (showmipscmdlist, "show mips ", all_commands, gdb_stdout);
}
-static void set_mips_command (char *, int);
static void
-set_mips_command (args, from_tty)
- char *args;
- int from_tty;
+set_mips_command (char *args, int from_tty)
{
printf_unfiltered ("\"set mips\" must be followed by an appropriate subcommand.\n");
help_list (setmipscmdlist, "set mips ", all_commands, gdb_stdout);
/* Commands to show/set the MIPS FPU type. */
-static void show_mipsfpu_command (char *, int);
static void
-show_mipsfpu_command (args, from_tty)
- char *args;
- int from_tty;
+show_mipsfpu_command (char *args, int from_tty)
{
- char *msg;
char *fpu;
switch (MIPS_FPU_TYPE)
{
case MIPS_FPU_NONE:
fpu = "absent (none)";
break;
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
}
if (mips_fpu_type_auto)
printf_unfiltered ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
}
-static void set_mipsfpu_command (char *, int);
static void
-set_mipsfpu_command (args, from_tty)
- char *args;
- int from_tty;
+set_mipsfpu_command (char *args, int from_tty)
{
printf_unfiltered ("\"set mipsfpu\" must be followed by \"double\", \"single\",\"none\" or \"auto\".\n");
show_mipsfpu_command (args, from_tty);
}
-static void set_mipsfpu_single_command (char *, int);
static void
-set_mipsfpu_single_command (args, from_tty)
- char *args;
- int from_tty;
+set_mipsfpu_single_command (char *args, int from_tty)
{
mips_fpu_type = MIPS_FPU_SINGLE;
mips_fpu_type_auto = 0;
}
}
-static void set_mipsfpu_double_command (char *, int);
static void
-set_mipsfpu_double_command (args, from_tty)
- char *args;
- int from_tty;
+set_mipsfpu_double_command (char *args, int from_tty)
{
mips_fpu_type = MIPS_FPU_DOUBLE;
mips_fpu_type_auto = 0;
}
}
-static void set_mipsfpu_none_command (char *, int);
static void
-set_mipsfpu_none_command (args, from_tty)
- char *args;
- int from_tty;
+set_mipsfpu_none_command (char *args, int from_tty)
{
mips_fpu_type = MIPS_FPU_NONE;
mips_fpu_type_auto = 0;
}
}
-static void set_mipsfpu_auto_command (char *, int);
static void
-set_mipsfpu_auto_command (args, from_tty)
- char *args;
- int from_tty;
+set_mipsfpu_auto_command (char *args, int from_tty)
{
mips_fpu_type_auto = 1;
}
/* Command to set the processor type. */
void
-mips_set_processor_type_command (args, from_tty)
- char *args;
- int from_tty;
+mips_set_processor_type_command (char *args, int from_tty)
{
int i;
printf_unfiltered ("%s\n", mips_processor_type_table[i].name);
/* Restore the value. */
- tmp_mips_processor_type = strsave (mips_processor_type);
+ tmp_mips_processor_type = xstrdup (mips_processor_type);
return;
}
{
error ("Unknown processor type `%s'.", tmp_mips_processor_type);
/* Restore its value. */
- tmp_mips_processor_type = strsave (mips_processor_type);
+ tmp_mips_processor_type = xstrdup (mips_processor_type);
}
}
static void
-mips_show_processor_type_command (args, from_tty)
- char *args;
- int from_tty;
+mips_show_processor_type_command (char *args, int from_tty)
{
}
/* Modify the actual processor type. */
int
-mips_set_processor_type (str)
- char *str;
+mips_set_processor_type (char *str)
{
- int i, j;
+ int i;
if (str == NULL)
return 0;
processor id. */
char *
-mips_read_processor_type ()
+mips_read_processor_type (void)
{
CORE_ADDR prid;
callable as an sfunc. */
static void
-reinit_frame_cache_sfunc (args, from_tty, c)
- char *args;
- int from_tty;
- struct cmd_list_element *c;
+reinit_frame_cache_sfunc (char *args, int from_tty,
+ struct cmd_list_element *c)
{
reinit_frame_cache ();
}
int
-gdb_print_insn_mips (memaddr, info)
- bfd_vma memaddr;
- disassemble_info *info;
+gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info)
{
mips_extra_func_info_t proc_desc;
breakpoint should be inserted. */
unsigned char *
-mips_breakpoint_from_pc (pcptr, lenptr)
- CORE_ADDR *pcptr;
- int *lenptr;
+mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
{
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
{
if (pc_is_mips16 (*pcptr))
{
- static char mips16_big_breakpoint[] = MIPS16_BIG_BREAKPOINT;
+ static unsigned char mips16_big_breakpoint[] =
+ MIPS16_BIG_BREAKPOINT;
*pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
*lenptr = sizeof (mips16_big_breakpoint);
return mips16_big_breakpoint;
}
else
{
- static char big_breakpoint[] = BIG_BREAKPOINT;
- static char pmon_big_breakpoint[] = PMON_BIG_BREAKPOINT;
- static char idt_big_breakpoint[] = IDT_BIG_BREAKPOINT;
+ static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
+ static unsigned char pmon_big_breakpoint[] = PMON_BIG_BREAKPOINT;
+ static unsigned char idt_big_breakpoint[] = IDT_BIG_BREAKPOINT;
*lenptr = sizeof (big_breakpoint);
{
if (pc_is_mips16 (*pcptr))
{
- static char mips16_little_breakpoint[] = MIPS16_LITTLE_BREAKPOINT;
+ static unsigned char mips16_little_breakpoint[] =
+ MIPS16_LITTLE_BREAKPOINT;
*pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
*lenptr = sizeof (mips16_little_breakpoint);
return mips16_little_breakpoint;
}
else
{
- static char little_breakpoint[] = LITTLE_BREAKPOINT;
- static char pmon_little_breakpoint[] = PMON_LITTLE_BREAKPOINT;
- static char idt_little_breakpoint[] = IDT_LITTLE_BREAKPOINT;
+ static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
+ static unsigned char pmon_little_breakpoint[] =
+ PMON_LITTLE_BREAKPOINT;
+ static unsigned char idt_little_breakpoint[] =
+ IDT_LITTLE_BREAKPOINT;
*lenptr = sizeof (little_breakpoint);
*/
CORE_ADDR
-mips_skip_stub (pc)
- CORE_ADDR pc;
+mips_skip_stub (CORE_ADDR pc)
{
char *name;
CORE_ADDR start_addr;
target PC is in $31 ($ra). */
if (strcmp (name, "__mips16_ret_sf") == 0
|| strcmp (name, "__mips16_ret_df") == 0)
- return read_register (RA_REGNUM);
+ return read_signed_register (RA_REGNUM);
if (strncmp (name, "__mips16_call_stub_", 19) == 0)
{
/* If the PC is in __mips16_call_stub_{1..10}, this is a call stub
and the target PC is in $2. */
if (name[19] >= '0' && name[19] <= '9')
- return read_register (2);
+ return read_signed_register (2);
/* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
before the jal instruction, this is effectively a call stub
So scan down to the lui/addi and extract the target
address from those two instructions. */
- CORE_ADDR target_pc = read_register (2);
+ CORE_ADDR target_pc = read_signed_register (2);
t_inst inst;
int i;
else
/* This is the 'return' part of a call stub. The return
address is in $r18. */
- return read_register (18);
+ return read_signed_register (18);
}
}
return 0; /* not a stub */
This implements the IN_SOLIB_CALL_TRAMPOLINE macro. */
int
-mips_in_call_stub (pc, name)
- CORE_ADDR pc;
- char *name;
+mips_in_call_stub (CORE_ADDR pc, char *name)
{
CORE_ADDR start_addr;
This implements the IN_SOLIB_RETURN_TRAMPOLINE macro. */
int
-mips_in_return_stub (pc, name)
- CORE_ADDR pc;
- char *name;
+mips_in_return_stub (CORE_ADDR pc, char *name)
{
CORE_ADDR start_addr;
be ignored. This implements the IGNORE_HELPER_CALL macro. */
int
-mips_ignore_helper (pc)
- CORE_ADDR pc;
+mips_ignore_helper (CORE_ADDR pc)
{
char *name;
whose address is the location where the breakpoint should be placed. */
CORE_ADDR
-mips_call_dummy_address ()
+mips_call_dummy_address (void)
{
struct minimal_symbol *sym;
}
-/* If the current gcc for for this target does not produce correct debugging
+/* If the current gcc for this target does not produce correct debugging
information for float parameters, both prototyped and unprototyped, then
define this macro. This forces gdb to always assume that floats are
passed as doubles and then converted in the callee.
macro - REGISTER_STACK_SIZE(). */
static void
-mips_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
- char *raw_buffer;
- int *optimized;
- CORE_ADDR *addrp;
- struct frame_info *frame;
- int regnum;
- enum lval_type *lval;
+mips_get_saved_register (char *raw_buffer,
+ int *optimized,
+ CORE_ADDR *addrp,
+ struct frame_info *frame,
+ int regnum,
+ enum lval_type *lval)
{
CORE_ADDR addr;
static CORE_ADDR
mips_saved_pc_after_call (struct frame_info *frame)
{
+ return read_signed_register (RA_REGNUM);
+}
+
- return read_register (RA_REGNUM);
+/* Convert a dbx stab register number (from `r' declaration) to a gdb
+ REGNUM */
+
+static int
+mips_stab_reg_to_regnum (int num)
+{
+ if (num < 32)
+ return num;
+ else
+ return num + FP0_REGNUM - 38;
}
+/* Convert a ecoff register number to a gdb REGNUM */
+
+static int
+mips_ecoff_reg_to_regnum (int num)
+{
+ if (num < 32)
+ return num;
+ else
+ return num + FP0_REGNUM - 32;
+}
-static gdbarch_init_ftype mips_gdbarch_init;
static struct gdbarch *
-mips_gdbarch_init (info, arches)
- struct gdbarch_info info;
- struct gdbarch_list *arches;
+mips_gdbarch_init (struct gdbarch_info info,
+ struct gdbarch_list *arches)
{
static LONGEST mips_call_dummy_words[] =
{0};
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
int elf_flags;
-#if 0
- int ef_mips_bitptrs;
-#endif
-#if 0
- int ef_mips_arch;
-#endif
enum mips_abi mips_abi;
+ /* Reset the disassembly info, in case it was set to something
+ non-default. */
+ tm_print_insn_info.flavour = bfd_target_unknown_flavour;
+ tm_print_insn_info.arch = bfd_arch_unknown;
+ tm_print_insn_info.mach = 0;
+
/* Extract the elf_flags if available */
if (info.abfd != NULL
&& bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
mips_abi = MIPS_ABI_EABI64;
break;
default:
- mips_abi = MIPS_ABI_UNKNOWN;
+ if ((elf_flags & EF_MIPS_ABI2))
+ mips_abi = MIPS_ABI_N32;
+ else
+ mips_abi = MIPS_ABI_UNKNOWN;
break;
}
+
/* Try the architecture for any hint of the corect ABI */
if (mips_abi == MIPS_ABI_UNKNOWN
&& info.bfd_arch_info != NULL
case bfd_mach_mips5000:
mips_abi = MIPS_ABI_EABI64;
break;
+ case bfd_mach_mips8000:
+ case bfd_mach_mips10000:
+ mips_abi = MIPS_ABI_N32;
+ break;
}
}
#ifdef MIPS_DEFAULT_ABI
fprintf_unfiltered (gdb_stdlog,
"mips_gdbarch_init: elf_flags = 0x%08x\n",
elf_flags);
-#if 0
- fprintf_unfiltered (gdb_stdlog,
- "mips_gdbarch_init: ef_mips_arch = %d\n",
- ef_mips_arch);
-#endif
-#if 0
- fprintf_unfiltered (gdb_stdlog,
- "mips_gdbarch_init: ef_mips_bitptrs = %d\n",
- ef_mips_bitptrs);
-#endif
fprintf_unfiltered (gdb_stdlog,
"mips_gdbarch_init: mips_abi = %d\n",
mips_abi);
{
/* MIPS needs to be pedantic about which ABI the object is
using. */
- if (gdbarch_tdep (current_gdbarch)->elf_flags != elf_flags)
+ if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags)
continue;
- if (gdbarch_tdep (current_gdbarch)->mips_abi != mips_abi)
+ if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
continue;
return arches->gdbarch;
}
set_gdbarch_double_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 64);
tdep->mips_abi = mips_abi;
+
switch (mips_abi)
{
case MIPS_ABI_O32:
+ tdep->mips_abi_string = "o32";
tdep->mips_default_saved_regsize = 4;
tdep->mips_default_stack_argsize = 4;
tdep->mips_fp_register_double = 0;
- tdep->mips_last_arg_regnum = ZERO_REGNUM + 7;
- tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 15;
+ tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
+ tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
tdep->mips_regs_have_home_p = 1;
tdep->gdb_target_is_mips64 = 0;
+ tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
set_gdbarch_ptr_bit (gdbarch, 32);
set_gdbarch_long_long_bit (gdbarch, 64);
break;
case MIPS_ABI_O64:
+ tdep->mips_abi_string = "o64";
tdep->mips_default_saved_regsize = 8;
tdep->mips_default_stack_argsize = 8;
tdep->mips_fp_register_double = 1;
- tdep->mips_last_arg_regnum = ZERO_REGNUM + 7;
- tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 15;
+ tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
+ tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
tdep->mips_regs_have_home_p = 1;
tdep->gdb_target_is_mips64 = 1;
+ tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
set_gdbarch_ptr_bit (gdbarch, 32);
set_gdbarch_long_long_bit (gdbarch, 64);
break;
case MIPS_ABI_EABI32:
+ tdep->mips_abi_string = "eabi32";
tdep->mips_default_saved_regsize = 4;
tdep->mips_default_stack_argsize = 4;
tdep->mips_fp_register_double = 0;
- tdep->mips_last_arg_regnum = ZERO_REGNUM + 11;
- tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 19;
+ tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+ tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
tdep->mips_regs_have_home_p = 0;
tdep->gdb_target_is_mips64 = 0;
+ tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
set_gdbarch_ptr_bit (gdbarch, 32);
set_gdbarch_long_long_bit (gdbarch, 64);
break;
case MIPS_ABI_EABI64:
+ tdep->mips_abi_string = "eabi64";
tdep->mips_default_saved_regsize = 8;
tdep->mips_default_stack_argsize = 8;
tdep->mips_fp_register_double = 1;
- tdep->mips_last_arg_regnum = ZERO_REGNUM + 11;
- tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 19;
+ tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+ tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
tdep->mips_regs_have_home_p = 0;
tdep->gdb_target_is_mips64 = 1;
+ tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 64);
set_gdbarch_ptr_bit (gdbarch, 64);
set_gdbarch_long_long_bit (gdbarch, 64);
break;
case MIPS_ABI_N32:
+ tdep->mips_abi_string = "n32";
tdep->mips_default_saved_regsize = 4;
tdep->mips_default_stack_argsize = 8;
tdep->mips_fp_register_double = 1;
- tdep->mips_last_arg_regnum = ZERO_REGNUM + 11;
- tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 19;
+ tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+ tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
tdep->mips_regs_have_home_p = 0;
tdep->gdb_target_is_mips64 = 0;
+ tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
set_gdbarch_ptr_bit (gdbarch, 32);
set_gdbarch_long_long_bit (gdbarch, 64);
+
+ /* Set up the disassembler info, so that we get the right
+ register names from libopcodes. */
+ tm_print_insn_info.flavour = bfd_target_elf_flavour;
+ tm_print_insn_info.arch = bfd_arch_mips;
+ if (info.bfd_arch_info != NULL
+ && info.bfd_arch_info->arch == bfd_arch_mips
+ && info.bfd_arch_info->mach)
+ tm_print_insn_info.mach = info.bfd_arch_info->mach;
+ else
+ tm_print_insn_info.mach = bfd_mach_mips8000;
break;
default:
+ tdep->mips_abi_string = "default";
tdep->mips_default_saved_regsize = MIPS_REGSIZE;
tdep->mips_default_stack_argsize = MIPS_REGSIZE;
tdep->mips_fp_register_double = (REGISTER_VIRTUAL_SIZE (FP0_REGNUM) == 8);
- tdep->mips_last_arg_regnum = ZERO_REGNUM + 11;
- tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 19;
+ tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+ tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
tdep->mips_regs_have_home_p = 1;
tdep->gdb_target_is_mips64 = 0;
+ tdep->default_mask_address_p = 0;
set_gdbarch_long_bit (gdbarch, 32);
set_gdbarch_ptr_bit (gdbarch, 32);
set_gdbarch_long_long_bit (gdbarch, 64);
the current gcc - it would make GDB treat these 64-bit programs
as 32-bit programs by default. */
-#if 0
- /* determine the ISA */
- switch (elf_flags & EF_MIPS_ARCH)
- {
- case E_MIPS_ARCH_1:
- ef_mips_arch = 1;
- break;
- case E_MIPS_ARCH_2:
- ef_mips_arch = 2;
- break;
- case E_MIPS_ARCH_3:
- ef_mips_arch = 3;
- break;
- case E_MIPS_ARCH_4:
- ef_mips_arch = 0;
- break;
- default:
- break;
- }
-#endif
-
-#if 0
- /* determine the size of a pointer */
- if ((elf_flags & EF_MIPS_32BITPTRS))
- {
- ef_mips_bitptrs = 32;
- }
- else if ((elf_flags & EF_MIPS_64BITPTRS))
- {
- ef_mips_bitptrs = 64;
- }
- else
- {
- ef_mips_bitptrs = 0;
- }
-#endif
-
/* enable/disable the MIPS FPU */
if (!mips_fpu_type_auto)
tdep->mips_fpu_type = mips_fpu_type;
#undef/#define REGISTER_NAMES and the new REGISTER_NAME(nr).
Further work on it is required. */
set_gdbarch_register_name (gdbarch, mips_register_name);
- set_gdbarch_read_pc (gdbarch, generic_target_read_pc);
+ set_gdbarch_read_pc (gdbarch, mips_read_pc);
set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
set_gdbarch_read_fp (gdbarch, generic_target_read_fp);
set_gdbarch_write_fp (gdbarch, generic_target_write_fp);
set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
+ /* Add/remove bits from an address. The MIPS needs be careful to
+ ensure that all 32 bit addresses are sign extended to 64 bits. */
+ set_gdbarch_addr_bits_remove (gdbarch, mips_addr_bits_remove);
+
+ /* There's a mess in stack frame creation. See comments in
+ blockframe.c near reference to INIT_FRAME_PC_FIRST. */
+ set_gdbarch_init_frame_pc_first (gdbarch, mips_init_frame_pc_first);
+ set_gdbarch_init_frame_pc (gdbarch, init_frame_pc_noop);
+
+ /* Map debug register numbers onto internal register numbers. */
+ set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
+ set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_ecoff_reg_to_regnum);
+
/* Initialize a frame */
set_gdbarch_init_extra_frame_info (gdbarch, mips_init_extra_frame_info);
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep != NULL)
{
+ int ef_mips_arch;
+ int ef_mips_32bitmode;
+ /* determine the ISA */
+ switch (tdep->elf_flags & EF_MIPS_ARCH)
+ {
+ case E_MIPS_ARCH_1:
+ ef_mips_arch = 1;
+ break;
+ case E_MIPS_ARCH_2:
+ ef_mips_arch = 2;
+ break;
+ case E_MIPS_ARCH_3:
+ ef_mips_arch = 3;
+ break;
+ case E_MIPS_ARCH_4:
+ ef_mips_arch = 4;
+ break;
+ default:
+ ef_mips_arch = 0;
+ break;
+ }
+ /* determine the size of a pointer */
+ ef_mips_32bitmode = (tdep->elf_flags & EF_MIPS_32BITMODE);
fprintf_unfiltered (file,
"mips_dump_tdep: tdep->elf_flags = 0x%x\n",
tdep->elf_flags);
fprintf_unfiltered (file,
- "mips_dump_tdep: tdep->mips_abi = %d\n",
- tdep->mips_abi);
+ "mips_dump_tdep: ef_mips_32bitmode = %d\n",
+ ef_mips_32bitmode);
+ fprintf_unfiltered (file,
+ "mips_dump_tdep: ef_mips_arch = %d\n",
+ ef_mips_arch);
+ fprintf_unfiltered (file,
+ "mips_dump_tdep: tdep->mips_abi = %d (%s)\n",
+ tdep->mips_abi,
+ tdep->mips_abi_string);
+ fprintf_unfiltered (file,
+ "mips_dump_tdep: mips_mask_address_p() %d (default %d)\n",
+ mips_mask_address_p (),
+ tdep->default_mask_address_p);
}
fprintf_unfiltered (file,
"mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
"mips_dump_tdep: MIPS_EABI = %d\n",
MIPS_EABI);
fprintf_unfiltered (file,
- "mips_dump_tdep: MIPS_LAST_FP_ARG_REGNUM = %d\n",
- MIPS_LAST_FP_ARG_REGNUM);
+ "mips_dump_tdep: MIPS_LAST_FP_ARG_REGNUM = %d (%d regs)\n",
+ MIPS_LAST_FP_ARG_REGNUM,
+ MIPS_LAST_FP_ARG_REGNUM - FPA0_REGNUM + 1);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_FPU_TYPE = %d (%s)\n",
MIPS_FPU_TYPE,
fprintf_unfiltered (file,
"mips_dump_tdep: IGNORE_HELPER_CALL # %s\n",
XSTRING (IGNORE_HELPER_CALL (PC)));
- fprintf_unfiltered (file,
- "mips_dump_tdep: INIT_FRAME_PC # %s\n",
- XSTRING (INIT_FRAME_PC (FROMLEAF, PREV)));
- fprintf_unfiltered (file,
- "mips_dump_tdep: INIT_FRAME_PC_FIRST # %s\n",
- XSTRING (INIT_FRAME_PC_FIRST (FROMLEAF, PREV)));
fprintf_unfiltered (file,
"mips_dump_tdep: IN_SIGTRAMP # %s\n",
XSTRING (IN_SIGTRAMP (PC, NAME)));
"mips_dump_tdep: MIPS_INSTLEN = %d\n",
MIPS_INSTLEN);
fprintf_unfiltered (file,
- "mips_dump_tdep: MIPS_LAST_ARG_REGNUM = %d\n",
- MIPS_LAST_ARG_REGNUM);
+ "mips_dump_tdep: MIPS_LAST_ARG_REGNUM = %d (%d regs)\n",
+ MIPS_LAST_ARG_REGNUM,
+ MIPS_LAST_ARG_REGNUM - A0_REGNUM + 1);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_NUMREGS = %d\n",
MIPS_NUMREGS);
"mips_dump_tdep: SOFTWARE_SINGLE_STEP # %s\n",
XSTRING (SOFTWARE_SINGLE_STEP (SIG, BP_P)));
fprintf_unfiltered (file,
- "mips_dump_tdep: SOFTWARE_SINGLE_STEP_P = %d\n",
- SOFTWARE_SINGLE_STEP_P);
- fprintf_unfiltered (file,
- "mips_dump_tdep: SOFTWARE_SINGLE_STEP_P = %d\n",
- SOFTWARE_SINGLE_STEP_P);
+ "mips_dump_tdep: SOFTWARE_SINGLE_STEP_P () = %d\n",
+ SOFTWARE_SINGLE_STEP_P ());
fprintf_unfiltered (file,
"mips_dump_tdep: STAB_REG_TO_REGNUM # %s\n",
XSTRING (STAB_REG_TO_REGNUM (REGNUM)));
}
void
-_initialize_mips_tdep ()
+_initialize_mips_tdep (void)
{
static struct cmd_list_element *mipsfpulist = NULL;
struct cmd_list_element *c;
"Select single-precision MIPS floating-point coprocessor.",
&mipsfpulist);
add_cmd ("double", class_support, set_mipsfpu_double_command,
- "Select double-precision MIPS floating-point coprocessor .",
+ "Select double-precision MIPS floating-point coprocessor.",
&mipsfpulist);
add_alias_cmd ("on", "double", class_support, 1, &mipsfpulist);
add_alias_cmd ("yes", "double", class_support, 1, &mipsfpulist);
c = add_show_from_set (c, &showlist);
c->function.cfunc = mips_show_processor_type_command;
- tmp_mips_processor_type = strsave (DEFAULT_MIPS_TYPE);
- mips_set_processor_type_command (strsave (DEFAULT_MIPS_TYPE), 0);
+ tmp_mips_processor_type = xstrdup (DEFAULT_MIPS_TYPE);
+ mips_set_processor_type_command (xstrdup (DEFAULT_MIPS_TYPE), 0);
#endif
/* We really would like to have both "0" and "unlimited" work, but
/* Allow the user to control whether the upper bits of 64-bit
addresses should be zeroed. */
- add_show_from_set
- (add_set_cmd ("mask-address", no_class, var_boolean, (char *) &mask_address_p,
- "Set zeroing of upper 32 bits of 64-bit addresses.\n\
-Use \"on\" to enable the masking, and \"off\" to disable it.\n\
-Without an argument, zeroing of upper address bits is enabled.", &setlist),
- &showlist);
+ c = add_set_auto_boolean_cmd ("mask-address", no_class, &mask_address_var,
+ "Set zeroing of upper 32 bits of 64-bit addresses.\n\
+Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to allow GDB to determine\n\
+the correct value.\n",
+ &setmipscmdlist);
+ add_cmd ("mask-address", no_class, show_mask_address,
+ "Show current mask-address value", &showmipscmdlist);
/* Allow the user to control the size of 32 bit registers within the
raw remote packet. */