+static void
+set_mipsfpu_none_command (char *args, int from_tty)
+{
+ struct gdbarch_info info;
+ gdbarch_info_init (&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 (__FILE__, __LINE__, _("set mipsfpu failed"));
+}
+
+static void
+set_mipsfpu_auto_command (char *args, int from_tty)
+{
+ mips_fpu_type_auto = 1;
+}
+
+/* Attempt to identify the particular processor model by reading the
+ processor id. NOTE: cagney/2003-11-15: Firstly it isn't clear that
+ the relevant processor still exists (it dates back to '94) and
+ secondly this is not the way to do this. The processor type should
+ be set by forcing an architecture change. */
+
+void
+deprecated_mips_set_processor_regs_hack (void)
+{
+ struct regcache *regcache = get_current_regcache ();
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ULONGEST prid;
+
+ regcache_cooked_read_unsigned (regcache, MIPS_PRID_REGNUM, &prid);
+ if ((prid & ~0xf) == 0x700)
+ tdep->mips_processor_reg_names = mips_r3041_reg_names;
+}
+
+/* Just like reinit_frame_cache, but with the right arguments to be
+ callable as an sfunc. */
+
+static void
+reinit_frame_cache_sfunc (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)
+{
+ struct gdbarch *gdbarch = info->application_data;
+
+ /* 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;
+
+ /* Set the disassembler options. */
+ if (!info->disassembler_options)
+ /* This string is not recognized explicitly by the disassembler,
+ but it tells the disassembler to not try to guess the ABI from
+ the bfd elf headers, such that, if the user overrides the ABI
+ of a program linked as NewABI, the disassembly will follow the
+ register naming conventions specified by the user. */
+ info->disassembler_options = "gpr-names=32";
+
+ /* Call the appropriate disassembler based on the target endian-ness. */
+ if (info->endian == BFD_ENDIAN_BIG)
+ return print_insn_big_mips (memaddr, info);
+ else
+ return print_insn_little_mips (memaddr, info);
+}
+
+static int
+gdb_print_insn_mips_n32 (bfd_vma memaddr, struct disassemble_info *info)
+{
+ /* Set up the disassembler info, so that we get the right
+ register names from libopcodes. */
+ info->disassembler_options = "gpr-names=n32";
+ info->flavour = bfd_target_elf_flavour;
+
+ return gdb_print_insn_mips (memaddr, info);
+}
+
+static int
+gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info)
+{
+ /* Set up the disassembler info, so that we get the right
+ register names from libopcodes. */
+ info->disassembler_options = "gpr-names=64";
+ info->flavour = bfd_target_elf_flavour;
+
+ return gdb_print_insn_mips (memaddr, info);
+}
+
+/* This function implements gdbarch_breakpoint_from_pc. It uses the
+ program counter value to determine whether a 16- or 32-bit breakpoint
+ should be used. It returns a pointer to a string of bytes that encode a
+ breakpoint instruction, stores the length of the string to *lenptr, and
+ adjusts pc (if necessary) to point to the actual memory location where
+ the breakpoint should be inserted. */
+
+static const gdb_byte *
+mips_breakpoint_from_pc (struct gdbarch *gdbarch,
+ CORE_ADDR *pcptr, int *lenptr)
+{
+ CORE_ADDR pc = *pcptr;
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ if (mips_pc_is_mips16 (gdbarch, pc))
+ {
+ static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
+ *pcptr = unmake_compact_addr (pc);
+ *lenptr = sizeof (mips16_big_breakpoint);
+ return mips16_big_breakpoint;
+ }
+ else if (mips_pc_is_micromips (gdbarch, pc))
+ {
+ static gdb_byte micromips16_big_breakpoint[] = { 0x46, 0x85 };
+ static gdb_byte micromips32_big_breakpoint[] = { 0, 0x5, 0, 0x7 };
+ ULONGEST insn;
+ int status;
+ int size;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
+ size = status ? 2
+ : mips_insn_size (ISA_MICROMIPS, insn) == 2 ? 2 : 4;
+ *pcptr = unmake_compact_addr (pc);
+ *lenptr = size;
+ return (size == 2) ? micromips16_big_breakpoint
+ : micromips32_big_breakpoint;
+ }
+ else
+ {
+ /* The IDT board uses an unusual breakpoint value, and
+ sometimes gets confused when it sees the usual MIPS
+ breakpoint instruction. */
+ static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
+ static gdb_byte pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
+ static gdb_byte idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
+ /* Likewise, IRIX appears to expect a different breakpoint,
+ although this is not apparent until you try to use pthreads. */
+ static gdb_byte irix_big_breakpoint[] = { 0, 0, 0, 0xd };
+
+ *lenptr = sizeof (big_breakpoint);
+
+ if (strcmp (target_shortname, "mips") == 0)
+ return idt_big_breakpoint;
+ else if (strcmp (target_shortname, "ddb") == 0
+ || strcmp (target_shortname, "pmon") == 0
+ || strcmp (target_shortname, "lsi") == 0)
+ return pmon_big_breakpoint;
+ else if (gdbarch_osabi (gdbarch) == GDB_OSABI_IRIX)
+ return irix_big_breakpoint;
+ else
+ return big_breakpoint;
+ }
+ }
+ else
+ {
+ if (mips_pc_is_mips16 (gdbarch, pc))
+ {
+ static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 };
+ *pcptr = unmake_compact_addr (pc);
+ *lenptr = sizeof (mips16_little_breakpoint);
+ return mips16_little_breakpoint;
+ }
+ else if (mips_pc_is_micromips (gdbarch, pc))
+ {
+ static gdb_byte micromips16_little_breakpoint[] = { 0x85, 0x46 };
+ static gdb_byte micromips32_little_breakpoint[] = { 0x5, 0, 0x7, 0 };
+ ULONGEST insn;
+ int status;
+ int size;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
+ size = status ? 2
+ : mips_insn_size (ISA_MICROMIPS, insn) == 2 ? 2 : 4;
+ *pcptr = unmake_compact_addr (pc);
+ *lenptr = size;
+ return (size == 2) ? micromips16_little_breakpoint
+ : micromips32_little_breakpoint;
+ }
+ else
+ {
+ static gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
+ static gdb_byte pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
+ static gdb_byte idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
+
+ *lenptr = sizeof (little_breakpoint);
+
+ if (strcmp (target_shortname, "mips") == 0)
+ return idt_little_breakpoint;
+ else if (strcmp (target_shortname, "ddb") == 0
+ || strcmp (target_shortname, "pmon") == 0
+ || strcmp (target_shortname, "lsi") == 0)
+ return pmon_little_breakpoint;
+ else
+ return little_breakpoint;
+ }
+ }
+}
+
+/* Determine the remote breakpoint kind suitable for the PC. The following
+ kinds are used:
+
+ * 2 -- 16-bit MIPS16 mode breakpoint,
+
+ * 3 -- 16-bit microMIPS mode breakpoint,
+
+ * 4 -- 32-bit standard MIPS mode breakpoint,
+
+ * 5 -- 32-bit microMIPS mode breakpoint. */
+
+static void
+mips_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
+ int *kindptr)
+{
+ CORE_ADDR pc = *pcptr;
+
+ if (mips_pc_is_mips16 (gdbarch, pc))
+ {
+ *pcptr = unmake_compact_addr (pc);
+ *kindptr = 2;
+ }
+ else if (mips_pc_is_micromips (gdbarch, pc))
+ {
+ ULONGEST insn;
+ int status;
+ int size;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, &status);
+ size = status ? 2 : mips_insn_size (ISA_MICROMIPS, insn) == 2 ? 2 : 4;
+ *pcptr = unmake_compact_addr (pc);
+ *kindptr = size | 1;
+ }
+ else
+ *kindptr = 4;
+}
+
+/* Return non-zero if the ADDR instruction 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, CORE_ADDR addr)
+{
+ unsigned long inst;
+ int status;
+ int op;
+ int rs;
+ int rt;
+
+ inst = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
+ if (status)
+ return 0;
+
+ op = itype_op (inst);
+ if ((inst & 0xe0000000) != 0)
+ {
+ rs = itype_rs (inst);
+ rt = itype_rt (inst);
+ return (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 the ADDR instruction, 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). */
+
+static int
+micromips_instruction_has_delay_slot (struct gdbarch *gdbarch,
+ CORE_ADDR addr, int mustbe32)
+{
+ ULONGEST insn;
+ int status;
+
+ insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
+ if (status)
+ return 0;
+
+ if (!mustbe32) /* 16-bit instructions. */
+ return (micromips_op (insn) == 0x11
+ /* POOL16C: bits 010001 */
+ && (b5s5_op (insn) == 0xc
+ /* JR16: bits 010001 01100 */
+ || (b5s5_op (insn) & 0x1e) == 0xe))
+ /* JALR16, JALRS16: bits 010001 0111x */
+ || (micromips_op (insn) & 0x37) == 0x23
+ /* BEQZ16, BNEZ16: bits 10x011 */
+ || micromips_op (insn) == 0x33;
+ /* B16: bits 110011 */
+
+ /* 32-bit instructions. */
+ if (micromips_op (insn) == 0x0)
+ /* POOL32A: bits 000000 */
+ {
+ insn <<= 16;
+ insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, addr, &status);
+ if (status)
+ return 0;
+ 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 */
+ }
+
+ return (micromips_op (insn) == 0x10
+ /* POOL32I: bits 010000 */
+ && ((b5s5_op (insn) & 0x1c) == 0x0
+ /* BLTZ, BLTZAL, BGEZ, BGEZAL: 010000 000xx */
+ || (b5s5_op (insn) & 0x1d) == 0x4
+ /* BLEZ, BGTZ: bits 010000 001x0 */
+ || (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 */
+ || (micromips_op (insn) & 0x1f) == 0x1d
+ /* JALS, JAL: bits x11101 */
+ || (micromips_op (insn) & 0x37) == 0x25
+ /* BEQ, BNE: bits 10x101 */
+ || micromips_op (insn) == 0x35
+ /* J: bits 110101 */
+ || micromips_op (insn) == 0x3c;
+ /* JALX: bits 111100 */
+}
+
+static int
+mips16_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr,
+ int mustbe32)
+{
+ unsigned short inst;
+ int status;
+
+ inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status);
+ if (status)
+ return 0;
+
+ if (!mustbe32)
+ return (inst & 0xf89f) == 0xe800; /* JR/JALR (16-bit instruction) */
+ return (inst & 0xf800) == 0x1800; /* JAL/JALX (32-bit instruction) */
+}
+
+/* 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_instruction_has_delay_slot (gdbarch, prev_addr))
+ bpaddr = prev_addr;
+ }
+ else
+ {
+ int (*instruction_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. */
+ instruction_has_delay_slot = (mips_pc_is_micromips (gdbarch, bpaddr)
+ ? micromips_instruction_has_delay_slot
+ : mips16_instruction_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 && instruction_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 && instruction_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;
+ }