This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] microMIPS support


Hi,

 Here is the final version of the change that I have applied.  Thanks to 
everybody involved in the review.

  Maciej

2012-05-18  Maciej W. Rozycki  <macro@codesourcery.com>

	gdb/
	* NEWS: Add microMIPS support and "set mips compression",
	"show mips compression" commands.
	* mips-tdep.h (mips_isa): New enum.
	(gdbarch_tdep): Add mips_isa.
	(mips_pc_is_mips16): Update prototype.
	(mips_pc_is_mips, mips_pc_is_micromips): New prototypes.
	* mips-tdep.c (mips_compression_mips16): New variable.
	(mips_compression_micromips): Likewise.
	(mips_compression_strings): Likewise.
	(mips_compression_string): Likewise.
	(is_mips16_isa, is_micromips_isa): New functions.
	(is_mips16_addr): Rename to...
	(is_compact_addr): ... this.
	(unmake_mips16_addr): Likewise to...
	(unmake_compact_addr): ... this.
	(make_mips16_addr): Likewise to...
	(make_compact_addr): ... this.
	(is_mips_addr, is_mips16_addr, is_micromips_addr): New
	functions.
	(mips_elf_make_msymbol_special): Handle microMIPS code.
	(msymbol_is_special): Rename to...
	(msymbol_is_mips16): ... this.
	(mips_make_symbol_special, mips_pc_is_mips16): Update
	accordingly.
	(msymbol_is_mips, msymbol_is_micromips): New functions.
	(mips16_to_32_reg): Rename to...
	(mips_reg3_to_reg): ... this.
	(mips_pc_is_mips, mips_pc_is_micromips): New functions.
	(mips_pc_isa): Likewise.
	(mips_read_pc, mips_unwind_pc, mips_write_pc): Handle microMIPS
	code.
	(mips_fetch_instruction): Pass return status instead of printing
	an error message if requested.  Handle microMIPS code.  Bail out
	on an invalid ISA.
	(micromips_op): New macro.
	(b0s4_imm, b0s5_imm, b0s5_reg, b0s7_imm, b0s10_imm): Likewise.
	(b1s9_imm, b2s3_cc, b4s2_regl, b5s5_op, b5s5_reg): Likewise.
	(b6s4_op, b7s3_reg): Likewise.
	(b0s6_op, b0s11_op, b0s12_imm, b0s16_imm, b0s26_imm): Likewise.
	(b6s10_ext, b11s5_reg, b12s4_op): Likewise.
	(mips_insn_size): New function.
	(mips32_next_pc): Update mips_fetch_instruction call.
	(micromips_relative_offset7): New function.
	(micromips_relative_offset10): Likewise.
	(micromips_relative_offset16): Likewise.
	(micromips_pc_insn_size): Likewise.
	(micromips_bc1_pc): Likewise.
	(micromips_next_pc): Likewise.
	(unpack_mips16): Update mips_fetch_instruction call.
	(extended_mips16_next_pc): Update according to change to
	mips16_to_32_reg.
	(mips_next_pc): Update mips_pc_is_mips16 call.  Handle microMIPS
	code.
	(mips16_scan_prologue): Update mips_fetch_instruction call.
	Update according to change to mips16_to_32_reg.
	(mips_insn16_frame_sniffer): Update mips_pc_is_mips16 call.
	(mips_insn16_frame_base_sniffer): Likewise.
	(micromips_decode_imm9): New function.
	(micromips_scan_prologue): Likewise.
	(mips_micro_frame_cache): Likewise.
	(mips_micro_frame_this_id): Likewise.
	(mips_micro_frame_prev_register): Likewise.
	(mips_micro_frame_sniffer): Likewise.
	(mips_micro_frame_unwind): New variable.
	(mips_micro_frame_base_address): New function.
	(mips_micro_frame_base): New variable.
	(mips_micro_frame_base_sniffer): New function.
	(mips32_scan_prologue): Update mips_fetch_instruction call.
	(mips_insn32_frame_sniffer): Check for the standard MIPS ISA
	rather than for MIPS16.
	(mips_insn32_frame_base_sniffer): Likewise.
	(mips_addr_bits_remove): Handle microMIPS code.
	(deal_with_atomic_sequence): Rename to...
	(mips_deal_with_atomic_sequence): ... this.  Update the type
	of the variable used to hold an instruction.  Remove the ISA bit
	check.  Update mips_fetch_instruction call.
	(micromips_deal_with_atomic_sequence): New function.
	(deal_with_atomic_sequence): Likewise.
	(mips_about_to_return): Handle microMIPS code.  Update
	mips_fetch_instruction call.
	(heuristic_proc_start): Check for the standard MIPS ISA rather
	than for MIPS16.  Update mips_pc_is_mips16 and
	mips_fetch_instruction calls.  Handle microMIPS code.
	(mips_push_dummy_code): Handle microMIPS code.
	(mips_eabi_push_dummy_call): Likewise.
	(mips_o32_return_value): Update mips_pc_is_mips16 call.
	(mips_o64_push_dummy_call): Handle microMIPS code.
	(mips_o64_return_value): Update mips_pc_is_mips16 call.
	(is_delayed): Remove function.
	(mips_single_step_through_delay): Replace the call to is_delayed
	with mips32_instruction_has_delay_slot.  Correct MIPS16 handling.
	Handle microMIPS code.
	(mips_skip_prologue): Update mips_pc_is_mips16 call.  Handle
	microMIPS code.
	(mips32_in_function_epilogue_p): Update mips_fetch_instruction
	call.
	(micromips_in_function_epilogue_p): New function.
	(mips16_in_function_epilogue_p): Update mips_fetch_instruction
	call.
	(mips_in_function_epilogue_p): Update mips_pc_is_mips16 call.
	Handle microMIPS.
	(gdb_print_insn_mips): Likewise.
	(mips_breakpoint_from_pc): Likewise.
	(mips_remote_breakpoint_from_pc): New function.
	(mips32_instruction_has_delay_slot): Simplify making use of the
	updated mips_fetch_instruction interface.
	(micromips_instruction_has_delay_slot): New function.
	(mips16_instruction_has_delay_slot): Simplify making use of the
	updated mips_fetch_instruction interface.
	(mips_adjust_breakpoint_address): Check for the standard MIPS
	ISA rather than for MIPS16 ISA.  Update for unmake_compact_addr 
	calls.  Handle microMIPS code.
	(mips_get_mips16_fn_stub_pc): Update mips_fetch_instruction call.
	(mips_skip_trampoline_code): Handle microMIPS code.
	(global_mips_compression): New function.
	(mips_gdbarch_init): Handle the compressed ISA setting from ELF
	file flags.  Register the microMIPS remote breakpoint handler
	and heuristic frame unwinder.
	(show_mips_compression): New function.
	(_initialize_mips_tdep): Add the "set mips compression" and
	"show mips compression" commands.

