diff --git a/gas/config/tc-pru.c b/gas/config/tc-pru.c
index e55ce4790ba..86ce28f6fb5 100644
--- a/gas/config/tc-pru.c
+++ b/gas/config/tc-pru.c
@@ -1253,6 +1253,92 @@ pru_assemble_arg_n (pru_insn_infoS *insn_info, const char *argstr)
     SET_INSN_FIELD (XFR_LENGTH, insn_info->insn_code, burstlen);
 }
 
+static void
+pru_parse_mvi_operand (const char *argstr,
+		       struct pru_reg **blreg,
+		       unsigned int *mode)
+{
+  char *regstr;
+
+  *mode = MVI_OP_MODE_DIRECT;
+
+  if (*argstr == '*')
+    {
+      *mode = MVI_OP_MODE_INDIRECT;
+      argstr++;
+
+      if (argstr[0] == '-' && argstr[1] == '-')
+	{
+	  argstr += 2;
+	  *mode = MVI_OP_MODE_INDIRECT_PREDEC;
+	}
+    }
+  /* Decouple register string from the post increment operator.  */
+  regstr = strdup (argstr);
+  *strchrnul (regstr, '+') = '\0';
+  *blreg = pru_reg_lookup (regstr);
+  if (*blreg == NULL)
+    as_bad (_("unknown register %s"), regstr);
+  free (regstr);
+  regstr = NULL;
+  argstr += strlen ((*blreg)->name);
+
+  if (argstr[0] == '+' && argstr[1] == '+')
+    {
+      argstr += 2;
+      if (*mode == MVI_OP_MODE_DIRECT)
+	as_bad (_("missing indirect operator for post-increment operand"));
+      if (*mode == MVI_OP_MODE_INDIRECT_PREDEC)
+	as_bad (_("cannot both pre-decrement and post-increment an operand"));
+      *mode = MVI_OP_MODE_INDIRECT_POSTINC;
+    }
+  if (argstr[0] != '\0')
+      as_bad (_("unexpected statements at and of instruction"));
+
+  if (*mode != MVI_OP_MODE_DIRECT)
+    {
+      if ((*blreg)->index != 1)
+	as_bad (_("only R1 can be used for indirect addressing"));
+
+      if ((*blreg)->regsel != RSEL_7_0
+	  && (*blreg)->regsel != RSEL_15_8
+	  && (*blreg)->regsel != RSEL_23_16
+	  && (*blreg)->regsel != RSEL_31_24)
+	as_bad (_("only byte mode can be used for R1"));
+    }
+}
+
+static void
+pru_assemble_arg_M (pru_insn_infoS *insn_info, const char *argstr)
+{
+  unsigned int mode, rdmode;
+  struct pru_reg *blreg;
+
+  pru_parse_mvi_operand (argstr, &blreg, &mode);
+
+  SET_INSN_FIELD (MVI_RS1_MODE, insn_info->insn_code, mode);
+  SET_INSN_FIELD (RS1, insn_info->insn_code, blreg->index);
+  SET_INSN_FIELD (RS1SEL, insn_info->insn_code, blreg->regsel);
+
+  /* Assume source operand would be parsed after destination one.  */
+  rdmode = GET_INSN_FIELD (MVI_RD_MODE, insn_info->insn_code);
+  if (rdmode == MVI_OP_MODE_DIRECT && mode == MVI_OP_MODE_DIRECT)
+    as_bad (_("at least one MVI operand must be indirect"));
+}
+
+static void
+pru_assemble_arg_m (pru_insn_infoS *insn_info, const char *argstr)
+{
+  unsigned int mode;
+  struct pru_reg *blreg;
+
+  pru_parse_mvi_operand (argstr, &blreg, &mode);
+
+  SET_INSN_FIELD (MVI_RD_MODE, insn_info->insn_code, mode);
+  SET_INSN_FIELD (RD, insn_info->insn_code, blreg->index);
+  SET_INSN_FIELD (RDSEL, insn_info->insn_code, blreg->regsel);
+}
+
 static void
 pru_assemble_arg_c (pru_insn_infoS *insn_info, const char *argstr)
 {
@@ -1264,6 +1350,17 @@ pru_assemble_arg_c (pru_insn_infoS *insn_info, const char *argstr)
     SET_INSN_FIELD (CB, insn_info->insn_code, cb);
 }
 
