blob: 006bc9270cadd1cc38bec7d9fc4d2e245004739a [file] [log] [blame]
/* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
Copyright (C) 1988-2024 Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "extract-store-integer.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "value.h"
#include "cli/cli-cmds.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 "osabi.h"
#include "mips-tdep.h"
#include "block.h"
#include "reggroups.h"
#include "opcode/mips.h"
#include "elf/mips.h"
#include "elf-bfd.h"
#include "symcat.h"
#include "sim-regno.h"
#include "dis-asm.h"
#include "disasm.h"
#include "frame-unwind.h"
#include "frame-base.h"
#include "trad-frame.h"
#include "infcall.h"
#include "remote.h"
#include "target-descriptions.h"
#include "dwarf2/frame.h"
#include "user-regs.h"
#include "valprint.h"
#include "ax.h"
#include "target-float.h"
#include <algorithm>
static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
static int mips32_instruction_has_delay_slot (struct gdbarch *gdbarch,
ULONGEST inst);
static int micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32);
static int mips16_instruction_has_delay_slot (unsigned short inst,
int mustbe32);
static int mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
CORE_ADDR addr);
static int micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
CORE_ADDR addr, int mustbe32);
static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
CORE_ADDR addr, int mustbe32);
static void mips_print_float_info (struct gdbarch *, struct ui_file *,
const frame_info_ptr &, const char *);
/* A useful bit in the CP0 status register (MIPS_PS_REGNUM). */
/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */
#define ST0_FR (1 << 26)
/* The sizes of floating point registers. */
enum
{
MIPS_FPU_SINGLE_REGSIZE = 4,
MIPS_FPU_DOUBLE_REGSIZE = 8
};
enum
{
MIPS32_REGSIZE = 4,
MIPS64_REGSIZE = 8
};
static const char *mips_abi_string;
static const char *const mips_abi_strings[] = {
"auto",
"n32",
"o32",
"n64",
"o64",
"eabi32",
"eabi64",
NULL
};
/* Enum describing the different kinds of breakpoints. */
enum mips_breakpoint_kind
{
/* 16-bit MIPS16 mode breakpoint. */
MIPS_BP_KIND_MIPS16 = 2,
/* 16-bit microMIPS mode breakpoint. */
MIPS_BP_KIND_MICROMIPS16 = 3,
/* 32-bit standard MIPS mode breakpoint. */
MIPS_BP_KIND_MIPS32 = 4,
/* 32-bit microMIPS mode breakpoint. */
MIPS_BP_KIND_MICROMIPS32 = 5,
};
/* For backwards compatibility we default to MIPS16. This flag is
overridden as soon as unambiguous ELF file flags tell us the
compressed ISA encoding used. */
static const char mips_compression_mips16[] = "mips16";
static const char mips_compression_micromips[] = "micromips";
static const char *const mips_compression_strings[] =
{
mips_compression_mips16,
mips_compression_micromips,
NULL
};
static const char *mips_compression_string = mips_compression_mips16;
/* The standard register names, and all the valid aliases for them. */
struct register_alias
{
const char *name;
int regnum;
};
/* Aliases for o32 and most other ABIs. */
const struct register_alias mips_o32_aliases[] = {
{ "ta0", 12 },
{ "ta1", 13 },
{ "ta2", 14 },
{ "ta3", 15 }
};
/* Aliases for n32 and n64. */
const struct register_alias mips_n32_n64_aliases[] = {
{ "ta0", 8 },
{ "ta1", 9 },
{ "ta2", 10 },
{ "ta3", 11 }
};
/* Aliases for ABI-independent registers. */
const struct register_alias mips_register_aliases[] = {
/* The architecture manuals specify these ABI-independent names for
the GPRs. */
#define R(n) { "r" #n, n }
R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7),
R(8), R(9), R(10), R(11), R(12), R(13), R(14), R(15),
R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23),
R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31),
#undef R
/* k0 and k1 are sometimes called these instead (for "kernel
temp"). */
{ "kt0", 26 },
{ "kt1", 27 },
/* This is the traditional GDB name for the CP0 status register. */
{ "sr", MIPS_PS_REGNUM },
/* This is the traditional GDB name for the CP0 BadVAddr register. */
{ "bad", MIPS_EMBED_BADVADDR_REGNUM },
/* This is the traditional GDB name for the FCSR. */
{ "fsr", MIPS_EMBED_FP0_REGNUM + 32 }
};
const struct register_alias mips_numeric_register_aliases[] = {
#define R(n) { #n, n }
R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7),
R(8), R(9), R(10), R(11), R(12), R(13), R(14), R(15),
R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23),
R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31),
#undef R
};
#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;
static unsigned int mips_debug = 0;
/* Properties (for struct target_desc) describing the g/G packet
layout. */
#define PROPERTY_GP32 "internal: transfers-32bit-registers"
#define PROPERTY_GP64 "internal: transfers-64bit-registers"
struct target_desc *mips_tdesc_gp32;
struct target_desc *mips_tdesc_gp64;
/* The current set of options to be passed to the disassembler. */
static std::string mips_disassembler_options;
/* Implicit disassembler options for individual ABIs. These tell
libopcodes to use general-purpose register names corresponding
to the ABI we have selected, perhaps via a `set mips abi ...'
override, rather than ones inferred from the ABI set in the ELF
headers of the binary file selected for debugging. */
static const char mips_disassembler_options_o32[] = "gpr-names=32";
static const char mips_disassembler_options_n32[] = "gpr-names=n32";
static const char mips_disassembler_options_n64[] = "gpr-names=64";
const struct mips_regnum *
mips_regnum (struct gdbarch *gdbarch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
return tdep->regnum;
}
static int
mips_fpa0_regnum (struct gdbarch *gdbarch)
{
return mips_regnum (gdbarch)->fp0 + 12;
}
/* Return 1 if REGNUM refers to a floating-point general register, raw
or cooked. Otherwise return 0. */
static int
mips_float_register_p (struct gdbarch *gdbarch, int regnum)
{
int rawnum = regnum % gdbarch_num_regs (gdbarch);
return (rawnum >= mips_regnum (gdbarch)->fp0
&& rawnum < mips_regnum (gdbarch)->fp0 + 32);
}
static bool
mips_eabi (gdbarch *arch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (arch);
return (tdep->mips_abi == MIPS_ABI_EABI32 \
|| tdep->mips_abi == MIPS_ABI_EABI64);
}
static int
mips_last_fp_arg_regnum (gdbarch *arch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (arch);
return tdep->mips_last_fp_arg_regnum;
}
static int
mips_last_arg_regnum (gdbarch *arch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (arch);
return tdep->mips_last_arg_regnum;
}
static enum mips_fpu_type
mips_get_fpu_type (gdbarch *arch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (arch);
return tdep->mips_fpu_type;
}
/* Return the MIPS ABI associated with GDBARCH. */
enum mips_abi
mips_abi (struct gdbarch *gdbarch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
return tdep->mips_abi;
}
int
mips_isa_regsize (struct gdbarch *gdbarch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
/* If we know how big the registers are, use that size. */
if (tdep->register_size_valid_p)
return tdep->register_size;
/* Fall back to the previous behavior. */
return (gdbarch_bfd_arch_info (gdbarch)->bits_per_word
/ gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);
}
/* Max saved register size. */
#define MAX_MIPS_ABI_REGSIZE 8
/* Return the currently configured (or set) saved register size. */
unsigned int
mips_abi_regsize (struct gdbarch *gdbarch)
{
switch (mips_abi (gdbarch))
{
case MIPS_ABI_EABI32:
case MIPS_ABI_O32:
return 4;
case MIPS_ABI_N32:
case MIPS_ABI_N64:
case MIPS_ABI_O64:
case MIPS_ABI_EABI64:
return 8;
case MIPS_ABI_UNKNOWN:
case MIPS_ABI_LAST:
default:
internal_error (_("bad switch"));
}
}
/* MIPS16/microMIPS function addresses are odd (bit 0 is set). Here
are some functions to handle addresses associated with compressed
code including but not limited to testing, setting, or clearing
bit 0 of such addresses. */
/* Return one iff compressed code is the MIPS16 instruction set. */
static int
is_mips16_isa (struct gdbarch *gdbarch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
return tdep->mips_isa == ISA_MIPS16;
}
/* Return one iff compressed code is the microMIPS instruction set. */
static int
is_micromips_isa (struct gdbarch *gdbarch)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
return tdep->mips_isa == ISA_MICROMIPS;
}
/* Return one iff ADDR denotes compressed code. */
static int
is_compact_addr (CORE_ADDR addr)
{
return ((addr) & 1);
}
/* Return one iff ADDR denotes standard ISA code. */
static int
is_mips_addr (CORE_ADDR addr)
{
return !is_compact_addr (addr);
}
/* Return one iff ADDR denotes MIPS16 code. */
static int
is_mips16_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
{
return is_compact_addr (addr) && is_mips16_isa (gdbarch);
}
/* Return one iff ADDR denotes microMIPS code. */
static int
is_micromips_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
{
return is_compact_addr (addr) && is_micromips_isa (gdbarch);
}
/* Strip the ISA (compression) bit off from ADDR. */
static CORE_ADDR
unmake_compact_addr (CORE_ADDR addr)
{
return ((addr) & ~(CORE_ADDR) 1);
}
/* Add the ISA (compression) bit to ADDR. */
static CORE_ADDR
make_compact_addr (CORE_ADDR addr)
{
return ((addr) | (CORE_ADDR) 1);
}
/* Extern version of unmake_compact_addr; we use a separate function
so that unmake_compact_addr can be inlined throughout this file. */
CORE_ADDR
mips_unmake_compact_addr (CORE_ADDR addr)
{
return unmake_compact_addr (addr);
}
/* Functions for setting and testing a bit in a minimal symbol that
marks it as MIPS16 or microMIPS function. The MSB of the minimal
symbol's "info" field is used for this purpose.
gdbarch_elf_make_msymbol_special tests whether an ELF symbol is
"special", i.e. refers to a MIPS16 or microMIPS function, and sets
one of the "special" bits in a minimal symbol to mark it accordingly.
The test checks an ELF-private flag that is valid for true function
symbols only; for synthetic symbols such as for PLT stubs that have
no ELF-private part at all the MIPS BFD backend arranges for this
information to be carried in the asymbol's udata field instead.
msymbol_is_mips16 and msymbol_is_micromips test the "special" bit
in a minimal symbol. */
static void
mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym)
{
elf_symbol_type *elfsym = (elf_symbol_type *) sym;
unsigned char st_other;
if ((sym->flags & BSF_SYNTHETIC) == 0)
st_other = elfsym->internal_elf_sym.st_other;
else if ((sym->flags & BSF_FUNCTION) != 0)
st_other = sym->udata.i;
else
return;
if (ELF_ST_IS_MICROMIPS (st_other))
{
SET_MSYMBOL_TARGET_FLAG_MICROMIPS (msym);
CORE_ADDR fixed = CORE_ADDR (msym->unrelocated_address ()) | 1;
msym->set_unrelocated_address (unrelocated_addr (fixed));
}
else if (ELF_ST_IS_MIPS16 (st_other))
{
SET_MSYMBOL_TARGET_FLAG_MIPS16 (msym);
CORE_ADDR fixed = CORE_ADDR (msym->unrelocated_address ()) | 1;
msym->set_unrelocated_address (unrelocated_addr (fixed));
}
}
/* Return one iff MSYM refers to standard ISA code. */
static int
msymbol_is_mips (struct minimal_symbol *msym)
{
return !(MSYMBOL_TARGET_FLAG_MIPS16 (msym)
|| MSYMBOL_TARGET_FLAG_MICROMIPS (msym));
}
/* Return one iff MSYM refers to MIPS16 code. */
static int
msymbol_is_mips16 (struct minimal_symbol *msym)
{
return MSYMBOL_TARGET_FLAG_MIPS16 (msym);
}
/* Return one iff MSYM refers to microMIPS code. */
static int
msymbol_is_micromips (struct minimal_symbol *msym)
{
return MSYMBOL_TARGET_FLAG_MICROMIPS (msym);
}
/* Set the ISA bit in the main symbol too, complementing the corresponding
minimal symbol setting and reflecting the run-time value of the symbol.
The need for comes from the ISA bit having been cleared as code in
`_bfd_mips_elf_symbol_processing' separated it into the ELF symbol's
`st_other' STO_MIPS16 or STO_MICROMIPS annotation, making the values
of symbols referring to compressed code different in GDB to the values
used by actual code. That in turn makes them evaluate incorrectly in
expressions, producing results different to what the same expressions
yield when compiled into the program being debugged. */
static void
mips_make_symbol_special (struct symbol *sym, struct objfile *objfile)
{
if (sym->aclass () == LOC_BLOCK)
{
/* We are in symbol reading so it is OK to cast away constness. */
struct block *block = (struct block *) sym->value_block ();
CORE_ADDR compact_block_start;
compact_block_start = block->start () | 1;
bound_minimal_symbol msym
= lookup_minimal_symbol_by_pc (compact_block_start);
if (msym.minsym && !msymbol_is_mips (msym.minsym))
{
block->set_start (compact_block_start);
}
}
}
/* XFER a value from the big/little/left end of the register.
Depending on the size of the value it might occupy the entire
register or just part of it. Make an allowance for this, aligning
things accordingly. */
static void
mips_xfer_register (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_num, int length,
enum bfd_endian endian, gdb_byte *in,
const gdb_byte *out, int buf_offset)
{
int reg_offset = 0;
gdb_assert (reg_num >= gdbarch_num_regs (gdbarch));
/* Need to transfer the left or right part of the register, based on
the targets byte order. */
switch (endian)
{
case BFD_ENDIAN_BIG:
reg_offset = register_size (gdbarch, reg_num) - length;
break;
case BFD_ENDIAN_LITTLE:
reg_offset = 0;
break;
case BFD_ENDIAN_UNKNOWN: /* Indicates no alignment. */
reg_offset = 0;
break;
default:
internal_error (_("bad switch"));
}
if (mips_debug)
gdb_printf (gdb_stderr,
"xfer $%d, reg offset %d, buf offset %d, length %d, ",
reg_num, reg_offset, buf_offset, length);
if (mips_debug && out != NULL)
{
int i;
gdb_printf (gdb_stdlog, "out ");
for (i = 0; i < length; i++)
gdb_printf (gdb_stdlog, "%02x", out[buf_offset + i]);
}
if (in != NULL)
regcache->cooked_read_part (reg_num, reg_offset, length, in + buf_offset);
if (out != NULL)
regcache->cooked_write_part (reg_num, reg_offset, length, out + buf_offset);
if (mips_debug && in != NULL)
{
int i;
gdb_printf (gdb_stdlog, "in ");
for (i = 0; i < length; i++)
gdb_printf (gdb_stdlog, "%02x", in[buf_offset + i]);
}
if (mips_debug)
gdb_printf (gdb_stdlog, "\n");
}
/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU
compatiblity mode. A return value of 1 means that we have
physical 64-bit registers, but should treat them as 32-bit registers. */
static int
mips2_fp_compat (const frame_info_ptr &frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
/* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
meaningful. */
if (register_size (gdbarch, mips_regnum (gdbarch)->fp0) == 4)
return 0;
#if 0
/* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
in all the places we deal with FP registers. PR gdb/413. */
/* Otherwise check the FR bit in the status register - it controls
the FP compatiblity mode. If it is clear we are in compatibility
mode. */
if ((get_frame_register_unsigned (frame, MIPS_PS_REGNUM) & ST0_FR) == 0)
return 1;
#endif
return 0;
}
#define VM_MIN_ADDRESS (CORE_ADDR)0x400000
static CORE_ADDR heuristic_proc_start (struct gdbarch *, CORE_ADDR);
/* The list of available "set mips " and "show mips " commands. */
static struct cmd_list_element *setmipscmdlist = NULL;
static struct cmd_list_element *showmipscmdlist = NULL;
/* Integer registers 0 thru 31 are handled explicitly by
mips_register_name(). Processor specific registers 32 and above
are listed in the following tables. */
enum
{ NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
/* Generic MIPS. */
static const char * const mips_generic_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
"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",
};
/* Names of tx39 registers. */
static const char * const mips_tx39_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
"sr", "lo", "hi", "bad", "cause", "pc",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "", "",
"", "", "", "", "", "", "", "",
"", "", "config", "cache", "debug", "depc", "epc",
};
/* Names of registers with Linux kernels. */
static const char * const mips_linux_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
"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"
};
/* Return the name of the register corresponding to REGNO. */
static const char *
mips_register_name (struct gdbarch *gdbarch, int regno)
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
/* GPR names for all ABIs other than n32/n64. */
static const char *mips_gpr_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",
};
/* GPR names for n32 and n64 ABIs. */
static const char *mips_n32_n64_gpr_names[] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
enum mips_abi abi = mips_abi (gdbarch);
/* Map [gdbarch_num_regs .. 2*gdbarch_num_regs) onto the raw registers,
but then don't make the raw register names visible. This (upper)
range of user visible register numbers are the pseudo-registers.
This approach was adopted accommodate the following scenario:
It is possible to debug a 64-bit device using a 32-bit
programming model. In such instances, the raw registers are
configured to be 64-bits wide, while the pseudo registers are
configured to be 32-bits wide. The registers that the user
sees - the pseudo registers - match the users expectations
given the programming model being used. */
int rawnum = regno % gdbarch_num_regs (gdbarch);
if (regno < gdbarch_num_regs (gdbarch))
return "";
/* The MIPS integer registers are always mapped from 0 to 31. The
names of the registers (which reflects the conventions regarding
register use) vary depending on the ABI. */
if (0 <= rawnum && rawnum < 32)
{
if (abi == MIPS_ABI_N32 || abi == MIPS_ABI_N64)
return mips_n32_n64_gpr_names[rawnum];
else
return mips_gpr_names[rawnum];
}
else if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
return tdesc_register_name (gdbarch, rawnum);
else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
{
gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS);
if (tdep->mips_processor_reg_names[rawnum - 32])
return tdep->mips_processor_reg_names[rawnum - 32];
return "";
}
else
internal_error (_("mips_register_name: bad register number %d"), rawnum);
}
/* Return the groups that a MIPS register can be categorised into. */
static int
mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
const struct reggroup *reggroup)
{
int vector_p;
int float_p;
int raw_p;
int rawnum = regnum % gdbarch_num_regs (gdbarch);
int pseudo = regnum / gdbarch_num_regs (gdbarch);
if (reggroup == all_reggroup)
return pseudo;
vector_p = register_type (gdbarch, regnum)->is_vector ();
float_p = register_type (gdbarch, regnum)->code () == TYPE_CODE_FLT;
/* FIXME: cagney/2003-04-13: Can't yet use gdbarch_num_regs
(gdbarch), as not all architectures are multi-arch. */
raw_p = rawnum < gdbarch_num_regs (gdbarch);
if (gdbarch_register_name (gdbarch, regnum)[0] == '\0')
return 0;
if (reggroup == float_reggroup)
return float_p && pseudo;
if (reggroup == vector_reggroup)
return vector_p && pseudo;
if (reggroup == general_reggroup)
return (!vector_p && !float_p) && pseudo;
/* Save the pseudo registers. Need to make certain that any code
extracting register values from a saved register cache also uses
pseudo registers. */
if (reggroup == save_reggroup)
return raw_p && pseudo;
/* Restore the same pseudo register. */
if (reggroup == restore_reggroup)
return raw_p && pseudo;
return 0;
}
/* Return the groups that a MIPS register can be categorised into.
This version is only used if we have a target description which
describes real registers (and their groups). */
static int
mips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
const struct reggroup *reggroup)
{
int rawnum = regnum % gdbarch_num_regs (gdbarch);
int pseudo = regnum / gdbarch_num_regs (gdbarch);
int ret;
/* Only save, restore, and display the pseudo registers. Need to
make certain that any code extracting register values from a
saved register cache also uses pseudo registers.
Note: saving and restoring the pseudo registers is slightly
strange; if we have 64 bits, we should save and restore all
64 bits. But this is hard and has little benefit. */
if (!pseudo)
return 0;
ret = tdesc_register_in_reggroup_p (gdbarch, rawnum, reggroup);
if (ret != -1)
return ret;
return mips_register_reggroup_p (gdbarch, regnum, reggroup);
}
/* Map the symbol table registers which live in the range [1 *
gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw
registers. Take care of alignment and size problems. */
static enum register_status
mips_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int cookednum, gdb_byte *buf)
{
int rawnum = cookednum % gdbarch_num_regs (gdbarch);
gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
&& cookednum < 2 * gdbarch_num_regs (gdbarch));
if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
return regcache->raw_read (rawnum, buf);
else if (register_size (gdbarch, rawnum) >
register_size (gdbarch, cookednum))
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
if (tdep->mips64_transfers_32bit_regs_p)
return regcache->raw_read_part (rawnum, 0, 4, buf);
else
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
LONGEST regval;
enum register_status status;
status = regcache->raw_read (rawnum, &regval);
if (status == REG_VALID)
store_signed_integer (buf, 4, byte_order, regval);
return status;
}
}
else
internal_error (_("bad register size"));
}
static void
mips_pseudo_register_write (struct gdbarch *gdbarch,
struct regcache *regcache, int cookednum,
const gdb_byte *buf)
{
int rawnum = cookednum % gdbarch_num_regs (gdbarch);
gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
&& cookednum < 2 * gdbarch_num_regs (gdbarch));
if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
regcache->raw_write (rawnum, buf);
else if (register_size (gdbarch, rawnum) >
register_size (gdbarch, cookednum))
{
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
if (tdep->mips64_transfers_32bit_regs_p)
regcache->raw_write_part (rawnum, 0, 4, buf);
else
{
/* Sign extend the shortened version of the register prior
to placing it in the raw register. This is required for
some mips64 parts in order to avoid unpredictable behavior. */
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
LONGEST regval = extract_signed_integer (buf, 4, byte_order);
regcache_raw_write_signed (regcache, rawnum, regval);
}
}
else
internal_error (_("bad register size"));
}
static int
mips_ax_pseudo_register_collect (struct gdbarch *gdbarch,
struct agent_expr *ax, int reg)
{
int rawnum = reg % gdbarch_num_regs (gdbarch);
gdb_assert (reg >= gdbarch_num_regs (gdbarch)
&& reg < 2 * gdbarch_num_regs (gdbarch));
ax_reg_mask (ax, rawnum);
return 0;
}
static int
mips_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
struct agent_expr *ax, int reg)
{
int rawnum = reg % gdbarch_num_regs (gdbarch);
gdb_assert (reg >= gdbarch_num_regs (gdbarch)
&& reg < 2 * gdbarch_num_regs (gdbarch));
if (register_size (gdbarch, rawnum) >= register_size (gdbarch, reg))
{
ax_reg (ax, rawnum);
if (register_size (gdbarch, rawnum) > register_size (gdbarch, reg))
{
mips_gdbarch_tdep *tdep
= gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
if (!tdep->mips64_transfers_32bit_regs_p
|| gdbarch_byte_order (gdbarch) != BFD_ENDIAN_BIG)
{
ax_const_l (ax, 32);
ax_simple (ax, aop_lsh);
}
ax_const_l (ax, 32);
ax_simple (ax, aop_rsh_signed);
}
}
else
internal_error (_("bad register size"));
return 0;
}
/* Table to translate 3-bit register field to actual register number. */
static const signed char mips_reg3_to_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
/* Heuristic_proc_start may hunt through the text section for a long
time across a 2400 baud serial line. Allows the user to limit this
search. */
static int heuristic_fence_post = 0;
/* Number of bytes of storage in the actual machine representation for
register N. NOTE: This defines the pseudo register type so need to
rebuild the architecture vector. */
static bool mips64_transfers_32bit_regs_p = false;
static void
set_mips64_transfers_32bit_regs (const char *args, int from_tty,
struct cmd_list_element *c)
{
struct gdbarch_info info;
/* FIXME: cagney/2003-11-15: Should be setting a field in "info"
instead of relying on globals. Doing that would let generic code
handle the search for this specific architecture. */
if (!gdbarch_update_p (current_inferior (), info))
{
mips64_transfers_32bit_regs_p = 0;
error (_("32-bit compatibility mode not supported"));
}
}
/* Convert to/from a register and the corresponding memory value. */
/* This predicate tests for the case of an 8 byte floating point
value that is being transferred to or from a pair of floating point
registers each of which are (or are considered to be) only 4 bytes
wide. */
static int
mips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
struct type *type)
{
return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
&& register_size (gdbarch, regnum) == 4
&& mips_float_register_p (gdbarch, regnum)
&& type->code () == TYPE_CODE_FLT && type->length () == 8);
}
/* This predicate tests for the case of a value of less than 8
bytes in width that is being transfered to or from an 8 byte
general purpose register. */
static int
mips_convert_register_gpreg_case_p (struct gdbarch *gdbarch, int regnum,
struct type *type)
{
int num_regs = gdbarch_num_regs (gdbarch);
return (register_size (gdbarch, regnum) == 8
&& regnum % num_regs > 0 && regnum % num_regs < 32
&& type->length () < 8);
}
static int
mips_convert_register_p (struct gdbarch *gdbarch,
int regnum, struct type *type)
{
return (mips_convert_register_float_case_p (gdbarch, regnum, type)
|| mips_convert_register_gpreg_case_p (gdbarch, regnum, type));
}
static int
mips_register_to_value (const frame_info_ptr &frame, int regnum,
struct type *type, gdb_byte *to,
int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame);
if (mips_convert_register_float_case_p (gdbarch, regnum, type))
{
get_frame_register (frame, regnum + 0, to + 4);
get_frame_register (frame, regnum + 1, to + 0);
if (!get_frame_register_bytes (next_frame, regnum + 0, 0, { to + 4, 4 },
optimizedp, unavailablep))
return 0;
if (!get_frame_register_bytes (next_frame, regnum + 1, 0, { to + 0, 4 },
optimizedp, unavailablep))
return 0;
*optimizedp = *unavailablep = 0;
return 1;
}
else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
{
size_t len = type->length ();
CORE_ADDR offset;
offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 - len : 0;
if (!get_frame_register_bytes (next_frame, regnum, offset, { to, len },
optimizedp, unavailablep))
return 0;
*optimizedp = *unavailablep = 0;
return 1;
}
else
{
internal_error (_("mips_register_to_value: unrecognized case"));
}
}
static void
mips_value_to_register (const frame_info_ptr &frame, int regnum,
struct type *type, const gdb_byte *from)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
if (mips_convert_register_float_case_p (gdbarch, regnum, type))
{
auto from_view = gdb::make_array_view (from, 8);
frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame);
put_frame_register (next_frame, regnum, from_view.slice (4));
put_frame_register (next_frame, regnum + 1, from_view.slice (0, 4));
}
else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
{
gdb_byte fill[8];
size_t len = type->length ();
frame_info_ptr next_frame = get_next_frame_sentinel_okay (frame);
/* Sign extend values, irrespective of type, that are stored to
a 64-bit general purpose register. (32-bit unsigned values
are stored as signed quantities within a 64-bit register.
When performing an operation, in compiled code, that combines
a 32-bit unsigned value with a signed 64-bit value, a type
conversion is first performed that zeroes out the high 32 bits.) */
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
if (from[0] & 0x80)
store_signed_integer (fill, 8, BFD_ENDIAN_BIG, -1);
else
store_signed_integer (fill, 8, BFD_ENDIAN_BIG, 0);
put_frame_register_bytes (next_frame, regnum, 0, {fill, 8 - len});
put_frame_register_bytes (next_frame, regnum, 8 - len, {from, len});
}
else
{
if (from[len-1] & 0x80)
store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, -1);
else
store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, 0);
put_frame_register_bytes (next_frame, regnum, 0, {from, len});
put_frame_register_bytes (next_frame, regnum, len, {fill, 8 - len});
}
}
else
{
internal_error (_("mips_value_to_register: unrecognized case"));
}
}
/* Return the GDB type object for the "standard" data type of data in
register REG. */
static struct type *
mips_register_type (struct gdbarch *gdbarch, int regnum)
{
gdb_assert (regnum >= 0 && regnum < 2 * gdbarch_num_regs (gdbarch));
if (mips_float_register_p (gdbarch, regnum))
{
/* The floating-point registers raw, or cooked, always match
mips_isa_regsize(), and also map 1:1, byte for byte. */
if (mips_isa_regsize (gdbarch) == 4)
return builtin_type (gdbarch)->builtin_float;
else
return builtin_type (gdbarch)->builtin_double;
}
else if (regnum < gdbarch_num_regs (gdbarch))
{
/* The raw or ISA registers. These are all sized according to
the ISA regsize. */
if (mips_isa_regsize (gdbarch) == 4)
return builtin_type (gdbarch)->builtin_int32;
else
return builtin_type (gdbarch)->builtin_int64;
}
else
{
int rawnum = regnum - gdbarch_num_regs (gdbarch);
mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
/* The cooked or ABI registers. These are sized according to
the ABI (with a few complications). */
if (rawnum == mips_regnum (gdbarch)->fp_control_status
|| rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
return builtin_type (gdbarch)->builtin_int32;
else if (gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
&& rawnum >= MIPS_FIRST_EMBED_REGNUM
&& rawnum <= MIPS_LAST_EMBED_REGNUM)
/* The pseudo/cooked view of the embedded registers is always
32-bit. The raw view is handled below. */
return builtin_type (gdbarch)->builtin_int32;
else if (tdep->mips64_transfers_32bit_regs_p)
/* The target, while possibly using a 64-bit register buffer,
is only transfering 32-bits of each integer register.
Reflect this in the cooked/pseudo (ABI) register value. */
return builtin_type (gdbarch)->builtin_int32;
else if (mips_abi_regsize (gdbarch) == 4)
/* The ABI is restricted to 32-bit registers (the ISA could be
32- or 64-bit). */
return builtin_type (gdbarch)->builtin_int32;
else
/* 64-bit ABI. */
return builtin_type (gdbarch)->builtin_int64;
}
}
/* Return the GDB type for the pseudo register REGNUM, which is the
ABI-level view. This function is only called if there is a target
description which includes registers, so we know precisely the
types of hardware registers. */
static struct type *
mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
const int num_regs = gdbarch_num_regs (gdbarch);
int rawnum = regnum % num_regs;
struct type *rawtype;
gdb_assert (regnum >= num_regs && regnum < 2 * num_regs);
/* Absent registers are still absent. */
rawtype = gdbarch_register_type (gdbarch, rawnum);
if (rawtype->length () == 0)
return rawtype;
/* Present the floating point registers however the hardware did;
do not try to convert between FPU layouts. */
if (mips_float_register_p (gdbarch, rawnum))
return rawtype;
/* Floating-point control registers are always 32-bit even though for
backwards compatibility reasons 64-bit targets will transfer them
as 64-bit quantities even if using XML descriptions. */
if (rawnum == mips_regnum (gdbarch)->fp_control_status
|| rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
return builtin_type (gdbarch)->builtin_int32;
/* Use pointer types for registers if we can. For n32 we can not,
since we do not have a 64-bit pointer type. */
if (mips_abi_regsize (gdbarch)
== builtin_type (gdbarch)->builtin_data_ptr->length())
{
if (rawnum == MIPS_SP_REGNUM
|| rawnum == mips_regnum (gdbarch)->badvaddr)
return builtin_type (gdbarch)->builtin_data_ptr;
else if (rawnum == mips_regnum (gdbarch)->pc)
return builtin_type (gdbarch)->builtin_func_ptr;
}
if (mips_abi_regsize (gdbarch) == 4 && rawtype->length () == 8
&& ((rawnum >= MIPS_ZERO_REGNUM && rawnum <= MIPS_PS_REGNUM)
|| rawnum == mips_regnum (gdbarch)->lo
|| rawnum == mips_regnum (gdbarch)->hi
|| rawnum == mips_regnum (gdbarch)->badvaddr
|| rawnum == mips_regnum (gdbarch)->cause
|| rawnum == mips_regnum (gdbarch)->pc
|| (mips_regnum (gdbarch)->dspacc != -1
&& rawnum >= mips_regnum (gdbarch)->dspacc
&& rawnum < mips_regnum (gdbarch)->dspacc + 6)))
return builtin_type (gdbarch)->builtin_int32;
/* The pseudo/cooked view of embedded registers is always
32-bit, even if the target transfers 64-bit values for them.
New targets relying on XML descriptions should only transfer
the necessary 32 bits, but older versions of GDB expected 64,
so allow the target to provide 64 bits without interfering
with the displayed type. */
if (gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
&& rawnum >= MIPS_FIRST_EMBED_REGNUM
&& rawnum <= MIPS_LAST_EMBED_REGNUM)
return builtin_type (gdbarch)->builtin_int32;
/* For all other registers, pass through the hardware type. */
return rawtype;
}
/* Should the upper word of 64-bit addresses be zeroed? */
static enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO;
static int
mips_mask_address_p (mips_gdbarch_tdep *tdep)
{
switch (mask_address_var)
{
case AUTO_BOOLEAN_TRUE:
return 1;
case AUTO_BOOLEAN_FALSE:
return 0;
break;
case AUTO_BOOLEAN_AUTO:
return tdep->default_mask_address_p;
default:
internal_error (_("mips_mask_address_p: bad switch"));
return -1;
}
}
static void
show_mask_address (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
const char *additional_text = "";
if (mask_address_var == AUTO_BOOLEAN_AUTO)
{
if (gdbarch_bfd_arch_info (current_inferior ()->arch ())->arch
!= bfd_arch_mips)
additional_text = _(" (current architecture is not MIPS)");
else
{
mips_gdbarch_tdep *tdep
= gdbarch_tdep<mips_gdbarch_tdep> (current_inferior ()->arch ());
if (mips_mask_address_p (tdep))
additional_text = _(" (currently \"on\")");
else
additional_text = _(" (currently \"off\")");
}
}
gdb_printf (file, _("Zeroing of upper 32 bits of 64-bit addresses is \"%s\"%s.\n"),
value, additional_text);
}
/* Tell if the program counter value in MEMADDR is in a standard ISA
function. */
int
mips_pc_is_mips (CORE_ADDR memaddr)
{
/* Flags indicating that this is a MIPS16 or microMIPS function is
stored by elfread.c in the high bit of the info field. Use this
to decide if the function is standard MIPS. Otherwise if bit 0
of the address is clear, then this is a standard MIPS function. */
bound_minimal_symbol sym
= lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips (sym.minsym);
else
return is_mips_addr (memaddr);
}
/* Tell if the program counter value in MEMADDR is in a MIPS16 function. */
int
mips_pc_is_mips16 (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
/* A flag indicating that this is a MIPS16 function is stored by
elfread.c in the high bit of the info field. Use this to decide
if the function is MIPS16. Otherwise if bit 0 of the address is
set, then ELF file flags will tell if this is a MIPS16 function. */
bound_minimal_symbol sym
= lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_mips16 (sym.minsym);
else
return is_mips16_addr (gdbarch, memaddr);
}
/* Tell if the program counter value in MEMADDR is in a microMIPS function. */
int
mips_pc_is_micromips (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
/* A flag indicating that this is a microMIPS function is stored by
elfread.c in the high bit of the info field. Use this to decide
if the function is microMIPS. Otherwise if bit 0 of the address
is set, then ELF file flags will tell if this is a microMIPS
function. */
bound_minimal_symbol sym
= lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
return msymbol_is_micromips (sym.minsym);
else
return is_micromips_addr (gdbarch, memaddr);
}
/* Tell the ISA type of the function the program counter value in MEMADDR
is in. */
static enum mips_isa
mips_pc_isa (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
/* A flag indicating that this is a MIPS16 or a microMIPS function
is stored by elfread.c in the high bit of the info field. Use
this to decide if the function is MIPS16 or microMIPS or normal
MIPS. Otherwise if bit 0 of the address is set, then ELF file
flags will tell if this is a MIPS16 or a microMIPS function. */
bound_minimal_symbol sym
= lookup_minimal_symbol_by_pc (make_compact_addr (memaddr));
if (sym.minsym)
{
if (msymbol_is_micromips (sym.minsym))
return ISA_MICROMIPS;
else if (msymbol_is_mips16 (sym.minsym))
return ISA_MIPS16;
else
return ISA_MIPS;
}
else
{
if (is_mips_addr (memaddr))
return ISA_MIPS;
else if (is_micromips_addr (gdbarch, memaddr))
return ISA_MICROMIPS;
else
return ISA_MIPS16;
}
}
/* Set the ISA bit correctly in the PC, used by DWARF-2 machinery.
The need for comes from the ISA bit having been cleared, making
addresses in FDE, range records, etc. referring to compressed code
different to those in line information, the symbol table and finally
the PC register. That in turn confuses many operations. */
static CORE_ADDR
mips_adjust_dwarf2_addr (CORE_ADDR pc)
{
pc = unmake_compact_addr (pc);
return mips_pc_is_mips (pc) ? pc : make_compact_addr (pc);
}
/* Recalculate the line record requested so that the resulting PC has
the ISA bit set correctly, used by DWARF-2 machinery. The need for
this adjustment comes from some records associated with compressed
code having the ISA bit cleared, most notably at function prologue
ends. The ISA bit is in this context retrieved from the minimal
symbol covering the address requested, which in turn has been
constructed from the binary's symbol table rather than DWARF-2
information. The correct setting of the ISA bit is required for
breakpoint addresses to correctly match against the stop PC.
As line entries can specify relative address adjustments we need to
keep track of the absolute value of the last line address recorded
in line information, so that we can calculate the actual address to
apply the ISA bit adjustment to. We use PC for this tracking and
keep the original address there.
As such relative address adjustments can be odd within compressed
code we need to keep track of the last line address with the ISA
bit adjustment applied too, as the original address may or may not
have had the ISA bit set. We use ADJ_PC for this tracking and keep
the adjusted address there.
For relative address adjustments we then use these variables to
calculate the address intended by line information, which will be
PC-relative, and return an updated adjustment carrying ISA bit
information, which will be ADJ_PC-relative. For absolute address
adjustments we just return the same address that we store in ADJ_PC
too.
As the first line entry can be relative to an implied address value
of 0 we need to have the initial address set up that we store in PC
and ADJ_PC. This is arranged with a call from `dwarf_decode_lines_1'
that sets PC to 0 and ADJ_PC accordingly, usually 0 as well. */
static CORE_ADDR
mips_adjust_dwarf2_line (CORE_ADDR addr, int rel)
{
static CORE_ADDR adj_pc;
static CORE_ADDR pc;
CORE_ADDR isa_pc;
pc = rel ? pc + addr : addr;
isa_pc = mips_adjust_dwarf2_addr (pc);
addr = rel ? isa_pc - adj_pc : isa_pc;
adj_pc = isa_pc;
return addr;
}
/* Various MIPS16 thunk (aka stub or trampoline) names. */
static const char mips_str_mips16_call_stub[] = "__mips16_call_stub_";
static const char mips_str_mips16_ret_stub[] = "__mips16_ret_";
static const char mips_str_call_fp_stub[] = "__call_stub_fp_";
static const char mips_str_call_stub[] = "__call_stub_";
static const char mips_str_fn_stub[] = "__fn_stub_";
/* This is used as a PIC thunk prefix. */
static const char mips_str_pic[] = ".pic.";
/* Return non-zero if the PC is inside a call thunk (aka stub or
trampoline) that should be treated as a temporary frame. */
static int
mips_in_frame_stub (CORE_ADDR pc)
{
CORE_ADDR start_addr;
const char *name;
/* Find the starting address of the function containing the PC. */
if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
return 0;
/* If the PC is in __mips16_call_stub_*, this is a call/return stub. */
if (startswith (name, mips_str_mips16_call_stub))
return 1;
/* If the PC is in __call_stub_*, this is a call/return or a call stub. */
if (startswith (name, mips_str_call_stub))
return 1;
/* If the PC is in __fn_stub_*, this is a call stub. */
if (startswith (name, mips_str_fn_stub))
return 1;
return 0; /* Not a stub. */
}
/* MIPS believes that the PC has a sign extended value. Perhaps the
all registers should be sign extended for simplicity? */
static CORE_ADDR
mips_read_pc (readable_regcache *regcache)
{
int regnum = gdbarch_pc_regnum (regcache->arch ());
LONGEST pc;
regcache->cooked_read (regnum, &pc);
return pc;
}
static CORE_ADDR
mips_unwind_pc (struct gdbarch *gdbarch, const frame_info_ptr &next_frame)
{
CORE_ADDR pc;
pc = frame_unwind_register_signed (next_frame, gdbarch_pc_regnum (gdbarch));
/* macro/2012-04-20: This hack skips over MIPS16 call thunks as
intermediate frames. In this case we can get the caller's address
from $ra, or if $ra contains an address within a thunk as well, then
it must be in the return path of __mips16_call_stub_{s,d}{f,c}_{0..10}
and thus the caller's address is in $s2. */
if (frame_relative_level (next_frame) >= 0 && mips_in_frame_stub (pc))
{
pc = frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM);
if (mips_in_frame_stub (pc))
pc = frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
}
return pc;
}
static CORE_ADDR
mips_unwind_sp (struct gdbarch *gdbarch, const frame_info_ptr &next_frame)
{
return frame_unwind_register_signed
(next_frame, gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM);
}
/* Assuming THIS_FRAME is a dummy, return the frame ID of that
dummy frame. The frame ID's base needs to match the TOS value
saved by save_dummy_frame_tos(), and the PC match the dummy frame's
breakpoint. */
static struct frame_id
mips_dummy_id (struct gdbarch *gdbarch, const frame_info_ptr &this_frame)
{
return frame_id_build
(get_frame_register_signed (this_frame,
gdbarch_num_regs (gdbarch)
+ MIPS_SP_REGNUM),
get_frame_pc (this_frame));
}
/* Implement the "write_pc" gdbarch method. */
void
mips_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
int regnum = gdbarch_pc_regnum (regcache->arch ());
regcache_cooked_write_unsigned (regcache, regnum, pc);
}
/* Fetch and return instruction from the specified location. Handle
MIPS16/microMIPS as appropriate. */
static ULONGEST
mips_fetch_instruction (struct gdbarch *gdbarch,
enum mips_isa isa, CORE_ADDR addr, int *errp)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[MIPS_INSN32_SIZE];
int instlen;
int err;
switch (isa)
{
case ISA_MICROMIPS:
case ISA_MIPS16:
instlen = MIPS_INSN16_SIZE;
addr = unmake_compact_addr (addr);
break;
case ISA_MIPS:
instlen = MIPS_INSN32_SIZE;
break;
default:
internal_error (_("invalid ISA"));
break;
}
err = target_read_memory (addr, buf, instlen);
if (errp != NULL)
*errp = err;
if (err != 0)
{
if (errp == NULL)
memory_error (TARGET_XFER_E_IO, addr);
return 0;
}
return extract_unsigned_integer (buf, instlen, byte_order);
}
/* These are the fields of 32 bit mips instructions. */
#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)
/* MicroMIPS instruction fields. */
#define micromips_op(x) ((x) >> 10)
/* 16-bit/32-bit-high-part instruction formats, B and S refer to the lowest
bit and the size respectively of the field extracted. */
#define b0s4_imm(x) ((x) & 0xf)
#define b0s5_imm(x) ((x) & 0x1f)
#define b0s5_reg(x) ((x) & 0x1f)
#define b0s7_imm(x) ((x) & 0x7f)
#define b0s10_imm(x) ((x) & 0x3ff)
#define b1s4_imm(x) (((x) >> 1) & 0xf)
#define b1s9_imm(x) (((x) >> 1) & 0x1ff)
#define b2s3_cc(x) (((x) >> 2) & 0x7)
#define b4s2_regl(x) (((x) >> 4) & 0x3)
#define b5s5_op(x) (((x) >> 5) & 0x1f)
#define b5s5_reg(x) (((x) >> 5) & 0x1f)
#define b6s4_op(x) (((x) >> 6) & 0xf)
#define b7s3_reg(x) (((x) >> 7) & 0x7)
/* 32-bit instruction formats, B and S refer to the lowest bit and the size
respectively of the field extracted. */
#define b0s6_op(x) ((x) & 0x3f)
#define b0s11_op(x) ((x) & 0x7ff)
#define b0s12_imm(x) ((x) & 0xfff)
#define b0s16_imm(x) ((x) & 0xffff)
#define b0s26_imm(x) ((x) & 0x3ffffff)
#define b6s10_ext(x) (((x) >> 6) & 0x3ff)
#define b11s5_reg(x) (((x) >> 11) & 0x1f)
#define b12s4_op(x) (((x) >> 12) & 0xf)
/* Return the size in bytes of the instruction INSN encoded in the ISA
instruction set. */
static int
mips_insn_size (enum mips_isa isa, ULONGEST insn)
{
switch (isa)
{
case ISA_MICROMIPS:
if ((micromips_op (insn) & 0x4) == 0x4
|| (micromips_op (insn) & 0x7) == 0x0)
return 2 * MIPS_INSN16_SIZE;
else
return MIPS_INSN16_SIZE;
case ISA_MIPS16:
if ((insn & 0xf800) == 0xf000)
return 2 * MIPS_INSN16_SIZE;
else
return MIPS_INSN16_SIZE;
case ISA_MIPS:
return MIPS_INSN32_SIZE;
}
internal_error (_("invalid ISA"));
}
static LONGEST
mips32_relative_offset (ULONGEST inst)
{
return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
}
/* Determine the address of the next instruction executed after the INST
floating condition branch instruction at PC. COUNT specifies the
number of the floating condition bits tested by the branch. */
static CORE_ADDR
mips32_bc1_pc (struct gdbarch *gdbarch, struct regcache *regcache,
ULONGEST inst, CORE_ADDR pc, int count)
{
int fcsr = mips_regnum (gdbarch)->fp_control_status;
int cnum = (itype_rt (inst) >> 2) & (count - 1);
int tf = itype_rt (inst) & 1;
int mask = (1 << count) - 1;
ULONGEST fcs;
int cond;
if (fcsr == -1)
/* No way to handle; it'll most likely trap anyway. */
return pc;
fcs = regcache_raw_get_unsigned (regcache, fcsr);
cond = ((fcs >> 24) & 0xfe) | ((fcs >> 23) & 0x01);
if (((cond >> cnum) & mask) != mask * !tf)
pc += mips32_relative_offset (inst);
else
pc += 4;
return pc;
}
/* Return nonzero if the gdbarch is an Octeon series. */
static int
is_octeon (struct gdbarch *gdbarch)
{
const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
return (info->mach == bfd_mach_mips_octeon
|| info->mach == bfd_mach_mips_octeonp
|| info->mach == bfd_mach_mips_octeon2);
}
/* Return true if the OP represents the Octeon's BBIT instruction. */
static int
is_octeon_bbit_op (int op, struct gdbarch *gdbarch)
{
if (!is_octeon (gdbarch))
return 0;
/* BBIT0 is encoded as LWC2: 110 010. */
/* BBIT032 is encoded as LDC2: 110 110. */
/* BBIT1 is encoded as SWC2: 111 010. */
/* BBIT132 is encoded as SDC2: 111 110. */
if (op == 50 || op == 54 || op == 58 || op == 62)
return 1;
return 0;
}
/* Determine where to set a single step breakpoint while considering
branch prediction. */
static CORE_ADDR
mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
struct gdbarch *gdbarch = regcache->arch ();
unsigned long inst;
int op;
inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
op = itype_op (inst);
if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch
instruction. */
{
if (op >> 2 == 5)
/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
{
switch (op & 0x03)
{
case 0: /* BEQL */
goto equal_branch;
case 1: /* BNEL */
goto neq_branch;
case 2: /* BLEZL */
goto less_branch;
case 3: /* BGTZL */
goto greater_branch;
default:
pc += 4;
}
}
else if (op == 17 && itype_rs (inst) == 8)
/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 1);
else if (op == 17 && itype_rs (inst) == 9
&& (itype_rt (inst) & 2) == 0)
/* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 2);
else if (op == 17 && itype_rs (inst) == 10
&& (itype_rt (inst) & 2) == 0)
/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 4);
else if (op == 29)
/* JALX: 011101 */
/* The new PC will be alternate mode. */
{
unsigned long reg;
reg = jtype_target (inst) << 2;
/* Add 1 to indicate 16-bit mode -- invert ISA mode. */
pc = ((pc + 4) & ~(CORE_ADDR) 0x0fffffff) + reg + 1;
}
else if (is_octeon_bbit_op (op, gdbarch))
{
int bit, branch_if;
branch_if = op == 58 || op == 62;
bit = itype_rt (inst);
/* Take into account the *32 instructions. */
if (op == 54 || op == 62)
bit += 32;
if (((regcache_raw_get_signed (regcache,
itype_rs (inst)) >> bit) & 1)
== branch_if)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* After the delay slot. */
}
else
pc += 4; /* Not a branch, next instruction is easy. */
}
else
{ /* This gets way messy. */
/* Further subdivide into SPECIAL, REGIMM and other. */
switch (op & 0x07) /* Extract bits 28,27,26. */
{
case 0: /* SPECIAL */
op = rtype_funct (inst);
switch (op)
{
case 8: /* JR */
case 9: /* JALR */
/* Set PC to that address. */
pc = regcache_raw_get_signed (regcache, rtype_rs (inst));
break;
case 12: /* SYSCALL */
{
mips_gdbarch_tdep *tdep
= gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
if (tdep->syscall_next_pc != NULL)
pc = tdep->syscall_next_pc (get_current_frame ());
else
pc += 4;
}
break;
default:
pc += 4;
}
break; /* end SPECIAL */
case 1: /* REGIMM */
{
op = itype_rt (inst); /* branch condition */
switch (op)
{
case 0: /* BLTZ */
case 2: /* BLTZL */
case 16: /* BLTZAL */
case 18: /* BLTZALL */
less_branch:
if (regcache_raw_get_signed (regcache, itype_rs (inst)) < 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
break;
case 1: /* BGEZ */
case 3: /* BGEZL */
case 17: /* BGEZAL */
case 19: /* BGEZALL */
if (regcache_raw_get_signed (regcache, itype_rs (inst)) >= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8; /* after the delay slot */
break;
case 0x1c: /* BPOSGE32 */
case 0x1e: /* BPOSGE64 */
pc += 4;
if (itype_rs (inst) == 0)
{
unsigned int pos = (op & 2) ? 64 : 32;
int dspctl = mips_regnum (gdbarch)->dspctl;
if (dspctl == -1)
/* No way to handle; it'll most likely trap anyway. */
break;
if ((regcache_raw_get_unsigned (regcache,
dspctl) & 0x7f) >= pos)
pc += mips32_relative_offset (inst);
else
pc += 4;
}
break;
/* All of the other instructions in the REGIMM category */
default:
pc += 4;
}
}
break; /* end REGIMM */
case 2: /* J */
case 3: /* JAL */
{
unsigned long reg;
reg = jtype_target (inst) << 2;
/* Upper four bits get never changed... */
pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff);
}
break;
case 4: /* BEQ, BEQL */
equal_branch:
if (regcache_raw_get_signed (regcache, itype_rs (inst)) ==
regcache_raw_get_signed (regcache, itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 5: /* BNE, BNEL */
neq_branch:
if (regcache_raw_get_signed (regcache, itype_rs (inst)) !=
regcache_raw_get_signed (regcache, itype_rt (inst)))
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 6: /* BLEZ, BLEZL */
if (regcache_raw_get_signed (regcache, itype_rs (inst)) <= 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
case 7:
default:
greater_branch: /* BGTZ, BGTZL */
if (regcache_raw_get_signed (regcache, itype_rs (inst)) > 0)
pc += mips32_relative_offset (inst) + 4;
else
pc += 8;
break;
} /* switch */
} /* else */
return pc;
} /* mips32_next_pc */
/* Extract the 7-bit signed immediate offset from the microMIPS instruction
INSN. */
static LONGEST
micromips_relative_offset7 (ULONGEST insn)
{
return ((b0s7_imm (insn) ^ 0x40) - 0x40) << 1;
}
/* Extract the 10-bit signed immediate offset from the microMIPS instruction
INSN. */
static LONGEST
micromips_relative_offset10 (ULONGEST insn)
{
return ((b0s10_imm (insn) ^ 0x200) - 0x200) << 1;
}
/* Extract the 16-bit signed immediate offset from the microMIPS instruction
INSN. */
static LONGEST
micromips_relative_offset16 (ULONGEST insn)
{
return ((b0s16_imm (insn) ^ 0x8000) - 0x8000) << 1;
}
/* Return the size in bytes of the microMIPS instruction at the address PC. */
static int
micromips_pc_insn_size (struct gdbarch *gdbarch, CORE_ADDR pc)
{
ULONGEST insn;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
return mips_insn_size (ISA_MICROMIPS, insn);
}
/* Calculate the address of the next microMIPS instruction to execute
after the INSN coprocessor 1 conditional branch instruction at the
address PC. COUNT denotes the number of coprocessor condition bits
examined by the branch. */
static CORE_ADDR
micromips_bc1_pc (struct gdbarch *gdbarch, struct regcache *regcache,
ULONGEST insn, CORE_ADDR pc, int count)
{
int fcsr = mips_regnum (gdbarch)->fp_control_status;
int cnum = b2s3_cc (insn >> 16) & (count - 1);
int tf = b5s5_op (insn >> 16) & 1;
int mask = (1 << count) - 1;
ULONGEST fcs;
int cond;
if (fcsr == -1)
/* No way to handle; it'll most likely trap anyway. */
return pc;
fcs = regcache_raw_get_unsigned (regcache, fcsr);
cond = ((fcs >> 24) & 0xfe) | ((fcs >> 23) & 0x01);
if (((cond >> cnum) & mask) != mask * !tf)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
return pc;
}
/* Calculate the address of the next microMIPS instruction to execute
after the instruction at the address PC. */
static CORE_ADDR
micromips_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
struct gdbarch *gdbarch = regcache->arch ();
ULONGEST insn;
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
pc += MIPS_INSN16_SIZE;
switch (mips_insn_size (ISA_MICROMIPS, insn))
{
/* 32-bit instructions. */
case 2 * MIPS_INSN16_SIZE:
insn <<= 16;
insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
pc += MIPS_INSN16_SIZE;
switch (micromips_op (insn >> 16))
{
case 0x00: /* POOL32A: bits 000000 */
switch (b0s6_op (insn))
{
case 0x3c: /* POOL32Axf: bits 000000 ... 111100 */
switch (b6s10_ext (insn))
{
case 0x3c: /* JALR: 000000 0000111100 111100 */
case 0x7c: /* JALR.HB: 000000 0001111100 111100 */
case 0x13c: /* JALRS: 000000 0100111100 111100 */
case 0x17c: /* JALRS.HB: 000000 0101111100 111100 */
pc = regcache_raw_get_signed (regcache,
b0s5_reg (insn >> 16));
break;
case 0x22d: /* SYSCALL: 000000 1000101101 111100 */
{
mips_gdbarch_tdep *tdep
= gdbarch_tdep<mips_gdbarch_tdep> (gdbarch);
if (tdep->syscall_next_pc != NULL)
pc = tdep->syscall_next_pc (get_current_frame ());
}
break;
}
break;
}
break;
case 0x10: /* POOL32I: bits 010000 */
switch (b5s5_op (insn >> 16))
{
case 0x00: /* BLTZ: bits 010000 00000 */
case 0x01: /* BLTZAL: bits 010000 00001 */
case 0x11: /* BLTZALS: bits 010000 10001 */
if (regcache_raw_get_signed (regcache,
b0s5_reg (insn >> 16)) < 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x02: /* BGEZ: bits 010000 00010 */
case 0x03: /* BGEZAL: bits 010000 00011 */
case 0x13: /* BGEZALS: bits 010000 10011 */
if (regcache_raw_get_signed (regcache,
b0s5_reg (insn >> 16)) >= 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x04: /* BLEZ: bits 010000 00100 */
if (regcache_raw_get_signed (regcache,
b0s5_reg (insn >> 16)) <= 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x05: /* BNEZC: bits 010000 00101 */
if (regcache_raw_get_signed (regcache,
b0s5_reg (insn >> 16)) != 0)
pc += micromips_relative_offset16 (insn);
break;
case 0x06: /* BGTZ: bits 010000 00110 */
if (regcache_raw_get_signed (regcache,
b0s5_reg (insn >> 16)) > 0)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x07: /* BEQZC: bits 010000 00111 */
if (regcache_raw_get_signed (regcache,
b0s5_reg (insn >> 16)) == 0)
pc += micromips_relative_offset16 (insn);
break;
case 0x14: /* BC2F: bits 010000 10100 xxx00 */
case 0x15: /* BC2T: bits 010000 10101 xxx00 */
if (((insn >> 16) & 0x3) == 0x0)
/* BC2F, BC2T: don't know how to handle these. */
break;
break;
case 0x1a: /* BPOSGE64: bits 010000 11010 */
case 0x1b: /* BPOSGE32: bits 010000 11011 */
{
unsigned int pos = (b5s5_op (insn >> 16) & 1) ? 32 : 64;
int dspctl = mips_regnum (gdbarch)->dspctl;
if (dspctl == -1)
/* No way to handle; it'll most likely trap anyway. */
break;
if ((regcache_raw_get_unsigned (regcache,
dspctl) & 0x7f) >= pos)
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
}
break;
case 0x1c: /* BC1F: bits 010000 11100 xxx00 */
/* BC1ANY2F: bits 010000 11100 xxx01 */
case 0x1d: /* BC1T: bits 010000 11101 xxx00 */
/* BC1ANY2T: bits 010000 11101 xxx01 */
if (((insn >> 16) & 0x2) == 0x0)
pc = micromips_bc1_pc (gdbarch, regcache, insn, pc,
((insn >> 16) & 0x1) + 1);
break;
case 0x1e: /* BC1ANY4F: bits 010000 11110 xxx01 */
case 0x1f: /* BC1ANY4T: bits 010000 11111 xxx01 */
if (((insn >> 16) & 0x3) == 0x1)
pc = micromips_bc1_pc (gdbarch, regcache, insn, pc, 4);
break;
}
break;
case 0x1d: /* JALS: bits 011101 */
case 0x35: /* J: bits 110101 */
case 0x3d: /* JAL: bits 111101 */
pc = ((pc | 0x7fffffe) ^ 0x7fffffe) | (b0s26_imm (insn) << 1);
break;
case 0x25: /* BEQ: bits 100101 */
if (regcache_raw_get_signed (regcache, b0s5_reg (insn >> 16))
== regcache_raw_get_signed (regcache, b5s5_reg (insn >> 16)))
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x2d: /* BNE: bits 101101 */
if (regcache_raw_get_signed (regcache, b0s5_reg (insn >> 16))
!= regcache_raw_get_signed (regcache, b5s5_reg (insn >> 16)))
pc += micromips_relative_offset16 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
break;
case 0x3c: /* JALX: bits 111100 */
pc = ((pc | 0xfffffff) ^ 0xfffffff) | (b0s26_imm (insn) << 2);
break;
}
break;
/* 16-bit instructions. */
case MIPS_INSN16_SIZE:
switch (micromips_op (insn))
{
case 0x11: /* POOL16C: bits 010001 */
if ((b5s5_op (insn) & 0x1c) == 0xc)
/* JR16, JRC, JALR16, JALRS16: 010001 011xx */
pc = regcache_raw_get_signed (regcache, b0s5_reg (insn));
else if (b5s5_op (insn) == 0x18)
/* JRADDIUSP: bits 010001 11000 */
pc = regcache_raw_get_signed (regcache, MIPS_RA_REGNUM);
break;
case 0x23: /* BEQZ16: bits 100011 */
{
int rs = mips_reg3_to_reg[b7s3_reg (insn)];
if (regcache_raw_get_signed (regcache, rs) == 0)
pc += micromips_relative_offset7 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
}
break;
case 0x2b: /* BNEZ16: bits 101011 */
{
int rs = mips_reg3_to_reg[b7s3_reg (insn)];
if (regcache_raw_get_signed (regcache, rs) != 0)
pc += micromips_relative_offset7 (insn);
else
pc += micromips_pc_insn_size (gdbarch, pc);
}
break;
case 0x33: /* B16: bits 110011 */
pc += micromips_relative_offset10 (insn);
break;
}
break;
}
return pc;
}
/* Decoding the next place to set a breakpoint is irregular for the
mips 16 variant, but fortunately, there fewer instructions. We have
to cope ith extensions for 16 bit instructions and a pair of actual
32 bit instructions. We dont want to set a single step instruction
on the extend instruction either. */
/* Lots of mips16 instruction formats */
/* Predicting jumps requires itype,ritype,i8type
and their extensions extItype,extritype,extI8type. */
enum mips16_inst_fmts
{
itype, /* 0 immediate 5,10 */
ritype, /* 1 5,3,8 */
rrtype, /* 2 5,3,3,5 */
rritype, /* 3 5,3,3,5 */
rrrtype, /* 4 5,3,3,3,2 */
rriatype, /* 5 5,3,3,1,4 */
shifttype, /* 6 5,3,3,3,2 */
i8type, /* 7 5,3,8 */
i8movtype, /* 8 5,3,3,5 */
i8mov32rtype, /* 9 5,3,5,3 */
i64type, /* 10 5,3,8 */
ri64type, /* 11 5,3,3,5 */
jalxtype, /* 12 5,1,5,5,16 - a 32 bit instruction */
exiItype, /* 13 5,6,5,5,1,1,1,1,1,1,5 */
extRitype, /* 14 5,6,5,5,3,1,1,1,5 */
extRRItype, /* 15 5,5,5,5,3,3,5 */
extRRIAtype, /* 16 5,7,4,5,3,3,1,4 */
EXTshifttype, /* 17 5,5,1,1,1,1,1,1,5,3,3,1,1,1,2 */
extI8type, /* 18 5,6,5,5,3,1,1,1,5 */
extI64type, /* 19 5,6,5,5,3,1,1,1,5 */
extRi64type, /* 20 5,6,5,5,3,3,5 */
extshift64type /* 21 5,5,1,1,1,1,1,1,5,1,1,1,3,5 */
};
/* I am heaping all the fields of the formats into one structure and
then, only the fields which are involved in instruction extension. */
struct upk_mips16
{
CORE_ADDR offset;
unsigned int regx; /* Function in i8 type. */
unsigned int regy;
};
/* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same format
for the bits which make up the immediate extension. */
static CORE_ADDR
extended_offset (unsigned int extension)
{
CORE_ADDR value;
value = (extension >> 16) & 0x1f; /* Extract 15:11. */
value = value << 6;
value |= (extension >> 21) & 0x3f; /* Extract 10:5. */
value = value << 5;
value |= extension & 0x1f; /* Extract 4:0. */
return value;
}
/* Only call this function if you know that this is an extendable
instruction. It won't malfunction, but why make excess remote memory
references? If the immediate operands get sign extended or something,
do it after the extension is performed. */
/* FIXME: Every one of these cases needs to worry about sign extension
when the offset is to be used in relative addressing. */
static unsigned int
fetch_mips_16 (struct gdbarch *gdbarch, CORE_ADDR pc)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[8];
pc = unmake_compact_addr (pc); /* Clear the low order bit. */
target_read_memory (pc, buf, 2);
return extract_unsigned_integer (buf, 2, byte_order);
}
static void
unpack_mips16 (struct gdbarch *gdbarch, 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 << 16) | inst);
value = (value ^ 0x8000) - 0x8000; /* Sign-extend. */
}
else
{
value = inst & 0x7ff;
value = (value ^ 0x400) - 0x400; /* Sign-extend. */
}
offset = value;
regx = -1;
regy = -1;
}
break;
case ritype:
case i8type:
{ /* A register identifier and an offset. */
/* Most of the fields are the same as I type but the
immediate value is of a different length. */
CORE_ADDR value;
if (extension)
{
value = extended_offset ((extension << 16) | inst);
value = (value ^ 0x8000) - 0x8000; /* Sign-extend. */
}
else
{
value = inst & 0xff; /* 8 bits */
value = (value ^ 0x80) - 0x80; /* Sign-extend. */
}
offset = value;
regx = (inst >> 8) & 0x07; /* i8 funct */
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 (gdbarch, ISA_MIPS16, pc + 2, NULL);
/* Low bit still set. */
value |= nexthalf;
offset = value;
regx = -1;
regy = -1;
break;
}
default:
internal_error (_("bad switch"));
}
upk->offset = offset;
upk->regx = regx;
upk->regy = regy;
}
/* Calculate the destination of a branch whose 16-bit opcode word is at PC,
and having a signed 16-bit OFFSET. */
static CORE_ADDR
add_offset_16 (CORE_ADDR pc, int offset)
{
return pc + (offset << 1) + 2;
}
static CORE_ADDR
extended_mips16_next_pc (regcache *regcache, CORE_ADDR pc,
unsigned int extension, unsigned int insn)
{
struct gdbarch *gdbarch = regcache->arch ();
int op = (insn >> 11);
switch (op)
{
case 2: /* Branch */
{
struct upk_mips16 upk;
unpack_mips16 (gdbarch, pc, extension, insn, itype, &upk);
pc = add_offset_16 (pc, upk.offset);
break;
}
case 3: /* JAL , JALX - Watch out, these are 32 bit
instructions. */
{
struct upk_mips16 upk;
unpack_mips16 (gdbarch, pc, extension, insn, jalxtype, &upk);
pc = ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)) | (upk.offset << 2);
if ((insn >> 10) & 0x01) /* Exchange mode */
pc = pc & ~0x01; /* Clear low bit, indicate 32 bit mode. */
else
pc |= 0x01;
break;
}
case 4: /* beqz */
{
struct upk_mips16 upk;
int reg;
unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
reg = regcache_raw_get_signed (regcache, mips_reg3_to_reg[upk.regx]);
if (reg == 0)
pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
}
case 5: /* bnez */
{
struct upk_mips16 upk;
int reg;
unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
reg = regcache_raw_get_signed (regcache, mips_reg3_to_reg[upk.regx]);
if (reg != 0)
pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
}
case 12: /* I8 Formats btez btnez */
{
struct upk_mips16 upk;
int reg;
unpack_mips16 (gdbarch, pc, extension, insn, i8type, &upk);
/* upk.regx contains the opcode */
/* Test register is 24 */
reg = regcache_raw_get_signed (regcache, 24);
if (((upk.regx == 0) && (reg == 0)) /* BTEZ */
|| ((upk.regx == 1) && (reg != 0))) /* BTNEZ */
pc = add_offset_16 (pc, upk.offset);
else
pc += 2;
break;
}
case 29: /* RR Formats JR, JALR, JALR-RA */
{
struct upk_mips16 upk;
/* upk.fmt = rrtype; */
op = insn & 0x1f;
if (op == 0)
{
int reg;
upk.regx = (insn >> 8) & 0x07;
upk.regy = (insn >> 5) & 0x07;
if ((upk.regy & 1) == 0)
reg = mips_reg3_to_reg[upk.regx];
else
reg = 31; /* Function return instruction. */
pc = regcache_raw_get_signed (regcache, reg);
}
else
pc += 2;
break;
}
case 30:
/* This is an instruction extension. Fetch the real instruction
(which follows the extension) and decode things based on
that. */
{
pc += 2;
pc = extended_mips16_next_pc (regcache, pc, insn,
fetch_mips_16 (gdbarch, pc));
break;
}
default:
{
pc += 2;
break;
}
}
return pc;
}
static CORE_ADDR
mips16_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
struct gdbarch *gdbarch = regcache->arch ();
unsigned int insn = fetch_mips_16 (gdbarch, pc);
return extended_mips16_next_pc (regcache, pc, 0, insn);
}
/* The mips_next_pc function supports single_step when the remote
target monitor or stub is not developed enough to do a single_step.
It works by decoding the current instruction and predicting where a
branch will go. This isn't hard because all the data is available.
The MIPS32, MIPS16 and microMIPS variants are quite different. */
static CORE_ADDR
mips_next_pc (struct regcache *regcache, CORE_ADDR pc)
{
struct gdbarch *gdbarch = regcache->arch ();
if (mips_pc_is_mips16 (gdbarch, pc))
return mips16_next_pc (regcache, pc);
else if (mips_pc_is_micromips (gdbarch, pc))
return micromips_next_pc (regcache, pc);
else
return mips32_next_pc (regcache, pc);
}
/* Return non-zero if the MIPS16 instruction INSN is a compact branch
or jump. */
static int
mips16_instruction_is_compact_branch (unsigned short insn)
{
switch (insn & 0xf800)
{
case 0xe800:
return (insn & 0x009f) == 0x80; /* JALRC/JRC */
case 0x6000:
return (insn & 0x0600) == 0; /* BTNEZ/BTEQZ */
case 0x2800: /* BNEZ */
case 0x2000: /* BEQZ */
case 0x1000: /* B */
return 1;
default:
return 0;
}
}
/* Return non-zero if the microMIPS instruction INSN is a compact branch
or jump. */
static int
micromips_instruction_is_compact_branch (unsigned short insn)
{
switch (micromips_op (insn))
{
case 0x11: /* POOL16C: bits 010001 */
return (b5s5_op (insn) == 0x18
/* JRADDIUSP: bits 010001 11000 */
|| b5s5_op (insn) == 0xd);
/* JRC: bits 010011 01101 */
case 0x10: /* POOL32I: bits 010000 */
return (b5s5_op (insn) & 0x1d) == 0x5;
/* BEQZC/BNEZC: bits 010000 001x1 */
default:
return 0;
}
}
struct mips_frame_cache
{
CORE_ADDR base;
trad_frame_saved_reg *saved_regs;
};
/* Set a register's saved stack address in temp_saved_regs. If an
address has already been set for this register, do nothing; this
way we will only recognize the first save of a given register in a
function prologue.
For simplicity, save the address in both [0 .. gdbarch_num_regs) and
[gdbarch_num_regs .. 2*gdbarch_num_regs).
Strictly speaking, only the second range is used as it is only second
range (the ABI instead of ISA registers) that comes into play when finding
saved registers in a frame. */
static void
set_reg_offset (struct gdbarch *gdbarch, struct mips_frame_cache *this_cache,
int regnum, CORE_ADDR offset)
{
if (this_cache != NULL
&& this_cache->saved_regs[regnum].is_realreg ()
&& this_cache->saved_regs[regnum].realreg () == regnum)
{
this_cache->saved_regs[regnum + 0
* gdbarch_num_regs (gdbarch)].set_addr (offset);
this_cache->saved_regs[regnum + 1
* gdbarch_num_regs (gdbarch)].set_addr (offset);
}
}
/* Fetch the immediate value from a MIPS16 instruction.
If the previous instruction was an EXTEND, use it to extend
the upper bits of the immediate value. This is a helper function
for mips16_scan_prologue. */
static int
mips16_get_imm (unsigned short prev_inst, /* previous instruction */
unsigned short inst, /* current instruction */
int nbits, /* number of bits in imm field */
int scale, /* scale factor to be applied to imm */
int is_signed) /* is the imm field signed? */
{
int offset;
if ((prev_inst & 0xf800) == 0xf000) /* prev instruction was EXTEND? */
{
offset = ((prev_inst & 0x1f) << 11) | (prev_inst & 0x7e0);
if (offset & 0x8000) /* check for negative extend */
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;
}
}
/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
the associated FRAME_CACHE if not null.
Return the address of the first instruction past the prologue. */
static CORE_ADDR
mips16_scan_prologue (struct gdbarch *gdbarch,
CORE_ADDR start_pc, CORE_ADDR limit_pc,
const frame_info_ptr &this_frame,
struct mips_frame_cache *this_cache)
{
int prev_non_prologue_insn = 0;
int this_non_prologue_insn;
int non_prologue_insns = 0;
CORE_ADDR prev_pc;
CORE_ADDR cur_pc;
CORE_ADDR frame_addr = 0; /* Value of $r17, used as frame pointer. */
CORE_ADDR sp;
long frame_offset = 0; /* Size of stack frame. */
long frame_adjust = 0; /* Offset of FP from SP. */
int frame_reg = MIPS_SP_REGNUM;
unsigned short prev_inst = 0; /* saved copy of previous instruction. */
unsigned inst = 0; /* current instruction */
unsigned entry_inst = 0; /* the entry instruction */
unsigned save_inst = 0; /* the save instruction */
int prev_delay_slot = 0;
int in_delay_slot;
int reg, offset;
int extend_bytes = 0;
int prev_extend_bytes = 0;
CORE_ADDR end_prologue_addr;
/* Can be called when there's no process, and hence when there's no
THIS_FRAME. */
if (this_frame != NULL)
sp = get_frame_register_signed (this_frame,
gdbarch_num_regs (gdbarch)
+ MIPS_SP_REGNUM);
else
sp = 0;
if (limit_pc > start_pc + 200)
limit_pc = start_pc + 200;
prev_pc = start_pc;
/* Permit at most one non-prologue non-control-transfer instruction
in the middle which may have been reordered by the compiler for
optimisation. */
for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN16_SIZE)
{
this_non_prologue_insn = 0;
in_delay_slot = 0;
/* Save the previous instruction. If it's an EXTEND, we'll extract
the immediate offset extension from it in mips16_get_imm. */
prev_inst = inst;
/* Fetch and decode the instruction. */
inst = (unsigned short) mips_fetch_instruction (gdbarch, ISA_MIPS16,
cur_pc, NULL);
/* Normally we ignore extend instructions. However, if it is
not followed by a valid prologue instruction, then this
instruction is not part of the prologue either. We must
remember in this case to adjust the end_prologue_addr back
over the extend. */
if ((inst & 0xf800) == 0xf000) /* extend */
{
extend_bytes = MIPS_INSN16_SIZE;
continue;
}
prev_extend_bytes = extend_bytes;
extend_bytes = 0;
if ((inst & 0xff00) == 0x6300 /* addiu sp */
|| (inst & 0xff00) == 0xfb00) /* daddiu sp */
{
offset = mips16_get_imm (prev_inst, inst, 8, 8, 1);
if (offset < 0) /* Negative stack adjustment? */
frame_offset -= offset;
else
/* Exit loop if a positive stack adjustment is found, which
usually means that the stack cleanup code in the function
epilogue is reached. */
break;
}
else if ((inst & 0xf800) == 0xd000) /* sw reg,n($sp) */
{
offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
reg = mips_reg3_to_reg[(inst & 0x700) >> 8];
set_reg_offset (gdbarch, this_cache, reg, sp + offset);
}
else if ((inst & 0xff00) == 0xf900) /* sd reg,n($sp) */
{
offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
reg = mips_reg3_to_reg[(inst & 0xe0) >> 5];
set_reg_offset (gdbarch, this_cache, reg, sp + offset);
}
else if ((inst & 0xff00) == 0x6200) /* sw $ra,n($sp) */
{
offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
set_reg_offset (gdbarch, this_cache, MIPS_RA_REGNUM, sp + offset);
}
else if ((inst & 0xff00) == 0xfa00) /* sd $ra,n($sp) */
{
offset = mips16_get_imm (prev_inst, inst, 8, 8, 0);
set_reg_offset (gdbarch, this_cache, MIPS_RA_REGNUM, sp + offset);
}
else if (inst == 0x673d) /* move $s1, $sp */
{
frame_addr = sp;
frame_reg = 17;
}
else if ((inst & 0xff00) == 0x0100) /* addiu $s1,sp,n */
{
offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
frame_addr = sp + offset;
frame_reg = 17;
frame_adjust = offset;
}
else if ((inst & 0xFF00) == 0xd900) /* sw reg,offset($s1) */
{
offset = mips16_get_imm (prev_inst, inst, 5, 4, 0);
reg = mips_reg3_to_reg[(inst & 0xe0) >> 5];
set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset);
}
else if ((inst & 0xFF00) == 0x7900) /* sd reg,offset($s1) */
{
offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
reg = mips_reg3_to_reg[(inst & 0xe0) >> 5];
set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset);
}
else if ((inst & 0xf81f) == 0xe809
&& (inst & 0x700) != 0x700) /* entry */
entry_inst = inst; /* Save for later processing. */
else if ((inst & 0xff80) == 0x6480) /* save */
{
save_inst = inst; /* Save for later processing. */
if (prev_extend_bytes) /* extend */
save_inst |= prev_inst << 16;
}
else if ((inst & 0xff1c) == 0x6704) /* move reg,$a0-$a3 */
{
/* This instruction is part of the prologue, but we don't
need to do anything special to handle it. */
}
else if (mips16_instruction_has_delay_slot (inst, 0))
/* JAL/JALR/JALX/JR */
{
/* The instruction in the delay slot can be a part
of the prologue, so move forward once more. */
in_delay_slot = 1;
if (mips16_instruction_has_delay_slot (inst, 1))
/* JAL/JALX */
{
prev_extend_bytes = MIPS_INSN16_SIZE;
cur_pc += MIPS_INSN16_SIZE; /* 32-bit instruction */
}
}
else
{
this_non_prologue_insn = 1;
}
non_prologue_insns += this_non_prologue_insn;
/* A jump or branch, or enough non-prologue insns seen? If so,
then we must have reached the end of the prologue by now. */
if (prev_delay_slot || non_prologue_insns > 1
|| mips16_instruction_is_compact_branch (inst))
break;
prev_non_prologue_insn = this_non_prologue_insn;
prev_delay_slot = in_delay_slot;
prev_pc = cur_pc - prev_extend_bytes;
}
/* The entry instruction is typically the first instruction in a function,
and it stores registers at offsets relative to the value of the old SP
(before the prologue). But the value of the sp parameter to this
function is the new SP (after the prologue has been executed). So we
can't calculate those offsets until we've seen the entire prologue,
and can calculate what the old SP must have been. */
if (entry_inst != 0)
{
int areg_count = (entry_inst >> 8) & 7;
int sreg_count = (entry_inst >> 6) & 3;
/* The entry instruction always subtracts 32 from the SP. */
frame_offset += 32;
/* Now we can calculate what the SP must have been at the
start of the function prologue. */
sp += frame_offset;
/* Check if a0-a3 were saved in the caller's argument save area. */
for (reg = 4, offset = 0; reg < areg_count + 4; reg++)
{
set_reg_offset (gdbarch, this_cache, reg, sp + offset);
offset += mips_abi_regsize (gdbarch);
}
/* Check if the ra register was pushed on the stack. */
offset = -4;
if (entry_inst & 0x20)
{
set_reg_offset (gdbarch, this_cache, MIPS_RA_REGNUM, sp + offset);
offset -= mips_abi_regsize (gdbarch);
}
/* Check if the s0 and s1 registers were pushed on the stack. */
for (reg = 16; reg < sreg_count + 16; reg++)
{
set_reg_offset (gdbarch, this_cache, reg, sp + offset);
offset -= mips_abi_regsize (gdbarch);
}
}
/* The SAVE instruction is similar to ENTRY, except that defined by the
MIPS16e ASE of the MIPS Architecture. Unlike with ENTRY though, the
size of the frame is specified as an immediate field of instruction
and an extended variation exists which lets additional registers and
frame space to be specified. The instruction always treats registers
as 32-bit so its usefulness for 64-bit ABIs is questionable. */
if (save_inst != 0 && mips_abi_regsize (gdbarch) == 4)
{
static int args_table[16] = {
0, 0, 0, 0, 1, 1, 1, 1,
2, 2, 2, 0, 3, 3, 4, -1,
};
static int astatic_table[16] = {
0, 1, 2, 3, 0, 1, 2, 3,
0, 1, 2, 4, 0, 1, 0, -1,
};
int aregs = (save_inst >> 16) & 0xf;
int xsregs = (save_inst >> 24) & 0x7;
int args = args_table[aregs];
int astatic = astatic_table[aregs];
long frame_size;
if (args < 0)
{
warning (_("Invalid number of argument registers encoded in SAVE."));
args = 0;
}
if (astatic < 0)
{
warning (_("Invalid number of static registers encoded in SAVE."));
astatic = 0;
}
/* For standard SAVE the frame size of 0 means 128. */
frame_size = ((save_inst >> 16) & 0xf0) | (save_inst & 0xf);
if (frame_size == 0 && (save_inst >> 16) == 0)
frame_size = 16;
frame_size *= 8;
frame_offset += frame_size;
/* Now we can calculate what the SP must have been at the
start of the function prologue. */
sp += frame_offset;
/* Check if A0-A3 were saved in the caller's argument save area. */
for (reg = MIPS_A0_REGNUM, offset = 0; reg < args + 4; reg++)
{
set_reg_offset (gdbarch, this_cache, reg, sp + offset);
offset += mips_abi_regsize (gdbarch);
}
offset = -4;
/* Check if the RA register was pushed on the stack. */
if (save_inst & 0x40)
{
set_reg_offset (gdbarch, this_cache, MIPS_RA_REGNUM, sp + offset);
offset -= mips_abi_regsize (gdbarch);
}
/* Check if the S8 register was pushed on the stack. */
if (xsregs > 6)
{
set_reg_offset (gdbarch, this_cache, 30, sp + offset);
offset -= mips_abi_regsize (gdbarch);
xsregs--;
}
/* Check if S2-S7 were pushed on the stack. */
for (reg = 18 + xsregs - 1; reg > 18 - 1; reg--)
{
set_reg_offset (gdbarch, this_cache, reg, sp + offset);
offset -= mips_abi_regsize (gdbarch);
}
/* Check if the S1 register was pushed on the stack. */
if (save_inst & 0x10)
{
set_reg_offset (gdbarch, this_cache, 17, sp + offset);
offset -= mips_abi_regsize (gdbarch);
}
/* Check if the S0 register was pushed on the stack. */
if (save_inst & 0x20)
{
set_reg_offset (gdbarch, this_cache, 16, sp + offset);
offset -= mips_abi_regsize (gdbarch);
}
/* Check if A0-A3 were pushed on the stack. */
for (reg = MIPS_A0_REGNUM + 3; reg > MIPS_A0_REGNUM + 3 - astatic; reg--)
{
set_reg_offset (gdbarch, this_cache, reg, sp + offset);
offset -= mips_abi_regsize (gdbarch);
}
}
if (this_cache != NULL)
{
this_cache->base =
(get_frame_register_signed (this_frame,
gdbarch_num_regs (gdbarch) + frame_reg)
+ frame_offset - frame_adjust);
/* FIXME: brobecker/2004-10-10: Just as in the mips32 case, we should
be able to get rid of the assignment below, evetually. But it's
still needed for now. */
this_cache->saved_regs[gdbarch_num_regs (gdbarch)
+ mips_regnum (gdbarch)->pc]
= this_cache->saved_regs[gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM];
}
/* Set end_prologue_addr to the address of the instruction immediately
after the last one we scanned. Unless the last one looked like a
non-prologue instruction (and we looked ahead), in which case use
its address instead. */
end_prologue_addr = (prev_non_prologue_insn || prev_delay_slot
? prev_pc : cur_pc - prev_extend_bytes);
return end_prologue_addr;
}
/* Heuristic unwinder for 16-bit MIPS instruction set (aka MIPS16).
Procedures that use the 32-bit instruction set are handled by the
mips_insn32 unwinder. */
static struct mips_frame_cache *
mips_insn16_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
struct mips_frame_cache *cache;
if ((*this_cache) != NULL)
return (struct mips_frame_cache *) (*this_cache);
cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
(*this_cache) = cache;
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
/* Analyze the function prologue. */
{
const CORE_ADDR pc = get_frame_address_in_block (this_frame);
CORE_ADDR start_addr;
find_pc_partial_function (pc, NULL, &start_addr, NULL);
if (start_addr == 0)
start_addr = heuristic_proc_start (gdbarch, pc);
/* We can't analyze the prologue if we couldn't find the begining
of the function. */
if (start_addr == 0)
return cache;
mips16_scan_prologue (gdbarch, start_addr, pc, this_frame,
(struct mips_frame_cache *) *this_cache);
}
/* gdbarch_sp_regnum contains the value and not the address. */
cache->saved_regs[gdbarch_num_regs (gdbarch)
+ MIPS_SP_REGNUM].set_value (cache->base);
return (struct mips_frame_cache *) (*this_cache);
}
static void
mips_insn16_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
struct frame_id *this_id)
{
struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
this_cache);
/* This marks the outermost frame. */
if (info->base == 0)
return;
(*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
}
static struct value *
mips_insn16_frame_prev_register (const frame_info_ptr &this_frame,
void **this_cache, int regnum)
{
struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
this_cache);
return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
}
static int
mips_insn16_frame_sniffer (const struct frame_unwind *self,
const frame_info_ptr &this_frame, void **this_cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
CORE_ADDR pc = get_frame_pc (this_frame);
if (mips_pc_is_mips16 (gdbarch, pc))
return 1;
return 0;
}
static const struct frame_unwind mips_insn16_frame_unwind =
{
"mips insn16 prologue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
mips_insn16_frame_this_id,
mips_insn16_frame_prev_register,
NULL,
mips_insn16_frame_sniffer
};
static CORE_ADDR
mips_insn16_frame_base_address (const frame_info_ptr &this_frame,
void **this_cache)
{
struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
this_cache);
return info->base;
}
static const struct frame_base mips_insn16_frame_base =
{
&mips_insn16_frame_unwind,
mips_insn16_frame_base_address,
mips_insn16_frame_base_address,
mips_insn16_frame_base_address
};
static const struct frame_base *
mips_insn16_frame_base_sniffer (const frame_info_ptr &this_frame)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
CORE_ADDR pc = get_frame_pc (this_frame);
if (mips_pc_is_mips16 (gdbarch, pc))
return &mips_insn16_frame_base;
else
return NULL;
}
/* Decode a 9-bit signed immediate argument of ADDIUSP -- -2 is mapped
to -258, -1 -- to -257, 0 -- to 256, 1 -- to 257 and other values are
interpreted directly, and then multiplied by 4. */
static int
micromips_decode_imm9 (int imm)
{
imm = (imm ^ 0x100) - 0x100;
if (imm > -3 && imm < 2)
imm ^= 0x100;
return imm << 2;
}
/* Analyze the function prologue from START_PC to LIMIT_PC. Return
the address of the first instruction past the prologue. */
static CORE_ADDR
micromips_scan_prologue (struct gdbarch *gdbarch,
CORE_ADDR start_pc, CORE_ADDR limit_pc,
const frame_info_ptr &this_frame,
struct mips_frame_cache *this_cache)
{
CORE_ADDR end_prologue_addr;
int prev_non_prologue_insn = 0;
int frame_reg = MIPS_SP_REGNUM;
int this_non_prologue_insn;
int non_prologue_insns = 0;
long frame_offset = 0; /* Size of stack frame. */
long frame_adjust = 0; /* Offset of FP from SP. */
int prev_delay_slot = 0;
int in_delay_slot;
CORE_ADDR prev_pc;
CORE_ADDR cur_pc;
ULONGEST insn; /* current instruction */
CORE_ADDR sp;
long offset;
long sp_adj;
long v1_off = 0; /* The assumption is LUI will replace it. */
int reglist;
int breg;
int dreg;
int sreg