2012-05-18  Sandra Loosemore  <sandra@codesourcery.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	gdb/doc/
	* gdb.texinfo (MIPS): Document "set mips compression" and "show
	mips compression".
	(MIPS Breakpoint Kinds): New subsubsection.

gdb-micromips.diff
Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo	2012-05-19 00:31:02.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo	2012-05-19 00:34:16.925630610 +0100
@@ -20547,6 +20547,38 @@ default).
 @kindex show mips abi
 Show the MIPS ABI used by @value{GDBN} to debug the inferior.
 
+@item set mips compression @var{arg}
+@kindex set mips compression
+@cindex code compression, @acronym{MIPS}
+Tell @value{GDBN} which @acronym{MIPS} compressed
+@acronym{ISA, Instruction Set Architecture} encoding is used by the
+inferior.  @value{GDBN} uses this for code disassembly and other
+internal interpretation purposes.  This setting is only referred to
+when no executable has been associated with the debugging session or
+the executable does not provide information about the encoding it uses.
+Otherwise this setting is automatically updated from information
+provided by the executable.
+
+Possible values of @var{arg} are @samp{mips16} and @samp{micromips}.
+The default compressed @acronym{ISA} encoding is @samp{mips16}, as
+executables containing @acronym{MIPS16} code frequently are not
+identified as such.
+
+This setting is ``sticky''; that is, it retains its value across
+debugging sessions until reset either explicitly with this command or
+implicitly from an executable.
+
+The compiler and/or assembler typically add symbol table annotations to
+identify functions compiled for the @acronym{MIPS16} or
+@acronym{microMIPS} @acronym{ISA}s.  If these function-scope annotations
+are present, @value{GDBN} uses them in preference to the global
+compressed @acronym{ISA} encoding setting.
+
+@item show mips compression
+@kindex show mips compression
+Show the @acronym{MIPS} compressed @acronym{ISA} encoding used by
+@value{GDBN} to debug the inferior.
+
 @item set mipsfpu
 @itemx show mipsfpu
 @xref{MIPS Embedded, set mipsfpu}.
@@ -36885,6 +36917,7 @@ These breakpoint kinds are defined for t
 
 @menu
 * MIPS Register packet Format::
+* MIPS Breakpoint Kinds::
 @end menu
 
 @node MIPS Register packet Format
@@ -36911,6 +36944,28 @@ as @code{MIPS32}.
 
 @end table
 
+@node MIPS Breakpoint Kinds
+@subsubsection @acronym{MIPS} Breakpoint Kinds
+@cindex breakpoint kinds, @acronym{MIPS}
+
+These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
+
+@table @r
+
+@item 2
+16-bit @acronym{MIPS16} mode breakpoint.
+
+@item 3
+16-bit @acronym{microMIPS} mode breakpoint.
+
+@item 4
+32-bit standard @acronym{MIPS} mode breakpoint.
+
+@item 5
+32-bit @acronym{microMIPS} mode breakpoint.
+
+@end table
+
 @node Tracepoint Packets
 @section Tracepoint Packets
 @cindex tracepoint packets
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c	2012-05-19 00:31:37.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c	2012-05-19 00:34:16.935626560 +0100
@@ -62,6 +62,12 @@ static const struct objfile_data *mips_p
 
 static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
 
+static int mips32_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR);
+static int micromips_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR,
+						 int);
+static int mips16_instruction_has_delay_slot (struct gdbarch *, CORE_ADDR,
+					      int);
+
 /* 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)
@@ -93,6 +99,20 @@ static const char *const mips_abi_string
   NULL
 };
 
+/* 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
 {
@@ -246,53 +266,127 @@ mips_abi_regsize (struct gdbarch *gdbarc
     }
 }
 
-/* MIPS16 function addresses are odd (bit 0 is set).  Here are some
-   functions to test, set, or clear bit 0 of addresses.  */
+/* 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.  */
 
-static CORE_ADDR
-is_mips16_addr (CORE_ADDR addr)
+/* Return one iff compressed code is the MIPS16 instruction set.  */
+
+static int
+is_mips16_isa (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->mips_isa == ISA_MIPS16;
+}
+
+/* Return one iff compressed code is the microMIPS instruction set.  */
+
+static int
+is_micromips_isa (struct gdbarch *gdbarch)
+{
+  return gdbarch_tdep (gdbarch)->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_mips16_addr (CORE_ADDR addr)
+unmake_compact_addr (CORE_ADDR addr)
 {
   return ((addr) & ~(CORE_ADDR) 1);
 }
 
+/* Add the ISA (compression) bit to ADDR.  */
+
 static CORE_ADDR
-make_mips16_addr (CORE_ADDR addr)
+make_compact_addr (CORE_ADDR addr)
 {
   return ((addr) | (CORE_ADDR) 1);
 }
 
 /* Functions for setting and testing a bit in a minimal symbol that
-   marks it as 16-bit function.  The MSB of the minimal symbol's
-   "info" field is used for this purpose.
+   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 16-bit function, and sets a "special" bit in a
-   minimal symbol to mark it as a 16-bit function
+   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; in particular synthetic symbols such as for PLT stubs
+   have no ELF-private part at all.
 
-   MSYMBOL_IS_SPECIAL   tests the "special" bit in a minimal symbol  */
+   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)
 {
-  if (ELF_ST_IS_MIPS16 (((elf_symbol_type *)
-			 (sym))->internal_elf_sym.st_other))
-    {
-      MSYMBOL_TARGET_FLAG_1 (msym) = 1;
-    }
+  elf_symbol_type *elfsym = (elf_symbol_type *) sym;
+
+  if ((sym->flags & BSF_SYNTHETIC) != 0)
+    return;
+
+  if (ELF_ST_IS_MICROMIPS (elfsym->internal_elf_sym.st_other))
+    MSYMBOL_TARGET_FLAG_2 (msym) = 1;
+  else if (ELF_ST_IS_MIPS16 (elfsym->internal_elf_sym.st_other))
+    MSYMBOL_TARGET_FLAG_1 (msym) = 1;
 }
 