+static void
+pru_assemble_arg_t (pru_insn_infoS *insn_info, const char *argstr)
+{
+  unsigned long val = pru_assemble_noreloc_expression (argstr);
+
+  if (val != 0 && val != 1)
+    as_bad (_("invalid task manager mode %ld"), val);
+  else
+    SET_INSN_FIELD (TSKMGR_MODE, insn_info->insn_code, val);
+}
+
 static void
 pru_assemble_arg_w (pru_insn_infoS *insn_info, const char *argstr)
 {
@@ -1354,7 +1451,10 @@ pru_consume_arg (char *argstr, const char *parsestr)
     case 'S':
     case 'l':
     case 'n':
+    case 'm':
+    case 'M':
     case 'R':
+    case 't':
     case 'w':
     case 'x':
       /* We can't have %pmem here.  */
@@ -1680,9 +1780,18 @@ md_assemble (char *op_str)
 	    case 'n':
 	      pru_assemble_arg_n (insn, *argtk++);
 	      continue;
+	    case 'm':
+	      pru_assemble_arg_m (insn, *argtk++);
+	      continue;
+	    case 'M':
+	      pru_assemble_arg_M (insn, *argtk++);
+	      continue;
 	    case 'c':
 	      pru_assemble_arg_c (insn, *argtk++);
 	      continue;
+	    case 't':
+	      pru_assemble_arg_t (insn, *argtk++);
+	      continue;
 	    case 'w':
 	      pru_assemble_arg_w (insn, *argtk++);
 	      continue;
diff --git a/gas/testsuite/gas/pru/mvi.d b/gas/testsuite/gas/pru/mvi.d
new file mode 100644
index 00000000000..626fc0cf0c4
--- /dev/null
+++ b/gas/testsuite/gas/pru/mvi.d
@@ -0,0 +1,17 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: PRU mvi
+
+# Test the mvi instruction
+
+.*: +file format elf32-pru
+
+Disassembly of section .text:
+0+0000 <[^>]*> 2c204198 	mvib	r24.w0, \*r1.b2
+0+0004 <[^>]*> 2ca20101 	mvid	\*r1.b0, \*r1.b0
+0+0008 <[^>]*> 2ce20101 	mvid	\*r1.b0, \*--r1.b0
+0+000c <[^>]*> 2dc20101 	mvid	\*--r1.b0, \*r1.b0\+\+
+0+0010 <[^>]*> 2cc14101 	mviw	\*r1.b0, \*r1.b2\+\+
+0+0014 <[^>]*> 2cc14121 	mviw	\*r1.b1, \*r1.b2\+\+
+0+0018 <[^>]*> 2c4261f4 	mvid	r20, \*r1.b3\+\+
+0+001c <[^>]*> 2c6241f4 	mvid	r20, \*--r1.b2
+0+0020 <[^>]*> 2d82ff41 	mvid	\*--r1.b2, r31
diff --git a/gas/testsuite/gas/pru/mvi.s b/gas/testsuite/gas/pru/mvi.s
new file mode 100644
index 00000000000..cf23515668f
--- /dev/null
+++ b/gas/testsuite/gas/pru/mvi.s
@@ -0,0 +1,12 @@
+# Source file used to test the MVI instruction.
+
+foo:
+	mvib	r24.w0, *r1.b2
+	mvid	*r1.b0, *r1.b0
+	mvid	*r1.b0, *--r1.b0
+	mvid	*--r1.b0, *r1.b0++
+	mviw	*r1.b0, *r1.b2++
+	mviw	*r1.b1, *r1.b2++
+	mvid	r20, *r1.b3++
+	mvid	r20, *--r1.b2
+	mvid	*--r1.b2, r31
diff --git a/gas/testsuite/gas/pru/tsen.d b/gas/testsuite/gas/pru/tsen.d
new file mode 100644
index 00000000000..5c4779bb015
--- /dev/null
+++ b/gas/testsuite/gas/pru/tsen.d
@@ -0,0 +1,10 @@
+#objdump: -dr --prefix-addresses --show-raw-insn
+#name: PRU tsen
+
+# Test the TSEN instruction
+
+.*: +file format elf32-pru
+
+Disassembly of section .text:
+0+0000 <[^>]*> 32000000 	tsen	0
+0+0004 <[^>]*> 32800000 	tsen	1
diff --git a/gas/testsuite/gas/pru/tsen.s b/gas/testsuite/gas/pru/tsen.s
new file mode 100644
index 00000000000..716d7f476c5
--- /dev/null
+++ b/gas/testsuite/gas/pru/tsen.s
@@ -0,0 +1,5 @@
+# Source file used to test the TSEN instruction.
+
+foo:
+	tsen	0
+	tsen	1
diff --git a/include/opcode/pru.h b/include/opcode/pru.h
index f47860a681c..379b11e56a7 100644
--- a/include/opcode/pru.h
+++ b/include/opcode/pru.h
@@ -64,7 +64,8 @@ enum pru_instr_type
   prui_halt, prui_slp, prui_xin, prui_xout, prui_xchg, prui_sxin,
   prui_sxout, prui_sxchg, prui_loop, prui_iloop, prui_qbgt, prui_qbge,
   prui_qblt, prui_qble, prui_qbeq, prui_qbne, prui_qba, prui_qbbs,
-  prui_qbbc, prui_lbbo, prui_sbbo, prui_lbco, prui_sbco
+  prui_qbbc, prui_lbbo, prui_sbbo, prui_lbco, prui_sbco, prui_tsen,
+  prui_mvib, prui_mviw, prui_mvid
 };
 
 /* This structure holds information for a particular instruction.
@@ -81,11 +82,14 @@ enum pru_instr_type
      j - a 5.3-bit right source register index OR 18-bit PC address
      l - burst length (unsigned 7-bit immediate or r0.b[0-3]) for xLBCO
      n - burst length (unsigned 7-bit immediate or r0.b[0-3]) for XFR
+     m - MVI destination operand
+     M - MVI source operand
      o - a 10-bit signed PC-relative offset
      O - an 8-bit unsigned PC-relative offset for LOOP termination point
      R - a 5-bit destination register index
      s - a 5.3-bit left source register index
      S - a 5-bit left source register index
+     t - task manager mode (0: disabled, 1: enabled)
      w - a single bit for "WakeOnStatus"
      W - a 16-bit unsigned immediate with IO=0 field (LDI)
      x - an 8-bit XFR wide-bus address immediate
@@ -236,15 +240,19 @@ struct pru_reg
 #define SUBOP_LMBD			3u
 #define SUBOP_SCAN			4u
 #define SUBOP_HALT			5u
-#define SUBOP_RSVD_FOR_MVIx		6u
+#define SUBOP_MVIX			6u
 #define SUBOP_XFR			7u
 #define SUBOP_LOOP			8u
+#define SUBOP_TSEN			9u
 #define SUBOP_RSVD_FOR_RFI		14u
 #define SUBOP_SLP			15u
 
 #define OP_SH_WAKEONSTATUS		23
 #define OP_MASK_WAKEONSTATUS		(0x1u << 23)
 
+#define OP_SH_TSKMGR_MODE		23
+#define OP_MASK_TSKMGR_MODE		(0x1u << 23)
+
 /* Format 2 XFR specific fields.  */
 #define OP_SH_SUBOP_XFR			23
 #define OP_MASK_SUBOP_XFR		(3u << 23)
