public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] microMIPS support
@ 2012-04-24 21:18 Maciej W. Rozycki
  2012-04-25  6:20 ` Eli Zaretskii
                   ` (5 more replies)
  0 siblings, 6 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-24 21:18 UTC (permalink / raw)
  To: gdb-patches

Hi,

 Here's a change that adds support for debugging binaries containing 
microMIPS code.  There's not much to say about it except that it works. ;)  

 The usual stuff is added: a heuristic unwinder, function epilogue 
determiner and branch decoding, both for software single-stepping and for 
moving breakpoints out of delay slots.  New remote breakpoint kinds are 
defined so that the remote stub has a chance to know it's microMIPS code 
being handled and can pick the right software breakpoint instruction if 
needed.  A new command/setting lets the user pick either of the MIPS16 or 
the microMIPS ASE to be assumed by GDB for code that has no instruction 
set information available, e.g. debugging ROM firmware with no debug 
information, so that basic stuff like disassembly, breakpoints and 
instruction single-stepping works in that case.

 One technical note -- some MIPS16 changes were inevitable, specifically 
mips_single_step_through_delay made an incorrect assumption that MIPS16 
instructions have no delay slots (this is not true -- JAL, JALX, JALR and 
JR do, already handled correctly by mips16_instruction_has_delay_slot) 
that has now been fixed as the function was rewritten to support microMIPS 
delay slots.  With these changes MIPS16 support became a two-liner that 
made no sense to postpone to a separate change and on the other hand the 
new infrastructure relies so much on rewrites made elsewhere as a part of 
microMIPS support that fixing MIPS16 support here without the rest of 
microMIPS changes was infeasible.

 There are no regressions for o32, MIPS16/o32 or n64 multilibs with 
mips-sde-elf or mips-linux-gnu targets.  New microMIPS test results for 
these targets respectively look more or less like these:

                === gdb Summary ===

# of expected passes		14092
# of unexpected failures	214
# of unexpected successes	2
# of expected failures		50
# of known failures		58
# of unresolved testcases	5
# of untested testcases		41
# of unsupported tests		175

and:

                === gdb Summary ===

# of expected passes		14242
# of unexpected failures	1289
# of unexpected successes	2
# of expected failures		41
# of known failures		61
# of unresolved testcases	8
# of untested testcases		35
# of unsupported tests		162

which is not breathtaking, but lots if not most of these failures come 
from our issues with handling the ISA bit that is shared between MIPS16 
and microMIPS code and which I already mentioned here a while ago.  These 
results are somewhat worse than ones for o32 and n64 multilibs, but still 
better than MIPS16 ones.  I'll be addressing this shortly in a separate 
thread.

 This is a substantial change, so I'll wait a couple days before 
committing it in case anyone wants to comment on anything; there's some 
overlap with the recent MIPS16 changes being discussed (six rejects at the 
moment), so I won't go through the hassle of regenerating this diff to 
reorder it ahead of those changes and make it apply cleanly anyway.

2011-04-24  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_eabi_push_dummy_call): Handle microMIPS code.
	(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.

2011-04-24  Sandra Loosemore  <sandra@codesourcery.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	gdb/doc/
	* gdb.texinfo (MIPS): Document "set mips compression" and "show
	mips compression".
	(Architecture-Specific Protocol Details): Document MIPS
	breakpoint types.

  Maciej

gdb-micromips.diff
Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo	2012-04-24 20:57:21.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo	2012-04-24 20:58:23.645567943 +0100
@@ -20263,6 +20263,35 @@ 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 MIPS code compression
+Tell @value{GDBN} which MIPS compressed ISA 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 ISA encoding is @samp{mips16}, as executables
+containing 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 MIPS16 or microMIPS ISAs.  If these
+function-scope annotations are present, @value{GDBN} uses them in
+preference to the global compressed ISA encoding setting.
+
+@item show mips compression
+@kindex show mips compression
+Show the MIPS compressed ISA encoding used by @value{GDBN} to debug the
+inferior.
+
 @item set mipsfpu
 @itemx show mipsfpu
 @xref{MIPS Embedded, set mipsfpu}.
@@ -36521,6 +36550,26 @@ as @code{MIPS32}.
 
 @end table
 
+@subsubsection Breakpoint Kinds
+
+These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
+
+@table @r
+
+@item 2
+16-bit MIPS16 mode breakpoint.
+
+@item 3
+16-bit microMIPS mode breakpoint.
+
+@item 4
+32-bit standard MIPS mode breakpoint.
+
+@item 5
+32-bit 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-04-24 20:57:21.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c	2012-04-24 21:12:02.475563647 +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,19 @@ 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 *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 +265,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 | BSF_FUNCTION)) != BSF_FUNCTION)
+    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 +779,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 +1110,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.  */
@@ -1083,8 +1248,8 @@ mips_read_pc (struct regcache *regcache)
   ULONGEST pc;
   int regnum = mips_regnum (get_regcache_arch (regcache))->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 +1260,8 @@ mips_unwind_pc (struct gdbarch *gdbarch,
 
   pc = frame_unwind_register_signed
 	 (next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
-  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 +1271,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;
@@ -1145,33 +1310,48 @@ static void
 mips_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
   int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
-  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);
 }
 
@@ -1192,6 +1372,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)
 {
@@ -1236,7 +1473,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.  */
     {
@@ -1406,6 +1643,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
@@ -1540,8 +2047,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;
@@ -1596,7 +2103,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
@@ -1608,7 +2115,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
@@ -1641,7 +2148,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);
@@ -1681,12 +2188,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);
 }
@@ -1803,7 +2314,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
@@ -1834,13 +2346,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) */
@@ -1868,13 +2380,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
@@ -2127,8 +2639,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;
 }
@@ -2163,13 +2676,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.  */
 
@@ -2234,7 +3180,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;
@@ -2418,7 +3365,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)
@@ -2483,7 +3430,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;
 }
@@ -2519,7 +3466,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;
@@ -2656,8 +3603,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
@@ -2680,34 +3627,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;
@@ -2718,7 +3664,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
@@ -2793,6 +3739,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
@@ -2825,10 +3942,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 */
 }
@@ -2856,7 +3973,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 ();
 
@@ -2901,7 +4018,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;
 
@@ -2913,12 +4030,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;
 	      }
@@ -2936,6 +4054,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.  */
@@ -3093,14 +4272,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.  */
@@ -4192,8 +5371,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;
@@ -4494,10 +5673,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;
 	    }
 	}
@@ -4660,8 +5839,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;
@@ -5104,42 +6283,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
@@ -5178,8 +6347,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);
 }
@@ -5206,7 +6377,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 */
@@ -5222,6 +6393,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
@@ -5243,7 +6515,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;
@@ -5267,8 +6539,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);
 }
@@ -5417,15 +6691,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)
@@ -5476,15 +6755,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
@@ -5513,13 +6810,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 };
@@ -5540,6 +6853,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.  */
@@ -5547,18 +6897,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)
     {
@@ -5602,18 +6950,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)  */
@@ -5702,7 +7115,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;
@@ -5715,32 +7128,38 @@ mips_adjust_breakpoint_address (struct g
     }
   else
     {
+      int (*instruction_has_delay_slot) (struct gdbarch *, CORE_ADDR, int);
       struct minimal_symbol *sym;
       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
@@ -5885,7 +7304,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;
@@ -6187,24 +7606,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);
@@ -6358,6 +7777,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)
 {
@@ -6395,6 +7831,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;
 
@@ -6688,6 +8125,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,
@@ -6793,6 +8241,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;
@@ -7020,6 +8469,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);
 
@@ -7086,10 +8537,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)
@@ -7183,6 +8636,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)
 {
@@ -7299,6 +8762,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."), _("\
+Show the compressed ISA encoding used."), _("\
+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-04-24 20:57:21.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.h	2012-04-24 20:58:23.645567943 +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-04-24 20:57:21.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/NEWS	2012-04-24 20:58:23.645567943 +0100
@@ -3,6 +3,8 @@
 
 *** Changes since GDB 7.4
 
+* GDB now supports debugging microMIPS binaries.
+
 * GDB now supports reversible debugging on ARM, it allows you to
   debug basic ARM and THUMB instructions, and provides 
   record/replay support.  
@@ -124,6 +126,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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-24 21:18 [PATCH] microMIPS support Maciej W. Rozycki
@ 2012-04-25  6:20 ` Eli Zaretskii
  2012-04-26 13:54   ` Maciej W. Rozycki
  2012-04-25 13:13 ` Yao Qi
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-04-25  6:20 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Tue, 24 Apr 2012 21:29:01 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> 
>  Here's a change that adds support for debugging binaries containing 
> microMIPS code.  There's not much to say about it except that it works. ;)  

Thanks.

> +@item set mips compression @var{arg}
> +@kindex set mips compression
> +@cindex MIPS code compression

Please use lower-case "mips" in the @cindex entry as well.

> +Tell @value{GDBN} which MIPS compressed ISA 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 ISA encoding is @samp{mips16}, as executables
> +containing 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 MIPS16 or microMIPS ISAs.  If these
> +function-scope annotations are present, @value{GDBN} uses them in
> +preference to the global compressed ISA encoding setting.

I would suggest to use either @acronym{ISA} or @sc{isa} (and the same
with "MIPS16" and "MIPS"), since they will look better in print.  Try
both, produce the PDF version of the manual, and keep the one you like
best.

> +@subsubsection Breakpoint Kinds
> +
> +These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.

I'd prefer to have a @node here; subsections without a node are
possible, but are harder to find.

Also, a @cindex entry here would be good; think about someone who'd
like to find this information quickly by searching the index.

OK with those changes.

> +  add_setshow_enum_cmd ("compression", class_obscure, mips_compression_strings,
> +			&mips_compression_string, _("\
> +Set the compressed ISA encoding used."), _("\
> +Show the compressed ISA encoding used."), _("\

I'd mention microMIPS in the doc strings, as in

 Set the compressed ISA encoding used by microMIPS binaries.

> Index: gdb-fsf-trunk-quilt/gdb/NEWS
> ===================================================================
> --- gdb-fsf-trunk-quilt.orig/gdb/NEWS	2012-04-24 20:57:21.000000000 +0100
> +++ gdb-fsf-trunk-quilt/gdb/NEWS	2012-04-24 20:58:23.645567943 +0100
> @@ -3,6 +3,8 @@
>  
>  *** Changes since GDB 7.4
>  
> +* GDB now supports debugging microMIPS binaries.
> +
>  * GDB now supports reversible debugging on ARM, it allows you to
>    debug basic ARM and THUMB instructions, and provides 
>    record/replay support.  
> @@ -124,6 +126,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.
> +

This is OK.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-24 21:18 [PATCH] microMIPS support Maciej W. Rozycki
  2012-04-25  6:20 ` Eli Zaretskii
@ 2012-04-25 13:13 ` Yao Qi
  2012-04-25 15:57   ` Maciej W. Rozycki
  2012-04-25 15:54 ` Joel Brobecker
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2012-04-25 13:13 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

On 04/25/2012 04:29 AM, Maciej W. Rozycki wrote:
> +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);
> +}

Why don't we check `is_micromips_addr' first, and return early if it
returns true?  In this way, we can avoid some symbol lookups.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-24 21:18 [PATCH] microMIPS support Maciej W. Rozycki
  2012-04-25  6:20 ` Eli Zaretskii
  2012-04-25 13:13 ` Yao Qi
@ 2012-04-25 15:54 ` Joel Brobecker
  2012-04-25 17:18   ` Maciej W. Rozycki
  2012-04-26 18:38 ` Jan Kratochvil
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 43+ messages in thread
From: Joel Brobecker @ 2012-04-25 15:54 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

I could only scan the patch briefly for today, but noticed something
that caught my attention:

> +/* 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 *mips_compression_strings[] = {
> +  mips_compression_mips16,
> +  mips_compression_micromips,
> +  NULL
> +};

We usually provide this sort of feature a little differently: Instead
of 2 values that are adjusted automatically by the debugger, we provide
3 values: auto, mips16, and micromips. If auto, then the debugger has
to guess, possibly defaulting to mips16 if guessing did not work.
But if the user sets the setting to either of the non-auto values,
then the setting should be honored, even if the user is wrong.

This is usually implemented using two variables: One representing
the setting, and one representing the actual value.

This brings me to the next question: Could this be an objfile-specific
setting? In other words, is it possible to that the same executable
might have one objfile using micromips while another might still be
using mips16? (this might be the stupidest question of the week...).
If not, I still believe that this is at least an inferior-specific
property. With multi-inferior debugging being possible, I can see
how one debugs two programs using a different setting. In that case,
you need to store that information in the inferior private data
(I do that in ada-tasks, IIRC, for storing the layout of some data
structures).

(oops, style issue as well, the opening curly bracket should be
at the start of the next line - we've seen a lot of your style too,
but I think it should be fixed)

-- 
Joel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-25 13:13 ` Yao Qi
@ 2012-04-25 15:57   ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-25 15:57 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On Wed, 25 Apr 2012, Yao Qi wrote:

> > +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);
> > +}
> 
> Why don't we check `is_micromips_addr' first, and return early if it
> returns true?  In this way, we can avoid some symbol lookups.

 The choice of the sequence is deliberate and actually we used to do the 
checks in the opposite order for MIPS16 code until recently.  The reason 
is there is IMO no point in using the wrong ISA type where the ISA bit has 
been set incorrectly, e.g. the wrong software breakpoint instruction when 
someone says:

(gdb) break *0xdeadbeef

and the address actually refers MIPS32 code.  Also the opposite does not 
work, that is with the current arrangement the ISA bit of the MEMADDR 
argument may have been implicitly cleared elsewhere even when referencing 
a piece of compressed code and no numeric address actually used.

 I think code should behave as consistently as possible, and therefore for 
all the three ISAs any associated symbol's attribute is checked first, 
followed by checking the ISA bit specified explicitly in the address.  The 
latter case is only meant to cover addresses for which no symbol 
information of any kind could have been found.

 Does it clear your concern?

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-25 15:54 ` Joel Brobecker
@ 2012-04-25 17:18   ` Maciej W. Rozycki
  2012-04-25 18:12     ` Joel Brobecker
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-25 17:18 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

On Wed, 25 Apr 2012, Joel Brobecker wrote:

> I could only scan the patch briefly for today, but noticed something
> that caught my attention:
> 
> > +/* 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 *mips_compression_strings[] = {
> > +  mips_compression_mips16,
> > +  mips_compression_micromips,
> > +  NULL
> > +};
> 
> We usually provide this sort of feature a little differently: Instead
> of 2 values that are adjusted automatically by the debugger, we provide
> 3 values: auto, mips16, and micromips. If auto, then the debugger has
> to guess, possibly defaulting to mips16 if guessing did not work.
> But if the user sets the setting to either of the non-auto values,
> then the setting should be honored, even if the user is wrong.
> 
> This is usually implemented using two variables: One representing
> the setting, and one representing the actual value.

 I have been aware of that and decided the model does not fit.  Please 
note that this setting is a fall-back that's never used when you have an 
executable available.  If you do have an executable, then the ISA mode of 
compressed code is always known, because it's recorded in two places: 
individual symbol's ELF st_other flags, and globally, in the ELF file 
header.

 The latter is actually optional, in the sense that originally the 
compressed ISA was not recorded at all.  However all microMIPS objects 
must have the microMIPS flag set and therefore any compressed code in an 
executable that does not have any compressed flag set must be MIPS16 code 
in a legacy object.

 It's the st_other flags that's normally used by GDB to determine the 
compressed ISA kind, the ELF header flags are only checked for pieces of 
code that have no symbol information available for some reason.  And there 
is no point in overriding the ISA mode mandated by the executable, it must 
be clearly wrong, and there is really nothing to "guess" for GDB here -- 
all the required information is always available.

 Therefore the "auto" setting is meaningless -- you cannot infer any mode 
in the scope this setting has any use for, that is debugging with no 
executable (e.g. connecting to a live remote target), which is the very 
point of providing this setting at all.  Also note that this setting is 
"sticky", that is it's set from any executable selected.  If the 
executable is later on discarded, then the last setting is preserved 
assuming that if the user worked with one compressed ISA before it's more 
likely that they still use that ISA and not the other for non-debug code.

 Note this is a corner case too, but I decided it has to be handled 
somehow for robustness of GDB -- e.g. you may want to step-through 
power-on firmware you have no matching executable for via a JTAG probe 
for some reason.

> This brings me to the next question: Could this be an objfile-specific
> setting? In other words, is it possible to that the same executable
> might have one objfile using micromips while another might still be
> using mips16? (this might be the stupidest question of the week...).
> If not, I still believe that this is at least an inferior-specific
> property. With multi-inferior debugging being possible, I can see
> how one debugs two programs using a different setting. In that case,
> you need to store that information in the inferior private data
> (I do that in ada-tasks, IIRC, for storing the layout of some data
> structures).

 The question is of course fine and actually asked before in the process 
of adding microMIPS support to binutils.  There is no way for MIPS16 and 
microMIPS code to be present in a single executable.  We mandated this in 
binutils deciding that it would be a corner case not worth handling.

 Background information: the architecture does not permit the MIPS16 and 
the microMIPS ASE to be implemented in a single processor, one precludes 
the other (note that the architecture does permit an implementation that 
only supports the microMIPS mode and not the "traditional" standard MIPS 
mode, known since ~1985).  Therefore the only case where an executable 
could contain both MIPS16 and microMIPS code would be a piece of software 
that dynamically determines which of the two ASEs is present on a 
processor and switch to the right set of procedures on the fly (this is 
similar to what some power-on firmware does to handle both endiannesses 
with a single image on systems where you can switch the endianness on the 
fly, either with a physical switch or via some board logic).  We decided 
this is too much complication for little possibility of this case to ever 
matter for anyone.

 And personally I think the case of mixing MIPS16- and microMIPS-capable 
processors in a multi-processor systems (for multi-inferior debugging) is 
very unlikely too.  I don't think anyone has plans to support such a 
system, that would sort of be missing the point (the microMIPS ASE is 
intended to replace the MIPS16 ASE in deployments where code density 
matters), not even mentioning this would most likely require different 
base processor types too as I don't expect any single MIPS processor to 
support the choice between the MIPS16 ASE and the microMIPS ASE as RTL 
options (currently only the MIPS M14K and M14Kc processors support the 
microMIPS ASE and neither base architecture supports the MIPS16 ASE as an 
option).

 So until (or really unless) somebody comes with the requirement to 
support both the microMIPS and the MIPS16 ASE at a time in a single debug 
session let's keep this simple.

> (oops, style issue as well, the opening curly bracket should be
> at the start of the next line - we've seen a lot of your style too,
> but I think it should be fixed)

 Yes, I've changed that, thanks.  Actually the very preceding array uses 
the very style I did. ;)

 Actually I keep getting confused about the style expected for aggregate 
types, especially in the context of initialisers.  So for example is this 
correct:

static int
foo (void)
{
  struct
    {
      int i;
      void *p;
    }
  s[] =
    {
      { 1, &foo },
      { 2, NULL }
    };
}

or should that be written yet differently?  What if that's defined at the 
file scope:

struct bar
  {
    int i;
    void *p;
  }
s[] =
  {
    { 1, &foo },
    { 2, NULL }
  };

or:

struct bar
{
  int i;
  void *p;
}
s[] =
{
  { 1, &foo },
  { 2, NULL }
};

?  I recall seeing both styles (plus some variations), but my inclination 
is not to give indentation to curly brackets at the file level in any 
cases -- compare global functions vs nested functions (a GCC extension).

 Then this gets even weirder with C99's compound literals, e.g. this piece 
gets tricky:

void
baz(struct bar b[])
{
}

void
bax(void)
{
  baz ((struct bar[]) { { .i = 3, .p = &bax }, { .i = 4, .p = NULL } });
}

when you need to wrap the line (e.g. add third element), sigh...

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-25 17:18   ` Maciej W. Rozycki
@ 2012-04-25 18:12     ` Joel Brobecker
  2012-04-25 18:27       ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Joel Brobecker @ 2012-04-25 18:12 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> So until (or really unless) somebody comes with the requirement to 
> support both the microMIPS and the MIPS16 ASE at a time in a single debug 
> session let's keep this simple.

OK, I'm sold :).

>  Actually I keep getting confused about the style expected for aggregate 
> types, especially in the context of initialisers.  So for example is this 
> correct:
[...]
> or should that be written yet differently?  What if that's defined at the 
> file scope:

Yeah, I am not sure what the proper kosher style would be in this case,
or if this has been discussed and decided, but I would tend to say that
the same style should be used regardless of scope.

-- 
Joel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-25 18:12     ` Joel Brobecker
@ 2012-04-25 18:27       ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-25 18:27 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