+/* Return one iff MSYM refers to standard ISA code.  */
+
 static int
-msymbol_is_special (struct minimal_symbol *msym)
+msymbol_is_mips (struct minimal_symbol *msym)
+{
+  return !(MSYMBOL_TARGET_FLAG_1 (msym) | MSYMBOL_TARGET_FLAG_2 (msym));
+}
+
+/* Return one iff MSYM refers to MIPS16 code.  */
+
+static int
+msymbol_is_mips16 (struct minimal_symbol *msym)
 {
   return MSYMBOL_TARGET_FLAG_1 (msym);
 }
 
+/* Return one iff MSYM refers to microMIPS code.  */
+
+static int
+msymbol_is_micromips (struct minimal_symbol *msym)
+{
+  return MSYMBOL_TARGET_FLAG_2 (msym);
+}
+
 /* 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
@@ -686,8 +780,8 @@ mips_ax_pseudo_register_push_stack (stru
   return 0;
 }
 
-/* Table to translate MIPS16 register field to actual register number.  */
-static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
+/* Table to translate 3-bit register field to actual register number.  */
+static int 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
@@ -1017,22 +1111,94 @@ show_mask_address (struct ui_file *file,
     }
 }
 
+/* Tell if the program counter value in MEMADDR is in a standard ISA
+   function.  */
+
+int
+mips_pc_is_mips (CORE_ADDR memaddr)
+{
+  struct 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 (memaddr);
+  if (sym)
+    return msymbol_is_mips (sym);
+  else
+    return is_mips_addr (memaddr);
+}
+
 /* Tell if the program counter value in MEMADDR is in a MIPS16 function.  */
 
 int
-mips_pc_is_mips16 (CORE_ADDR memaddr)
+mips_pc_is_mips16 (struct gdbarch *gdbarch, CORE_ADDR memaddr)
 {
   struct 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 or normal MIPS.  Otherwise if bit 0 of
-     the address is set, assume this is a MIPS16 address.  */
+     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 (memaddr);
   if (sym)
-    return msymbol_is_special (sym);
+    return msymbol_is_mips16 (sym);
   else
-    return is_mips16_addr (memaddr);
+    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 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 (memaddr);
+  if (sym)
+    return msymbol_is_micromips (sym);
+  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 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 (memaddr);
+  if (sym)
+    {
+      if (msymbol_is_micromips (sym))
+	return ISA_MICROMIPS;
+      else if (msymbol_is_mips16 (sym))
+	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;
+    }
 }
 
 /* Various MIPS16 thunk (aka stub or trampoline) names.  */
@@ -1084,8 +1250,8 @@ mips_read_pc (struct regcache *regcache)
   ULONGEST pc;
 
   regcache_cooked_read_signed (regcache, regnum, &pc);
-  if (is_mips16_addr (pc))
-    pc = unmake_mips16_addr (pc);
+  if (is_compact_addr (pc))
+    pc = unmake_compact_addr (pc);
   return pc;
 }
 
@@ -1095,8 +1261,8 @@ mips_unwind_pc (struct gdbarch *gdbarch,
   CORE_ADDR pc;
 
   pc = frame_unwind_register_signed (next_frame, gdbarch_pc_regnum (gdbarch));
-  if (is_mips16_addr (pc))
-    pc = unmake_mips16_addr (pc);
+  if (is_compact_addr (pc))
+    pc = unmake_compact_addr (pc);
   /* 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
@@ -1106,14 +1272,14 @@ mips_unwind_pc (struct gdbarch *gdbarch,
     {
       pc = frame_unwind_register_signed
 	     (next_frame, gdbarch_num_regs (gdbarch) + MIPS_RA_REGNUM);
-      if (is_mips16_addr (pc))
-	pc = unmake_mips16_addr (pc);
+      if (is_compact_addr (pc))
+	pc = unmake_compact_addr (pc);
       if (mips_in_frame_stub (pc))
 	{
 	  pc = frame_unwind_register_signed
 		 (next_frame, gdbarch_num_regs (gdbarch) + MIPS_S2_REGNUM);
-	  if (is_mips16_addr (pc))
-	    pc = unmake_mips16_addr (pc);
+	  if (is_compact_addr (pc))
+	    pc = unmake_compact_addr (pc);
 	}
     }
   return pc;
@@ -1148,33 +1314,47 @@ mips_write_pc (struct regcache *regcache
 {
   int regnum = gdbarch_pc_regnum (get_regcache_arch (regcache));
 
-  if (mips_pc_is_mips16 (pc))
-    regcache_cooked_write_unsigned (regcache, regnum, make_mips16_addr (pc));
-  else
+  if (mips_pc_is_mips (pc))
     regcache_cooked_write_unsigned (regcache, regnum, pc);
+  else
+    regcache_cooked_write_unsigned (regcache, regnum, make_compact_addr (pc));
 }
 
-/* Fetch and return instruction from the specified location.  If the PC
-   is odd, assume it's a MIPS16 instruction; otherwise MIPS32.  */
+/* Fetch and return instruction from the specified location.  Handle
+   MIPS16/microMIPS as appropriate.  */
 
 static ULONGEST
-mips_fetch_instruction (struct gdbarch *gdbarch, CORE_ADDR addr)
+mips_fetch_instruction (struct gdbarch *gdbarch,
+			enum mips_isa isa, CORE_ADDR addr, int *statusp)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte buf[MIPS_INSN32_SIZE];
   int instlen;
   int status;
 
-  if (mips_pc_is_mips16 (addr))
+  switch (isa)
     {
+    case ISA_MICROMIPS:
+    case ISA_MIPS16:
       instlen = MIPS_INSN16_SIZE;
-      addr = unmake_mips16_addr (addr);
+      addr = unmake_compact_addr (addr);
+      break;
+    case ISA_MIPS:
+      instlen = MIPS_INSN32_SIZE;
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, _("invalid ISA"));
+      break;
     }
-  else
-    instlen = MIPS_INSN32_SIZE;
   status = target_read_memory (addr, buf, instlen);
+  if (statusp != NULL)
+    *statusp = status;
   if (status)
-    memory_error (status, addr);
+    {
+      if (statusp == NULL)
+	memory_error (status, addr);
+      return 0;
+    }
   return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