@@ -265,6 +273,23 @@ struct pru_reg
 #define OP_SH_LOOP_JMPOFFS		0
 #define OP_MASK_LOOP_JMPOFFS		(0xffu << 0)
 
+/* Format 2 MVI specific fields.  */
+#define OP_SH_MVI_RS1_MODE		21
+#define OP_MASK_MVI_RS1_MODE		(3u << 21)
+#define OP_SH_MVI_RD_MODE		23
+#define OP_MASK_MVI_RD_MODE		(3u << 23)
+#define OP_SH_MVI_LEN			16
+#define OP_MASK_MVI_LEN			(3u << 16)
+
+#define MVI_OP_MODE_DIRECT		0u
+#define MVI_OP_MODE_INDIRECT		1u
+#define MVI_OP_MODE_INDIRECT_POSTINC	2u
+#define MVI_OP_MODE_INDIRECT_PREDEC	3u
+
+#define MVI_LEN_BYTE			0u
+#define MVI_LEN_WORD			1u
+#define MVI_LEN_DWORD			2u
+
 /* Format 4 specific fields.  */
 #define OP_SH_BROFF98			25
 #define OP_MASK_BROFF98			(0x3u << 25)
@@ -331,6 +356,12 @@ struct pru_reg
 #define OP_MATCH_SCAN	(OP_MATCH_FMT2_OP | (SUBOP_SCAN << OP_SH_SUBOP))
 #define OP_MATCH_HALT	(OP_MATCH_FMT2_OP | (SUBOP_HALT << OP_SH_SUBOP))
 #define OP_MATCH_SLP	(OP_MATCH_FMT2_OP | (SUBOP_SLP << OP_SH_SUBOP))
