|  | /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger. | 
|  |  | 
|  | Copyright (C) 1988-2023 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 "defs.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 "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 *, | 
|  | 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 char *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; | 
|  | struct bound_minimal_symbol msym; | 
|  |  | 
|  | compact_block_start = block->start () | 1; | 
|  | 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 (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, ®val); | 
|  | 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 (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 (frame_info_ptr frame, int regnum, | 
|  | struct type *type, gdb_byte *to, | 
|  | int *optimizedp, int *unavailablep) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  |  | 
|  | if (mips_convert_register_float_case_p (gdbarch, regnum, type)) | 
|  | { | 
|  | get_frame_register (frame, regnum + 0, to + 4); | 
|  | get_frame_register (frame, regnum + 1, to + 0); | 
|  |  | 
|  | if (!get_frame_register_bytes (frame, regnum + 0, 0, {to + 4, 4}, | 
|  | optimizedp, unavailablep)) | 
|  | return 0; | 
|  |  | 
|  | if (!get_frame_register_bytes (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 (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 (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)) | 
|  | { | 
|  | put_frame_register (frame, regnum + 0, from + 4); | 
|  | put_frame_register (frame, regnum + 1, from + 0); | 
|  | } | 
|  | else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type)) | 
|  | { | 
|  | gdb_byte fill[8]; | 
|  | size_t len = type->length (); | 
|  |  | 
|  | /* Sign extend values, irrespective of type, that are stored to | 
|  | a 64-bit general purpose register.  (32-bit unsigned values | 
|  | are stored as signed quantities within a 64-bit register. | 
|  | When performing an operation, in compiled code, that combines | 
|  | a 32-bit unsigned value with a signed 64-bit value, a type | 
|  | conversion is first performed that zeroes out the high 32 bits.)  */ | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) | 
|  | { | 
|  | if (from[0] & 0x80) | 
|  | store_signed_integer (fill, 8, BFD_ENDIAN_BIG, -1); | 
|  | else | 
|  | store_signed_integer (fill, 8, BFD_ENDIAN_BIG, 0); | 
|  | put_frame_register_bytes (frame, regnum, 0, {fill, 8 - len}); | 
|  | put_frame_register_bytes (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 (frame, regnum, 0, {from, len}); | 
|  | put_frame_register_bytes (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) | 
|  | { | 
|  | struct bound_minimal_symbol sym; | 
|  |  | 
|  | /* Flags indicating that this is a MIPS16 or microMIPS function is | 
|  | stored by elfread.c in the high bit of the info field.  Use this | 
|  | to decide if the function is standard MIPS.  Otherwise if bit 0 | 
|  | of the address is clear, then this is a standard MIPS function.  */ | 
|  | sym = lookup_minimal_symbol_by_pc (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) | 
|  | { | 
|  | struct bound_minimal_symbol sym; | 
|  |  | 
|  | /* A flag indicating that this is a MIPS16 function is stored by | 
|  | elfread.c in the high bit of the info field.  Use this to decide | 
|  | if the function is MIPS16.  Otherwise if bit 0 of the address is | 
|  | set, then ELF file flags will tell if this is a MIPS16 function.  */ | 
|  | sym = lookup_minimal_symbol_by_pc (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) | 
|  | { | 
|  | struct bound_minimal_symbol sym; | 
|  |  | 
|  | /* A flag indicating that this is a microMIPS function is stored by | 
|  | elfread.c in the high bit of the info field.  Use this to decide | 
|  | 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.  */ | 
|  | 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) | 
|  | { | 
|  | struct bound_minimal_symbol sym; | 
|  |  | 
|  | /* A flag indicating that this is a MIPS16 or a microMIPS function | 
|  | is stored by elfread.c in the high bit of the info field.  Use | 
|  | 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.  */ | 
|  | 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, 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, 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, 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, | 
|  | 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 (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 (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 (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, | 
|  | 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 (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 (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, | 
|  | 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; | 
|  | int treg; | 
|  | int loc; | 
|  | int op; | 
|  | int s; | 
|  | int i; | 
|  |  | 
|  | /* 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 += loc) | 
|  | { | 
|  | this_non_prologue_insn = 0; | 
|  | in_delay_slot = 0; | 
|  | sp_adj = 0; | 
|  | loc = 0; | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, cur_pc, NULL); | 
|  | loc += 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, cur_pc + loc, NULL); | 
|  | loc += MIPS_INSN16_SIZE; | 
|  | switch (micromips_op (insn >> 16)) | 
|  | { | 
|  | /* Record $sp/$fp adjustment.  */ | 
|  | /* Discard (D)ADDU $gp,$jp used for PIC code.  */ | 
|  | case 0x0: /* POOL32A: bits 000000 */ | 
|  | case 0x16: /* POOL32S: bits 010110 */ | 
|  | op = b0s11_op (insn); | 
|  | sreg = b0s5_reg (insn >> 16); | 
|  | treg = b5s5_reg (insn >> 16); | 
|  | dreg = b11s5_reg (insn); | 
|  | if (op == 0x1d0 | 
|  | /* SUBU: bits 000000 00111010000 */ | 
|  | /* DSUBU: bits 010110 00111010000 */ | 
|  | && dreg == MIPS_SP_REGNUM && sreg == MIPS_SP_REGNUM | 
|  | && treg == 3) | 
|  | /* (D)SUBU $sp, $v1 */ | 
|  | sp_adj = v1_off; | 
|  | else if (op != 0x150 | 
|  | /* ADDU: bits 000000 00101010000 */ | 
|  | /* DADDU: bits 010110 00101010000 */ | 
|  | || dreg != 28 || sreg != 28 || treg != MIPS_T9_REGNUM) | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | case 0x8: /* POOL32B: bits 001000 */ | 
|  | op = b12s4_op (insn); | 
|  | breg = b0s5_reg (insn >> 16); | 
|  | reglist = sreg = b5s5_reg (insn >> 16); | 
|  | offset = (b0s12_imm (insn) ^ 0x800) - 0x800; | 
|  | if ((op == 0x9 || op == 0xc) | 
|  | /* SWP: bits 001000 1001 */ | 
|  | /* SDP: bits 001000 1100 */ | 
|  | && breg == MIPS_SP_REGNUM && sreg < MIPS_RA_REGNUM) | 
|  | /* S[DW]P reg,offset($sp) */ | 
|  | { | 
|  | s = 4 << ((b12s4_op (insn) & 0x4) == 0x4); | 
|  | set_reg_offset (gdbarch, this_cache, | 
|  | sreg, sp + offset); | 
|  | set_reg_offset (gdbarch, this_cache, | 
|  | sreg + 1, sp + offset + s); | 
|  | } | 
|  | else if ((op == 0xd || op == 0xf) | 
|  | /* SWM: bits 001000 1101 */ | 
|  | /* SDM: bits 001000 1111 */ | 
|  | && breg == MIPS_SP_REGNUM | 
|  | /* SWM reglist,offset($sp) */ | 
|  | && ((reglist >= 1 && reglist <= 9) | 
|  | || (reglist >= 16 && reglist <= 25))) | 
|  | { | 
|  | int sreglist = std::min(reglist & 0xf, 8); | 
|  |  | 
|  | s = 4 << ((b12s4_op (insn) & 0x2) == 0x2); | 
|  | for (i = 0; i < sreglist; i++) | 
|  | set_reg_offset (gdbarch, this_cache, 16 + i, sp + s * i); | 
|  | if ((reglist & 0xf) > 8) | 
|  | set_reg_offset (gdbarch, this_cache, 30, sp + s * i++); | 
|  | if ((reglist & 0x10) == 0x10) | 
|  | set_reg_offset (gdbarch, this_cache, | 
|  | MIPS_RA_REGNUM, sp + s * i++); | 
|  | } | 
|  | else | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | /* Record $sp/$fp adjustment.  */ | 
|  | /* Discard (D)ADDIU $gp used for PIC code.  */ | 
|  | case 0xc: /* ADDIU: bits 001100 */ | 
|  | case 0x17: /* DADDIU: bits 010111 */ | 
|  | sreg = b0s5_reg (insn >> 16); | 
|  | dreg = b5s5_reg (insn >> 16); | 
|  | offset = (b0s16_imm (insn) ^ 0x8000) - 0x8000; | 
|  | if (sreg == MIPS_SP_REGNUM && dreg == MIPS_SP_REGNUM) | 
|  | /* (D)ADDIU $sp, imm */ | 
|  | sp_adj = offset; | 
|  | else if (sreg == MIPS_SP_REGNUM && dreg == 30) | 
|  | /* (D)ADDIU $fp, $sp, imm */ | 
|  | { | 
|  | frame_adjust = offset; | 
|  | frame_reg = 30; | 
|  | } | 
|  | else if (sreg != 28 || dreg != 28) | 
|  | /* (D)ADDIU $gp, imm */ | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | /* LUI $v1 is used for larger $sp adjustments.  */ | 
|  | /* Discard LUI $gp used for PIC code.  */ | 
|  | case 0x10: /* POOL32I: bits 010000 */ | 
|  | if (b5s5_op (insn >> 16) == 0xd | 
|  | /* LUI: bits 010000 001101 */ | 
|  | && b0s5_reg (insn >> 16) == 3) | 
|  | /* LUI $v1, imm */ | 
|  | v1_off = ((b0s16_imm (insn) << 16) ^ 0x80000000) - 0x80000000; | 
|  | else if (b5s5_op (insn >> 16) != 0xd | 
|  | /* LUI: bits 010000 001101 */ | 
|  | || b0s5_reg (insn >> 16) != 28) | 
|  | /* LUI $gp, imm */ | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | /* ORI $v1 is used for larger $sp adjustments.  */ | 
|  | case 0x14: /* ORI: bits 010100 */ | 
|  | sreg = b0s5_reg (insn >> 16); | 
|  | dreg = b5s5_reg (insn >> 16); | 
|  | if (sreg == 3 && dreg == 3) | 
|  | /* ORI $v1, imm */ | 
|  | v1_off |= b0s16_imm (insn); | 
|  | else | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | case 0x26: /* SWC1: bits 100110 */ | 
|  | case 0x2e: /* SDC1: bits 101110 */ | 
|  | breg = b0s5_reg (insn >> 16); | 
|  | if (breg != MIPS_SP_REGNUM) | 
|  | /* S[DW]C1 reg,offset($sp) */ | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | case 0x36: /* SD: bits 110110 */ | 
|  | case 0x3e: /* SW: bits 111110 */ | 
|  | breg = b0s5_reg (insn >> 16); | 
|  | sreg = b5s5_reg (insn >> 16); | 
|  | offset = (b0s16_imm (insn) ^ 0x8000) - 0x8000; | 
|  | if (breg == MIPS_SP_REGNUM) | 
|  | /* S[DW] reg,offset($sp) */ | 
|  | set_reg_offset (gdbarch, this_cache, sreg, sp + offset); | 
|  | else | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | /* The instruction in the delay slot can be a part | 
|  | of the prologue, so move forward once more.  */ | 
|  | if (micromips_instruction_has_delay_slot (insn, 0)) | 
|  | in_delay_slot = 1; | 
|  | else | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  | } | 
|  | insn >>= 16; | 
|  | break; | 
|  |  | 
|  | /* 16-bit instructions.  */ | 
|  | case MIPS_INSN16_SIZE: | 
|  | switch (micromips_op (insn)) | 
|  | { | 
|  | case 0x3: /* MOVE: bits 000011 */ | 
|  | sreg = b0s5_reg (insn); | 
|  | dreg = b5s5_reg (insn); | 
|  | if (sreg == MIPS_SP_REGNUM && dreg == 30) | 
|  | /* MOVE  $fp, $sp */ | 
|  | frame_reg = 30; | 
|  | else if ((sreg & 0x1c) != 0x4) | 
|  | /* MOVE  reg, $a0-$a3 */ | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | case 0x11: /* POOL16C: bits 010001 */ | 
|  | if (b6s4_op (insn) == 0x5) | 
|  | /* SWM: bits 010001 0101 */ | 
|  | { | 
|  | offset = ((b0s4_imm (insn) << 2) ^ 0x20) - 0x20; | 
|  | reglist = b4s2_regl (insn); | 
|  | for (i = 0; i <= reglist; i++) | 
|  | set_reg_offset (gdbarch, this_cache, 16 + i, sp + 4 * i); | 
|  | set_reg_offset (gdbarch, this_cache, | 
|  | MIPS_RA_REGNUM, sp + 4 * i++); | 
|  | } | 
|  | else | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | case 0x13: /* POOL16D: bits 010011 */ | 
|  | if ((insn & 0x1) == 0x1) | 
|  | /* ADDIUSP: bits 010011 1 */ | 
|  | sp_adj = micromips_decode_imm9 (b1s9_imm (insn)); | 
|  | else if (b5s5_reg (insn) == MIPS_SP_REGNUM) | 
|  | /* ADDIUS5: bits 010011 0 */ | 
|  | /* ADDIUS5 $sp, imm */ | 
|  | sp_adj = (b1s4_imm (insn) ^ 8) - 8; | 
|  | else | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  |  | 
|  | case 0x32: /* SWSP: bits 110010 */ | 
|  | offset = b0s5_imm (insn) << 2; | 
|  | sreg = b5s5_reg (insn); | 
|  | set_reg_offset (gdbarch, this_cache, sreg, sp + offset); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | /* The instruction in the delay slot can be a part | 
|  | of the prologue, so move forward once more.  */ | 
|  | if (micromips_instruction_has_delay_slot (insn << 16, 0)) | 
|  | in_delay_slot = 1; | 
|  | else | 
|  | this_non_prologue_insn = 1; | 
|  | break; | 
|  | } | 
|  | break; | 
|  | } | 
|  | if (sp_adj < 0) | 
|  | frame_offset -= sp_adj; | 
|  |  | 
|  | non_prologue_insns += this_non_prologue_insn; | 
|  |  | 
|  | /* A jump or branch, enough non-prologue insns seen or positive | 
|  | stack adjustment?  If so, then we must have reached the end | 
|  | of the prologue by now.  */ | 
|  | if (prev_delay_slot || non_prologue_insns > 1 || sp_adj > 0 | 
|  | || micromips_instruction_is_compact_branch (insn)) | 
|  | break; | 
|  |  | 
|  | prev_non_prologue_insn = this_non_prologue_insn; | 
|  | prev_delay_slot = in_delay_slot; | 
|  | prev_pc = cur_pc; | 
|  | } | 
|  |  | 
|  | 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; | 
|  |  | 
|  | return end_prologue_addr; | 
|  | } | 
|  |  | 
|  | /* Heuristic unwinder for procedures using microMIPS instructions. | 
|  | Procedures that use the 32-bit instruction set are handled by the | 
|  | mips_insn32 unwinder.  Likewise MIPS16 and the mips_insn16 unwinder. */ | 
|  |  | 
|  | static struct mips_frame_cache * | 
|  | mips_micro_frame_cache (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 (get_frame_arch (this_frame), pc); | 
|  | /* We can't analyze the prologue if we couldn't find the begining | 
|  | of the function.  */ | 
|  | if (start_addr == 0) | 
|  | return cache; | 
|  |  | 
|  | micromips_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_micro_frame_this_id (frame_info_ptr this_frame, void **this_cache, | 
|  | struct frame_id *this_id) | 
|  | { | 
|  | struct mips_frame_cache *info = mips_micro_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_micro_frame_prev_register (frame_info_ptr this_frame, | 
|  | void **this_cache, int regnum) | 
|  | { | 
|  | struct mips_frame_cache *info = mips_micro_frame_cache (this_frame, | 
|  | this_cache); | 
|  | return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); | 
|  | } | 
|  |  | 
|  | static int | 
|  | mips_micro_frame_sniffer (const struct frame_unwind *self, | 
|  | 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_micromips (gdbarch, pc)) | 
|  | return 1; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static const struct frame_unwind mips_micro_frame_unwind = | 
|  | { | 
|  | "mips micro prologue", | 
|  | NORMAL_FRAME, | 
|  | default_frame_unwind_stop_reason, | 
|  | mips_micro_frame_this_id, | 
|  | mips_micro_frame_prev_register, | 
|  | NULL, | 
|  | mips_micro_frame_sniffer | 
|  | }; | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_micro_frame_base_address (frame_info_ptr this_frame, | 
|  | void **this_cache) | 
|  | { | 
|  | struct mips_frame_cache *info = mips_micro_frame_cache (this_frame, | 
|  | this_cache); | 
|  | return info->base; | 
|  | } | 
|  |  | 
|  | static const struct frame_base mips_micro_frame_base = | 
|  | { | 
|  | &mips_micro_frame_unwind, | 
|  | mips_micro_frame_base_address, | 
|  | mips_micro_frame_base_address, | 
|  | mips_micro_frame_base_address | 
|  | }; | 
|  |  | 
|  | static const struct frame_base * | 
|  | mips_micro_frame_base_sniffer (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_micromips (gdbarch, pc)) | 
|  | return &mips_micro_frame_base; | 
|  | else | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /* Mark all the registers as unset in the saved_regs array | 
|  | of THIS_CACHE.  Do nothing if THIS_CACHE is null.  */ | 
|  |  | 
|  | static void | 
|  | reset_saved_regs (struct gdbarch *gdbarch, struct mips_frame_cache *this_cache) | 
|  | { | 
|  | if (this_cache == NULL || this_cache->saved_regs == NULL) | 
|  | return; | 
|  |  | 
|  | { | 
|  | const int num_regs = gdbarch_num_regs (gdbarch); | 
|  | int i; | 
|  |  | 
|  | /* Reset the register values to their default state.  Register i's value | 
|  | is in register i.  */ | 
|  | for (i = 0; i < num_regs; i++) | 
|  | this_cache->saved_regs[i].set_realreg (i); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* 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 | 
|  | mips32_scan_prologue (struct gdbarch *gdbarch, | 
|  | CORE_ADDR start_pc, CORE_ADDR limit_pc, | 
|  | frame_info_ptr this_frame, | 
|  | struct mips_frame_cache *this_cache) | 
|  | { | 
|  | int prev_non_prologue_insn; | 
|  | int this_non_prologue_insn; | 
|  | int non_prologue_insns; | 
|  | CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for | 
|  | frame-pointer.  */ | 
|  | int prev_delay_slot; | 
|  | CORE_ADDR prev_pc; | 
|  | CORE_ADDR cur_pc; | 
|  | CORE_ADDR sp; | 
|  | long frame_offset; | 
|  | int  frame_reg = MIPS_SP_REGNUM; | 
|  |  | 
|  | CORE_ADDR end_prologue_addr; | 
|  | int seen_sp_adjust = 0; | 
|  | int load_immediate_bytes = 0; | 
|  | int in_delay_slot; | 
|  | int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8); | 
|  |  | 
|  | /* 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; | 
|  |  | 
|  | restart: | 
|  | prev_non_prologue_insn = 0; | 
|  | non_prologue_insns = 0; | 
|  | prev_delay_slot = 0; | 
|  | 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.  */ | 
|  | frame_offset = 0; | 
|  | for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN32_SIZE) | 
|  | { | 
|  | unsigned long inst, high_word; | 
|  | long offset; | 
|  | int reg; | 
|  |  | 
|  | this_non_prologue_insn = 0; | 
|  | in_delay_slot = 0; | 
|  |  | 
|  | /* Fetch the instruction.  */ | 
|  | inst = (unsigned long) mips_fetch_instruction (gdbarch, ISA_MIPS, | 
|  | cur_pc, NULL); | 
|  |  | 
|  | /* Save some code by pre-extracting some useful fields.  */ | 
|  | high_word = (inst >> 16) & 0xffff; | 
|  | offset = ((inst & 0xffff) ^ 0x8000) - 0x8000; | 
|  | reg = high_word & 0x1f; | 
|  |  | 
|  | if (high_word == 0x27bd		/* addiu $sp,$sp,-i */ | 
|  | || high_word == 0x23bd	/* addi $sp,$sp,-i */ | 
|  | || high_word == 0x67bd)	/* daddiu $sp,$sp,-i */ | 
|  | { | 
|  | 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; | 
|  | seen_sp_adjust = 1; | 
|  | } | 
|  | else if (((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */ | 
|  | && !regsize_is_64_bits) | 
|  | { | 
|  | set_reg_offset (gdbarch, this_cache, reg, sp + offset); | 
|  | } | 
|  | else if (((high_word & 0xFFE0) == 0xffa0)	/* sd reg,offset($sp) */ | 
|  | && regsize_is_64_bits) | 
|  | { | 
|  | /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra.  */ | 
|  | set_reg_offset (gdbarch, this_cache, reg, sp + offset); | 
|  | } | 
|  | else if (high_word == 0x27be)	/* addiu $30,$sp,size */ | 
|  | { | 
|  | /* Old gcc frame, r30 is virtual frame pointer.  */ | 
|  | if (offset != frame_offset) | 
|  | frame_addr = sp + offset; | 
|  | else if (this_frame && frame_reg == MIPS_SP_REGNUM) | 
|  | { | 
|  | unsigned alloca_adjust; | 
|  |  | 
|  | frame_reg = 30; | 
|  | frame_addr = get_frame_register_signed | 
|  | (this_frame, gdbarch_num_regs (gdbarch) + 30); | 
|  | frame_offset = 0; | 
|  |  | 
|  | alloca_adjust = (unsigned) (frame_addr - (sp + offset)); | 
|  | if (alloca_adjust > 0) | 
|  | { | 
|  | /* FP > SP + frame_size.  This may be because of | 
|  | an alloca or somethings similar.  Fix sp to | 
|  | "pre-alloca" value, and try again.  */ | 
|  | sp += alloca_adjust; | 
|  | /* Need to reset the status of all registers.  Otherwise, | 
|  | we will hit a guard that prevents the new address | 
|  | for each register to be recomputed during the second | 
|  | pass.  */ | 
|  | reset_saved_regs (gdbarch, this_cache); | 
|  | goto restart; | 
|  | } | 
|  | } | 
|  | } | 
|  | /* move $30,$sp.  With different versions of gas this will be either | 
|  | `addu $30,$sp,$zero' or `or $30,$sp,$zero' or `daddu 30,sp,$0'. | 
|  | Accept any one of these.  */ | 
|  | else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d) | 
|  | { | 
|  | /* New gcc frame, virtual frame pointer is at r30 + frame_size.  */ | 
|  | if (this_frame && frame_reg == MIPS_SP_REGNUM) | 
|  | { | 
|  | unsigned alloca_adjust; | 
|  |  | 
|  | frame_reg = 30; | 
|  | frame_addr = get_frame_register_signed | 
|  | (this_frame, gdbarch_num_regs (gdbarch) + 30); | 
|  |  | 
|  | alloca_adjust = (unsigned) (frame_addr - sp); | 
|  | if (alloca_adjust > 0) | 
|  | { | 
|  | /* FP > SP + frame_size.  This may be because of | 
|  | an alloca or somethings similar.  Fix sp to | 
|  | "pre-alloca" value, and try again.  */ | 
|  | sp = frame_addr; | 
|  | /* Need to reset the status of all registers.  Otherwise, | 
|  | we will hit a guard that prevents the new address | 
|  | for each register to be recomputed during the second | 
|  | pass.  */ | 
|  | reset_saved_regs (gdbarch, this_cache); | 
|  | goto restart; | 
|  | } | 
|  | } | 
|  | } | 
|  | else if ((high_word & 0xFFE0) == 0xafc0 	/* sw reg,offset($30) */ | 
|  | && !regsize_is_64_bits) | 
|  | { | 
|  | set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset); | 
|  | } | 
|  | else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */ | 
|  | || (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */ | 
|  | || (inst & 0xFF9F07FF) == 0x00800021 /* move reg,$a0-$a3 */ | 
|  | || high_word == 0x3c1c /* lui $gp,n */ | 
|  | || high_word == 0x279c /* addiu $gp,$gp,n */ | 
|  | || high_word == 0x679c /* daddiu $gp,$gp,n */ | 
|  | || inst == 0x0399e021 /* addu $gp,$gp,$t9 */ | 
|  | || inst == 0x033ce021 /* addu $gp,$t9,$gp */ | 
|  | || inst == 0x0399e02d /* daddu $gp,$gp,$t9 */ | 
|  | || inst == 0x033ce02d /* daddu $gp,$t9,$gp */ | 
|  | ) | 
|  | { | 
|  | /* These instructions are part of the prologue, but we don't | 
|  | need to do anything special to handle them.  */ | 
|  | } | 
|  | /* The instructions below load $at or $t0 with an immediate | 
|  | value in preparation for a stack adjustment via | 
|  | subu $sp,$sp,[$at,$t0].  These instructions could also | 
|  | initialize a local variable, so we accept them only before | 
|  | a stack adjustment instruction was seen.  */ | 
|  | else if (!seen_sp_adjust | 
|  | && !prev_delay_slot | 
|  | && (high_word == 0x3c01 /* lui $at,n */ | 
|  | || high_word == 0x3c08 /* lui $t0,n */ | 
|  | || high_word == 0x3421 /* ori $at,$at,n */ | 
|  | || high_word == 0x3508 /* ori $t0,$t0,n */ | 
|  | || high_word == 0x3401 /* ori $at,$zero,n */ | 
|  | || high_word == 0x3408 /* ori $t0,$zero,n */ | 
|  | )) | 
|  | { | 
|  | load_immediate_bytes += MIPS_INSN32_SIZE;		/* FIXME!  */ | 
|  | } | 
|  | /* Check for branches and jumps.  The instruction in the delay | 
|  | slot can be a part of the prologue, so move forward once more.  */ | 
|  | else if (mips32_instruction_has_delay_slot (gdbarch, inst)) | 
|  | { | 
|  | in_delay_slot = 1; | 
|  | } | 
|  | /* This instruction is not an instruction typically found | 
|  | in a prologue, so we must have reached the end of the | 
|  | prologue.  */ | 
|  | 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) | 
|  | break; | 
|  |  | 
|  | prev_non_prologue_insn = this_non_prologue_insn; | 
|  | prev_delay_slot = in_delay_slot; | 
|  | prev_pc = cur_pc; | 
|  | } | 
|  |  | 
|  | if (this_cache != NULL) | 
|  | { | 
|  | this_cache->base = | 
|  | (get_frame_register_signed (this_frame, | 
|  | gdbarch_num_regs (gdbarch) + frame_reg) | 
|  | + frame_offset); | 
|  | /* FIXME: brobecker/2004-09-15: We should be able to get rid of | 
|  | this assignment below, eventually.  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; | 
|  |  | 
|  | /* In a frameless function, we might have incorrectly | 
|  | skipped some load immediate instructions.  Undo the skipping | 
|  | if the load immediate was not followed by a stack adjustment.  */ | 
|  | if (load_immediate_bytes && !seen_sp_adjust) | 
|  | end_prologue_addr -= load_immediate_bytes; | 
|  |  | 
|  | return end_prologue_addr; | 
|  | } | 
|  |  | 
|  | /* Heuristic unwinder for procedures using 32-bit instructions (covers | 
|  | both 32-bit and 64-bit MIPS ISAs).  Procedures using 16-bit | 
|  | instructions (a.k.a. MIPS16) are handled by the mips_insn16 | 
|  | unwinder.  Likewise microMIPS and the mips_micro unwinder. */ | 
|  |  | 
|  | static struct mips_frame_cache * | 
|  | mips_insn32_frame_cache (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; | 
|  |  | 
|  | mips32_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_insn32_frame_this_id (frame_info_ptr this_frame, void **this_cache, | 
|  | struct frame_id *this_id) | 
|  | { | 
|  | struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame, | 
|  | this_cache); | 
|  | /* This marks the outermost frame.  */ | 
|  | if (info->base == 0) | 
|  | return; | 
|  | (*this_id) = frame_id_build (info->base, get_frame_func (this_frame)); | 
|  | } | 
|  |  | 
|  | static struct value * | 
|  | mips_insn32_frame_prev_register (frame_info_ptr this_frame, | 
|  | void **this_cache, int regnum) | 
|  | { | 
|  | struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame, | 
|  | this_cache); | 
|  | return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum); | 
|  | } | 
|  |  | 
|  | static int | 
|  | mips_insn32_frame_sniffer (const struct frame_unwind *self, | 
|  | frame_info_ptr this_frame, void **this_cache) | 
|  | { | 
|  | CORE_ADDR pc = get_frame_pc (this_frame); | 
|  | if (mips_pc_is_mips (pc)) | 
|  | return 1; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static const struct frame_unwind mips_insn32_frame_unwind = | 
|  | { | 
|  | "mips insn32 prologue", | 
|  | NORMAL_FRAME, | 
|  | default_frame_unwind_stop_reason, | 
|  | mips_insn32_frame_this_id, | 
|  | mips_insn32_frame_prev_register, | 
|  | NULL, | 
|  | mips_insn32_frame_sniffer | 
|  | }; | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_insn32_frame_base_address (frame_info_ptr this_frame, | 
|  | void **this_cache) | 
|  | { | 
|  | struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame, | 
|  | this_cache); | 
|  | return info->base; | 
|  | } | 
|  |  | 
|  | static const struct frame_base mips_insn32_frame_base = | 
|  | { | 
|  | &mips_insn32_frame_unwind, | 
|  | mips_insn32_frame_base_address, | 
|  | mips_insn32_frame_base_address, | 
|  | mips_insn32_frame_base_address | 
|  | }; | 
|  |  | 
|  | static const struct frame_base * | 
|  | mips_insn32_frame_base_sniffer (frame_info_ptr this_frame) | 
|  | { | 
|  | CORE_ADDR pc = get_frame_pc (this_frame); | 
|  | if (mips_pc_is_mips (pc)) | 
|  | return &mips_insn32_frame_base; | 
|  | else | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | static struct trad_frame_cache * | 
|  | mips_stub_frame_cache (frame_info_ptr this_frame, void **this_cache) | 
|  | { | 
|  | CORE_ADDR pc; | 
|  | CORE_ADDR start_addr; | 
|  | CORE_ADDR stack_addr; | 
|  | struct trad_frame_cache *this_trad_cache; | 
|  | struct gdbarch *gdbarch = get_frame_arch (this_frame); | 
|  | int num_regs = gdbarch_num_regs (gdbarch); | 
|  |  | 
|  | if ((*this_cache) != NULL) | 
|  | return (struct trad_frame_cache *) (*this_cache); | 
|  | this_trad_cache = trad_frame_cache_zalloc (this_frame); | 
|  | (*this_cache) = this_trad_cache; | 
|  |  | 
|  | /* The return address is in the link register.  */ | 
|  | trad_frame_set_reg_realreg (this_trad_cache, | 
|  | gdbarch_pc_regnum (gdbarch), | 
|  | num_regs + MIPS_RA_REGNUM); | 
|  |  | 
|  | /* Frame ID, since it's a frameless / stackless function, no stack | 
|  | space is allocated and SP on entry is the current SP.  */ | 
|  | pc = get_frame_pc (this_frame); | 
|  | find_pc_partial_function (pc, NULL, &start_addr, NULL); | 
|  | stack_addr = get_frame_register_signed (this_frame, | 
|  | num_regs + MIPS_SP_REGNUM); | 
|  | trad_frame_set_id (this_trad_cache, frame_id_build (stack_addr, start_addr)); | 
|  |  | 
|  | /* Assume that the frame's base is the same as the | 
|  | stack-pointer.  */ | 
|  | trad_frame_set_this_base (this_trad_cache, stack_addr); | 
|  |  | 
|  | return this_trad_cache; | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_stub_frame_this_id (frame_info_ptr this_frame, void **this_cache, | 
|  | struct frame_id *this_id) | 
|  | { | 
|  | struct trad_frame_cache *this_trad_cache | 
|  | = mips_stub_frame_cache (this_frame, this_cache); | 
|  | trad_frame_get_id (this_trad_cache, this_id); | 
|  | } | 
|  |  | 
|  | static struct value * | 
|  | mips_stub_frame_prev_register (frame_info_ptr this_frame, | 
|  | void **this_cache, int regnum) | 
|  | { | 
|  | struct trad_frame_cache *this_trad_cache | 
|  | = mips_stub_frame_cache (this_frame, this_cache); | 
|  | return trad_frame_get_register (this_trad_cache, this_frame, regnum); | 
|  | } | 
|  |  | 
|  | static int | 
|  | mips_stub_frame_sniffer (const struct frame_unwind *self, | 
|  | frame_info_ptr this_frame, void **this_cache) | 
|  | { | 
|  | gdb_byte dummy[4]; | 
|  | CORE_ADDR pc = get_frame_address_in_block (this_frame); | 
|  | struct bound_minimal_symbol msym; | 
|  |  | 
|  | /* Use the stub unwinder for unreadable code.  */ | 
|  | if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0) | 
|  | return 1; | 
|  |  | 
|  | if (in_plt_section (pc) || in_mips_stubs_section (pc)) | 
|  | return 1; | 
|  |  | 
|  | /* Calling a PIC function from a non-PIC function passes through a | 
|  | stub.  The stub for foo is named ".pic.foo".  */ | 
|  | msym = lookup_minimal_symbol_by_pc (pc); | 
|  | if (msym.minsym != NULL | 
|  | && msym.minsym->linkage_name () != NULL | 
|  | && startswith (msym.minsym->linkage_name (), ".pic.")) | 
|  | return 1; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static const struct frame_unwind mips_stub_frame_unwind = | 
|  | { | 
|  | "mips stub", | 
|  | NORMAL_FRAME, | 
|  | default_frame_unwind_stop_reason, | 
|  | mips_stub_frame_this_id, | 
|  | mips_stub_frame_prev_register, | 
|  | NULL, | 
|  | mips_stub_frame_sniffer | 
|  | }; | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_stub_frame_base_address (frame_info_ptr this_frame, | 
|  | void **this_cache) | 
|  | { | 
|  | struct trad_frame_cache *this_trad_cache | 
|  | = mips_stub_frame_cache (this_frame, this_cache); | 
|  | return trad_frame_get_this_base (this_trad_cache); | 
|  | } | 
|  |  | 
|  | static const struct frame_base mips_stub_frame_base = | 
|  | { | 
|  | &mips_stub_frame_unwind, | 
|  | mips_stub_frame_base_address, | 
|  | mips_stub_frame_base_address, | 
|  | mips_stub_frame_base_address | 
|  | }; | 
|  |  | 
|  | static const struct frame_base * | 
|  | mips_stub_frame_base_sniffer (frame_info_ptr this_frame) | 
|  | { | 
|  | if (mips_stub_frame_sniffer (&mips_stub_frame_unwind, this_frame, NULL)) | 
|  | return &mips_stub_frame_base; | 
|  | else | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /* mips_addr_bits_remove - remove useless address bits  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr) | 
|  | { | 
|  | mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch); | 
|  |  | 
|  | if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL)) | 
|  | /* This hack is a work-around for existing boards using PMON, the | 
|  | simulator, and any other 64-bit targets that doesn't have true | 
|  | 64-bit addressing.  On these targets, the upper 32 bits of | 
|  | addresses are ignored by the hardware.  Thus, the PC or SP are | 
|  | likely to have been sign extended to all 1s by instruction | 
|  | sequences that load 32-bit addresses.  For example, a typical | 
|  | piece of code that loads an address is this: | 
|  |  | 
|  | lui $r2, <upper 16 bits> | 
|  | ori $r2, <lower 16 bits> | 
|  |  | 
|  | But the lui sign-extends the value such that the upper 32 bits | 
|  | may be all 1s.  The workaround is simply to mask off these | 
|  | bits.  In the future, gcc may be changed to support true 64-bit | 
|  | addressing, and this masking will have to be disabled.  */ | 
|  | return addr &= 0xffffffffUL; | 
|  | else | 
|  | return addr; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Checks for an atomic sequence of instructions beginning with a LL/LLD | 
|  | instruction and ending with a SC/SCD instruction.  If such a sequence | 
|  | is found, attempt to step through it.  A breakpoint is placed at the end of | 
|  | the sequence.  */ | 
|  |  | 
|  | /* Instructions used during single-stepping of atomic sequences, standard | 
|  | ISA version.  */ | 
|  | #define LL_OPCODE 0x30 | 
|  | #define LLD_OPCODE 0x34 | 
|  | #define SC_OPCODE 0x38 | 
|  | #define SCD_OPCODE 0x3c | 
|  |  | 
|  | static std::vector<CORE_ADDR> | 
|  | mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR breaks[2] = {CORE_ADDR_MAX, CORE_ADDR_MAX}; | 
|  | CORE_ADDR loc = pc; | 
|  | CORE_ADDR branch_bp; /* Breakpoint at branch instruction's destination.  */ | 
|  | ULONGEST insn; | 
|  | int insn_count; | 
|  | int index; | 
|  | int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */ | 
|  | const int atomic_sequence_length = 16; /* Instruction sequence length.  */ | 
|  |  | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL); | 
|  | /* Assume all atomic sequences start with a ll/lld instruction.  */ | 
|  | if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE) | 
|  | return {}; | 
|  |  | 
|  | /* Assume that no atomic sequence is longer than "atomic_sequence_length" | 
|  | instructions.  */ | 
|  | for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count) | 
|  | { | 
|  | int is_branch = 0; | 
|  | loc += MIPS_INSN32_SIZE; | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL); | 
|  |  | 
|  | /* Assume that there is at most one branch in the atomic | 
|  | sequence.  If a branch is found, put a breakpoint in its | 
|  | destination address.  */ | 
|  | switch (itype_op (insn)) | 
|  | { | 
|  | case 0: /* SPECIAL */ | 
|  | if (rtype_funct (insn) >> 1 == 4) /* JR, JALR */ | 
|  | return {}; /* fallback to the standard single-step code.  */ | 
|  | break; | 
|  | case 1: /* REGIMM */ | 
|  | is_branch = ((itype_rt (insn) & 0xc) == 0 /* B{LT,GE}Z* */ | 
|  | || ((itype_rt (insn) & 0x1e) == 0 | 
|  | && itype_rs (insn) == 0)); /* BPOSGE* */ | 
|  | break; | 
|  | case 2: /* J */ | 
|  | case 3: /* JAL */ | 
|  | return {}; /* fallback to the standard single-step code.  */ | 
|  | case 4: /* BEQ */ | 
|  | case 5: /* BNE */ | 
|  | case 6: /* BLEZ */ | 
|  | case 7: /* BGTZ */ | 
|  | case 20: /* BEQL */ | 
|  | case 21: /* BNEL */ | 
|  | case 22: /* BLEZL */ | 
|  | case 23: /* BGTTL */ | 
|  | is_branch = 1; | 
|  | break; | 
|  | case 17: /* COP1 */ | 
|  | is_branch = ((itype_rs (insn) == 9 || itype_rs (insn) == 10) | 
|  | && (itype_rt (insn) & 0x2) == 0); | 
|  | if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */ | 
|  | break; | 
|  | /* Fall through.  */ | 
|  | case 18: /* COP2 */ | 
|  | case 19: /* COP3 */ | 
|  | is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */ | 
|  | break; | 
|  | } | 
|  | if (is_branch) | 
|  | { | 
|  | branch_bp = loc + mips32_relative_offset (insn) + 4; | 
|  | if (last_breakpoint >= 1) | 
|  | return {}; /* More than one branch found, fallback to the | 
|  | standard single-step code.  */ | 
|  | breaks[1] = branch_bp; | 
|  | last_breakpoint++; | 
|  | } | 
|  |  | 
|  | if (itype_op (insn) == SC_OPCODE || itype_op (insn) == SCD_OPCODE) | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* Assume that the atomic sequence ends with a sc/scd instruction.  */ | 
|  | if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE) | 
|  | return {}; | 
|  |  | 
|  | loc += MIPS_INSN32_SIZE; | 
|  |  | 
|  | /* Insert a breakpoint right after the end of the atomic sequence.  */ | 
|  | breaks[0] = loc; | 
|  |  | 
|  | /* Check for duplicated breakpoints.  Check also for a breakpoint | 
|  | placed (branch instruction's destination) in the atomic sequence.  */ | 
|  | if (last_breakpoint && pc <= breaks[1] && breaks[1] <= breaks[0]) | 
|  | last_breakpoint = 0; | 
|  |  | 
|  | std::vector<CORE_ADDR> next_pcs; | 
|  |  | 
|  | /* Effectively inserts the breakpoints.  */ | 
|  | for (index = 0; index <= last_breakpoint; index++) | 
|  | next_pcs.push_back (breaks[index]); | 
|  |  | 
|  | return next_pcs; | 
|  | } | 
|  |  | 
|  | static std::vector<CORE_ADDR> | 
|  | micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch, | 
|  | CORE_ADDR pc) | 
|  | { | 
|  | const int atomic_sequence_length = 16; /* Instruction sequence length.  */ | 
|  | int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */ | 
|  | CORE_ADDR breaks[2] = {CORE_ADDR_MAX, CORE_ADDR_MAX}; | 
|  | CORE_ADDR branch_bp = 0; /* Breakpoint at branch instruction's | 
|  | destination.  */ | 
|  | CORE_ADDR loc = pc; | 
|  | int sc_found = 0; | 
|  | ULONGEST insn; | 
|  | int insn_count; | 
|  | int index; | 
|  |  | 
|  | /* Assume all atomic sequences start with a ll/lld instruction.  */ | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL); | 
|  | if (micromips_op (insn) != 0x18)	/* POOL32C: bits 011000 */ | 
|  | return {}; | 
|  | loc += MIPS_INSN16_SIZE; | 
|  | insn <<= 16; | 
|  | insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL); | 
|  | if ((b12s4_op (insn) & 0xb) != 0x3)	/* LL, LLD: bits 011000 0x11 */ | 
|  | return {}; | 
|  | loc += MIPS_INSN16_SIZE; | 
|  |  | 
|  | /* Assume all atomic sequences end with an sc/scd instruction.  Assume | 
|  | that no atomic sequence is longer than "atomic_sequence_length" | 
|  | instructions.  */ | 
|  | for (insn_count = 0; | 
|  | !sc_found && insn_count < atomic_sequence_length; | 
|  | ++insn_count) | 
|  | { | 
|  | int is_branch = 0; | 
|  |  | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL); | 
|  | loc += MIPS_INSN16_SIZE; | 
|  |  | 
|  | /* Assume that there is at most one conditional branch in the | 
|  | atomic sequence.  If a branch is found, put a breakpoint in | 
|  | its destination address.  */ | 
|  | switch (mips_insn_size (ISA_MICROMIPS, insn)) | 
|  | { | 
|  | /* 32-bit instructions.  */ | 
|  | case 2 * MIPS_INSN16_SIZE: | 
|  | switch (micromips_op (insn)) | 
|  | { | 
|  | case 0x10: /* POOL32I: bits 010000 */ | 
|  | if ((b5s5_op (insn) & 0x18) != 0x0 | 
|  | /* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */ | 
|  | /* BLEZ, BNEZC, BGTZ, BEQZC: 010000 001xx */ | 
|  | && (b5s5_op (insn) & 0x1d) != 0x11 | 
|  | /* BLTZALS, BGEZALS: bits 010000 100x1 */ | 
|  | && ((b5s5_op (insn) & 0x1e) != 0x14 | 
|  | || (insn & 0x3) != 0x0) | 
|  | /* BC2F, BC2T: bits 010000 1010x xxx00 */ | 
|  | && (b5s5_op (insn) & 0x1e) != 0x1a | 
|  | /* BPOSGE64, BPOSGE32: bits 010000 1101x */ | 
|  | && ((b5s5_op (insn) & 0x1e) != 0x1c | 
|  | || (insn & 0x3) != 0x0) | 
|  | /* BC1F, BC1T: bits 010000 1110x xxx00 */ | 
|  | && ((b5s5_op (insn) & 0x1c) != 0x1c | 
|  | || (insn & 0x3) != 0x1)) | 
|  | /* BC1ANY*: bits 010000 111xx xxx01 */ | 
|  | break; | 
|  | /* Fall through.  */ | 
|  |  | 
|  | case 0x25: /* BEQ: bits 100101 */ | 
|  | case 0x2d: /* BNE: bits 101101 */ | 
|  | insn <<= 16; | 
|  | insn |= mips_fetch_instruction (gdbarch, | 
|  | ISA_MICROMIPS, loc, NULL); | 
|  | branch_bp = (loc + MIPS_INSN16_SIZE | 
|  | + micromips_relative_offset16 (insn)); | 
|  | is_branch = 1; | 
|  | break; | 
|  |  | 
|  | case 0x00: /* POOL32A: bits 000000 */ | 
|  | insn <<= 16; | 
|  | insn |= mips_fetch_instruction (gdbarch, | 
|  | ISA_MICROMIPS, loc, NULL); | 
|  | if (b0s6_op (insn) != 0x3c | 
|  | /* POOL32Axf: bits 000000 ... 111100 */ | 
|  | || (b6s10_ext (insn) & 0x2bf) != 0x3c) | 
|  | /* JALR, JALR.HB: 000000 000x111100 111100 */ | 
|  | /* JALRS, JALRS.HB: 000000 010x111100 111100 */ | 
|  | break; | 
|  | /* Fall through.  */ | 
|  |  | 
|  | case 0x1d: /* JALS: bits 011101 */ | 
|  | case 0x35: /* J: bits 110101 */ | 
|  | case 0x3d: /* JAL: bits 111101 */ | 
|  | case 0x3c: /* JALX: bits 111100 */ | 
|  | return {}; /* Fall back to the standard single-step code. */ | 
|  |  | 
|  | case 0x18: /* POOL32C: bits 011000 */ | 
|  | if ((b12s4_op (insn) & 0xb) == 0xb) | 
|  | /* SC, SCD: bits 011000 1x11 */ | 
|  | sc_found = 1; | 
|  | break; | 
|  | } | 
|  | loc += MIPS_INSN16_SIZE; | 
|  | break; | 
|  |  | 
|  | /* 16-bit instructions.  */ | 
|  | case MIPS_INSN16_SIZE: | 
|  | switch (micromips_op (insn)) | 
|  | { | 
|  | case 0x23: /* BEQZ16: bits 100011 */ | 
|  | case 0x2b: /* BNEZ16: bits 101011 */ | 
|  | branch_bp = loc + micromips_relative_offset7 (insn); | 
|  | is_branch = 1; | 
|  | break; | 
|  |  | 
|  | case 0x11: /* POOL16C: bits 010001 */ | 
|  | if ((b5s5_op (insn) & 0x1c) != 0xc | 
|  | /* JR16, JRC, JALR16, JALRS16: 010001 011xx */ | 
|  | && b5s5_op (insn) != 0x18) | 
|  | /* JRADDIUSP: bits 010001 11000 */ | 
|  | break; | 
|  | return {}; /* Fall back to the standard single-step code. */ | 
|  |  | 
|  | case 0x33: /* B16: bits 110011 */ | 
|  | return {}; /* Fall back to the standard single-step code. */ | 
|  | } | 
|  | break; | 
|  | } | 
|  | if (is_branch) | 
|  | { | 
|  | if (last_breakpoint >= 1) | 
|  | return {}; /* More than one branch found, fallback to the | 
|  | standard single-step code.  */ | 
|  | breaks[1] = branch_bp; | 
|  | last_breakpoint++; | 
|  | } | 
|  | } | 
|  | if (!sc_found) | 
|  | return {}; | 
|  |  | 
|  | /* Insert a breakpoint right after the end of the atomic sequence.  */ | 
|  | breaks[0] = loc; | 
|  |  | 
|  | /* Check for duplicated breakpoints.  Check also for a breakpoint | 
|  | placed (branch instruction's destination) in the atomic sequence */ | 
|  | if (last_breakpoint && pc <= breaks[1] && breaks[1] <= breaks[0]) | 
|  | last_breakpoint = 0; | 
|  |  | 
|  | std::vector<CORE_ADDR> next_pcs; | 
|  |  | 
|  | /* Effectively inserts the breakpoints.  */ | 
|  | for (index = 0; index <= last_breakpoint; index++) | 
|  | next_pcs.push_back (breaks[index]); | 
|  |  | 
|  | return next_pcs; | 
|  | } | 
|  |  | 
|  | static std::vector<CORE_ADDR> | 
|  | deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | if (mips_pc_is_mips (pc)) | 
|  | return mips_deal_with_atomic_sequence (gdbarch, pc); | 
|  | else if (mips_pc_is_micromips (gdbarch, pc)) | 
|  | return micromips_deal_with_atomic_sequence (gdbarch, pc); | 
|  | else | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | /* mips_software_single_step() is called just before we want to resume | 
|  | the inferior, if we want to single-step it but there is no hardware | 
|  | or kernel single-step support (MIPS on GNU/Linux for example).  We find | 
|  | the target of the coming instruction and breakpoint it.  */ | 
|  |  | 
|  | std::vector<CORE_ADDR> | 
|  | mips_software_single_step (struct regcache *regcache) | 
|  | { | 
|  | struct gdbarch *gdbarch = regcache->arch (); | 
|  | CORE_ADDR pc, next_pc; | 
|  |  | 
|  | pc = regcache_read_pc (regcache); | 
|  | std::vector<CORE_ADDR> next_pcs = deal_with_atomic_sequence (gdbarch, pc); | 
|  |  | 
|  | if (!next_pcs.empty ()) | 
|  | return next_pcs; | 
|  |  | 
|  | next_pc = mips_next_pc (regcache, pc); | 
|  |  | 
|  | return {next_pc}; | 
|  | } | 
|  |  | 
|  | /* Test whether the PC points to the return instruction at the | 
|  | end of a function.  */ | 
|  |  | 
|  | static int | 
|  | mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | ULONGEST insn; | 
|  | ULONGEST hint; | 
|  |  | 
|  | /* This used to check for MIPS16, but this piece of code is never | 
|  | called for MIPS16 functions.  And likewise microMIPS ones.  */ | 
|  | gdb_assert (mips_pc_is_mips (pc)); | 
|  |  | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL); | 
|  | hint = 0x7c0; | 
|  | return (insn & ~hint) == 0x3e00008;			/* jr(.hb) $ra */ | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This fencepost looks highly suspicious to me.  Removing it also | 
|  | seems suspicious as it could affect remote debugging across serial | 
|  | lines.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | heuristic_proc_start (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR start_pc; | 
|  | CORE_ADDR fence; | 
|  | int instlen; | 
|  | int seen_adjsp = 0; | 
|  | struct inferior *inf; | 
|  |  | 
|  | pc = gdbarch_addr_bits_remove (gdbarch, pc); | 
|  | start_pc = pc; | 
|  | fence = start_pc - heuristic_fence_post; | 
|  | if (start_pc == 0) | 
|  | return 0; | 
|  |  | 
|  | if (heuristic_fence_post == -1 || fence < VM_MIN_ADDRESS) | 
|  | fence = VM_MIN_ADDRESS; | 
|  |  | 
|  | instlen = mips_pc_is_mips (pc) ? MIPS_INSN32_SIZE : MIPS_INSN16_SIZE; | 
|  |  | 
|  | inf = current_inferior (); | 
|  |  | 
|  | /* Search back for previous return.  */ | 
|  | for (start_pc -= instlen;; start_pc -= instlen) | 
|  | if (start_pc < fence) | 
|  | { | 
|  | /* It's not clear to me why we reach this point when | 
|  | stop_soon, but with this test, at least we | 
|  | don't print out warnings for every child forked (eg, on | 
|  | decstation).  22apr93 rich@cygnus.com.  */ | 
|  | if (inf->control.stop_soon == NO_STOP_QUIETLY) | 
|  | { | 
|  | static int blurb_printed = 0; | 
|  |  | 
|  | warning (_("GDB can't find the start of the function at %s."), | 
|  | paddress (gdbarch, pc)); | 
|  |  | 
|  | if (!blurb_printed) | 
|  | { | 
|  | /* This actually happens frequently in embedded | 
|  | development, when you first connect to a board | 
|  | and your stack pointer and pc are nowhere in | 
|  | particular.  This message needs to give people | 
|  | in that situation enough information to | 
|  | determine that it's no big deal.  */ | 
|  | gdb_printf ("\n\ | 
|  | GDB is unable to find the start of the function at %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 %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", | 
|  | paddress (gdbarch, pc), paddress (gdbarch, pc)); | 
|  | blurb_printed = 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | else if (mips_pc_is_mips16 (gdbarch, start_pc)) | 
|  | { | 
|  | unsigned short inst; | 
|  |  | 
|  | /* On MIPS16, any one of the following is likely to be the | 
|  | start of a function: | 
|  | extend save | 
|  | save | 
|  | entry | 
|  | addiu sp,-n | 
|  | daddiu sp,-n | 
|  | extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n'.  */ | 
|  | inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, start_pc, NULL); | 
|  | if ((inst & 0xff80) == 0x6480)		/* save */ | 
|  | { | 
|  | if (start_pc - instlen >= fence) | 
|  | { | 
|  | inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, | 
|  | start_pc - instlen, NULL); | 
|  | if ((inst & 0xf800) == 0xf000)	/* extend */ | 
|  | start_pc -= instlen; | 
|  | } | 
|  | break; | 
|  | } | 
|  | else if (((inst & 0xf81f) == 0xe809 | 
|  | && (inst & 0x700) != 0x700)	/* entry */ | 
|  | || (inst & 0xff80) == 0x6380	/* addiu sp,-n */ | 
|  | || (inst & 0xff80) == 0xfb80	/* daddiu sp,-n */ | 
|  | || ((inst & 0xf810) == 0xf010 && seen_adjsp))	/* extend -n */ | 
|  | break; | 
|  | else if ((inst & 0xff00) == 0x6300	/* addiu sp */ | 
|  | || (inst & 0xff00) == 0xfb00)	/* daddiu sp */ | 
|  | seen_adjsp = 1; | 
|  | else | 
|  | seen_adjsp = 0; | 
|  | } | 
|  | else if (mips_pc_is_micromips (gdbarch, start_pc)) | 
|  | { | 
|  | ULONGEST insn; | 
|  | int stop = 0; | 
|  | long offset; | 
|  | int dreg; | 
|  | int sreg; | 
|  |  | 
|  | /* On microMIPS, any one of the following is likely to be the | 
|  | start of a function: | 
|  | ADDIUSP -imm | 
|  | (D)ADDIU $sp, -imm | 
|  | LUI $gp, imm  */ | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL); | 
|  | switch (micromips_op (insn)) | 
|  | { | 
|  | case 0xc: /* ADDIU: bits 001100 */ | 
|  | case 0x17: /* DADDIU: bits 010111 */ | 
|  | sreg = b0s5_reg (insn); | 
|  | dreg = b5s5_reg (insn); | 
|  | insn <<= 16; | 
|  | insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, | 
|  | pc + MIPS_INSN16_SIZE, NULL); | 
|  | offset = (b0s16_imm (insn) ^ 0x8000) - 0x8000; | 
|  | if (sreg == MIPS_SP_REGNUM && dreg == MIPS_SP_REGNUM | 
|  | /* (D)ADDIU $sp, imm */ | 
|  | && offset < 0) | 
|  | stop = 1; | 
|  | break; | 
|  |  | 
|  | case 0x10: /* POOL32I: bits 010000 */ | 
|  | if (b5s5_op (insn) == 0xd | 
|  | /* LUI: bits 010000 001101 */ | 
|  | && b0s5_reg (insn >> 16) == 28) | 
|  | /* LUI $gp, imm */ | 
|  | stop = 1; | 
|  | break; | 
|  |  | 
|  | case 0x13: /* POOL16D: bits 010011 */ | 
|  | if ((insn & 0x1) == 0x1) | 
|  | /* ADDIUSP: bits 010011 1 */ | 
|  | { | 
|  | offset = micromips_decode_imm9 (b1s9_imm (insn)); | 
|  | if (offset < 0) | 
|  | /* ADDIUSP -imm */ | 
|  | stop = 1; | 
|  | } | 
|  | else | 
|  | /* ADDIUS5: bits 010011 0 */ | 
|  | { | 
|  | dreg = b5s5_reg (insn); | 
|  | offset = (b1s4_imm (insn) ^ 8) - 8; | 
|  | if (dreg == MIPS_SP_REGNUM && offset < 0) | 
|  | /* ADDIUS5  $sp, -imm */ | 
|  | stop = 1; | 
|  | } | 
|  | break; | 
|  | } | 
|  | if (stop) | 
|  | break; | 
|  | } | 
|  | else if (mips_about_to_return (gdbarch, start_pc)) | 
|  | { | 
|  | /* Skip return and its delay slot.  */ | 
|  | start_pc += 2 * MIPS_INSN32_SIZE; | 
|  | break; | 
|  | } | 
|  |  | 
|  | return start_pc; | 
|  | } | 
|  |  | 
|  | struct mips_objfile_private | 
|  | { | 
|  | bfd_size_type size; | 
|  | char *contents; | 
|  | }; | 
|  |  | 
|  | /* According to the current ABI, should the type be passed in a | 
|  | floating-point register (assuming that there is space)?  When there | 
|  | is no FPU, FP are not even considered as possible candidates for | 
|  | FP registers and, consequently this returns false - forces FP | 
|  | arguments into integer registers.  */ | 
|  |  | 
|  | static int | 
|  | fp_register_arg_p (struct gdbarch *gdbarch, enum type_code typecode, | 
|  | struct type *arg_type) | 
|  | { | 
|  | return ((typecode == TYPE_CODE_FLT | 
|  | || (mips_eabi (gdbarch) | 
|  | && (typecode == TYPE_CODE_STRUCT | 
|  | || typecode == TYPE_CODE_UNION) | 
|  | && arg_type->num_fields () == 1 | 
|  | && check_typedef (arg_type->field (0).type ())->code () | 
|  | == TYPE_CODE_FLT)) | 
|  | && mips_get_fpu_type (gdbarch) != MIPS_FPU_NONE); | 
|  | } | 
|  |  | 
|  | /* On o32, argument passing in GPRs depends on the alignment of the type being | 
|  | passed.  Return 1 if this type must be aligned to a doubleword boundary.  */ | 
|  |  | 
|  | static int | 
|  | mips_type_needs_double_align (struct type *type) | 
|  | { | 
|  | enum type_code typecode = type->code (); | 
|  |  | 
|  | if (typecode == TYPE_CODE_FLT && type->length () == 8) | 
|  | return 1; | 
|  | else if (typecode == TYPE_CODE_STRUCT) | 
|  | { | 
|  | if (type->num_fields () < 1) | 
|  | return 0; | 
|  | return mips_type_needs_double_align (type->field (0).type ()); | 
|  | } | 
|  | else if (typecode == TYPE_CODE_UNION) | 
|  | { | 
|  | int i, n; | 
|  |  | 
|  | n = type->num_fields (); | 
|  | for (i = 0; i < n; i++) | 
|  | if (mips_type_needs_double_align (type->field (i).type ())) | 
|  | return 1; | 
|  | return 0; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Adjust the address downward (direction of stack growth) so that it | 
|  | is correctly aligned for a new stack frame.  */ | 
|  | static CORE_ADDR | 
|  | mips_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr) | 
|  | { | 
|  | return align_down (addr, 16); | 
|  | } | 
|  |  | 
|  | /* Implement the "push_dummy_code" gdbarch method.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, | 
|  | CORE_ADDR funaddr, struct value **args, | 
|  | int nargs, struct type *value_type, | 
|  | CORE_ADDR *real_pc, CORE_ADDR *bp_addr, | 
|  | struct regcache *regcache) | 
|  | { | 
|  | static gdb_byte nop_insn[] = { 0, 0, 0, 0 }; | 
|  | CORE_ADDR nop_addr; | 
|  | CORE_ADDR bp_slot; | 
|  |  | 
|  | /* Reserve enough room on the stack for our breakpoint instruction.  */ | 
|  | bp_slot = sp - sizeof (nop_insn); | 
|  |  | 
|  | /* Return to microMIPS mode if calling microMIPS code to avoid | 
|  | triggering an address error exception on processors that only | 
|  | support microMIPS execution.  */ | 
|  | *bp_addr = (mips_pc_is_micromips (gdbarch, funaddr) | 
|  | ? make_compact_addr (bp_slot) : bp_slot); | 
|  |  | 
|  | /* The breakpoint layer automatically adjusts the address of | 
|  | breakpoints inserted in a branch delay slot.  With enough | 
|  | bad luck, the 4 bytes located just before our breakpoint | 
|  | instruction could look like a branch instruction, and thus | 
|  | trigger the adjustement, and break the function call entirely. | 
|  | So, we reserve those 4 bytes and write a nop instruction | 
|  | to prevent that from happening.  */ | 
|  | nop_addr = bp_slot - sizeof (nop_insn); | 
|  | write_memory (nop_addr, nop_insn, sizeof (nop_insn)); | 
|  | sp = mips_frame_align (gdbarch, nop_addr); | 
|  |  | 
|  | /* Inferior resumes at the function entry point.  */ | 
|  | *real_pc = funaddr; | 
|  |  | 
|  | return sp; | 
|  | } | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, | 
|  | struct regcache *regcache, CORE_ADDR bp_addr, | 
|  | int nargs, struct value **args, CORE_ADDR sp, | 
|  | function_call_return_method return_method, | 
|  | CORE_ADDR struct_addr) | 
|  | { | 
|  | int argreg; | 
|  | int float_argreg; | 
|  | int argnum; | 
|  | int arg_space = 0; | 
|  | int stack_offset = 0; | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | CORE_ADDR func_addr = find_function_addr (function, NULL); | 
|  | int abi_regsize = mips_abi_regsize (gdbarch); | 
|  |  | 
|  | /* For shared libraries, "t9" needs to point at the function | 
|  | address.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr); | 
|  |  | 
|  | /* Set the return address register to point to the entry point of | 
|  | the program, where a breakpoint lies in wait.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr); | 
|  |  | 
|  | /* First ensure that the stack and structure return address (if any) | 
|  | are properly aligned.  The stack has to be at least 64-bit | 
|  | aligned even on 32-bit machines, because doubles must be 64-bit | 
|  | aligned.  For n32 and n64, stack frames need to be 128-bit | 
|  | aligned, so we round to this widest known alignment.  */ | 
|  |  | 
|  | sp = align_down (sp, 16); | 
|  | struct_addr = align_down (struct_addr, 16); | 
|  |  | 
|  | /* Now make space on the stack for the args.  We allocate more | 
|  | than necessary for EABI, because the first few arguments are | 
|  | passed in registers, but that's OK.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | arg_space += align_up (args[argnum]->type ()->length (), | 
|  | abi_regsize); | 
|  | sp -= align_up (arg_space, 16); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_eabi_push_dummy_call: sp=%s allocated %ld\n", | 
|  | paddress (gdbarch, sp), | 
|  | (long) align_up (arg_space, 16)); | 
|  |  | 
|  | /* Initialize the integer and float register pointers.  */ | 
|  | argreg = MIPS_A0_REGNUM; | 
|  | float_argreg = mips_fpa0_regnum (gdbarch); | 
|  |  | 
|  | /* The struct_return pointer occupies the first parameter-passing reg.  */ | 
|  | if (return_method == return_method_struct) | 
|  | { | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_eabi_push_dummy_call: " | 
|  | "struct_return reg=%d %s\n", | 
|  | argreg, paddress (gdbarch, struct_addr)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg++, struct_addr); | 
|  | } | 
|  |  | 
|  | /* Now load as many as possible of the first arguments into | 
|  | registers, and push the rest onto the stack.  Loop thru args | 
|  | from first to last.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | { | 
|  | const gdb_byte *val; | 
|  | /* This holds the address of structures that are passed by | 
|  | reference.  */ | 
|  | gdb_byte ref_valbuf[MAX_MIPS_ABI_REGSIZE]; | 
|  | struct value *arg = args[argnum]; | 
|  | struct type *arg_type = check_typedef (arg->type ()); | 
|  | int len = arg_type->length (); | 
|  | enum type_code typecode = arg_type->code (); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_eabi_push_dummy_call: %d len=%d type=%d", | 
|  | argnum + 1, len, (int) typecode); | 
|  |  | 
|  | /* The EABI passes structures that do not fit in a register by | 
|  | reference.  */ | 
|  | if (len > abi_regsize | 
|  | && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) | 
|  | { | 
|  | gdb_assert (abi_regsize <= ARRAY_SIZE (ref_valbuf)); | 
|  | store_unsigned_integer (ref_valbuf, abi_regsize, byte_order, | 
|  | arg->address ()); | 
|  | typecode = TYPE_CODE_PTR; | 
|  | len = abi_regsize; | 
|  | val = ref_valbuf; | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " push"); | 
|  | } | 
|  | else | 
|  | val = arg->contents ().data (); | 
|  |  | 
|  | /* 32-bit ABIs always start floating point arguments in an | 
|  | even-numbered floating point register.  Round the FP register | 
|  | up before the check to see if there are any FP registers | 
|  | left.  Non MIPS_EABI targets also pass the FP in the integer | 
|  | registers so also round up normal registers.  */ | 
|  | if (abi_regsize < 8 && fp_register_arg_p (gdbarch, typecode, arg_type)) | 
|  | { | 
|  | if ((float_argreg & 1)) | 
|  | float_argreg++; | 
|  | } | 
|  |  | 
|  | /* Floating point arguments passed in registers have to be | 
|  | treated specially.  On 32-bit architectures, doubles | 
|  | are passed in register pairs; the even register gets | 
|  | the low word, and the odd register gets the high word. | 
|  | On non-EABI processors, the first two floating point arguments are | 
|  | also copied to general registers, because MIPS16 functions | 
|  | don't use float registers for arguments.  This duplication of | 
|  | arguments in general registers can't hurt non-MIPS16 functions | 
|  | because those registers are normally skipped.  */ | 
|  | /* MIPS_EABI squeezes a struct that contains a single floating | 
|  | point value into an FP register instead of pushing it onto the | 
|  | stack.  */ | 
|  | if (fp_register_arg_p (gdbarch, typecode, arg_type) | 
|  | && float_argreg <= mips_last_fp_arg_regnum (gdbarch)) | 
|  | { | 
|  | /* EABI32 will pass doubles in consecutive registers, even on | 
|  | 64-bit cores.  At one time, we used to check the size of | 
|  | `float_argreg' to determine whether or not to pass doubles | 
|  | in consecutive registers, but this is not sufficient for | 
|  | making the ABI determination.  */ | 
|  | if (len == 8 && mips_abi (gdbarch) == MIPS_ABI_EABI32) | 
|  | { | 
|  | int low_offset = gdbarch_byte_order (gdbarch) | 
|  | == BFD_ENDIAN_BIG ? 4 : 0; | 
|  | long regval; | 
|  |  | 
|  | /* Write the low word of the double to the even register(s).  */ | 
|  | regval = extract_signed_integer (val + low_offset, | 
|  | 4, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, phex (regval, 4)); | 
|  | regcache_cooked_write_signed (regcache, float_argreg++, regval); | 
|  |  | 
|  | /* Write the high word of the double to the odd register(s).  */ | 
|  | regval = extract_signed_integer (val + 4 - low_offset, | 
|  | 4, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, phex (regval, 4)); | 
|  | regcache_cooked_write_signed (regcache, float_argreg++, regval); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* This is a floating point value that fits entirely | 
|  | in a single register.  */ | 
|  | /* On 32 bit ABI's the float_argreg is further adjusted | 
|  | above to ensure that it is even register aligned.  */ | 
|  | LONGEST regval = extract_signed_integer (val, len, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, phex (regval, len)); | 
|  | regcache_cooked_write_signed (regcache, float_argreg++, regval); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Copy the argument to general registers or the stack in | 
|  | register-sized pieces.  Large arguments are split between | 
|  | registers and stack.  */ | 
|  | /* Note: structs whose size is not a multiple of abi_regsize | 
|  | are treated specially: Irix cc passes | 
|  | them in registers where gcc sometimes puts them on the | 
|  | stack.  For maximum compatibility, we will put them in | 
|  | both places.  */ | 
|  | int odd_sized_struct = (len > abi_regsize && len % abi_regsize != 0); | 
|  |  | 
|  | /* Note: Floating-point values that didn't fit into an FP | 
|  | register are only written to memory.  */ | 
|  | while (len > 0) | 
|  | { | 
|  | /* Remember if the argument was written to the stack.  */ | 
|  | int stack_used_p = 0; | 
|  | int partial_len = (len < abi_regsize ? len : abi_regsize); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " -- partial=%d", | 
|  | partial_len); | 
|  |  | 
|  | /* Write this portion of the argument to the stack.  */ | 
|  | if (argreg > mips_last_arg_regnum (gdbarch) | 
|  | || odd_sized_struct | 
|  | || fp_register_arg_p (gdbarch, typecode, arg_type)) | 
|  | { | 
|  | /* Should shorter than int integer values be | 
|  | promoted to int before being stored?  */ | 
|  | int longword_offset = 0; | 
|  | CORE_ADDR addr; | 
|  | stack_used_p = 1; | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) | 
|  | { | 
|  | if (abi_regsize == 8 | 
|  | && (typecode == TYPE_CODE_INT | 
|  | || typecode == TYPE_CODE_PTR | 
|  | || typecode == TYPE_CODE_FLT) && len <= 4) | 
|  | longword_offset = abi_regsize - len; | 
|  | else if ((typecode == TYPE_CODE_STRUCT | 
|  | || typecode == TYPE_CODE_UNION) | 
|  | && arg_type->length () < abi_regsize) | 
|  | longword_offset = abi_regsize - len; | 
|  | } | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, " - stack_offset=%s", | 
|  | paddress (gdbarch, stack_offset)); | 
|  | gdb_printf (gdb_stdlog, " longword_offset=%s", | 
|  | paddress (gdbarch, longword_offset)); | 
|  | } | 
|  |  | 
|  | addr = sp + stack_offset + longword_offset; | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | int i; | 
|  | gdb_printf (gdb_stdlog, " @%s ", | 
|  | paddress (gdbarch, addr)); | 
|  | for (i = 0; i < partial_len; i++) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, "%02x", | 
|  | val[i] & 0xff); | 
|  | } | 
|  | } | 
|  | write_memory (addr, val, partial_len); | 
|  | } | 
|  |  | 
|  | /* Note!!! This is NOT an else clause.  Odd sized | 
|  | structs may go thru BOTH paths.  Floating point | 
|  | arguments will not.  */ | 
|  | /* Write this portion of the argument to a general | 
|  | purpose register.  */ | 
|  | if (argreg <= mips_last_arg_regnum (gdbarch) | 
|  | && !fp_register_arg_p (gdbarch, typecode, arg_type)) | 
|  | { | 
|  | LONGEST regval = | 
|  | extract_signed_integer (val, partial_len, byte_order); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, | 
|  | phex (regval, abi_regsize)); | 
|  | regcache_cooked_write_signed (regcache, argreg, regval); | 
|  | argreg++; | 
|  | } | 
|  |  | 
|  | len -= partial_len; | 
|  | val += partial_len; | 
|  |  | 
|  | /* Compute the offset into the stack at which we will | 
|  | copy the next parameter. | 
|  |  | 
|  | In the new EABI (and the NABI32), the stack_offset | 
|  | only needs to be adjusted when it has been used.  */ | 
|  |  | 
|  | if (stack_used_p) | 
|  | stack_offset += align_up (partial_len, abi_regsize); | 
|  | } | 
|  | } | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, "\n"); | 
|  | } | 
|  |  | 
|  | regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp); | 
|  |  | 
|  | /* Return adjusted stack pointer.  */ | 
|  | return sp; | 
|  | } | 
|  |  | 
|  | /* Determine the return value convention being used.  */ | 
|  |  | 
|  | static enum return_value_convention | 
|  | mips_eabi_return_value (struct gdbarch *gdbarch, struct value *function, | 
|  | struct type *type, struct regcache *regcache, | 
|  | gdb_byte *readbuf, const gdb_byte *writebuf) | 
|  | { | 
|  | mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch); | 
|  | int fp_return_type = 0; | 
|  | int offset, regnum, xfer; | 
|  |  | 
|  | if (type->length () > 2 * mips_abi_regsize (gdbarch)) | 
|  | return RETURN_VALUE_STRUCT_CONVENTION; | 
|  |  | 
|  | /* Floating point type?  */ | 
|  | if (tdep->mips_fpu_type != MIPS_FPU_NONE) | 
|  | { | 
|  | if (type->code () == TYPE_CODE_FLT) | 
|  | fp_return_type = 1; | 
|  | /* Structs with a single field of float type | 
|  | are returned in a floating point register.  */ | 
|  | if ((type->code () == TYPE_CODE_STRUCT | 
|  | || type->code () == TYPE_CODE_UNION) | 
|  | && type->num_fields () == 1) | 
|  | { | 
|  | struct type *fieldtype = type->field (0).type (); | 
|  |  | 
|  | if (check_typedef (fieldtype)->code () == TYPE_CODE_FLT) | 
|  | fp_return_type = 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (fp_return_type) | 
|  | { | 
|  | /* A floating-point value belongs in the least significant part | 
|  | of FP0/FP1.  */ | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return float in $fp0\n"); | 
|  | regnum = mips_regnum (gdbarch)->fp0; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* An integer value goes in V0/V1.  */ | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return scalar in $v0\n"); | 
|  | regnum = MIPS_V0_REGNUM; | 
|  | } | 
|  | for (offset = 0; | 
|  | offset < type->length (); | 
|  | offset += mips_abi_regsize (gdbarch), regnum++) | 
|  | { | 
|  | xfer = mips_abi_regsize (gdbarch); | 
|  | if (offset + xfer > type->length ()) | 
|  | xfer = type->length () - offset; | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, xfer, | 
|  | gdbarch_byte_order (gdbarch), readbuf, writebuf, | 
|  | offset); | 
|  | } | 
|  |  | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* N32/N64 ABI stuff.  */ | 
|  |  | 
|  | /* Search for a naturally aligned double at OFFSET inside a struct | 
|  | ARG_TYPE.  The N32 / N64 ABIs pass these in floating point | 
|  | registers.  */ | 
|  |  | 
|  | static int | 
|  | mips_n32n64_fp_arg_chunk_p (struct gdbarch *gdbarch, struct type *arg_type, | 
|  | int offset) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | if (arg_type->code () != TYPE_CODE_STRUCT) | 
|  | return 0; | 
|  |  | 
|  | if (mips_get_fpu_type (gdbarch) != MIPS_FPU_DOUBLE) | 
|  | return 0; | 
|  |  | 
|  | if (arg_type->length () < offset + MIPS64_REGSIZE) | 
|  | return 0; | 
|  |  | 
|  | for (i = 0; i < arg_type->num_fields (); i++) | 
|  | { | 
|  | int pos; | 
|  | struct type *field_type; | 
|  |  | 
|  | /* We're only looking at normal fields.  */ | 
|  | if (arg_type->field (i).is_static () | 
|  | || (arg_type->field (i).loc_bitpos () % 8) != 0) | 
|  | continue; | 
|  |  | 
|  | /* If we have gone past the offset, there is no double to pass.  */ | 
|  | pos = arg_type->field (i).loc_bitpos () / 8; | 
|  | if (pos > offset) | 
|  | return 0; | 
|  |  | 
|  | field_type = check_typedef (arg_type->field (i).type ()); | 
|  |  | 
|  | /* If this field is entirely before the requested offset, go | 
|  | on to the next one.  */ | 
|  | if (pos + field_type->length () <= offset) | 
|  | continue; | 
|  |  | 
|  | /* If this is our special aligned double, we can stop.  */ | 
|  | if (field_type->code () == TYPE_CODE_FLT | 
|  | && field_type->length () == MIPS64_REGSIZE) | 
|  | return 1; | 
|  |  | 
|  | /* This field starts at or before the requested offset, and | 
|  | overlaps it.  If it is a structure, recurse inwards.  */ | 
|  | return mips_n32n64_fp_arg_chunk_p (gdbarch, field_type, offset - pos); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, | 
|  | struct regcache *regcache, CORE_ADDR bp_addr, | 
|  | int nargs, struct value **args, CORE_ADDR sp, | 
|  | function_call_return_method return_method, | 
|  | CORE_ADDR struct_addr) | 
|  | { | 
|  | int argreg; | 
|  | int float_argreg; | 
|  | int argnum; | 
|  | int arg_space = 0; | 
|  | int stack_offset = 0; | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | CORE_ADDR func_addr = find_function_addr (function, NULL); | 
|  |  | 
|  | /* For shared libraries, "t9" needs to point at the function | 
|  | address.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr); | 
|  |  | 
|  | /* Set the return address register to point to the entry point of | 
|  | the program, where a breakpoint lies in wait.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr); | 
|  |  | 
|  | /* First ensure that the stack and structure return address (if any) | 
|  | are properly aligned.  The stack has to be at least 64-bit | 
|  | aligned even on 32-bit machines, because doubles must be 64-bit | 
|  | aligned.  For n32 and n64, stack frames need to be 128-bit | 
|  | aligned, so we round to this widest known alignment.  */ | 
|  |  | 
|  | sp = align_down (sp, 16); | 
|  | struct_addr = align_down (struct_addr, 16); | 
|  |  | 
|  | /* Now make space on the stack for the args.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | arg_space += align_up (args[argnum]->type ()->length (), | 
|  | MIPS64_REGSIZE); | 
|  | sp -= align_up (arg_space, 16); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_n32n64_push_dummy_call: sp=%s allocated %ld\n", | 
|  | paddress (gdbarch, sp), | 
|  | (long) align_up (arg_space, 16)); | 
|  |  | 
|  | /* Initialize the integer and float register pointers.  */ | 
|  | argreg = MIPS_A0_REGNUM; | 
|  | float_argreg = mips_fpa0_regnum (gdbarch); | 
|  |  | 
|  | /* The struct_return pointer occupies the first parameter-passing reg.  */ | 
|  | if (return_method == return_method_struct) | 
|  | { | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_n32n64_push_dummy_call: " | 
|  | "struct_return reg=%d %s\n", | 
|  | argreg, paddress (gdbarch, struct_addr)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg++, struct_addr); | 
|  | } | 
|  |  | 
|  | /* Now load as many as possible of the first arguments into | 
|  | registers, and push the rest onto the stack.  Loop thru args | 
|  | from first to last.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | { | 
|  | const gdb_byte *val; | 
|  | struct value *arg = args[argnum]; | 
|  | struct type *arg_type = check_typedef (arg->type ()); | 
|  | int len = arg_type->length (); | 
|  | enum type_code typecode = arg_type->code (); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_n32n64_push_dummy_call: %d len=%d type=%d", | 
|  | argnum + 1, len, (int) typecode); | 
|  |  | 
|  | val = arg->contents ().data (); | 
|  |  | 
|  | /* A 128-bit long double value requires an even-odd pair of | 
|  | floating-point registers.  */ | 
|  | if (len == 16 | 
|  | && fp_register_arg_p (gdbarch, typecode, arg_type) | 
|  | && (float_argreg & 1)) | 
|  | { | 
|  | float_argreg++; | 
|  | argreg++; | 
|  | } | 
|  |  | 
|  | if (fp_register_arg_p (gdbarch, typecode, arg_type) | 
|  | && argreg <= mips_last_arg_regnum (gdbarch)) | 
|  | { | 
|  | /* This is a floating point value that fits entirely | 
|  | in a single register or a pair of registers.  */ | 
|  | int reglen = (len <= MIPS64_REGSIZE ? len : MIPS64_REGSIZE); | 
|  | LONGEST regval = extract_unsigned_integer (val, reglen, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, phex (regval, reglen)); | 
|  | regcache_cooked_write_unsigned (regcache, float_argreg, regval); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, phex (regval, reglen)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg, regval); | 
|  | float_argreg++; | 
|  | argreg++; | 
|  | if (len == 16) | 
|  | { | 
|  | regval = extract_unsigned_integer (val + reglen, | 
|  | reglen, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, phex (regval, reglen)); | 
|  | regcache_cooked_write_unsigned (regcache, float_argreg, regval); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, phex (regval, reglen)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg, regval); | 
|  | float_argreg++; | 
|  | argreg++; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Copy the argument to general registers or the stack in | 
|  | register-sized pieces.  Large arguments are split between | 
|  | registers and stack.  */ | 
|  | /* For N32/N64, structs, unions, or other composite types are | 
|  | treated as a sequence of doublewords, and are passed in integer | 
|  | or floating point registers as though they were simple scalar | 
|  | parameters to the extent that they fit, with any excess on the | 
|  | stack packed according to the normal memory layout of the | 
|  | object. | 
|  | The caller does not reserve space for the register arguments; | 
|  | the callee is responsible for reserving it if required.  */ | 
|  | /* Note: Floating-point values that didn't fit into an FP | 
|  | register are only written to memory.  */ | 
|  | while (len > 0) | 
|  | { | 
|  | /* Remember if the argument was written to the stack.  */ | 
|  | int stack_used_p = 0; | 
|  | int partial_len = (len < MIPS64_REGSIZE ? len : MIPS64_REGSIZE); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " -- partial=%d", | 
|  | partial_len); | 
|  |  | 
|  | if (fp_register_arg_p (gdbarch, typecode, arg_type)) | 
|  | gdb_assert (argreg > mips_last_arg_regnum (gdbarch)); | 
|  |  | 
|  | /* Write this portion of the argument to the stack.  */ | 
|  | if (argreg > mips_last_arg_regnum (gdbarch)) | 
|  | { | 
|  | /* Should shorter than int integer values be | 
|  | promoted to int before being stored?  */ | 
|  | int longword_offset = 0; | 
|  | CORE_ADDR addr; | 
|  | stack_used_p = 1; | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) | 
|  | { | 
|  | if ((typecode == TYPE_CODE_INT | 
|  | || typecode == TYPE_CODE_PTR) | 
|  | && len <= 4) | 
|  | longword_offset = MIPS64_REGSIZE - len; | 
|  | } | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, " - stack_offset=%s", | 
|  | paddress (gdbarch, stack_offset)); | 
|  | gdb_printf (gdb_stdlog, " longword_offset=%s", | 
|  | paddress (gdbarch, longword_offset)); | 
|  | } | 
|  |  | 
|  | addr = sp + stack_offset + longword_offset; | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | int i; | 
|  | gdb_printf (gdb_stdlog, " @%s ", | 
|  | paddress (gdbarch, addr)); | 
|  | for (i = 0; i < partial_len; i++) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, "%02x", | 
|  | val[i] & 0xff); | 
|  | } | 
|  | } | 
|  | write_memory (addr, val, partial_len); | 
|  | } | 
|  |  | 
|  | /* Note!!! This is NOT an else clause.  Odd sized | 
|  | structs may go thru BOTH paths.  */ | 
|  | /* Write this portion of the argument to a general | 
|  | purpose register.  */ | 
|  | if (argreg <= mips_last_arg_regnum (gdbarch)) | 
|  | { | 
|  | LONGEST regval; | 
|  |  | 
|  | /* Sign extend pointers, 32-bit integers and signed | 
|  | 16-bit and 8-bit integers; everything else is taken | 
|  | as is.  */ | 
|  |  | 
|  | if ((partial_len == 4 | 
|  | && (typecode == TYPE_CODE_PTR | 
|  | || typecode == TYPE_CODE_INT)) | 
|  | || (partial_len < 4 | 
|  | && typecode == TYPE_CODE_INT | 
|  | && !arg_type->is_unsigned ())) | 
|  | regval = extract_signed_integer (val, partial_len, | 
|  | byte_order); | 
|  | else | 
|  | regval = extract_unsigned_integer (val, partial_len, | 
|  | byte_order); | 
|  |  | 
|  | /* A non-floating-point argument being passed in a | 
|  | general register.  If a struct or union, and if | 
|  | the remaining length is smaller than the register | 
|  | size, we have to adjust the register value on | 
|  | big endian targets. | 
|  |  | 
|  | It does not seem to be necessary to do the | 
|  | same for integral types.  */ | 
|  |  | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG | 
|  | && partial_len < MIPS64_REGSIZE | 
|  | && (typecode == TYPE_CODE_STRUCT | 
|  | || typecode == TYPE_CODE_UNION)) | 
|  | regval <<= ((MIPS64_REGSIZE - partial_len) | 
|  | * TARGET_CHAR_BIT); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, | 
|  | phex (regval, MIPS64_REGSIZE)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg, regval); | 
|  |  | 
|  | if (mips_n32n64_fp_arg_chunk_p (gdbarch, arg_type, | 
|  | arg_type->length () - len)) | 
|  | { | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, | 
|  | phex (regval, MIPS64_REGSIZE)); | 
|  | regcache_cooked_write_unsigned (regcache, float_argreg, | 
|  | regval); | 
|  | } | 
|  |  | 
|  | float_argreg++; | 
|  | argreg++; | 
|  | } | 
|  |  | 
|  | len -= partial_len; | 
|  | val += partial_len; | 
|  |  | 
|  | /* Compute the offset into the stack at which we will | 
|  | copy the next parameter. | 
|  |  | 
|  | In N32 (N64?), the stack_offset only needs to be | 
|  | adjusted when it has been used.  */ | 
|  |  | 
|  | if (stack_used_p) | 
|  | stack_offset += align_up (partial_len, MIPS64_REGSIZE); | 
|  | } | 
|  | } | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, "\n"); | 
|  | } | 
|  |  | 
|  | regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp); | 
|  |  | 
|  | /* Return adjusted stack pointer.  */ | 
|  | return sp; | 
|  | } | 
|  |  | 
|  | static enum return_value_convention | 
|  | mips_n32n64_return_value (struct gdbarch *gdbarch, struct value *function, | 
|  | struct type *type, struct regcache *regcache, | 
|  | gdb_byte *readbuf, const gdb_byte *writebuf) | 
|  | { | 
|  | mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch); | 
|  |  | 
|  | /* From MIPSpro N32 ABI Handbook, Document Number: 007-2816-004 | 
|  |  | 
|  | Function results are returned in $2 (and $3 if needed), or $f0 (and $f2 | 
|  | if needed), as appropriate for the type.  Composite results (struct, | 
|  | union, or array) are returned in $2/$f0 and $3/$f2 according to the | 
|  | following rules: | 
|  |  | 
|  | * A struct with only one or two floating point fields is returned in $f0 | 
|  | (and $f2 if necessary).  This is a generalization of the Fortran COMPLEX | 
|  | case. | 
|  |  | 
|  | * Any other composite results of at most 128 bits are returned in | 
|  | $2 (first 64 bits) and $3 (remainder, if necessary). | 
|  |  | 
|  | * Larger composite results are handled by converting the function to a | 
|  | procedure with an implicit first parameter, which is a pointer to an area | 
|  | reserved by the caller to receive the result.  [The o32-bit ABI requires | 
|  | that all composite results be handled by conversion to implicit first | 
|  | parameters.  The MIPS/SGI Fortran implementation has always made a | 
|  | specific exception to return COMPLEX results in the floating point | 
|  | registers.] | 
|  |  | 
|  | From MIPSpro Assembly Language Programmer's Guide, Document Number: | 
|  | 007-2418-004 | 
|  |  | 
|  | Software | 
|  | Register Name(from | 
|  | Name     fgregdef.h) Use and Linkage | 
|  | ----------------------------------------------------------------- | 
|  | $f0, $f2 fv0, fv1    Hold results of floating-point type function | 
|  | ($f0) and complex type function ($f0 has the | 
|  | real part, $f2 has the imaginary part.)  */ | 
|  |  | 
|  | if (type->length () > 2 * MIPS64_REGSIZE) | 
|  | return RETURN_VALUE_STRUCT_CONVENTION; | 
|  | else if ((type->code () == TYPE_CODE_COMPLEX | 
|  | || (type->code () == TYPE_CODE_FLT && type->length () == 16)) | 
|  | && tdep->mips_fpu_type != MIPS_FPU_NONE) | 
|  | { | 
|  | /* A complex value of up to 128 bits in width as well as a 128-bit | 
|  | floating-point value goes in both $f0 and $f2.  A single complex | 
|  | value is held in the lower halves only of the respective registers. | 
|  | The two registers are used in the same as memory order, so the | 
|  | bytes with the lower memory address are in $f0.  */ | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return float in $f0 and $f2\n"); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0), | 
|  | type->length () / 2, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0 + 2), | 
|  | type->length () / 2, gdbarch_byte_order (gdbarch), | 
|  | readbuf ? readbuf + type->length () / 2 : readbuf, | 
|  | (writebuf | 
|  | ? writebuf + type->length () / 2 : writebuf), 0); | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | else if (type->code () == TYPE_CODE_FLT | 
|  | && tdep->mips_fpu_type != MIPS_FPU_NONE) | 
|  | { | 
|  | /* A single or double floating-point value that fits in FP0.  */ | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return float in $fp0\n"); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0), | 
|  | type->length (), | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | else if (type->code () == TYPE_CODE_STRUCT | 
|  | && type->num_fields () <= 2 | 
|  | && type->num_fields () >= 1 | 
|  | && ((type->num_fields () == 1 | 
|  | && (check_typedef (type->field (0).type ())->code () | 
|  | == TYPE_CODE_FLT)) | 
|  | || (type->num_fields () == 2 | 
|  | && (check_typedef (type->field (0).type ())->code () | 
|  | == TYPE_CODE_FLT) | 
|  | && (check_typedef (type->field (1).type ())->code () | 
|  | == TYPE_CODE_FLT)))) | 
|  | { | 
|  | /* A struct that contains one or two floats.  Each value is part | 
|  | in the least significant part of their floating point | 
|  | register (or GPR, for soft float).  */ | 
|  | int regnum; | 
|  | int field; | 
|  | for (field = 0, regnum = (tdep->mips_fpu_type != MIPS_FPU_NONE | 
|  | ? mips_regnum (gdbarch)->fp0 | 
|  | : MIPS_V0_REGNUM); | 
|  | field < type->num_fields (); field++, regnum += 2) | 
|  | { | 
|  | int offset = type->field (field).loc_bitpos () / TARGET_CHAR_BIT; | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return float struct+%d\n", | 
|  | offset); | 
|  | if (type->field (field).type ()->length () == 16) | 
|  | { | 
|  | /* A 16-byte long double field goes in two consecutive | 
|  | registers.  */ | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, | 
|  | 8, | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, offset); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum + 1, | 
|  | 8, | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, offset + 8); | 
|  | } | 
|  | else | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, | 
|  | type->field (field).type ()->length (), | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, offset); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | else if (type->code () == TYPE_CODE_STRUCT | 
|  | || type->code () == TYPE_CODE_UNION | 
|  | || type->code () == TYPE_CODE_ARRAY) | 
|  | { | 
|  | /* A composite type.  Extract the left justified value, | 
|  | regardless of the byte order.  I.e. DO NOT USE | 
|  | mips_xfer_lower.  */ | 
|  | int offset; | 
|  | int regnum; | 
|  | for (offset = 0, regnum = MIPS_V0_REGNUM; | 
|  | offset < type->length (); | 
|  | offset += register_size (gdbarch, regnum), regnum++) | 
|  | { | 
|  | int xfer = register_size (gdbarch, regnum); | 
|  | if (offset + xfer > type->length ()) | 
|  | xfer = type->length () - offset; | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return struct+%d:%d in $%d\n", | 
|  | offset, xfer, regnum); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, | 
|  | xfer, BFD_ENDIAN_UNKNOWN, readbuf, writebuf, | 
|  | offset); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* A scalar extract each part but least-significant-byte | 
|  | justified.  */ | 
|  | int offset; | 
|  | int regnum; | 
|  | for (offset = 0, regnum = MIPS_V0_REGNUM; | 
|  | offset < type->length (); | 
|  | offset += register_size (gdbarch, regnum), regnum++) | 
|  | { | 
|  | int xfer = register_size (gdbarch, regnum); | 
|  | if (offset + xfer > type->length ()) | 
|  | xfer = type->length () - offset; | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return scalar+%d:%d in $%d\n", | 
|  | offset, xfer, regnum); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, | 
|  | xfer, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, offset); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Which registers to use for passing floating-point values between | 
|  | function calls, one of floating-point, general and both kinds of | 
|  | registers.  O32 and O64 use different register kinds for standard | 
|  | MIPS and MIPS16 code; to make the handling of cases where we may | 
|  | not know what kind of code is being used (e.g. no debug information) | 
|  | easier we sometimes use both kinds.  */ | 
|  |  | 
|  | enum mips_fval_reg | 
|  | { | 
|  | mips_fval_fpr, | 
|  | mips_fval_gpr, | 
|  | mips_fval_both | 
|  | }; | 
|  |  | 
|  | /* O32 ABI stuff.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, | 
|  | struct regcache *regcache, CORE_ADDR bp_addr, | 
|  | int nargs, struct value **args, CORE_ADDR sp, | 
|  | function_call_return_method return_method, | 
|  | CORE_ADDR struct_addr) | 
|  | { | 
|  | int argreg; | 
|  | int float_argreg; | 
|  | int argnum; | 
|  | int arg_space = 0; | 
|  | int stack_offset = 0; | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | CORE_ADDR func_addr = find_function_addr (function, NULL); | 
|  |  | 
|  | /* For shared libraries, "t9" needs to point at the function | 
|  | address.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr); | 
|  |  | 
|  | /* Set the return address register to point to the entry point of | 
|  | the program, where a breakpoint lies in wait.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr); | 
|  |  | 
|  | /* First ensure that the stack and structure return address (if any) | 
|  | are properly aligned.  The stack has to be at least 64-bit | 
|  | aligned even on 32-bit machines, because doubles must be 64-bit | 
|  | aligned.  For n32 and n64, stack frames need to be 128-bit | 
|  | aligned, so we round to this widest known alignment.  */ | 
|  |  | 
|  | sp = align_down (sp, 16); | 
|  | struct_addr = align_down (struct_addr, 16); | 
|  |  | 
|  | /* Now make space on the stack for the args.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | { | 
|  | struct type *arg_type = check_typedef (args[argnum]->type ()); | 
|  |  | 
|  | /* Align to double-word if necessary.  */ | 
|  | if (mips_type_needs_double_align (arg_type)) | 
|  | arg_space = align_up (arg_space, MIPS32_REGSIZE * 2); | 
|  | /* Allocate space on the stack.  */ | 
|  | arg_space += align_up (arg_type->length (), MIPS32_REGSIZE); | 
|  | } | 
|  | sp -= align_up (arg_space, 16); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_o32_push_dummy_call: sp=%s allocated %ld\n", | 
|  | paddress (gdbarch, sp), | 
|  | (long) align_up (arg_space, 16)); | 
|  |  | 
|  | /* Initialize the integer and float register pointers.  */ | 
|  | argreg = MIPS_A0_REGNUM; | 
|  | float_argreg = mips_fpa0_regnum (gdbarch); | 
|  |  | 
|  | /* The struct_return pointer occupies the first parameter-passing reg.  */ | 
|  | if (return_method == return_method_struct) | 
|  | { | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_o32_push_dummy_call: " | 
|  | "struct_return reg=%d %s\n", | 
|  | argreg, paddress (gdbarch, struct_addr)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg++, struct_addr); | 
|  | stack_offset += MIPS32_REGSIZE; | 
|  | } | 
|  |  | 
|  | /* Now load as many as possible of the first arguments into | 
|  | registers, and push the rest onto the stack.  Loop thru args | 
|  | from first to last.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | { | 
|  | const gdb_byte *val; | 
|  | struct value *arg = args[argnum]; | 
|  | struct type *arg_type = check_typedef (arg->type ()); | 
|  | int len = arg_type->length (); | 
|  | enum type_code typecode = arg_type->code (); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_o32_push_dummy_call: %d len=%d type=%d", | 
|  | argnum + 1, len, (int) typecode); | 
|  |  | 
|  | val = arg->contents ().data (); | 
|  |  | 
|  | /* 32-bit ABIs always start floating point arguments in an | 
|  | even-numbered floating point register.  Round the FP register | 
|  | up before the check to see if there are any FP registers | 
|  | left.  O32 targets also pass the FP in the integer registers | 
|  | so also round up normal registers.  */ | 
|  | if (fp_register_arg_p (gdbarch, typecode, arg_type)) | 
|  | { | 
|  | if ((float_argreg & 1)) | 
|  | float_argreg++; | 
|  | } | 
|  |  | 
|  | /* Floating point arguments passed in registers have to be | 
|  | treated specially.  On 32-bit architectures, doubles are | 
|  | passed in register pairs; the even FP register gets the | 
|  | low word, and the odd FP register gets the high word. | 
|  | On O32, the first two floating point arguments are also | 
|  | copied to general registers, following their memory order, | 
|  | because MIPS16 functions don't use float registers for | 
|  | arguments.  This duplication of arguments in general | 
|  | registers can't hurt non-MIPS16 functions, because those | 
|  | registers are normally skipped.  */ | 
|  |  | 
|  | if (fp_register_arg_p (gdbarch, typecode, arg_type) | 
|  | && float_argreg <= mips_last_fp_arg_regnum (gdbarch)) | 
|  | { | 
|  | if (register_size (gdbarch, float_argreg) < 8 && len == 8) | 
|  | { | 
|  | int freg_offset = gdbarch_byte_order (gdbarch) | 
|  | == BFD_ENDIAN_BIG ? 1 : 0; | 
|  | unsigned long regval; | 
|  |  | 
|  | /* First word.  */ | 
|  | regval = extract_unsigned_integer (val, 4, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg + freg_offset, | 
|  | phex (regval, 4)); | 
|  | regcache_cooked_write_unsigned (regcache, | 
|  | float_argreg++ + freg_offset, | 
|  | regval); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, phex (regval, 4)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg++, regval); | 
|  |  | 
|  | /* Second word.  */ | 
|  | regval = extract_unsigned_integer (val + 4, 4, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg - freg_offset, | 
|  | phex (regval, 4)); | 
|  | regcache_cooked_write_unsigned (regcache, | 
|  | float_argreg++ - freg_offset, | 
|  | regval); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, phex (regval, 4)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg++, regval); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* This is a floating point value that fits entirely | 
|  | in a single register.  */ | 
|  | /* On 32 bit ABI's the float_argreg is further adjusted | 
|  | above to ensure that it is even register aligned.  */ | 
|  | LONGEST regval = extract_unsigned_integer (val, len, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, phex (regval, len)); | 
|  | regcache_cooked_write_unsigned (regcache, | 
|  | float_argreg++, regval); | 
|  | /* Although two FP registers are reserved for each | 
|  | argument, only one corresponding integer register is | 
|  | reserved.  */ | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, phex (regval, len)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg++, regval); | 
|  | } | 
|  | /* Reserve space for the FP register.  */ | 
|  | stack_offset += align_up (len, MIPS32_REGSIZE); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Copy the argument to general registers or the stack in | 
|  | register-sized pieces.  Large arguments are split between | 
|  | registers and stack.  */ | 
|  | /* Note: structs whose size is not a multiple of MIPS32_REGSIZE | 
|  | are treated specially: Irix cc passes | 
|  | them in registers where gcc sometimes puts them on the | 
|  | stack.  For maximum compatibility, we will put them in | 
|  | both places.  */ | 
|  | int odd_sized_struct = (len > MIPS32_REGSIZE | 
|  | && len % MIPS32_REGSIZE != 0); | 
|  | /* Structures should be aligned to eight bytes (even arg registers) | 
|  | on MIPS_ABI_O32, if their first member has double precision.  */ | 
|  | if (mips_type_needs_double_align (arg_type)) | 
|  | { | 
|  | if ((argreg & 1)) | 
|  | { | 
|  | argreg++; | 
|  | stack_offset += MIPS32_REGSIZE; | 
|  | } | 
|  | } | 
|  | while (len > 0) | 
|  | { | 
|  | int partial_len = (len < MIPS32_REGSIZE ? len : MIPS32_REGSIZE); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " -- partial=%d", | 
|  | partial_len); | 
|  |  | 
|  | /* Write this portion of the argument to the stack.  */ | 
|  | if (argreg > mips_last_arg_regnum (gdbarch) | 
|  | || odd_sized_struct) | 
|  | { | 
|  | /* Should shorter than int integer values be | 
|  | promoted to int before being stored?  */ | 
|  | int longword_offset = 0; | 
|  | CORE_ADDR addr; | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, " - stack_offset=%s", | 
|  | paddress (gdbarch, stack_offset)); | 
|  | gdb_printf (gdb_stdlog, " longword_offset=%s", | 
|  | paddress (gdbarch, longword_offset)); | 
|  | } | 
|  |  | 
|  | addr = sp + stack_offset + longword_offset; | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | int i; | 
|  | gdb_printf (gdb_stdlog, " @%s ", | 
|  | paddress (gdbarch, addr)); | 
|  | for (i = 0; i < partial_len; i++) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, "%02x", | 
|  | val[i] & 0xff); | 
|  | } | 
|  | } | 
|  | write_memory (addr, val, partial_len); | 
|  | } | 
|  |  | 
|  | /* Note!!! This is NOT an else clause.  Odd sized | 
|  | structs may go thru BOTH paths.  */ | 
|  | /* Write this portion of the argument to a general | 
|  | purpose register.  */ | 
|  | if (argreg <= mips_last_arg_regnum (gdbarch)) | 
|  | { | 
|  | LONGEST regval = extract_signed_integer (val, partial_len, | 
|  | byte_order); | 
|  | /* Value may need to be sign extended, because | 
|  | mips_isa_regsize() != mips_abi_regsize().  */ | 
|  |  | 
|  | /* A non-floating-point argument being passed in a | 
|  | general register.  If a struct or union, and if | 
|  | the remaining length is smaller than the register | 
|  | size, we have to adjust the register value on | 
|  | big endian targets. | 
|  |  | 
|  | It does not seem to be necessary to do the | 
|  | same for integral types. | 
|  |  | 
|  | Also don't do this adjustment on O64 binaries. | 
|  |  | 
|  | cagney/2001-07-23: gdb/179: Also, GCC, when | 
|  | outputting LE O32 with sizeof (struct) < | 
|  | mips_abi_regsize(), generates a left shift | 
|  | as part of storing the argument in a register | 
|  | (the left shift isn't generated when | 
|  | sizeof (struct) >= mips_abi_regsize()).  Since | 
|  | it is quite possible that this is GCC | 
|  | contradicting the LE/O32 ABI, GDB has not been | 
|  | adjusted to accommodate this.  Either someone | 
|  | needs to demonstrate that the LE/O32 ABI | 
|  | specifies such a left shift OR this new ABI gets | 
|  | identified as such and GDB gets tweaked | 
|  | accordingly.  */ | 
|  |  | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG | 
|  | && partial_len < MIPS32_REGSIZE | 
|  | && (typecode == TYPE_CODE_STRUCT | 
|  | || typecode == TYPE_CODE_UNION)) | 
|  | regval <<= ((MIPS32_REGSIZE - partial_len) | 
|  | * TARGET_CHAR_BIT); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, | 
|  | phex (regval, MIPS32_REGSIZE)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg, regval); | 
|  | argreg++; | 
|  |  | 
|  | /* Prevent subsequent floating point arguments from | 
|  | being passed in floating point registers.  */ | 
|  | float_argreg = mips_last_fp_arg_regnum (gdbarch) + 1; | 
|  | } | 
|  |  | 
|  | len -= partial_len; | 
|  | val += partial_len; | 
|  |  | 
|  | /* Compute the offset into the stack at which we will | 
|  | copy the next parameter. | 
|  |  | 
|  | In older ABIs, the caller reserved space for | 
|  | registers that contained arguments.  This was loosely | 
|  | referred to as their "home".  Consequently, space is | 
|  | always allocated.  */ | 
|  |  | 
|  | stack_offset += align_up (partial_len, MIPS32_REGSIZE); | 
|  | } | 
|  | } | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, "\n"); | 
|  | } | 
|  |  | 
|  | regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp); | 
|  |  | 
|  | /* Return adjusted stack pointer.  */ | 
|  | return sp; | 
|  | } | 
|  |  | 
|  | static enum return_value_convention | 
|  | mips_o32_return_value (struct gdbarch *gdbarch, struct value *function, | 
|  | struct type *type, struct regcache *regcache, | 
|  | gdb_byte *readbuf, const gdb_byte *writebuf) | 
|  | { | 
|  | CORE_ADDR func_addr = function ? find_function_addr (function, NULL) : 0; | 
|  | int mips16 = mips_pc_is_mips16 (gdbarch, func_addr); | 
|  | mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch); | 
|  | enum mips_fval_reg fval_reg; | 
|  |  | 
|  | fval_reg = readbuf ? mips16 ? mips_fval_gpr : mips_fval_fpr : mips_fval_both; | 
|  | if (type->code () == TYPE_CODE_STRUCT | 
|  | || type->code () == TYPE_CODE_UNION | 
|  | || type->code () == TYPE_CODE_ARRAY) | 
|  | return RETURN_VALUE_STRUCT_CONVENTION; | 
|  | else if (type->code () == TYPE_CODE_FLT | 
|  | && type->length () == 4 && tdep->mips_fpu_type != MIPS_FPU_NONE) | 
|  | { | 
|  | /* A single-precision floating-point value.  If reading in or copying, | 
|  | then we get it from/put it to FP0 for standard MIPS code or GPR2 | 
|  | for MIPS16 code.  If writing out only, then we put it to both FP0 | 
|  | and GPR2.  We do not support reading in with no function known, if | 
|  | this safety check ever triggers, then we'll have to try harder.  */ | 
|  | gdb_assert (function || !readbuf); | 
|  | if (mips_debug) | 
|  | switch (fval_reg) | 
|  | { | 
|  | case mips_fval_fpr: | 
|  | gdb_printf (gdb_stderr, "Return float in $fp0\n"); | 
|  | break; | 
|  | case mips_fval_gpr: | 
|  | gdb_printf (gdb_stderr, "Return float in $2\n"); | 
|  | break; | 
|  | case mips_fval_both: | 
|  | gdb_printf (gdb_stderr, "Return float in $fp0 and $2\n"); | 
|  | break; | 
|  | } | 
|  | if (fval_reg != mips_fval_gpr) | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0), | 
|  | type->length (), | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | if (fval_reg != mips_fval_fpr) | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + 2, | 
|  | type->length (), | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | else if (type->code () == TYPE_CODE_FLT | 
|  | && type->length () == 8 && tdep->mips_fpu_type != MIPS_FPU_NONE) | 
|  | { | 
|  | /* A double-precision floating-point value.  If reading in or copying, | 
|  | then we get it from/put it to FP1 and FP0 for standard MIPS code or | 
|  | GPR2 and GPR3 for MIPS16 code.  If writing out only, then we put it | 
|  | to both FP1/FP0 and GPR2/GPR3.  We do not support reading in with | 
|  | no function known, if this safety check ever triggers, then we'll | 
|  | have to try harder.  */ | 
|  | gdb_assert (function || !readbuf); | 
|  | if (mips_debug) | 
|  | switch (fval_reg) | 
|  | { | 
|  | case mips_fval_fpr: | 
|  | gdb_printf (gdb_stderr, "Return float in $fp1/$fp0\n"); | 
|  | break; | 
|  | case mips_fval_gpr: | 
|  | gdb_printf (gdb_stderr, "Return float in $2/$3\n"); | 
|  | break; | 
|  | case mips_fval_both: | 
|  | gdb_printf (gdb_stderr, | 
|  | "Return float in $fp1/$fp0 and $2/$3\n"); | 
|  | break; | 
|  | } | 
|  | if (fval_reg != mips_fval_gpr) | 
|  | { | 
|  | /* The most significant part goes in FP1, and the least significant | 
|  | in FP0.  */ | 
|  | switch (gdbarch_byte_order (gdbarch)) | 
|  | { | 
|  | case BFD_ENDIAN_LITTLE: | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0 + 0), | 
|  | 4, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0 + 1), | 
|  | 4, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 4); | 
|  | break; | 
|  | case BFD_ENDIAN_BIG: | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0 + 1), | 
|  | 4, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0 + 0), | 
|  | 4, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 4); | 
|  | break; | 
|  | default: | 
|  | internal_error (_("bad switch")); | 
|  | } | 
|  | } | 
|  | if (fval_reg != mips_fval_fpr) | 
|  | { | 
|  | /* The two 32-bit parts are always placed in GPR2 and GPR3 | 
|  | following these registers' memory order.  */ | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + 2, | 
|  | 4, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + 3, | 
|  | 4, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 4); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | #if 0 | 
|  | else if (type->code () == TYPE_CODE_STRUCT | 
|  | && type->num_fields () <= 2 | 
|  | && type->num_fields () >= 1 | 
|  | && ((type->num_fields () == 1 | 
|  | && (TYPE_CODE (type->field (0).type ()) | 
|  | == TYPE_CODE_FLT)) | 
|  | || (type->num_fields () == 2 | 
|  | && (TYPE_CODE (type->field (0).type ()) | 
|  | == TYPE_CODE_FLT) | 
|  | && (TYPE_CODE (type->field (1).type ()) | 
|  | == TYPE_CODE_FLT))) | 
|  | && tdep->mips_fpu_type != MIPS_FPU_NONE) | 
|  | { | 
|  | /* A struct that contains one or two floats.  Each value is part | 
|  | in the least significant part of their floating point | 
|  | register..  */ | 
|  | int regnum; | 
|  | int field; | 
|  | for (field = 0, regnum = mips_regnum (gdbarch)->fp0; | 
|  | field < type->num_fields (); field++, regnum += 2) | 
|  | { | 
|  | int offset = (type->fields ()[field].loc_bitpos () / TARGET_CHAR_BIT); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return float struct+%d\n", | 
|  | offset); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, | 
|  | TYPE_LENGTH (type->field (field).type ()), | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, offset); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | #endif | 
|  | #if 0 | 
|  | else if (type->code () == TYPE_CODE_STRUCT | 
|  | || type->code () == TYPE_CODE_UNION) | 
|  | { | 
|  | /* A structure or union.  Extract the left justified value, | 
|  | regardless of the byte order.  I.e. DO NOT USE | 
|  | mips_xfer_lower.  */ | 
|  | int offset; | 
|  | int regnum; | 
|  | for (offset = 0, regnum = MIPS_V0_REGNUM; | 
|  | offset < type->length (); | 
|  | offset += register_size (gdbarch, regnum), regnum++) | 
|  | { | 
|  | int xfer = register_size (gdbarch, regnum); | 
|  | if (offset + xfer > type->length ()) | 
|  | xfer = type->length () - offset; | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return struct+%d:%d in $%d\n", | 
|  | offset, xfer, regnum); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, xfer, | 
|  | BFD_ENDIAN_UNKNOWN, readbuf, writebuf, offset); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | #endif | 
|  | else | 
|  | { | 
|  | /* A scalar extract each part but least-significant-byte | 
|  | justified.  o32 thinks registers are 4 byte, regardless of | 
|  | the ISA.  */ | 
|  | int offset; | 
|  | int regnum; | 
|  | for (offset = 0, regnum = MIPS_V0_REGNUM; | 
|  | offset < type->length (); | 
|  | offset += MIPS32_REGSIZE, regnum++) | 
|  | { | 
|  | int xfer = MIPS32_REGSIZE; | 
|  | if (offset + xfer > type->length ()) | 
|  | xfer = type->length () - offset; | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return scalar+%d:%d in $%d\n", | 
|  | offset, xfer, regnum); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, xfer, | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, offset); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* O64 ABI.  This is a hacked up kind of 64-bit version of the o32 | 
|  | ABI.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, | 
|  | struct regcache *regcache, CORE_ADDR bp_addr, | 
|  | int nargs, | 
|  | struct value **args, CORE_ADDR sp, | 
|  | function_call_return_method return_method, CORE_ADDR struct_addr) | 
|  | { | 
|  | int argreg; | 
|  | int float_argreg; | 
|  | int argnum; | 
|  | int arg_space = 0; | 
|  | int stack_offset = 0; | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | CORE_ADDR func_addr = find_function_addr (function, NULL); | 
|  |  | 
|  | /* For shared libraries, "t9" needs to point at the function | 
|  | address.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr); | 
|  |  | 
|  | /* Set the return address register to point to the entry point of | 
|  | the program, where a breakpoint lies in wait.  */ | 
|  | regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr); | 
|  |  | 
|  | /* First ensure that the stack and structure return address (if any) | 
|  | are properly aligned.  The stack has to be at least 64-bit | 
|  | aligned even on 32-bit machines, because doubles must be 64-bit | 
|  | aligned.  For n32 and n64, stack frames need to be 128-bit | 
|  | aligned, so we round to this widest known alignment.  */ | 
|  |  | 
|  | sp = align_down (sp, 16); | 
|  | struct_addr = align_down (struct_addr, 16); | 
|  |  | 
|  | /* Now make space on the stack for the args.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | { | 
|  | struct type *arg_type = check_typedef (args[argnum]->type ()); | 
|  |  | 
|  | /* Allocate space on the stack.  */ | 
|  | arg_space += align_up (arg_type->length (), MIPS64_REGSIZE); | 
|  | } | 
|  | sp -= align_up (arg_space, 16); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_o64_push_dummy_call: sp=%s allocated %ld\n", | 
|  | paddress (gdbarch, sp), | 
|  | (long) align_up (arg_space, 16)); | 
|  |  | 
|  | /* Initialize the integer and float register pointers.  */ | 
|  | argreg = MIPS_A0_REGNUM; | 
|  | float_argreg = mips_fpa0_regnum (gdbarch); | 
|  |  | 
|  | /* The struct_return pointer occupies the first parameter-passing reg.  */ | 
|  | if (return_method == return_method_struct) | 
|  | { | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_o64_push_dummy_call: " | 
|  | "struct_return reg=%d %s\n", | 
|  | argreg, paddress (gdbarch, struct_addr)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg++, struct_addr); | 
|  | stack_offset += MIPS64_REGSIZE; | 
|  | } | 
|  |  | 
|  | /* Now load as many as possible of the first arguments into | 
|  | registers, and push the rest onto the stack.  Loop thru args | 
|  | from first to last.  */ | 
|  | for (argnum = 0; argnum < nargs; argnum++) | 
|  | { | 
|  | const gdb_byte *val; | 
|  | struct value *arg = args[argnum]; | 
|  | struct type *arg_type = check_typedef (arg->type ()); | 
|  | int len = arg_type->length (); | 
|  | enum type_code typecode = arg_type->code (); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_o64_push_dummy_call: %d len=%d type=%d", | 
|  | argnum + 1, len, (int) typecode); | 
|  |  | 
|  | val = arg->contents ().data (); | 
|  |  | 
|  | /* Floating point arguments passed in registers have to be | 
|  | treated specially.  On 32-bit architectures, doubles are | 
|  | passed in register pairs; the even FP register gets the | 
|  | low word, and the odd FP register gets the high word. | 
|  | On O64, the first two floating point arguments are also | 
|  | copied to general registers, because MIPS16 functions | 
|  | don't use float registers for arguments.  This duplication | 
|  | of arguments in general registers can't hurt non-MIPS16 | 
|  | functions because those registers are normally skipped.  */ | 
|  |  | 
|  | if (fp_register_arg_p (gdbarch, typecode, arg_type) | 
|  | && float_argreg <= mips_last_fp_arg_regnum (gdbarch)) | 
|  | { | 
|  | LONGEST regval = extract_unsigned_integer (val, len, byte_order); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - fpreg=%d val=%s", | 
|  | float_argreg, phex (regval, len)); | 
|  | regcache_cooked_write_unsigned (regcache, float_argreg++, regval); | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, phex (regval, len)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg, regval); | 
|  | argreg++; | 
|  | /* Reserve space for the FP register.  */ | 
|  | stack_offset += align_up (len, MIPS64_REGSIZE); | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Copy the argument to general registers or the stack in | 
|  | register-sized pieces.  Large arguments are split between | 
|  | registers and stack.  */ | 
|  | /* Note: structs whose size is not a multiple of MIPS64_REGSIZE | 
|  | are treated specially: Irix cc passes them in registers | 
|  | where gcc sometimes puts them on the stack.  For maximum | 
|  | compatibility, we will put them in both places.  */ | 
|  | int odd_sized_struct = (len > MIPS64_REGSIZE | 
|  | && len % MIPS64_REGSIZE != 0); | 
|  | while (len > 0) | 
|  | { | 
|  | int partial_len = (len < MIPS64_REGSIZE ? len : MIPS64_REGSIZE); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " -- partial=%d", | 
|  | partial_len); | 
|  |  | 
|  | /* Write this portion of the argument to the stack.  */ | 
|  | if (argreg > mips_last_arg_regnum (gdbarch) | 
|  | || odd_sized_struct) | 
|  | { | 
|  | /* Should shorter than int integer values be | 
|  | promoted to int before being stored?  */ | 
|  | int longword_offset = 0; | 
|  | CORE_ADDR addr; | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) | 
|  | { | 
|  | if ((typecode == TYPE_CODE_INT | 
|  | || typecode == TYPE_CODE_PTR | 
|  | || typecode == TYPE_CODE_FLT) | 
|  | && len <= 4) | 
|  | longword_offset = MIPS64_REGSIZE - len; | 
|  | } | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, " - stack_offset=%s", | 
|  | paddress (gdbarch, stack_offset)); | 
|  | gdb_printf (gdb_stdlog, " longword_offset=%s", | 
|  | paddress (gdbarch, longword_offset)); | 
|  | } | 
|  |  | 
|  | addr = sp + stack_offset + longword_offset; | 
|  |  | 
|  | if (mips_debug) | 
|  | { | 
|  | int i; | 
|  | gdb_printf (gdb_stdlog, " @%s ", | 
|  | paddress (gdbarch, addr)); | 
|  | for (i = 0; i < partial_len; i++) | 
|  | { | 
|  | gdb_printf (gdb_stdlog, "%02x", | 
|  | val[i] & 0xff); | 
|  | } | 
|  | } | 
|  | write_memory (addr, val, partial_len); | 
|  | } | 
|  |  | 
|  | /* Note!!! This is NOT an else clause.  Odd sized | 
|  | structs may go thru BOTH paths.  */ | 
|  | /* Write this portion of the argument to a general | 
|  | purpose register.  */ | 
|  | if (argreg <= mips_last_arg_regnum (gdbarch)) | 
|  | { | 
|  | LONGEST regval = extract_signed_integer (val, partial_len, | 
|  | byte_order); | 
|  | /* Value may need to be sign extended, because | 
|  | mips_isa_regsize() != mips_abi_regsize().  */ | 
|  |  | 
|  | /* A non-floating-point argument being passed in a | 
|  | general register.  If a struct or union, and if | 
|  | the remaining length is smaller than the register | 
|  | size, we have to adjust the register value on | 
|  | big endian targets. | 
|  |  | 
|  | It does not seem to be necessary to do the | 
|  | same for integral types.  */ | 
|  |  | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG | 
|  | && partial_len < MIPS64_REGSIZE | 
|  | && (typecode == TYPE_CODE_STRUCT | 
|  | || typecode == TYPE_CODE_UNION)) | 
|  | regval <<= ((MIPS64_REGSIZE - partial_len) | 
|  | * TARGET_CHAR_BIT); | 
|  |  | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, " - reg=%d val=%s", | 
|  | argreg, | 
|  | phex (regval, MIPS64_REGSIZE)); | 
|  | regcache_cooked_write_unsigned (regcache, argreg, regval); | 
|  | argreg++; | 
|  |  | 
|  | /* Prevent subsequent floating point arguments from | 
|  | being passed in floating point registers.  */ | 
|  | float_argreg = mips_last_fp_arg_regnum (gdbarch) + 1; | 
|  | } | 
|  |  | 
|  | len -= partial_len; | 
|  | val += partial_len; | 
|  |  | 
|  | /* Compute the offset into the stack at which we will | 
|  | copy the next parameter. | 
|  |  | 
|  | In older ABIs, the caller reserved space for | 
|  | registers that contained arguments.  This was loosely | 
|  | referred to as their "home".  Consequently, space is | 
|  | always allocated.  */ | 
|  |  | 
|  | stack_offset += align_up (partial_len, MIPS64_REGSIZE); | 
|  | } | 
|  | } | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stdlog, "\n"); | 
|  | } | 
|  |  | 
|  | regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp); | 
|  |  | 
|  | /* Return adjusted stack pointer.  */ | 
|  | return sp; | 
|  | } | 
|  |  | 
|  | static enum return_value_convention | 
|  | mips_o64_return_value (struct gdbarch *gdbarch, struct value *function, | 
|  | struct type *type, struct regcache *regcache, | 
|  | gdb_byte *readbuf, const gdb_byte *writebuf) | 
|  | { | 
|  | CORE_ADDR func_addr = function ? find_function_addr (function, NULL) : 0; | 
|  | int mips16 = mips_pc_is_mips16 (gdbarch, func_addr); | 
|  | enum mips_fval_reg fval_reg; | 
|  |  | 
|  | fval_reg = readbuf ? mips16 ? mips_fval_gpr : mips_fval_fpr : mips_fval_both; | 
|  | if (type->code () == TYPE_CODE_STRUCT | 
|  | || type->code () == TYPE_CODE_UNION | 
|  | || type->code () == TYPE_CODE_ARRAY) | 
|  | return RETURN_VALUE_STRUCT_CONVENTION; | 
|  | else if (fp_register_arg_p (gdbarch, type->code (), type)) | 
|  | { | 
|  | /* A floating-point value.  If reading in or copying, then we get it | 
|  | from/put it to FP0 for standard MIPS code or GPR2 for MIPS16 code. | 
|  | If writing out only, then we put it to both FP0 and GPR2.  We do | 
|  | not support reading in with no function known, if this safety | 
|  | check ever triggers, then we'll have to try harder.  */ | 
|  | gdb_assert (function || !readbuf); | 
|  | if (mips_debug) | 
|  | switch (fval_reg) | 
|  | { | 
|  | case mips_fval_fpr: | 
|  | gdb_printf (gdb_stderr, "Return float in $fp0\n"); | 
|  | break; | 
|  | case mips_fval_gpr: | 
|  | gdb_printf (gdb_stderr, "Return float in $2\n"); | 
|  | break; | 
|  | case mips_fval_both: | 
|  | gdb_printf (gdb_stderr, "Return float in $fp0 and $2\n"); | 
|  | break; | 
|  | } | 
|  | if (fval_reg != mips_fval_gpr) | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | (gdbarch_num_regs (gdbarch) | 
|  | + mips_regnum (gdbarch)->fp0), | 
|  | type->length (), | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | if (fval_reg != mips_fval_fpr) | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + 2, | 
|  | type->length (), | 
|  | gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, 0); | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* A scalar extract each part but least-significant-byte | 
|  | justified.  */ | 
|  | int offset; | 
|  | int regnum; | 
|  | for (offset = 0, regnum = MIPS_V0_REGNUM; | 
|  | offset < type->length (); | 
|  | offset += MIPS64_REGSIZE, regnum++) | 
|  | { | 
|  | int xfer = MIPS64_REGSIZE; | 
|  | if (offset + xfer > type->length ()) | 
|  | xfer = type->length () - offset; | 
|  | if (mips_debug) | 
|  | gdb_printf (gdb_stderr, "Return scalar+%d:%d in $%d\n", | 
|  | offset, xfer, regnum); | 
|  | mips_xfer_register (gdbarch, regcache, | 
|  | gdbarch_num_regs (gdbarch) + regnum, | 
|  | xfer, gdbarch_byte_order (gdbarch), | 
|  | readbuf, writebuf, offset); | 
|  | } | 
|  | return RETURN_VALUE_REGISTER_CONVENTION; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Floating point register management. | 
|  |  | 
|  | Background: MIPS1 & 2 fp registers are 32 bits wide.  To support | 
|  | 64bit operations, these early MIPS cpus treat fp register pairs | 
|  | (f0,f1) as a single register (d0).  Later MIPS cpu's have 64 bit fp | 
|  | registers and offer a compatibility mode that emulates the MIPS2 fp | 
|  | model.  When operating in MIPS2 fp compat mode, later cpu's split | 
|  | double precision floats into two 32-bit chunks and store them in | 
|  | consecutive fp regs.  To display 64-bit floats stored in this | 
|  | fashion, we have to combine 32 bits from f0 and 32 bits from f1. | 
|  | Throw in user-configurable endianness and you have a real mess. | 
|  |  | 
|  | The way this works is: | 
|  | - If we are in 32-bit mode or on a 32-bit processor, then a 64-bit | 
|  | double-precision value will be split across two logical registers. | 
|  | The lower-numbered logical register will hold the low-order bits, | 
|  | regardless of the processor's endianness. | 
|  | - If we are on a 64-bit processor, and we are looking for a | 
|  | single-precision value, it will be in the low ordered bits | 
|  | of a 64-bit GPR (after mfc1, for example) or a 64-bit register | 
|  | save slot in memory. | 
|  | - If we are in 64-bit mode, everything is straightforward. | 
|  |  | 
|  | Note that this code only deals with "live" registers at the top of the | 
|  | stack.  We will attempt to deal with saved registers later, when | 
|  | the raw/cooked register interface is in place.  (We need a general | 
|  | interface that can deal with dynamic saved register sizes -- fp | 
|  | regs could be 32 bits wide in one frame and 64 on the frame above | 
|  | and below).  */ | 
|  |  | 
|  | /* Copy a 32-bit single-precision value from the current frame | 
|  | into rare_buffer.  */ | 
|  |  | 
|  | static void | 
|  | mips_read_fp_register_single (frame_info_ptr frame, int regno, | 
|  | gdb_byte *rare_buffer) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | int raw_size = register_size (gdbarch, regno); | 
|  | gdb_byte *raw_buffer = (gdb_byte *) alloca (raw_size); | 
|  |  | 
|  | if (!deprecated_frame_register_read (frame, regno, raw_buffer)) | 
|  | error (_("can't read register %d (%s)"), | 
|  | regno, gdbarch_register_name (gdbarch, regno)); | 
|  | if (raw_size == 8) | 
|  | { | 
|  | /* We have a 64-bit value for this register.  Find the low-order | 
|  | 32 bits.  */ | 
|  | int offset; | 
|  |  | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) | 
|  | offset = 4; | 
|  | else | 
|  | offset = 0; | 
|  |  | 
|  | memcpy (rare_buffer, raw_buffer + offset, 4); | 
|  | } | 
|  | else | 
|  | { | 
|  | memcpy (rare_buffer, raw_buffer, 4); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Copy a 64-bit double-precision value from the current frame into | 
|  | rare_buffer.  This may include getting half of it from the next | 
|  | register.  */ | 
|  |  | 
|  | static void | 
|  | mips_read_fp_register_double (frame_info_ptr frame, int regno, | 
|  | gdb_byte *rare_buffer) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | int raw_size = register_size (gdbarch, regno); | 
|  |  | 
|  | if (raw_size == 8 && !mips2_fp_compat (frame)) | 
|  | { | 
|  | /* We have a 64-bit value for this register, and we should use | 
|  | all 64 bits.  */ | 
|  | if (!deprecated_frame_register_read (frame, regno, rare_buffer)) | 
|  | error (_("can't read register %d (%s)"), | 
|  | regno, gdbarch_register_name (gdbarch, regno)); | 
|  | } | 
|  | else | 
|  | { | 
|  | int rawnum = regno % gdbarch_num_regs (gdbarch); | 
|  |  | 
|  | if ((rawnum - mips_regnum (gdbarch)->fp0) & 1) | 
|  | internal_error (_("mips_read_fp_register_double: bad access to " | 
|  | "odd-numbered FP register")); | 
|  |  | 
|  | /* mips_read_fp_register_single will find the correct 32 bits from | 
|  | each register.  */ | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) | 
|  | { | 
|  | mips_read_fp_register_single (frame, regno, rare_buffer + 4); | 
|  | mips_read_fp_register_single (frame, regno + 1, rare_buffer); | 
|  | } | 
|  | else | 
|  | { | 
|  | mips_read_fp_register_single (frame, regno, rare_buffer); | 
|  | mips_read_fp_register_single (frame, regno + 1, rare_buffer + 4); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_print_fp_register (struct ui_file *file, frame_info_ptr frame, | 
|  | int regnum) | 
|  | {				/* Do values for FP (float) regs.  */ | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | gdb_byte *raw_buffer; | 
|  | std::string flt_str, dbl_str; | 
|  |  | 
|  | const struct type *flt_type = builtin_type (gdbarch)->builtin_float; | 
|  | const struct type *dbl_type = builtin_type (gdbarch)->builtin_double; | 
|  |  | 
|  | raw_buffer | 
|  | = ((gdb_byte *) | 
|  | alloca (2 * register_size (gdbarch, mips_regnum (gdbarch)->fp0))); | 
|  |  | 
|  | gdb_printf (file, "%s:", gdbarch_register_name (gdbarch, regnum)); | 
|  | gdb_printf (file, "%*s", | 
|  | 4 - (int) strlen (gdbarch_register_name (gdbarch, regnum)), | 
|  | ""); | 
|  |  | 
|  | if (register_size (gdbarch, regnum) == 4 || mips2_fp_compat (frame)) | 
|  | { | 
|  | struct value_print_options opts; | 
|  |  | 
|  | /* 4-byte registers: Print hex and floating.  Also print even | 
|  | numbered registers as doubles.  */ | 
|  | mips_read_fp_register_single (frame, regnum, raw_buffer); | 
|  | flt_str = target_float_to_string (raw_buffer, flt_type, "%-17.9g"); | 
|  |  | 
|  | get_formatted_print_options (&opts, 'x'); | 
|  | print_scalar_formatted (raw_buffer, | 
|  | builtin_type (gdbarch)->builtin_uint32, | 
|  | &opts, 'w', file); | 
|  |  | 
|  | gdb_printf (file, " flt: %s", flt_str.c_str ()); | 
|  |  | 
|  | if ((regnum - gdbarch_num_regs (gdbarch)) % 2 == 0) | 
|  | { | 
|  | mips_read_fp_register_double (frame, regnum, raw_buffer); | 
|  | dbl_str = target_float_to_string (raw_buffer, dbl_type, "%-24.17g"); | 
|  |  | 
|  | gdb_printf (file, " dbl: %s", dbl_str.c_str ()); | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | struct value_print_options opts; | 
|  |  | 
|  | /* Eight byte registers: print each one as hex, float and double.  */ | 
|  | mips_read_fp_register_single (frame, regnum, raw_buffer); | 
|  | flt_str = target_float_to_string (raw_buffer, flt_type, "%-17.9g"); | 
|  |  | 
|  | mips_read_fp_register_double (frame, regnum, raw_buffer); | 
|  | dbl_str = target_float_to_string (raw_buffer, dbl_type, "%-24.17g"); | 
|  |  | 
|  | get_formatted_print_options (&opts, 'x'); | 
|  | print_scalar_formatted (raw_buffer, | 
|  | builtin_type (gdbarch)->builtin_uint64, | 
|  | &opts, 'g', file); | 
|  |  | 
|  | gdb_printf (file, " flt: %s", flt_str.c_str ()); | 
|  | gdb_printf (file, " dbl: %s", dbl_str.c_str ()); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_print_register (struct ui_file *file, frame_info_ptr frame, | 
|  | int regnum) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | struct value_print_options opts; | 
|  | struct value *val; | 
|  |  | 
|  | if (mips_float_register_p (gdbarch, regnum)) | 
|  | { | 
|  | mips_print_fp_register (file, frame, regnum); | 
|  | return; | 
|  | } | 
|  |  | 
|  | val = get_frame_register_value (frame, regnum); | 
|  |  | 
|  | gdb_puts (gdbarch_register_name (gdbarch, regnum), file); | 
|  |  | 
|  | /* The problem with printing numeric register names (r26, etc.) is that | 
|  | the user can't use them on input.  Probably the best solution is to | 
|  | fix it so that either the numeric or the funky (a2, etc.) names | 
|  | are accepted on input.  */ | 
|  | if (regnum < MIPS_NUMREGS) | 
|  | gdb_printf (file, "(r%d): ", regnum); | 
|  | else | 
|  | gdb_printf (file, ": "); | 
|  |  | 
|  | get_formatted_print_options (&opts, 'x'); | 
|  | value_print_scalar_formatted (val, &opts, 0, file); | 
|  | } | 
|  |  | 
|  | /* Print IEEE exception condition bits in FLAGS.  */ | 
|  |  | 
|  | static void | 
|  | print_fpu_flags (struct ui_file *file, int flags) | 
|  | { | 
|  | if (flags & (1 << 0)) | 
|  | gdb_puts (" inexact", file); | 
|  | if (flags & (1 << 1)) | 
|  | gdb_puts (" uflow", file); | 
|  | if (flags & (1 << 2)) | 
|  | gdb_puts (" oflow", file); | 
|  | if (flags & (1 << 3)) | 
|  | gdb_puts (" div0", file); | 
|  | if (flags & (1 << 4)) | 
|  | gdb_puts (" inval", file); | 
|  | if (flags & (1 << 5)) | 
|  | gdb_puts (" unimp", file); | 
|  | gdb_putc ('\n', file); | 
|  | } | 
|  |  | 
|  | /* Print interesting information about the floating point processor | 
|  | (if present) or emulator.  */ | 
|  |  | 
|  | static void | 
|  | mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, | 
|  | frame_info_ptr frame, const char *args) | 
|  | { | 
|  | int fcsr = mips_regnum (gdbarch)->fp_control_status; | 
|  | enum mips_fpu_type type = mips_get_fpu_type (gdbarch); | 
|  | ULONGEST fcs = 0; | 
|  | int i; | 
|  |  | 
|  | if (fcsr == -1 || !read_frame_register_unsigned (frame, fcsr, &fcs)) | 
|  | type = MIPS_FPU_NONE; | 
|  |  | 
|  | gdb_printf (file, "fpu type: %s\n", | 
|  | type == MIPS_FPU_DOUBLE ? "double-precision" | 
|  | : type == MIPS_FPU_SINGLE ? "single-precision" | 
|  | : "none / unused"); | 
|  |  | 
|  | if (type == MIPS_FPU_NONE) | 
|  | return; | 
|  |  | 
|  | gdb_printf (file, "reg size: %d bits\n", | 
|  | register_size (gdbarch, mips_regnum (gdbarch)->fp0) * 8); | 
|  |  | 
|  | gdb_puts ("cond    :", file); | 
|  | if (fcs & (1 << 23)) | 
|  | gdb_puts (" 0", file); | 
|  | for (i = 1; i <= 7; i++) | 
|  | if (fcs & (1 << (24 + i))) | 
|  | gdb_printf (file, " %d", i); | 
|  | gdb_putc ('\n', file); | 
|  |  | 
|  | gdb_puts ("cause   :", file); | 
|  | print_fpu_flags (file, (fcs >> 12) & 0x3f); | 
|  | fputs ("mask    :", stdout); | 
|  | print_fpu_flags (file, (fcs >> 7) & 0x1f); | 
|  | fputs ("flags   :", stdout); | 
|  | print_fpu_flags (file, (fcs >> 2) & 0x1f); | 
|  |  | 
|  | gdb_puts ("rounding: ", file); | 
|  | switch (fcs & 3) | 
|  | { | 
|  | case 0: gdb_puts ("nearest\n", file); break; | 
|  | case 1: gdb_puts ("zero\n", file); break; | 
|  | case 2: gdb_puts ("+inf\n", file); break; | 
|  | case 3: gdb_puts ("-inf\n", file); break; | 
|  | } | 
|  |  | 
|  | gdb_puts ("flush   :", file); | 
|  | if (fcs & (1 << 21)) | 
|  | gdb_puts (" nearest", file); | 
|  | if (fcs & (1 << 22)) | 
|  | gdb_puts (" override", file); | 
|  | if (fcs & (1 << 24)) | 
|  | gdb_puts (" zero", file); | 
|  | if ((fcs & (0xb << 21)) == 0) | 
|  | gdb_puts (" no", file); | 
|  | gdb_putc ('\n', file); | 
|  |  | 
|  | gdb_printf (file, "nan2008 : %s\n", fcs & (1 << 18) ? "yes" : "no"); | 
|  | gdb_printf (file, "abs2008 : %s\n", fcs & (1 << 19) ? "yes" : "no"); | 
|  | gdb_putc ('\n', file); | 
|  |  | 
|  | default_print_float_info (gdbarch, file, frame, args); | 
|  | } | 
|  |  | 
|  | /* Replacement for generic do_registers_info. | 
|  | Print regs in pretty columns.  */ | 
|  |  | 
|  | static int | 
|  | print_fp_register_row (struct ui_file *file, frame_info_ptr frame, | 
|  | int regnum) | 
|  | { | 
|  | gdb_printf (file, " "); | 
|  | mips_print_fp_register (file, frame, regnum); | 
|  | gdb_printf (file, "\n"); | 
|  | return regnum + 1; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Print a row's worth of GP (int) registers, with name labels above.  */ | 
|  |  | 
|  | static int | 
|  | print_gp_register_row (struct ui_file *file, frame_info_ptr frame, | 
|  | int start_regnum) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | /* Do values for GP (int) regs.  */ | 
|  | const gdb_byte *raw_buffer; | 
|  | struct value *value; | 
|  | int ncols = (mips_abi_regsize (gdbarch) == 8 ? 4 : 8);    /* display cols | 
|  | per row.  */ | 
|  | int col, byte; | 
|  | int regnum; | 
|  |  | 
|  | /* For GP registers, we print a separate row of names above the vals.  */ | 
|  | for (col = 0, regnum = start_regnum; | 
|  | col < ncols && regnum < gdbarch_num_cooked_regs (gdbarch); | 
|  | regnum++) | 
|  | { | 
|  | if (*gdbarch_register_name (gdbarch, regnum) == '\0') | 
|  | continue;		/* unused register */ | 
|  | if (mips_float_register_p (gdbarch, regnum)) | 
|  | break;			/* End the row: reached FP register.  */ | 
|  | /* Large registers are handled separately.  */ | 
|  | if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch)) | 
|  | { | 
|  | if (col > 0) | 
|  | break;		/* End the row before this register.  */ | 
|  |  | 
|  | /* Print this register on a row by itself.  */ | 
|  | mips_print_register (file, frame, regnum); | 
|  | gdb_printf (file, "\n"); | 
|  | return regnum + 1; | 
|  | } | 
|  | if (col == 0) | 
|  | gdb_printf (file, "     "); | 
|  | gdb_printf (file, | 
|  | mips_abi_regsize (gdbarch) == 8 ? "%17s" : "%9s", | 
|  | gdbarch_register_name (gdbarch, regnum)); | 
|  | col++; | 
|  | } | 
|  |  | 
|  | if (col == 0) | 
|  | return regnum; | 
|  |  | 
|  | /* Print the R0 to R31 names.  */ | 
|  | if ((start_regnum % gdbarch_num_regs (gdbarch)) < MIPS_NUMREGS) | 
|  | gdb_printf (file, "\n R%-4d", | 
|  | start_regnum % gdbarch_num_regs (gdbarch)); | 
|  | else | 
|  | gdb_printf (file, "\n      "); | 
|  |  | 
|  | /* Now print the values in hex, 4 or 8 to the row.  */ | 
|  | for (col = 0, regnum = start_regnum; | 
|  | col < ncols && regnum < gdbarch_num_cooked_regs (gdbarch); | 
|  | regnum++) | 
|  | { | 
|  | if (*gdbarch_register_name (gdbarch, regnum) == '\0') | 
|  | continue;		/* unused register */ | 
|  | if (mips_float_register_p (gdbarch, regnum)) | 
|  | break;			/* End row: reached FP register.  */ | 
|  | if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch)) | 
|  | break;			/* End row: large register.  */ | 
|  |  | 
|  | /* OK: get the data in raw format.  */ | 
|  | value = get_frame_register_value (frame, regnum); | 
|  | if (value->optimized_out () | 
|  | || !value->entirely_available ()) | 
|  | { | 
|  | gdb_printf (file, "%*s ", | 
|  | (int) mips_abi_regsize (gdbarch) * 2, | 
|  | (mips_abi_regsize (gdbarch) == 4 ? "<unavl>" | 
|  | : "<unavailable>")); | 
|  | col++; | 
|  | continue; | 
|  | } | 
|  | raw_buffer = value->contents_all ().data (); | 
|  | /* pad small registers */ | 
|  | for (byte = 0; | 
|  | byte < (mips_abi_regsize (gdbarch) | 
|  | - register_size (gdbarch, regnum)); byte++) | 
|  | gdb_printf (file, "  "); | 
|  | /* Now print the register value in hex, endian order.  */ | 
|  | if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) | 
|  | for (byte = | 
|  | register_size (gdbarch, regnum) - register_size (gdbarch, regnum); | 
|  | byte < register_size (gdbarch, regnum); byte++) | 
|  | gdb_printf (file, "%02x", raw_buffer[byte]); | 
|  | else | 
|  | for (byte = register_size (gdbarch, regnum) - 1; | 
|  | byte >= 0; byte--) | 
|  | gdb_printf (file, "%02x", raw_buffer[byte]); | 
|  | gdb_printf (file, " "); | 
|  | col++; | 
|  | } | 
|  | if (col > 0)			/* ie. if we actually printed anything...  */ | 
|  | gdb_printf (file, "\n"); | 
|  |  | 
|  | return regnum; | 
|  | } | 
|  |  | 
|  | /* MIPS_DO_REGISTERS_INFO(): called by "info register" command.  */ | 
|  |  | 
|  | static void | 
|  | mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, | 
|  | frame_info_ptr frame, int regnum, int all) | 
|  | { | 
|  | if (regnum != -1)		/* Do one specified register.  */ | 
|  | { | 
|  | gdb_assert (regnum >= gdbarch_num_regs (gdbarch)); | 
|  | if (*(gdbarch_register_name (gdbarch, regnum)) == '\0') | 
|  | error (_("Not a valid register for the current processor type")); | 
|  |  | 
|  | mips_print_register (file, frame, regnum); | 
|  | gdb_printf (file, "\n"); | 
|  | } | 
|  | else | 
|  | /* Do all (or most) registers.  */ | 
|  | { | 
|  | regnum = gdbarch_num_regs (gdbarch); | 
|  | while (regnum < gdbarch_num_cooked_regs (gdbarch)) | 
|  | { | 
|  | if (mips_float_register_p (gdbarch, regnum)) | 
|  | { | 
|  | if (all)		/* True for "INFO ALL-REGISTERS" command.  */ | 
|  | regnum = print_fp_register_row (file, frame, regnum); | 
|  | else | 
|  | regnum += MIPS_NUMREGS;	/* Skip floating point regs.  */ | 
|  | } | 
|  | else | 
|  | regnum = print_gp_register_row (file, frame, regnum); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | static int | 
|  | mips_single_step_through_delay (struct gdbarch *gdbarch, | 
|  | frame_info_ptr frame) | 
|  | { | 
|  | CORE_ADDR pc = get_frame_pc (frame); | 
|  | enum mips_isa isa; | 
|  | ULONGEST insn; | 
|  | int size; | 
|  |  | 
|  | if ((mips_pc_is_mips (pc) | 
|  | && !mips32_insn_at_pc_has_delay_slot (gdbarch, pc)) | 
|  | || (mips_pc_is_micromips (gdbarch, pc) | 
|  | && !micromips_insn_at_pc_has_delay_slot (gdbarch, pc, 0)) | 
|  | || (mips_pc_is_mips16 (gdbarch, pc) | 
|  | && !mips16_insn_at_pc_has_delay_slot (gdbarch, pc, 0))) | 
|  | return 0; | 
|  |  | 
|  | isa = mips_pc_isa (gdbarch, pc); | 
|  | /* _has_delay_slot above will have validated the read.  */ | 
|  | insn = mips_fetch_instruction (gdbarch, isa, pc, NULL); | 
|  | size = mips_insn_size (isa, insn); | 
|  |  | 
|  | const address_space *aspace = get_frame_address_space (frame); | 
|  |  | 
|  | return breakpoint_here_p (aspace, pc + size) != no_breakpoint_here; | 
|  | } | 
|  |  | 
|  | /* To skip prologues, I use this predicate.  Returns either PC itself | 
|  | if the code at PC does not look like a function prologue; otherwise | 
|  | returns an address that (if we're lucky) follows the prologue.  If | 
|  | LENIENT, then we must skip everything which is involved in setting | 
|  | up the frame (it's OK to skip more, just so long as we don't skip | 
|  | anything which might clobber the registers which are being saved. | 
|  | We must skip more in the case where part of the prologue is in the | 
|  | delay slot of a non-prologue instruction).  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR limit_pc; | 
|  | CORE_ADDR func_addr; | 
|  |  | 
|  | /* See if we can determine the end of the prologue via the symbol table. | 
|  | If so, then return either PC, or the PC after the prologue, whichever | 
|  | is greater.  */ | 
|  | if (find_pc_partial_function (pc, NULL, &func_addr, NULL)) | 
|  | { | 
|  | CORE_ADDR post_prologue_pc | 
|  | = skip_prologue_using_sal (gdbarch, func_addr); | 
|  | if (post_prologue_pc != 0) | 
|  | return std::max (pc, post_prologue_pc); | 
|  | } | 
|  |  | 
|  | /* Can't determine prologue from the symbol table, need to examine | 
|  | instructions.  */ | 
|  |  | 
|  | /* Find an upper limit on the function prologue using the debug | 
|  | information.  If the debug information could not be used to provide | 
|  | that bound, then use an arbitrary large number as the upper bound.  */ | 
|  | limit_pc = skip_prologue_using_sal (gdbarch, pc); | 
|  | if (limit_pc == 0) | 
|  | limit_pc = pc + 100;          /* Magic.  */ | 
|  |  | 
|  | if (mips_pc_is_mips16 (gdbarch, pc)) | 
|  | return mips16_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL); | 
|  | else if (mips_pc_is_micromips (gdbarch, pc)) | 
|  | return micromips_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL); | 
|  | else | 
|  | return mips32_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL); | 
|  | } | 
|  |  | 
|  | /* Implement the stack_frame_destroyed_p gdbarch method (32-bit version). | 
|  | This is a helper function for mips_stack_frame_destroyed_p.  */ | 
|  |  | 
|  | static int | 
|  | mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR func_addr = 0, func_end = 0; | 
|  |  | 
|  | if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) | 
|  | { | 
|  | /* The MIPS epilogue is max. 12 bytes long.  */ | 
|  | CORE_ADDR addr = func_end - 12; | 
|  |  | 
|  | if (addr < func_addr + 4) | 
|  | addr = func_addr + 4; | 
|  | if (pc < addr) | 
|  | return 0; | 
|  |  | 
|  | for (; pc < func_end; pc += MIPS_INSN32_SIZE) | 
|  | { | 
|  | unsigned long high_word; | 
|  | unsigned long inst; | 
|  |  | 
|  | inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL); | 
|  | high_word = (inst >> 16) & 0xffff; | 
|  |  | 
|  | if (high_word != 0x27bd	/* addiu $sp,$sp,offset */ | 
|  | && high_word != 0x67bd	/* daddiu $sp,$sp,offset */ | 
|  | && inst != 0x03e00008	/* jr $ra */ | 
|  | && inst != 0x00000000)	/* nop */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Implement the stack_frame_destroyed_p gdbarch method (microMIPS version). | 
|  | This is a helper function for mips_stack_frame_destroyed_p.  */ | 
|  |  | 
|  | static int | 
|  | micromips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR func_addr = 0; | 
|  | CORE_ADDR func_end = 0; | 
|  | CORE_ADDR addr; | 
|  | ULONGEST insn; | 
|  | long offset; | 
|  | int dreg; | 
|  | int sreg; | 
|  | int loc; | 
|  |  | 
|  | if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end)) | 
|  | return 0; | 
|  |  | 
|  | /* The microMIPS epilogue is max. 12 bytes long.  */ | 
|  | addr = func_end - 12; | 
|  |  | 
|  | if (addr < func_addr + 2) | 
|  | addr = func_addr + 2; | 
|  | if (pc < addr) | 
|  | return 0; | 
|  |  | 
|  | for (; pc < func_end; pc += loc) | 
|  | { | 
|  | loc = 0; | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL); | 
|  | loc += 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 + loc, NULL); | 
|  | loc += MIPS_INSN16_SIZE; | 
|  | switch (micromips_op (insn >> 16)) | 
|  | { | 
|  | case 0xc: /* ADDIU: bits 001100 */ | 
|  | case 0x17: /* DADDIU: bits 010111 */ | 
|  | sreg = b0s5_reg (insn >> 16); | 
|  | dreg = b5s5_reg (insn >> 16); | 
|  | offset = (b0s16_imm (insn) ^ 0x8000) - 0x8000; | 
|  | if (sreg == MIPS_SP_REGNUM && dreg == MIPS_SP_REGNUM | 
|  | /* (D)ADDIU $sp, imm */ | 
|  | && offset >= 0) | 
|  | break; | 
|  | return 0; | 
|  |  | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  | break; | 
|  |  | 
|  | /* 16-bit instructions.  */ | 
|  | case MIPS_INSN16_SIZE: | 
|  | switch (micromips_op (insn)) | 
|  | { | 
|  | case 0x3: /* MOVE: bits 000011 */ | 
|  | sreg = b0s5_reg (insn); | 
|  | dreg = b5s5_reg (insn); | 
|  | if (sreg == 0 && dreg == 0) | 
|  | /* MOVE $zero, $zero aka NOP */ | 
|  | break; | 
|  | return 0; | 
|  |  | 
|  | case 0x11: /* POOL16C: bits 010001 */ | 
|  | if (b5s5_op (insn) == 0x18 | 
|  | /* JRADDIUSP: bits 010011 11000 */ | 
|  | || (b5s5_op (insn) == 0xd | 
|  | /* JRC: bits 010011 01101 */ | 
|  | && b0s5_reg (insn) == MIPS_RA_REGNUM)) | 
|  | /* JRC $ra */ | 
|  | break; | 
|  | return 0; | 
|  |  | 
|  | case 0x13: /* POOL16D: bits 010011 */ | 
|  | offset = micromips_decode_imm9 (b1s9_imm (insn)); | 
|  | if ((insn & 0x1) == 0x1 | 
|  | /* ADDIUSP: bits 010011 1 */ | 
|  | && offset > 0) | 
|  | break; | 
|  | return 0; | 
|  |  | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /* Implement the stack_frame_destroyed_p gdbarch method (16-bit version). | 
|  | This is a helper function for mips_stack_frame_destroyed_p.  */ | 
|  |  | 
|  | static int | 
|  | mips16_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR func_addr = 0, func_end = 0; | 
|  |  | 
|  | if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) | 
|  | { | 
|  | /* The MIPS epilogue is max. 12 bytes long.  */ | 
|  | CORE_ADDR addr = func_end - 12; | 
|  |  | 
|  | if (addr < func_addr + 4) | 
|  | addr = func_addr + 4; | 
|  | if (pc < addr) | 
|  | return 0; | 
|  |  | 
|  | for (; pc < func_end; pc += MIPS_INSN16_SIZE) | 
|  | { | 
|  | unsigned short inst; | 
|  |  | 
|  | inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, pc, NULL); | 
|  |  | 
|  | if ((inst & 0xf800) == 0xf000)	/* extend */ | 
|  | continue; | 
|  |  | 
|  | if (inst != 0x6300		/* addiu $sp,offset */ | 
|  | && inst != 0xfb00		/* daddiu $sp,$sp,offset */ | 
|  | && inst != 0xe820		/* jr $ra */ | 
|  | && inst != 0xe8a0		/* jrc $ra */ | 
|  | && inst != 0x6500)	/* nop */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* Implement the stack_frame_destroyed_p gdbarch method. | 
|  |  | 
|  | The epilogue is defined here as the area at the end of a function, | 
|  | after an instruction which destroys the function's stack frame.  */ | 
|  |  | 
|  | static int | 
|  | mips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) | 
|  | { | 
|  | if (mips_pc_is_mips16 (gdbarch, pc)) | 
|  | return mips16_stack_frame_destroyed_p (gdbarch, pc); | 
|  | else if (mips_pc_is_micromips (gdbarch, pc)) | 
|  | return micromips_stack_frame_destroyed_p (gdbarch, pc); | 
|  | else | 
|  | return mips32_stack_frame_destroyed_p (gdbarch, pc); | 
|  | } | 
|  |  | 
|  | /* Commands to show/set the MIPS FPU type.  */ | 
|  |  | 
|  | static void | 
|  | show_mipsfpu_command (const char *args, int from_tty) | 
|  | { | 
|  | const char *fpu; | 
|  |  | 
|  | if (gdbarch_bfd_arch_info (current_inferior ()->arch ())->arch | 
|  | != bfd_arch_mips) | 
|  | { | 
|  | gdb_printf | 
|  | ("The MIPS floating-point coprocessor is unknown " | 
|  | "because the current architecture is not MIPS.\n"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | switch (mips_get_fpu_type (current_inferior ()->arch  ())) | 
|  | { | 
|  | 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 (_("bad switch")); | 
|  | } | 
|  | if (mips_fpu_type_auto) | 
|  | gdb_printf ("The MIPS floating-point coprocessor " | 
|  | "is set automatically (currently %s)\n", | 
|  | fpu); | 
|  | else | 
|  | gdb_printf | 
|  | ("The MIPS floating-point coprocessor is assumed to be %s\n", fpu); | 
|  | } | 
|  |  | 
|  |  | 
|  | static void | 
|  | set_mipsfpu_single_command (const char *args, int from_tty) | 
|  | { | 
|  | struct gdbarch_info info; | 
|  | mips_fpu_type = MIPS_FPU_SINGLE; | 
|  | mips_fpu_type_auto = 0; | 
|  | /* 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 (info)) | 
|  | internal_error (_("set mipsfpu failed")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | set_mipsfpu_double_command (const char *args, int from_tty) | 
|  | { | 
|  | struct gdbarch_info info; | 
|  | mips_fpu_type = MIPS_FPU_DOUBLE; | 
|  | mips_fpu_type_auto = 0; | 
|  | /* 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 (info)) | 
|  | internal_error (_("set mipsfpu failed")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | set_mipsfpu_none_command (const char *args, int from_tty) | 
|  | { | 
|  | struct gdbarch_info info; | 
|  | mips_fpu_type = MIPS_FPU_NONE; | 
|  | mips_fpu_type_auto = 0; | 
|  | /* 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 (info)) | 
|  | internal_error (_("set mipsfpu failed")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | set_mipsfpu_auto_command (const char *args, int from_tty) | 
|  | { | 
|  | mips_fpu_type_auto = 1; | 
|  | } | 
|  |  | 
|  | /* Just like reinit_frame_cache, but with the right arguments to be | 
|  | callable as an sfunc.  */ | 
|  |  | 
|  | static void | 
|  | reinit_frame_cache_sfunc (const char *args, int from_tty, | 
|  | struct cmd_list_element *c) | 
|  | { | 
|  | reinit_frame_cache (); | 
|  | } | 
|  |  | 
|  | static int | 
|  | gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info) | 
|  | { | 
|  | gdb_disassemble_info *di | 
|  | = static_cast<gdb_disassemble_info *> (info->application_data); | 
|  | struct gdbarch *gdbarch = di->arch (); | 
|  |  | 
|  | /* FIXME: cagney/2003-06-26: Is this even necessary?  The | 
|  | disassembler needs to be able to locally determine the ISA, and | 
|  | not rely on GDB.  Otherwize the stand-alone 'objdump -d' will not | 
|  | work.  */ | 
|  | if (mips_pc_is_mips16 (gdbarch, memaddr)) | 
|  | info->mach = bfd_mach_mips16; | 
|  | else if (mips_pc_is_micromips (gdbarch, memaddr)) | 
|  | info->mach = bfd_mach_mips_micromips; | 
|  |  | 
|  | /* Round down the instruction address to the appropriate boundary.  */ | 
|  | memaddr &= (info->mach == bfd_mach_mips16 | 
|  | || info->mach == bfd_mach_mips_micromips) ? ~1 : ~3; | 
|  |  | 
|  | return default_print_insn (memaddr, info); | 
|  | } | 
|  |  | 
|  | /* Implement the breakpoint_kind_from_pc gdbarch method.  */ | 
|  |  | 
|  | static int | 
|  | mips_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr) | 
|  | { | 
|  | CORE_ADDR pc = *pcptr; | 
|  |  | 
|  | if (mips_pc_is_mips16 (gdbarch, pc)) | 
|  | { | 
|  | *pcptr = unmake_compact_addr (pc); | 
|  | return MIPS_BP_KIND_MIPS16; | 
|  | } | 
|  | else if (mips_pc_is_micromips (gdbarch, pc)) | 
|  | { | 
|  | ULONGEST insn; | 
|  | int status; | 
|  |  | 
|  | *pcptr = unmake_compact_addr (pc); | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status); | 
|  | if (status || (mips_insn_size (ISA_MICROMIPS, insn) == 2)) | 
|  | return MIPS_BP_KIND_MICROMIPS16; | 
|  | else | 
|  | return MIPS_BP_KIND_MICROMIPS32; | 
|  | } | 
|  | else | 
|  | return MIPS_BP_KIND_MIPS32; | 
|  | } | 
|  |  | 
|  | /* Implement the sw_breakpoint_from_kind gdbarch method.  */ | 
|  |  | 
|  | static const gdb_byte * | 
|  | mips_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size) | 
|  | { | 
|  | enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); | 
|  |  | 
|  | switch (kind) | 
|  | { | 
|  | case MIPS_BP_KIND_MIPS16: | 
|  | { | 
|  | static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 }; | 
|  | static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 }; | 
|  |  | 
|  | *size = 2; | 
|  | if (byte_order_for_code == BFD_ENDIAN_BIG) | 
|  | return mips16_big_breakpoint; | 
|  | else | 
|  | return mips16_little_breakpoint; | 
|  | } | 
|  | case MIPS_BP_KIND_MICROMIPS16: | 
|  | { | 
|  | static gdb_byte micromips16_big_breakpoint[] = { 0x46, 0x85 }; | 
|  | static gdb_byte micromips16_little_breakpoint[] = { 0x85, 0x46 }; | 
|  |  | 
|  | *size = 2; | 
|  |  | 
|  | if (byte_order_for_code == BFD_ENDIAN_BIG) | 
|  | return micromips16_big_breakpoint; | 
|  | else | 
|  | return micromips16_little_breakpoint; | 
|  | } | 
|  | case MIPS_BP_KIND_MICROMIPS32: | 
|  | { | 
|  | static gdb_byte micromips32_big_breakpoint[] = { 0, 0x5, 0, 0x7 }; | 
|  | static gdb_byte micromips32_little_breakpoint[] = { 0x5, 0, 0x7, 0 }; | 
|  |  | 
|  | *size = 4; | 
|  | if (byte_order_for_code == BFD_ENDIAN_BIG) | 
|  | return micromips32_big_breakpoint; | 
|  | else | 
|  | return micromips32_little_breakpoint; | 
|  | } | 
|  | case MIPS_BP_KIND_MIPS32: | 
|  | { | 
|  | static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd }; | 
|  | static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 }; | 
|  |  | 
|  | *size = 4; | 
|  | if (byte_order_for_code == BFD_ENDIAN_BIG) | 
|  | return big_breakpoint; | 
|  | else | 
|  | return little_breakpoint; | 
|  | } | 
|  | default: | 
|  | gdb_assert_not_reached ("unexpected mips breakpoint kind"); | 
|  | }; | 
|  | } | 
|  |  | 
|  | /* Return non-zero if the standard MIPS instruction INST has a branch | 
|  | delay slot (i.e. it is a jump or branch instruction).  This function | 
|  | is based on mips32_next_pc.  */ | 
|  |  | 
|  | static int | 
|  | mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst) | 
|  | { | 
|  | int op; | 
|  | int rs; | 
|  | int rt; | 
|  |  | 
|  | op = itype_op (inst); | 
|  | if ((inst & 0xe0000000) != 0) | 
|  | { | 
|  | rs = itype_rs (inst); | 
|  | rt = itype_rt (inst); | 
|  | return (is_octeon_bbit_op (op, gdbarch) | 
|  | || op >> 2 == 5	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx  */ | 
|  | || op == 29	/* JALX: bits 011101  */ | 
|  | || (op == 17 | 
|  | && (rs == 8 | 
|  | /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000  */ | 
|  | || (rs == 9 && (rt & 0x2) == 0) | 
|  | /* BC1ANY2F, BC1ANY2T: bits 010001 01001  */ | 
|  | || (rs == 10 && (rt & 0x2) == 0)))); | 
|  | /* BC1ANY4F, BC1ANY4T: bits 010001 01010  */ | 
|  | } | 
|  | else | 
|  | switch (op & 0x07)		/* extract bits 28,27,26  */ | 
|  | { | 
|  | case 0:			/* SPECIAL  */ | 
|  | op = rtype_funct (inst); | 
|  | return (op == 8		/* JR  */ | 
|  | || op == 9);	/* JALR  */ | 
|  | break;			/* end SPECIAL  */ | 
|  | case 1:			/* REGIMM  */ | 
|  | rs = itype_rs (inst); | 
|  | rt = itype_rt (inst);	/* branch condition  */ | 
|  | return ((rt & 0xc) == 0 | 
|  | /* BLTZ, BLTZL, BGEZ, BGEZL: bits 000xx  */ | 
|  | /* BLTZAL, BLTZALL, BGEZAL, BGEZALL: 100xx  */ | 
|  | || ((rt & 0x1e) == 0x1c && rs == 0)); | 
|  | /* BPOSGE32, BPOSGE64: bits 1110x  */ | 
|  | break;			/* end REGIMM  */ | 
|  | default:			/* J, JAL, BEQ, BNE, BLEZ, BGTZ  */ | 
|  | return 1; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Return non-zero if a standard MIPS instruction at ADDR has a branch | 
|  | delay slot (i.e. it is a jump or branch instruction).  */ | 
|  |  | 
|  | static int | 
|  | mips32_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr) | 
|  | { | 
|  | ULONGEST insn; | 
|  | int status; | 
|  |  | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status); | 
|  | if (status) | 
|  | return 0; | 
|  |  | 
|  | return mips32_instruction_has_delay_slot (gdbarch, insn); | 
|  | } | 
|  |  | 
|  | /* Return non-zero if the microMIPS instruction INSN, comprising the | 
|  | 16-bit major opcode word in the high 16 bits and any second word | 
|  | in the low 16 bits, has a branch delay slot (i.e. it is a non-compact | 
|  | jump or branch instruction).  The instruction must be 32-bit if | 
|  | MUSTBE32 is set or can be any instruction otherwise.  */ | 
|  |  | 
|  | static int | 
|  | micromips_instruction_has_delay_slot (ULONGEST insn, int mustbe32) | 
|  | { | 
|  | ULONGEST major = insn >> 16; | 
|  |  | 
|  | switch (micromips_op (major)) | 
|  | { | 
|  | /* 16-bit instructions.  */ | 
|  | case 0x33:			/* B16: bits 110011 */ | 
|  | case 0x2b:			/* BNEZ16: bits 101011 */ | 
|  | case 0x23:			/* BEQZ16: bits 100011 */ | 
|  | return !mustbe32; | 
|  | case 0x11:			/* POOL16C: bits 010001 */ | 
|  | return (!mustbe32 | 
|  | && ((b5s5_op (major) == 0xc | 
|  | /* JR16: bits 010001 01100 */ | 
|  | || (b5s5_op (major) & 0x1e) == 0xe))); | 
|  | /* JALR16, JALRS16: bits 010001 0111x */ | 
|  | /* 32-bit instructions.  */ | 
|  | case 0x3d:			/* JAL: bits 111101 */ | 
|  | case 0x3c:			/* JALX: bits 111100 */ | 
|  | case 0x35:			/* J: bits 110101 */ | 
|  | case 0x2d:			/* BNE: bits 101101 */ | 
|  | case 0x25:			/* BEQ: bits 100101 */ | 
|  | case 0x1d:			/* JALS: bits 011101 */ | 
|  | return 1; | 
|  | case 0x10:			/* POOL32I: bits 010000 */ | 
|  | return ((b5s5_op (major) & 0x1c) == 0x0 | 
|  | /* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */ | 
|  | || (b5s5_op (major) & 0x1d) == 0x4 | 
|  | /* BLEZ, BGTZ: bits 010000 001x0 */ | 
|  | || (b5s5_op (major) & 0x1d) == 0x11 | 
|  | /* BLTZALS, BGEZALS: bits 010000 100x1 */ | 
|  | || ((b5s5_op (major) & 0x1e) == 0x14 | 
|  | && (major & 0x3) == 0x0) | 
|  | /* BC2F, BC2T: bits 010000 1010x xxx00 */ | 
|  | || (b5s5_op (major) & 0x1e) == 0x1a | 
|  | /* BPOSGE64, BPOSGE32: bits 010000 1101x */ | 
|  | || ((b5s5_op (major) & 0x1e) == 0x1c | 
|  | && (major & 0x3) == 0x0) | 
|  | /* BC1F, BC1T: bits 010000 1110x xxx00 */ | 
|  | || ((b5s5_op (major) & 0x1c) == 0x1c | 
|  | && (major & 0x3) == 0x1)); | 
|  | /* BC1ANY*: bits 010000 111xx xxx01 */ | 
|  | case 0x0:			/* POOL32A: bits 000000 */ | 
|  | return (b0s6_op (insn) == 0x3c | 
|  | /* POOL32Axf: bits 000000 ... 111100 */ | 
|  | && (b6s10_ext (insn) & 0x2bf) == 0x3c); | 
|  | /* JALR, JALR.HB: 000000 000x111100 111100 */ | 
|  | /* JALRS, JALRS.HB: 000000 010x111100 111100 */ | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Return non-zero if a microMIPS instruction at ADDR has a branch delay | 
|  | slot (i.e. it is a non-compact jump instruction).  The instruction | 
|  | must be 32-bit if MUSTBE32 is set or can be any instruction otherwise.  */ | 
|  |  | 
|  | static int | 
|  | micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, | 
|  | CORE_ADDR addr, int mustbe32) | 
|  | { | 
|  | ULONGEST insn; | 
|  | int status; | 
|  | int size; | 
|  |  | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status); | 
|  | if (status) | 
|  | return 0; | 
|  | size = mips_insn_size (ISA_MICROMIPS, insn); | 
|  | insn <<= 16; | 
|  | if (size == 2 * MIPS_INSN16_SIZE) | 
|  | { | 
|  | insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status); | 
|  | if (status) | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | return micromips_instruction_has_delay_slot (insn, mustbe32); | 
|  | } | 
|  |  | 
|  | /* Return non-zero if the MIPS16 instruction INST, which must be | 
|  | a 32-bit instruction if MUSTBE32 is set or can be any instruction | 
|  | otherwise, has a branch delay slot (i.e. it is a non-compact jump | 
|  | instruction).  This function is based on mips16_next_pc.  */ | 
|  |  | 
|  | static int | 
|  | mips16_instruction_has_delay_slot (unsigned short inst, int mustbe32) | 
|  | { | 
|  | if ((inst & 0xf89f) == 0xe800)	/* JR/JALR (16-bit instruction)  */ | 
|  | return !mustbe32; | 
|  | return (inst & 0xf800) == 0x1800;	/* JAL/JALX (32-bit instruction)  */ | 
|  | } | 
|  |  | 
|  | /* Return non-zero if a MIPS16 instruction at ADDR has a branch delay | 
|  | slot (i.e. it is a non-compact jump instruction).  The instruction | 
|  | must be 32-bit if MUSTBE32 is set or can be any instruction otherwise.  */ | 
|  |  | 
|  | static int | 
|  | mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, | 
|  | CORE_ADDR addr, int mustbe32) | 
|  | { | 
|  | unsigned short insn; | 
|  | int status; | 
|  |  | 
|  | insn = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status); | 
|  | if (status) | 
|  | return 0; | 
|  |  | 
|  | return mips16_instruction_has_delay_slot (insn, mustbe32); | 
|  | } | 
|  |  | 
|  | /* Calculate the starting address of the MIPS memory segment BPADDR is in. | 
|  | This assumes KSSEG exists.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_segment_boundary (CORE_ADDR bpaddr) | 
|  | { | 
|  | CORE_ADDR mask = CORE_ADDR_MAX; | 
|  | int segsize; | 
|  |  | 
|  | if (sizeof (CORE_ADDR) == 8) | 
|  | /* Get the topmost two bits of bpaddr in a 32-bit safe manner (avoid | 
|  | a compiler warning produced where CORE_ADDR is a 32-bit type even | 
|  | though in that case this is dead code).  */ | 
|  | switch (bpaddr >> ((sizeof (CORE_ADDR) << 3) - 2) & 3) | 
|  | { | 
|  | case 3: | 
|  | if (bpaddr == (bfd_signed_vma) (int32_t) bpaddr) | 
|  | segsize = 29;			/* 32-bit compatibility segment  */ | 
|  | else | 
|  | segsize = 62;			/* xkseg  */ | 
|  | break; | 
|  | case 2:				/* xkphys  */ | 
|  | segsize = 59; | 
|  | break; | 
|  | default:				/* xksseg (1), xkuseg/kuseg (0)  */ | 
|  | segsize = 62; | 
|  | break; | 
|  | } | 
|  | else if (bpaddr & 0x80000000)		/* kernel segment  */ | 
|  | segsize = 29; | 
|  | else | 
|  | segsize = 31;			/* user segment  */ | 
|  | mask <<= segsize; | 
|  | return bpaddr & mask; | 
|  | } | 
|  |  | 
|  | /* Move the breakpoint at BPADDR out of any branch delay slot by shifting | 
|  | it backwards if necessary.  Return the address of the new location.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) | 
|  | { | 
|  | CORE_ADDR prev_addr; | 
|  | CORE_ADDR boundary; | 
|  | CORE_ADDR func_addr; | 
|  |  | 
|  | /* If a breakpoint is set on the instruction in a branch delay slot, | 
|  | GDB gets confused.  When the breakpoint is hit, the PC isn't on | 
|  | the instruction in the branch delay slot, the PC will point to | 
|  | the branch instruction.  Since the PC doesn't match any known | 
|  | breakpoints, GDB reports a trap exception. | 
|  |  | 
|  | There are two possible fixes for this problem. | 
|  |  | 
|  | 1) When the breakpoint gets hit, see if the BD bit is set in the | 
|  | Cause register (which indicates the last exception occurred in a | 
|  | branch delay slot).  If the BD bit is set, fix the PC to point to | 
|  | the instruction in the branch delay slot. | 
|  |  | 
|  | 2) When the user sets the breakpoint, don't allow him to set the | 
|  | breakpoint on the instruction in the branch delay slot.  Instead | 
|  | move the breakpoint to the branch instruction (which will have | 
|  | the same result). | 
|  |  | 
|  | The problem with the first solution is that if the user then | 
|  | single-steps the processor, the branch instruction will get | 
|  | skipped (since GDB thinks the PC is on the instruction in the | 
|  | branch delay slot). | 
|  |  | 
|  | So, we'll use the second solution.  To do this we need to know if | 
|  | the instruction we're trying to set the breakpoint on is in the | 
|  | branch delay slot.  */ | 
|  |  | 
|  | boundary = mips_segment_boundary (bpaddr); | 
|  |  | 
|  | /* Make sure we don't scan back before the beginning of the current | 
|  | function, since we may fetch constant data or insns that look like | 
|  | a jump.  Of course we might do that anyway if the compiler has | 
|  | moved constants inline. :-(  */ | 
|  | if (find_pc_partial_function (bpaddr, NULL, &func_addr, NULL) | 
|  | && func_addr > boundary && func_addr <= bpaddr) | 
|  | boundary = func_addr; | 
|  |  | 
|  | if (mips_pc_is_mips (bpaddr)) | 
|  | { | 
|  | if (bpaddr == boundary) | 
|  | return bpaddr; | 
|  |  | 
|  | /* If the previous instruction has a branch delay slot, we have | 
|  | to move the breakpoint to the branch instruction. */ | 
|  | prev_addr = bpaddr - 4; | 
|  | if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr)) | 
|  | bpaddr = prev_addr; | 
|  | } | 
|  | else | 
|  | { | 
|  | int (*insn_at_pc_has_delay_slot) (struct gdbarch *, CORE_ADDR, int); | 
|  | CORE_ADDR addr, jmpaddr; | 
|  | int i; | 
|  |  | 
|  | boundary = unmake_compact_addr (boundary); | 
|  |  | 
|  | /* The only MIPS16 instructions with delay slots are JAL, JALX, | 
|  | JALR and JR.  An absolute JAL/JALX is always 4 bytes long, | 
|  | so try for that first, then try the 2 byte JALR/JR. | 
|  | The microMIPS ASE has a whole range of jumps and branches | 
|  | with delay slots, some of which take 4 bytes and some take | 
|  | 2 bytes, so the idea is the same. | 
|  | FIXME: We have to assume that bpaddr is not the second half | 
|  | of an extended instruction.  */ | 
|  | insn_at_pc_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr) | 
|  | ? micromips_insn_at_pc_has_delay_slot | 
|  | : mips16_insn_at_pc_has_delay_slot); | 
|  |  | 
|  | jmpaddr = 0; | 
|  | addr = bpaddr; | 
|  | for (i = 1; i < 4; i++) | 
|  | { | 
|  | if (unmake_compact_addr (addr) == boundary) | 
|  | break; | 
|  | addr -= MIPS_INSN16_SIZE; | 
|  | if (i == 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 0)) | 
|  | /* Looks like a JR/JALR at [target-1], but it could be | 
|  | the second word of a previous JAL/JALX, so record it | 
|  | and check back one more.  */ | 
|  | jmpaddr = addr; | 
|  | else if (i > 1 && insn_at_pc_has_delay_slot (gdbarch, addr, 1)) | 
|  | { | 
|  | if (i == 2) | 
|  | /* Looks like a JAL/JALX at [target-2], but it could also | 
|  | be the second word of a previous JAL/JALX, record it, | 
|  | and check back one more.  */ | 
|  | jmpaddr = addr; | 
|  | else | 
|  | /* Looks like a JAL/JALX at [target-3], so any previously | 
|  | recorded JAL/JALX or JR/JALR must be wrong, because: | 
|  |  | 
|  | >-3: JAL | 
|  | -2: JAL-ext (can't be JAL/JALX) | 
|  | -1: bdslot (can't be JR/JALR) | 
|  | 0: target insn | 
|  |  | 
|  | Of course it could be another JAL-ext which looks | 
|  | like a JAL, but in that case we'd have broken out | 
|  | of this loop at [target-2]: | 
|  |  | 
|  | -4: JAL | 
|  | >-3: JAL-ext | 
|  | -2: bdslot (can't be jmp) | 
|  | -1: JR/JALR | 
|  | 0: target insn  */ | 
|  | jmpaddr = 0; | 
|  | } | 
|  | else | 
|  | { | 
|  | /* Not a jump instruction: if we're at [target-1] this | 
|  | could be the second word of a JAL/JALX, so continue; | 
|  | otherwise we're done.  */ | 
|  | if (i > 1) | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (jmpaddr) | 
|  | bpaddr = jmpaddr; | 
|  | } | 
|  |  | 
|  | return bpaddr; | 
|  | } | 
|  |  | 
|  | /* Return non-zero if SUFFIX is one of the numeric suffixes used for MIPS16 | 
|  | call stubs, one of 1, 2, 5, 6, 9, 10, or, if ZERO is non-zero, also 0.  */ | 
|  |  | 
|  | static int | 
|  | mips_is_stub_suffix (const char *suffix, int zero) | 
|  | { | 
|  | switch (suffix[0]) | 
|  | { | 
|  | case '0': | 
|  | return zero && suffix[1] == '\0'; | 
|  | case '1': | 
|  | return suffix[1] == '\0' || (suffix[1] == '0' && suffix[2] == '\0'); | 
|  | case '2': | 
|  | case '5': | 
|  | case '6': | 
|  | case '9': | 
|  | return suffix[1] == '\0'; | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Return non-zero if MODE is one of the mode infixes used for MIPS16 | 
|  | call stubs, one of sf, df, sc, or dc.  */ | 
|  |  | 
|  | static int | 
|  | mips_is_stub_mode (const char *mode) | 
|  | { | 
|  | return ((mode[0] == 's' || mode[0] == 'd') | 
|  | && (mode[1] == 'f' || mode[1] == 'c')); | 
|  | } | 
|  |  | 
|  | /* Code at PC is a compiler-generated stub.  Such a stub for a function | 
|  | bar might have a name like __fn_stub_bar, and might look like this: | 
|  |  | 
|  | mfc1    $4, $f13 | 
|  | mfc1    $5, $f12 | 
|  | mfc1    $6, $f15 | 
|  | mfc1    $7, $f14 | 
|  |  | 
|  | followed by (or interspersed with): | 
|  |  | 
|  | j       bar | 
|  |  | 
|  | or: | 
|  |  | 
|  | lui     $25, %hi(bar) | 
|  | addiu   $25, $25, %lo(bar) | 
|  | jr      $25 | 
|  |  | 
|  | ($1 may be used in old code; for robustness we accept any register) | 
|  | or, in PIC code: | 
|  |  | 
|  | lui     $28, %hi(_gp_disp) | 
|  | addiu   $28, $28, %lo(_gp_disp) | 
|  | addu    $28, $28, $25 | 
|  | lw      $25, %got(bar) | 
|  | addiu   $25, $25, %lo(bar) | 
|  | jr      $25 | 
|  |  | 
|  | In the case of a __call_stub_bar stub, the sequence to set up | 
|  | arguments might look like this: | 
|  |  | 
|  | mtc1    $4, $f13 | 
|  | mtc1    $5, $f12 | 
|  | mtc1    $6, $f15 | 
|  | mtc1    $7, $f14 | 
|  |  | 
|  | followed by (or interspersed with) one of the jump sequences above. | 
|  |  | 
|  | In the case of a __call_stub_fp_bar stub, JAL or JALR is used instead | 
|  | of J or JR, respectively, followed by: | 
|  |  | 
|  | mfc1    $2, $f0 | 
|  | mfc1    $3, $f1 | 
|  | jr      $18 | 
|  |  | 
|  | We are at the beginning of the stub here, and scan down and extract | 
|  | the target address from the jump immediate instruction or, if a jump | 
|  | register instruction is used, from the register referred.  Return | 
|  | the value of PC calculated or 0 if inconclusive. | 
|  |  | 
|  | The limit on the search is arbitrarily set to 20 instructions.  FIXME.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_get_mips16_fn_stub_pc (frame_info_ptr frame, CORE_ADDR pc) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | int addrreg = MIPS_ZERO_REGNUM; | 
|  | CORE_ADDR start_pc = pc; | 
|  | CORE_ADDR target_pc = 0; | 
|  | CORE_ADDR addr = 0; | 
|  | CORE_ADDR gp = 0; | 
|  | int status = 0; | 
|  | int i; | 
|  |  | 
|  | for (i = 0; | 
|  | status == 0 && target_pc == 0 && i < 20; | 
|  | i++, pc += MIPS_INSN32_SIZE) | 
|  | { | 
|  | ULONGEST inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL); | 
|  | CORE_ADDR imm; | 
|  | int rt; | 
|  | int rs; | 
|  | int rd; | 
|  |  | 
|  | switch (itype_op (inst)) | 
|  | { | 
|  | case 0:		/* SPECIAL */ | 
|  | switch (rtype_funct (inst)) | 
|  | { | 
|  | case 8:		/* JR */ | 
|  | case 9:		/* JALR */ | 
|  | rs = rtype_rs (inst); | 
|  | if (rs == MIPS_GP_REGNUM) | 
|  | target_pc = gp;				/* Hmm...  */ | 
|  | else if (rs == addrreg) | 
|  | target_pc = addr; | 
|  | break; | 
|  |  | 
|  | case 0x21:		/* ADDU */ | 
|  | rt = rtype_rt (inst); | 
|  | rs = rtype_rs (inst); | 
|  | rd = rtype_rd (inst); | 
|  | if (rd == MIPS_GP_REGNUM | 
|  | && ((rs == MIPS_GP_REGNUM && rt == MIPS_T9_REGNUM) | 
|  | || (rs == MIPS_T9_REGNUM && rt == MIPS_GP_REGNUM))) | 
|  | gp += start_pc; | 
|  | break; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 2:		/* J */ | 
|  | case 3:		/* JAL */ | 
|  | target_pc = jtype_target (inst) << 2; | 
|  | target_pc += ((pc + 4) & ~(CORE_ADDR) 0x0fffffff); | 
|  | break; | 
|  |  | 
|  | case 9:		/* ADDIU */ | 
|  | rt = itype_rt (inst); | 
|  | rs = itype_rs (inst); | 
|  | if (rt == rs) | 
|  | { | 
|  | imm = (itype_immediate (inst) ^ 0x8000) - 0x8000; | 
|  | if (rt == MIPS_GP_REGNUM) | 
|  | gp += imm; | 
|  | else if (rt == addrreg) | 
|  | addr += imm; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 0xf:	/* LUI */ | 
|  | rt = itype_rt (inst); | 
|  | imm = ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 16; | 
|  | if (rt == MIPS_GP_REGNUM) | 
|  | gp = imm; | 
|  | else if (rt != MIPS_ZERO_REGNUM) | 
|  | { | 
|  | addrreg = rt; | 
|  | addr = imm; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case 0x23:	/* LW */ | 
|  | rt = itype_rt (inst); | 
|  | rs = itype_rs (inst); | 
|  | imm = (itype_immediate (inst) ^ 0x8000) - 0x8000; | 
|  | if (gp != 0 && rs == MIPS_GP_REGNUM) | 
|  | { | 
|  | gdb_byte buf[4]; | 
|  |  | 
|  | memset (buf, 0, sizeof (buf)); | 
|  | status = target_read_memory (gp + imm, buf, sizeof (buf)); | 
|  | addrreg = rt; | 
|  | addr = extract_signed_integer (buf, sizeof (buf), byte_order); | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | return target_pc; | 
|  | } | 
|  |  | 
|  | /* If PC is in a MIPS16 call or return stub, return the address of the | 
|  | target PC, which is either the callee or the caller.  There are several | 
|  | cases which must be handled: | 
|  |  | 
|  | * If the PC is in __mips16_ret_{d,s}{f,c}, this is a return stub | 
|  | and the target PC is in $31 ($ra). | 
|  | * If the PC is in __mips16_call_stub_{1..10}, this is a call stub | 
|  | and the target PC is in $2. | 
|  | * If the PC at the start of __mips16_call_stub_{s,d}{f,c}_{0..10}, | 
|  | i.e. before the JALR instruction, this is effectively a call stub | 
|  | and the target PC is in $2.  Otherwise this is effectively | 
|  | a return stub and the target PC is in $18. | 
|  | * If the PC is at the start of __call_stub_fp_*, i.e. before the | 
|  | JAL or JALR instruction, this is effectively a call stub and the | 
|  | target PC is buried in the instruction stream.  Otherwise this | 
|  | is effectively a return stub and the target PC is in $18. | 
|  | * If the PC is in __call_stub_* or in __fn_stub_*, this is a call | 
|  | stub and the target PC is buried in the instruction stream. | 
|  |  | 
|  | See the source code for the stubs in gcc/config/mips/mips16.S, or the | 
|  | stub builder in gcc/config/mips/mips.c (mips16_build_call_stub) for the | 
|  | gory details.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_skip_mips16_trampoline_code (frame_info_ptr frame, CORE_ADDR pc) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | CORE_ADDR start_addr; | 
|  | const char *name; | 
|  | size_t prefixlen; | 
|  |  | 
|  | /* Find the starting address and name 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_ret_{d,s}{f,c}, this is a return stub | 
|  | and the target PC is in $31 ($ra).  */ | 
|  | prefixlen = strlen (mips_str_mips16_ret_stub); | 
|  | if (strncmp (name, mips_str_mips16_ret_stub, prefixlen) == 0 | 
|  | && mips_is_stub_mode (name + prefixlen) | 
|  | && name[prefixlen + 2] == '\0') | 
|  | return get_frame_register_signed | 
|  | (frame, gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM); | 
|  |  | 
|  | /* If the PC is in __mips16_call_stub_*, this is one of the call | 
|  | call/return stubs.  */ | 
|  | prefixlen = strlen (mips_str_mips16_call_stub); | 
|  | if (strncmp (name, mips_str_mips16_call_stub, prefixlen) == 0) | 
|  | { | 
|  | /* If the PC is in __mips16_call_stub_{1..10}, this is a call stub | 
|  | and the target PC is in $2.  */ | 
|  | if (mips_is_stub_suffix (name + prefixlen, 0)) | 
|  | return get_frame_register_signed | 
|  | (frame, gdbarch_num_regs (gdbarch) + MIPS_V0_REGNUM); | 
|  |  | 
|  | /* If the PC at the start of __mips16_call_stub_{s,d}{f,c}_{0..10}, | 
|  | i.e. before the JALR instruction, this is effectively a call stub | 
|  | and the target PC is in $2.  Otherwise this is effectively | 
|  | a return stub and the target PC is in $18.  */ | 
|  | else if (mips_is_stub_mode (name + prefixlen) | 
|  | && name[prefixlen + 2] == '_' | 
|  | && mips_is_stub_suffix (name + prefixlen + 3, 0)) | 
|  | { | 
|  | if (pc == start_addr) | 
|  | /* This is the 'call' part of a call stub.  The return | 
|  | address is in $2.  */ | 
|  | return get_frame_register_signed | 
|  | (frame, gdbarch_num_regs (gdbarch) + MIPS_V0_REGNUM); | 
|  | else | 
|  | /* This is the 'return' part of a call stub.  The return | 
|  | address is in $18.  */ | 
|  | return get_frame_register_signed | 
|  | (frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM); | 
|  | } | 
|  | else | 
|  | return 0;		/* Not a stub.  */ | 
|  | } | 
|  |  | 
|  | /* If the PC is in __call_stub_* or __fn_stub*, this is one of the | 
|  | compiler-generated call or call/return stubs.  */ | 
|  | if (startswith (name, mips_str_fn_stub) | 
|  | || startswith (name, mips_str_call_stub)) | 
|  | { | 
|  | if (pc == start_addr) | 
|  | /* This is the 'call' part of a call stub.  Call this helper | 
|  | to scan through this code for interesting instructions | 
|  | and determine the final PC.  */ | 
|  | return mips_get_mips16_fn_stub_pc (frame, pc); | 
|  | else | 
|  | /* This is the 'return' part of a call stub.  The return address | 
|  | is in $18.  */ | 
|  | return get_frame_register_signed | 
|  | (frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM); | 
|  | } | 
|  |  | 
|  | return 0;			/* Not a stub.  */ | 
|  | } | 
|  |  | 
|  | /* Return non-zero if the PC is inside a return thunk (aka stub or trampoline). | 
|  | This implements the IN_SOLIB_RETURN_TRAMPOLINE macro.  */ | 
|  |  | 
|  | static int | 
|  | mips_in_return_stub (struct gdbarch *gdbarch, CORE_ADDR pc, const char *name) | 
|  | { | 
|  | CORE_ADDR start_addr; | 
|  | size_t prefixlen; | 
|  |  | 
|  | /* Find the starting address of the function containing the PC.  */ | 
|  | if (find_pc_partial_function (pc, NULL, &start_addr, NULL) == 0) | 
|  | return 0; | 
|  |  | 
|  | /* If the PC is in __mips16_call_stub_{s,d}{f,c}_{0..10} but not at | 
|  | the start, i.e. after the JALR instruction, this is effectively | 
|  | a return stub.  */ | 
|  | prefixlen = strlen (mips_str_mips16_call_stub); | 
|  | if (pc != start_addr | 
|  | && strncmp (name, mips_str_mips16_call_stub, prefixlen) == 0 | 
|  | && mips_is_stub_mode (name + prefixlen) | 
|  | && name[prefixlen + 2] == '_' | 
|  | && mips_is_stub_suffix (name + prefixlen + 3, 1)) | 
|  | return 1; | 
|  |  | 
|  | /* If the PC is in __call_stub_fp_* but not at the start, i.e. after | 
|  | the JAL or JALR instruction, this is effectively a return stub.  */ | 
|  | prefixlen = strlen (mips_str_call_fp_stub); | 
|  | if (pc != start_addr | 
|  | && strncmp (name, mips_str_call_fp_stub, prefixlen) == 0) | 
|  | return 1; | 
|  |  | 
|  | /* Consume the .pic. prefix of any PIC stub, this function must return | 
|  | true when the PC is in a PIC stub of a __mips16_ret_{d,s}{f,c} stub | 
|  | or the call stub path will trigger in handle_inferior_event causing | 
|  | it to go astray.  */ | 
|  | prefixlen = strlen (mips_str_pic); | 
|  | if (strncmp (name, mips_str_pic, prefixlen) == 0) | 
|  | name += prefixlen; | 
|  |  | 
|  | /* If the PC is in __mips16_ret_{d,s}{f,c}, this is a return stub.  */ | 
|  | prefixlen = strlen (mips_str_mips16_ret_stub); | 
|  | if (strncmp (name, mips_str_mips16_ret_stub, prefixlen) == 0 | 
|  | && mips_is_stub_mode (name + prefixlen) | 
|  | && name[prefixlen + 2] == '\0') | 
|  | return 1; | 
|  |  | 
|  | return 0;			/* Not a stub.  */ | 
|  | } | 
|  |  | 
|  | /* If the current PC is the start of a non-PIC-to-PIC stub, return the | 
|  | PC of the stub target.  The stub just loads $t9 and jumps to it, | 
|  | so that $t9 has the correct value at function entry.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_skip_pic_trampoline_code (frame_info_ptr frame, CORE_ADDR pc) | 
|  | { | 
|  | struct gdbarch *gdbarch = get_frame_arch (frame); | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | struct bound_minimal_symbol msym; | 
|  | int i; | 
|  | gdb_byte stub_code[16]; | 
|  | int32_t stub_words[4]; | 
|  |  | 
|  | /* The stub for foo is named ".pic.foo", and is either two | 
|  | instructions inserted before foo or a three instruction sequence | 
|  | which jumps to foo.  */ | 
|  | msym = lookup_minimal_symbol_by_pc (pc); | 
|  | if (msym.minsym == NULL | 
|  | || msym.value_address () != pc | 
|  | || msym.minsym->linkage_name () == NULL | 
|  | || !startswith (msym.minsym->linkage_name (), ".pic.")) | 
|  | return 0; | 
|  |  | 
|  | /* A two-instruction header.  */ | 
|  | if (msym.minsym->size () == 8) | 
|  | return pc + 8; | 
|  |  | 
|  | /* A three-instruction (plus delay slot) trampoline.  */ | 
|  | if (msym.minsym->size () == 16) | 
|  | { | 
|  | if (target_read_memory (pc, stub_code, 16) != 0) | 
|  | return 0; | 
|  | for (i = 0; i < 4; i++) | 
|  | stub_words[i] = extract_unsigned_integer (stub_code + i * 4, | 
|  | 4, byte_order); | 
|  |  | 
|  | /* A stub contains these instructions: | 
|  | lui	t9, %hi(target) | 
|  | j	target | 
|  | addiu	t9, t9, %lo(target) | 
|  | nop | 
|  |  | 
|  | This works even for N64, since stubs are only generated with | 
|  | -msym32.  */ | 
|  | if ((stub_words[0] & 0xffff0000U) == 0x3c190000 | 
|  | && (stub_words[1] & 0xfc000000U) == 0x08000000 | 
|  | && (stub_words[2] & 0xffff0000U) == 0x27390000 | 
|  | && stub_words[3] == 0x00000000) | 
|  | return ((((stub_words[0] & 0x0000ffff) << 16) | 
|  | + (stub_words[2] & 0x0000ffff)) ^ 0x8000) - 0x8000; | 
|  | } | 
|  |  | 
|  | /* Not a recognized stub.  */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_skip_trampoline_code (frame_info_ptr frame, CORE_ADDR pc) | 
|  | { | 
|  | CORE_ADDR requested_pc = pc; | 
|  | CORE_ADDR target_pc; | 
|  | CORE_ADDR new_pc; | 
|  |  | 
|  | do | 
|  | { | 
|  | target_pc = pc; | 
|  |  | 
|  | new_pc = mips_skip_mips16_trampoline_code (frame, pc); | 
|  | if (new_pc) | 
|  | pc = new_pc; | 
|  |  | 
|  | new_pc = find_solib_trampoline_target (frame, pc); | 
|  | if (new_pc) | 
|  | pc = new_pc; | 
|  |  | 
|  | new_pc = mips_skip_pic_trampoline_code (frame, pc); | 
|  | if (new_pc) | 
|  | pc = new_pc; | 
|  | } | 
|  | while (pc != target_pc); | 
|  |  | 
|  | return pc != requested_pc ? pc : 0; | 
|  | } | 
|  |  | 
|  | /* Convert a dbx stab register number (from `r' declaration) to a GDB | 
|  | [1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */ | 
|  |  | 
|  | static int | 
|  | mips_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) | 
|  | { | 
|  | int regnum; | 
|  | if (num >= 0 && num < 32) | 
|  | regnum = num; | 
|  | else if (num >= 38 && num < 70) | 
|  | regnum = num + mips_regnum (gdbarch)->fp0 - 38; | 
|  | else if (num == 70) | 
|  | regnum = mips_regnum (gdbarch)->hi; | 
|  | else if (num == 71) | 
|  | regnum = mips_regnum (gdbarch)->lo; | 
|  | else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 72 && num < 78) | 
|  | regnum = num + mips_regnum (gdbarch)->dspacc - 72; | 
|  | else | 
|  | return -1; | 
|  | return gdbarch_num_regs (gdbarch) + regnum; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Convert a dwarf, dwarf2, or ecoff register number to a GDB [1 * | 
|  | gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */ | 
|  |  | 
|  | static int | 
|  | mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num) | 
|  | { | 
|  | int regnum; | 
|  | if (num >= 0 && num < 32) | 
|  | regnum = num; | 
|  | else if (num >= 32 && num < 64) | 
|  | regnum = num + mips_regnum (gdbarch)->fp0 - 32; | 
|  | else if (num == 64) | 
|  | regnum = mips_regnum (gdbarch)->hi; | 
|  | else if (num == 65) | 
|  | regnum = mips_regnum (gdbarch)->lo; | 
|  | else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 66 && num < 72) | 
|  | regnum = num + mips_regnum (gdbarch)->dspacc - 66; | 
|  | else | 
|  | return -1; | 
|  | return gdbarch_num_regs (gdbarch) + regnum; | 
|  | } | 
|  |  | 
|  | static int | 
|  | mips_register_sim_regno (struct gdbarch *gdbarch, int regnum) | 
|  | { | 
|  | /* Only makes sense to supply raw registers.  */ | 
|  | gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch)); | 
|  | /* FIXME: cagney/2002-05-13: Need to look at the pseudo register to | 
|  | decide if it is valid.  Should instead define a standard sim/gdb | 
|  | register numbering scheme.  */ | 
|  | if (gdbarch_register_name (gdbarch, | 
|  | gdbarch_num_regs (gdbarch) + regnum)[0] != '\0') | 
|  | return regnum; | 
|  | else | 
|  | return LEGACY_SIM_REGNO_IGNORE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Convert an integer into an address.  Extracting the value signed | 
|  | guarantees a correctly sign extended address.  */ | 
|  |  | 
|  | static CORE_ADDR | 
|  | mips_integer_to_address (struct gdbarch *gdbarch, | 
|  | struct type *type, const gdb_byte *buf) | 
|  | { | 
|  | enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); | 
|  | return extract_signed_integer (buf, type->length (), byte_order); | 
|  | } | 
|  |  | 
|  | /* Dummy virtual frame pointer method.  This is no more or less accurate | 
|  | than most other architectures; we just need to be explicit about it, | 
|  | because the pseudo-register gdbarch_sp_regnum will otherwise lead to | 
|  | an assertion failure.  */ | 
|  |  | 
|  | static void | 
|  | mips_virtual_frame_pointer (struct gdbarch *gdbarch, | 
|  | CORE_ADDR pc, int *reg, LONGEST *offset) | 
|  | { | 
|  | *reg = MIPS_SP_REGNUM; | 
|  | *offset = 0; | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_find_abi_section (bfd *abfd, asection *sect, void *obj) | 
|  | { | 
|  | enum mips_abi *abip = (enum mips_abi *) obj; | 
|  | const char *name = bfd_section_name (sect); | 
|  |  | 
|  | if (*abip != MIPS_ABI_UNKNOWN) | 
|  | return; | 
|  |  | 
|  | if (!startswith (name, ".mdebug.")) | 
|  | return; | 
|  |  | 
|  | if (strcmp (name, ".mdebug.abi32") == 0) | 
|  | *abip = MIPS_ABI_O32; | 
|  | else if (strcmp (name, ".mdebug.abiN32") == 0) | 
|  | *abip = MIPS_ABI_N32; | 
|  | else if (strcmp (name, ".mdebug.abi64") == 0) | 
|  | *abip = MIPS_ABI_N64; | 
|  | else if (strcmp (name, ".mdebug.abiO64") == 0) | 
|  | *abip = MIPS_ABI_O64; | 
|  | else if (strcmp (name, ".mdebug.eabi32") == 0) | 
|  | *abip = MIPS_ABI_EABI32; | 
|  | else if (strcmp (name, ".mdebug.eabi64") == 0) | 
|  | *abip = MIPS_ABI_EABI64; | 
|  | else | 
|  | warning (_("unsupported ABI %s."), name + 8); | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_find_long_section (bfd *abfd, asection *sect, void *obj) | 
|  | { | 
|  | int *lbp = (int *) obj; | 
|  | const char *name = bfd_section_name (sect); | 
|  |  | 
|  | if (startswith (name, ".gcc_compiled_long32")) | 
|  | *lbp = 32; | 
|  | else if (startswith (name, ".gcc_compiled_long64")) | 
|  | *lbp = 64; | 
|  | else if (startswith (name, ".gcc_compiled_long")) | 
|  | warning (_("unrecognized .gcc_compiled_longXX")); | 
|  | } | 
|  |  | 
|  | static enum mips_abi | 
|  | global_mips_abi (void) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | for (i = 0; mips_abi_strings[i] != NULL; i++) | 
|  | if (mips_abi_strings[i] == mips_abi_string) | 
|  | return (enum mips_abi) i; | 
|  |  | 
|  | internal_error (_("unknown ABI string")); | 
|  | } | 
|  |  | 
|  | /* Return the default compressed instruction set, either of MIPS16 | 
|  | or microMIPS, selected when none could have been determined from | 
|  | the ELF header of the binary being executed (or no binary has been | 
|  | selected.  */ | 
|  |  | 
|  | static enum mips_isa | 
|  | global_mips_compression (void) | 
|  | { | 
|  | int i; | 
|  |  | 
|  | for (i = 0; mips_compression_strings[i] != NULL; i++) | 
|  | if (mips_compression_strings[i] == mips_compression_string) | 
|  | return (enum mips_isa) i; | 
|  |  | 
|  | internal_error (_("unknown compressed ISA string")); | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_register_g_packet_guesses (struct gdbarch *gdbarch) | 
|  | { | 
|  | /* If the size matches the set of 32-bit or 64-bit integer registers, | 
|  | assume that's what we've got.  */ | 
|  | register_remote_g_packet_guess (gdbarch, 38 * 4, mips_tdesc_gp32); | 
|  | register_remote_g_packet_guess (gdbarch, 38 * 8, mips_tdesc_gp64); | 
|  |  | 
|  | /* If the size matches the full set of registers GDB traditionally | 
|  | knows about, including floating point, for either 32-bit or | 
|  | 64-bit, assume that's what we've got.  */ | 
|  | register_remote_g_packet_guess (gdbarch, 90 * 4, mips_tdesc_gp32); | 
|  | register_remote_g_packet_guess (gdbarch, 90 * 8, mips_tdesc_gp64); | 
|  |  | 
|  | /* Otherwise we don't have a useful guess.  */ | 
|  | } | 
|  |  | 
|  | static struct value * | 
|  | value_of_mips_user_reg (frame_info_ptr frame, const void *baton) | 
|  | { | 
|  | const int *reg_p = (const int *) baton; | 
|  | return value_of_register (*reg_p, frame); | 
|  | } | 
|  |  | 
|  | static struct gdbarch * | 
|  | mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | 
|  | { | 
|  | int elf_flags; | 
|  | enum mips_abi mips_abi, found_abi, wanted_abi; | 
|  | int i, num_regs; | 
|  | enum mips_fpu_type fpu_type; | 
|  | tdesc_arch_data_up tdesc_data; | 
|  | int elf_fpu_type = Val_GNU_MIPS_ABI_FP_ANY; | 
|  | const char * const *reg_names; | 
|  | struct mips_regnum mips_regnum, *regnum; | 
|  | enum mips_isa mips_isa; | 
|  | int dspacc; | 
|  | int dspctl; | 
|  |  | 
|  | /* First of all, extract the elf_flags, if available.  */ | 
|  | if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) | 
|  | elf_flags = elf_elfheader (info.abfd)->e_flags; | 
|  | else if (arches != NULL) | 
|  | { | 
|  | mips_gdbarch_tdep *tdep | 
|  | = gdbarch_tdep<mips_gdbarch_tdep> (arches->gdbarch); | 
|  | elf_flags = tdep->elf_flags; | 
|  | } | 
|  | else | 
|  | elf_flags = 0; | 
|  | if (gdbarch_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_gdbarch_init: elf_flags = 0x%08x\n", elf_flags); | 
|  |  | 
|  | /* Check ELF_FLAGS to see if it specifies the ABI being used.  */ | 
|  | switch ((elf_flags & EF_MIPS_ABI)) | 
|  | { | 
|  | case EF_MIPS_ABI_O32: | 
|  | found_abi = MIPS_ABI_O32; | 
|  | break; | 
|  | case EF_MIPS_ABI_O64: | 
|  | found_abi = MIPS_ABI_O64; | 
|  | break; | 
|  | case EF_MIPS_ABI_EABI32: | 
|  | found_abi = MIPS_ABI_EABI32; | 
|  | break; | 
|  | case EF_MIPS_ABI_EABI64: | 
|  | found_abi = MIPS_ABI_EABI64; | 
|  | break; | 
|  | default: | 
|  | if ((elf_flags & EF_MIPS_ABI2)) | 
|  | found_abi = MIPS_ABI_N32; | 
|  | else | 
|  | found_abi = MIPS_ABI_UNKNOWN; | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* GCC creates a pseudo-section whose name describes the ABI.  */ | 
|  | if (found_abi == MIPS_ABI_UNKNOWN && info.abfd != NULL) | 
|  | bfd_map_over_sections (info.abfd, mips_find_abi_section, &found_abi); | 
|  |  | 
|  | /* If we have no useful BFD information, use the ABI from the last | 
|  | MIPS architecture (if there is one).  */ | 
|  | if (found_abi == MIPS_ABI_UNKNOWN && info.abfd == NULL && arches != NULL) | 
|  | { | 
|  | mips_gdbarch_tdep *tdep | 
|  | = gdbarch_tdep<mips_gdbarch_tdep> (arches->gdbarch); | 
|  | found_abi = tdep->found_abi; | 
|  | } | 
|  |  | 
|  | /* Try the architecture for any hint of the correct ABI.  */ | 
|  | if (found_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: | 
|  | found_abi = MIPS_ABI_EABI32; | 
|  | break; | 
|  | case bfd_mach_mips4100: | 
|  | case bfd_mach_mips5000: | 
|  | found_abi = MIPS_ABI_EABI64; | 
|  | break; | 
|  | case bfd_mach_mips8000: | 
|  | case bfd_mach_mips10000: | 
|  | /* On Irix, ELF64 executables use the N64 ABI.  The | 
|  | pseudo-sections which describe the ABI aren't present | 
|  | on IRIX.  (Even for executables created by gcc.)  */ | 
|  | if (info.abfd != NULL | 
|  | && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour | 
|  | && elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64) | 
|  | found_abi = MIPS_ABI_N64; | 
|  | else | 
|  | found_abi = MIPS_ABI_N32; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Default 64-bit objects to N64 instead of O32.  */ | 
|  | if (found_abi == MIPS_ABI_UNKNOWN | 
|  | && info.abfd != NULL | 
|  | && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour | 
|  | && elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64) | 
|  | found_abi = MIPS_ABI_N64; | 
|  |  | 
|  | if (gdbarch_debug) | 
|  | gdb_printf (gdb_stdlog, "mips_gdbarch_init: found_abi = %d\n", | 
|  | found_abi); | 
|  |  | 
|  | /* What has the user specified from the command line?  */ | 
|  | wanted_abi = global_mips_abi (); | 
|  | if (gdbarch_debug) | 
|  | gdb_printf (gdb_stdlog, "mips_gdbarch_init: wanted_abi = %d\n", | 
|  | wanted_abi); | 
|  |  | 
|  | /* Now that we have found what the ABI for this binary would be, | 
|  | check whether the user is overriding it.  */ | 
|  | if (wanted_abi != MIPS_ABI_UNKNOWN) | 
|  | mips_abi = wanted_abi; | 
|  | else if (found_abi != MIPS_ABI_UNKNOWN) | 
|  | mips_abi = found_abi; | 
|  | else | 
|  | mips_abi = MIPS_ABI_O32; | 
|  | if (gdbarch_debug) | 
|  | gdb_printf (gdb_stdlog, "mips_gdbarch_init: mips_abi = %d\n", | 
|  | mips_abi); | 
|  |  | 
|  | /* Make sure we don't use a 32-bit architecture with a 64-bit ABI.  */ | 
|  | if (mips_abi != MIPS_ABI_EABI32 | 
|  | && mips_abi != MIPS_ABI_O32 | 
|  | && info.bfd_arch_info != NULL | 
|  | && info.bfd_arch_info->arch == bfd_arch_mips | 
|  | && info.bfd_arch_info->bits_per_word < 64) | 
|  | info.bfd_arch_info = bfd_lookup_arch (bfd_arch_mips, bfd_mach_mips4000); | 
|  |  | 
|  | /* Determine the default compressed ISA.  */ | 
|  | if ((elf_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0 | 
|  | && (elf_flags & EF_MIPS_ARCH_ASE_M16) == 0) | 
|  | mips_isa = ISA_MICROMIPS; | 
|  | else if ((elf_flags & EF_MIPS_ARCH_ASE_M16) != 0 | 
|  | && (elf_flags & EF_MIPS_ARCH_ASE_MICROMIPS) == 0) | 
|  | mips_isa = ISA_MIPS16; | 
|  | else | 
|  | mips_isa = global_mips_compression (); | 
|  | mips_compression_string = mips_compression_strings[mips_isa]; | 
|  |  | 
|  | /* Also used when doing an architecture lookup.  */ | 
|  | if (gdbarch_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_gdbarch_init: " | 
|  | "mips64_transfers_32bit_regs_p = %d\n", | 
|  | mips64_transfers_32bit_regs_p); | 
|  |  | 
|  | /* Determine the MIPS FPU type.  */ | 
|  | #ifdef HAVE_ELF | 
|  | if (info.abfd | 
|  | && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour) | 
|  | elf_fpu_type = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, | 
|  | Tag_GNU_MIPS_ABI_FP); | 
|  | #endif /* HAVE_ELF */ | 
|  |  | 
|  | if (!mips_fpu_type_auto) | 
|  | fpu_type = mips_fpu_type; | 
|  | else if (elf_fpu_type != Val_GNU_MIPS_ABI_FP_ANY) | 
|  | { | 
|  | switch (elf_fpu_type) | 
|  | { | 
|  | case Val_GNU_MIPS_ABI_FP_DOUBLE: | 
|  | fpu_type = MIPS_FPU_DOUBLE; | 
|  | break; | 
|  | case Val_GNU_MIPS_ABI_FP_SINGLE: | 
|  | fpu_type = MIPS_FPU_SINGLE; | 
|  | break; | 
|  | case Val_GNU_MIPS_ABI_FP_SOFT: | 
|  | default: | 
|  | /* Soft float or unknown.  */ | 
|  | fpu_type = MIPS_FPU_NONE; | 
|  | break; | 
|  | } | 
|  | } | 
|  | 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: | 
|  | case bfd_mach_mips4120: | 
|  | fpu_type = MIPS_FPU_NONE; | 
|  | break; | 
|  | case bfd_mach_mips4650: | 
|  | fpu_type = MIPS_FPU_SINGLE; | 
|  | break; | 
|  | default: | 
|  | fpu_type = MIPS_FPU_DOUBLE; | 
|  | break; | 
|  | } | 
|  | else if (arches != NULL) | 
|  | fpu_type = mips_get_fpu_type (arches->gdbarch); | 
|  | else | 
|  | fpu_type = MIPS_FPU_DOUBLE; | 
|  | if (gdbarch_debug) | 
|  | gdb_printf (gdb_stdlog, | 
|  | "mips_gdbarch_init: fpu_type = %d\n", fpu_type); | 
|  |  | 
|  | /* Check for blatant incompatibilities.  */ | 
|  |  | 
|  | /* If we have only 32-bit registers, then we can't debug a 64-bit | 
|  | ABI.  */ | 
|  | if (info.target_desc | 
|  | && tdesc_property (info.target_desc, PROPERTY_GP32) != NULL | 
|  | && mips_abi != MIPS_ABI_EABI32 | 
|  | && mips_abi != MIPS_ABI_O32) | 
|  | return NULL; | 
|  |  | 
|  | /* Fill in the OS dependent register numbers and names.  */ | 
|  | if (info.osabi == GDB_OSABI_LINUX) | 
|  | { | 
|  | mips_regnum.fp0 = 38; | 
|  | mips_regnum.pc = 37; | 
|  | mips_regnum.cause = 36; | 
|  | mips_regnum.badvaddr = 35; | 
|  | mips_regnum.hi = 34; | 
|  | mips_regnum.lo = 33; | 
|  | mips_regnum.fp_control_status = 70; | 
|  | mips_regnum.fp_implementation_revision = 71; | 
|  | mips_regnum.dspacc = -1; | 
|  | mips_regnum.dspctl = -1; | 
|  | dspacc = 72; | 
|  | dspctl = 78; | 
|  | num_regs = 90; | 
|  | reg_names = mips_linux_reg_names; | 
|  | } | 
|  | else | 
|  | { | 
|  | mips_regnum.lo = MIPS_EMBED_LO_REGNUM; | 
|  | mips_regnum.hi = MIPS_EMBED_HI_REGNUM; | 
|  | mips_regnum.badvaddr = MIPS_EMBED_BADVADDR_REGNUM; | 
|  | mips_regnum.cause = MIPS_EMBED_CAUSE_REGNUM; | 
|  | mips_regnum.pc = MIPS_EMBED_PC_REGNUM; | 
|  | mips_regnum.fp0 = MIPS_EMBED_FP0_REGNUM; | 
|  | mips_regnum.fp_control_status = 70; | 
|  | mips_regnum.fp_implementation_revision = 71; | 
|  | mips_regnum.dspacc = dspacc = -1; | 
|  | mips_regnum.dspctl = dspctl = -1; | 
|  | num_regs = MIPS_LAST_EMBED_REGNUM + 1; | 
|  | if (info.bfd_arch_info != NULL | 
|  | && info.bfd_arch_info->mach == bfd_mach_mips3900) | 
|  | reg_names = mips_tx39_reg_names; | 
|  | else | 
|  | reg_names = mips_generic_reg_names; | 
|  | } | 
|  |  | 
|  | /* Check any target description for validity.  */ | 
|  | if (tdesc_has_registers (info.target_desc)) | 
|  | { | 
|  | static const char *const mips_gprs[] = { | 
|  | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 
|  | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 
|  | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | 
|  | "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" | 
|  | }; | 
|  | static const char *const mips_fprs[] = { | 
|  | "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", | 
|  | }; | 
|  |  | 
|  | const struct tdesc_feature *feature; | 
|  | int valid_p; | 
|  |  | 
|  | feature = tdesc_find_feature (info.target_desc, | 
|  | "org.gnu.gdb.mips.cpu"); | 
|  | if (feature == NULL) | 
|  | return NULL; | 
|  |  | 
|  | tdesc_data = tdesc_data_alloc (); | 
|  |  | 
|  | valid_p = 1; | 
|  | for (i = MIPS_ZERO_REGNUM; i <= MIPS_RA_REGNUM; i++) | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i, | 
|  | mips_gprs[i]); | 
|  |  | 
|  |  | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | mips_regnum.lo, "lo"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | mips_regnum.hi, "hi"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | mips_regnum.pc, "pc"); | 
|  |  | 
|  | if (!valid_p) | 
|  | return NULL; | 
|  |  | 
|  | feature = tdesc_find_feature (info.target_desc, | 
|  | "org.gnu.gdb.mips.cp0"); | 
|  | if (feature == NULL) | 
|  | return NULL; | 
|  |  | 
|  | valid_p = 1; | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | mips_regnum.badvaddr, "badvaddr"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | MIPS_PS_REGNUM, "status"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | mips_regnum.cause, "cause"); | 
|  |  | 
|  | if (!valid_p) | 
|  | return NULL; | 
|  |  | 
|  | /* FIXME drow/2007-05-17: The FPU should be optional.  The MIPS | 
|  | backend is not prepared for that, though.  */ | 
|  | feature = tdesc_find_feature (info.target_desc, | 
|  | "org.gnu.gdb.mips.fpu"); | 
|  | if (feature == NULL) | 
|  | return NULL; | 
|  |  | 
|  | valid_p = 1; | 
|  | for (i = 0; i < 32; i++) | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | i + mips_regnum.fp0, mips_fprs[i]); | 
|  |  | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | mips_regnum.fp_control_status, | 
|  | "fcsr"); | 
|  | valid_p | 
|  | &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | mips_regnum.fp_implementation_revision, | 
|  | "fir"); | 
|  |  | 
|  | if (!valid_p) | 
|  | return NULL; | 
|  |  | 
|  | num_regs = mips_regnum.fp_implementation_revision + 1; | 
|  |  | 
|  | if (dspacc >= 0) | 
|  | { | 
|  | feature = tdesc_find_feature (info.target_desc, | 
|  | "org.gnu.gdb.mips.dsp"); | 
|  | /* The DSP registers are optional; it's OK if they are absent.  */ | 
|  | if (feature != NULL) | 
|  | { | 
|  | i = 0; | 
|  | valid_p = 1; | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | dspacc + i++, "hi1"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | dspacc + i++, "lo1"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | dspacc + i++, "hi2"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | dspacc + i++, "lo2"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | dspacc + i++, "hi3"); | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | dspacc + i++, "lo3"); | 
|  |  | 
|  | valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), | 
|  | dspctl, "dspctl"); | 
|  |  | 
|  | if (!valid_p) | 
|  | return NULL; | 
|  |  | 
|  | mips_regnum.dspacc = dspacc; | 
|  | mips_regnum.dspctl = dspctl; | 
|  |  | 
|  | num_regs = mips_regnum.dspctl + 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* It would be nice to detect an attempt to use a 64-bit ABI | 
|  | when only 32-bit registers are provided.  */ | 
|  | reg_names = NULL; | 
|  | } | 
|  |  | 
|  | /* Try to find a pre-existing architecture.  */ | 
|  | for (arches = gdbarch_list_lookup_by_info (arches, &info); | 
|  | arches != NULL; | 
|  | arches = gdbarch_list_lookup_by_info (arches->next, &info)) | 
|  | { | 
|  | mips_gdbarch_tdep *tdep | 
|  | = gdbarch_tdep<mips_gdbarch_tdep> (arches->gdbarch); | 
|  |  | 
|  | /* MIPS needs to be pedantic about which ABI and the compressed | 
|  | ISA variation the object is using.  */ | 
|  | if (tdep->elf_flags != elf_flags) | 
|  | continue; | 
|  | if (tdep->mips_abi != mips_abi) | 
|  | continue; | 
|  | if (tdep->mips_isa != mips_isa) | 
|  | continue; | 
|  | /* Need to be pedantic about which register virtual size is | 
|  | used.  */ | 
|  | if (tdep->mips64_transfers_32bit_regs_p | 
|  | != mips64_transfers_32bit_regs_p) | 
|  | continue; | 
|  | /* Be pedantic about which FPU is selected.  */ | 
|  | if (mips_get_fpu_type (arches->gdbarch) != fpu_type) | 
|  | continue; | 
|  |  | 
|  | return arches->gdbarch; | 
|  | } | 
|  |  | 
|  | /* Need a new architecture.  Fill in a target specific vector.  */ | 
|  | gdbarch *gdbarch | 
|  | = gdbarch_alloc (&info, gdbarch_tdep_up (new mips_gdbarch_tdep)); | 
|  | mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch); | 
|  |  | 
|  | tdep->elf_flags = elf_flags; | 
|  | tdep->mips64_transfers_32bit_regs_p = mips64_transfers_32bit_regs_p; | 
|  | tdep->found_abi = found_abi; | 
|  | tdep->mips_abi = mips_abi; | 
|  | tdep->mips_isa = mips_isa; | 
|  | tdep->mips_fpu_type = fpu_type; | 
|  | tdep->register_size_valid_p = 0; | 
|  | tdep->register_size = 0; | 
|  |  | 
|  | if (info.target_desc) | 
|  | { | 
|  | /* Some useful properties can be inferred from the target.  */ | 
|  | if (tdesc_property (info.target_desc, PROPERTY_GP32) != NULL) | 
|  | { | 
|  | tdep->register_size_valid_p = 1; | 
|  | tdep->register_size = 4; | 
|  | } | 
|  | else if (tdesc_property (info.target_desc, PROPERTY_GP64) != NULL) | 
|  | { | 
|  | tdep->register_size_valid_p = 1; | 
|  | tdep->register_size = 8; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Initially set everything according to the default ABI/ISA.  */ | 
|  | 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_reggroup_p (gdbarch, mips_register_reggroup_p); | 
|  | set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read); | 
|  | set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write); | 
|  |  | 
|  | set_gdbarch_ax_pseudo_register_collect (gdbarch, | 
|  | mips_ax_pseudo_register_collect); | 
|  | set_gdbarch_ax_pseudo_register_push_stack | 
|  | (gdbarch, mips_ax_pseudo_register_push_stack); | 
|  |  | 
|  | set_gdbarch_elf_make_msymbol_special (gdbarch, | 
|  | mips_elf_make_msymbol_special); | 
|  | set_gdbarch_make_symbol_special (gdbarch, mips_make_symbol_special); | 
|  | set_gdbarch_adjust_dwarf2_addr (gdbarch, mips_adjust_dwarf2_addr); | 
|  | set_gdbarch_adjust_dwarf2_line (gdbarch, mips_adjust_dwarf2_line); | 
|  |  | 
|  | regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum); | 
|  | *regnum = mips_regnum; | 
|  | set_gdbarch_fp0_regnum (gdbarch, regnum->fp0); | 
|  | set_gdbarch_num_regs (gdbarch, num_regs); | 
|  | set_gdbarch_num_pseudo_regs (gdbarch, num_regs); | 
|  | set_gdbarch_register_name (gdbarch, mips_register_name); | 
|  | set_gdbarch_virtual_frame_pointer (gdbarch, mips_virtual_frame_pointer); | 
|  | tdep->mips_processor_reg_names = reg_names; | 
|  | tdep->regnum = regnum; | 
|  |  | 
|  | switch (mips_abi) | 
|  | { | 
|  | case MIPS_ABI_O32: | 
|  | set_gdbarch_push_dummy_call (gdbarch, mips_o32_push_dummy_call); | 
|  | set_gdbarch_return_value (gdbarch, mips_o32_return_value); | 
|  | tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 4 - 1; | 
|  | tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 4 - 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_O64: | 
|  | set_gdbarch_push_dummy_call (gdbarch, mips_o64_push_dummy_call); | 
|  | set_gdbarch_return_value (gdbarch, mips_o64_return_value); | 
|  | tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 4 - 1; | 
|  | tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 4 - 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: | 
|  | set_gdbarch_push_dummy_call (gdbarch, mips_eabi_push_dummy_call); | 
|  | set_gdbarch_return_value (gdbarch, mips_eabi_return_value); | 
|  | tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1; | 
|  | tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 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_EABI64: | 
|  | set_gdbarch_push_dummy_call (gdbarch, mips_eabi_push_dummy_call); | 
|  | set_gdbarch_return_value (gdbarch, mips_eabi_return_value); | 
|  | tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1; | 
|  | tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 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: | 
|  | set_gdbarch_push_dummy_call (gdbarch, mips_n32n64_push_dummy_call); | 
|  | set_gdbarch_return_value (gdbarch, mips_n32n64_return_value); | 
|  | tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1; | 
|  | tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 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); | 
|  | set_gdbarch_long_double_bit (gdbarch, 128); | 
|  | set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double); | 
|  | break; | 
|  | case MIPS_ABI_N64: | 
|  | set_gdbarch_push_dummy_call (gdbarch, mips_n32n64_push_dummy_call); | 
|  | set_gdbarch_return_value (gdbarch, mips_n32n64_return_value); | 
|  | tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1; | 
|  | tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 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); | 
|  | set_gdbarch_long_double_bit (gdbarch, 128); | 
|  | set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double); | 
|  | break; | 
|  | default: | 
|  | internal_error (_("unknown ABI in switch")); | 
|  | } | 
|  |  | 
|  | /* GCC creates a pseudo-section whose name specifies the size of | 
|  | longs, since -mlong32 or -mlong64 may be used independent of | 
|  | other options.  How those options affect pointer sizes is ABI and | 
|  | architecture dependent, so use them to override the default sizes | 
|  | set by the ABI.  This table shows the relationship between ABI, | 
|  | -mlongXX, and size of pointers: | 
|  |  | 
|  | ABI		-mlongXX	ptr bits | 
|  | ---		--------	-------- | 
|  | o32		32		32 | 
|  | o32		64		32 | 
|  | n32		32		32 | 
|  | n32		64		64 | 
|  | o64		32		32 | 
|  | o64		64		64 | 
|  | n64		32		32 | 
|  | n64		64		64 | 
|  | eabi32		32		32 | 
|  | eabi32		64		32 | 
|  | eabi64		32		32 | 
|  | eabi64		64		64 | 
|  |  | 
|  | Note that for o32 and eabi32, pointers are always 32 bits | 
|  | regardless of any -mlongXX option.  For all others, pointers and | 
|  | longs are the same, as set by -mlongXX or set by defaults.  */ | 
|  |  | 
|  | if (info.abfd != NULL) | 
|  | { | 
|  | int long_bit = 0; | 
|  |  | 
|  | bfd_map_over_sections (info.abfd, mips_find_long_section, &long_bit); | 
|  | if (long_bit) | 
|  | { | 
|  | set_gdbarch_long_bit (gdbarch, long_bit); | 
|  | switch (mips_abi) | 
|  | { | 
|  | case MIPS_ABI_O32: | 
|  | case MIPS_ABI_EABI32: | 
|  | break; | 
|  | case MIPS_ABI_N32: | 
|  | case MIPS_ABI_O64: | 
|  | case MIPS_ABI_N64: | 
|  | case MIPS_ABI_EABI64: | 
|  | set_gdbarch_ptr_bit (gdbarch, long_bit); | 
|  | break; | 
|  | default: | 
|  | internal_error (_("unknown ABI in switch")); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* FIXME: jlarmour/2000-04-07: There *is* a flag EF_MIPS_32BIT_MODE | 
|  | that could indicate -gp32 BUT gas/config/tc-mips.c contains the | 
|  | comment: | 
|  |  | 
|  | ``We deliberately don't allow "-gp32" to set the MIPS_32BITMODE | 
|  | flag in object files because to do so would make it impossible to | 
|  | link with libraries compiled without "-gp32".  This is | 
|  | unnecessarily restrictive. | 
|  |  | 
|  | We could solve this problem by adding "-gp32" multilibs to gcc, | 
|  | but to set this flag before gcc is built with such multilibs will | 
|  | break too many systems.'' | 
|  |  | 
|  | But even more unhelpfully, the default linker output target for | 
|  | mips64-elf is elf32-bigmips, and has EF_MIPS_32BIT_MODE set, even | 
|  | for 64-bit programs - you need to change the ABI to change this, | 
|  | and not all gcc targets support that currently.  Therefore using | 
|  | this flag to detect 32-bit mode would do the wrong thing given | 
|  | the current gcc - it would make GDB treat these 64-bit programs | 
|  | as 32-bit programs by default.  */ | 
|  |  | 
|  | set_gdbarch_read_pc (gdbarch, mips_read_pc); | 
|  | set_gdbarch_write_pc (gdbarch, mips_write_pc); | 
|  |  | 
|  | /* Add/remove bits from an address.  The MIPS needs be careful to | 
|  | ensure that all 32 bit addresses are sign extended to 64 bits.  */ | 
|  | set_gdbarch_addr_bits_remove (gdbarch, mips_addr_bits_remove); | 
|  |  | 
|  | /* Unwind the frame.  */ | 
|  | set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc); | 
|  | set_gdbarch_unwind_sp (gdbarch, mips_unwind_sp); | 
|  | set_gdbarch_dummy_id (gdbarch, mips_dummy_id); | 
|  |  | 
|  | /* Map debug register numbers onto internal register numbers.  */ | 
|  | set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum); | 
|  | set_gdbarch_ecoff_reg_to_regnum (gdbarch, | 
|  | mips_dwarf_dwarf2_ecoff_reg_to_regnum); | 
|  | set_gdbarch_dwarf2_reg_to_regnum (gdbarch, | 
|  | mips_dwarf_dwarf2_ecoff_reg_to_regnum); | 
|  | set_gdbarch_register_sim_regno (gdbarch, mips_register_sim_regno); | 
|  |  | 
|  | /* MIPS version of CALL_DUMMY.  */ | 
|  |  | 
|  | set_gdbarch_call_dummy_location (gdbarch, ON_STACK); | 
|  | set_gdbarch_push_dummy_code (gdbarch, mips_push_dummy_code); | 
|  | set_gdbarch_frame_align (gdbarch, mips_frame_align); | 
|  |  | 
|  | set_gdbarch_print_float_info (gdbarch, mips_print_float_info); | 
|  |  | 
|  | set_gdbarch_convert_register_p (gdbarch, mips_convert_register_p); | 
|  | set_gdbarch_register_to_value (gdbarch, mips_register_to_value); | 
|  | set_gdbarch_value_to_register (gdbarch, mips_value_to_register); | 
|  |  | 
|  | set_gdbarch_inner_than (gdbarch, core_addr_lessthan); | 
|  | set_gdbarch_breakpoint_kind_from_pc (gdbarch, mips_breakpoint_kind_from_pc); | 
|  | set_gdbarch_sw_breakpoint_from_kind (gdbarch, mips_sw_breakpoint_from_kind); | 
|  | set_gdbarch_adjust_breakpoint_address (gdbarch, | 
|  | mips_adjust_breakpoint_address); | 
|  |  | 
|  | set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue); | 
|  |  | 
|  | set_gdbarch_stack_frame_destroyed_p (gdbarch, mips_stack_frame_destroyed_p); | 
|  |  | 
|  | 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); | 
|  |  | 
|  | set_gdbarch_register_type (gdbarch, mips_register_type); | 
|  |  | 
|  | set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info); | 
|  |  | 
|  | set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips); | 
|  | if (mips_abi == MIPS_ABI_N64) | 
|  | set_gdbarch_disassembler_options_implicit | 
|  | (gdbarch, (const char *) mips_disassembler_options_n64); | 
|  | else if (mips_abi == MIPS_ABI_N32) | 
|  | set_gdbarch_disassembler_options_implicit | 
|  | (gdbarch, (const char *) mips_disassembler_options_n32); | 
|  | else | 
|  | set_gdbarch_disassembler_options_implicit | 
|  | (gdbarch, (const char *) mips_disassembler_options_o32); | 
|  | set_gdbarch_disassembler_options (gdbarch, &mips_disassembler_options); | 
|  | set_gdbarch_valid_disassembler_options (gdbarch, | 
|  | disassembler_options_mips ()); | 
|  |  | 
|  | /* FIXME: cagney/2003-08-29: The macros target_have_steppable_watchpoint, | 
|  | HAVE_NONSTEPPABLE_WATCHPOINT, and target_have_continuable_watchpoint | 
|  | need to all be folded into the target vector.  Since they are | 
|  | being used as guards for target_stopped_by_watchpoint, why not have | 
|  | target_stopped_by_watchpoint return the type of watchpoint that the code | 
|  | is sitting on?  */ | 
|  | set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); | 
|  |  | 
|  | set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_trampoline_code); | 
|  |  | 
|  | /* NOTE drow/2012-04-25: We overload the core solib trampoline code | 
|  | to support MIPS16.  This is a bad thing.  Make sure not to do it | 
|  | if we have an OS ABI that actually supports shared libraries, since | 
|  | shared library support is more important.  If we have an OS someday | 
|  | that supports both shared libraries and MIPS16, we'll have to find | 
|  | a better place for these. | 
|  | macro/2012-04-25: But that applies to return trampolines only and | 
|  | currently no MIPS OS ABI uses shared libraries that have them.  */ | 
|  | set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub); | 
|  |  | 
|  | set_gdbarch_single_step_through_delay (gdbarch, | 
|  | mips_single_step_through_delay); | 
|  |  | 
|  | /* Virtual tables.  */ | 
|  | set_gdbarch_vbit_in_delta (gdbarch, 1); | 
|  |  | 
|  | mips_register_g_packet_guesses (gdbarch); | 
|  |  | 
|  | /* Hook in OS ABI-specific overrides, if they have been registered.  */ | 
|  | info.tdesc_data = tdesc_data.get (); | 
|  | gdbarch_init_osabi (info, gdbarch); | 
|  |  | 
|  | /* The hook may have adjusted num_regs, fetch the final value and | 
|  | set pc_regnum and sp_regnum now that it has been fixed.  */ | 
|  | num_regs = gdbarch_num_regs (gdbarch); | 
|  | set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs); | 
|  | set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs); | 
|  |  | 
|  | /* Unwind the frame.  */ | 
|  | dwarf2_append_unwinders (gdbarch); | 
|  | frame_unwind_append_unwinder (gdbarch, &mips_stub_frame_unwind); | 
|  | frame_unwind_append_unwinder (gdbarch, &mips_insn16_frame_unwind); | 
|  | frame_unwind_append_unwinder (gdbarch, &mips_micro_frame_unwind); | 
|  | frame_unwind_append_unwinder (gdbarch, &mips_insn32_frame_unwind); | 
|  | frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer); | 
|  | frame_base_append_sniffer (gdbarch, mips_stub_frame_base_sniffer); | 
|  | frame_base_append_sniffer (gdbarch, mips_insn16_frame_base_sniffer); | 
|  | frame_base_append_sniffer (gdbarch, mips_micro_frame_base_sniffer); | 
|  | frame_base_append_sniffer (gdbarch, mips_insn32_frame_base_sniffer); | 
|  |  | 
|  | if (tdesc_data != nullptr) | 
|  | { | 
|  | set_tdesc_pseudo_register_type (gdbarch, mips_pseudo_register_type); | 
|  | tdesc_use_registers (gdbarch, info.target_desc, std::move (tdesc_data)); | 
|  |  | 
|  | /* Override the normal target description methods to handle our | 
|  | dual real and pseudo registers.  */ | 
|  | set_gdbarch_register_name (gdbarch, mips_register_name); | 
|  | set_gdbarch_register_reggroup_p (gdbarch, | 
|  | mips_tdesc_register_reggroup_p); | 
|  |  | 
|  | num_regs = gdbarch_num_regs (gdbarch); | 
|  | set_gdbarch_num_pseudo_regs (gdbarch, num_regs); | 
|  | set_gdbarch_pc_regnum (gdbarch, tdep->regnum->pc + num_regs); | 
|  | set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs); | 
|  | } | 
|  |  | 
|  | /* Add ABI-specific aliases for the registers.  */ | 
|  | if (mips_abi == MIPS_ABI_N32 || mips_abi == MIPS_ABI_N64) | 
|  | for (i = 0; i < ARRAY_SIZE (mips_n32_n64_aliases); i++) | 
|  | user_reg_add (gdbarch, mips_n32_n64_aliases[i].name, | 
|  | value_of_mips_user_reg, &mips_n32_n64_aliases[i].regnum); | 
|  | else | 
|  | for (i = 0; i < ARRAY_SIZE (mips_o32_aliases); i++) | 
|  | user_reg_add (gdbarch, mips_o32_aliases[i].name, | 
|  | value_of_mips_user_reg, &mips_o32_aliases[i].regnum); | 
|  |  | 
|  | /* Add some other standard aliases.  */ | 
|  | for (i = 0; i < ARRAY_SIZE (mips_register_aliases); i++) | 
|  | user_reg_add (gdbarch, mips_register_aliases[i].name, | 
|  | value_of_mips_user_reg, &mips_register_aliases[i].regnum); | 
|  |  | 
|  | for (i = 0; i < ARRAY_SIZE (mips_numeric_register_aliases); i++) | 
|  | user_reg_add (gdbarch, mips_numeric_register_aliases[i].name, | 
|  | value_of_mips_user_reg, | 
|  | &mips_numeric_register_aliases[i].regnum); | 
|  |  | 
|  | return gdbarch; | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_abi_update (const char *ignore_args, | 
|  | int from_tty, struct cmd_list_element *c) | 
|  | { | 
|  | struct gdbarch_info info; | 
|  |  | 
|  | /* Force the architecture to update, and (if it's a MIPS architecture) | 
|  | mips_gdbarch_init will take care of the rest.  */ | 
|  | gdbarch_update_p (info); | 
|  | } | 
|  |  | 
|  | /* Print out which MIPS ABI is in use.  */ | 
|  |  | 
|  | static void | 
|  | show_mips_abi (struct ui_file *file, | 
|  | int from_tty, | 
|  | struct cmd_list_element *ignored_cmd, | 
|  | const char *ignored_value) | 
|  | { | 
|  | if (gdbarch_bfd_arch_info (current_inferior ()->arch  ())->arch | 
|  | != bfd_arch_mips) | 
|  | gdb_printf | 
|  | (file, | 
|  | "The MIPS ABI is unknown because the current architecture " | 
|  | "is not MIPS.\n"); | 
|  | else | 
|  | { | 
|  | enum mips_abi global_abi = global_mips_abi (); | 
|  | enum mips_abi actual_abi = mips_abi (current_inferior ()->arch ()); | 
|  | const char *actual_abi_str = mips_abi_strings[actual_abi]; | 
|  |  | 
|  | if (global_abi == MIPS_ABI_UNKNOWN) | 
|  | gdb_printf | 
|  | (file, | 
|  | "The MIPS ABI is set automatically (currently \"%s\").\n", | 
|  | actual_abi_str); | 
|  | else if (global_abi == actual_abi) | 
|  | gdb_printf | 
|  | (file, | 
|  | "The MIPS ABI is assumed to be \"%s\" (due to user setting).\n", | 
|  | actual_abi_str); | 
|  | else | 
|  | { | 
|  | /* Probably shouldn't happen...  */ | 
|  | gdb_printf (file, | 
|  | "The (auto detected) MIPS ABI \"%s\" is in use " | 
|  | "even though the user setting was \"%s\".\n", | 
|  | actual_abi_str, mips_abi_strings[global_abi]); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Print out which MIPS compressed ISA encoding is used.  */ | 
|  |  | 
|  | static void | 
|  | show_mips_compression (struct ui_file *file, int from_tty, | 
|  | struct cmd_list_element *c, const char *value) | 
|  | { | 
|  | gdb_printf (file, _("The compressed ISA encoding used is %s.\n"), | 
|  | value); | 
|  | } | 
|  |  | 
|  | /* Return a textual name for MIPS FPU type FPU_TYPE.  */ | 
|  |  | 
|  | static const char * | 
|  | mips_fpu_type_str (enum mips_fpu_type fpu_type) | 
|  | { | 
|  | switch (fpu_type) | 
|  | { | 
|  | case MIPS_FPU_NONE: | 
|  | return "none"; | 
|  | case MIPS_FPU_SINGLE: | 
|  | return "single"; | 
|  | case MIPS_FPU_DOUBLE: | 
|  | return "double"; | 
|  | default: | 
|  | return "???"; | 
|  | } | 
|  | } | 
|  |  | 
|  | static void | 
|  | mips_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file) | 
|  | { | 
|  | mips_gdbarch_tdep *tdep = gdbarch_tdep<mips_gdbarch_tdep> (gdbarch); | 
|  | if (tdep != NULL) | 
|  | { | 
|  | int ef_mips_arch; | 
|  | int ef_mips_32bitmode; | 
|  | /* Determine the ISA.  */ | 
|  | switch (tdep->elf_flags & EF_MIPS_ARCH) | 
|  | { | 
|  | case EF_MIPS_ARCH_1: | 
|  | ef_mips_arch = 1; | 
|  | break; | 
|  | case EF_MIPS_ARCH_2: | 
|  | ef_mips_arch = 2; | 
|  | break; | 
|  | case EF_MIPS_ARCH_3: | 
|  | ef_mips_arch = 3; | 
|  | break; | 
|  | case EF_MIPS_ARCH_4: | 
|  | ef_mips_arch = 4; | 
|  | break; | 
|  | default: | 
|  | ef_mips_arch = 0; | 
|  | break; | 
|  | } | 
|  | /* Determine the size of a pointer.  */ | 
|  | ef_mips_32bitmode = (tdep->elf_flags & EF_MIPS_32BITMODE); | 
|  | gdb_printf (file, | 
|  | "mips_dump_tdep: tdep->elf_flags = 0x%x\n", | 
|  | tdep->elf_flags); | 
|  | gdb_printf (file, | 
|  | "mips_dump_tdep: ef_mips_32bitmode = %d\n", | 
|  | ef_mips_32bitmode); | 
|  | gdb_printf (file, | 
|  | "mips_dump_tdep: ef_mips_arch = %d\n", | 
|  | ef_mips_arch); | 
|  | gdb_printf (file, | 
|  | "mips_dump_tdep: tdep->mips_abi = %d (%s)\n", | 
|  | tdep->mips_abi, mips_abi_strings[tdep->mips_abi]); | 
|  | gdb_printf (file, | 
|  | "mips_dump_tdep: " | 
|  | "mips_mask_address_p() %d (default %d)\n", | 
|  | mips_mask_address_p (tdep), | 
|  | tdep->default_mask_address_p); | 
|  | } | 
|  | gdb_printf (file, | 
|  | "mips_dump_tdep: MIPS_DEFAULT_FPU_TYPE = %d (%s)\n", | 
|  | MIPS_DEFAULT_FPU_TYPE, | 
|  | mips_fpu_type_str (MIPS_DEFAULT_FPU_TYPE)); | 
|  | gdb_printf (file, "mips_dump_tdep: MIPS_EABI = %d\n", | 
|  | mips_eabi (gdbarch)); | 
|  | gdb_printf (file, | 
|  | "mips_dump_tdep: MIPS_FPU_TYPE = %d (%s)\n", | 
|  | mips_get_fpu_type (gdbarch), | 
|  | mips_fpu_type_str (mips_get_fpu_type (gdbarch))); | 
|  | } | 
|  |  | 
|  | void _initialize_mips_tdep (); | 
|  | void | 
|  | _initialize_mips_tdep () | 
|  | { | 
|  | static struct cmd_list_element *mipsfpulist = NULL; | 
|  |  | 
|  | mips_abi_string = mips_abi_strings[MIPS_ABI_UNKNOWN]; | 
|  | if (MIPS_ABI_LAST + 1 | 
|  | != sizeof (mips_abi_strings) / sizeof (mips_abi_strings[0])) | 
|  | internal_error (_("mips_abi_strings out of sync")); | 
|  |  | 
|  | gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep); | 
|  |  | 
|  | /* Create feature sets with the appropriate properties.  The values | 
|  | are not important.  */ | 
|  | mips_tdesc_gp32 = allocate_target_description ().release (); | 
|  | set_tdesc_property (mips_tdesc_gp32, PROPERTY_GP32, ""); | 
|  |  | 
|  | mips_tdesc_gp64 = allocate_target_description ().release (); | 
|  | set_tdesc_property (mips_tdesc_gp64, PROPERTY_GP64, ""); | 
|  |  | 
|  | /* Add root prefix command for all "set mips"/"show mips" commands.  */ | 
|  | add_setshow_prefix_cmd ("mips", no_class, | 
|  | _("Various MIPS specific commands."), | 
|  | _("Various MIPS specific commands."), | 
|  | &setmipscmdlist, &showmipscmdlist, | 
|  | &setlist, &showlist); | 
|  |  | 
|  | /* Allow the user to override the ABI.  */ | 
|  | add_setshow_enum_cmd ("abi", class_obscure, mips_abi_strings, | 
|  | &mips_abi_string, _("\ | 
|  | Set the MIPS ABI used by this program."), _("\ | 
|  | Show the MIPS ABI used by this program."), _("\ | 
|  | This option can be set to one of:\n\ | 
|  | auto  - the default ABI associated with the current binary\n\ | 
|  | o32\n\ | 
|  | o64\n\ | 
|  | n32\n\ | 
|  | n64\n\ | 
|  | eabi32\n\ | 
|  | eabi64"), | 
|  | mips_abi_update, | 
|  | show_mips_abi, | 
|  | &setmipscmdlist, &showmipscmdlist); | 
|  |  | 
|  | /* Allow the user to set the ISA to assume for compressed code if ELF | 
|  | file flags don't tell or there is no program file selected.  This | 
|  | setting is updated whenever unambiguous ELF file flags are interpreted, | 
|  | and carried over to subsequent sessions.  */ | 
|  | add_setshow_enum_cmd ("compression", class_obscure, mips_compression_strings, | 
|  | &mips_compression_string, _("\ | 
|  | Set the compressed ISA encoding used by MIPS code."), _("\ | 
|  | Show the compressed ISA encoding used by MIPS code."), _("\ | 
|  | Select the compressed ISA encoding used in functions that have no symbol\n\ | 
|  | information available.  The encoding can be set to either of:\n\ | 
|  | mips16\n\ | 
|  | micromips\n\ | 
|  | and is updated automatically from ELF file flags if available."), | 
|  | mips_abi_update, | 
|  | show_mips_compression, | 
|  | &setmipscmdlist, &showmipscmdlist); | 
|  |  | 
|  | /* Let the user turn off floating point and set the fence post for | 
|  | heuristic_proc_start.  */ | 
|  |  | 
|  | add_basic_prefix_cmd ("mipsfpu", class_support, | 
|  | _("Set use of MIPS floating-point coprocessor."), | 
|  | &mipsfpulist, 0, &setlist); | 
|  | add_cmd ("single", class_support, set_mipsfpu_single_command, | 
|  | _("Select single-precision MIPS floating-point coprocessor."), | 
|  | &mipsfpulist); | 
|  | cmd_list_element *set_mipsfpu_double_cmd | 
|  | = add_cmd ("double", class_support, set_mipsfpu_double_command, | 
|  | _("Select double-precision MIPS floating-point coprocessor."), | 
|  | &mipsfpulist); | 
|  | add_alias_cmd ("on", set_mipsfpu_double_cmd, class_support, 1, &mipsfpulist); | 
|  | add_alias_cmd ("yes", set_mipsfpu_double_cmd, class_support, 1, &mipsfpulist); | 
|  | add_alias_cmd ("1", set_mipsfpu_double_cmd, class_support, 1, &mipsfpulist); | 
|  |  | 
|  | cmd_list_element *set_mipsfpu_none_cmd | 
|  | = add_cmd ("none", class_support, set_mipsfpu_none_command, | 
|  | _("Select no MIPS floating-point coprocessor."), &mipsfpulist); | 
|  | add_alias_cmd ("off", set_mipsfpu_none_cmd, class_support, 1, &mipsfpulist); | 
|  | add_alias_cmd ("no", set_mipsfpu_none_cmd, class_support, 1, &mipsfpulist); | 
|  | add_alias_cmd ("0", set_mipsfpu_none_cmd, 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); | 
|  |  | 
|  | /* We really would like to have both "0" and "unlimited" work, but | 
|  | command.c doesn't deal with that.  So make it a var_zinteger | 
|  | because the user can always use "999999" or some such for unlimited.  */ | 
|  | add_setshow_zinteger_cmd ("heuristic-fence-post", class_support, | 
|  | &heuristic_fence_post, _("\ | 
|  | Set the distance searched for the start of a function."), _("\ | 
|  | Show the distance searched for the start of a function."), _("\ | 
|  | 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."), | 
|  | reinit_frame_cache_sfunc, | 
|  | NULL, /* FIXME: i18n: The distance searched for | 
|  | the start of a function is %s.  */ | 
|  | &setlist, &showlist); | 
|  |  | 
|  | /* Allow the user to control whether the upper bits of 64-bit | 
|  | addresses should be zeroed.  */ | 
|  | add_setshow_auto_boolean_cmd ("mask-address", no_class, | 
|  | &mask_address_var, _("\ | 
|  | Set zeroing of upper 32 bits of 64-bit addresses."), _("\ | 
|  | Show zeroing of upper 32 bits of 64-bit addresses."), _("\ | 
|  | Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to\n\ | 
|  | allow GDB to determine the correct value."), | 
|  | NULL, show_mask_address, | 
|  | &setmipscmdlist, &showmipscmdlist); | 
|  |  | 
|  | /* Allow the user to control the size of 32 bit registers within the | 
|  | raw remote packet.  */ | 
|  | add_setshow_boolean_cmd ("remote-mips64-transfers-32bit-regs", class_obscure, | 
|  | &mips64_transfers_32bit_regs_p, _("\ | 
|  | Set compatibility with 64-bit MIPS target that transfers 32-bit quantities."), | 
|  | _("\ | 
|  | Show compatibility with 64-bit MIPS target that transfers 32-bit quantities."), | 
|  | _("\ | 
|  | 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"), | 
|  | set_mips64_transfers_32bit_regs, | 
|  | NULL, /* FIXME: i18n: Compatibility with 64-bit | 
|  | MIPS target that transfers 32-bit | 
|  | quantities is %s.  */ | 
|  | &setlist, &showlist); | 
|  |  | 
|  | /* Debug this files internals.  */ | 
|  | add_setshow_zuinteger_cmd ("mips", class_maintenance, | 
|  | &mips_debug, _("\ | 
|  | Set mips debugging."), _("\ | 
|  | Show mips debugging."), _("\ | 
|  | When non-zero, mips specific debugging is enabled."), | 
|  | NULL, | 
|  | NULL, /* FIXME: i18n: Mips debugging is | 
|  | currently %s.  */ | 
|  | &setdebuglist, &showdebuglist); | 
|  | } |