On Wed, 25 Apr 2012, Joel Brobecker wrote:

> >  Actually I keep getting confused about the style expected for aggregate 
> > types, especially in the context of initialisers.  So for example is this 
> > correct:
> [...]
> > or should that be written yet differently?  What if that's defined at the 
> > file scope:
> 
> Yeah, I am not sure what the proper kosher style would be in this case,
> or if this has been discussed and decided, but I would tend to say that
> the same style should be used regardless of scope.

 I am unconvinced.  We make an exception for global functions and do not 
indent their brackets.  However we do indent nested (local) functions.  
Have a look at elf/dl-deps.c in glibc sources (that follow the same style 
that we do) for an example -- there's a nested "preload" function in 
"_dl_map_object_deps" and its indented just as any other entity would be 
(personally I would find an unindented nested block confusing).

 So why should we treat all the other kinds of entities differently?  
What's the rationale?  I think all file-scope entities look better 
unindented, not just functions.

 That's my personal view anyway, feel free to differ.  Though I have to 
admit my view is not particularly strong here and then TBH file-scope 
structures in the glibc source referred above are indeed indented, so I am 
not going to argue either way if there's any doubt.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-25  6:20 ` Eli Zaretskii
@ 2012-04-26 13:54   ` Maciej W. Rozycki
  2012-04-26 14:14     ` Eli Zaretskii
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-26 13:54 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Wed, 25 Apr 2012, Eli Zaretskii wrote:

> > +@item set mips compression @var{arg}
> > +@kindex set mips compression
> > +@cindex MIPS code compression
> 
> Please use lower-case "mips" in the @cindex entry as well.

 It is a proper name, why?  All the other places capitalise it correctly, 
e.g.:

@kindex set mips mask-address
@cindex MIPS addresses, masking

and likewise for other proper names, e.g. AIX.

> > +Tell @value{GDBN} which MIPS compressed ISA 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 ISA encoding is @samp{mips16}, as executables
> > +containing 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 MIPS16 or microMIPS ISAs.  If these
> > +function-scope annotations are present, @value{GDBN} uses them in
> > +preference to the global compressed ISA encoding setting.
> 
> I would suggest to use either @acronym{ISA} or @sc{isa} (and the same
> with "MIPS16" and "MIPS"), since they will look better in print.  Try
> both, produce the PDF version of the manual, and keep the one you like
> best.

 Hmm, there is no existing place that uses any formatting whatever for 
"MIPS" or any derivatives (see e.g. "MIPS ABI" just above), except from 
@code{MIPS32} used in a single place to refer to a packet format.  The 
same stands for other processor architectures or names of instruction 
sets.  I am not trying to say that I disagree with your suggestion as is, 
only asking why you think I should be making these changes to my patch?

 FWIW, I can't tell the difference between text rendered with no 
formatting and the @sc macro; @acronym yields a little bit smaller text 
that I actually like, but as I say, it seems to make little sense to me 
just to apply it here where the rest of the manual does not use it.

 And if we're going to apply such a bulk change to the manual, then it 
shouldn't matter if this change has been previously included here or not.  
As it stands I'd prefer to keep the formatting consistent through the 
manual.

> > +@subsubsection Breakpoint Kinds
> > +
> > +These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
> 
> I'd prefer to have a @node here; subsections without a node are
> possible, but are harder to find.
> 
> Also, a @cindex entry here would be good; think about someone who'd
> like to find this information quickly by searching the index.

 I copied the layout from the "Register Packet Format" subsubsection that 
immediately precedes; actually the whole section lacks any subnodes.  I 
now recall a similar discussion a while ago about another patch; this 
change originally predates that discussion.  Sorry for missing that.

 However in this case the whole section would have to be updated 
throughout, it does not make sense to have a subnode just for one of the 
subsubsections, and revamping the whole section does not belong to this 
change.

 And last but not least I am not even sure if splitting this particular 
section into subpages makes sense in the first place.  Nesting too deep 
can be frustrating too, and here you'd have to have two intermediate pages 
with node lists only for just a couple lines' worth of nodes.

 I think index references would better be added separately too -- these 
would be "ARM Breakpoint Kinds," "MIPS Register Packet Format" and "MIPS 
Breakpoint Kinds," respectively.

> OK with those changes.

 Well, as you can see I have troubles to agree, sorry.

 What I can do is pushing the change below on top of my microMIPS change.  
Or alternatively I can split it into two changes and apply changes to the 
existing pieces now and fold the microMIPS index entries into the 
microMIPS change -- whichever you might find more suitable.