+#define OP_MATCH_MVIB	(OP_MATCH_FMT2_OP | (SUBOP_MVIX << OP_SH_SUBOP) \
+			 | (MVI_LEN_BYTE << OP_SH_MVI_LEN))
+#define OP_MATCH_MVIW	(OP_MATCH_FMT2_OP | (SUBOP_MVIX << OP_SH_SUBOP) \
+			 | (MVI_LEN_WORD << OP_SH_MVI_LEN))
+#define OP_MATCH_MVID	(OP_MATCH_FMT2_OP | (SUBOP_MVIX << OP_SH_SUBOP) \
+			 | (MVI_LEN_DWORD << OP_SH_MVI_LEN))
 #define OP_MATCH_XFR	(OP_MATCH_FMT2_OP | (SUBOP_XFR << OP_SH_SUBOP))
 #define OP_MATCH_SXFR	(OP_MATCH_XFR | OP_MASK_XFR_S)
 #define OP_MATCH_XIN	(OP_MATCH_XFR | (SUBOP_XFR_XIN << OP_SH_SUBOP_XFR))
@@ -342,6 +373,7 @@ struct pru_reg
 #define OP_MATCH_LOOP	(OP_MATCH_FMT2_OP | (SUBOP_LOOP << OP_SH_SUBOP))
 #define OP_MATCH_ILOOP	(OP_MATCH_FMT2_OP | (SUBOP_LOOP << OP_SH_SUBOP) \
 			 | OP_MASK_LOOP_INTERRUPTIBLE)
+#define OP_MATCH_TSEN	(OP_MATCH_FMT2_OP | (SUBOP_TSEN << OP_SH_SUBOP))
 
 #define OP_MATCH_QBGT	(OP_MATCH_FMT4_OP | OP_MASK_GT)
 #define OP_MATCH_QBGE	(OP_MATCH_FMT4_OP | OP_MASK_GT | OP_MASK_EQ)
@@ -394,6 +426,9 @@ struct pru_reg
 #define OP_MASK_LOOP_OP		(OP_MASK_FMT2_OP | OP_MASK_SUBOP \
 				 | OP_MASK_LOOP_INTERRUPTIBLE)
 
+#define OP_MASK_MVIX_OP		(OP_MASK_FMT2_OP | OP_MASK_SUBOP \
+				 | OP_MASK_MVI_LEN)
+
 /* These are the data structures we use to hold the instruction information.  */
 extern const struct pru_opcode pru_opcodes[];
 extern const int bfd_pru_num_opcodes;
diff --git a/opcodes/pru-dis.c b/opcodes/pru-dis.c
index 5465c26a138..547e3f3a2f8 100644
--- a/opcodes/pru-dis.c
+++ b/opcodes/pru-dis.c
@@ -66,15 +66,34 @@ pru_find_opcode (unsigned long opcode)
 #define NUMREGNAMES (32 * 8)
 
 static void
