Index: gcc/gcc/config/mips/mips-protos.h
===================================================================
--- gcc.orig/gcc/config/mips/mips-protos.h	2016-11-09 18:56:34.412202878 +0000
+++ gcc/gcc/config/mips/mips-protos.h	2016-11-09 18:57:01.571953223 +0000
@@ -271,6 +271,8 @@ extern void mips_declare_object (FILE *,
 				 const char *, ...) ATTRIBUTE_PRINTF_4;
 extern void mips_declare_object_name (FILE *, const char *, tree);
 extern void mips_finish_declare_object (FILE *, tree, int, int);
+extern void mips_set_text_contents_type (FILE *, const char *,
+					 unsigned long, bool);
 
 extern bool mips_small_data_pattern_p (rtx);
 extern rtx mips_rewrite_small_data (rtx);
Index: gcc/gcc/config/mips/mips.c
===================================================================
--- gcc.orig/gcc/config/mips/mips.c	2016-11-09 18:56:34.423849203 +0000
+++ gcc/gcc/config/mips/mips.c	2016-11-09 18:57:01.752162039 +0000
@@ -9742,6 +9742,37 @@ mips_finish_declare_object (FILE *stream
     }
 }
 #endif
+
+/* Mark text contents as code or data, mainly for the purpose of correct
+   disassembly.  Emit a local symbol and set its type appropriately for
+   that purpose.  Also emit `.insn' if marking contents as code so that
+   the ISA mode is recorded and any padding that follows is disassembled
+   as correct instructions.  */
+
+void
+mips_set_text_contents_type (FILE *file ATTRIBUTE_UNUSED,
+			     const char *prefix ATTRIBUTE_UNUSED,
+			     unsigned long num ATTRIBUTE_UNUSED,
+			     bool function_p ATTRIBUTE_UNUSED)
+{
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
+  char buf[(sizeof (num) * 10) / 4 + 2];
+  const char *fnname;
+  char *sname;
+  rtx symbol;
+
+  sprintf (buf, "%lu", num);
+  symbol = XEXP (DECL_RTL (current_function_decl), 0);
+  fnname = targetm.strip_name_encoding (XSTR (symbol, 0));
+  sname = ACONCAT ((prefix, fnname, "_", buf, NULL));
+
+  ASM_OUTPUT_TYPE_DIRECTIVE (file, sname, function_p ? "function" : "object");
+  assemble_name (file, sname);
+  fputs (":\n", file);
+  if (function_p)
+    fputs ("\t.insn\n", file);
+#endif
+}
 
 /* Return the FOO in the name of the ".mdebug.FOO" section associated
    with the current ABI.  */
@@ -17124,17 +17155,22 @@ mips16_emit_constants_1 (machine_mode mo
   gcc_unreachable ();
 }
 
