#include "defs.h"
#include "gdb_string.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "gdbcmd.h"
#include "language.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbtypes.h"
#include "target.h"
#include "arch-utils.h"
#include "regcache.h"
#include "opcode/mips.h"
#include "elf/mips.h"
#include "elf-bfd.h"
#include "symcat.h"
enum
{
MIPS_FPU_SINGLE_REGSIZE = 4,
MIPS_FPU_DOUBLE_REGSIZE = 8
};
enum mips_abi
{
MIPS_ABI_UNKNOWN,
MIPS_ABI_N32,
MIPS_ABI_O32,
MIPS_ABI_O64,
MIPS_ABI_EABI32,
MIPS_ABI_EABI64
};
struct frame_extra_info
{
mips_extra_func_info_t proc_desc;
int num_args;
};
static const char size_auto[] = "auto";
static const char size_32[] = "32";
static const char size_64[] = "64";
static const char *size_enums[] = {
size_auto,
size_32,
size_64,
0
};
enum mips_fpu_type
{
MIPS_FPU_DOUBLE,
MIPS_FPU_SINGLE,
MIPS_FPU_NONE
};
#ifndef MIPS_DEFAULT_FPU_TYPE
#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_DOUBLE
#endif
static int mips_fpu_type_auto = 1;
static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE;
#define MIPS_FPU_TYPE mips_fpu_type
#ifndef FP_REGISTER_DOUBLE
#define FP_REGISTER_DOUBLE (REGISTER_VIRTUAL_SIZE(FP0_REGNUM) == 8)
#endif
static int mips_debug = 0;
struct gdbarch_tdep
{
int elf_flags;
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_default_saved_regsize;
int mips_fp_register_double;
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
#undef MIPS_EABI
#define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
|| gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
#endif
#if GDB_MULTI_ARCH
#undef MIPS_LAST_FP_ARG_REGNUM
#define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum)
#endif
#if GDB_MULTI_ARCH
#undef MIPS_LAST_ARG_REGNUM
#define MIPS_LAST_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_arg_regnum)
#endif
#if GDB_MULTI_ARCH
#undef MIPS_FPU_TYPE
#define MIPS_FPU_TYPE (gdbarch_tdep (current_gdbarch)->mips_fpu_type)
#endif
#if GDB_MULTI_ARCH
#undef MIPS_DEFAULT_SAVED_REGSIZE
#define MIPS_DEFAULT_SAVED_REGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_saved_regsize)
#elif !defined (MIPS_DEFAULT_SAVED_REGSIZE)
#define MIPS_DEFAULT_SAVED_REGSIZE MIPS_REGSIZE
#endif
static const char *mips_saved_regsize_string = size_auto;
#define MIPS_SAVED_REGSIZE (mips_saved_regsize())
static unsigned int
mips_saved_regsize (void)
{
if (mips_saved_regsize_string == size_auto)
return MIPS_DEFAULT_SAVED_REGSIZE;
else if (mips_saved_regsize_string == size_64)
return 8;
else
return 4;
}
#if GDB_MULTI_ARCH
#undef FP_REGISTER_DOUBLE
#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
#endif
#if GDB_MULTI_ARCH
#undef MIPS_REGS_HAVE_HOME_P
#define MIPS_REGS_HAVE_HOME_P (gdbarch_tdep (current_gdbarch)->mips_regs_have_home_p)
#elif !defined (MIPS_REGS_HAVE_HOME_P)
#define MIPS_REGS_HAVE_HOME_P (!MIPS_EABI)
#endif
#if GDB_MULTI_ARCH
#undef MIPS_DEFAULT_STACK_ARGSIZE
#define MIPS_DEFAULT_STACK_ARGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_stack_argsize)
#elif !defined (MIPS_DEFAULT_STACK_ARGSIZE)
#define MIPS_DEFAULT_STACK_ARGSIZE (MIPS_DEFAULT_SAVED_REGSIZE)
#endif
#define MIPS_STACK_ARGSIZE (mips_stack_argsize ())
static const char *mips_stack_argsize_string = size_auto;
static unsigned int
mips_stack_argsize (void)
{
if (mips_stack_argsize_string == size_auto)
return MIPS_DEFAULT_STACK_ARGSIZE;
else if (mips_stack_argsize_string == size_64)
return 8;
else
return 4;
}
#if GDB_MULTI_ARCH
#undef GDB_TARGET_IS_MIPS64
#define GDB_TARGET_IS_MIPS64 (gdbarch_tdep (current_gdbarch)->gdb_target_is_mips64 + 0)
#endif
#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);
static mips_extra_func_info_t
heuristic_proc_desc (CORE_ADDR, CORE_ADDR, struct frame_info *, int);
static CORE_ADDR heuristic_proc_start (CORE_ADDR);
static CORE_ADDR read_next_frame_reg (struct frame_info *, int);
int mips_set_processor_type (char *);
static void mips_show_processor_type_command (char *, int);
static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
static mips_extra_func_info_t
find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame);
static CORE_ADDR after_prologue (CORE_ADDR pc,
mips_extra_func_info_t proc_desc);
char *mips_processor_type;
char *tmp_mips_processor_type;
static struct cmd_list_element *setmipscmdlist = NULL;
static struct cmd_list_element *showmipscmdlist = NULL;
char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES;
char **mips_processor_reg_names = mips_generic_reg_names;
char *
mips_register_name (int i)
{
return mips_processor_reg_names[i];
}
char *mips_r3041_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"sr", "lo", "hi", "bad", "cause","pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"fsr", "fir", "fp", "",
"", "", "bus", "ccfg", "", "", "", "",
"", "", "port", "cmp", "", "", "epc", "prid",
};
char *mips_r3051_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"sr", "lo", "hi", "bad", "cause","pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"fsr", "fir", "fp", "",
"inx", "rand", "elo", "", "ctxt", "", "", "",
"", "", "ehi", "", "", "", "epc", "prid",
};
char *mips_r3081_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"sr", "lo", "hi", "bad", "cause","pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
"fsr", "fir", "fp", "",
"inx", "rand", "elo", "cfg", "ctxt", "", "", "",
"", "", "ehi", "", "", "", "epc", "prid",
};
char *mips_lsi33k_reg_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"epc", "hi", "lo", "sr", "cause","badvaddr",
"dcic", "bpc", "bda", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
};
struct {
char *name;
char **regnames;
} mips_processor_type_table[] = {
{ "generic", mips_generic_reg_names },
{ "r3041", mips_r3041_reg_names },
{ "r3051", mips_r3051_reg_names },
{ "r3071", mips_r3081_reg_names },
{ "r3081", mips_r3081_reg_names },
{ "lsi33k", mips_lsi33k_reg_names },
{ NULL, NULL }
};
static int mips16_to_32_reg[8] =
{16, 17, 2, 3, 4, 5, 6, 7};
static unsigned int heuristic_fence_post = 0;
#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)
#define PROC_HIGH_ADDR(proc) ((proc)->high_addr)
#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
#define PROC_FRAME_ADJUST(proc) ((proc)->frame_adjust)
#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
#define _PROC_MAGIC_ 0x0F0F0F0F
#define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym = _PROC_MAGIC_)
struct linked_proc_info
{
struct mips_extra_func_info info;
struct linked_proc_info *next;
}
*linked_proc_desc_table = NULL;
void
mips_print_extra_frame_info (struct frame_info *fi)
{
if (fi
&& fi->extra_info
&& fi->extra_info->proc_desc
&& fi->extra_info->proc_desc->pdr.framereg < NUM_REGS)
printf_filtered (" frame pointer is at %s+%s\n",
REGISTER_NAME (fi->extra_info->proc_desc->pdr.framereg),
paddr_d (fi->extra_info->proc_desc->pdr.frameoffset));
}
static int mips64_transfers_32bit_regs_p = 0;
int
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)
return 8;
else
return MIPS_REGSIZE;
}
int
mips_register_convertible (int reg_nr)
{
if (mips64_transfers_32bit_regs_p)
return 0;
else
return (REGISTER_RAW_SIZE (reg_nr) > REGISTER_VIRTUAL_SIZE (reg_nr));
}
void
mips_register_convert_to_virtual (int n, struct type *virtual_type,
char *raw_buf, char *virt_buf)
{
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
memcpy (virt_buf,
raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
TYPE_LENGTH (virtual_type));
else
memcpy (virt_buf,
raw_buf,
TYPE_LENGTH (virtual_type));
}
void
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 == BFD_ENDIAN_BIG)
memcpy (raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
virt_buf,
TYPE_LENGTH (virtual_type));
else
memcpy (raw_buf,
virt_buf,
TYPE_LENGTH (virtual_type));
}
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;
}
}
int
mips_use_struct_convention (int gcc_p, struct type *type)
{
if (MIPS_EABI)
return (TYPE_LENGTH (type) > 2 * MIPS_SAVED_REGSIZE);
else
return 1;
}
static int
pc_is_mips16 (bfd_vma memaddr)
{
struct minimal_symbol *sym;
if (IS_MIPS16_ADDR (memaddr))
return 1;
sym = lookup_minimal_symbol_by_pc (memaddr);
if (sym)
return MSYMBOL_IS_SPECIAL (sym);
else
return 0;
}
static CORE_ADDR
mips_read_pc (ptid_t ptid)
{
return read_signed_register_pid (PC_REGNUM, ptid);
}
static CORE_ADDR
after_prologue (CORE_ADDR pc,
mips_extra_func_info_t proc_desc)
{
struct symtab_and_line sal;
CORE_ADDR func_addr, func_end;
if (!proc_desc)
proc_desc = find_proc_desc (pc, NULL, 0);
if (proc_desc)
{
if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
&& PROC_FRAME_OFFSET (proc_desc) == 0)
return 0;
}
if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
return 0;
sal = find_pc_line (func_addr, 0);
if (sal.end < func_end)
return sal.end;
return 0;
}
static void
mips32_decode_reg_save (t_inst inst, unsigned long *gen_mask,
unsigned long *float_mask)
{
int reg;
if ((inst & 0xffe00000) == 0xafa00000
|| (inst & 0xffe00000) == 0xafc00000
|| (inst & 0xffe00000) == 0xffa00000)
{
reg = (inst & 0x001f0000) >> 16;
*gen_mask |= (1 << reg);
}
else if ((inst & 0xffe00000) == 0xe7a00000
|| (inst & 0xffe00000) == 0xe7c00000
|| (inst & 0xffe00000) == 0xf7a00000)
{
reg = ((inst & 0x001f0000) >> 16);
*float_mask |= (1 << reg);
}
}
static void
mips16_decode_reg_save (t_inst inst, unsigned long *gen_mask)
{
if ((inst & 0xf800) == 0xd000)
{
int reg = mips16_to_32_reg[(inst & 0x700) >> 8];
*gen_mask |= (1 << reg);
}
else if ((inst & 0xff00) == 0xf900)
{
int reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
*gen_mask |= (1 << reg);
}
else if ((inst & 0xff00) == 0x6200
|| (inst & 0xff00) == 0xfa00)
*gen_mask |= (1 << RA_REGNUM);
}
static t_inst
mips_fetch_instruction (CORE_ADDR addr)
{
char buf[MIPS_INSTLEN];
int instlen;
int status;
if (pc_is_mips16 (addr))
{
instlen = MIPS16_INSTLEN;
addr = UNMAKE_MIPS16_ADDR (addr);
}
else
instlen = MIPS_INSTLEN;
status = read_memory_nobpt (addr, buf, instlen);
if (status)
memory_error (status, addr);
return extract_unsigned_integer (buf, instlen);
}
#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 jtype_op(x) (x >> 26)
#define jtype_target(x) (x & 0x03ffffff)
#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)
{
long x;
x = itype_immediate (inst);
if (x & 0x8000)
{
x |= 0xffff0000;
}
x = x << 2;
return x;
}
CORE_ADDR
mips32_next_pc (CORE_ADDR pc)
{
unsigned long inst;
int op;
inst = mips_fetch_instruction (pc);
if ((inst & 0xe0000000) != 0)
{
if (itype_op (inst) >> 2 == 5)
{
op = (itype_op (inst) & 0x03);
switch (op)
{
case 0:
goto equal_branch;
case 1:
goto neq_branch;
case 2:
goto less_branch;
case 3:
goto greater_branch;
default:
pc += 4;
}
}
else if (itype_op (inst) == 17 && itype_rs (inst) == 8)
{
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;
}
else
{
switch (op = itype_op (inst) & 0x07)
{
case 0:
op = rtype_funct (inst);
switch (op)
{
case 8:
case 9:
pc = read_signed_register (rtype_rs (inst));
break;
default:
pc += 4;
}
break;
case 1:
{
op = itype_rt (inst);
switch (op)
{
case 0:
case 2:
case 16:
case 18:
less_branch:
if (read_signed_register (itype_rs (inst)) < 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 1:
case 3:
case 17:
case 19:
greater_equal_branch:
if (read_signed_register (itype_rs (inst)) >= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
default:
pc += 4;
}
}
break;
case 2:
case 3:
{
unsigned long reg;
reg = jtype_target (inst) << 2;
pc = reg + ((pc + 4) & 0xf0000000);
}
break;
{
unsigned long reg;
reg = jtype_target (inst) << 2;
pc = reg + ((pc + 4) & 0xf0000000) + 1;
}
break;
case 4:
equal_branch:
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:
neq_branch:
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:
less_zero_branch:
if (read_signed_register (itype_rs (inst) <= 0))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 7:
default:
greater_branch:
if (read_signed_register (itype_rs (inst) > 0))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
}
}
return pc;
}
enum mips16_inst_fmts
{
itype,
ritype,
rrtype,
rritype,
rrrtype,
rriatype,
shifttype,
i8type,
i8movtype,
i8mov32rtype,
i64type,
ri64type,
jalxtype,
exiItype,
extRitype,
extRRItype,
extRRIAtype,
EXTshifttype,
extI8type,
extI64type,
extRi64type,
extshift64type
};
struct upk_mips16
{
CORE_ADDR offset;
unsigned int regx;
unsigned int regy;
};
static CORE_ADDR
extended_offset (unsigned int extension)
{
CORE_ADDR value;
value = (extension >> 21) & 0x3f;
value = value << 6;
value |= (extension >> 16) & 0x1f;
value = value << 5;
value |= extension & 0x01f;
return value;
}
static unsigned int
fetch_mips_16 (CORE_ADDR pc)
{
char buf[8];
pc &= 0xfffffffe;
target_read_memory (pc, buf, 2);
return extract_unsigned_integer (buf, 2);
}
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 offset;
int regx;
int regy;
switch (insn_format)
{
case itype:
{
CORE_ADDR value;
if (extension)
{
value = extended_offset (extension);
value = value << 11;
value |= inst & 0x7ff;
}
else
{
value = inst & 0x7ff;
}
offset = value;
regx = -1;
regy = -1;
}
break;
case ritype:
case i8type:
{
CORE_ADDR value;
if (extension)
{
value = extended_offset (extension);
value = value << 8;
value |= inst & 0xff;
regx = (extension >> 8) & 0x07;
if (value & 0x4000)
{
value &= ~0x3fff;
value = -value;
}
}
else
{
value = inst & 0xff;
regx = (inst >> 8) & 0x07;
if (value & 0x80)
{
value &= 0xef;
value = -value;
}
}
offset = value;
regy = -1;
break;
}
case jalxtype:
{
unsigned long value;
unsigned int nexthalf;
value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f);
value = value << 16;
nexthalf = mips_fetch_instruction (pc + 2);
value |= nexthalf;
offset = value;
regx = -1;
regy = -1;
break;
}
default:
internal_error (__FILE__, __LINE__,
"bad switch");
}
upk->offset = offset;
upk->regx = regx;
upk->regy = regy;
}
static CORE_ADDR
add_offset_16 (CORE_ADDR pc, int offset)
{
return ((offset << 2) | ((pc + 2) & (0xf0000000)));
}
static CORE_ADDR
extended_mips16_next_pc (CORE_ADDR pc,
unsigned int extension,
unsigned int insn)
{
int op = (insn >> 11);
switch (op)
{
case 2:
{
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:
{
struct upk_mips16 upk;
unpack_mips16 (pc, extension, insn, jalxtype, &upk);
pc = add_offset_16 (pc, upk.offset);
if ((insn >> 10) & 0x01)
pc = pc & ~0x01;
else
pc |= 0x01;
break;
}
case 4:
{
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:
{
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:
{
struct upk_mips16 upk;
int reg;
unpack_mips16 (pc, extension, insn, i8type, &upk);
reg = read_signed_register (24);
if (((upk.regx == 0) && (reg == 0))
|| ((upk.regx == 1) && (reg != 0)))
pc += (upk.offset << 1) + 2;
else
pc += 2;
break;
}
case 29:
{
struct upk_mips16 upk;
op = insn & 0x1f;
if (op == 0)
{
int reg;
upk.regx = (insn >> 8) & 0x07;
upk.regy = (insn >> 5) & 0x07;
switch (upk.regy)
{
case 0:
reg = upk.regx;
break;
case 1:
reg = 31;
break;
case 2:
reg = upk.regx;
break;
default:
reg = 31;
break;
}
pc = read_signed_register (reg);
}
else
pc += 2;
break;
}
case 30:
{
pc += 2;
pc = extended_mips16_next_pc (pc, insn, fetch_mips_16 (pc));
break;
}
default:
{
pc += 2;
break;
}
}
return pc;
}
CORE_ADDR
mips16_next_pc (CORE_ADDR pc)
{
unsigned int insn = fetch_mips_16 (pc);
return extended_mips16_next_pc (pc, 0, insn);
}
CORE_ADDR
mips_next_pc (CORE_ADDR pc)
{
if (pc & 0x01)
return mips16_next_pc (pc);
else
return mips32_next_pc (pc);
}
void
mips_find_saved_regs (struct frame_info *fci)
{
int ireg;
CORE_ADDR reg_position;
int kernel_trap;
unsigned long gen_mask, float_mask;
mips_extra_func_info_t proc_desc;
t_inst inst;
frame_saved_regs_zalloc (fci);
#ifndef SIGFRAME_BASE
#define SIGFRAME_BASE MIPS_REGSIZE
#define SIGFRAME_PC_OFF (SIGFRAME_BASE + 2 * MIPS_REGSIZE)
#define SIGFRAME_REGSAVE_OFF (SIGFRAME_BASE + 3 * MIPS_REGSIZE)
#define SIGFRAME_FPREGSAVE_OFF \
(SIGFRAME_REGSAVE_OFF + MIPS_NUMREGS * MIPS_REGSIZE + 3 * MIPS_REGSIZE)
#endif
#ifndef SIGFRAME_REG_SIZE
#define SIGFRAME_REG_SIZE MIPS_REGSIZE
#endif
if (fci->signal_handler_caller)
{
for (ireg = 0; ireg < MIPS_NUMREGS; ireg++)
{
reg_position = fci->frame + SIGFRAME_REGSAVE_OFF
+ ireg * SIGFRAME_REG_SIZE;
fci->saved_regs[ireg] = reg_position;
}
for (ireg = 0; ireg < MIPS_NUMREGS; ireg++)
{
reg_position = fci->frame + SIGFRAME_FPREGSAVE_OFF
+ ireg * SIGFRAME_REG_SIZE;
fci->saved_regs[FP0_REGNUM + ireg] = reg_position;
}
fci->saved_regs[PC_REGNUM] = fci->frame + SIGFRAME_PC_OFF;
return;
}
proc_desc = fci->extra_info->proc_desc;
if (proc_desc == NULL)
return;
kernel_trap = PROC_REG_MASK (proc_desc) & 1;
gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK (proc_desc);
float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK (proc_desc);
if (
(fci->next == NULL || fci->next->signal_handler_caller)
&& !PROC_DESC_IS_DUMMY (proc_desc)
&& in_prologue (fci->pc, PROC_LOW_ADDR (proc_desc))
&& !kernel_trap)
{
CORE_ADDR addr;
unsigned long gen_save_found = 0;
unsigned long float_save_found = 0;
int instlen;
addr = PROC_LOW_ADDR (proc_desc);
instlen = pc_is_mips16 (addr) ? MIPS16_INSTLEN : MIPS_INSTLEN;
while (addr < fci->pc)
{
inst = mips_fetch_instruction (addr);
if (pc_is_mips16 (addr))
mips16_decode_reg_save (inst, &gen_save_found);
else
mips32_decode_reg_save (inst, &gen_save_found, &float_save_found);
addr += instlen;
}
gen_mask = gen_save_found;
float_mask = float_save_found;
}
reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
for (ireg = MIPS_NUMREGS - 1; gen_mask; --ireg, gen_mask <<= 1)
if (gen_mask & 0x80000000)
{
fci->saved_regs[ireg] = reg_position;
reg_position -= MIPS_SAVED_REGSIZE;
}
if (pc_is_mips16 (PROC_LOW_ADDR (proc_desc)))
{
inst = mips_fetch_instruction (PROC_LOW_ADDR (proc_desc));
if ((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)
{
int reg;
int sreg_count = (inst >> 6) & 3;
reg_position = fci->frame + PROC_REG_OFFSET (proc_desc);
if (inst & 0x20)
reg_position -= MIPS_SAVED_REGSIZE;
for (reg = 16; reg < sreg_count + 16; reg++)
{
fci->saved_regs[reg] = reg_position;
reg_position -= MIPS_SAVED_REGSIZE;
}
}
}
reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc);
if (!GDB_TARGET_IS_MIPS64)
reg_position += MIPS_SAVED_REGSIZE;
for (ireg = MIPS_NUMREGS - 1; float_mask; --ireg, float_mask <<= 1)
if (float_mask & 0x80000000)
{
fci->saved_regs[FP0_REGNUM + ireg] = reg_position;
reg_position -= MIPS_SAVED_REGSIZE;
}
fci->saved_regs[PC_REGNUM] = fci->saved_regs[RA_REGNUM];
}
static CORE_ADDR
read_next_frame_reg (struct frame_info *fi, int regno)
{
for (; fi; fi = fi->next)
{
if (regno == SP_REGNUM && !fi->signal_handler_caller)
return fi->frame;
else
{
if (fi->saved_regs == NULL)
mips_find_saved_regs (fi);
if (fi->saved_regs[regno])
return read_memory_integer (ADDR_BITS_REMOVE (fi->saved_regs[regno]), MIPS_SAVED_REGSIZE);
}
}
return read_signed_register (regno);
}
static CORE_ADDR
mips_addr_bits_remove (CORE_ADDR addr)
{
if (GDB_TARGET_IS_MIPS64)
{
if (mips_mask_address_p () && (addr >> 32 == (CORE_ADDR) 0xffffffff))
{
addr &= (CORE_ADDR) 0xffffffff;
}
}
else if (mips_mask_address_p ())
{
addr &= (CORE_ADDR) 0xffffffff;
}
return addr;
}
void
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;
pc = ((fromleaf) ? SAVED_PC_AFTER_CALL (prev->next) :
prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
tmp = mips_skip_stub (pc);
prev->pc = tmp ? tmp : pc;
}
CORE_ADDR
mips_frame_saved_pc (struct frame_info *frame)
{
CORE_ADDR saved_pc;
mips_extra_func_info_t proc_desc = frame->extra_info->proc_desc;
int pcreg = frame->signal_handler_caller ? PC_REGNUM
: (proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM);
if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
saved_pc = read_memory_integer (frame->frame - MIPS_SAVED_REGSIZE, MIPS_SAVED_REGSIZE);
else
saved_pc = read_next_frame_reg (frame, pcreg);
return ADDR_BITS_REMOVE (saved_pc);
}
static struct mips_extra_func_info temp_proc_desc;
static CORE_ADDR temp_saved_regs[NUM_REGS];
static void
set_reg_offset (int regno, CORE_ADDR offset)
{
if (temp_saved_regs[regno] == 0)
temp_saved_regs[regno] = offset;
}
static int
mips_about_to_return (CORE_ADDR pc)
{
if (pc_is_mips16 (pc))
return mips_fetch_instruction (pc) == 0xe820;
else
return mips_fetch_instruction (pc) == 0x3e00008;
}
static CORE_ADDR
heuristic_proc_start (CORE_ADDR pc)
{
CORE_ADDR start_pc;
CORE_ADDR fence;
int instlen;
int seen_adjsp = 0;
pc = ADDR_BITS_REMOVE (pc);
start_pc = pc;
fence = start_pc - heuristic_fence_post;
if (start_pc == 0)
return 0;
if (heuristic_fence_post == UINT_MAX
|| fence < VM_MIN_ADDRESS)
fence = VM_MIN_ADDRESS;
instlen = pc_is_mips16 (pc) ? MIPS16_INSTLEN : MIPS_INSTLEN;
for (start_pc -= instlen;; start_pc -= instlen)
if (start_pc < fence)
{
if (!stop_soon_quietly)
{
static int blurb_printed = 0;
warning ("Warning: GDB can't find the start of the function at 0x%s.",
paddr_nz (pc));
if (!blurb_printed)
{
printf_filtered ("\n\
GDB is unable to find the start of the function at 0x%s\n\
and thus can't determine the size of that function's stack frame.\n\
This means that GDB may be unable to access that stack frame, or\n\
the frames below it.\n\
This problem is most likely caused by an invalid program counter or\n\
stack pointer.\n\
However, if you think GDB should simply search farther back\n\
from 0x%s for code which looks like the beginning of a\n\
function, you can increase the range of the search using the `set\n\
heuristic-fence-post' command.\n",
paddr_nz (pc), paddr_nz (pc));
blurb_printed = 1;
}
}
return 0;
}
else if (pc_is_mips16 (start_pc))
{
unsigned short inst;
inst = mips_fetch_instruction (start_pc);
if (((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)
|| (inst & 0xff80) == 0x6380
|| (inst & 0xff80) == 0xfb80
|| ((inst & 0xf810) == 0xf010 && seen_adjsp))
break;
else if ((inst & 0xff00) == 0x6300
|| (inst & 0xff00) == 0xfb00)
seen_adjsp = 1;
else
seen_adjsp = 0;
}
else if (mips_about_to_return (start_pc))
{
start_pc += 2 * MIPS_INSTLEN;
break;
}
return start_pc;
}
static int
mips16_get_imm (unsigned short prev_inst,
unsigned short inst,
int nbits,
int scale,
int is_signed)
{
int offset;
if ((prev_inst & 0xf800) == 0xf000)
{
offset = ((prev_inst & 0x1f) << 11) | (prev_inst & 0x7e0);
if (offset & 0x8000)
offset = 0 - (0x10000 - (offset & 0xffff));
return offset | (inst & 0x1f);
}
else
{
int max_imm = 1 << nbits;
int mask = max_imm - 1;
int sign_bit = max_imm >> 1;
offset = inst & mask;
if (is_signed && (offset & sign_bit))
offset = 0 - (max_imm - offset);
return offset * scale;
}
}
static void
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;
unsigned short prev_inst = 0;
unsigned inst = 0;
unsigned entry_inst = 0;
int reg, offset;
PROC_FRAME_OFFSET (&temp_proc_desc) = 0;
PROC_FRAME_ADJUST (&temp_proc_desc) = 0;
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS16_INSTLEN)
{
prev_inst = inst;
inst = (unsigned short) mips_fetch_instruction (cur_pc);
if ((inst & 0xff00) == 0x6300
|| (inst & 0xff00) == 0xfb00)
{
offset = mips16_get_imm (prev_inst, inst, 8, 8, 1);
if (offset < 0)
PROC_FRAME_OFFSET (&temp_proc_desc) -= offset;
else
break;
}
else if ((inst & 0xf800) == 0xd000)
{
offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
reg = mips16_to_32_reg[(inst & 0x700) >> 8];
PROC_REG_MASK (&temp_proc_desc) |= (1 << reg);
set_reg_offset (reg, sp + offset);
}
else if ((inst & 0xff00) == 0xf900)
{
offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
PROC_REG_MASK (&temp_proc_desc) |= (1 << reg);
set_reg_offset (reg, sp + offset);
}
else if ((inst & 0xff00) == 0x6200)
{
offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
set_reg_offset (RA_REGNUM, sp + offset);
}
else if ((inst & 0xff00) == 0xfa00)
{
offset = mips16_get_imm (prev_inst, inst, 8, 8, 0);
PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
set_reg_offset (RA_REGNUM, sp + offset);
}
else if (inst == 0x673d)
{
frame_addr = sp;
PROC_FRAME_REG (&temp_proc_desc) = 17;
}
else if ((inst & 0xff00) == 0x0100)
{
offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
frame_addr = sp + offset;
PROC_FRAME_REG (&temp_proc_desc) = 17;
PROC_FRAME_ADJUST (&temp_proc_desc) = offset;
}
else if ((inst & 0xFF00) == 0xd900)
{
offset = mips16_get_imm (prev_inst, inst, 5, 4, 0);
reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
set_reg_offset (reg, frame_addr + offset);
}
else if ((inst & 0xFF00) == 0x7900)
{
offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
set_reg_offset (reg, frame_addr + offset);
}
else if ((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)
entry_inst = inst;
else if ((inst & 0xf800) == 0x1800)
cur_pc += MIPS16_INSTLEN;
}
if (entry_inst != 0)
{
int areg_count = (entry_inst >> 8) & 7;
int sreg_count = (entry_inst >> 6) & 3;
PROC_FRAME_OFFSET (&temp_proc_desc) += 32;
sp += PROC_FRAME_OFFSET (&temp_proc_desc);
for (reg = 4, offset = 0; reg < areg_count + 4; reg++)
{
PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
set_reg_offset (reg, sp + offset);
offset += MIPS_SAVED_REGSIZE;
}
offset = -4;
if (entry_inst & 0x20)
{
PROC_REG_MASK (&temp_proc_desc) |= 1 << RA_REGNUM;
set_reg_offset (RA_REGNUM, sp + offset);
offset -= MIPS_SAVED_REGSIZE;
}
for (reg = 16; reg < sreg_count + 16; reg++)
{
PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
set_reg_offset (reg, sp + offset);
offset -= MIPS_SAVED_REGSIZE;
}
}
}
static void
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;
restart:
memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
PROC_FRAME_OFFSET (&temp_proc_desc) = 0;
PROC_FRAME_ADJUST (&temp_proc_desc) = 0;
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSTLEN)
{
unsigned long inst, high_word, low_word;
int reg;
inst = (unsigned long) mips_fetch_instruction (cur_pc);
high_word = (inst >> 16) & 0xffff;
low_word = inst & 0xffff;
reg = high_word & 0x1f;
if (high_word == 0x27bd
|| high_word == 0x23bd
|| high_word == 0x67bd)
{
if (low_word & 0x8000)
PROC_FRAME_OFFSET (&temp_proc_desc) += 0x10000 - low_word;
else
break;
}
else if ((high_word & 0xFFE0) == 0xafa0)
{
PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
set_reg_offset (reg, sp + low_word);
}
else if ((high_word & 0xFFE0) == 0xffa0)
{
PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
set_reg_offset (reg, sp + low_word + 8 - MIPS_REGSIZE);
}
else if (high_word == 0x27be)
{
if ((long) low_word != PROC_FRAME_OFFSET (&temp_proc_desc))
frame_addr = sp + low_word;
else if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
{
unsigned alloca_adjust;
PROC_FRAME_REG (&temp_proc_desc) = 30;
frame_addr = read_next_frame_reg (next_frame, 30);
alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
if (alloca_adjust > 0)
{
sp += alloca_adjust;
goto restart;
}
}
}
else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
{
if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
{
unsigned alloca_adjust;
PROC_FRAME_REG (&temp_proc_desc) = 30;
frame_addr = read_next_frame_reg (next_frame, 30);
alloca_adjust = (unsigned) (frame_addr - sp);
if (alloca_adjust > 0)
{
sp += alloca_adjust;
goto restart;
}
}
}
else if ((high_word & 0xFFE0) == 0xafc0)
{
PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
set_reg_offset (reg, frame_addr + low_word);
}
}
}
static mips_extra_func_info_t
heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
struct frame_info *next_frame, int cur_frame)
{
CORE_ADDR sp;
if (cur_frame)
sp = read_next_frame_reg (next_frame, SP_REGNUM);
else
sp = 0;
if (start_pc == 0)
return NULL;
memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc));
memset (&temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
PROC_PC_REG (&temp_proc_desc) = RA_REGNUM;
if (start_pc + 200 < limit_pc)
limit_pc = start_pc + 200;
if (pc_is_mips16 (start_pc))
mips16_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
else
mips32_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
return &temp_proc_desc;
}
static mips_extra_func_info_t
non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
{
CORE_ADDR startaddr;
mips_extra_func_info_t proc_desc;
struct block *b = block_for_pc (pc);
struct symbol *sym;
find_pc_partial_function (pc, NULL, &startaddr, NULL);
if (addrptr)
*addrptr = startaddr;
if (b == NULL || PC_IN_CALL_DUMMY (pc, 0, 0))
sym = NULL;
else
{
if (startaddr > BLOCK_START (b))
sym = NULL;
else
sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL);
}
if (sym)
{
proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
if (PROC_FRAME_REG (proc_desc) == -1)
return NULL;
else
return proc_desc;
}
else
return NULL;
}
static mips_extra_func_info_t
find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame)
{
mips_extra_func_info_t proc_desc;
CORE_ADDR startaddr;
proc_desc = non_heuristic_proc_desc (pc, &startaddr);
if (proc_desc)
{
if (next_frame == NULL)
{
struct symtab_and_line val;
struct symbol *proc_symbol =
PROC_DESC_IS_DUMMY (proc_desc) ? 0 : PROC_SYMBOL (proc_desc);
if (proc_symbol)
{
val = find_pc_line (BLOCK_START
(SYMBOL_BLOCK_VALUE (proc_symbol)),
0);
val.pc = val.end ? val.end : pc;
}
if (!proc_symbol || pc < val.pc)
{
mips_extra_func_info_t found_heuristic =
heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
pc, next_frame, cur_frame);
if (found_heuristic)
proc_desc = found_heuristic;
}
}
}
else
{
register struct linked_proc_info *link;
for (link = linked_proc_desc_table; link; link = link->next)
if (PROC_LOW_ADDR (&link->info) <= pc
&& PROC_HIGH_ADDR (&link->info) > pc)
return &link->info;
if (startaddr == 0)
startaddr = heuristic_proc_start (pc);
proc_desc =
heuristic_proc_desc (startaddr, pc, next_frame, cur_frame);
}
return proc_desc;
}
static CORE_ADDR
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)) +
PROC_FRAME_OFFSET (proc_desc) - PROC_FRAME_ADJUST (proc_desc));
}
mips_extra_func_info_t cached_proc_desc;
CORE_ADDR
mips_frame_chain (struct frame_info *frame)
{
mips_extra_func_info_t proc_desc;
CORE_ADDR tmp;
CORE_ADDR saved_pc = FRAME_SAVED_PC (frame);
if (saved_pc == 0 || inside_entry_file (saved_pc))
return 0;
if ((tmp = mips_skip_stub (saved_pc)) != 0)
saved_pc = tmp;
proc_desc = find_proc_desc (saved_pc, frame, 1);
if (!proc_desc)
return 0;
cached_proc_desc = proc_desc;
if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
&& PROC_FRAME_OFFSET (proc_desc) == 0
&& !frame->signal_handler_caller)
return 0;
else
return get_frame_pointer (frame, proc_desc);
}
void
mips_init_extra_frame_info (int fromleaf, struct frame_info *fci)
{
int regnum;
mips_extra_func_info_t proc_desc =
fci->next ? cached_proc_desc : find_proc_desc (fci->pc, fci->next, 1);
fci->extra_info = (struct frame_extra_info *)
frame_obstack_alloc (sizeof (struct frame_extra_info));
fci->saved_regs = NULL;
fci->extra_info->proc_desc =
proc_desc == &temp_proc_desc ? 0 : proc_desc;
if (proc_desc)
{
if (fci->pc == PROC_LOW_ADDR (proc_desc)
&& !PROC_DESC_IS_DUMMY (proc_desc))
fci->frame = read_next_frame_reg (fci->next, SP_REGNUM);
else
fci->frame = get_frame_pointer (fci->next, proc_desc);
if (proc_desc == &temp_proc_desc)
{
char *name;
find_pc_partial_function (fci->pc, &name,
(CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
if (!IN_SIGTRAMP (fci->pc, name))
{
frame_saved_regs_zalloc (fci);
memcpy (fci->saved_regs, temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
fci->saved_regs[PC_REGNUM]
= fci->saved_regs[RA_REGNUM];
}
}
fci->extra_info->num_args = -1;
for (regnum = MIPS_LAST_ARG_REGNUM; regnum >= A0_REGNUM; regnum--)
{
if (PROC_REG_MASK (proc_desc) & (1 << regnum))
{
fci->extra_info->num_args = regnum - A0_REGNUM + 1;
break;
}
}
}
}
struct frame_info *
setup_arbitrary_frame (int argc, CORE_ADDR *argv)
{
if (argc != 2)
error ("MIPS frame specifications require two arguments: sp and pc");
return create_new_frame (argv[0], argv[1]);
}
static int
fp_register_arg_p (enum type_code typecode, struct type *arg_type)
{
return ((typecode == TYPE_CODE_FLT
|| (MIPS_EABI
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
&& TYPE_NFIELDS (arg_type) == 1
&& TYPE_CODE (TYPE_FIELD_TYPE (arg_type, 0)) == TYPE_CODE_FLT))
&& MIPS_FPU_TYPE != MIPS_FPU_NONE);
}
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 (int nargs,
struct value **args,
CORE_ADDR sp,
int struct_return,
CORE_ADDR struct_addr)
{
int argreg;
int float_argreg;
int argnum;
int len = 0;
int stack_offset = 0;
#define ROUND_DOWN(n,a) ((n) & ~((a)-1))
#define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1))
sp = ROUND_DOWN (sp, 16);
struct_addr = ROUND_DOWN (struct_addr, 16);
for (argnum = 0; argnum < nargs; argnum++)
len += ROUND_UP (TYPE_LENGTH (VALUE_TYPE (args[argnum])), MIPS_STACK_ARGSIZE);
sp -= ROUND_UP (len, 16);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, "mips_push_arguments: sp=0x%lx allocated %d\n",
(long) sp, ROUND_UP (len, 16));
argreg = A0_REGNUM;
float_argreg = FPA0_REGNUM;
if (struct_return)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog,
"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;
}
for (argnum = 0; argnum < nargs; argnum++)
{
char *val;
char valbuf[MAX_REGISTER_RAW_SIZE];
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 + 1, len, (int) typecode);
if (MIPS_EABI
&& len > MIPS_SAVED_REGSIZE
&& (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
{
store_address (valbuf, MIPS_SAVED_REGSIZE, VALUE_ADDRESS (arg));
typecode = TYPE_CODE_PTR;
len = MIPS_SAVED_REGSIZE;
val = valbuf;
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " push");
}
else
val = (char *) VALUE_CONTENTS (arg);
if (!FP_REGISTER_DOUBLE
&& fp_register_arg_p (typecode, arg_type))
{
if ((float_argreg & 1))
float_argreg++;
}
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
{
if (!FP_REGISTER_DOUBLE && len == 8)
{
int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
unsigned long regval;
regval = extract_unsigned_integer (val + low_offset, 4);
if (mips_debug)
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",
argreg, phex (regval, 4));
write_register (argreg++, regval);
}
regval = extract_unsigned_integer (val + 4 - low_offset, 4);
if (mips_debug)
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",
argreg, phex (regval, 4));
write_register (argreg++, regval);
}
}
else
{
LONGEST regval = extract_unsigned_integer (val, len);
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
float_argreg, phex (regval, len));
write_register (float_argreg++, regval);
if (!MIPS_EABI)
{
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
argreg, phex (regval, len));
write_register (argreg, regval);
argreg += FP_REGISTER_DOUBLE ? 1 : 2;
}
}
if (MIPS_REGS_HAVE_HOME_P)
stack_offset += ROUND_UP (len, MIPS_STACK_ARGSIZE);
}
else
{
int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) &&
(len % MIPS_SAVED_REGSIZE != 0));
if (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_O32
&& mips_type_needs_double_align (arg_type))
{
if ((argreg & 1))
argreg++;
}
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);
if (argreg > MIPS_LAST_ARG_REGNUM
|| odd_sized_struct
|| fp_register_arg_p (typecode, arg_type))
{
int longword_offset = 0;
CORE_ADDR addr;
stack_used_p = 1;
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
{
if (MIPS_STACK_ARGSIZE == 8 &&
(typecode == TYPE_CODE_INT ||
typecode == TYPE_CODE_PTR ||
typecode == TYPE_CODE_FLT) && len <= 4)
longword_offset = MIPS_STACK_ARGSIZE - len;
else if ((typecode == TYPE_CODE_STRUCT ||
typecode == TYPE_CODE_UNION) &&
TYPE_LENGTH (arg_type) < MIPS_STACK_ARGSIZE)
longword_offset = MIPS_STACK_ARGSIZE - len;
}
if (mips_debug)
{
fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%lx",
(long) stack_offset);
fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%lx",
(long) longword_offset);
}
addr = sp + stack_offset + longword_offset;
if (mips_debug)
{
int i;
fprintf_unfiltered (gdb_stdlog, " @0x%lx ", (long) addr);
for (i = 0; i < partial_len; i++)
{
fprintf_unfiltered (gdb_stdlog, "%02x", val[i] & 0xff);
}
}
write_memory (addr, val, partial_len);
}
if (argreg <= MIPS_LAST_ARG_REGNUM
&& !fp_register_arg_p (typecode, arg_type))
{
LONGEST regval = extract_unsigned_integer (val, partial_len);
if (!MIPS_EABI
&& MIPS_SAVED_REGSIZE < 8
&& TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& partial_len < MIPS_SAVED_REGSIZE
&& (typecode == TYPE_CODE_STRUCT ||
typecode == TYPE_CODE_UNION))
regval <<= ((MIPS_SAVED_REGSIZE - partial_len) *
TARGET_CHAR_BIT);
if (mips_debug)
fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
argreg,
phex (regval, MIPS_SAVED_REGSIZE));
write_register (argreg, regval);
argreg++;
if (!MIPS_EABI)
float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
}
len -= partial_len;
val += partial_len;
if (MIPS_REGS_HAVE_HOME_P || stack_used_p)
stack_offset += ROUND_UP (partial_len, MIPS_STACK_ARGSIZE);
}
}
if (mips_debug)
fprintf_unfiltered (gdb_stdlog, "\n");
}
return sp;
}
CORE_ADDR
mips_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
write_register (RA_REGNUM, CALL_DUMMY_ADDRESS ());
return sp;
}
static void
mips_push_register (CORE_ADDR * sp, int regno)
{
char buffer[MAX_REGISTER_RAW_SIZE];
int regsize;
int offset;
if (MIPS_SAVED_REGSIZE < REGISTER_RAW_SIZE (regno))
{
regsize = MIPS_SAVED_REGSIZE;
offset = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
? REGISTER_RAW_SIZE (regno) - MIPS_SAVED_REGSIZE
: 0);
}
else
{
regsize = REGISTER_RAW_SIZE (regno);
offset = 0;
}
*sp -= regsize;
read_register_gen (regno, buffer);
write_memory (*sp, buffer + offset, regsize);
}
#define MASK(i,j) (((1 << ((j)+1))-1) ^ ((1 << (i))-1))
void
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_signed_register (SP_REGNUM));
CORE_ADDR old_sp = sp;
link->next = linked_proc_desc_table;
linked_proc_desc_table = link;
#define PUSH_FP_REGNUM 16
#define GEN_REG_SAVE_MASK MASK(1,16)|MASK(24,28)|(1<<(MIPS_NUMREGS-1))
#define FLOAT_REG_SAVE_MASK MASK(0,19)
#define FLOAT_SINGLE_REG_SAVE_MASK \
((1<<18)|(1<<16)|(1<<14)|(1<<12)|(1<<10)|(1<<8)|(1<<6)|(1<<4)|(1<<2)|(1<<0))
PROC_FRAME_REG (proc_desc) = PUSH_FP_REGNUM;
PROC_FRAME_OFFSET (proc_desc) = 0;
PROC_FRAME_ADJUST (proc_desc) = 0;
mips_push_register (&sp, PC_REGNUM);
mips_push_register (&sp, HI_REGNUM);
mips_push_register (&sp, LO_REGNUM);
mips_push_register (&sp, MIPS_FPU_TYPE == MIPS_FPU_NONE ? 0 : FCRCS_REGNUM);
PROC_REG_MASK (proc_desc) = GEN_REG_SAVE_MASK;
PROC_REG_OFFSET (proc_desc) = sp - old_sp - MIPS_SAVED_REGSIZE;
for (ireg = 32; --ireg >= 0;)
if (PROC_REG_MASK (proc_desc) & (1 << ireg))
mips_push_register (&sp, ireg);
PROC_FREG_MASK (proc_desc) =
MIPS_FPU_TYPE == MIPS_FPU_DOUBLE ? FLOAT_REG_SAVE_MASK
: MIPS_FPU_TYPE == MIPS_FPU_SINGLE ? FLOAT_SINGLE_REG_SAVE_MASK : 0;
PROC_FREG_OFFSET (proc_desc) = sp - old_sp - 8;
for (ireg = 32; --ireg >= 0;)
if (PROC_FREG_MASK (proc_desc) & (1 << ireg))
mips_push_register (&sp, ireg + FP0_REGNUM);
write_register (PUSH_FP_REGNUM, old_sp);
write_register (SP_REGNUM, sp);
PROC_LOW_ADDR (proc_desc) = CALL_DUMMY_ADDRESS ();
PROC_HIGH_ADDR (proc_desc) = CALL_DUMMY_ADDRESS () + 4;
SET_PROC_DESC_IS_DUMMY (proc_desc);
PROC_PC_REG (proc_desc) = RA_REGNUM;
}
void
mips_pop_frame (void)
{
register int regnum;
struct frame_info *frame = get_current_frame ();
CORE_ADDR new_sp = FRAME_FP (frame);
mips_extra_func_info_t proc_desc = frame->extra_info->proc_desc;
write_register (PC_REGNUM, FRAME_SAVED_PC (frame));
if (frame->saved_regs == NULL)
mips_find_saved_regs (frame);
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
if (regnum != SP_REGNUM && regnum != PC_REGNUM
&& frame->saved_regs[regnum])
write_register (regnum,
read_memory_integer (frame->saved_regs[regnum],
MIPS_SAVED_REGSIZE));
}
write_register (SP_REGNUM, new_sp);
flush_cached_frames ();
if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
{
struct linked_proc_info *pi_ptr, *prev_ptr;
for (pi_ptr = linked_proc_desc_table, prev_ptr = NULL;
pi_ptr != NULL;
prev_ptr = pi_ptr, pi_ptr = pi_ptr->next)
{
if (&pi_ptr->info == proc_desc)
break;
}
if (pi_ptr == NULL)
error ("Can't locate dummy extra frame info\n");
if (prev_ptr != NULL)
prev_ptr->next = pi_ptr->next;
else
linked_proc_desc_table = pi_ptr->next;
xfree (pi_ptr);
write_register (HI_REGNUM,
read_memory_integer (new_sp - 2 * MIPS_SAVED_REGSIZE,
MIPS_SAVED_REGSIZE));
write_register (LO_REGNUM,
read_memory_integer (new_sp - 3 * MIPS_SAVED_REGSIZE,
MIPS_SAVED_REGSIZE));
if (MIPS_FPU_TYPE != MIPS_FPU_NONE)
write_register (FCRCS_REGNUM,
read_memory_integer (new_sp - 4 * MIPS_SAVED_REGSIZE,
MIPS_SAVED_REGSIZE));
}
}
static void
mips_print_register (int regnum, int all)
{
char raw_buffer[MAX_REGISTER_RAW_SIZE];
if (read_relative_register_raw_bytes (regnum, raw_buffer))
{
printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
return;
}
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
&& !((regnum - FP0_REGNUM) & 1))
if (REGISTER_RAW_SIZE (regnum) == 4)
{
char dbuffer[2 * MAX_REGISTER_RAW_SIZE];
read_relative_register_raw_bytes (regnum, dbuffer);
read_relative_register_raw_bytes (regnum + 1, dbuffer + MIPS_REGSIZE);
REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer);
printf_filtered ("(d%d: ", regnum - FP0_REGNUM);
val_print (builtin_type_double, dbuffer, 0, 0,
gdb_stdout, 0, 1, 0, Val_pretty_default);
printf_filtered ("); ");
}
fputs_filtered (REGISTER_NAME (regnum), gdb_stdout);
if (regnum < MIPS_NUMREGS)
printf_filtered ("(r%d): ", regnum);
else
printf_filtered (": ");
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
if (FP_REGISTER_DOUBLE)
{
int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
printf_filtered (" (float) ");
val_print (builtin_type_float, raw_buffer + offset, 0, 0,
gdb_stdout, 0, 1, 0, Val_pretty_default);
printf_filtered (", (double) ");
val_print (builtin_type_double, raw_buffer, 0, 0,
gdb_stdout, 0, 1, 0, Val_pretty_default);
}
else
val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0, 0,
gdb_stdout, 0, 1, 0, Val_pretty_default);
else
{
int offset;
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
offset = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
else
offset = 0;
print_scalar_formatted (raw_buffer + offset,
REGISTER_VIRTUAL_TYPE (regnum),
'x', 0, gdb_stdout);
}
}
static int
do_fp_register_row (int regnum)
{
char *raw_buffer[2];
char *dbl_buffer;
int HI = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
int LO = (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG);
double doub, flt1, flt2;
int inv1, inv2, inv3;
raw_buffer[0] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
raw_buffer[1] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
dbl_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
if (read_relative_register_raw_bytes (regnum, raw_buffer[HI]))
error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
if (REGISTER_RAW_SIZE (regnum) == 4)
{
if (read_relative_register_raw_bytes (regnum + 1, raw_buffer[LO]))
error ("can't read register %d (%s)",
regnum + 1, REGISTER_NAME (regnum + 1));
memcpy (dbl_buffer, raw_buffer, 2 * REGISTER_RAW_SIZE (FP0_REGNUM));
flt1 = unpack_double (builtin_type_float, raw_buffer[HI], &inv1);
flt2 = unpack_double (builtin_type_float, raw_buffer[LO], &inv2);
doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
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");
regnum += 2;
}
else
{
int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
memcpy (dbl_buffer, raw_buffer[HI], 2 * REGISTER_RAW_SIZE (FP0_REGNUM));
flt1 = unpack_double (builtin_type_float,
&raw_buffer[HI][offset], &inv1);
doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
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");
regnum++;
}
return regnum;
}
static int
do_gp_register_row (int regnum)
{
char raw_buffer[MAX_REGISTER_RAW_SIZE];
int ncols = (MIPS_REGSIZE == 8 ? 4 : 8);
int col, byte;
int start_regnum = regnum;
int numregs = NUM_REGS;
printf_filtered (" ");
for (col = 0; col < ncols && regnum < numregs; regnum++)
{
if (*REGISTER_NAME (regnum) == '\0')
continue;
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
break;
printf_filtered (MIPS_REGSIZE == 8 ? "%17s" : "%9s",
REGISTER_NAME (regnum));
col++;
}
printf_filtered (start_regnum < MIPS_NUMREGS ? "\n R%-4d" : "\n ",
start_regnum);
regnum = start_regnum;
for (col = 0; col < ncols && regnum < numregs; regnum++)
{
if (*REGISTER_NAME (regnum) == '\0')
continue;
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
break;
if (read_relative_register_raw_bytes (regnum, raw_buffer))
error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
for (byte = 0; byte < (MIPS_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
printf_filtered (" ");
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
byte < REGISTER_RAW_SIZE (regnum);
byte++)
printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
else
for (byte = REGISTER_VIRTUAL_SIZE (regnum) - 1;
byte >= 0;
byte--)
printf_filtered ("%02x", (unsigned char) raw_buffer[byte]);
printf_filtered (" ");
col++;
}
if (col > 0)
printf_filtered ("\n");
return regnum;
}
void
mips_do_registers_info (int regnum, int fpregs)
{
if (regnum != -1)
{
if (*(REGISTER_NAME (regnum)) == '\0')
error ("Not a valid register for the current processor type");
mips_print_register (regnum, 0);
printf_filtered ("\n");
}
else
{
regnum = 0;
while (regnum < NUM_REGS)
{
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
if (fpregs)
regnum = do_fp_register_row (regnum);
else
regnum += MIPS_NUMREGS;
else
regnum = do_gp_register_row (regnum);
}
}
}
int
mips_frame_num_args (struct frame_info *frame)
{
return -1;
}
static int is_delayed (unsigned long);
static int
is_delayed (unsigned long insn)
{
int i;
for (i = 0; i < NUMOPCODES; ++i)
if (mips_opcodes[i].pinfo != INSN_MACRO
&& (insn & mips_opcodes[i].mask) == mips_opcodes[i].match)
break;
return (i < NUMOPCODES
&& (mips_opcodes[i].pinfo & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
| INSN_COND_BRANCH_LIKELY)));
}
int
mips_step_skips_delay (CORE_ADDR pc)
{
char buf[MIPS_INSTLEN];
if (pc_is_mips16 (pc))
return 0;
if (target_read_memory (pc, buf, MIPS_INSTLEN) != 0)
return 0;
return is_delayed ((unsigned long) extract_unsigned_integer (buf, MIPS_INSTLEN));
}
static CORE_ADDR
mips32_skip_prologue (CORE_ADDR pc)
{
t_inst inst;
CORE_ADDR end_pc;
int seen_sp_adjust = 0;
int load_immediate_bytes = 0;
for (end_pc = pc + 100; pc < end_pc; pc += MIPS_INSTLEN)
{
unsigned long high_word;
inst = mips_fetch_instruction (pc);
high_word = (inst >> 16) & 0xffff;
if (high_word == 0x27bd
|| high_word == 0x67bd)
seen_sp_adjust = 1;
else if (inst == 0x03a1e823 ||
inst == 0x03a8e823)
seen_sp_adjust = 1;
else if (((inst & 0xFFE00000) == 0xAFA00000
|| (inst & 0xFFE00000) == 0xFFA00000)
&& (inst & 0x001F0000))
continue;
else if ((inst & 0xFFE00000) == 0xE7A00000)
continue;
else if ((inst & 0xF3E00000) == 0xA3C00000 && (inst & 0x001F0000))
continue;
else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
continue;
else if ((inst & 0xFF9F07FF) == 0x00800021)
continue;
else if (high_word == 0x3c1c)
continue;
else if (high_word == 0x279c)
continue;
else if (inst == 0x0399e021
|| inst == 0x033ce021)
continue;
else if (!seen_sp_adjust)
{
if (high_word == 0x3c01 ||
high_word == 0x3c08)
{
load_immediate_bytes += MIPS_INSTLEN;
continue;
}
else if (high_word == 0x3421 ||
high_word == 0x3508 ||
high_word == 0x3401 ||
high_word == 0x3408)
{
load_immediate_bytes += MIPS_INSTLEN;
continue;
}
else
break;
}
else
break;
}
if (load_immediate_bytes && !seen_sp_adjust)
pc -= load_immediate_bytes;
return pc;
}
static CORE_ADDR
mips16_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR end_pc;
int extend_bytes = 0;
int prev_extend_bytes;
static struct
{
unsigned short inst;
unsigned short mask;
}
table[] =
{
{
0x6300, 0xff00
}
,
{
0xfb00, 0xff00
}
,
{
0xd000, 0xf800
}
,
{
0xf900, 0xff00
}
,
{
0x6200, 0xff00
}
,
{
0xfa00, 0xff00
}
,
{
0x673d, 0xffff
}
,
{
0xd980, 0xff80
}
,
{
0x6704, 0xff1c
}
,
{
0xe809, 0xf81f
}
,
{
0x0100, 0xff00
}
,
{
0, 0
}
};
for (end_pc = pc + 100; pc < end_pc; pc += MIPS16_INSTLEN)
{
unsigned short inst;
int i;
inst = mips_fetch_instruction (pc);
if ((inst & 0xf800) == 0xf000)
{
extend_bytes = MIPS16_INSTLEN;
continue;
}
prev_extend_bytes = extend_bytes;
extend_bytes = 0;
for (i = 0; table[i].mask != 0; i++)
if ((inst & table[i].mask) == table[i].inst)
break;
if (table[i].mask != 0)
continue;
else
{
return pc - prev_extend_bytes;
}
}
return pc;
}
CORE_ADDR
mips_skip_prologue (CORE_ADDR pc)
{
CORE_ADDR post_prologue_pc = after_prologue (pc, NULL);
if (post_prologue_pc != 0)
return max (pc, post_prologue_pc);
if (pc_is_mips16 (pc))
return mips16_skip_prologue (pc);
else
return mips32_skip_prologue (pc);
}
struct return_value_word
{
int len;
int reg;
int reg_offset;
int buf_offset;
};
static void
return_value_location (struct type *valtype,
struct return_value_word *hi,
struct return_value_word *lo)
{
int len = TYPE_LENGTH (valtype);
if (TYPE_CODE (valtype) == TYPE_CODE_FLT
&& ((MIPS_FPU_TYPE == MIPS_FPU_DOUBLE && (len == 4 || len == 8))
|| (MIPS_FPU_TYPE == MIPS_FPU_SINGLE && len == 4)))
{
if (!FP_REGISTER_DOUBLE && len == 8)
{
lo->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
hi->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 0 : 4;
lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& REGISTER_RAW_SIZE (FP0_REGNUM) == 8)
? 4 : 0);
hi->reg_offset = lo->reg_offset;
lo->reg = FP0_REGNUM + 0;
hi->reg = FP0_REGNUM + 1;
lo->len = 4;
hi->len = 4;
}
else
{
lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& REGISTER_RAW_SIZE (FP0_REGNUM) == 8
&& len == 4)
? 4 : 0);
lo->reg = FP0_REGNUM;
lo->len = len;
lo->buf_offset = 0;
hi->len = 0;
hi->reg_offset = 0;
hi->buf_offset = 0;
hi->reg = 0;
}
}
else
{
int regnum = 2;
lo->reg = regnum + 0;
hi->reg = regnum + 1;
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& len < MIPS_SAVED_REGSIZE)
{
lo->reg_offset = MIPS_SAVED_REGSIZE - len;
lo->len = len;
hi->reg_offset = 0;
hi->len = 0;
}
else if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& len > MIPS_SAVED_REGSIZE
&& len < MIPS_SAVED_REGSIZE * 2
&& (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
TYPE_CODE (valtype) == TYPE_CODE_UNION))
{
lo->reg_offset = 2 * MIPS_SAVED_REGSIZE - len;
lo->len = MIPS_SAVED_REGSIZE - lo->reg_offset;
hi->reg_offset = 0;
hi->len = len - lo->len;
}
else
{
lo->reg_offset = 0;
hi->reg_offset = 0;
if (len > MIPS_SAVED_REGSIZE)
{
lo->len = MIPS_SAVED_REGSIZE;
hi->len = len - MIPS_SAVED_REGSIZE;
}
else
{
lo->len = len;
hi->len = 0;
}
}
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& REGISTER_RAW_SIZE (regnum) == 8
&& MIPS_SAVED_REGSIZE == 4)
{
lo->reg_offset += 4;
hi->reg_offset += 4;
}
lo->buf_offset = 0;
hi->buf_offset = lo->len;
}
}
void
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, &hi, &lo);
memcpy (valbuf + lo.buf_offset,
regbuf + REGISTER_BYTE (lo.reg) + lo.reg_offset,
lo.len);
if (hi.len > 0)
memcpy (valbuf + hi.buf_offset,
regbuf + REGISTER_BYTE (hi.reg) + hi.reg_offset,
hi.len);
}
void
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, &hi, &lo);
memset (raw_buffer, 0, sizeof (raw_buffer));
memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len);
write_register_bytes (REGISTER_BYTE (lo.reg),
raw_buffer,
REGISTER_RAW_SIZE (lo.reg));
if (hi.len > 0)
{
memset (raw_buffer, 0, sizeof (raw_buffer));
memcpy (raw_buffer + hi.reg_offset, valbuf + hi.buf_offset, hi.len);
write_register_bytes (REGISTER_BYTE (hi.reg),
raw_buffer,
REGISTER_RAW_SIZE (hi.reg));
}
}
int
in_sigtramp (CORE_ADDR pc, char *ignore)
{
if (sigtramp_address == 0)
fixup_sigtramp ();
return (pc >= sigtramp_address && pc < sigtramp_end);
}
static void
show_mips_command (char *args, int from_tty)
{
help_list (showmipscmdlist, "show mips ", all_commands, gdb_stdout);
}
static void
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);
}
static void
show_mipsfpu_command (char *args, int from_tty)
{
char *fpu;
switch (MIPS_FPU_TYPE)
{
case MIPS_FPU_SINGLE:
fpu = "single-precision";
break;
case MIPS_FPU_DOUBLE:
fpu = "double-precision";
break;
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",
fpu);
else
printf_unfiltered ("The MIPS floating-point coprocessor is assumed to be %s\n",
fpu);
}
static void
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 *args, int from_tty)
{
mips_fpu_type = MIPS_FPU_SINGLE;
mips_fpu_type_auto = 0;
if (GDB_MULTI_ARCH)
{
gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_SINGLE;
}
}
static void
set_mipsfpu_double_command (char *args, int from_tty)
{
mips_fpu_type = MIPS_FPU_DOUBLE;
mips_fpu_type_auto = 0;
if (GDB_MULTI_ARCH)
{
gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_DOUBLE;
}
}
static void
set_mipsfpu_none_command (char *args, int from_tty)
{
mips_fpu_type = MIPS_FPU_NONE;
mips_fpu_type_auto = 0;
if (GDB_MULTI_ARCH)
{
gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_NONE;
}
}
static void
set_mipsfpu_auto_command (char *args, int from_tty)
{
mips_fpu_type_auto = 1;
}
void
mips_set_processor_type_command (char *args, int from_tty)
{
int i;
if (tmp_mips_processor_type == NULL || *tmp_mips_processor_type == '\0')
{
printf_unfiltered ("The known MIPS processor types are as follows:\n\n");
for (i = 0; mips_processor_type_table[i].name != NULL; ++i)
printf_unfiltered ("%s\n", mips_processor_type_table[i].name);
tmp_mips_processor_type = xstrdup (mips_processor_type);
return;
}
if (!mips_set_processor_type (tmp_mips_processor_type))
{
error ("Unknown processor type `%s'.", tmp_mips_processor_type);
tmp_mips_processor_type = xstrdup (mips_processor_type);
}
}
static void
mips_show_processor_type_command (char *args, int from_tty)
{
}
int
mips_set_processor_type (char *str)
{
int i;
if (str == NULL)
return 0;
for (i = 0; mips_processor_type_table[i].name != NULL; ++i)
{
if (strcasecmp (str, mips_processor_type_table[i].name) == 0)
{
mips_processor_type = str;
mips_processor_reg_names = mips_processor_type_table[i].regnames;
return 1;
}
}
return 0;
}
char *
mips_read_processor_type (void)
{
CORE_ADDR prid;
prid = read_register (PRID_REGNUM);
if ((prid & ~0xf) == 0x700)
return savestring ("r3041", strlen ("r3041"));
return NULL;
}
static void
reinit_frame_cache_sfunc (char *args, int from_tty,
struct cmd_list_element *c)
{
reinit_frame_cache ();
}
int
gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info)
{
mips_extra_func_info_t proc_desc;
memaddr = ADDR_BITS_REMOVE (memaddr);
proc_desc = non_heuristic_proc_desc (MAKE_MIPS16_ADDR (memaddr), NULL);
if (proc_desc)
info->mach = pc_is_mips16 (PROC_LOW_ADDR (proc_desc)) ?
bfd_mach_mips16 : TM_PRINT_INSN_MACH;
else
info->mach = pc_is_mips16 (memaddr) ?
bfd_mach_mips16 : TM_PRINT_INSN_MACH;
memaddr &= (info->mach == bfd_mach_mips16 ? ~1 : ~3);
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
return print_insn_big_mips (memaddr, info);
else
return print_insn_little_mips (memaddr, info);
}
#define BIG_BREAKPOINT {0, 0x5, 0, 0xd}
#define LITTLE_BREAKPOINT {0xd, 0, 0x5, 0}
#define PMON_BIG_BREAKPOINT {0, 0, 0, 0xd}
#define PMON_LITTLE_BREAKPOINT {0xd, 0, 0, 0}
#define IDT_BIG_BREAKPOINT {0, 0, 0x0a, 0xd}
#define IDT_LITTLE_BREAKPOINT {0xd, 0x0a, 0, 0}
#define MIPS16_BIG_BREAKPOINT {0xe8, 0xa5}
#define MIPS16_LITTLE_BREAKPOINT {0xa5, 0xe8}
unsigned char *
mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
{
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
{
if (pc_is_mips16 (*pcptr))
{
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 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 (strcmp (target_shortname, "mips") == 0)
return idt_big_breakpoint;
else if (strcmp (target_shortname, "ddb") == 0
|| strcmp (target_shortname, "pmon") == 0
|| strcmp (target_shortname, "lsi") == 0)
return pmon_big_breakpoint;
else
return big_breakpoint;
}
}
else
{
if (pc_is_mips16 (*pcptr))
{
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 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);
if (strcmp (target_shortname, "mips") == 0)
return idt_little_breakpoint;
else if (strcmp (target_shortname, "ddb") == 0
|| strcmp (target_shortname, "pmon") == 0
|| strcmp (target_shortname, "lsi") == 0)
return pmon_little_breakpoint;
else
return little_breakpoint;
}
}
}
CORE_ADDR
mips_skip_stub (CORE_ADDR pc)
{
char *name;
CORE_ADDR start_addr;
if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
return 0;
if (strcmp (name, "__mips16_ret_sf") == 0
|| strcmp (name, "__mips16_ret_df") == 0)
return read_signed_register (RA_REGNUM);
if (strncmp (name, "__mips16_call_stub_", 19) == 0)
{
if (name[19] >= '0' && name[19] <= '9')
return read_signed_register (2);
else if (name[19] == 's' || name[19] == 'd')
{
if (pc == start_addr)
{
CORE_ADDR target_pc = read_signed_register (2);
t_inst inst;
int i;
if (find_pc_partial_function (target_pc, &name, NULL, NULL) == 0)
return target_pc;
if (strncmp (name, "__fn_stub_", 10) != 0
&& strcmp (name, "etext") != 0
&& strcmp (name, "_etext") != 0)
return target_pc;
for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSTLEN)
{
inst = mips_fetch_instruction (target_pc);
if ((inst & 0xffff0000) == 0x3c010000)
pc = (inst << 16) & 0xffff0000;
else if ((inst & 0xffff0000) == 0x24210000)
return pc | (inst & 0xffff);
}
return target_pc;
}
else
return read_signed_register (18);
}
}
return 0;
}
int
mips_in_call_stub (CORE_ADDR pc, char *name)
{
CORE_ADDR start_addr;
if (find_pc_partial_function (pc, name ? NULL : &name, &start_addr, NULL) == 0)
return 0;
if (strncmp (name, "__mips16_call_stub_", 19) == 0)
{
if (name[19] >= '0' && name[19] <= '9')
return 1;
else if (name[19] == 's' || name[19] == 'd')
return pc == start_addr;
}
return 0;
}
int
mips_in_return_stub (CORE_ADDR pc, char *name)
{
CORE_ADDR start_addr;
if (find_pc_partial_function (pc, NULL, &start_addr, NULL) == 0)
return 0;
if (strcmp (name, "__mips16_ret_sf") == 0
|| strcmp (name, "__mips16_ret_df") == 0)
return 1;
if (strncmp (name, "__mips16_call_stub_", 19) == 0
&& (name[19] == 's' || name[19] == 'd')
&& pc != start_addr)
return 1;
return 0;
}
int
mips_ignore_helper (CORE_ADDR pc)
{
char *name;
if (find_pc_partial_function (pc, &name, NULL, NULL) == 0)
return 0;
return (strcmp (name, "__mips16_ret_sf") == 0
|| strcmp (name, "__mips16_ret_df") == 0);
}
CORE_ADDR
mips_call_dummy_address (void)
{
struct minimal_symbol *sym;
sym = lookup_minimal_symbol ("__CALL_DUMMY_ADDRESS", NULL, NULL);
if (sym)
return SYMBOL_VALUE_ADDRESS (sym);
else
return entry_point_address ();
}
static int
mips_coerce_float_to_double (struct type *formal, struct type *actual)
{
return current_language->la_language == language_c;
}
static void
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;
if (!target_has_registers)
error ("No registers.");
if (optimized != NULL)
*optimized = 0;
addr = find_saved_register (frame, regnum);
if (addr != 0)
{
if (lval != NULL)
*lval = lval_memory;
if (regnum == SP_REGNUM)
{
if (raw_buffer != NULL)
{
store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
(LONGEST) addr);
}
if (addrp != NULL)
*addrp = 0;
return;
}
if (raw_buffer != NULL)
{
LONGEST val;
if (regnum < 32)
val = read_memory_integer (addr, MIPS_SAVED_REGSIZE);
else
val = read_memory_integer (addr, REGISTER_RAW_SIZE (regnum));
store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), val);
}
}
else
{
if (lval != NULL)
*lval = lval_register;
addr = REGISTER_BYTE (regnum);
if (raw_buffer != NULL)
read_register_gen (regnum, raw_buffer);
}
if (addrp != NULL)
*addrp = addr;
}
static CORE_ADDR
mips_saved_pc_after_call (struct frame_info *frame)
{
return read_signed_register (RA_REGNUM);
}
static int
mips_stab_reg_to_regnum (int num)
{
if (num < 32)
return num;
else
return num + FP0_REGNUM - 38;
}
static int
mips_ecoff_reg_to_regnum (int num)
{
if (num < 32)
return num;
else
return num + FP0_REGNUM - 32;
}
static CORE_ADDR
mips_integer_to_address (struct type *type, void *buf)
{
char *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
LONGEST val = unpack_long (type, buf);
store_signed_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
return extract_signed_integer (tmp,
TYPE_LENGTH (builtin_type_void_data_ptr));
}
static struct gdbarch *
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;
enum mips_abi mips_abi;
tm_print_insn_info.flavour = bfd_target_unknown_flavour;
tm_print_insn_info.arch = bfd_arch_unknown;
tm_print_insn_info.mach = 0;
if (info.abfd != NULL
&& bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
elf_flags = elf_elfheader (info.abfd)->e_flags;
else
elf_flags = 0;
switch ((elf_flags & EF_MIPS_ABI))
{
case E_MIPS_ABI_O32:
mips_abi = MIPS_ABI_O32;
break;
case E_MIPS_ABI_O64:
mips_abi = MIPS_ABI_O64;
break;
case E_MIPS_ABI_EABI32:
mips_abi = MIPS_ABI_EABI32;
break;
case E_MIPS_ABI_EABI64:
mips_abi = MIPS_ABI_EABI64;
break;
default:
if ((elf_flags & EF_MIPS_ABI2))
mips_abi = MIPS_ABI_N32;
else
mips_abi = MIPS_ABI_UNKNOWN;
break;
}
if (mips_abi == MIPS_ABI_UNKNOWN
&& info.bfd_arch_info != NULL
&& info.bfd_arch_info->arch == bfd_arch_mips)
{
switch (info.bfd_arch_info->mach)
{
case bfd_mach_mips3900:
mips_abi = MIPS_ABI_EABI32;
break;
case bfd_mach_mips4100:
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
if (mips_abi == MIPS_ABI_UNKNOWN)
mips_abi = MIPS_DEFAULT_ABI;
#endif
if (gdbarch_debug)
{
fprintf_unfiltered (gdb_stdlog,
"mips_gdbarch_init: elf_flags = 0x%08x\n",
elf_flags);
fprintf_unfiltered (gdb_stdlog,
"mips_gdbarch_init: mips_abi = %d\n",
mips_abi);
}
for (arches = gdbarch_list_lookup_by_info (arches, &info);
arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
if (gdbarch_tdep (arches->gdbarch)->elf_flags != elf_flags)
continue;
if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
continue;
return arches->gdbarch;
}
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
tdep->elf_flags = elf_flags;
set_gdbarch_short_bit (gdbarch, 16);
set_gdbarch_int_bit (gdbarch, 32);
set_gdbarch_float_bit (gdbarch, 32);
set_gdbarch_double_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 64);
set_gdbarch_register_raw_size (gdbarch, mips_register_raw_size);
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 = 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 = 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 = 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 = 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 = 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);
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 = 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);
break;
}
if (!mips_fpu_type_auto)
tdep->mips_fpu_type = mips_fpu_type;
else if (info.bfd_arch_info != NULL
&& info.bfd_arch_info->arch == bfd_arch_mips)
switch (info.bfd_arch_info->mach)
{
case bfd_mach_mips3900:
case bfd_mach_mips4100:
case bfd_mach_mips4111:
tdep->mips_fpu_type = MIPS_FPU_NONE;
break;
case bfd_mach_mips4650:
tdep->mips_fpu_type = MIPS_FPU_SINGLE;
break;
default:
tdep->mips_fpu_type = MIPS_FPU_DOUBLE;
break;
}
else
tdep->mips_fpu_type = MIPS_FPU_DOUBLE;
set_gdbarch_register_name (gdbarch, mips_register_name);
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);
set_gdbarch_addr_bits_remove (gdbarch, mips_addr_bits_remove);
set_gdbarch_init_frame_pc_first (gdbarch, mips_init_frame_pc_first);
set_gdbarch_init_frame_pc (gdbarch, init_frame_pc_noop);
set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_ecoff_reg_to_regnum);
set_gdbarch_init_extra_frame_info (gdbarch, mips_init_extra_frame_info);
set_gdbarch_call_dummy_p (gdbarch, 1);
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
set_gdbarch_call_dummy_address (gdbarch, mips_call_dummy_address);
set_gdbarch_call_dummy_start_offset (gdbarch, 0);
set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);
set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
set_gdbarch_call_dummy_words (gdbarch, mips_call_dummy_words);
set_gdbarch_sizeof_call_dummy_words (gdbarch, sizeof (mips_call_dummy_words));
set_gdbarch_push_return_address (gdbarch, mips_push_return_address);
set_gdbarch_push_arguments (gdbarch, mips_push_arguments);
set_gdbarch_register_convertible (gdbarch, generic_register_convertible_not);
set_gdbarch_coerce_float_to_double (gdbarch, mips_coerce_float_to_double);
set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
set_gdbarch_get_saved_register (gdbarch, mips_get_saved_register);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
set_gdbarch_decr_pc_after_break (gdbarch, 0);
set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
set_gdbarch_saved_pc_after_call (gdbarch, mips_saved_pc_after_call);
set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
return gdbarch;
}
static void
mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
if (tdep != NULL)
{
int ef_mips_arch;
int ef_mips_32bitmode;
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;
}
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: 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",
FP_REGISTER_DOUBLE);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_DEFAULT_FPU_TYPE = %d (%s)\n",
MIPS_DEFAULT_FPU_TYPE,
(MIPS_DEFAULT_FPU_TYPE == MIPS_FPU_NONE ? "none"
: MIPS_DEFAULT_FPU_TYPE == MIPS_FPU_SINGLE ? "single"
: MIPS_DEFAULT_FPU_TYPE == MIPS_FPU_DOUBLE ? "double"
: "???"));
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_EABI = %d\n",
MIPS_EABI);
fprintf_unfiltered (file,
"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,
(MIPS_FPU_TYPE == MIPS_FPU_NONE ? "none"
: MIPS_FPU_TYPE == MIPS_FPU_SINGLE ? "single"
: MIPS_FPU_TYPE == MIPS_FPU_DOUBLE ? "double"
: "???"));
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_DEFAULT_SAVED_REGSIZE = %d\n",
MIPS_DEFAULT_SAVED_REGSIZE);
fprintf_unfiltered (file,
"mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
FP_REGISTER_DOUBLE);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_REGS_HAVE_HOME_P = %d\n",
MIPS_REGS_HAVE_HOME_P);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_DEFAULT_STACK_ARGSIZE = %d\n",
MIPS_DEFAULT_STACK_ARGSIZE);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_STACK_ARGSIZE = %d\n",
MIPS_STACK_ARGSIZE);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_REGSIZE = %d\n",
MIPS_REGSIZE);
fprintf_unfiltered (file,
"mips_dump_tdep: A0_REGNUM = %d\n",
A0_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: ADDR_BITS_REMOVE # %s\n",
XSTRING (ADDR_BITS_REMOVE(ADDR)));
fprintf_unfiltered (file,
"mips_dump_tdep: ATTACH_DETACH # %s\n",
XSTRING (ATTACH_DETACH));
fprintf_unfiltered (file,
"mips_dump_tdep: BADVADDR_REGNUM = %d\n",
BADVADDR_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: BIG_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: CAUSE_REGNUM = %d\n",
CAUSE_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: CPLUS_MARKER = %c\n",
CPLUS_MARKER);
fprintf_unfiltered (file,
"mips_dump_tdep: DEFAULT_MIPS_TYPE = %s\n",
DEFAULT_MIPS_TYPE);
fprintf_unfiltered (file,
"mips_dump_tdep: DO_REGISTERS_INFO # %s\n",
XSTRING (DO_REGISTERS_INFO));
fprintf_unfiltered (file,
"mips_dump_tdep: DWARF_REG_TO_REGNUM # %s\n",
XSTRING (DWARF_REG_TO_REGNUM (REGNUM)));
fprintf_unfiltered (file,
"mips_dump_tdep: ECOFF_REG_TO_REGNUM # %s\n",
XSTRING (ECOFF_REG_TO_REGNUM (REGNUM)));
fprintf_unfiltered (file,
"mips_dump_tdep: ELF_MAKE_MSYMBOL_SPECIAL # %s\n",
XSTRING (ELF_MAKE_MSYMBOL_SPECIAL (SYM, MSYM)));
fprintf_unfiltered (file,
"mips_dump_tdep: FCRCS_REGNUM = %d\n",
FCRCS_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: FCRIR_REGNUM = %d\n",
FCRIR_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: FIRST_EMBED_REGNUM = %d\n",
FIRST_EMBED_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: FPA0_REGNUM = %d\n",
FPA0_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: GDB_TARGET_IS_MIPS64 = %d\n",
GDB_TARGET_IS_MIPS64);
fprintf_unfiltered (file,
"mips_dump_tdep: GDB_TARGET_MASK_DISAS_PC # %s\n",
XSTRING (GDB_TARGET_MASK_DISAS_PC (PC)));
fprintf_unfiltered (file,
"mips_dump_tdep: GDB_TARGET_UNMASK_DISAS_PC # %s\n",
XSTRING (GDB_TARGET_UNMASK_DISAS_PC (PC)));
fprintf_unfiltered (file,
"mips_dump_tdep: GEN_REG_SAVE_MASK = %d\n",
GEN_REG_SAVE_MASK);
fprintf_unfiltered (file,
"mips_dump_tdep: HAVE_NONSTEPPABLE_WATCHPOINT # %s\n",
XSTRING (HAVE_NONSTEPPABLE_WATCHPOINT));
fprintf_unfiltered (file,
"mips_dump_tdep: HI_REGNUM = %d\n",
HI_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: IDT_BIG_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: IDT_LITTLE_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: IGNORE_HELPER_CALL # %s\n",
XSTRING (IGNORE_HELPER_CALL (PC)));
fprintf_unfiltered (file,
"mips_dump_tdep: IN_SIGTRAMP # %s\n",
XSTRING (IN_SIGTRAMP (PC, NAME)));
fprintf_unfiltered (file,
"mips_dump_tdep: IN_SOLIB_CALL_TRAMPOLINE # %s\n",
XSTRING (IN_SOLIB_CALL_TRAMPOLINE (PC, NAME)));
fprintf_unfiltered (file,
"mips_dump_tdep: IN_SOLIB_RETURN_TRAMPOLINE # %s\n",
XSTRING (IN_SOLIB_RETURN_TRAMPOLINE (PC, NAME)));
fprintf_unfiltered (file,
"mips_dump_tdep: IS_MIPS16_ADDR = FIXME!\n");
fprintf_unfiltered (file,
"mips_dump_tdep: LAST_EMBED_REGNUM = %d\n",
LAST_EMBED_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: LITTLE_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: LO_REGNUM = %d\n",
LO_REGNUM);
#ifdef MACHINE_CPROC_FP_OFFSET
fprintf_unfiltered (file,
"mips_dump_tdep: MACHINE_CPROC_FP_OFFSET = %d\n",
MACHINE_CPROC_FP_OFFSET);
#endif
#ifdef MACHINE_CPROC_PC_OFFSET
fprintf_unfiltered (file,
"mips_dump_tdep: MACHINE_CPROC_PC_OFFSET = %d\n",
MACHINE_CPROC_PC_OFFSET);
#endif
#ifdef MACHINE_CPROC_SP_OFFSET
fprintf_unfiltered (file,
"mips_dump_tdep: MACHINE_CPROC_SP_OFFSET = %d\n",
MACHINE_CPROC_SP_OFFSET);
#endif
fprintf_unfiltered (file,
"mips_dump_tdep: MAKE_MIPS16_ADDR = FIXME!\n");
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS16_BIG_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS16_INSTLEN = %d\n",
MIPS16_INSTLEN);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS16_LITTLE_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_DEFAULT_ABI = FIXME!\n");
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_EFI_SYMBOL_NAME = multi-arch!!\n");
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_INSTLEN = %d\n",
MIPS_INSTLEN);
fprintf_unfiltered (file,
"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);
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_REGISTER_NAMES = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: MIPS_SAVED_REGSIZE = %d\n",
MIPS_SAVED_REGSIZE);
fprintf_unfiltered (file,
"mips_dump_tdep: MSYMBOL_IS_SPECIAL = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: MSYMBOL_SIZE # %s\n",
XSTRING (MSYMBOL_SIZE (MSYM)));
fprintf_unfiltered (file,
"mips_dump_tdep: OP_LDFPR = used?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: OP_LDGPR = used?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PMON_BIG_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PMON_LITTLE_BREAKPOINT = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PRID_REGNUM = %d\n",
PRID_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: PRINT_EXTRA_FRAME_INFO # %s\n",
XSTRING (PRINT_EXTRA_FRAME_INFO (FRAME)));
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_DESC_IS_DUMMY = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_FRAME_ADJUST = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_FRAME_OFFSET = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_FRAME_REG = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_FREG_MASK = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_FREG_OFFSET = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_HIGH_ADDR = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_LOW_ADDR = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_PC_REG = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_REG_MASK = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_REG_OFFSET = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PROC_SYMBOL = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: PS_REGNUM = %d\n",
PS_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: PUSH_FP_REGNUM = %d\n",
PUSH_FP_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: RA_REGNUM = %d\n",
RA_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: REGISTER_CONVERT_FROM_TYPE # %s\n",
XSTRING (REGISTER_CONVERT_FROM_TYPE (REGNUM, VALTYPE, RAW_BUFFER)));
fprintf_unfiltered (file,
"mips_dump_tdep: REGISTER_CONVERT_TO_TYPE # %s\n",
XSTRING (REGISTER_CONVERT_TO_TYPE (REGNUM, VALTYPE, RAW_BUFFER)));
fprintf_unfiltered (file,
"mips_dump_tdep: REGISTER_NAMES = delete?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: ROUND_DOWN = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: ROUND_UP = function?\n");
#ifdef SAVED_BYTES
fprintf_unfiltered (file,
"mips_dump_tdep: SAVED_BYTES = %d\n",
SAVED_BYTES);
#endif
#ifdef SAVED_FP
fprintf_unfiltered (file,
"mips_dump_tdep: SAVED_FP = %d\n",
SAVED_FP);
#endif
#ifdef SAVED_PC
fprintf_unfiltered (file,
"mips_dump_tdep: SAVED_PC = %d\n",
SAVED_PC);
#endif
fprintf_unfiltered (file,
"mips_dump_tdep: SETUP_ARBITRARY_FRAME # %s\n",
XSTRING (SETUP_ARBITRARY_FRAME (NUMARGS, ARGS)));
fprintf_unfiltered (file,
"mips_dump_tdep: SET_PROC_DESC_IS_DUMMY = function?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: SIGFRAME_BASE = %d\n",
SIGFRAME_BASE);
fprintf_unfiltered (file,
"mips_dump_tdep: SIGFRAME_FPREGSAVE_OFF = %d\n",
SIGFRAME_FPREGSAVE_OFF);
fprintf_unfiltered (file,
"mips_dump_tdep: SIGFRAME_PC_OFF = %d\n",
SIGFRAME_PC_OFF);
fprintf_unfiltered (file,
"mips_dump_tdep: SIGFRAME_REGSAVE_OFF = %d\n",
SIGFRAME_REGSAVE_OFF);
fprintf_unfiltered (file,
"mips_dump_tdep: SIGFRAME_REG_SIZE = %d\n",
SIGFRAME_REG_SIZE);
fprintf_unfiltered (file,
"mips_dump_tdep: SKIP_TRAMPOLINE_CODE # %s\n",
XSTRING (SKIP_TRAMPOLINE_CODE (PC)));
fprintf_unfiltered (file,
"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: STAB_REG_TO_REGNUM # %s\n",
XSTRING (STAB_REG_TO_REGNUM (REGNUM)));
#ifdef STACK_END_ADDR
fprintf_unfiltered (file,
"mips_dump_tdep: STACK_END_ADDR = %d\n",
STACK_END_ADDR);
#endif
fprintf_unfiltered (file,
"mips_dump_tdep: STEP_SKIPS_DELAY # %s\n",
XSTRING (STEP_SKIPS_DELAY (PC)));
fprintf_unfiltered (file,
"mips_dump_tdep: STEP_SKIPS_DELAY_P = %d\n",
STEP_SKIPS_DELAY_P);
fprintf_unfiltered (file,
"mips_dump_tdep: STOPPED_BY_WATCHPOINT # %s\n",
XSTRING (STOPPED_BY_WATCHPOINT (WS)));
fprintf_unfiltered (file,
"mips_dump_tdep: T9_REGNUM = %d\n",
T9_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: TABULAR_REGISTER_OUTPUT = used?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: TARGET_CAN_USE_HARDWARE_WATCHPOINT # %s\n",
XSTRING (TARGET_CAN_USE_HARDWARE_WATCHPOINT (TYPE,CNT,OTHERTYPE)));
fprintf_unfiltered (file,
"mips_dump_tdep: TARGET_HAS_HARDWARE_WATCHPOINTS # %s\n",
XSTRING (TARGET_HAS_HARDWARE_WATCHPOINTS));
fprintf_unfiltered (file,
"mips_dump_tdep: TARGET_MIPS = used?\n");
fprintf_unfiltered (file,
"mips_dump_tdep: TM_PRINT_INSN_MACH # %s\n",
XSTRING (TM_PRINT_INSN_MACH));
#ifdef TRACE_CLEAR
fprintf_unfiltered (file,
"mips_dump_tdep: TRACE_CLEAR # %s\n",
XSTRING (TRACE_CLEAR (THREAD, STATE)));
#endif
#ifdef TRACE_FLAVOR
fprintf_unfiltered (file,
"mips_dump_tdep: TRACE_FLAVOR = %d\n",
TRACE_FLAVOR);
#endif
#ifdef TRACE_FLAVOR_SIZE
fprintf_unfiltered (file,
"mips_dump_tdep: TRACE_FLAVOR_SIZE = %d\n",
TRACE_FLAVOR_SIZE);
#endif
#ifdef TRACE_SET
fprintf_unfiltered (file,
"mips_dump_tdep: TRACE_SET # %s\n",
XSTRING (TRACE_SET (X,STATE)));
#endif
fprintf_unfiltered (file,
"mips_dump_tdep: UNMAKE_MIPS16_ADDR = function?\n");
#ifdef UNUSED_REGNUM
fprintf_unfiltered (file,
"mips_dump_tdep: UNUSED_REGNUM = %d\n",
UNUSED_REGNUM);
#endif
fprintf_unfiltered (file,
"mips_dump_tdep: V0_REGNUM = %d\n",
V0_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: VM_MIN_ADDRESS = %ld\n",
(long) VM_MIN_ADDRESS);
#ifdef VX_NUM_REGS
fprintf_unfiltered (file,
"mips_dump_tdep: VX_NUM_REGS = %d (used?)\n",
VX_NUM_REGS);
#endif
fprintf_unfiltered (file,
"mips_dump_tdep: ZERO_REGNUM = %d\n",
ZERO_REGNUM);
fprintf_unfiltered (file,
"mips_dump_tdep: _PROC_MAGIC_ = %d\n",
_PROC_MAGIC_);
}
void
_initialize_mips_tdep (void)
{
static struct cmd_list_element *mipsfpulist = NULL;
struct cmd_list_element *c;
gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
if (!tm_print_insn)
tm_print_insn = gdb_print_insn_mips;
add_prefix_cmd ("mips", no_class, set_mips_command,
"Various MIPS specific commands.",
&setmipscmdlist, "set mips ", 0, &setlist);
add_prefix_cmd ("mips", no_class, show_mips_command,
"Various MIPS specific commands.",
&showmipscmdlist, "show mips ", 0, &showlist);
add_show_from_set (add_set_enum_cmd ("saved-gpreg-size",
class_obscure,
size_enums,
&mips_saved_regsize_string, "\
Set size of general purpose registers saved on the stack.\n\
This option can be set to one of:\n\
32 - Force GDB to treat saved GP registers as 32-bit\n\
64 - Force GDB to treat saved GP registers as 64-bit\n\
auto - Allow GDB to use the target's default setting or autodetect the\n\
saved GP register size from information contained in the executable.\n\
(default: auto)",
&setmipscmdlist),
&showmipscmdlist);
add_show_from_set (add_set_enum_cmd ("stack-arg-size",
class_obscure,
size_enums,
&mips_stack_argsize_string, "\
Set the amount of stack space reserved for each argument.\n\
This option can be set to one of:\n\
32 - Force GDB to allocate 32-bit chunks per argument\n\
64 - Force GDB to allocate 64-bit chunks per argument\n\
auto - Allow GDB to determine the correct setting from the current\n\
target and executable (default)",
&setmipscmdlist),
&showmipscmdlist);
add_prefix_cmd ("mipsfpu", class_support, set_mipsfpu_command,
"Set use of MIPS floating-point coprocessor.",
&mipsfpulist, "set mipsfpu ", 0, &setlist);
add_cmd ("single", class_support, set_mipsfpu_single_command,
"Select single-precision MIPS floating-point coprocessor.",
&mipsfpulist);
add_cmd ("double", class_support, set_mipsfpu_double_command,
"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);
add_alias_cmd ("1", "double", class_support, 1, &mipsfpulist);
add_cmd ("none", class_support, set_mipsfpu_none_command,
"Select no MIPS floating-point coprocessor.",
&mipsfpulist);
add_alias_cmd ("off", "none", class_support, 1, &mipsfpulist);
add_alias_cmd ("no", "none", class_support, 1, &mipsfpulist);
add_alias_cmd ("0", "none", class_support, 1, &mipsfpulist);
add_cmd ("auto", class_support, set_mipsfpu_auto_command,
"Select MIPS floating-point coprocessor automatically.",
&mipsfpulist);
add_cmd ("mipsfpu", class_support, show_mipsfpu_command,
"Show current use of MIPS floating-point coprocessor target.",
&showlist);
#if !GDB_MULTI_ARCH
c = add_set_cmd ("processor", class_support, var_string_noescape,
(char *) &tmp_mips_processor_type,
"Set the type of MIPS processor in use.\n\
Set this to be able to access processor-type-specific registers.\n\
",
&setlist);
c->function.cfunc = mips_set_processor_type_command;
c = add_show_from_set (c, &showlist);
c->function.cfunc = mips_show_processor_type_command;
tmp_mips_processor_type = xstrdup (DEFAULT_MIPS_TYPE);
mips_set_processor_type_command (xstrdup (DEFAULT_MIPS_TYPE), 0);
#endif
c = add_set_cmd ("heuristic-fence-post", class_support, var_zinteger,
(char *) &heuristic_fence_post,
"\
Set the distance searched for the start of a function.\n\
If you are debugging a stripped executable, GDB needs to search through the\n\
program for the start of a function. This command sets the distance of the\n\
search. The only need to set it is when debugging a stripped executable.",
&setlist);
c->function.sfunc = reinit_frame_cache_sfunc;
add_show_from_set (c, &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);
add_show_from_set (add_set_cmd ("remote-mips64-transfers-32bit-regs",
class_obscure,
var_boolean,
(char *)&mips64_transfers_32bit_regs_p, "\
Set compatibility with MIPS targets that transfers 32 and 64 bit quantities.\n\
Use \"on\" to enable backward compatibility with older MIPS 64 GDB+target\n\
that would transfer 32 bits for some registers (e.g. SR, FSR) and\n\
64 bits for others. Use \"off\" to disable compatibility mode",
&setlist),
&showlist);
add_show_from_set (add_set_cmd ("mips", class_maintenance, var_zinteger,
&mips_debug, "Set mips debugging.\n\
When non-zero, mips specific debugging is enabled.", &setdebuglist),
&showdebuglist);
}