@@ -1195,6 +1375,63 @@ mips_fetch_instruction (struct gdbarch *
 #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) == 0x1f)
+        return 3 * MIPS_INSN16_SIZE;
+      else 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 (__FILE__, __LINE__, _("invalid ISA"));
+}
+
 static LONGEST
 mips32_relative_offset (ULONGEST inst)
 {
@@ -1239,7 +1476,7 @@ mips32_next_pc (struct frame_info *frame
   struct gdbarch *gdbarch = get_frame_arch (frame);
   unsigned long inst;
   int op;
-  inst = mips_fetch_instruction (gdbarch, pc);
+  inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
   if ((inst & 0xe0000000) != 0)		/* Not a special, jump or branch
 					   instruction.  */
     {
@@ -1409,6 +1646,276 @@ mips32_next_pc (struct frame_info *frame
   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 frame_info *frame,
+		  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 = get_frame_register_unsigned (frame, 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 frame_info *frame, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  ULONGEST insn;
+
+  insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, pc, NULL);
+  pc += MIPS_INSN16_SIZE;
+  switch (mips_insn_size (ISA_MICROMIPS, insn))
+    {
+    /* 48-bit instructions.  */
+    case 3 * MIPS_INSN16_SIZE: /* POOL48A: bits 011111 */
+      /* No branch or jump instructions in this category.  */
+      pc += 2 * MIPS_INSN16_SIZE;
+      break;
+
+    /* 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 */
+	  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 */
+	    pc = get_frame_register_signed (frame, b0s5_reg (insn >> 16));
+	  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 (get_frame_register_signed (frame,
+					     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 (get_frame_register_signed (frame,
+					     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 (get_frame_register_signed (frame,
+					     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 (get_frame_register_signed (frame,
+					     b0s5_reg (insn >> 16)) != 0)
+		pc += micromips_relative_offset16 (insn);
+	      break;
+
+	    case 0x06: /* BGTZ: bits 010000 00110 */
+	      if (get_frame_register_signed (frame,
+					     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 (get_frame_register_signed (frame,
+					     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 ((get_frame_register_unsigned (frame,
+						  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, frame, 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, frame, 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 (get_frame_register_signed (frame, b0s5_reg (insn >> 16))
+		== get_frame_register_signed (frame, b5s5_reg (insn >> 16)))
+	      pc += micromips_relative_offset16 (insn);
+	    else
+	      pc += micromips_pc_insn_size (gdbarch, pc);
+	  break;
+
+	case 0x2d: /* BNE: bits 101101 */
+	    if (get_frame_register_signed (frame, b0s5_reg (insn >> 16))
+		!= get_frame_register_signed (frame, 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 = get_frame_register_signed (frame, b0s5_reg (insn));
+	  else if (b5s5_op (insn) == 0x18)
+	    /* JRADDIUSP: bits 010001 11000 */
+	    pc = get_frame_register_signed (frame, MIPS_RA_REGNUM);
+	  break;
+
+	case 0x23: /* BEQZ16: bits 100011 */
+	  {
+	    int rs = mips_reg3_to_reg[b7s3_reg (insn)];
+
+	    if (get_frame_register_signed (frame, 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 (get_frame_register_signed (frame, 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
@@ -1543,8 +2050,8 @@ unpack_mips16 (struct gdbarch *gdbarch, 
 	unsigned int nexthalf;
 	value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f);
 	value = value << 16;
-	nexthalf = mips_fetch_instruction (gdbarch, pc + 2);  /* low bit
-								 still set.  */
+	nexthalf = mips_fetch_instruction (gdbarch, ISA_MIPS16, pc + 2, NULL);
+						/* Low bit still set.  */
 	value |= nexthalf;
 	offset = value;
 	regx = -1;
@@ -1598,7 +2105,7 @@ extended_mips16_next_pc (struct frame_in
 	struct upk_mips16 upk;
 	int reg;
 	unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
-	reg = get_frame_register_signed (frame, mips16_to_32_reg[upk.regx]);
+	reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]);
 	if (reg == 0)
 	  pc += (upk.offset << 1) + 2;
 	else
@@ -1610,7 +2117,7 @@ extended_mips16_next_pc (struct frame_in
 	struct upk_mips16 upk;
 	int reg;
 	unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
-	reg = get_frame_register_signed (frame, mips16_to_32_reg[upk.regx]);
+	reg = get_frame_register_signed (frame, mips_reg3_to_reg[upk.regx]);
 	if (reg != 0)
 	  pc += (upk.offset << 1) + 2;
 	else
@@ -1643,7 +2150,7 @@ extended_mips16_next_pc (struct frame_in
 	    upk.regx = (insn >> 8) & 0x07;
 	    upk.regy = (insn >> 5) & 0x07;
 	    if ((upk.regy & 1) == 0)
-	      reg = mips16_to_32_reg[upk.regx];
+	      reg = mips_reg3_to_reg[upk.regx];
 	    else
 	      reg = 31;		/* Function return instruction.  */
 	    pc = get_frame_register_signed (frame, reg);
@@ -1683,12 +2190,16 @@ mips16_next_pc (struct frame_info *frame
    target monitor or stub is not developed enough to do a single_step.
    It works by decoding the current instruction and predicting where a
    branch will go.  This isnt hard because all the data is available.
-   The MIPS32 and MIPS16 variants are quite different.  */
+   The MIPS32, MIPS16 and microMIPS variants are quite different.  */
 static CORE_ADDR
 mips_next_pc (struct frame_info *frame, CORE_ADDR pc)
 {
-  if (mips_pc_is_mips16 (pc))
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  if (mips_pc_is_mips16 (gdbarch, pc))
     return mips16_next_pc (frame, pc);
+  else if (mips_pc_is_micromips (gdbarch, pc))
+    return micromips_next_pc (frame, pc);
   else
     return mips32_next_pc (frame, pc);
 }
@@ -1805,7 +2316,8 @@ mips16_scan_prologue (struct gdbarch *gd
       prev_inst = inst;
 
       /* Fetch and decode the instruction.  */
-      inst = (unsigned short) mips_fetch_instruction (gdbarch, cur_pc);
+      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
@@ -1836,13 +2348,13 @@ mips16_scan_prologue (struct gdbarch *gd
       else if ((inst & 0xf800) == 0xd000)	/* sw reg,n($sp) */
 	{
 	  offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
-	  reg = mips16_to_32_reg[(inst & 0x700) >> 8];
+	  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 = mips16_to_32_reg[(inst & 0xe0) >> 5];
+	  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) */
@@ -1870,13 +2382,13 @@ mips16_scan_prologue (struct gdbarch *gd
       else if ((inst & 0xFF00) == 0xd900)	/* sw reg,offset($s1) */
 	{
 	  offset = mips16_get_imm (prev_inst, inst, 5, 4, 0);
-	  reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+	  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 = mips16_to_32_reg[(inst & 0xe0) >> 5];
+	  reg = mips_reg3_to_reg[(inst & 0xe0) >> 5];
 	  set_reg_offset (gdbarch, this_cache, reg, frame_addr + offset);
 	}
       else if ((inst & 0xf81f) == 0xe809
@@ -2129,8 +2641,9 @@ static int
 mips_insn16_frame_sniffer (const struct frame_unwind *self,
 			   struct frame_info *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 (pc))
+  if (mips_pc_is_mips16 (gdbarch, pc))
     return 1;
   return 0;
 }
@@ -2165,13 +2678,446 @@ static const struct frame_base mips_insn
 static const struct frame_base *
 mips_insn16_frame_base_sniffer (struct frame_info *this_frame)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   CORE_ADDR pc = get_frame_pc (this_frame);
-  if (mips_pc_is_mips16 (pc))
+  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,
+			 struct frame_info *this_frame,
+			 struct mips_frame_cache *this_cache)
+{
+  CORE_ADDR end_prologue_addr = 0;
+  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.  */
+  CORE_ADDR frame_addr = 0;	/* Value of $30, used as frame pointer.  */
+  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;
+      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))
+	{
+	/* 48-bit instructions.  */
+	case 3 * MIPS_INSN16_SIZE:
+	  /* No prologue instructions in this category.  */
+	  this_non_prologue_insn = 1;
+	  loc += 2 * MIPS_INSN16_SIZE;
+	  break;
+
+	/* 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 = 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_addr = sp + offset;
+		  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 is 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:
+	      this_non_prologue_insn = 1;
+	      break;
+	    }
+	  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_addr = 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:
+	      this_non_prologue_insn = 1;
+	      break;
+	    }
+	  break;
+	}
+      if (sp_adj < 0)
+	frame_offset -= sp_adj;
+
+      non_prologue_insns += this_non_prologue_insn;
+      /* Enough non-prologue insns seen or positive stack adjustment? */
+      if (end_prologue_addr == 0 && (non_prologue_insns > 1 || sp_adj > 0))
+	{
+	  end_prologue_addr = prev_non_prologue_insn ? prev_pc : cur_pc;
+	  break;
+	}
+      prev_non_prologue_insn = this_non_prologue_insn;
+      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];
+    }
+
+  /* If we didn't reach the end of the prologue when scanning the function
+     instructions, then 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.  */
+  if (end_prologue_addr == 0)
+    end_prologue_addr = prev_non_prologue_insn ? 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 (struct frame_info *this_frame, void **this_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct mips_frame_cache *cache;
+
+  if ((*this_cache) != NULL)
+    return (*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, *this_cache);
+  }
+
+  /* gdbarch_sp_regnum contains the value and not the address.  */
+  trad_frame_set_value (cache->saved_regs,
+			gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
+			cache->base);
+
+  return (*this_cache);
+}
+
+static void
+mips_micro_frame_this_id (struct frame_info *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 (struct frame_info *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,
+			  struct frame_info *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 =
+{
+  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 (struct frame_info *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 (struct frame_info *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.  */
 
@@ -2236,7 +3182,8 @@ mips32_scan_prologue (struct gdbarch *gd
       int reg;
 
       /* Fetch the instruction.  */
-      inst = (unsigned long) mips_fetch_instruction (gdbarch, cur_pc);
+      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;
@@ -2420,7 +3367,7 @@ mips32_scan_prologue (struct gdbarch *gd
 /* 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.  */
+   unwinder.  Likewise microMIPS and the mips_micro unwinder. */
 
 static struct mips_frame_cache *
 mips_insn32_frame_cache (struct frame_info *this_frame, void **this_cache)
@@ -2485,7 +3432,7 @@ mips_insn32_frame_sniffer (const struct 
 			   struct frame_info *this_frame, void **this_cache)
 {
   CORE_ADDR pc = get_frame_pc (this_frame);
-  if (! mips_pc_is_mips16 (pc))
+  if (mips_pc_is_mips (pc))
     return 1;
   return 0;
 }
@@ -2521,7 +3468,7 @@ static const struct frame_base *
 mips_insn32_frame_base_sniffer (struct frame_info *this_frame)
 {
   CORE_ADDR pc = get_frame_pc (this_frame);
-  if (! mips_pc_is_mips16 (pc))
+  if (mips_pc_is_mips (pc))
     return &mips_insn32_frame_base;
   else
     return NULL;
@@ -2658,8 +3605,8 @@ mips_addr_bits_remove (struct gdbarch *g
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  if (is_mips16_addr (addr))
-    addr = unmake_mips16_addr (addr);
+  if (is_compact_addr (addr))
+    addr = unmake_compact_addr (addr);
 
   if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
     /* This hack is a work-around for existing boards using PMON, the
@@ -2682,34 +3629,33 @@ mips_addr_bits_remove (struct gdbarch *g
     return addr;
 }
 
-/* Instructions used during single-stepping of atomic sequences.  */
-#define LL_OPCODE 0x30
-#define LLD_OPCODE 0x34
-#define SC_OPCODE 0x38
-#define SCD_OPCODE 0x3c
 
 /* 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 int
-deal_with_atomic_sequence (struct gdbarch *gdbarch,
-			   struct address_space *aspace, CORE_ADDR pc)
+mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
+ 				struct address_space *aspace, CORE_ADDR pc)
 {
   CORE_ADDR breaks[2] = {-1, -1};
   CORE_ADDR loc = pc;
   CORE_ADDR branch_bp; /* Breakpoint at branch instruction's destination.  */
-  unsigned long insn;
+  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.  */
 
-  if (pc & 0x01)
-    return 0;
-
-  insn = mips_fetch_instruction (gdbarch, loc);
+  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 0;
@@ -2720,7 +3666,7 @@ deal_with_atomic_sequence (struct gdbarc
     {
       int is_branch = 0;
       loc += MIPS_INSN32_SIZE;
-      insn = mips_fetch_instruction (gdbarch, loc);
+      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
@@ -2795,6 +3741,177 @@ deal_with_atomic_sequence (struct gdbarc
   return 1;
 }
 
+static int
+micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
+				     struct address_space *aspace,
+				     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] = {-1, -1};
+  CORE_ADDR branch_bp; /* 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 0;
+  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 0;
+  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))
+	{
+	/* 48-bit instructions.  */
+	case 3 * MIPS_INSN16_SIZE: /* POOL48A: bits 011111 */
+	  loc += 2 * MIPS_INSN16_SIZE;
+	  break;
+
+	/* 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 0; /* 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 0; /* Fall back to the standard single-step code. */
+
+	    case 0x33: /* B16: bits 110011 */
+	      return 0; /* Fall back to the standard single-step code. */
+	    }
+	  break;
+	}
+      if (is_branch)
+	{
+	  if (last_breakpoint >= 1)
+	    return 0; /* More than one branch found, fallback to the
+			 standard single-step code.  */
+	  breaks[1] = branch_bp;
+	  last_breakpoint++;
+	}
+    }
+  if (!sc_found)
+    return 0;
+
+  /* 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;
+
+  /* Effectively inserts the breakpoints.  */
+  for (index = 0; index <= last_breakpoint; index++)
+      insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
+
+  return 1;
+}
+
+static int
+deal_with_atomic_sequence (struct gdbarch *gdbarch,
+			   struct address_space *aspace, CORE_ADDR pc)
+{
+  if (mips_pc_is_mips (pc))
+    return mips_deal_with_atomic_sequence (gdbarch, aspace, pc);
+  else if (mips_pc_is_micromips (gdbarch, pc))
+    return micromips_deal_with_atomic_sequence (gdbarch, aspace, pc);
+  else
+    return 0;
+}
+
 /* 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
@@ -2827,10 +3944,10 @@ mips_about_to_return (struct gdbarch *gd
   ULONGEST hint;
 
   /* This used to check for MIPS16, but this piece of code is never
-     called for MIPS16 functions.  */
-  gdb_assert (!mips_pc_is_mips16 (pc));
+     called for MIPS16 functions.  And likewise microMIPS ones.  */
+  gdb_assert (mips_pc_is_mips (pc));
 
-  insn = mips_fetch_instruction (gdbarch, pc);
+  insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
   hint = 0x7c0;
   return (insn & ~hint) == 0x3e00008;			/* jr(.hb) $ra */
 }
@@ -2858,7 +3975,7 @@ heuristic_proc_start (struct gdbarch *gd
   if (heuristic_fence_post == UINT_MAX || fence < VM_MIN_ADDRESS)
     fence = VM_MIN_ADDRESS;
 
-  instlen = mips_pc_is_mips16 (pc) ? MIPS_INSN16_SIZE : MIPS_INSN32_SIZE;
+  instlen = mips_pc_is_mips (pc) ? MIPS_INSN32_SIZE : MIPS_INSN16_SIZE;
 
   inf = current_inferior ();
 
@@ -2903,7 +4020,7 @@ heuristic-fence-post' command.\n",
 
 	return 0;
       }
-    else if (mips_pc_is_mips16 (start_pc))
+    else if (mips_pc_is_mips16 (gdbarch, start_pc))
       {
 	unsigned short inst;
 
@@ -2915,12 +4032,13 @@ heuristic-fence-post' command.\n",
 	   addiu sp,-n
 	   daddiu sp,-n
 	   extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n'.  */
-	inst = mips_fetch_instruction (gdbarch, start_pc);
+	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, start_pc - instlen);
+		inst = mips_fetch_instruction (gdbarch, ISA_MIPS16,
+					       start_pc - instlen, NULL);
 		if ((inst & 0xf800) == 0xf000)	/* extend */
 		  start_pc -= instlen;
 	      }
@@ -2938,6 +4056,67 @@ heuristic-fence-post' command.\n",
 	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.  */
@@ -3127,14 +4306,14 @@ mips_eabi_push_dummy_call (struct gdbarc
 	{
 	  CORE_ADDR addr = extract_signed_integer (value_contents (arg),
 						   len, byte_order);
-	  if (mips_pc_is_mips16 (addr))
+	  if (mips_pc_is_mips (addr))
+	    val = value_contents (arg);
+	  else
 	    {
 	      store_signed_integer (valbuf, len, byte_order, 
-				    make_mips16_addr (addr));
+				    make_compact_addr (addr));
 	      val = valbuf;
 	    }
-	  else
-	    val = value_contents (arg);
 	}
       /* The EABI passes structures that do not fit in a register by
          reference.  */
@@ -4226,8 +5405,8 @@ mips_o32_return_value (struct gdbarch *g
 		       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);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int mips16 = mips_pc_is_mips16 (func_addr);
   enum mips_fval_reg fval_reg;
 
   fval_reg = readbuf ? mips16 ? mips_fval_gpr : mips_fval_fpr : mips_fval_both;
@@ -4528,10 +5707,10 @@ mips_o64_push_dummy_call (struct gdbarch
 	{
 	  CORE_ADDR addr = extract_signed_integer (value_contents (arg),
 						   len, byte_order);
-	  if (mips_pc_is_mips16 (addr))
+	  if (!mips_pc_is_mips (addr))
 	    {
 	      store_signed_integer (valbuf, len, byte_order, 
-				    make_mips16_addr (addr));
+				    make_compact_addr (addr));
 	      val = valbuf;
 	    }
 	}
@@ -4694,8 +5873,8 @@ mips_o64_return_value (struct gdbarch *g
 		       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);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  int mips16 = mips_pc_is_mips16 (func_addr);
   enum mips_fval_reg fval_reg;
 
   fval_reg = readbuf ? mips16 ? mips_fval_gpr : mips_fval_fpr : mips_fval_both;
@@ -5137,42 +6316,32 @@ mips_print_registers_info (struct gdbarc
     }
 }
 
-/* Is this a branch with a delay slot?  */
-
-static int
-is_delayed (unsigned long insn)
-{
-  int i;
-  for (i = 0; i < NUMOPCODES; ++i)
-    if (mips_opcodes[i].pinfo != INSN_MACRO
-	&& (insn & mips_opcodes[i].mask) == mips_opcodes[i].match)
-      break;
-  return (i < NUMOPCODES
-	  && (mips_opcodes[i].pinfo & (INSN_UNCOND_BRANCH_DELAY
-				       | INSN_COND_BRANCH_DELAY
-				       | INSN_COND_BRANCH_LIKELY)));
-}
-
 static int
 mips_single_step_through_delay (struct gdbarch *gdbarch,
 				struct frame_info *frame)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR pc = get_frame_pc (frame);
-  gdb_byte buf[MIPS_INSN32_SIZE];
-
-  /* There is no branch delay slot on MIPS16.  */
-  if (mips_pc_is_mips16 (pc))
-    return 0;
+  struct address_space *aspace;
+  enum mips_isa isa;
+  ULONGEST insn;
+  int status;
+  int size;
 
-  if (!breakpoint_here_p (get_frame_address_space (frame), pc + 4))
+  if ((mips_pc_is_mips (pc)
+       && !mips32_instruction_has_delay_slot (gdbarch, pc))
+      || (mips_pc_is_micromips (gdbarch, pc)
+	  && !micromips_instruction_has_delay_slot (gdbarch, pc, 0))
+      || (mips_pc_is_mips16 (gdbarch, pc)
+	  && !mips16_instruction_has_delay_slot (gdbarch, pc, 0)))
     return 0;
 
-  if (!safe_frame_unwind_memory (frame, pc, buf, sizeof buf))
-    /* If error reading memory, guess that it is not a delayed
-       branch.  */
-    return 0;
-  return is_delayed (extract_unsigned_integer (buf, sizeof buf, byte_order));
+  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);
+  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
@@ -5211,8 +6380,10 @@ mips_skip_prologue (struct gdbarch *gdba
   if (limit_pc == 0)
     limit_pc = pc + 100;          /* Magic.  */
 
-  if (mips_pc_is_mips16 (pc))
+  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);
 }
@@ -5239,7 +6410,7 @@ mips32_in_function_epilogue_p (struct gd
 	  unsigned long high_word;
 	  unsigned long inst;
 
-	  inst = mips_fetch_instruction (gdbarch, pc);
+	  inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
 	  high_word = (inst >> 16) & 0xffff;
 
 	  if (high_word != 0x27bd	/* addiu $sp,$sp,offset */
@@ -5255,6 +6426,107 @@ mips32_in_function_epilogue_p (struct gd
   return 0;
 }
 
+/* Check whether the PC is in a function epilogue (microMIPS version).
+   This is a helper function for mips_in_function_epilogue_p.  */
+
+static int
+micromips_in_function_epilogue_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))
+	{
+	/* 48-bit instructions.  */
+	case 3 * MIPS_INSN16_SIZE:
+	  /* No epilogue instructions in this category.  */
+	  return 0;
+
+	/* 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;
+}
+
 /* Check whether the PC is in a function epilogue (16-bit version).
    This is a helper function for mips_in_function_epilogue_p.  */
 static int
@@ -5276,7 +6548,7 @@ mips16_in_function_epilogue_p (struct gd
 	{
 	  unsigned short inst;
 
-	  inst = mips_fetch_instruction (gdbarch, pc);
+	  inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, pc, NULL);
 
 	  if ((inst & 0xf800) == 0xf000)	/* extend */
 	    continue;
@@ -5300,8 +6572,10 @@ mips16_in_function_epilogue_p (struct gd
 static int
 mips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
-  if (mips_pc_is_mips16 (pc))
+  if (mips_pc_is_mips16 (gdbarch, pc))
     return mips16_in_function_epilogue_p (gdbarch, pc);
+  else if (mips_pc_is_micromips (gdbarch, pc))
+    return micromips_in_function_epilogue_p (gdbarch, pc);
   else
     return mips32_in_function_epilogue_p (gdbarch, pc);
 }
@@ -5450,15 +6724,20 @@ reinit_frame_cache_sfunc (char *args, in
 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 (memaddr))
+  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 ? ~1 : ~3);
+  memaddr &= (info->mach == bfd_mach_mips16
+	      || info->mach == bfd_mach_mips_micromips) ? ~1 : ~3;
 
   /* Set the disassembler options.  */
   if (!info->disassembler_options)
@@ -5509,15 +6788,33 @@ 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 (*pcptr))
+      if (mips_pc_is_mips16 (gdbarch, pc))
 	{
 	  static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
-	  *pcptr = unmake_mips16_addr (*pcptr);
+	  *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
@@ -5546,13 +6843,29 @@ mips_breakpoint_from_pc (struct gdbarch 
     }
   else
     {
-      if (mips_pc_is_mips16 (*pcptr))
+      if (mips_pc_is_mips16 (gdbarch, pc))
 	{
 	  static gdb_byte mips16_little_breakpoint[] = { 0xa5, 0xe8 };
-	  *pcptr = unmake_mips16_addr (*pcptr);
+	  *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 };
@@ -5573,6 +6886,43 @@ mips_breakpoint_from_pc (struct gdbarch 
     }
 }
 
+/* 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.  */
@@ -5580,18 +6930,16 @@ mips_breakpoint_from_pc (struct gdbarch 
 static int
 mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
-  gdb_byte buf[MIPS_INSN32_SIZE];
   unsigned long inst;
   int status;
   int op;
   int rs;
   int rt;
 
-  status = target_read_memory (addr, buf, MIPS_INSN32_SIZE);
+  inst = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
   if (status)
     return 0;
 
-  inst = mips_fetch_instruction (gdbarch, addr);
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)
     {
@@ -5635,18 +6983,83 @@ mips32_instruction_has_delay_slot (struc
    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)
 {
-  gdb_byte buf[MIPS_INSN16_SIZE];
   unsigned short inst;
   int status;
 
-  status = target_read_memory (addr, buf, MIPS_INSN16_SIZE);
+  inst = mips_fetch_instruction (gdbarch, ISA_MIPS16, addr, &status);
   if (status)
     return 0;
 
-  inst = mips_fetch_instruction (gdbarch, addr);
   if (!mustbe32)
     return (inst & 0xf89f) == 0xe800;	/* JR/JALR (16-bit instruction)  */
   return (inst & 0xf800) == 0x1800;	/* JAL/JALX (32-bit instruction)  */
@@ -5735,7 +7148,7 @@ mips_adjust_breakpoint_address (struct g
       && func_addr > boundary && func_addr <= bpaddr)
     boundary = func_addr;
 
-  if (!mips_pc_is_mips16 (bpaddr))
+  if (mips_pc_is_mips (bpaddr))
     {
       if (bpaddr == boundary)
 	return bpaddr;
@@ -5748,31 +7161,37 @@ mips_adjust_breakpoint_address (struct g
     }
   else
     {
+      int (*instruction_has_delay_slot) (struct gdbarch *, CORE_ADDR, int);
       CORE_ADDR addr, jmpaddr;
       int i;
 
-      boundary = unmake_mips16_addr (boundary);
+      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_mips16_addr (addr) == boundary)
+	  if (unmake_compact_addr (addr) == boundary)
 	    break;
-	  addr -= 2;
-	  if (i == 1 && mips16_instruction_has_delay_slot (gdbarch, addr, 0))
+	  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
-		   && mips16_instruction_has_delay_slot (gdbarch, addr, 1))
+	  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
@@ -5917,7 +7336,7 @@ mips_get_mips16_fn_stub_pc (struct frame
        status == 0 && target_pc == 0 && i < 20;
        i++, pc += MIPS_INSN32_SIZE)
     {
-      ULONGEST inst = mips_fetch_instruction (gdbarch, pc);
+      ULONGEST inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
       CORE_ADDR imm;
       int rt;
       int rs;
@@ -6219,24 +7638,24 @@ mips_skip_trampoline_code (struct frame_
       if (new_pc)
 	{
 	  pc = new_pc;
-	  if (is_mips16_addr (pc))
-	    pc = unmake_mips16_addr (pc);
+	  if (is_compact_addr (pc))
+	    pc = unmake_compact_addr (pc);
 	}
 
       new_pc = find_solib_trampoline_target (frame, pc);
       if (new_pc)
 	{
 	  pc = new_pc;
-	  if (is_mips16_addr (pc))
-	    pc = unmake_mips16_addr (pc);
+	  if (is_compact_addr (pc))
+	    pc = unmake_compact_addr (pc);
 	}
 
       new_pc = mips_skip_pic_trampoline_code (frame, pc);
       if (new_pc)
 	{
 	  pc = new_pc;
-	  if (is_mips16_addr (pc))
-	    pc = unmake_mips16_addr (pc);
+	  if (is_compact_addr (pc))
+	    pc = unmake_compact_addr (pc);
 	}
     }
   while (pc != target_pc);
@@ -6390,6 +7809,23 @@ global_mips_abi (void)
   internal_error (__FILE__, __LINE__, _("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 (__FILE__, __LINE__, _("unknown compressed ISA string"));
+}
+
 static void
 mips_register_g_packet_guesses (struct gdbarch *gdbarch)
 {
@@ -6427,6 +7863,7 @@ mips_gdbarch_init (struct gdbarch_info i
   int elf_fpu_type = 0;
   const char **reg_names;
   struct mips_regnum mips_regnum, *regnum;
+  enum mips_isa mips_isa;
   int dspacc;
   int dspctl;
 
@@ -6720,6 +8157,17 @@ mips_gdbarch_init (struct gdbarch_info i
     fprintf_unfiltered (gdb_stdlog, "mips_gdbarch_init: mips_abi = %d\n",
 			mips_abi);
 
+  /* 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)
     fprintf_unfiltered (gdb_stdlog,
@@ -6825,6 +8273,7 @@ mips_gdbarch_init (struct gdbarch_info i
   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;
@@ -7050,6 +8499,8 @@ mips_gdbarch_init (struct gdbarch_info i
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
+  set_gdbarch_remote_breakpoint_from_pc (gdbarch,
+					 mips_remote_breakpoint_from_pc);
   set_gdbarch_adjust_breakpoint_address (gdbarch,
 					 mips_adjust_breakpoint_address);
 
@@ -7114,10 +8565,12 @@ mips_gdbarch_init (struct gdbarch_info i
   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)
@@ -7211,6 +8664,16 @@ show_mips_abi (struct ui_file *file,
     }
 }
 
+/* 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)
+{
+  fprintf_filtered (file, _("The compressed ISA encoding used is %s.\n"),
+		    value);
+}
+
 static void
 mips_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
 {
@@ -7327,6 +8790,23 @@ This option can be set to one of:\n\
 			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.  */
 
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.h	2012-05-19 00:27:31.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.h	2012-05-19 00:34:16.935626560 +0100
@@ -38,6 +38,14 @@ enum mips_abi
 /* Return the MIPS ABI associated with GDBARCH.  */
 enum mips_abi mips_abi (struct gdbarch *gdbarch);
 
+/* Base and compressed MIPS ISA variations.  */
+enum mips_isa
+  {
+    ISA_MIPS = -1,		/* mips_compression_string depends on it.  */
+    ISA_MIPS16,
+    ISA_MICROMIPS
+  };
+
 /* Return the MIPS ISA's register size.  Just a short cut to the BFD
    architecture's word size.  */
 extern int mips_isa_regsize (struct gdbarch *gdbarch);
@@ -77,6 +85,7 @@ struct gdbarch_tdep
   /* mips options */
   enum mips_abi mips_abi;
   enum mips_abi found_abi;
+  enum mips_isa mips_isa;
   enum mips_fpu_type mips_fpu_type;
   int mips_last_arg_regnum;
   int mips_last_fp_arg_regnum;
@@ -152,9 +161,17 @@ enum
 /* Single step based on where the current instruction will take us.  */
 extern int mips_software_single_step (struct frame_info *frame);
 
+/* Tell if the program counter value in MEMADDR is in a standard
+   MIPS function.  */
+extern int mips_pc_is_mips (bfd_vma memaddr);
+
 /* Tell if the program counter value in MEMADDR is in a MIPS16
    function.  */
-extern int mips_pc_is_mips16 (bfd_vma memaddr);
+extern int mips_pc_is_mips16 (struct gdbarch *gdbarch, bfd_vma memaddr);
+
+/* Tell if the program counter value in MEMADDR is in a microMIPS
+   function.  */
+extern int mips_pc_is_micromips (struct gdbarch *gdbarch, bfd_vma memaddr);
 
 /* Return the currently configured (or set) saved register size.  */
 extern unsigned int mips_abi_regsize (struct gdbarch *gdbarch);
Index: gdb-fsf-trunk-quilt/gdb/NEWS
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/NEWS	2012-05-19 00:27:31.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/NEWS	2012-05-19 00:34:16.935626560 +0100
@@ -3,6 +3,8 @@
 
 *** Changes since GDB 7.4
 
+* GDB now supports debugging microMIPS binaries.
+
 * The "info os" command on GNU/Linux can now display information on
   several new classes of objects managed by the operating system:
     "info os procgroups" lists process groups
@@ -160,6 +162,14 @@ HP OpenVMS ia64			ia64-hp-openvms*
 
 * New options
 
+set mips compression
+show mips compression
+  Select the compressed ISA encoding used in functions that have no symbol
+  information available.  The encoding can be set to either of:
+    mips16
+    micromips
+  and is updated automatically from ELF file flags if available.
+
 set breakpoint condition-evaluation
 show breakpoint condition-evaluation
   Control whether breakpoint conditions are evaluated by GDB ("host") or by


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]