-/* Dump out the constants in CONSTANTS after INSN.  */
+/* Dump out the constants in CONSTANTS after INSN.  Record the initial
+   label number in the `consttable' and `consttable_end' insns emitted
+   at the beginning and the end of the constant pool respectively, so
+   that individual pools can be uniquely marked as data for the purpose
+   of disassembly.  */
 
 static void
 mips16_emit_constants (struct mips16_constant *constants, rtx_insn *insn)
 {
+  int label_num = constants ? CODE_LABEL_NUMBER (constants->label) : 0;
   struct mips16_constant *c, *next;
   int align;
 
   align = 0;
   if (constants)
-    insn = emit_insn_after (gen_consttable (), insn);
+    insn = emit_insn_after (gen_consttable (GEN_INT (label_num)), insn);
   for (c = constants; c != NULL; c = next)
     {
       /* If necessary, increase the alignment of PC.  */
@@ -17151,6 +17187,8 @@ mips16_emit_constants (struct mips16_con
       next = c->next;
       free (c);
     }
+  if (constants)
+    insn = emit_insn_after (gen_consttable_end (GEN_INT (label_num)), insn);
 
   emit_barrier_after (insn);
 }
@@ -20261,16 +20299,32 @@ mips_need_noat_wrapper_p (rtx_insn *insn
   return false;
 }
 
-/* Implement FINAL_PRESCAN_INSN.  */
+/* Implement FINAL_PRESCAN_INSN.  Mark MIPS16 inline constant pools
+   as data for the purpose of disassembly.  For simplicity embed the
+   pool's initial label number in the local symbol produced so that
+   multiple pools within a single function end up marked with unique
+   symbols.  The label number is carried by the `consttable' insn
+   emitted at the beginning of each pool.  */
 
 void
 mips_final_prescan_insn (rtx_insn *insn, rtx *opvec, int noperands)
 {
+  if (INSN_P (insn)
+      && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+      && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE)
+    mips_set_text_contents_type (asm_out_file, "__pool_",
+				 XINT (XVECEXP (PATTERN (insn), 0, 0), 0),
+				 FALSE);
+
   if (mips_need_noat_wrapper_p (insn, opvec, noperands))
     mips_push_asm_switch (&mips_noat);
 }
 
-/* Implement TARGET_ASM_FINAL_POSTSCAN_INSN.  */
+/* Implement TARGET_ASM_FINAL_POSTSCAN_INSN.  Reset text marking to
+   code after a MIPS16 inline constant pool.  Like with the beginning
+   of a pool table use the pool's initial label number to keep symbols
+   unique.  The label number is carried by the `consttable_end' insn
+   emitted at the end of each pool.  */
 
 static void
 mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx_insn *insn,
@@ -20278,6 +20332,13 @@ mips_final_postscan_insn (FILE *file ATT
 {
   if (mips_need_noat_wrapper_p (insn, opvec, noperands))
     mips_pop_asm_switch (&mips_noat);
+
+  if (INSN_P (insn)
+      && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+      && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE_END)
+    mips_set_text_contents_type (asm_out_file, "__pend_",
+				 XINT (XVECEXP (PATTERN (insn), 0, 0), 0),
+				 TRUE);
 }
 
 /* Return the function that is used to expand the <u>mulsidi3 pattern.
Index: gcc/gcc/config/mips/mips.h
===================================================================
--- gcc.orig/gcc/config/mips/mips.h	2016-11-09 18:56:34.445992594 +0000
+++ gcc/gcc/config/mips/mips.h	2016-11-09 18:57:01.804444614 +0000
@@ -2986,6 +2986,32 @@ do {									\
 	     LOCAL_LABEL_PREFIX, VALUE);				\
 } while (0)
 
+/* Mark inline jump tables as data for the purpose of disassembly.  For
+   simplicity embed the jump table's label number in the local symbol
+   produced so that multiple jump tables within a single function end
+   up marked with unique symbols.  Retain the alignment setting from
+   `elfos.h' as we are replacing the definition from there.  */
+
+#undef ASM_OUTPUT_BEFORE_CASE_LABEL
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(STREAM, PREFIX, NUM, TABLE)	\
+  do									\
+    {									\
+      ASM_OUTPUT_ALIGN ((STREAM), 2);					\
+      if (JUMP_TABLES_IN_TEXT_SECTION)					\
+	mips_set_text_contents_type (STREAM, "__jump_", NUM, FALSE);	\
+    }									\
+  while (0);
+
+/* Reset text marking to code after an inline jump table.  Like with
+   the beginning of a jump table use the label number to keep symbols
+   unique.  */
+
+#define ASM_OUTPUT_CASE_END(STREAM, NUM, TABLE)				\
+  do									\
+    if (JUMP_TABLES_IN_TEXT_SECTION)					\
+      mips_set_text_contents_type (STREAM, "__jend_", NUM, TRUE);	\
+  while (0);
+
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
Index: gcc/gcc/config/mips/mips.md
===================================================================
--- gcc.orig/gcc/config/mips/mips.md	2016-11-09 18:56:34.458515411 +0000
+++ gcc/gcc/config/mips/mips.md	2016-11-09 20:54:38.794831645 +0000
@@ -121,6 +121,7 @@
   ;; MIPS16 constant pools.
   UNSPEC_ALIGN
   UNSPEC_CONSTTABLE
+  UNSPEC_CONSTTABLE_END
   UNSPEC_CONSTTABLE_INT
   UNSPEC_CONSTTABLE_FLOAT
 
@@ -7321,7 +7322,16 @@
 ;;
 
 (define_insn "consttable"
-  [(unspec_volatile [(const_int 0)] UNSPEC_CONSTTABLE)]
+  [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
+		    UNSPEC_CONSTTABLE)]
+  ""
+  ""
+  [(set_attr "mode" "none")
+   (set_attr "insn_count" "0")])
+
+(define_insn "consttable_end"
+  [(unspec_volatile [(match_operand 0 "const_int_operand" "")]
+		    UNSPEC_CONSTTABLE_END)]
   ""
   ""
   [(set_attr "mode" "none")
Index: gcc/gcc/testsuite/gcc.target/mips/data-sym-jump.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/data-sym-jump.c	2016-11-09 20:57:25.850097225 +0000
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+/* { dg-skip-if "MIPS16 `casesi' loses at -Os" { *-*-* } { "-Os"} { "" } } */
+
+int
+frob (int i)
+{
+  switch (i)
+    {
+    case -5:
+      return -2;
+    case -3:
+      return -1;
+    case 0:
+      return 0;
+    case 3:
+      return 1;
+    case 5:
+      break;
+    default:
+      __builtin_unreachable ();
+    }
+  return i;
+}
+
+/* Expect assembly like:
+
+	la	$2, $L4
+						# Anything goes here.
+	.type	__jump_frob_4, @object		# Symbol # must match label.
+__jump_frob_4:					# The symbol must match.
+$L4:						# The label must match.
+	.half	$L3-$L4				# Or `.word'.  The subtrahend
+	.half	$L2-$L4				# label must match thoughout
+	.half	$L9-$L4				# (repeated 11 times).
+	.half	$L2-$L4				# .
+	.half	$L2-$L4				# .
+	.half	$L8-$L4				# .
+	.half	$L2-$L4				# .
+	.half	$L2-$L4				# .
+	.half	$L7-$L4				# .
+	.half	$L2-$L4				# .
+	.half	$L8-$L4				# .
+	.type	__jend_frob_4, @function	# Symbol # must match label.
+__jend_frob_4:					# The symbol must match.
+	.insn
+
+   that is `__jump_*'/`__jend_*' symbols inserted around a jump table.  */
+
+/* { dg-final { scan-assembler "\tla\t\\\$\[0-9\]+, (.L(\[0-9\]+))\n.*\t\\.type\t(__jump_frob_\\2), @object\n\\3:\n\\1:\n(?:\t\\.(?:half|word)\t.L\[0-9\]+-\\1\n)\{11\}\t\\.type\t(__jend_frob_\\2), @function\n\\4:\n\t\\.insn\n" } } */
Index: gcc/gcc/testsuite/gcc.target/mips/data-sym-pool.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/data-sym-pool.c	2016-11-09 20:57:25.880515516 +0000
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+
+int
+frob (void)
+{
+  return 0x12345678;
+}
+
+/* Expect assembly like:
+
+	lw	$2,$L3
+						# Anything goes here.
+	.type	__pool_frob_3, @object		# Symbol # must match label.
+__pool_frob_3:					# The symbol must match.
+	.align	2
+$L3:						# The label must match.
+	.word	305419896
+	.type	__pend_frob_3, @function	# Symbol # must match label.
+__pend_frob_3:					# The symbol must match.
+	.insn
+
+   that is `__pool_*'/`__pend_*' symbols inserted around a constant pool.  */
+
+/* { dg-final { scan-assembler "\tlw\t\\\$\[0-9\]+,(.L(\[0-9\]+))\n.*\t\\.type\t(__pool_frob_\\2), @object\n\\3:\n\t\\.align\t2\n\\1:\n\t\\.word\t305419896\n\t\\.type\t(__pend_frob_\\2), @function\n\\4:\n\t\\.insn\n" } } */
Index: gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c	2016-11-09 20:57:21.901118536 +0000
+++ gcc/gcc/testsuite/gcc.target/mips/insn-pseudo-4.c	2016-11-09 20:57:25.890641344 +0000
@@ -18,10 +18,12 @@ unreachable (void)
 $L2:				# The label must match.
 	.insn
 $L3 = .				# It's there, but we don't care.
+	.type	__pool_unreachable_5, @object
+__pool_unreachable_5:
 	.align	2
 $L5:				# The label must match.
 	.word	305419896
 
    that is .insn to be inserted if a code label is at a constant pool.  */
 
-/* { dg-final { scan-assembler "\tlw\t(\\\$\[0-9\]+),(.L\[0-9\]+)\n.*\tbeqz\t\\1,(.L\[0-9\]+)\n.*\n\\3:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.align\t2\n\\2:\n\t\\.word\t305419896\n" } } */
+/* { dg-final { scan-assembler "\tlw\t(\\\$\[0-9\]+),(.L\[0-9\]+)\n.*\tbeqz\t\\1,(.L\[0-9\]+)\n.*\n\\3:\n\t\\.insn\n(?:.L\[0-9\]+ = \\.\n)?\t\\.type\t__pool_unreachable_\[0-9\]+, @object\n__pool_unreachable_\[0-9\]+:\n\t\\.align\t2\n\\2:\n\t\\.word\t305419896\n" } } */