-pru_print_insn_arg_reg (unsigned int r, unsigned int sel,
-			disassemble_info *info)
+pru_print_insn_arg_indreg (unsigned int r, unsigned int sel,
+			   unsigned int mode,
+			   disassemble_info *info)
 {
+  const char *fmtstr;
   unsigned int i = r * RSEL_NUM_ITEMS + sel;
   assert (i < (unsigned int)pru_num_regs);
   assert (i < NUMREGNAMES);
-  (*info->fprintf_func) (info->stream, "%s", pru_regs[i].name);
+
+  switch (mode)
+    {
+    case MVI_OP_MODE_DIRECT:		fmtstr = "%s"; break;
+    case MVI_OP_MODE_INDIRECT:		fmtstr = "*%s"; break;
+    case MVI_OP_MODE_INDIRECT_POSTINC:	fmtstr = "*%s++"; break;
+    case MVI_OP_MODE_INDIRECT_PREDEC:	fmtstr = "*--%s"; break;
+    default:				fmtstr = "<invalid>%s"; break;
+    }
+  (*info->fprintf_func) (info->stream, fmtstr, pru_regs[i].name);
+}
+
+static void
+pru_print_insn_arg_reg (unsigned int r, unsigned int sel,
+			disassemble_info *info)
+{
+  pru_print_insn_arg_indreg (r, sel, MVI_OP_MODE_DIRECT, info);
 }
 
+
 /* The function pru_print_insn_arg uses the character pointed
    to by ARGPTR to determine how it print the next token or separator
    character in the arguments to an instruction.  */
@@ -186,6 +205,18 @@ pru_print_insn_arg (const char *argptr,
 	  (*info->fprintf_func) (info->stream, "r0.b%ld", i);
 	}
       break;
+    case 'm':
+      pru_print_insn_arg_indreg (GET_INSN_FIELD (RD, opcode),
+				 GET_INSN_FIELD (RDSEL, opcode),
+				 GET_INSN_FIELD (MVI_RD_MODE, opcode),
+				 info);
+      break;
+    case 'M':
+      pru_print_insn_arg_indreg (GET_INSN_FIELD (RS1, opcode),
+				 GET_INSN_FIELD (RS1SEL, opcode),
+				 GET_INSN_FIELD (MVI_RS1_MODE, opcode),
+				 info);
+      break;
     case 'n':
       i = GET_INSN_FIELD (XFR_LENGTH, opcode);
       if (i < LSSBBO_BYTECOUNT_R0_BITS7_0)
@@ -200,6 +231,10 @@ pru_print_insn_arg (const char *argptr,
       i = GET_INSN_FIELD (CB, opcode);
       (*info->fprintf_func) (info->stream, "%ld", i);
       break;
+    case 't':
+      i = GET_INSN_FIELD (TSKMGR_MODE, opcode);
+      (*info->fprintf_func) (info->stream, "%ld", i);
+      break;
     case 'w':
       i = GET_INSN_FIELD (WAKEONSTATUS, opcode);
       (*info->fprintf_func) (info->stream, "%ld", i);
diff --git a/opcodes/pru-opc.c b/opcodes/pru-opc.c
index ee7fb16d8d4..aeef5224b29 100644
--- a/opcodes/pru-opc.c
+++ b/opcodes/pru-opc.c
@@ -125,9 +125,18 @@ const struct pru_opcode pru_opcodes[] =
    OP_MATCH_LMBD, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, unsigned_immed8_overflow},
   { "halt", prui_halt, "",
    OP_MATCH_HALT, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, no_overflow},
+  { "tsen", prui_tsen, "t",
+   OP_MATCH_TSEN, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, no_overflow},
   { "slp", prui_slp, "w",
    OP_MATCH_SLP, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, no_overflow},
 
+  { "mvib", prui_mvib, "m,M",
+   OP_MATCH_MVIB, OP_MASK_MVIX_OP, 0, no_overflow},
+  { "mviw", prui_mviw, "m,M",
+   OP_MATCH_MVIW, OP_MASK_MVIX_OP, 0, no_overflow},
+  { "mvid", prui_mvid, "m,M",
+   OP_MATCH_MVID, OP_MASK_MVIX_OP, 0, no_overflow},
+
   { "xin", prui_xin, "x,D,n",
    OP_MATCH_XIN, OP_MASK_XFR_OP, 0, unsigned_immed8_overflow},
   { "xout", prui_xout, "x,D,n",