> > +  add_setshow_enum_cmd ("compression", class_obscure, mips_compression_strings,
> > +			&mips_compression_string, _("\
> > +Set the compressed ISA encoding used."), _("\
> > +Show the compressed ISA encoding used."), _("\
> 
> I'd mention microMIPS in the doc strings, as in
> 
>  Set the compressed ISA encoding used by microMIPS binaries.

 Err, that's not the point of the setting in both aspects.  First, it's 
not specific to microMIPS code as its very purpose is to switch between 
MIPS16 and microMIPS encoding that's mutually exclusive.  Second, it's 
only used where no binary is available (usually selected with "file" or 
suchlike), e.g. ROM contents:

(gdb) target remote foo
(gdb) x/i $pc
(gdb) stepi

etc.  I agree the description is a bit lacking, but I have also decided 
the verbose output from:

(gdb) help set mips compression
(gdb) help show mips compression

(which is the same as I pasted in NEWS) is good enough.  Do you think it 
is not?

> > Index: gdb-fsf-trunk-quilt/gdb/NEWS
> > ===================================================================
> > --- gdb-fsf-trunk-quilt.orig/gdb/NEWS	2012-04-24 20:57:21.000000000 +0100
> > +++ gdb-fsf-trunk-quilt/gdb/NEWS	2012-04-24 20:58:23.645567943 +0100
> > @@ -3,6 +3,8 @@
> >  
> >  *** Changes since GDB 7.4
> >  
> > +* GDB now supports debugging microMIPS binaries.
> > +
> >  * GDB now supports reversible debugging on ARM, it allows you to
> >    debug basic ARM and THUMB instructions, and provides 
> >    record/replay support.  
> > @@ -124,6 +126,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.
> > +
> 
> This is OK.

 Thanks for your review.

  Maciej

2012-04-26  Maciej W. Rozycki  <macro@codesourcery.com>

	gdb/doc/
	* gdb.texinfo (Architecture-Specific Protocol Details): Add index 
	entries throughout.

gdb-doc-remote-arch-index.diff
Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo	2012-04-26 01:56:46.885629533 +0100
+++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo	2012-04-26 01:57:07.065637214 +0100
@@ -36507,6 +36507,8 @@ details of XML target descriptions for e
 @subsection ARM
 
 @subsubsection Breakpoint Kinds
+@cindex ARM breakpoint kinds
+@cindex breakpoint kinds, ARM
 
 These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
 
@@ -36526,6 +36528,8 @@ These breakpoint kinds are defined for t
 @subsection MIPS
 
 @subsubsection Register Packet Format
+@cindex MIPS register packet format
+@cindex register packet format, MIPS
 
 The following @code{g}/@code{G} packets have previously been defined.
 In the below, some thirty-two bit registers are transferred as
@@ -36551,6 +36555,8 @@ as @code{MIPS32}.
 @end table
 
 @subsubsection Breakpoint Kinds
+@cindex MIPS breakpoint kinds
+@cindex breakpoint kinds, MIPS
 
 These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
 

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 13:54   ` Maciej W. Rozycki
@ 2012-04-26 14:14     ` Eli Zaretskii
  2012-04-26 18:03       ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-04-26 14:14 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Thu, 26 Apr 2012 14:34:12 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
> 
> On Wed, 25 Apr 2012, Eli Zaretskii wrote:
> 
> > > +@item set mips compression @var{arg}
> > > +@kindex set mips compression
> > > +@cindex MIPS code compression
> > 
> > Please use lower-case "mips" in the @cindex entry as well.
> 
>  It is a proper name, why?  All the other places capitalise it correctly, 
> e.g.:
> 
> @kindex set mips mask-address
> @cindex MIPS addresses, masking
> 
> and likewise for other proper names, e.g. AIX.

Index entries should all start with lower-case letters, otherwise the
index sorting is unpredictable (in non-US locales).

> > I would suggest to use either @acronym{ISA} or @sc{isa} (and the same
> > with "MIPS16" and "MIPS"), since they will look better in print.  Try
> > both, produce the PDF version of the manual, and keep the one you like
> > best.
> 
>  Hmm, there is no existing place that uses any formatting whatever for 
> "MIPS" or any derivatives (see e.g. "MIPS ABI" just above), except from 
> @code{MIPS32} used in a single place to refer to a packet format.  The 
> same stands for other processor architectures or names of instruction 
> sets.  I am not trying to say that I disagree with your suggestion as is, 
> only asking why you think I should be making these changes to my patch?

Why not?  It's TRT to do.

>  FWIW, I can't tell the difference between text rendered with no 
> formatting and the @sc macro

In the PDF and DVI output, @sc{isa} should yield a smaller font.
Maybe you used @sc{ISA}?

> As it stands I'd prefer to keep the formatting consistent through the 
> manual.

There's no reason to consistently do the wrong thing.  Every 1000-mile
journey begins with the first step.

> > > +@subsubsection Breakpoint Kinds
> > > +
> > > +These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
> > 
> > I'd prefer to have a @node here; subsections without a node are
> > possible, but are harder to find.
> > 
> > Also, a @cindex entry here would be good; think about someone who'd
> > like to find this information quickly by searching the index.
> 
>  I copied the layout from the "Register Packet Format" subsubsection that 
> immediately precedes; actually the whole section lacks any subnodes.  I 
> now recall a similar discussion a while ago about another patch; this 
> change originally predates that discussion.  Sorry for missing that.
> 
>  However in this case the whole section would have to be updated 
> throughout, it does not make sense to have a subnode just for one of the 
> subsubsections, and revamping the whole section does not belong to this 
> change.

I didn't ask you to revamp the entire section.  Even if the rest of
the section will never be fixed, it still makes sense to not increase
the amount of node-less subsections.

>  And last but not least I am not even sure if splitting this particular 
> section into subpages makes sense in the first place.

As long as we keep the subsection, the printed version of the manual
will layout it separately anyway, even if the Info version doesn't.

> Nesting too deep can be frustrating too, and here you'd have to have
> two intermediate pages with node lists only for just a couple lines'
> worth of nodes.

I can go with removing the subsection altogether, if you don't feel
strongly with keeping it.

But if we keep the subsection, I'd like to have a node there.

>  I think index references would better be added separately too -- these 
> would be "ARM Breakpoint Kinds," "MIPS Register Packet Format" and "MIPS 
> Breakpoint Kinds," respectively.

Sorry, I don't follow.  Please elaborate.

> > OK with those changes.
> 
>  Well, as you can see I have troubles to agree, sorry.

How can I convince you?

> > > +  add_setshow_enum_cmd ("compression", class_obscure, mips_compression_strings,
> > > +			&mips_compression_string, _("\
> > > +Set the compressed ISA encoding used."), _("\
> > > +Show the compressed ISA encoding used."), _("\
> > 
> > I'd mention microMIPS in the doc strings, as in
> > 
> >  Set the compressed ISA encoding used by microMIPS binaries.
> 
>  Err, that's not the point of the setting in both aspects.  First, it's 
> not specific to microMIPS code as its very purpose is to switch between 
> MIPS16 and microMIPS encoding that's mutually exclusive.

OK, then how about "MIPS" instead of "microMIPS"?

> Second, it's 
> only used where no binary is available (usually selected with "file" or 
> suchlike), e.g. ROM contents:
> 
> (gdb) target remote foo
> (gdb) x/i $pc
> (gdb) stepi
> 
> etc.

Then how about "executables" or "executable code" instead of
"binaries"?

> I agree the description is a bit lacking, but I have also decided 
> the verbose output from:
> 
> (gdb) help set mips compression
> (gdb) help show mips compression
> 
> (which is the same as I pasted in NEWS) is good enough.  Do you think it 
> is not?

The thing is, commands that display only the first line of the doc
string, such as "apropos", will not show the rest of the text.  So the
user will just see

 set mips compression -- Set the compressed ISA encoding used.

This looks too vague to me.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 14:14     ` Eli Zaretskii
@ 2012-04-26 18:03       ` Maciej W. Rozycki
  2012-04-26 20:39         ` Eli Zaretskii
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-26 18:03 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Thu, 26 Apr 2012, Eli Zaretskii wrote:

> > > Please use lower-case "mips" in the @cindex entry as well.
> > 
> >  It is a proper name, why?  All the other places capitalise it correctly, 
> > e.g.:
> > 
> > @kindex set mips mask-address
> > @cindex MIPS addresses, masking
> > 
> > and likewise for other proper names, e.g. AIX.
> 
> Index entries should all start with lower-case letters, otherwise the
> index sorting is unpredictable (in non-US locales).

 OK, but is that a problem?  If a foreign locale uses a different sorting 
order, then it's exactly what the user of that locale expects, isn't it?  
Unless that sorting is broken for some reason, that is, but that's a 
problem to solve in the particular collator implementation, such as the C 
library in question.

 As far as I know writing MIPS in small letters when referred to the name 
of the architecture (as opposed to a keyword, such in GAS's `.set mips0' 
directive) is incorrect.

> > > I would suggest to use either @acronym{ISA} or @sc{isa} (and the same
> > > with "MIPS16" and "MIPS"), since they will look better in print.  Try
> > > both, produce the PDF version of the manual, and keep the one you like
> > > best.
> > 
> >  Hmm, there is no existing place that uses any formatting whatever for 
> > "MIPS" or any derivatives (see e.g. "MIPS ABI" just above), except from 
> > @code{MIPS32} used in a single place to refer to a packet format.  The 
> > same stands for other processor architectures or names of instruction 
> > sets.  I am not trying to say that I disagree with your suggestion as is, 
> > only asking why you think I should be making these changes to my patch?
> 
> Why not?  It's TRT to do.

 As the platform maintainer I can offer you to review the whole manual and 
adjust all the instances of "MIPS" (plus any variants and any related 
acronyms I'll spot) as a separate change.  I think it will be more 
productive and not really a lot of effort.

> >  FWIW, I can't tell the difference between text rendered with no 
> > formatting and the @sc macro
> 
> In the PDF and DVI output, @sc{isa} should yield a smaller font.
> Maybe you used @sc{ISA}?

 D'oh, that's what I did -- how did you know?  That however has prompted 
me to check the texinfo manual and it looks like @sc is actually not what 
fits here:

 "As shown here, we recommend using `@acronym' for actual acronyms
(*note acronym::), and reserving `@sc' for special cases where you want
small caps.  The output is not the same (`@acronym' prints in a smaller
text font, not the small caps font), but more importantly it describes
the actual text more accurately."

so I'd rather stick to @acronym (besides, "microMIPS" is supposed to use 
small letters for the first part and not small capitals).

 But then the application of @acronym to anything that is derived from 
"MIPS" is questionable, because "MIPS" is considered a proper name these 
days, not an acronym anymore (it's a trademark as well, and as such the 
word is an adjective, as are any derivatives, such as "MIPS16", etc.).  
Some probably don't even remember or know what the original acronym was 
supposed to expand to.  Of course there is no question about words such as 
ISA or ABI, these are true acronyms.

 So in the end it looks to me "MIPS", etc. should actually use no special 
formatting (except possibly where used as keywords), so while I can still 
go through the manual, I'll only adjust items like ISA or ASE.

> > As it stands I'd prefer to keep the formatting consistent through the 
> > manual.
> 
> There's no reason to consistently do the wrong thing.  Every 1000-mile
> journey begins with the first step.

 I think the right thing is to fix it all in one go first and only then 
enforce the new rule.  I think holding a useful functional change just 
because it keeps using the established practice in documentation is 
counter-productive.

> > > > +@subsubsection Breakpoint Kinds
> > > > +
> > > > +These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
> > > 
> > > I'd prefer to have a @node here; subsections without a node are
> > > possible, but are harder to find.
> > > 
> > > Also, a @cindex entry here would be good; think about someone who'd
> > > like to find this information quickly by searching the index.
> > 
> >  I copied the layout from the "Register Packet Format" subsubsection that 
> > immediately precedes; actually the whole section lacks any subnodes.  I 
> > now recall a similar discussion a while ago about another patch; this 
> > change originally predates that discussion.  Sorry for missing that.
> > 
> >  However in this case the whole section would have to be updated 
> > throughout, it does not make sense to have a subnode just for one of the 
> > subsubsections, and revamping the whole section does not belong to this 
> > change.
> 
> I didn't ask you to revamp the entire section.  Even if the rest of
> the section will never be fixed, it still makes sense to not increase
> the amount of node-less subsections.

 It makes no sense to me not to revamp the entire section -- the parent 
section will only have a reference to one of its child subsections only; 
that's missing the point IMHO.

> >  And last but not least I am not even sure if splitting this particular 
> > section into subpages makes sense in the first place.
> 
> As long as we keep the subsection, the printed version of the manual
> will layout it separately anyway, even if the Info version doesn't.

 I'm getting a continuous flow of text in the PDF version with no page 
breaks at section boundaries -- these I only get between whole chapters.

> > Nesting too deep can be frustrating too, and here you'd have to have
> > two intermediate pages with node lists only for just a couple lines'
> > worth of nodes.
> 
> I can go with removing the subsection altogether, if you don't feel
> strongly with keeping it.
> 
> But if we keep the subsection, I'd like to have a node there.

 It doesn't make sense to me to make this whole section flat, the matters 
described are distinct enough, I just can't seem convinced we need all 
these nodes here.

> >  I think index references would better be added separately too -- these 
> > would be "ARM Breakpoint Kinds," "MIPS Register Packet Format" and "MIPS 
> > Breakpoint Kinds," respectively.
> 
> Sorry, I don't follow.  Please elaborate.

 These are the three subsubsections in the section concerned 
(Architecture-Specific Protocol Details).  With my change in place two 
will be titled "Breakpoint Kinds" so I prepended their containing 
subsection names (ARM and MIPS) to the respective index entries.  
Likewise I can see no sense in having a generic index entry such as 
"Register Packet Format" for a reference to a platform-specific piece of 
text, so I have prepended the subsection (platform) name there too.

> > > OK with those changes.
> > 
> >  Well, as you can see I have troubles to agree, sorry.
> 
> How can I convince you?

 I don't know -- are you suggesting that I start inventing ways to 
convince myself?  I don't think that's going to work as it sort of 
conflicts with the point of view I have.  I am willing to get convinced if 
you give me good arguments of course.

> > > > +  add_setshow_enum_cmd ("compression", class_obscure, mips_compression_strings,
> > > > +			&mips_compression_string, _("\
> > > > +Set the compressed ISA encoding used."), _("\
> > > > +Show the compressed ISA encoding used."), _("\
> > > 
> > > I'd mention microMIPS in the doc strings, as in
> > > 
> > >  Set the compressed ISA encoding used by microMIPS binaries.
> > 
> >  Err, that's not the point of the setting in both aspects.  First, it's 
> > not specific to microMIPS code as its very purpose is to switch between 
> > MIPS16 and microMIPS encoding that's mutually exclusive.
> 
> OK, then how about "MIPS" instead of "microMIPS"?
> 
> > Second, it's 
> > only used where no binary is available (usually selected with "file" or 
> > suchlike), e.g. ROM contents:
> > 
> > (gdb) target remote foo
> > (gdb) x/i $pc
> > (gdb) stepi
> > 
> > etc.
> 
> Then how about "executables" or "executable code" instead of
> "binaries"?

 OK, that sounds like a plan to me -- how about:

"Set the compressed ISA encoding used by MIPS code."

then?  I think "executable code" is redundant, code is expected to be 
executable.

> > I agree the description is a bit lacking, but I have also decided 
> > the verbose output from:
> > 
> > (gdb) help set mips compression
> > (gdb) help show mips compression
> > 
> > (which is the same as I pasted in NEWS) is good enough.  Do you think it 
> > is not?
> 
> The thing is, commands that display only the first line of the doc
> string, such as "apropos", will not show the rest of the text.  So the

 Yes, I know.

> user will just see
> 
>  set mips compression -- Set the compressed ISA encoding used.
> 
> This looks too vague to me.

 Maybe, maybe not -- the name of the command itself already names the MIPS 
architecture, which is why I thought the description above should be 
enough.  I hope we can agree on the new proposal earlier on though.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-24 21:18 [PATCH] microMIPS support Maciej W. Rozycki
                   ` (2 preceding siblings ...)
  2012-04-25 15:54 ` Joel Brobecker
@ 2012-04-26 18:38 ` Jan Kratochvil
  2012-04-26 19:04   ` Maciej W. Rozycki
  2012-05-18 21:32 ` [PATCH] microMIPS support (Linux signal trampolines) Maciej W. Rozycki
  2012-05-18 23:47 ` [PATCH] microMIPS support Maciej W. Rozycki
  5 siblings, 1 reply; 43+ messages in thread
From: Jan Kratochvil @ 2012-04-26 18:38 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

Hello Maciej,

sure I have seen no MIPS arch bugs...


On Tue, 24 Apr 2012 22:29:01 +0200, Maciej W. Rozycki wrote:
[...]
> +/* 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 *mips_compression_strings[] = {

nitpick, be more readonly:

static const char *const mips_compression_strings[] = {


> +  mips_compression_mips16,
> +  mips_compression_micromips,
> +  NULL
> +};
[...]
> +/* 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));

(a) | -> ||
(b) I have found here it is best to expand logical expressions for the patch
    readers, despite author may see it more logical with the parentheses.

return !MSYMBOL_TARGET_FLAG_1 (msym) && !MSYMBOL_TARGET_FLAG_2 (msym);


> +}
[...]
> @@ -686,8 +779,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 };

It can be const.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 18:38 ` Jan Kratochvil
@ 2012-04-26 19:04   ` Maciej W. Rozycki
  2012-04-26 19:29     ` Jan Kratochvil
  2012-05-18 23:53     ` Maciej W. Rozycki
  0 siblings, 2 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-26 19:04 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

Hi Jan,

> sure I have seen no MIPS arch bugs...

 Yeah...

> > +/* 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 *mips_compression_strings[] = {
> 
> nitpick, be more readonly:
> 
> static const char *const mips_compression_strings[] = {

 Hmm, no objection to your suggestion per se, but is it allowed by C89?

> > +  mips_compression_mips16,
> > +  mips_compression_micromips,
> > +  NULL
> > +};
> [...]
> > +/* 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));
> 
> (a) | -> ||
> (b) I have found here it is best to expand logical expressions for the patch
>     readers, despite author may see it more logical with the parentheses.
> 
> return !MSYMBOL_TARGET_FLAG_1 (msym) && !MSYMBOL_TARGET_FLAG_2 (msym);

 Bitwise OR usually produces better code that has fewer branches (though 
hosts that support conditional move instructions may limit the impact here 
a bit), here's no harm to evaluate both sides of the expression in all 
cases.

> > @@ -686,8 +779,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 };
> 
> It can be const.

 One change at a time.

 This lookup can also be transformed into a simple 
three-assembly-instruction calculation, but it's called in enough places 
that I think it's cheaper in the current form.  But for this to stand this 
table should also be of the "unsigned char" type.

 Thanks for your notes.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 19:04   ` Maciej W. Rozycki
@ 2012-04-26 19:29     ` Jan Kratochvil
  2012-04-26 21:59       ` Maciej W. Rozycki
  2012-05-18 23:53     ` Maciej W. Rozycki
  1 sibling, 1 reply; 43+ messages in thread
From: Jan Kratochvil @ 2012-04-26 19:29 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

On Thu, 26 Apr 2012 21:03:35 +0200, Maciej W. Rozycki wrote:
> > static const char *const mips_compression_strings[] = {
> 
>  Hmm, no objection to your suggestion per se, but is it allowed by C89?

It is already used in GDB since:
	http://sourceware.org/ml/gdb-patches/2012-01/msg00973.html
	[obv] Code cleanup: add_setshow_enum_cmd: Make 1440 bytes of data segment read-only

I am not aware of any compatibility issue of it.



Thanks,
Jan

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 18:03       ` Maciej W. Rozycki
@ 2012-04-26 20:39         ` Eli Zaretskii
  2012-04-27 18:16           ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-04-26 20:39 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Thu, 26 Apr 2012 19:00:55 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
> 
> > Index entries should all start with lower-case letters, otherwise the
> > index sorting is unpredictable (in non-US locales).
> 
>  OK, but is that a problem?  If a foreign locale uses a different sorting 
> order, then it's exactly what the user of that locale expects, isn't it?  

Not if the Info files are then put into a release tarball and
distributed worldwide.

>  As far as I know writing MIPS in small letters when referred to the name 
> of the architecture (as opposed to a keyword, such in GAS's `.set mips0' 
> directive) is incorrect.

You could have "MIPS" not as the first word in the index entry, if you
must have it in caps.

>  As the platform maintainer I can offer you to review the whole manual and 
> adjust all the instances of "MIPS" (plus any variants and any related 
> acronyms I'll spot) as a separate change.  I think it will be more 
> productive and not really a lot of effort.

I will do that when I have time, thanks.

> so I'd rather stick to @acronym

Fine with me, I suggested to use either one.

>  So in the end it looks to me "MIPS", etc. should actually use no special 
> formatting (except possibly where used as keywords), so while I can still 
> go through the manual, I'll only adjust items like ISA or ASE.

I think @acronym{MIPS} looks nicer, but I won't insist on that.

> > > As it stands I'd prefer to keep the formatting consistent through the 
> > > manual.
> > 
> > There's no reason to consistently do the wrong thing.  Every 1000-mile
> > journey begins with the first step.
> 
>  I think the right thing is to fix it all in one go first and only then 
> enforce the new rule.  I think holding a useful functional change just 
> because it keeps using the established practice in documentation is 
> counter-productive.

Actually, _you_ are holding it, by continuously rejecting my requests
for changes.  The changes I asked for are not so extensive, so I
really don't understand why we are still arguing.

> > I didn't ask you to revamp the entire section.  Even if the rest of
> > the section will never be fixed, it still makes sense to not increase
> > the amount of node-less subsections.
> 
>  It makes no sense to me not to revamp the entire section

I won't object if you do revamp it, if you feel like it.  But I will
approve the patch even if you don't, because I think it's unfair to
ask you to fix what you didn't break.

> > > Nesting too deep can be frustrating too, and here you'd have to have
> > > two intermediate pages with node lists only for just a couple lines'
> > > worth of nodes.
> > 
> > I can go with removing the subsection altogether, if you don't feel
> > strongly with keeping it.
> > 
> > But if we keep the subsection, I'd like to have a node there.
> 
>  It doesn't make sense to me to make this whole section flat, the matters 
> described are distinct enough

I'm confused: you just said above that too deep nesting is not good,
now you are saying that NOT nesting will be too shallow?  Shouldn't
there be some middle ground between these two extremes?

> I just can't seem convinced we need all these nodes here.

Can I ask you to trust my experience on this one?  Having nodes makes
navigation inside Info easier.

> > >  I think index references would better be added separately too -- these 
> > > would be "ARM Breakpoint Kinds," "MIPS Register Packet Format" and "MIPS 
> > > Breakpoint Kinds," respectively.
> > 
> > Sorry, I don't follow.  Please elaborate.
> 
>  These are the three subsubsections in the section concerned 
> (Architecture-Specific Protocol Details).  With my change in place two 
> will be titled "Breakpoint Kinds" so I prepended their containing 
> subsection names (ARM and MIPS) to the respective index entries.  
> Likewise I can see no sense in having a generic index entry such as 
> "Register Packet Format" for a reference to a platform-specific piece of 
> text, so I have prepended the subsection (platform) name there too.

That's fine, thanks.

> > Then how about "executables" or "executable code" instead of
> > "binaries"?
> 
>  OK, that sounds like a plan to me -- how about:
> 
> "Set the compressed ISA encoding used by MIPS code."
> 
> then?

OK.

Thanks.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 19:29     ` Jan Kratochvil
@ 2012-04-26 21:59       ` Maciej W. Rozycki
  2012-04-27  7:11         ` Jan Kratochvil
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-26 21:59 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Thu, 26 Apr 2012, Jan Kratochvil wrote:

> > > static const char *const mips_compression_strings[] = {
> > 
> >  Hmm, no objection to your suggestion per se, but is it allowed by C89?
> 
> It is already used in GDB since:
> 	http://sourceware.org/ml/gdb-patches/2012-01/msg00973.html
> 	[obv] Code cleanup: add_setshow_enum_cmd: Make 1440 bytes of data segment read-only

 But it's your own change and there wasn't any discussion about it there, 
so I can't take it as an argument, sorry.

> I am not aware of any compatibility issue of it.

 But are you absolutely sure that it was a supported construct with C89 or 
are you only assuming having no counter-evidence?  Do you have a copy of 
the standard?  Unfortunately I don't or otherwise I would have checked 
myself and C99 doesn't note it in the list of major changes from the 
previous version of the standard (but then I wouldn't classify it as a 
major change).

 At the time I learnt C (some 18 years ago) that certainly wasn't a 
construct I had seen in any language reference I had available or was made 
aware of in any other way and I am fairly sure it's quite a recent 
addition.  I first heard of it in the 2000s only (and then well into).  
An equivalent construct that I am sure to be portable is:

typedef const char *ccharp;
const ccharp foo;

but I'm not sure that's maintainable -- too obfuscated in my view.

 AFAIK we still require our code to conform to C89 (fortunately not K&R 
anymore) or we could use lots of good stuff, starting from the long long 
type (so much needed for MIPS opcode tables in opcodes/ among others; we 
had a discussion in the context of MIPS segments not so long ago here as 
well, ending with a piece of convoluted code to avoid both the long long 
type and compiler warnings, depending on the configuration chosen), 
through designated initialisers (suddenly you stop losing track of your 
NULLs through your 50-member struct), etc.

 Any comments, anyone?

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 21:59       ` Maciej W. Rozycki
@ 2012-04-27  7:11         ` Jan Kratochvil
  2012-04-27 15:14           ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Jan Kratochvil @ 2012-04-27  7:11 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

On Thu, 26 Apr 2012 23:52:22 +0200, Maciej W. Rozycki wrote:
>  But are you absolutely sure that it was a supported construct with C89 or 
> are you only assuming having no counter-evidence?

(a) C89 == C90: http://en.wikipedia.org/wiki/C89_%28C_version%29#C89
(b) The suggested 'const' construct is compliant with 'gcc -std=c89 -pedantic'.
    This does not prove it is really C89 compliant but:
(c) GDB codebase is already not C90 compliant, at least not
    with 'gcc -std=c89 -pedantic', as discussed in the thread
    Re: [no-commit-intention] Naive unnamed fields for main_type
    http://sourceware.org/ml/gdb-patches/2012-02/msg00146.html

I checked according to C90 const array means const elements of the array.
And 'const type *var;' does not make 'var' const - my conclusion is qualifier
'const' is therefore independent for 'var' and the target type.


>  At the time I learnt C (some 18 years ago) that certainly wasn't a 
> construct I had seen in any language reference

I do not see any problem using const for an array, what specifically do you
see wrong here?


>  AFAIK we still require our code to conform to C89 (fortunately not K&R 
> anymore) or we could use lots of good stuff,

I agree.  I find const arrays compliant with C89.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-27  7:11         ` Jan Kratochvil
@ 2012-04-27 15:14           ` Maciej W. Rozycki
  2012-04-27 15:29             ` Pedro Alves
  2012-04-27 15:54             ` Tom Tromey
  0 siblings, 2 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-27 15:14 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Fri, 27 Apr 2012, Jan Kratochvil wrote:

> >  But are you absolutely sure that it was a supported construct with C89 or 
> > are you only assuming having no counter-evidence?
> 
> (a) C89 == C90: http://en.wikipedia.org/wiki/C89_%28C_version%29#C89
> (b) The suggested 'const' construct is compliant with 'gcc -std=c89 -pedantic'.
>     This does not prove it is really C89 compliant but:

 In the absence of an actual copy of the standard itself checking with a 
third-party known-C89/C90-only compiler would be better.

> (c) GDB codebase is already not C90 compliant, at least not
>     with 'gcc -std=c89 -pedantic', as discussed in the thread
>     Re: [no-commit-intention] Naive unnamed fields for main_type
>     http://sourceware.org/ml/gdb-patches/2012-02/msg00146.html

 These are merely bugs IMO, that should simply be fixed instead (and some 
are outside GDB, readline for one is not a part of GDB, just bundled for 
convenience, and optional, though I'd agree that using GDB's CLI without 
readline is a bit painful).  We shouldn't deliberately create new bugs on 
the basis we already have some. ;)

 As I say I'd be first happy to hear we can finally switch to C99.

> I checked according to C90 const array means const elements of the array.
> And 'const type *var;' does not make 'var' const - my conclusion is qualifier
> 'const' is therefore independent for 'var' and the target type.

"const type *var" is a pointer to a variable of "const type" type.
"type *const var" is a const pointer to a variable of "type" type.

> >  At the time I learnt C (some 18 years ago) that certainly wasn't a 
> > construct I had seen in any language reference
> 
> I do not see any problem using const for an array, what specifically do you
> see wrong here?

 Not a const array, but a const pointer.

> >  AFAIK we still require our code to conform to C89 (fortunately not K&R 
> > anymore) or we could use lots of good stuff,
> 
> I agree.  I find const arrays compliant with C89.

 But this is about an array of const pointers, I wouldn't see any problem 
with an array of const arithmetic-type elements.

 So far it's your word against mine, I'd like to hear from someone else 
too.  I'll accept whatever their decision will be.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-27 15:14           ` Maciej W. Rozycki
@ 2012-04-27 15:29             ` Pedro Alves
  2012-04-27 15:46               ` Maciej W. Rozycki
  2012-04-27 15:54             ` Tom Tromey
  1 sibling, 1 reply; 43+ messages in thread
From: Pedro Alves @ 2012-04-27 15:29 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Jan Kratochvil, gdb-patches

On 04/27/2012 03:48 PM, Maciej W. Rozycki wrote:

> "const type *var" is a pointer to a variable of "const type" type.
> "type *const var" is a const pointer to a variable of "type" type.
> 
>>> > >  At the time I learnt C (some 18 years ago) that certainly wasn't a 
>>> > > construct I had seen in any language reference
>> > 
>> > I do not see any problem using const for an array, what specifically do you
>> > see wrong here?
>  Not a const array, but a const pointer.


There's a c89 draft publicly available at:

http://nepsweb.co.uk/langstand/isoC/gordon/ansi-c89u.txt

And '3.5.4.1 Pointer declarators' describes const pointers.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-27 15:29             ` Pedro Alves
@ 2012-04-27 15:46               ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-27 15:46 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Jan Kratochvil, gdb-patches

On Fri, 27 Apr 2012, Pedro Alves wrote:

> There's a c89 draft publicly available at:
> 
> http://nepsweb.co.uk/langstand/isoC/gordon/ansi-c89u.txt
> 
> And '3.5.4.1 Pointer declarators' describes const pointers.

 Excellent, that's the bit I was missing, so Jan's suggestion is now in.  
Plus this is a good resource for any future reference, thanks for the 
pointer!  And last but not least thanks, everyone, for patience with my 
inquisitiveness.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-27 15:14           ` Maciej W. Rozycki
  2012-04-27 15:29             ` Pedro Alves
@ 2012-04-27 15:54             ` Tom Tromey
  1 sibling, 0 replies; 43+ messages in thread
From: Tom Tromey @ 2012-04-27 15:54 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Jan Kratochvil, gdb-patches

>>>>> "Maciej" == Maciej W Rozycki <macro@codesourcery.com> writes:

Maciej>  So far it's your word against mine, I'd like to hear from someone else 
Maciej> too.  I'll accept whatever their decision will be.

It is fine to use.  It is already used in many places in gdb.

barimba. grep 'static const char [*] *const' *.c|wc -l
76

Tom

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 20:39         ` Eli Zaretskii
@ 2012-04-27 18:16           ` Maciej W. Rozycki
  2012-04-27 18:24             ` Eli Zaretskii
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-04-27 18:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Thu, 26 Apr 2012, Eli Zaretskii wrote:

> > > Index entries should all start with lower-case letters, otherwise the
> > > index sorting is unpredictable (in non-US locales).
> > 
> >  OK, but is that a problem?  If a foreign locale uses a different sorting 
> > order, then it's exactly what the user of that locale expects, isn't it?  
> 
> Not if the Info files are then put into a release tarball and
> distributed worldwide.

 So may I suggest fixing the release process to use the intended locale 
instead (C or en_US, or whatever)?  Force it in a `make' rule or whatever.  
I think you'll get worse troubles than just an incorrect index order when 
an incorrect locale is selected.  It's the tools that should be fixed, not 
the text of the manual modified to work around any limitations.

> >  As far as I know writing MIPS in small letters when referred to the name 
> > of the architecture (as opposed to a keyword, such in GAS's `.set mips0' 
> > directive) is incorrect.
> 
> You could have "MIPS" not as the first word in the index entry, if you
> must have it in caps.

 I'll see what I can do about it then, if that satisfies you.  However I 
still have troubles to accept this requirement.  So if the first word had 
to be a city or person's name, you'd demand it to start with a small 
letter too?  I just don't buy it, sorry, there's something wrong with the 
process if you must make such requirements.

> >  As the platform maintainer I can offer you to review the whole manual and 
> > adjust all the instances of "MIPS" (plus any variants and any related 
> > acronyms I'll spot) as a separate change.  I think it will be more 
> > productive and not really a lot of effort.
> 
> I will do that when I have time, thanks.

 I offered you mine instead, but I won't insist.

> >  So in the end it looks to me "MIPS", etc. should actually use no special 
> > formatting (except possibly where used as keywords), so while I can still 
> > go through the manual, I'll only adjust items like ISA or ASE.
> 
> I think @acronym{MIPS} looks nicer, but I won't insist on that.

 I have regenerated both paragraphs added with the tag applied and 
actually I agree -- and contrary to documentation it works just fine for 
microMIPS.  So I decided to follow your suggestion even though @acronym is 
a misnomer here ("MIPS" and all the derivatives are really the same class 
of names as "Intel", or "Linux", or "NetBSD" are -- it's just that their
capitalisation is weird).  You've convinced me.

> > > I didn't ask you to revamp the entire section.  Even if the rest of
> > > the section will never be fixed, it still makes sense to not increase
> > > the amount of node-less subsections.
> >
> >  It makes no sense to me not to revamp the entire section
> 
> I won't object if you do revamp it, if you feel like it.  But I will
> approve the patch even if you don't, because I think it's unfair to
> ask you to fix what you didn't break.

 I appreciate that, but likewise it's my right to offer you doing it.

> > > > Nesting too deep can be frustrating too, and here you'd have to have
> > > > two intermediate pages with node lists only for just a couple lines'
> > > > worth of nodes.
> > > 
> > > I can go with removing the subsection altogether, if you don't feel
> > > strongly with keeping it.
> > > 
> > > But if we keep the subsection, I'd like to have a node there.
> > 
> >  It doesn't make sense to me to make this whole section flat, the matters 
> > described are distinct enough
> 
> I'm confused: you just said above that too deep nesting is not good,
> now you are saying that NOT nesting will be too shallow?  Shouldn't
> there be some middle ground between these two extremes?

 I am opposed to nesting nodes, not subsections (including, in particular, 
numbering the latters allow) -- which appear tangential to each other -- 
the formers are used for structuring by the Info format and the latters by 
PDF (for bookmarks, that clearly correspond to Info's nodes, but do not 
interfere with how the document itself is paginated).  And to breaking 
structure with partial changes -- that's no different to how I treat 
changes to code.

> > I just can't seem convinced we need all these nodes here.
> 
> Can I ask you to trust my experience on this one?  Having nodes makes
> navigation inside Info easier.

 I've used Info documentation for some 15 years now and I am not getting 
lost on pages like one concerned.  However I do recognise your experience 
may be different.  So I have reworked the section as below.  Do you really 
like the outcome, like an empty "ARM" subsection with a lone reference to 
its "Breakpoint Kinds" subsubsection?  I find it an unnecessary hassle to 
go through when reading the manual.

 Note that I had to use node names different to sub- and subsubsection 
titles to avoid duplicate names that are not supported for nodes.

 I still think your original suggestion to have such a reference in the 
MIPS subsection for one of its subsubsections, but not the other would be 
rather odd.

 So here goes the section rework (I have merged the node additions with 
index reference updates; I have applied your request to avoid capitalised 
proper names at the beginning for the ARM reference as well) followed by 
a diff to my microMIPS changes.  I hope you can accept these changes.

  Maciej

2012-04-26  Maciej W. Rozycki  <macro@codesourcery.com>

	gdb/doc/
	* gdb.texinfo (Architecture-Specific Protocol Details): Add nodes
	and index entries throughout.

gdb-doc-remote-arch.diff
Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo	2012-04-27 00:08:04.055561374 +0100
+++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo	2012-04-27 00:36:17.025444873 +0100
@@ -36475,9 +36475,21 @@ This section describes how the remote pr
 target architectures.  Also see @ref{Standard Target Features}, for
 details of XML target descriptions for each architecture.
 
+@menu
+* ARM Architecture-Specific Protocol Details::
+* MIPS Architecture-Specific Protocol Details::
+@end menu
+
+@node ARM Architecture-Specific Protocol Details
 @subsection ARM
 
+@menu
+* ARM Breakpoint Kinds::
+@end menu
+
+@node ARM Breakpoint Kinds
 @subsubsection Breakpoint Kinds
+@cindex breakpoint kinds, @acronym{ARM}
 
 These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
 
@@ -36494,9 +36506,16 @@ These breakpoint kinds are defined for t
 
 @end table
 
+@node MIPS Architecture-Specific Protocol Details
 @subsection MIPS
 
+@menu
+* MIPS Register Packet Format::
+@end menu
+
+@node MIPS Register Packet Format
 @subsubsection Register Packet Format
+@cindex register packet format, @acronym{MIPS}
 
 The following @code{g}/@code{G} packets have previously been defined.
 In the below, some thirty-two bit registers are transferred as

gdb-micromips-doc-fix.diff
Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo	2012-04-27 00:33:17.515562192 +0100
+++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo	2012-04-27 00:23:50.675579198 +0100
@@ -20265,8 +20265,9 @@ Show the MIPS ABI used by @value{GDBN} t
 
 @item set mips compression @var{arg}
 @kindex set mips compression
-@cindex MIPS code compression
-Tell @value{GDBN} which MIPS compressed ISA encoding is used by the
+@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
@@ -20275,22 +20276,24 @@ Otherwise this setting is automatically 
 provided by the executable.
 
 Possible values of @var{arg} are @samp{mips16} and @samp{micromips}.
-The default compressed ISA encoding is @samp{mips16}, as executables
-containing MIPS16 code frequently are not identified as such.
+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 MIPS16 or microMIPS ISAs.  If these
-function-scope annotations are present, @value{GDBN} uses them in
-preference to the global compressed ISA encoding setting.
+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 MIPS compressed ISA encoding used by @value{GDBN} to debug the
-inferior.
+Show the @acronym{MIPS} compressed @acronym{ISA} encoding used by
+@value{GDBN} to debug the inferior.
 
 @item set mipsfpu
 @itemx show mipsfpu
@@ -36540,6 +36543,7 @@ These breakpoint kinds are defined for t
 
 @menu
 * MIPS Register Packet Format::
+* MIPS Breakpoint Kinds::
 @end menu
 
 @node MIPS Register Packet Format
@@ -36569,23 +36573,25 @@ as @code{MIPS32}.
 
 @end table
 
+@node MIPS Breakpoint Kinds
 @subsubsection 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 MIPS16 mode breakpoint.
+16-bit @acronym{MIPS16} mode breakpoint.
 
 @item 3
-16-bit microMIPS mode breakpoint.
+16-bit @acronym{microMIPS} mode breakpoint.
 
 @item 4
-32-bit standard MIPS mode breakpoint.
+32-bit standard @acronym{MIPS} mode breakpoint.
 
 @item 5
-32-bit microMIPS mode breakpoint.
+32-bit @acronym{microMIPS} mode breakpoint.
 
 @end table
 
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c	2012-04-27 00:33:17.515562192 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c	2012-04-27 00:11:50.385601288 +0100
@@ -8769,8 +8769,8 @@ This option can be set to one of:\n\
      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."), _("\
-Show the compressed ISA encoding used."), _("\
+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\

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-27 18:16           ` Maciej W. Rozycki
@ 2012-04-27 18:24             ` Eli Zaretskii
       [not found]               ` <alpine.DEB.1.10.1204302334520.19835@tp.orcam.me.uk>
  0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-04-27 18:24 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Fri, 27 Apr 2012 18:45:56 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
> 
> On Thu, 26 Apr 2012, Eli Zaretskii wrote:
> 
> > > > Index entries should all start with lower-case letters, otherwise the
> > > > index sorting is unpredictable (in non-US locales).
> > > 
> > >  OK, but is that a problem?  If a foreign locale uses a different sorting 
> > > order, then it's exactly what the user of that locale expects, isn't it?  
> > 
> > Not if the Info files are then put into a release tarball and
> > distributed worldwide.
> 
>  So may I suggest fixing the release process to use the intended locale 
> instead (C or en_US, or whatever)?

I don't know enough about the GDB releases to tell if this is
practical.

Anyway, I try to keep all index entries start with a lower-case
letter.  This is more reliable than imposing a certain locale on the
environment where the release tarballs are made.

>  I'll see what I can do about it then, if that satisfies you.  However I 
> still have troubles to accept this requirement.  So if the first word had 
> to be a city or person's name, you'd demand it to start with a small 
> letter too?

We don't have person names or cities in the GDB manual.  A manual that
has many of these in the indices should probably consistently use
capitalization of the first word in the index entries.

> I just don't buy it, sorry, there's something wrong with the process
> if you must make such requirements.

I don't understand why it matters to you so much, sorry.

> > >  As the platform maintainer I can offer you to review the whole manual and 
> > > adjust all the instances of "MIPS" (plus any variants and any related 
> > > acronyms I'll spot) as a separate change.  I think it will be more 
> > > productive and not really a lot of effort.
> > 
> > I will do that when I have time, thanks.
> 
>  I offered you mine instead, but I won't insist.

Sorry, my misunderstanding.  If you want to do it, I'd appreciate
that.

>  I have regenerated both paragraphs added with the tag applied and 
> actually I agree -- and contrary to documentation it works just fine for 
> microMIPS.  So I decided to follow your suggestion even though @acronym is 
> a misnomer here ("MIPS" and all the derivatives are really the same class 
> of names as "Intel", or "Linux", or "NetBSD" are -- it's just that their
> capitalisation is weird).  You've convinced me.

Thank you.

> > > > I didn't ask you to revamp the entire section.  Even if the rest of
> > > > the section will never be fixed, it still makes sense to not increase
> > > > the amount of node-less subsections.
> > >
> > >  It makes no sense to me not to revamp the entire section
> > 
> > I won't object if you do revamp it, if you feel like it.  But I will
> > approve the patch even if you don't, because I think it's unfair to
> > ask you to fix what you didn't break.
> 
>  I appreciate that, but likewise it's my right to offer you doing it.

I accept the offer, thanks.

> Do you really like the outcome, like an empty "ARM" subsection with
> a lone reference to its "Breakpoint Kinds" subsubsection?  I find it
> an unnecessary hassle to go through when reading the manual.

There's no need to have empty subsections or nodes.  Please delete
those empty nodes.  All I asked was to have a node where you have a
subsection with some content.  There's no need to introduce
subsections or node with no content at all.

> I hope you can accept these changes.

I accept, but please remove the empty subsections/nodes.

Thanks.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
       [not found]               ` <alpine.DEB.1.10.1204302334520.19835@tp.orcam.me.uk>
@ 2012-05-02 16:39                 ` Eli Zaretskii
  2012-05-17 15:07                   ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-05-02 16:39 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Tue, 1 May 2012 00:45:06 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
> 
>  I've just checked a random book that I have handy, that is "MIPS R4000 
> Microprocessor User's Manual" and they mix cases in the index just fine on 
> the similar principles that I'm referring to here.  As does "The Cambridge 
> Grammar of the English Language" (a reference of a better authority 
> probably, but only available in hard copy, so you may not have one readily 
> available to check yourself).
> 
>  Therefore it doesn't appear to me starting index entries with a letter of 
> any particular case is a requirement in English literature (being a 
> non-native English speaker I have to rely on references).

I'm trying to follow the instructions in the Texinfo manual, not in
other books.  The Texinfo manual says to choose a convention for
capitalization of the first word of the index entries, and stick to
it.  (It does allow using caps for proper names.)

Anyway, I think this is a moot point now, because there are no index
entries in your patch whose first word may need capitalization.

> gdb/doc/gdb.texinfo:36670: `MIPS Breakpoint Kinds' has no Up field (perhaps incorrect sectioning?).
> 
> if I add a lone @node definition, or that plus:
> 
> gdb/doc/gdb.texinfo:36670: warning: unreferenced node `MIPS Breakpoint Kinds'.
> 
> if I place a @menu reference to that node in any of the upper sections.  

That's most probably because you added only some of the menus, not all
of them.  The minor variation of your patch below doesn't have this
problem, it produces an Info manual without any warnings or errors.

> I'll be pushing it in this form as soon as the MIPS16 manual
> function call change has been committed.

I believe committing a patch over objections of the responsible
maintainer is against the rules described in MAINTAINERS (as I
understand them).  So please don't do that.

Please use the slightly modified patch below instead.

(After you install your patch, I will follow up with a patch that
changes all occurrences of "MIPS" to use @acronym.  I already have
that patch ready on my box.)

Thanks.

=== modified file 'gdb/doc/gdb.texinfo'
--- gdb/doc/gdb.texinfo	2012-04-29 06:45:02 +0000
+++ gdb/doc/gdb.texinfo	2012-05-02 05:12:51 +0000
@@ -20377,6 +20377,38 @@
 @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}.
@@ -36589,9 +36621,21 @@
 target architectures.  Also see @ref{Standard Target Features}, for
 details of XML target descriptions for each architecture.
 
-@subsection ARM
-
-@subsubsection Breakpoint Kinds
+@menu
+* ARM-Specific Protocol Details::
+* MIPS-Specific Protocol Details::
+@end menu
+
+@node ARM-Specific Protocol Details
+@subsection @acronym{ARM}-specific Protocol Details
+
+@menu
+* ARM Breakpoint Kinds::
+@end menu
+
+@node ARM Breakpoint Kinds
+@subsubsection @acronym{ARM} Breakpoint Kinds
+@cindex breakpoint kinds, @acronym{ARM}
 
 These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
 
@@ -36604,37 +36648,64 @@
 32-bit Thumb mode (Thumb-2) breakpoint.
 
 @item 4
-32-bit ARM mode breakpoint.
+32-bit @acronym{ARM} mode breakpoint.
 
 @end table
 
-@subsection MIPS
-
-@subsubsection Register Packet Format
+@node MIPS-Specific Protocol Details
+@subsection @acronym{MIPS}-specific Protocol Details
+
+@menu
+* MIPS Register packet Format::
+* MIPS Breakpoint Kinds::
+@end menu
+
+@node MIPS Register packet Format
+@subsubsection @acronym{MIPS} Register Packet Format
 
 The following @code{g}/@code{G} packets have previously been defined.
 In the below, some thirty-two bit registers are transferred as
 sixty-four bits.  Those registers should be zero/sign extended (which?)
 to fill the space allocated.  Register bytes are transferred in target
 byte order.  The two nibbles within a register byte are transferred
-most-significant - least-significant.
+most-significant -- least-significant.
 
 @table @r
 
 @item MIPS32
-
 All registers are transferred as thirty-two bit quantities in the order:
 32 general-purpose; sr; lo; hi; bad; cause; pc; 32 floating-point
 registers; fsr; fir; fp.
 
 @item MIPS64
-
 All registers are transferred as sixty-four bit quantities (including
 thirty-two bit registers such as @code{sr}).  The ordering is the same
 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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-05-02 16:39                 ` Eli Zaretskii
@ 2012-05-17 15:07                   ` Maciej W. Rozycki
  2012-05-17 16:10                     ` Eli Zaretskii
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-05-17 15:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Wed, 2 May 2012, Eli Zaretskii wrote:

> > gdb/doc/gdb.texinfo:36670: `MIPS Breakpoint Kinds' has no Up field (perhaps incorrect sectioning?).
> > 
> > if I add a lone @node definition, or that plus:
> > 
> > gdb/doc/gdb.texinfo:36670: warning: unreferenced node `MIPS Breakpoint Kinds'.
> > 
> > if I place a @menu reference to that node in any of the upper sections.  
> 
> That's most probably because you added only some of the menus, not all
> of them.  The minor variation of your patch below doesn't have this
> problem, it produces an Info manual without any warnings or errors.

 I added only some of the menus by your explicit request.  You rejected my 
proposal that I made in response which added all of them and that was only 
trivially different to the version you have proposed now.

> > I'll be pushing it in this form as soon as the MIPS16 manual
> > function call change has been committed.
> 
> I believe committing a patch over objections of the responsible
> maintainer is against the rules described in MAINTAINERS (as I
> understand them).  So please don't do that.

 Certainly, next time I'll just drop any changes to the manual I disagree 
with.

> Please use the slightly modified patch below instead.

 Thanks for your proposal, even though my original concern about pages 
containing single-entry menus still stands.  This doesn't really matter 
however for two reasons, first and foremost because you have the power to 
override my objection to any changes to the manual, and second because it 
contains changes irrelevant to my change and as such I cannot integrate 
them.  Please split changes to the existing pieces of the manual off and 
commit them separately.  I'll extract the rest and fold into my change.

 I'll be doing the final round of testing of the microMIPS feature now, 
now that I made a final adjustment that I found necessary after 
investigation related to some changes I posted more recently.  I want to 
push the microMIPS change by the end of tomorrow at the latest.

> (After you install your patch, I will follow up with a patch that
> changes all occurrences of "MIPS" to use @acronym.  I already have
> that patch ready on my box.)

 I appreciate your effort.  Thank you.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-05-17 15:07                   ` Maciej W. Rozycki
@ 2012-05-17 16:10                     ` Eli Zaretskii
  2012-05-18 23:13                       ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-05-17 16:10 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Thu, 17 May 2012 16:06:37 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
> 
> > > if I place a @menu reference to that node in any of the upper sections.  
> > 
> > That's most probably because you added only some of the menus, not all
> > of them.  The minor variation of your patch below doesn't have this
> > problem, it produces an Info manual without any warnings or errors.
> 
>  I added only some of the menus by your explicit request.  You rejected my 
> proposal that I made in response which added all of them and that was only 
> trivially different to the version you have proposed now.

In that case, I apologize for my initial misunderstanding.

> > > I'll be pushing it in this form as soon as the MIPS16 manual
> > > function call change has been committed.
> > 
> > I believe committing a patch over objections of the responsible
> > maintainer is against the rules described in MAINTAINERS (as I
> > understand them).  So please don't do that.
> 
>  Certainly, next time I'll just drop any changes to the manual I disagree 
> with.

I'd prefer that next time we could arrive at an agreement sooner.

> > Please use the slightly modified patch below instead.
> 
>  Thanks for your proposal, even though my original concern about pages 
> containing single-entry menus still stands.  This doesn't really matter 
> however for two reasons, first and foremost because you have the power to 
> override my objection to any changes to the manual, and second because it 
> contains changes irrelevant to my change and as such I cannot integrate 
> them.  Please split changes to the existing pieces of the manual off and 
> commit them separately.  I'll extract the rest and fold into my change.

Which changes are irrelevant?  I tried deliberately to put aside any
such unrelated changes, but maybe I missed some.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support (Linux signal trampolines)
  2012-04-24 21:18 [PATCH] microMIPS support Maciej W. Rozycki
                   ` (3 preceding siblings ...)
  2012-04-26 18:38 ` Jan Kratochvil
@ 2012-05-18 21:32 ` Maciej W. Rozycki
  2012-05-18 22:25   ` Mark Kettenis
  2012-05-18 23:47 ` [PATCH] microMIPS support Maciej W. Rozycki
  5 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-05-18 21:32 UTC (permalink / raw)
  To: gdb-patches

Hi,

On Tue, 24 Apr 2012, Maciej W. Rozycki wrote:

>  Here's a change that adds support for debugging binaries containing 
> microMIPS code.  There's not much to say about it except that it works. ;)  

 And with the update below it works even better. :)

 The necessity for this change was revealed in the course of investigation 
related to my recent ISA bit submission.  It adds support for Linux signal 
trampolines encoded with the microMIPS instruction set.  Such trampolines 
are used by the Linux kernel if compiled as a microMIPS binary (even if 
the binary run/debugged itself contains no microMIPS code at all).  Until 
recently the reliability of such kernel binaries was not good enough for 
regression testing as they would typically not get through at all.  
Therefore the need for this change was not covered and escaped testing.  
It was revealed by code inspection.

 To see if we need to check whether the execution mode selected matches 
the given trampoline I have checked what the bit patterns of all the 
trampoline sequences decode to in the opposite instruction set.  This 
produced useless or at least unusual code in most cases, for example:

microMIPS/EB, o32 sigreturn, decoded as MIPS:
	30401017 	andi	zero,v0,0x1017
	00008b7c 	dsll32	s1,zero,0xd

MIPS/EL, o32 sigreturn, decoded as microMIPS:
	1017 2402 	addi	zero,s7,9218
	000c 0000 	sll	zero,t0,0x0

However in some corner cases reasonable code can mimic a trampoline, for 
example:

MIPS/EB, n32 rt_sigreturn, decoded as microMIPS:
	2402      	sll	s0,s0,1
	1843 0000 	sb	v0,0(v1)
	000c 0f3c 	jr	t0

-- here the first instruction is a 16-bit one making things nastier even 
as there are some other microMIPS instructions whose first 16-bit halfword 
is 0x000c and therefore matches this whole trampoline pattern.

 To overcome this problem I have decided the signal trampoline unwinder 
has to ask the platform backend whether it can apply a given trampoline 
pattern to the code location being concerned or not.  Anticipating the 
acceptance of the ISA bit proposal I decided the handler not to merely be 
a predicate, but also to be able to provide an adjusted PC if required.  
I decided that returning zero will mean that the trampoline pattern is not 
applicable and any other value is the adjusted PC to use; a handler may 
return the value requested if the trampoline pattern and the PC requested 
as-is are both accepted.

 This changes the semantics of the trampoline unwinder a bit in that the 
zero PC now has a special value.  I think this should be safe as a NULL 
pointer is generally supposed to be invalid.  Let me know if you think 
that could cause any troubles (the zero PC serves as a frame chain 
termination mark in some ABIs, including the MIPS ABI; I have a vague 
recollection that it is actually already caught elsewhere, but couldn't 
track that place down easily).

 A corresponding change will be required to the ISA bit proposal that I 
shall send separately -- the signal trampoline unwinder is a piece of 
generic code that interpretes the instruction stream (hopefully this is 
the only such place across GDB), so it has to see the ISA bit stripped off 
which the change below doesn't do for obvious reasons.

 Also obviously, if the ISA bit was stripped off from the PC as execution 
stopped in an actual trampoline, then we'll never have a chance to know 
that we stopped in the microMIPS mode in the first place as the trampoline 
will not have any symbol information associated and by now the ISA bit has 
been lost.  Which really means the change below will only make sense once 
the ISA bit proposal has got in.

 I'll be pushing this update through testing now.  I don't expect any 
problems, the change is mostly mechanical (as noted before microMIPS 
instructions, similarly to MIPS16 ones, are sequences of halfwords, hence 
the different arrangement of the instruction patterns used; POOL32A is the 
name of the major opcode the SYSCALL instruction is assigned to, that 
takes the upper six bits and happens to be all-zeros, the rest of the 
halfword is the SYSCALL immediate "argument" that is all-zeros too).

 Given that this change touches generic parts, the note about the ISA bit 
above, and that the original microMIPS change has worked correctly for 
many months now (especially given that microMIPS Linux kernel binaries may 
have only recently become usable), I decided I would be treating these two 
patches as separate and will therefore commit the microMIPS patch in its 
original form straight away.

 Meanwhile I'll be happy to answer any questions.

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

	gdb/
	* tramp-frame.h (tramp_frame): Add validate member.
	* tramp-frame.c (tramp_frame_start): Validate trampoline before
	scanning.
	* mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro.
	(MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise.
	(mips_linux_o32_sigframe): Initialize validate member.
	(mips_linux_o32_rt_sigframe): Likewise.
	(mips_linux_n32_rt_sigframe): Likewise.
	(mips_linux_n64_rt_sigframe): Likewise.
	(micromips_linux_o32_sigframe): New variable.
	(micromips_linux_o32_rt_sigframe): Likewise.
	(micromips_linux_n32_rt_sigframe): Likewise.
	(micromips_linux_n64_rt_sigframe): Likewise.
	(mips_linux_o32_sigframe_init): Handle microMIPS trampolines.
	(mips_linux_n32n64_sigframe_init): Likewise.
	(mips_linux_sigframe_validate): New function.
	(micromips_linux_sigframe_validate): Likewise.
	(mips_linux_init_abi): Install microMIPS trampoline unwinders.

  Maciej

gdb-micromips-linux-sigtramp.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.c	2012-05-18 19:46:29.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c	2012-05-18 20:41:04.625560181 +0100
@@ -800,6 +800,14 @@ static void mips_linux_n32n64_sigframe_i
 					     struct trad_frame_cache *this_cache,
 					     CORE_ADDR func);
 
+static CORE_ADDR mips_linux_sigframe_validate (const struct tramp_frame *self,
+					       struct frame_info *this_frame,
+					       CORE_ADDR pc);
+
+static CORE_ADDR micromips_linux_sigframe_validate (const struct tramp_frame *self,
+						    struct frame_info *this_frame,
+						    CORE_ADDR pc);
+
 #define MIPS_NR_LINUX 4000
 #define MIPS_NR_N64_LINUX 5000
 #define MIPS_NR_N32_LINUX 6000
@@ -815,6 +823,10 @@ static void mips_linux_n32n64_sigframe_i
 #define MIPS_INST_LI_V0_N32_RT_SIGRETURN 0x24020000 + MIPS_NR_N32_rt_sigreturn
 #define MIPS_INST_SYSCALL 0x0000000c
 
+#define MICROMIPS_INST_LI_V0 0x3040
+#define MICROMIPS_INST_POOL32A 0x0000
+#define MICROMIPS_INST_SYSCALL 0x8b7c
+
 static const struct tramp_frame mips_linux_o32_sigframe = {
   SIGTRAMP_FRAME,
   4,
@@ -823,7 +835,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_o32_sigframe_init
+  mips_linux_o32_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_o32_rt_sigframe = {
@@ -833,7 +846,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_LI_V0_RT_SIGRETURN, -1 },
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 } },
-  mips_linux_o32_sigframe_init
+  mips_linux_o32_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_n32_rt_sigframe = {
@@ -844,7 +858,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_n32n64_sigframe_init
+  mips_linux_n32n64_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_n64_rt_sigframe = {
@@ -855,7 +870,63 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_n32n64_sigframe_init
+  mips_linux_n32n64_sigframe_init,
+  mips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_o32_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_o32_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_o32_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 } },
+  mips_linux_o32_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_n32_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_N32_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_n32n64_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_N64_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_n32n64_sigframe_init,
+  micromips_linux_sigframe_validate
 };
 
 /* *INDENT-OFF* */
@@ -942,7 +1013,8 @@ mips_linux_o32_sigframe_init (const stru
   const struct mips_regnum *regs = mips_regnum (gdbarch);
   CORE_ADDR regs_base;
 
-  if (self == &mips_linux_o32_sigframe)
+  if (self == &mips_linux_o32_sigframe
+      || self == &micromips_linux_o32_sigframe)
     sigcontext_base = frame_sp + SIGFRAME_SIGCONTEXT_OFFSET;
   else
     sigcontext_base = frame_sp + RTSIGFRAME_SIGCONTEXT_OFFSET;
@@ -1107,7 +1179,8 @@ mips_linux_n32n64_sigframe_init (const s
   CORE_ADDR sigcontext_base;
   const struct mips_regnum *regs = mips_regnum (gdbarch);
 
-  if (self == &mips_linux_n32_rt_sigframe)
+  if (self == &mips_linux_n32_rt_sigframe
+      || self == &micromips_linux_n32_rt_sigframe)
     sigcontext_base = frame_sp + N32_SIGFRAME_SIGCONTEXT_OFFSET;
   else
     sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET;
@@ -1151,6 +1224,22 @@ mips_linux_n32n64_sigframe_init (const s
   trad_frame_set_id (this_cache, frame_id_build (frame_sp, func));
 }
 
+static CORE_ADDR
+mips_linux_sigframe_validate (const struct tramp_frame *self,
+			      struct frame_info *this_frame,
+			      CORE_ADDR pc)
+{
+  return mips_pc_is_mips (pc) ? pc : 0;
+}
+
+static CORE_ADDR
+micromips_linux_sigframe_validate (const struct tramp_frame *self,
+				   struct frame_info *this_frame,
+				   CORE_ADDR pc)
+{
+  return mips_pc_is_micromips (get_frame_arch (this_frame), pc) ? pc : 0;
+}
+
 /* Implement the "write_pc" gdbarch method.  */
 
 static void
@@ -1254,6 +1343,9 @@ mips_linux_init_abi (struct gdbarch_info
 	                                mips_linux_get_longjmp_target);
 	set_solib_svr4_fetch_link_map_offsets
 	  (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+	tramp_frame_prepend_unwinder (gdbarch, &micromips_linux_o32_sigframe);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_o32_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-o32-linux.xml");
@@ -1269,6 +1361,8 @@ mips_linux_init_abi (struct gdbarch_info
 	   except that the quiet/signalling NaN bit is reversed (GDB
 	   does not distinguish between quiet and signalling NaNs).  */
 	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_n32_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-n32-linux.xml");
 	break;
@@ -1283,6 +1377,8 @@ mips_linux_init_abi (struct gdbarch_info
 	   except that the quiet/signalling NaN bit is reversed (GDB
 	   does not distinguish between quiet and signalling NaNs).  */
 	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_n64_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-n64-linux.xml");
 	break;
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.c	2012-02-24 15:23:42.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.c	2012-05-18 20:03:53.775469792 +0100
@@ -87,6 +87,12 @@ tramp_frame_start (const struct tramp_fr
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int ti;
 
+  /* Check if we can use this trampoline.  */
+  if (tramp->validate)
+    pc = tramp->validate (tramp, this_frame, pc);
+  if (pc == 0)
+    return 0;
+
   /* Search through the trampoline for one that matches the
      instruction sequence around PC.  */
   for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.h	2012-02-24 15:23:42.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.h	2012-05-18 19:56:11.745630232 +0100
@@ -69,6 +69,12 @@ struct tramp_frame
 		struct frame_info *this_frame,
 		struct trad_frame_cache *this_cache,
 		CORE_ADDR func);
+  /* Check if the tramp-frame is valid for the PC requested.  Return
+     the address to check the instruction sequence against if so,
+     otherwise zero.  If this is NULL, then any PC is valid.  */
+  CORE_ADDR (*validate) (const struct tramp_frame *self,
+			 struct frame_info *this_frame,
+			 CORE_ADDR pc);
 };
 
 void tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support (Linux signal trampolines)
  2012-05-18 21:32 ` [PATCH] microMIPS support (Linux signal trampolines) Maciej W. Rozycki
@ 2012-05-18 22:25   ` Mark Kettenis
  2012-05-21 14:33     ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Mark Kettenis @ 2012-05-18 22:25 UTC (permalink / raw)
  To: macro; +Cc: gdb-patches

> Date: Fri, 18 May 2012 22:31:45 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
>
>  To see if we need to check whether the execution mode selected matches 
> the given trampoline I have checked what the bit patterns of all the 
> trampoline sequences decode to in the opposite instruction set.  This 
> produced useless or at least unusual code in most cases, for example:
> 
> microMIPS/EB, o32 sigreturn, decoded as MIPS:
> 	30401017 	andi	zero,v0,0x1017
> 	00008b7c 	dsll32	s1,zero,0xd
> 
> MIPS/EL, o32 sigreturn, decoded as microMIPS:
> 	1017 2402 	addi	zero,s7,9218
> 	000c 0000 	sll	zero,t0,0x0
> 
> However in some corner cases reasonable code can mimic a trampoline, for 
> example:
> 
> MIPS/EB, n32 rt_sigreturn, decoded as microMIPS:
> 	2402      	sll	s0,s0,1
> 	1843 0000 	sb	v0,0(v1)
> 	000c 0f3c 	jr	t0
> 
> -- here the first instruction is a 16-bit one making things nastier even 
> as there are some other microMIPS instructions whose first 16-bit halfword 
> is 0x000c and therefore matches this whole trampoline pattern.

On some OSes the signal trampolines are guaranteed to have a certain
alignment.  Is that the case for MIPS Linux as well perhaps?  Or would
that not help you?

> Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.c
> ===================================================================
> --- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.c	2012-02-24 15:23:42.000000000 +0000
> +++ gdb-fsf-trunk-quilt/gdb/tramp-frame.c	2012-05-18 20:03:53.775469792 +0100
> @@ -87,6 +87,12 @@ tramp_frame_start (const struct tramp_fr
>    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>    int ti;
>  
> +  /* Check if we can use this trampoline.  */
> +  if (tramp->validate)
> +    pc = tramp->validate (tramp, this_frame, pc);
> +  if (pc == 0)
> +    return 0;

I suppose chances are small we'll ever have a platform with
trampolines at address 0, but nevertheless, wouldn't it be more
correct to write

  if (tramp->validate)
    {
      pc = tramp->validate (tramp, this_frame, pc);
      if (pc == 0)
        return 0;
    }

as you're checking for the magic return value?

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-05-17 16:10                     ` Eli Zaretskii
@ 2012-05-18 23:13                       ` Maciej W. Rozycki
  2012-05-19  8:20                         ` Eli Zaretskii
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-05-18 23:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Thu, 17 May 2012, Eli Zaretskii wrote:

> >  I added only some of the menus by your explicit request.  You rejected my 
> > proposal that I made in response which added all of them and that was only 
> > trivially different to the version you have proposed now.
> 
> In that case, I apologize for my initial misunderstanding.

 Accepted, thank you.

> >  Certainly, next time I'll just drop any changes to the manual I disagree 
> > with.
> 
> I'd prefer that next time we could arrive at an agreement sooner.

 Me too, however I can't guarantee we'll always agree just as I couldn't 
agree with you on this occasion.  In which case I'd rather keep the 
functional bits and let you do with the corresponding manual updates 
whatever you want to, than drop everything.

> >  Thanks for your proposal, even though my original concern about pages 
> > containing single-entry menus still stands.  This doesn't really matter 
> > however for two reasons, first and foremost because you have the power to 
> > override my objection to any changes to the manual, and second because it 
> > contains changes irrelevant to my change and as such I cannot integrate 
> > them.  Please split changes to the existing pieces of the manual off and 
> > commit them separately.  I'll extract the rest and fold into my change.
> 
> Which changes are irrelevant?  I tried deliberately to put aside any
> such unrelated changes, but maybe I missed some.

 I have now extracted them and provided below, for a reference.  I have 
now committed them assuming that anything you have proposed has been 
self-approved.  I'll be providing the rest with the final version of the 
microMIPS change separately as soon as I have committed it straight away.

  Maciej

2011-05-18  Eli Zaretskii  <eliz@gnu.org>

	gdb/doc/
	* gdb.texinfo (Architecture-Specific Protocol Details): Define
	nodes for subsections.  Add @acronym mark-ups and adjust 
	formatting.

gdb-doc-acronym.diff
Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo	2012-05-18 23:22:56.135560932 +0100
+++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo	2012-05-18 23:24:04.235631195 +0100
@@ -36849,9 +36849,21 @@ This section describes how the remote pr
 target architectures.  Also see @ref{Standard Target Features}, for
 details of XML target descriptions for each architecture.
 
-@subsection ARM
+@menu
+* ARM-Specific Protocol Details::
+* MIPS-Specific Protocol Details::
+@end menu
 
-@subsubsection Breakpoint Kinds
+@node ARM-Specific Protocol Details
+@subsection @acronym{ARM}-specific Protocol Details
+
+@menu
+* ARM Breakpoint Kinds::
+@end menu
+
+@node ARM Breakpoint Kinds
+@subsubsection @acronym{ARM} Breakpoint Kinds
+@cindex breakpoint kinds, @acronym{ARM}
 
 These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
 
@@ -36864,31 +36876,35 @@ These breakpoint kinds are defined for t
 32-bit Thumb mode (Thumb-2) breakpoint.
 
 @item 4
-32-bit ARM mode breakpoint.
+32-bit @acronym{ARM} mode breakpoint.
 
 @end table
 
-@subsection MIPS
+@node MIPS-Specific Protocol Details
+@subsection @acronym{MIPS}-specific Protocol Details
 
-@subsubsection Register Packet Format
+@menu
+* MIPS Register packet Format::
+@end menu
+
+@node MIPS Register packet Format
+@subsubsection @acronym{MIPS} Register Packet Format
 
 The following @code{g}/@code{G} packets have previously been defined.
 In the below, some thirty-two bit registers are transferred as
 sixty-four bits.  Those registers should be zero/sign extended (which?)
 to fill the space allocated.  Register bytes are transferred in target
 byte order.  The two nibbles within a register byte are transferred
-most-significant - least-significant.
+most-significant -- least-significant.
 
 @table @r
 
 @item MIPS32
-
 All registers are transferred as thirty-two bit quantities in the order:
 32 general-purpose; sr; lo; hi; bad; cause; pc; 32 floating-point
 registers; fsr; fir; fp.
 
 @item MIPS64
-
 All registers are transferred as sixty-four bit quantities (including
 thirty-two bit registers such as @code{sr}).  The ordering is the same
 as @code{MIPS32}.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-24 21:18 [PATCH] microMIPS support Maciej W. Rozycki
                   ` (4 preceding siblings ...)
  2012-05-18 21:32 ` [PATCH] microMIPS support (Linux signal trampolines) Maciej W. Rozycki
@ 2012-05-18 23:47 ` Maciej W. Rozycki
  2012-05-19  8:52   ` Eli Zaretskii
  5 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-05-18 23:47 UTC (permalink / raw)
  To: gdb-patches

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

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-04-26 19:04   ` Maciej W. Rozycki
  2012-04-26 19:29     ` Jan Kratochvil
@ 2012-05-18 23:53     ` Maciej W. Rozycki
  1 sibling, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-05-18 23:53 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Thu, 26 Apr 2012, Maciej W. Rozycki wrote:

> > > @@ -686,8 +779,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 };
> > 
> > It can be const.
> 
>  One change at a time.
> 
>  This lookup can also be transformed into a simple 
> three-assembly-instruction calculation, but it's called in enough places 
> that I think it's cheaper in the current form.  But for this to stand this 
> table should also be of the "unsigned char" type.

 I have applied the change below now too.

  Maciej

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

	gdb/
	* mips-tdep.c (mips_reg3_to_reg): Optimize storage.

gdb-mips-reg3.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c	2012-04-27 19:05:14.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c	2012-04-27 19:34:09.795560276 +0100
@@ -781,7 +781,7 @@ mips_ax_pseudo_register_push_stack (stru
 }
 
 /* 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 };
+static const signed char mips_reg3_to_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
 
 /* Heuristic_proc_start may hunt through the text section for a long
    time across a 2400 baud serial line.  Allows the user to limit this

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-05-18 23:13                       ` Maciej W. Rozycki
@ 2012-05-19  8:20                         ` Eli Zaretskii
  0 siblings, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2012-05-19  8:20 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Sat, 19 May 2012 00:12:42 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
> 
> > >  Thanks for your proposal, even though my original concern about pages 
> > > containing single-entry menus still stands.  This doesn't really matter 
> > > however for two reasons, first and foremost because you have the power to 
> > > override my objection to any changes to the manual, and second because it 
> > > contains changes irrelevant to my change and as such I cannot integrate 
> > > them.  Please split changes to the existing pieces of the manual off and 
> > > commit them separately.  I'll extract the rest and fold into my change.
> > 
> > Which changes are irrelevant?  I tried deliberately to put aside any
> > such unrelated changes, but maybe I missed some.
> 
>  I have now extracted them and provided below, for a reference.

Thanks.  These are part of converting the entire section to using
nodes, so I considered them a part of the rest.

> I have 
> now committed them assuming that anything you have proposed has been 
> self-approved.  I'll be providing the rest with the final version of the 
> microMIPS change separately as soon as I have committed it straight away.

Thanks.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-05-18 23:47 ` [PATCH] microMIPS support Maciej W. Rozycki
@ 2012-05-19  8:52   ` Eli Zaretskii
  2012-05-22  0:07     ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2012-05-19  8:52 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Sat, 19 May 2012 00:46:50 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> 
>  Here is the final version of the change that I have applied.  Thanks to 
> everybody involved in the review.

As promised, I committed the following as followup:

2012-05-19  Eli Zaretskii  <eliz@gnu.org>

	* gdb.texinfo (Continuing and Stepping, Selection, Byte Order)
	(MIPS Embedded, MIPS, MIPS Register packet Format)
	(Target Descriptions, MIPS Features): Use @acronym{MIPS} where
	appropriate.

Index: gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.968
diff -u -p -r1.968 gdb.texinfo
--- gdb.texinfo	18 May 2012 23:46:40 -0000	1.968
+++ gdb.texinfo	19 May 2012 08:49:25 -0000
@@ -4957,7 +4957,7 @@ called within the line.
 Also, the @code{step} command only enters a function if there is line
 number information for the function.  Otherwise it acts like the
 @code{next} command.  This avoids problems when using @code{cc -gl}
-on MIPS machines.  Previously, @code{step} entered subroutines if there
+on @acronym{MIPS} machines.  Previously, @code{step} entered subroutines if there
 was any debugging information about the routine.
 
 @item step @var{count}
@@ -6489,7 +6489,7 @@ switches between them.
 On the SPARC architecture, @code{frame} needs two addresses to
 select an arbitrary frame: a frame pointer and a stack pointer.
 
-On the MIPS and Alpha architecture, it needs two addresses: a stack
+On the @acronym{MIPS} and Alpha architecture, it needs two addresses: a stack
 pointer and a program counter.
 
 On the 29k architecture, it needs three addresses: a register stack
@@ -17090,7 +17090,7 @@ load programs into flash memory.
 @cindex choosing target byte order
 @cindex target byte order
 
-Some types of processors, such as the MIPS, PowerPC, and Renesas SH,
+Some types of processors, such as the @acronym{MIPS}, PowerPC, and Renesas SH,
 offer the ability to run either big-endian or little-endian byte
 orders.  Usually the executable or symbol will include a bit to
 designate the endian-ness, and you will not need to worry about
@@ -19757,11 +19757,11 @@ Show MicroBlaze-specific debugging level
 @end table
 
 @node MIPS Embedded
-@subsection MIPS Embedded
+@subsection @acronym{MIPS} Embedded
 
-@cindex MIPS boards
-@value{GDBN} can use the MIPS remote debugging protocol to talk to a
-MIPS board attached to a serial line.  This is available when
+@cindex @acronym{MIPS} boards
+@value{GDBN} can use the @acronym{MIPS} remote debugging protocol to talk to a
+@acronym{MIPS} board attached to a serial line.  This is available when
 you configure @value{GDBN} with @samp{--target=mips-elf}.
 
 @need 1000
@@ -19819,7 +19819,7 @@ Array Tech LSI33K RAID controller board.
 
 
 @noindent
-@value{GDBN} also supports these special commands for MIPS targets:
+@value{GDBN} also supports these special commands for @acronym{MIPS} targets:
 
 @table @code
 @item set mipsfpu double
@@ -19829,9 +19829,9 @@ Array Tech LSI33K RAID controller board.
 @itemx show mipsfpu
 @kindex set mipsfpu
 @kindex show mipsfpu
-@cindex MIPS remote floating point
-@cindex floating point, MIPS remote
-If your target board does not support the MIPS floating point
+@cindex @acronym{MIPS} remote floating point
+@cindex floating point, @acronym{MIPS} remote
+If your target board does not support the @acronym{MIPS} floating point
 coprocessor, you should use the command @samp{set mipsfpu none} (if you
 need this, you may wish to put the command in your @value{GDBN} init
 file).  This tells @value{GDBN} how to find the return value of
@@ -19854,13 +19854,13 @@ As usual, you can inquire about the @cod
 @itemx set retransmit-timeout @var{seconds}
 @itemx show timeout
 @itemx show retransmit-timeout
-@cindex @code{timeout}, MIPS protocol
-@cindex @code{retransmit-timeout}, MIPS protocol
+@cindex @code{timeout}, @acronym{MIPS} protocol
+@cindex @code{retransmit-timeout}, @acronym{MIPS} protocol
 @kindex set timeout
 @kindex show timeout
 @kindex set retransmit-timeout
 @kindex show retransmit-timeout
-You can control the timeout used while waiting for a packet, in the MIPS
+You can control the timeout used while waiting for a packet, in the @acronym{MIPS}
 remote protocol, with the @code{set timeout @var{seconds}} command.  The
 default is 5 seconds.  Similarly, you can control the timeout used while
 waiting for an acknowledgment of a packet with the @code{set
@@ -19875,19 +19875,19 @@ forever because it has no way of knowing
 to run before stopping.
 
 @item set syn-garbage-limit @var{num}
-@kindex set syn-garbage-limit@r{, MIPS remote}
-@cindex synchronize with remote MIPS target
+@kindex set syn-garbage-limit@r{, @acronym{MIPS} remote}
+@cindex synchronize with remote @acronym{MIPS} target
 Limit the maximum number of characters @value{GDBN} should ignore when
 it tries to synchronize with the remote target.  The default is 10
 characters.  Setting the limit to -1 means there's no limit.
 
 @item show syn-garbage-limit
-@kindex show syn-garbage-limit@r{, MIPS remote}
+@kindex show syn-garbage-limit@r{, @acronym{MIPS} remote}
 Show the current limit on the number of characters to ignore when
 trying to synchronize with the remote system.
 
 @item set monitor-prompt @var{prompt}
-@kindex set monitor-prompt@r{, MIPS remote}
+@kindex set monitor-prompt@r{, @acronym{MIPS} remote}
 @cindex remote monitor prompt
 Tell @value{GDBN} to expect the specified @var{prompt} string from the
 remote monitor.  The default depends on the target:
@@ -19901,23 +19901,23 @@ remote monitor.  The default depends on 
 @end table
 
 @item show monitor-prompt
-@kindex show monitor-prompt@r{, MIPS remote}
+@kindex show monitor-prompt@r{, @acronym{MIPS} remote}
 Show the current strings @value{GDBN} expects as the prompt from the
 remote monitor.
 
 @item set monitor-warnings
-@kindex set monitor-warnings@r{, MIPS remote}
+@kindex set monitor-warnings@r{, @acronym{MIPS} remote}
 Enable or disable monitor warnings about hardware breakpoints.  This
 has effect only for the @code{lsi} target.  When on, @value{GDBN} will
 display warning messages whose codes are returned by the @code{lsi}
 PMON monitor for breakpoint commands.
 
 @item show monitor-warnings
-@kindex show monitor-warnings@r{, MIPS remote}
+@kindex show monitor-warnings@r{, @acronym{MIPS} remote}
 Show the current setting of printing monitor warnings.
 
 @item pmon @var{command}
-@kindex pmon@r{, MIPS remote}
+@kindex pmon@r{, @acronym{MIPS} remote}
 @cindex send PMON command
 This command allows sending an arbitrary @var{command} string to the
 monitor.  The monitor must be in debug mode for this to work.
@@ -20505,24 +20505,24 @@ from functions.
 See the following section.
 
 @node MIPS
-@subsection MIPS
+@subsection @acronym{MIPS}
 
 @cindex stack on Alpha
-@cindex stack on MIPS
+@cindex stack on @acronym{MIPS}
 @cindex Alpha stack
-@cindex MIPS stack
-Alpha- and MIPS-based computers use an unusual stack frame, which
+@cindex @acronym{MIPS} stack
+Alpha- and @acronym{MIPS}-based computers use an unusual stack frame, which
 sometimes requires @value{GDBN} to search backward in the object code to
 find the beginning of a function.
 
-@cindex response time, MIPS debugging
+@cindex response time, @acronym{MIPS} debugging
 To improve response time (especially for embedded applications, where
 @value{GDBN} may be restricted to a slow serial line for this search)
 you may want to limit the size of this search, using one of these
 commands:
 
 @table @code
-@cindex @code{heuristic-fence-post} (Alpha, MIPS)
+@cindex @code{heuristic-fence-post} (Alpha, @acronym{MIPS})
 @item set heuristic-fence-post @var{limit}
 Restrict @value{GDBN} to examining at most @var{limit} bytes in its
 search for the beginning of a function.  A value of @var{0} (the
@@ -20537,16 +20537,16 @@ Display the current limit.
 
 @noindent
 These commands are available @emph{only} when @value{GDBN} is configured
-for debugging programs on Alpha or MIPS processors.
+for debugging programs on Alpha or @acronym{MIPS} processors.
 
-Several MIPS-specific commands are available when debugging MIPS
+Several @acronym{MIPS}-specific commands are available when debugging @acronym{MIPS}
 programs:
 
 @table @code
 @item set mips abi @var{arg}
 @kindex set mips abi
-@cindex set ABI for MIPS
-Tell @value{GDBN} which MIPS ABI is used by the inferior.  Possible
+@cindex set ABI for @acronym{MIPS}
+Tell @value{GDBN} which @acronym{MIPS} ABI is used by the inferior.  Possible
 values of @var{arg} are:
 
 @table @samp
@@ -20563,7 +20563,7 @@ default).
 
 @item show mips abi
 @kindex show mips abi
-Show the MIPS ABI used by @value{GDBN} to debug the inferior.
+Show the @acronym{MIPS} ABI used by @value{GDBN} to debug the inferior.
 
 @item set mips compression @var{arg}
 @kindex set mips compression
@@ -20603,36 +20603,36 @@ Show the @acronym{MIPS} compressed @acro
 
 @item set mips mask-address @var{arg}
 @kindex set mips mask-address
-@cindex MIPS addresses, masking
+@cindex @acronym{MIPS} addresses, masking
 This command determines whether the most-significant 32 bits of 64-bit
-MIPS addresses are masked off.  The argument @var{arg} can be
+@acronym{MIPS} addresses are masked off.  The argument @var{arg} can be
 @samp{on}, @samp{off}, or @samp{auto}.  The latter is the default
 setting, which lets @value{GDBN} determine the correct value.
 
 @item show mips mask-address
 @kindex show mips mask-address
-Show whether the upper 32 bits of MIPS addresses are masked off or
+Show whether the upper 32 bits of @acronym{MIPS} addresses are masked off or
 not.
 
 @item set remote-mips64-transfers-32bit-regs
 @kindex set remote-mips64-transfers-32bit-regs
-This command controls compatibility with 64-bit MIPS targets that
-transfer data in 32-bit quantities.  If you have an old MIPS 64 target
+This command controls compatibility with 64-bit @acronym{MIPS} targets that
+transfer data in 32-bit quantities.  If you have an old @acronym{MIPS} 64 target
 that transfers 32 bits for some registers, like @sc{sr} and @sc{fsr},
 and 64 bits for other registers, set this option to @samp{on}.
 
 @item show remote-mips64-transfers-32bit-regs
 @kindex show remote-mips64-transfers-32bit-regs
-Show the current setting of compatibility with older MIPS 64 targets.
+Show the current setting of compatibility with older @acronym{MIPS} 64 targets.
 
 @item set debug mips
 @kindex set debug mips
-This command turns on and off debugging messages for the MIPS-specific
+This command turns on and off debugging messages for the @acronym{MIPS}-specific
 target code in @value{GDBN}.
 
 @item show debug mips
 @kindex show debug mips
-Show the current setting of MIPS debugging messages.
+Show the current setting of @acronym{MIPS} debugging messages.
 @end table
 
 
@@ -36940,6 +36940,7 @@ These breakpoint kinds are defined for t
 
 @node MIPS Register packet Format
 @subsubsection @acronym{MIPS} Register Packet Format
+@cindex register packet format, @acronym{MIPS}
 
 The following @code{g}/@code{G} packets have previously been defined.
 In the below, some thirty-two bit registers are transferred as
@@ -39290,7 +39291,7 @@ The formal DTD for the traceframe info f
 One of the challenges of using @value{GDBN} to debug embedded systems
 is that there are so many minor variants of each processor
 architecture in use.  It is common practice for vendors to start with
-a standard processor core --- ARM, PowerPC, or MIPS, for example ---
+a standard processor core --- ARM, PowerPC, or @acronym{MIPS}, for example ---
 and then make changes to adapt it to a particular market niche.  Some
 architectures have hundreds of variants, available from dozens of
 vendors.  This leads to a number of problems:
@@ -39833,10 +39834,10 @@ The @samp{org.gnu.gdb.i386.linux} featur
 describe a single register, @samp{orig_eax}.
 
 @node MIPS Features
-@subsection MIPS Features
-@cindex target descriptions, MIPS features
+@subsection @acronym{MIPS} Features
+@cindex target descriptions, @acronym{MIPS} features
 
-The @samp{org.gnu.gdb.mips.cpu} feature is required for MIPS targets.
+The @samp{org.gnu.gdb.mips.cpu} feature is required for @acronym{MIPS} targets.
 It should contain registers @samp{r0} through @samp{r31}, @samp{lo},
 @samp{hi}, and @samp{pc}.  They may be 32-bit or 64-bit depending
 on the target.

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support (Linux signal trampolines)
  2012-05-18 22:25   ` Mark Kettenis
@ 2012-05-21 14:33     ` Maciej W. Rozycki
  2012-06-11 10:32       ` [PING][PATCH] " Maciej W. Rozycki
  2014-09-28 11:12       ` [PATCH] " Maciej W. Rozycki
  0 siblings, 2 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-05-21 14:33 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

Mark,

On Fri, 18 May 2012, Mark Kettenis wrote:

> >  To see if we need to check whether the execution mode selected matches 
> > the given trampoline I have checked what the bit patterns of all the 
> > trampoline sequences decode to in the opposite instruction set.  This 
> > produced useless or at least unusual code in most cases, for example:
> > 
> > microMIPS/EB, o32 sigreturn, decoded as MIPS:
> > 	30401017 	andi	zero,v0,0x1017
> > 	00008b7c 	dsll32	s1,zero,0xd
> > 
> > MIPS/EL, o32 sigreturn, decoded as microMIPS:
> > 	1017 2402 	addi	zero,s7,9218
> > 	000c 0000 	sll	zero,t0,0x0
> > 
> > However in some corner cases reasonable code can mimic a trampoline, for 
> > example:
> > 
> > MIPS/EB, n32 rt_sigreturn, decoded as microMIPS:
> > 	2402      	sll	s0,s0,1
> > 	1843 0000 	sb	v0,0(v1)
> > 	000c 0f3c 	jr	t0
> > 
> > -- here the first instruction is a 16-bit one making things nastier even 
> > as there are some other microMIPS instructions whose first 16-bit halfword 
> > is 0x000c and therefore matches this whole trampoline pattern.
> 
> On some OSes the signal trampolines are guaranteed to have a certain
> alignment.  Is that the case for MIPS Linux as well perhaps?  Or would
> that not help you?

 The alignment is always the same -- 4 bytes, I would even say that the 
page offsets are the same too.  The structure used by the kernel is the 
same in both cases and also in both cases two 4-byte instructions are 
used.  The ISA bit is the only difference.

 This is how it looks in the kernel sources, BTW:

#ifdef CONFIG_32BIT
struct mips_vdso {
	u32 signal_trampoline[2];
	u32 rt_signal_trampoline[2];
};
#else  /* !CONFIG_32BIT */
struct mips_vdso {
	u32 o32_signal_trampoline[2];
	u32 o32_rt_signal_trampoline[2];
	u32 rt_signal_trampoline[2];
	u32 n32_rt_signal_trampoline[2];
};
#endif /* CONFIG_32BIT */

the instructions for each trampoline are filled by the kernel at 
bootstrap, using the kernel built-in "assembler" -- originally contributed 
by Thiemo Seufer and recently updated for microMIPS support -- like this:

static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
{
	uasm_i_addiu(&tramp, 2, 0, sigreturn);	/* li v0, sigreturn */
	uasm_i_syscall(&tramp, 0);
}

-- uasm_i_addiu and uasm_i_syscall produce standard MIPS or microMIPS 
machine instructions in standard MIPS and microMIPS kernel binaries 
respectively.

 The VDSO itself is currently placed beyond the stack.  The VDSO is a page 
and therefore its size and base address depend on the processor's page 
size that is at the moment a kernel build-time configuration option, one 
of 4kB, 16kB or 64kB (MIPS processors themselves can support page sizes 
from 1kB up to 256TB; usually multiple page sizes are supported in a given 
chip and are run-time selectable on a per-TLB-entry basis, i.e. a mixture 
of page mappings of different sizes is possible, but Linux only supports 
uniform page sizes; unlike IRIX IIUC).  AFAIK the presence and the 
location of the VDSO is an internal implementation detail and does not 
constitute a part of the Linux ABI.

 In older kernels these trampolines used to be located on user stack, so I 
am even more convinced that we cannot assume anything special about the 
VDSO in this context (obviously those older kernels did not support 
microMIPS processors either).

 References:

http://sourceware.org/ml/gdb-patches/2010-02/msg00546.html
http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=1266538385-29088-1-git-send-email-ddaney%40caviumnetworks.com

 Besides, the ISA bit is what hardware uses to switch between modes, so I 
insist that it is our best bet to rely on it rather than trying to invent 
smart ways to avoid referring to it that are guaranteed to fail once the 
indirect dependencies have outsmarted us.

> > Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.c
> > ===================================================================
> > --- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.c	2012-02-24 15:23:42.000000000 +0000
> > +++ gdb-fsf-trunk-quilt/gdb/tramp-frame.c	2012-05-18 20:03:53.775469792 +0100
> > @@ -87,6 +87,12 @@ tramp_frame_start (const struct tramp_fr
> >    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> >    int ti;
> >  
> > +  /* Check if we can use this trampoline.  */
> > +  if (tramp->validate)
> > +    pc = tramp->validate (tramp, this_frame, pc);
> > +  if (pc == 0)
> > +    return 0;
> 
> I suppose chances are small we'll ever have a platform with
> trampolines at address 0, but nevertheless, wouldn't it be more
> correct to write
> 
>   if (tramp->validate)
>     {
>       pc = tramp->validate (tramp, this_frame, pc);
>       if (pc == 0)
>         return 0;
>     }
> 
> as you're checking for the magic return value?

 Then the value of zero suddenly won't work if a platform where zero is a 
valid PC needs to provide a validator.

 If you think the special treatment of a zero PC is a real issue, then I'd 
rather trivially rewrite the change making the result of ->validate 
boolean and passing the PC by reference, to be modified by the callee if 
needed.  And after some thinking I have concluded there's no harm in doing 
this anyway, there's no performance hit for platforms that do not need to 
tweak the PC (to say nothing of these that do not need to validate at 
all), and the hit for ones that do is probably negligible.

 Here's the result -- diff to previous and a new version.  As a side 
effect it neatly avoids the problem of an overwide prototype I have 
otherwise found no way to solve.

  Maciej

gdb-micromips-linux-sigtramp-update.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.c	2012-05-21 15:15:59.365610943 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c	2012-05-21 14:56:48.755479474 +0100
@@ -800,13 +800,13 @@ static void mips_linux_n32n64_sigframe_i
 					     struct trad_frame_cache *this_cache,
 					     CORE_ADDR func);
 
-static CORE_ADDR mips_linux_sigframe_validate (const struct tramp_frame *self,
-					       struct frame_info *this_frame,
-					       CORE_ADDR pc);
+static int mips_linux_sigframe_validate (const struct tramp_frame *self,
+					 struct frame_info *this_frame,
+					 CORE_ADDR *pc);
 
-static CORE_ADDR micromips_linux_sigframe_validate (const struct tramp_frame *self,
-						    struct frame_info *this_frame,
-						    CORE_ADDR pc);
+static int micromips_linux_sigframe_validate (const struct tramp_frame *self,
+					      struct frame_info *this_frame,
+					      CORE_ADDR *pc);
 
 #define MIPS_NR_LINUX 4000
 #define MIPS_NR_N64_LINUX 5000
@@ -1224,20 +1224,20 @@ mips_linux_n32n64_sigframe_init (const s
   trad_frame_set_id (this_cache, frame_id_build (frame_sp, func));
 }
 
-static CORE_ADDR
+static int
 mips_linux_sigframe_validate (const struct tramp_frame *self,
 			      struct frame_info *this_frame,
-			      CORE_ADDR pc)
+			      CORE_ADDR *pc)
 {
-  return mips_pc_is_mips (pc) ? pc : 0;
+  return mips_pc_is_mips (*pc);
 }
 
-static CORE_ADDR
+static int
 micromips_linux_sigframe_validate (const struct tramp_frame *self,
 				   struct frame_info *this_frame,
-				   CORE_ADDR pc)
+				   CORE_ADDR *pc)
 {
-  return mips_pc_is_micromips (get_frame_arch (this_frame), pc) ? pc : 0;
+  return mips_pc_is_micromips (get_frame_arch (this_frame), *pc);
 }
 
 /* Implement the "write_pc" gdbarch method.  */
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.c	2012-05-21 15:15:59.365610943 +0100
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.c	2012-05-21 14:49:33.745653948 +0100
@@ -88,9 +88,7 @@ tramp_frame_start (const struct tramp_fr
   int ti;
 
   /* Check if we can use this trampoline.  */
-  if (tramp->validate)
-    pc = tramp->validate (tramp, this_frame, pc);
-  if (pc == 0)
+  if (tramp->validate && !tramp->validate (tramp, this_frame, &pc))
     return 0;
 
   /* Search through the trampoline for one that matches the
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.h	2012-05-21 15:15:59.375625452 +0100
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.h	2012-05-21 14:47:31.735646199 +0100
@@ -69,12 +69,13 @@ struct tramp_frame
 		struct frame_info *this_frame,
 		struct trad_frame_cache *this_cache,
 		CORE_ADDR func);
-  /* Check if the tramp-frame is valid for the PC requested.  Return
-     the address to check the instruction sequence against if so,
-     otherwise zero.  If this is NULL, then any PC is valid.  */
-  CORE_ADDR (*validate) (const struct tramp_frame *self,
-			 struct frame_info *this_frame,
-			 CORE_ADDR pc);
+  /* Return non-zero if the tramp-frame is valid for the PC requested.
+     Adjust the PC to point to the address to check the instruction
+     sequence against if required.  If this is NULL, then the tramp-frame
+     is valid for any PC.  */
+  int (*validate) (const struct tramp_frame *self,
+		   struct frame_info *this_frame,
+		   CORE_ADDR *pc);
 };
 
 void tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,


gdb-micromips-linux-sigtramp.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.c	2012-05-19 00:47:08.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c	2012-05-21 14:56:48.755479474 +0100
@@ -800,6 +800,14 @@ static void mips_linux_n32n64_sigframe_i
 					     struct trad_frame_cache *this_cache,
 					     CORE_ADDR func);
 
+static int mips_linux_sigframe_validate (const struct tramp_frame *self,
+					 struct frame_info *this_frame,
+					 CORE_ADDR *pc);
+
+static int micromips_linux_sigframe_validate (const struct tramp_frame *self,
+					      struct frame_info *this_frame,
+					      CORE_ADDR *pc);
+
 #define MIPS_NR_LINUX 4000
 #define MIPS_NR_N64_LINUX 5000
 #define MIPS_NR_N32_LINUX 6000
@@ -815,6 +823,10 @@ static void mips_linux_n32n64_sigframe_i
 #define MIPS_INST_LI_V0_N32_RT_SIGRETURN 0x24020000 + MIPS_NR_N32_rt_sigreturn
 #define MIPS_INST_SYSCALL 0x0000000c
 
+#define MICROMIPS_INST_LI_V0 0x3040
+#define MICROMIPS_INST_POOL32A 0x0000
+#define MICROMIPS_INST_SYSCALL 0x8b7c
+
 static const struct tramp_frame mips_linux_o32_sigframe = {
   SIGTRAMP_FRAME,
   4,
@@ -823,7 +835,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_o32_sigframe_init
+  mips_linux_o32_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_o32_rt_sigframe = {
@@ -833,7 +846,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_LI_V0_RT_SIGRETURN, -1 },
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 } },
-  mips_linux_o32_sigframe_init
+  mips_linux_o32_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_n32_rt_sigframe = {
@@ -844,7 +858,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_n32n64_sigframe_init
+  mips_linux_n32n64_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_n64_rt_sigframe = {
@@ -855,7 +870,63 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_n32n64_sigframe_init
+  mips_linux_n32n64_sigframe_init,
+  mips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_o32_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_o32_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_o32_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 } },
+  mips_linux_o32_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_n32_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_N32_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_n32n64_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_N64_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_n32n64_sigframe_init,
+  micromips_linux_sigframe_validate
 };
 
 /* *INDENT-OFF* */
@@ -942,7 +1013,8 @@ mips_linux_o32_sigframe_init (const stru
   const struct mips_regnum *regs = mips_regnum (gdbarch);
   CORE_ADDR regs_base;
 
-  if (self == &mips_linux_o32_sigframe)
+  if (self == &mips_linux_o32_sigframe
+      || self == &micromips_linux_o32_sigframe)
     sigcontext_base = frame_sp + SIGFRAME_SIGCONTEXT_OFFSET;
   else
     sigcontext_base = frame_sp + RTSIGFRAME_SIGCONTEXT_OFFSET;
@@ -1107,7 +1179,8 @@ mips_linux_n32n64_sigframe_init (const s
   CORE_ADDR sigcontext_base;
   const struct mips_regnum *regs = mips_regnum (gdbarch);
 
-  if (self == &mips_linux_n32_rt_sigframe)
+  if (self == &mips_linux_n32_rt_sigframe
+      || self == &micromips_linux_n32_rt_sigframe)
     sigcontext_base = frame_sp + N32_SIGFRAME_SIGCONTEXT_OFFSET;
   else
     sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET;
@@ -1151,6 +1224,22 @@ mips_linux_n32n64_sigframe_init (const s
   trad_frame_set_id (this_cache, frame_id_build (frame_sp, func));
 }
 
+static int
+mips_linux_sigframe_validate (const struct tramp_frame *self,
+			      struct frame_info *this_frame,
+			      CORE_ADDR *pc)
+{
+  return mips_pc_is_mips (*pc);
+}
+
+static int
+micromips_linux_sigframe_validate (const struct tramp_frame *self,
+				   struct frame_info *this_frame,
+				   CORE_ADDR *pc)
+{
+  return mips_pc_is_micromips (get_frame_arch (this_frame), *pc);
+}
+
 /* Implement the "write_pc" gdbarch method.  */
 
 static void
@@ -1254,6 +1343,9 @@ mips_linux_init_abi (struct gdbarch_info
 	                                mips_linux_get_longjmp_target);
 	set_solib_svr4_fetch_link_map_offsets
 	  (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+	tramp_frame_prepend_unwinder (gdbarch, &micromips_linux_o32_sigframe);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_o32_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-o32-linux.xml");
@@ -1269,6 +1361,8 @@ mips_linux_init_abi (struct gdbarch_info
 	   except that the quiet/signalling NaN bit is reversed (GDB
 	   does not distinguish between quiet and signalling NaNs).  */
 	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_n32_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-n32-linux.xml");
 	break;
@@ -1283,6 +1377,8 @@ mips_linux_init_abi (struct gdbarch_info
 	   except that the quiet/signalling NaN bit is reversed (GDB
 	   does not distinguish between quiet and signalling NaNs).  */
 	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_n64_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-n64-linux.xml");
 	break;
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.c	2012-05-18 23:16:22.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.c	2012-05-21 14:49:33.745653948 +0100
@@ -87,6 +87,10 @@ tramp_frame_start (const struct tramp_fr
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int ti;
 
+  /* Check if we can use this trampoline.  */
+  if (tramp->validate && !tramp->validate (tramp, this_frame, &pc))
+    return 0;
+
   /* Search through the trampoline for one that matches the
      instruction sequence around PC.  */
   for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.h	2012-05-18 23:16:22.000000000 +0100
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.h	2012-05-21 14:47:31.735646199 +0100
@@ -69,6 +69,13 @@ struct tramp_frame
 		struct frame_info *this_frame,
 		struct trad_frame_cache *this_cache,
 		CORE_ADDR func);
+  /* Return non-zero if the tramp-frame is valid for the PC requested.
+     Adjust the PC to point to the address to check the instruction
+     sequence against if required.  If this is NULL, then the tramp-frame
+     is valid for any PC.  */
+  int (*validate) (const struct tramp_frame *self,
+		   struct frame_info *this_frame,
+		   CORE_ADDR *pc);
 };
 
 void tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support
  2012-05-19  8:52   ` Eli Zaretskii
@ 2012-05-22  0:07     ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-05-22  0:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Sat, 19 May 2012, Eli Zaretskii wrote:

> As promised, I committed the following as followup:
> 
> 2012-05-19  Eli Zaretskii  <eliz@gnu.org>
> 
> 	* gdb.texinfo (Continuing and Stepping, Selection, Byte Order)
> 	(MIPS Embedded, MIPS, MIPS Register packet Format)
> 	(Target Descriptions, MIPS Features): Use @acronym{MIPS} where
> 	appropriate.

 Thanks for doing this clean-up.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PING][PATCH] microMIPS support (Linux signal trampolines)
  2012-05-21 14:33     ` Maciej W. Rozycki
@ 2012-06-11 10:32       ` Maciej W. Rozycki
  2014-09-28 11:12       ` [PATCH] " Maciej W. Rozycki
  1 sibling, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2012-06-11 10:32 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

Mark, anyone,

 I made the adjustments you requested, is there still any problem with 
this change?

> 2011-05-18  Maciej W. Rozycki  <macro@codesourcery.com>
> 
> 	gdb/
> 	* tramp-frame.h (tramp_frame): Add validate member.
> 	* tramp-frame.c (tramp_frame_start): Validate trampoline before
> 	scanning.
> 	* mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro.
> 	(MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise.
> 	(mips_linux_o32_sigframe): Initialize validate member.
> 	(mips_linux_o32_rt_sigframe): Likewise.
> 	(mips_linux_n32_rt_sigframe): Likewise.
> 	(mips_linux_n64_rt_sigframe): Likewise.
> 	(micromips_linux_o32_sigframe): New variable.
> 	(micromips_linux_o32_rt_sigframe): Likewise.
> 	(micromips_linux_n32_rt_sigframe): Likewise.
> 	(micromips_linux_n64_rt_sigframe): Likewise.
> 	(mips_linux_o32_sigframe_init): Handle microMIPS trampolines.
> 	(mips_linux_n32n64_sigframe_init): Likewise.
> 	(mips_linux_sigframe_validate): New function.
> 	(micromips_linux_sigframe_validate): Likewise.
> 	(mips_linux_init_abi): Install microMIPS trampoline unwinders.

Latest submission:

http://sourceware.org/ml/gdb-patches/2012-05/msg00769.html

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support (Linux signal trampolines)
  2012-05-21 14:33     ` Maciej W. Rozycki
  2012-06-11 10:32       ` [PING][PATCH] " Maciej W. Rozycki
@ 2014-09-28 11:12       ` Maciej W. Rozycki
  2014-10-06  0:46         ` [PING][PATCH] " Maciej W. Rozycki
  2014-11-16  8:58         ` [PATCH] " Joel Brobecker
  1 sibling, 2 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-09-28 11:12 UTC (permalink / raw)
  To: gdb-patches; +Cc: Mark Kettenis

On Mon, 21 May 2012, Maciej W. Rozycki wrote:

> On Fri, 18 May 2012, Mark Kettenis wrote:
> 
> > >  To see if we need to check whether the execution mode selected matches 
> > > the given trampoline I have checked what the bit patterns of all the 
> > > trampoline sequences decode to in the opposite instruction set.  This 
> > > produced useless or at least unusual code in most cases, for example:
> > > 
> > > microMIPS/EB, o32 sigreturn, decoded as MIPS:
> > > 	30401017 	andi	zero,v0,0x1017
> > > 	00008b7c 	dsll32	s1,zero,0xd
> > > 
> > > MIPS/EL, o32 sigreturn, decoded as microMIPS:
> > > 	1017 2402 	addi	zero,s7,9218
> > > 	000c 0000 	sll	zero,t0,0x0
> > > 
> > > However in some corner cases reasonable code can mimic a trampoline, for 
> > > example:
> > > 
> > > MIPS/EB, n32 rt_sigreturn, decoded as microMIPS:
> > > 	2402      	sll	s0,s0,1
> > > 	1843 0000 	sb	v0,0(v1)
> > > 	000c 0f3c 	jr	t0
> > > 
> > > -- here the first instruction is a 16-bit one making things nastier even 
> > > as there are some other microMIPS instructions whose first 16-bit halfword 
> > > is 0x000c and therefore matches this whole trampoline pattern.
> > 
> > On some OSes the signal trampolines are guaranteed to have a certain
> > alignment.  Is that the case for MIPS Linux as well perhaps?  Or would
> > that not help you?
> 
>  The alignment is always the same -- 4 bytes, I would even say that the 
> page offsets are the same too.  The structure used by the kernel is the 
> same in both cases and also in both cases two 4-byte instructions are 
> used.  The ISA bit is the only difference.
> 
>  This is how it looks in the kernel sources, BTW:
> 
> #ifdef CONFIG_32BIT
> struct mips_vdso {
> 	u32 signal_trampoline[2];
> 	u32 rt_signal_trampoline[2];
> };
> #else  /* !CONFIG_32BIT */
> struct mips_vdso {
> 	u32 o32_signal_trampoline[2];
> 	u32 o32_rt_signal_trampoline[2];
> 	u32 rt_signal_trampoline[2];
> 	u32 n32_rt_signal_trampoline[2];
> };
> #endif /* CONFIG_32BIT */
> 
> the instructions for each trampoline are filled by the kernel at 
> bootstrap, using the kernel built-in "assembler" -- originally contributed 
> by Thiemo Seufer and recently updated for microMIPS support -- like this:
> 
> static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
> {
> 	uasm_i_addiu(&tramp, 2, 0, sigreturn);	/* li v0, sigreturn */
> 	uasm_i_syscall(&tramp, 0);
> }
> 
> -- uasm_i_addiu and uasm_i_syscall produce standard MIPS or microMIPS 
> machine instructions in standard MIPS and microMIPS kernel binaries 
> respectively.
> 
>  The VDSO itself is currently placed beyond the stack.  The VDSO is a page 
> and therefore its size and base address depend on the processor's page 
> size that is at the moment a kernel build-time configuration option, one 
> of 4kB, 16kB or 64kB (MIPS processors themselves can support page sizes 
> from 1kB up to 256TB; usually multiple page sizes are supported in a given 
> chip and are run-time selectable on a per-TLB-entry basis, i.e. a mixture 
> of page mappings of different sizes is possible, but Linux only supports 
> uniform page sizes; unlike IRIX IIUC).  AFAIK the presence and the 
> location of the VDSO is an internal implementation detail and does not 
> constitute a part of the Linux ABI.
> 
>  In older kernels these trampolines used to be located on user stack, so I 
> am even more convinced that we cannot assume anything special about the 
> VDSO in this context (obviously those older kernels did not support 
> microMIPS processors either).
> 
>  References:
> 
> http://sourceware.org/ml/gdb-patches/2010-02/msg00546.html
> http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=1266538385-29088-1-git-send-email-ddaney%40caviumnetworks.com
> 
>  Besides, the ISA bit is what hardware uses to switch between modes, so I 
> insist that it is our best bet to rely on it rather than trying to invent 
> smart ways to avoid referring to it that are guaranteed to fail once the 
> indirect dependencies have outsmarted us.
> 
> > > Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.c
> > > ===================================================================
> > > --- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.c	2012-02-24 15:23:42.000000000 +0000
> > > +++ gdb-fsf-trunk-quilt/gdb/tramp-frame.c	2012-05-18 20:03:53.775469792 +0100
> > > @@ -87,6 +87,12 @@ tramp_frame_start (const struct tramp_fr
> > >    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> > >    int ti;
> > >  
> > > +  /* Check if we can use this trampoline.  */
> > > +  if (tramp->validate)
> > > +    pc = tramp->validate (tramp, this_frame, pc);
> > > +  if (pc == 0)
> > > +    return 0;
> > 
> > I suppose chances are small we'll ever have a platform with
> > trampolines at address 0, but nevertheless, wouldn't it be more
> > correct to write
> > 
> >   if (tramp->validate)
> >     {
> >       pc = tramp->validate (tramp, this_frame, pc);
> >       if (pc == 0)
> >         return 0;
> >     }
> > 
> > as you're checking for the magic return value?
> 
>  Then the value of zero suddenly won't work if a platform where zero is a 
> valid PC needs to provide a validator.
> 
>  If you think the special treatment of a zero PC is a real issue, then I'd 
> rather trivially rewrite the change making the result of ->validate 
> boolean and passing the PC by reference, to be modified by the callee if 
> needed.  And after some thinking I have concluded there's no harm in doing 
> this anyway, there's no performance hit for platforms that do not need to 
> tweak the PC (to say nothing of these that do not need to validate at 
> all), and the hit for ones that do is probably negligible.
> 
>  Here's the result -- diff to previous and a new version.  As a side 
> effect it neatly avoids the problem of an overwide prototype I have 
> otherwise found no way to solve.

 I'd like to get back to this change and review.  Here's the same code 
regenerated against current trunk.  Can we please get consensus on changes 
to tramp-frame.[ch]?

 Regression-tested with the mips-linux-gnu target and the following 
multilibs:

-EB
-EB -msoft-float
-EB -mips16
-EB -mips16 -msoft-float
-EB -mmicromips
-EB -mmicromips -msoft-float
-EB -mabi=n32
-EB -mabi=n32 -msoft-float
-EB -mabi=64
-EB -mabi=64 -msoft-float

and the -EL variants of same with no regressions.

2014-09-28  Maciej W. Rozycki  <macro@codesourcery.com>

	gdb/
	* tramp-frame.h (tramp_frame): Add validate member.
	* tramp-frame.c (tramp_frame_start): Validate trampoline before
	scanning.
	* mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro.
	(MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise.
	(mips_linux_o32_sigframe): Initialize validate member.
	(mips_linux_o32_rt_sigframe): Likewise.
	(mips_linux_n32_rt_sigframe): Likewise.
	(mips_linux_n64_rt_sigframe): Likewise.
	(micromips_linux_o32_sigframe): New variable.
	(micromips_linux_o32_rt_sigframe): Likewise.
	(micromips_linux_n32_rt_sigframe): Likewise.
	(micromips_linux_n64_rt_sigframe): Likewise.
	(mips_linux_o32_sigframe_init): Handle microMIPS trampolines.
	(mips_linux_n32n64_sigframe_init): Likewise.
	(mips_linux_sigframe_validate): New function.
	(micromips_linux_sigframe_validate): Likewise.
	(mips_linux_init_abi): Install microMIPS trampoline unwinders.

  Maciej

gdb-micromips-linux-sigtramp.diff
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.c	2014-08-23 01:11:20.568972186 +0100
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c	2014-08-23 01:17:50.608926711 +0100
@@ -840,6 +840,14 @@ static void mips_linux_n32n64_sigframe_i
 					     struct trad_frame_cache *this_cache,
 					     CORE_ADDR func);
 
+static int mips_linux_sigframe_validate (const struct tramp_frame *self,
+					 struct frame_info *this_frame,
+					 CORE_ADDR *pc);
+
+static int micromips_linux_sigframe_validate (const struct tramp_frame *self,
+					      struct frame_info *this_frame,
+					      CORE_ADDR *pc);
+
 #define MIPS_NR_LINUX 4000
 #define MIPS_NR_N64_LINUX 5000
 #define MIPS_NR_N32_LINUX 6000
@@ -855,6 +863,10 @@ static void mips_linux_n32n64_sigframe_i
 #define MIPS_INST_LI_V0_N32_RT_SIGRETURN 0x24020000 + MIPS_NR_N32_rt_sigreturn
 #define MIPS_INST_SYSCALL 0x0000000c
 
+#define MICROMIPS_INST_LI_V0 0x3040
+#define MICROMIPS_INST_POOL32A 0x0000
+#define MICROMIPS_INST_SYSCALL 0x8b7c
+
 static const struct tramp_frame mips_linux_o32_sigframe = {
   SIGTRAMP_FRAME,
   4,
@@ -863,7 +875,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_o32_sigframe_init
+  mips_linux_o32_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_o32_rt_sigframe = {
@@ -873,7 +886,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_LI_V0_RT_SIGRETURN, -1 },
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 } },
-  mips_linux_o32_sigframe_init
+  mips_linux_o32_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_n32_rt_sigframe = {
@@ -884,7 +898,8 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_n32n64_sigframe_init
+  mips_linux_n32n64_sigframe_init,
+  mips_linux_sigframe_validate
 };
 
 static const struct tramp_frame mips_linux_n64_rt_sigframe = {
@@ -895,7 +910,63 @@ static const struct tramp_frame mips_lin
     { MIPS_INST_SYSCALL, -1 },
     { TRAMP_SENTINEL_INSN, -1 }
   },
-  mips_linux_n32n64_sigframe_init
+  mips_linux_n32n64_sigframe_init,
+  mips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_o32_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_o32_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_o32_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 } },
+  mips_linux_o32_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_n32_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_N32_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_n32n64_sigframe_init,
+  micromips_linux_sigframe_validate
+};
+
+static const struct tramp_frame micromips_linux_n64_rt_sigframe = {
+  SIGTRAMP_FRAME,
+  2,
+  {
+    { MICROMIPS_INST_LI_V0, -1 },
+    { MIPS_NR_N64_rt_sigreturn, -1 },
+    { MICROMIPS_INST_POOL32A, -1 },
+    { MICROMIPS_INST_SYSCALL, -1 },
+    { TRAMP_SENTINEL_INSN, -1 }
+  },
+  mips_linux_n32n64_sigframe_init,
+  micromips_linux_sigframe_validate
 };
 
 /* *INDENT-OFF* */
@@ -1015,7 +1086,8 @@ mips_linux_o32_sigframe_init (const stru
   const struct mips_regnum *regs = mips_regnum (gdbarch);
   CORE_ADDR regs_base;
 
-  if (self == &mips_linux_o32_sigframe)
+  if (self == &mips_linux_o32_sigframe
+      || self == &micromips_linux_o32_sigframe)
     sigcontext_base = frame_sp + SIGFRAME_SIGCONTEXT_OFFSET;
   else
     sigcontext_base = frame_sp + RTSIGFRAME_SIGCONTEXT_OFFSET;
@@ -1216,7 +1288,8 @@ mips_linux_n32n64_sigframe_init (const s
   CORE_ADDR sigcontext_base;
   const struct mips_regnum *regs = mips_regnum (gdbarch);
 
-  if (self == &mips_linux_n32_rt_sigframe)
+  if (self == &mips_linux_n32_rt_sigframe
+      || self == &micromips_linux_n32_rt_sigframe)
     sigcontext_base = frame_sp + N32_SIGFRAME_SIGCONTEXT_OFFSET;
   else
     sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET;
@@ -1286,6 +1359,22 @@ mips_linux_n32n64_sigframe_init (const s
   trad_frame_set_id (this_cache, frame_id_build (frame_sp, func));
 }
 
+static int
+mips_linux_sigframe_validate (const struct tramp_frame *self,
+			      struct frame_info *this_frame,
+			      CORE_ADDR *pc)
+{
+  return mips_pc_is_mips (*pc);
+}
+
+static int
+micromips_linux_sigframe_validate (const struct tramp_frame *self,
+				   struct frame_info *this_frame,
+				   CORE_ADDR *pc)
+{
+  return mips_pc_is_micromips (get_frame_arch (this_frame), *pc);
+}
+
 /* Implement the "write_pc" gdbarch method.  */
 
 static void
@@ -1569,6 +1658,9 @@ mips_linux_init_abi (struct gdbarch_info
 					mips_linux_get_longjmp_target);
 	set_solib_svr4_fetch_link_map_offsets
 	  (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+	tramp_frame_prepend_unwinder (gdbarch, &micromips_linux_o32_sigframe);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_o32_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-o32-linux.xml");
@@ -1584,6 +1676,8 @@ mips_linux_init_abi (struct gdbarch_info
 	   except that the quiet/signalling NaN bit is reversed (GDB
 	   does not distinguish between quiet and signalling NaNs).  */
 	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_n32_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-n32-linux.xml");
 	break;
@@ -1598,6 +1692,8 @@ mips_linux_init_abi (struct gdbarch_info
 	   except that the quiet/signalling NaN bit is reversed (GDB
 	   does not distinguish between quiet and signalling NaNs).  */
 	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
+	tramp_frame_prepend_unwinder (gdbarch,
+				      &micromips_linux_n64_rt_sigframe);
 	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe);
 	set_xml_syscall_file_name ("syscalls/mips-n64-linux.xml");
 	break;
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.c	2014-08-23 01:11:20.568972186 +0100
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.c	2014-08-23 01:17:50.608926711 +0100
@@ -86,6 +86,10 @@ tramp_frame_start (const struct tramp_fr
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   int ti;
 
+  /* Check if we can use this trampoline.  */
+  if (tramp->validate && !tramp->validate (tramp, this_frame, &pc))
+    return 0;
+
   /* Search through the trampoline for one that matches the
      instruction sequence around PC.  */
   for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
Index: gdb-fsf-trunk-quilt/gdb/tramp-frame.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/tramp-frame.h	2014-08-23 01:00:49.498973998 +0100
+++ gdb-fsf-trunk-quilt/gdb/tramp-frame.h	2014-08-23 01:17:50.608926711 +0100
@@ -69,6 +69,13 @@ struct tramp_frame
 		struct frame_info *this_frame,
 		struct trad_frame_cache *this_cache,
 		CORE_ADDR func);
+  /* Return non-zero if the tramp-frame is valid for the PC requested.
+     Adjust the PC to point to the address to check the instruction
+     sequence against if required.  If this is NULL, then the tramp-frame
+     is valid for any PC.  */
+  int (*validate) (const struct tramp_frame *self,
+		   struct frame_info *this_frame,
+		   CORE_ADDR *pc);
 };
 
 void tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PING][PATCH] microMIPS support (Linux signal trampolines)
  2014-09-28 11:12       ` [PATCH] " Maciej W. Rozycki
@ 2014-10-06  0:46         ` Maciej W. Rozycki
  2014-10-13 12:24           ` [PING^2][PATCH] " Maciej W. Rozycki
  2014-11-16  8:58         ` [PATCH] " Joel Brobecker
  1 sibling, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-10-06  0:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: Mark Kettenis

On Sun, 28 Sep 2014, Maciej W. Rozycki wrote:

>  I'd like to get back to this change and review.  Here's the same code 
> regenerated against current trunk.  Can we please get consensus on changes 
> to tramp-frame.[ch]?
> 
>  Regression-tested with the mips-linux-gnu target and the following 
> multilibs:
> 
> -EB
> -EB -msoft-float
> -EB -mips16
> -EB -mips16 -msoft-float
> -EB -mmicromips
> -EB -mmicromips -msoft-float
> -EB -mabi=n32
> -EB -mabi=n32 -msoft-float
> -EB -mabi=64
> -EB -mabi=64 -msoft-float
> 
> and the -EL variants of same with no regressions.
> 
> 2014-09-28  Maciej W. Rozycki  <macro@codesourcery.com>
> 
> 	gdb/
> 	* tramp-frame.h (tramp_frame): Add validate member.
> 	* tramp-frame.c (tramp_frame_start): Validate trampoline before
> 	scanning.
> 	* mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro.
> 	(MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise.
> 	(mips_linux_o32_sigframe): Initialize validate member.
> 	(mips_linux_o32_rt_sigframe): Likewise.
> 	(mips_linux_n32_rt_sigframe): Likewise.
> 	(mips_linux_n64_rt_sigframe): Likewise.
> 	(micromips_linux_o32_sigframe): New variable.
> 	(micromips_linux_o32_rt_sigframe): Likewise.
> 	(micromips_linux_n32_rt_sigframe): Likewise.
> 	(micromips_linux_n64_rt_sigframe): Likewise.
> 	(mips_linux_o32_sigframe_init): Handle microMIPS trampolines.
> 	(mips_linux_n32n64_sigframe_init): Likewise.
> 	(mips_linux_sigframe_validate): New function.
> 	(micromips_linux_sigframe_validate): Likewise.
> 	(mips_linux_init_abi): Install microMIPS trampoline unwinders.

 Ping!

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PING^2][PATCH] microMIPS support (Linux signal trampolines)
  2014-10-06  0:46         ` [PING][PATCH] " Maciej W. Rozycki
@ 2014-10-13 12:24           ` Maciej W. Rozycki
  2014-10-20 17:01             ` [PING^3][PATCH] " Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-10-13 12:24 UTC (permalink / raw)
  To: gdb-patches

Hi,

 This patch:

http://sourceware.org/ml/gdb-patches/2014-09/msg00805.html

is still waiting, please review.

 Thanks,

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PING^3][PATCH] microMIPS support (Linux signal trampolines)
  2014-10-13 12:24           ` [PING^2][PATCH] " Maciej W. Rozycki
@ 2014-10-20 17:01             ` Maciej W. Rozycki
  2014-11-03 16:04               ` [PING^4][PATCH] " Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-10-20 17:01 UTC (permalink / raw)
  To: gdb-patches

Hi,

 This patch:

http://sourceware.org/ml/gdb-patches/2014-09/msg00805.html

is still waiting, please review.

 Thanks,

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PING^4][PATCH] microMIPS support (Linux signal trampolines)
  2014-10-20 17:01             ` [PING^3][PATCH] " Maciej W. Rozycki
@ 2014-11-03 16:04               ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-11-03 16:04 UTC (permalink / raw)
  To: gdb-patches

Hi,

 This patch:

http://sourceware.org/ml/gdb-patches/2014-09/msg00805.html

is still waiting, please review.

 Thanks,

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support (Linux signal trampolines)
  2014-09-28 11:12       ` [PATCH] " Maciej W. Rozycki
  2014-10-06  0:46         ` [PING][PATCH] " Maciej W. Rozycki
@ 2014-11-16  8:58         ` Joel Brobecker
  2014-12-03 21:00           ` Maciej W. Rozycki
  1 sibling, 1 reply; 43+ messages in thread
From: Joel Brobecker @ 2014-11-16  8:58 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches, Mark Kettenis

>  I'd like to get back to this change and review.  Here's the same code 
> regenerated against current trunk.  Can we please get consensus on changes 
> to tramp-frame.[ch]?
[...]
> 2014-09-28  Maciej W. Rozycki  <macro@codesourcery.com>
> 
> 	gdb/
> 	* tramp-frame.h (tramp_frame): Add validate member.
> 	* tramp-frame.c (tramp_frame_start): Validate trampoline before
> 	scanning.
> 	* mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro.
> 	(MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise.
> 	(mips_linux_o32_sigframe): Initialize validate member.
> 	(mips_linux_o32_rt_sigframe): Likewise.
> 	(mips_linux_n32_rt_sigframe): Likewise.
> 	(mips_linux_n64_rt_sigframe): Likewise.
> 	(micromips_linux_o32_sigframe): New variable.
> 	(micromips_linux_o32_rt_sigframe): Likewise.
> 	(micromips_linux_n32_rt_sigframe): Likewise.
> 	(micromips_linux_n64_rt_sigframe): Likewise.
> 	(mips_linux_o32_sigframe_init): Handle microMIPS trampolines.
> 	(mips_linux_n32n64_sigframe_init): Likewise.
> 	(mips_linux_sigframe_validate): New function.
> 	(micromips_linux_sigframe_validate): Likewise.
> 	(mips_linux_init_abi): Install microMIPS trampoline unwinders.

Sorry again for the late review, Maciej.

This patch is pre-approved, with one tiny little request:
Can you add a quick one-liner comment as documentation for
all the new functions? For instance:

    /* Implement struct tramp_frame's "validate" method for [...]  */

    static int
    mips_linux_sigframe_validate (const struct tramp_frame *self,

Thank you!
-- 
Joel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH] microMIPS support (Linux signal trampolines)
  2014-11-16  8:58         ` [PATCH] " Joel Brobecker
@ 2014-12-03 21:00           ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-03 21:00 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches, Mark Kettenis

On Sun, 16 Nov 2014, Joel Brobecker wrote:

> > 	gdb/
> > 	* tramp-frame.h (tramp_frame): Add validate member.
> > 	* tramp-frame.c (tramp_frame_start): Validate trampoline before
> > 	scanning.
> > 	* mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro.
> > 	(MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise.
> > 	(mips_linux_o32_sigframe): Initialize validate member.
> > 	(mips_linux_o32_rt_sigframe): Likewise.
> > 	(mips_linux_n32_rt_sigframe): Likewise.
> > 	(mips_linux_n64_rt_sigframe): Likewise.
> > 	(micromips_linux_o32_sigframe): New variable.
> > 	(micromips_linux_o32_rt_sigframe): Likewise.
> > 	(micromips_linux_n32_rt_sigframe): Likewise.
> > 	(micromips_linux_n64_rt_sigframe): Likewise.
> > 	(mips_linux_o32_sigframe_init): Handle microMIPS trampolines.
> > 	(mips_linux_n32n64_sigframe_init): Likewise.
> > 	(mips_linux_sigframe_validate): New function.
> > 	(micromips_linux_sigframe_validate): Likewise.
> > 	(mips_linux_init_abi): Install microMIPS trampoline unwinders.
> 
> Sorry again for the late review, Maciej.

 No worries, better late than never, and I contributed to the delay in 
the first place, by keeping it all aside for two years or so.

> This patch is pre-approved, with one tiny little request:
> Can you add a quick one-liner comment as documentation for
> all the new functions? For instance:
> 
>     /* Implement struct tramp_frame's "validate" method for [...]  */
> 
>     static int
>     mips_linux_sigframe_validate (const struct tramp_frame *self,

 Done now, for the above and `micromips_linux_sigframe_validate' too.  
I fixed a minor formatting issue with `micromips_linux_o32_rt_sigframe' 
as well.  I have committed the change now; I think the updates are too 
insignificant to justify reposting the final version, just check the 
repository if curious.

 Thanks for your review.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2014-12-03 21:00 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-24 21:18 [PATCH] microMIPS support Maciej W. Rozycki
2012-04-25  6:20 ` Eli Zaretskii
2012-04-26 13:54   ` Maciej W. Rozycki
2012-04-26 14:14     ` Eli Zaretskii
2012-04-26 18:03       ` Maciej W. Rozycki
2012-04-26 20:39         ` Eli Zaretskii
2012-04-27 18:16           ` Maciej W. Rozycki
2012-04-27 18:24             ` Eli Zaretskii
     [not found]               ` <alpine.DEB.1.10.1204302334520.19835@tp.orcam.me.uk>
2012-05-02 16:39                 ` Eli Zaretskii
2012-05-17 15:07                   ` Maciej W. Rozycki
2012-05-17 16:10                     ` Eli Zaretskii
2012-05-18 23:13                       ` Maciej W. Rozycki
2012-05-19  8:20                         ` Eli Zaretskii
2012-04-25 13:13 ` Yao Qi
2012-04-25 15:57   ` Maciej W. Rozycki
2012-04-25 15:54 ` Joel Brobecker
2012-04-25 17:18   ` Maciej W. Rozycki
2012-04-25 18:12     ` Joel Brobecker
2012-04-25 18:27       ` Maciej W. Rozycki
2012-04-26 18:38 ` Jan Kratochvil
2012-04-26 19:04   ` Maciej W. Rozycki
2012-04-26 19:29     ` Jan Kratochvil
2012-04-26 21:59       ` Maciej W. Rozycki
2012-04-27  7:11         ` Jan Kratochvil
2012-04-27 15:14           ` Maciej W. Rozycki
2012-04-27 15:29             ` Pedro Alves
2012-04-27 15:46               ` Maciej W. Rozycki
2012-04-27 15:54             ` Tom Tromey
2012-05-18 23:53     ` Maciej W. Rozycki
2012-05-18 21:32 ` [PATCH] microMIPS support (Linux signal trampolines) Maciej W. Rozycki
2012-05-18 22:25   ` Mark Kettenis
2012-05-21 14:33     ` Maciej W. Rozycki
2012-06-11 10:32       ` [PING][PATCH] " Maciej W. Rozycki
2014-09-28 11:12       ` [PATCH] " Maciej W. Rozycki
2014-10-06  0:46         ` [PING][PATCH] " Maciej W. Rozycki
2014-10-13 12:24           ` [PING^2][PATCH] " Maciej W. Rozycki
2014-10-20 17:01             ` [PING^3][PATCH] " Maciej W. Rozycki
2014-11-03 16:04               ` [PING^4][PATCH] " Maciej W. Rozycki
2014-11-16  8:58         ` [PATCH] " Joel Brobecker
2014-12-03 21:00           ` Maciej W. Rozycki
2012-05-18 23:47 ` [PATCH] microMIPS support Maciej W. Rozycki
2012-05-19  8:52   ` Eli Zaretskii
2012-05-22  0:07     ` Maciej W. Rozycki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).