diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7820302..58df751 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2016-08-02  David Taylor  <dtaylor@emc.com>
+
+	* ax-gdb.c (gen_expr): Add support for assignment to more than
+	just trace state variables.
+	(gen_expr_binop_rest): Ditto.
+	* ax-general.c (ax_setreg): New function.
+	* ax.h (ax_setreg): Declare it.
+	* common/ax.def (setmem8, setmem16, setmem32, setmem64, setreg):
+	New agent bytecodes.
+
 2016-08-01  Joel Brobecker  <brobecker@adacore.com>
 
 	* NEWS: Create a new section for the next release branch.
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 7c6cb64..cfe46af 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -1895,6 +1895,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
 
 	  (*pc) += 3;
 	  gen_expr (exp, pc, ax, value);
+	  require_rvalue (ax, value);
 	  tsv = find_trace_state_variable (name);
 	  if (tsv)
 	    {
@@ -1903,11 +1904,62 @@ gen_expr (struct expression *exp, union exp_element **pc,
 		ax_tsv (ax, aop_tracev, tsv->number);
 	    }
 	  else
-	    error (_("$%s is not a trace state variable, "
-		     "may not assign to it"), name);
+	    error (_("$%s is convenience variable, not a trace state variable, "
+		     "You may not assign to it."), name);
+	}
+      else if ((*pc)[0].opcode == OP_VAR_VALUE)
+	{
+	  int len;
+	  enum agent_op opcode;
+	  struct type *type = check_typedef (SYMBOL_TYPE ((*pc)[2].symbol));
+
+	  len = TYPE_LENGTH (type);
+
+	  if (len == 1)
+	    opcode = aop_setmem8;
+	  else if (len == 2)
+	    opcode = aop_setmem16;
+	  else if (len == 4)
+	    opcode = aop_setmem32;
+	  else if (len == 8)
+	    opcode = aop_setmem64;
+	  else
+	    error (_("Unsupported OP_VAR_VALUE of length %d"), len);
+
+	  gen_expr (exp, pc, ax, &value1);
+
+	  if (value1.kind != axs_lvalue_register)
+	    {
+	      if (ax->tracing)
+		ax_trace_quick (ax, len); /* record original value */
+	    }
+
+	  gen_expr (exp, pc, ax, value);
+	  gen_usual_unary (exp, ax, value);
+	  require_rvalue (ax, value);
+
+	  if (value1.kind == axs_lvalue_register)
+	    {
+	      ax_reg_mask (ax, value1.u.reg);
+	      ax_setreg (ax, value1.u.reg);
+	    }
+	  else
+	    ax_simple (ax, opcode);
+	}
+      else if ((*pc)[0].opcode == OP_REGISTER)
+	{
+	  gen_expr (exp, pc, ax, &value1);
+
+	  gen_expr (exp, pc, ax, value);
+	  gen_usual_unary (exp, ax, value);
+	  require_rvalue (ax, value);
+
+	  ax_reg_mask (ax, value1.u.reg);
+	  ax_setreg (ax, value1.u.reg);
 	}
       else
-	error (_("May only assign to trace state variables"));
+	error (_("Opcode %s unsupported for agent expressions"),
+	       op_name_standard ((*pc)[0].opcode));
       break;
 
     case BINOP_ASSIGN_MODIFY:
@@ -1939,8 +1991,74 @@ gen_expr (struct expression *exp, union exp_element **pc,
 		ax_tsv (ax, aop_tracev, tsv->number);
 	    }
 	  else
-	    error (_("$%s is not a trace state variable, "
-		     "may not assign to it"), name);
+	    error (_("Convenience variables such as '$%s' are known only to the debugger and "
+		     "you may not assign to them in an action."), name);
+	}
+      else if ((*pc)[0].opcode == OP_VAR_VALUE)
+	{
+	  int len;
+	  enum agent_op opcode;
+	  struct type *type;
+	  struct axs_value saved_value;
+
+	  gen_expr (exp, pc, ax, value);
+	  type = check_typedef (value->type);
+	  len = TYPE_LENGTH (type);
+
+	  if (len == 1)
+	    opcode = aop_setmem8;
+	  else if (len == 2)
+	    opcode = aop_setmem16;
+	  else if (len == 4)
+	    opcode = aop_setmem32;
+	  else if (len == 8)
+	    opcode = aop_setmem64;
+	  else
+	    error (_("Unsupported OP_VAR_VALUE of length %d"), len);
+
+	  if (value->kind != axs_lvalue_register)
+	    {
+	      ax_simple (ax, aop_dup); /* keep the address around */
+
+	      if (ax->tracing)
+		ax_trace_quick (ax, len); /* record original value */
+	    }
+
+	  value1.kind = value->kind;
+	  value1.type = value->type;
+	  value1.u.reg = value->u.reg;
+
+	  /* gen_expr_binop_rest will set value, value1, and value2.
+	     And typically value for value, value1 ends up as
+	     axs_rvalue.  We need to remember whether it was a
+	     register and, if so, which register */
+	  saved_value.kind = value->kind;
+	  saved_value.u.reg = value->u.reg;
+
+	  /* Now do right half of expression.  */
+	  gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
+
+	  /* We have the result of the binary op, set the variable */
+	  if (saved_value.kind == axs_lvalue_register)
+	    {
+	      ax_reg_mask (ax, saved_value.u.reg);
+	      ax_setreg (ax, saved_value.u.reg);
+	    }
+	  else
+	    ax_simple (ax, opcode);
+	}
+      else if ((*pc)[0].opcode == OP_REGISTER)
+	{
+	  gen_expr (exp, pc, ax, value);
+
+	  value1.kind = value->kind;
+	  value1.type = value->type;
+	  value1.u.reg = value->u.reg;
+
+	  /* Now do right half of expression.  */
+	  gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
+
+	  ax_setreg (ax, value->u.reg);
 	}
       else
 	error (_("May only assign to trace state variables"));
@@ -2246,6 +2364,7 @@ gen_expr_binop_rest (struct expression *exp,
 {
   struct type *int_type = builtin_type (exp->gdbarch)->builtin_int;
 
+  require_rvalue (ax, value1);
   gen_expr (exp, pc, ax, value2);
   gen_usual_unary (exp, ax, value2);
   gen_usual_arithmetic (exp, ax, value1, value2);
diff --git a/gdb/ax-general.c b/gdb/ax-general.c
index 7f27a45..5406ab8 100644
--- a/gdb/ax-general.c
+++ b/gdb/ax-general.c
@@ -323,6 +323,28 @@ ax_reg (struct agent_expr *x, int reg)
     }
 }
 
+/* Assemble code to pop the top of stack and set register number REG
+   to its value.  */
+
+void
+ax_setreg (struct agent_expr *x, int reg)
+{
+  if (reg >= gdbarch_num_regs (x->gdbarch))
+    error (_("register number '%d' is a pseudo register or is out of range"), reg);
+  else
+    {
+      /* Make sure the register number is in range.  */
+      if (reg < 0 || reg > 0xffff)
+        error (_("GDB bug: ax-general.c (ax_reg): "
+		 "register number out of range"));
+      grow_expr (x, 3);
+      x->buf[x->len] = aop_setreg;
+      x->buf[x->len + 1] = (reg >> 8) & 0xff;
+      x->buf[x->len + 2] = (reg) & 0xff;
+      x->len += 3;
+    }
+}
+
 /* Assemble code to operate on a trace state variable.  */
 
 void
diff --git a/gdb/ax.h b/gdb/ax.h
index 536efe8..7b10355 100644
--- a/gdb/ax.h
+++ b/gdb/ax.h
@@ -234,6 +234,11 @@ extern void ax_const_d (struct agent_expr *EXPR, LONGEST d);
    stack.  */
 extern void ax_reg (struct agent_expr *EXPR, int REG);
 
+/* Assemble code to pop the top of stack and set register number REG
+   to its value.  */
+
+extern void ax_setreg (struct agent_expr *EXPR, int REG);
+
 /* Add the given register to the register mask of the expression.  */
 extern void ax_reg_mask (struct agent_expr *ax, int reg);
 
diff --git a/gdb/common/ax.def b/gdb/common/ax.def
index f375373..86cf4b5 100644
--- a/gdb/common/ax.def
+++ b/gdb/common/ax.def
@@ -95,3 +95,9 @@ DEFOP (pick, 1, 0, 0, 1, 0x32)
 DEFOP (rot, 0, 0, 3, 3, 0x33)
 /* Both the argument and consumed numbers are dynamic for this one.  */
 DEFOP (printf, 0, 0, 0, 0, 0x34)
+/* The following five operands are not yet implemented.  */
+DEFOP (setmem8, 0, 8, 2, 1, 0x35)
+DEFOP (setmem16, 0, 16, 2, 1, 0x36)
+DEFOP (setmem32, 0, 32, 2, 1, 0x37)
+DEFOP (setmem64, 0, 64, 2, 1, 0x38)
+DEFOP (setreg, 2, 0, 1, 1, 0x39)
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index cc9bc70..35afac2 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2016-08-02  David Taylor  <dtaylor@emc.com>
+
+	* agentexpr.texi (Bytecode Descriptions): Add descriptions of
+	bytecodes setmem8, setmem16, setmem32, setmem64, and setreg.
+
 2016-07-25  Tim Wiederhake  <tim.wiederhake@intel.com>
 
 	* gdb.texinfo: Resume btrace on reconnect.
diff --git a/gdb/doc/agentexpr.texi b/gdb/doc/agentexpr.texi
index ade7638..23e0ccc 100644
--- a/gdb/doc/agentexpr.texi
+++ b/gdb/doc/agentexpr.texi
@@ -515,6 +515,25 @@ stack.  If the purpose of the expression was to compute an lvalue or a
 range of memory, then the next-to-top of the stack is the lvalue's
 address, and the top of the stack is the lvalue's size, in bytes.
 
+@item @code{setmem8} (0x35): @var{addr} @var{value} @result{} @var{value}
+@itemx @code{setmem16} (0x36): @var{addr} @var{value} @result{} @var{value}
+@itemx @code{setmem32} (0x37): @var{addr} @var{value} @result{} @var{value}
+@itemx @code{setmem64} (0x38): @var{addr} @var{value} @result{} @var{value}
+For bytecode @code{setmem}@var{n}, set an @var{n}-bit value at
+@var{addr}, using the @var{n}-bit least significant bits of @var{value}
+and natural target endianness.  The address @var{addr} is popped off the
+stack; the value @var{value} is left on the stack.
+
+If attempting to write memory at @var{addr} would cause a processor
+exception of some sort, terminate with an error.
+
+@item @code{setreg} (0x39) @var{regnum}: @var{value} @result{} @var{value}
+Set register @var{regnum} to @var{value}.  The value @var{value} is left
+on the stack.
+
+If the register is read-only or if attempting to write @var{value} to it
+would cause a processor exception of some sort, terminate with an error.
+
 @end table
 
 
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index f4523f7..5990ce2 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-02  David Taylor  <dtaylor@emc.com>
+
+	* ax.c (compile_bytecodes): Add cases for new bytecodes (setmem8,
+	setmem16, setmem32, setmem64, and setreg).
+	* tracepoint.c (write_inferior_memory, agent_mem_write): New
+	functions.
+	* tracepoint.h (agent_mem_write): Declare.
+
 2016-08-02  Yao Qi  <yao.qi@linaro.org>
 
 	* thread-db.c (struct thread_db) <td_ta_event_getmsg_p>: Remove.
diff --git a/gdb/gdbserver/ax.c b/gdb/gdbserver/ax.c
index d5144c2..bf33d42 100644
--- a/gdb/gdbserver/ax.c
+++ b/gdb/gdbserver/ax.c
@@ -736,6 +736,26 @@ compile_bytecodes (struct agent_expr *aexpr)
 	  UNHANDLED;
 	  break;
 
+	case gdb_agent_op_setmem8:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_setmem16:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_setmem32:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_setmem64:
+	  UNHANDLED;
+	  break;
+
+	case gdb_agent_op_setreg:
+	  UNHANDLED;
+	  break;
+
 	  /* GDB never (currently) generates any of these ops.  */
 	case gdb_agent_op_float:
 	case gdb_agent_op_ref_float:
@@ -1322,6 +1342,53 @@ gdb_eval_agent_expr (struct eval_agent_expr_context *ctx,
 	  }
 	  break;
 
+	  /* for the setmem{8,16,32,64} opcodes, we leave the value on
+	     the stack (in top), but the address written to is popped
+	     from the stack */
+	case gdb_agent_op_setmem8:
+	  cnv.u8.val = (unsigned char) top;
+	  agent_mem_write (ctx, cnv.u8.bytes, stack[sp--], 1);
+	  break;
+
+	case gdb_agent_op_setmem16:
+	  cnv.u16.val = (unsigned short) top;
+	  agent_mem_write (ctx, cnv.u16.bytes, stack[sp--], 2);
+	  break;
+
+	case gdb_agent_op_setmem32:
+	  cnv.u32.val = (unsigned int) top;
+	  agent_mem_write (ctx, cnv.u32.bytes, stack[sp--], 4);
+	  break;
+
+	case gdb_agent_op_setmem64:
+	  cnv.u64.val = (ULONGEST) top;
+	  agent_mem_write (ctx, cnv.u64.bytes, stack[sp--], 8);
+	  break;
+
+	case gdb_agent_op_setreg:
+	  arg = aexpr->bytes[pc++];
+	  arg = (arg << 8) + aexpr->bytes[pc++];
+	  switch (register_size (ctx->regcache->tdesc, arg))
+	    {
+	    case 8:
+	      cnv.u8.val = (unsigned char) top;
+	      break;
+	    case 16:
+	      cnv.u16.val = (unsigned short) top;
+	      break;
+	    case 32:
+	      cnv.u32.val = (unsigned int) top;
+	      break;
+	    case 64:
+	      cnv.u64.val = (ULONGEST) top;
+	      break;
+	    default:
+	      internal_error (__FILE__, __LINE__,
+			      "unhandled register size");
+	    }
+	  supply_register (ctx->regcache, arg, &cnv);
+	  break;
+
 	  /* GDB never (currently) generates any of these ops.  */
 	case gdb_agent_op_float:
 	case gdb_agent_op_ref_float:
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index c07e525..c4ee465 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -357,6 +357,13 @@ read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
   return 0;
 }
 
+int
+write_inferior_memory (CORE_ADDR memaddr, unsigned char const *myaddr, int len)
+{
+  memcpy ((void *) (uintptr_t) memaddr, myaddr, len);
+  return 0;
+}
+
 /* Call this in the functions where GDBserver places a breakpoint, so
    that the compiler doesn't try to be clever and skip calling the
    function at all.  This is necessary, even if we tell the compiler
@@ -4948,6 +4955,14 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
 }
 
 /* Do memory copies for bytecodes.  */
+int
+agent_mem_write (struct eval_agent_expr_context *ctx,
+		 unsigned char *from, CORE_ADDR to, ULONGEST len)
+{
+  return write_inferior_memory (to, from, len);
+}
+
+/* Do memory copies for bytecodes.  */
 /* Do the recording of memory blocks for actions and bytecodes.  */
 
 int
diff --git a/gdb/gdbserver/tracepoint.h b/gdb/gdbserver/tracepoint.h
index 679a32a..0886f8e 100644
--- a/gdb/gdbserver/tracepoint.h
+++ b/gdb/gdbserver/tracepoint.h
@@ -154,6 +154,10 @@ int agent_mem_read (struct eval_agent_expr_context *ctx,
 		    unsigned char *to, CORE_ADDR from,
 		    ULONGEST len);
 
+int agent_mem_write (struct eval_agent_expr_context *ctx,
+		     unsigned char *from, CORE_ADDR to,
+		     ULONGEST len);
+
 LONGEST agent_get_trace_state_variable_value (int num);
 void agent_set_trace_state_variable_value (int num, LONGEST val);
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 51e8073..8bafcdc 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2016-08-02  David Taylor  <dtaylor@emc.com>
+
+	* gdb.trace/actions.c: (get_int_test): New variable.
+	(struct GDB_STRUCT_TEST): New int field.
+	(gdb_c_test): Assign values to new variable and struct member.
+	* gdb.trace/ax.exp: Add new tests.
+
 2016-08-01  Yao Qi  <yao.qi@linaro.org>
 
 	* gdb.threads/process-dies-while-detaching.exp (do_test): Set
diff --git a/gdb/testsuite/gdb.trace/actions.c b/gdb/testsuite/gdb.trace/actions.c
index aedd202..ebc1559 100644
--- a/gdb/testsuite/gdb.trace/actions.c
+++ b/gdb/testsuite/gdb.trace/actions.c
@@ -25,12 +25,14 @@
 
 static char   gdb_char_test;
 static short  gdb_short_test;
+static int    gdb_int_test;
 static long   gdb_long_test;
 static char   gdb_arr_test[25];
 static struct GDB_STRUCT_TEST
 {
   char   c;
   short  s;
+  int    i;
   long   l;
   int    bfield : 11;	/* collect bitfield */
   char   arr[25];
@@ -97,6 +99,7 @@ unsigned long   gdb_c_test( unsigned long *parm )
 
    gdb_char_test   = gdb_struct1_test.c = (char)   ((long) parm[1] & 0xff);
    gdb_short_test  = gdb_struct1_test.s = (short)  ((long) parm[2] & 0xffff);
+   gdb_int_test    = gdb_struct1_test.i = (int)    ((long) parm[3] & 0xffffffff);
    gdb_long_test   = gdb_struct1_test.l = (long)   ((long) parm[3] & 0xffffffff);
    gdb_union1_test.l = (long) parm[4];
    gdb_arr_test[0] = gdb_struct1_test.arr[0] = (char) ((long) parm[1] & 0xff);
@@ -113,7 +116,7 @@ unsigned long   gdb_c_test( unsigned long *parm )
    gdb_recursion_test_ptr (3, (long) parm[1], (long) parm[2], (long) parm[3],
 		       (long) parm[4], (long) parm[5], (long) parm[6]);
 
-   gdb_char_test = gdb_short_test = gdb_long_test = 0;
+   gdb_char_test = gdb_short_test = gdb_int_test = gdb_long_test = 0;
    gdb_structp_test  = (void *) 0;
    gdb_structpp_test = (void *) 0;
    memset ((char *) &gdb_struct1_test, 0, sizeof (gdb_struct1_test));
diff --git a/gdb/testsuite/gdb.trace/ax.exp b/gdb/testsuite/gdb.trace/ax.exp
index 5e9783f..da424f3 100644
--- a/gdb/testsuite/gdb.trace/ax.exp
+++ b/gdb/testsuite/gdb.trace/ax.exp
@@ -82,6 +82,17 @@ gdb_test "maint agent &gdb_long_test < &gdb_short_test" "" "maint agent &gdb_lon
 
 gdb_test "maint agent (unsigned char)1L" ".*ext 8.*" "maint agent (unsigned char)1L"
 
+gdb_test "maint agent long_long = 12" "" "maint agent long_long = 12"
+
+gdb_test "maint agent gdb_char_test = 19" "" "maint agent gdb_char_test = 19"
+
+gdb_test "maint agent gdb_short_test = 24" "" "maint agent gdb_short_test = 24"
+
+gdb_test "maint agent gdb_int_test = 35" "" "maint agent gdb_int_test = 35"
+
+gdb_test "maint agent gdb_long_test = 45" "" "maint agent gdb_long_test = 45"
+
+gdb_test "maint agent -at gdb_recursion_test, depth = 100" "" "maint agent -at gdb_recursion_test, depth = 100"
 # Now test eval version of agent expressions.
 
 gdb_test "maint agent-eval 12" ".*const8 12.*end.*" "maint agent-eval 12"
@@ -130,3 +141,15 @@ gdb_test "maint agent-eval &gdb_long_test == &gdb_short_test" ".*equal.*end.*" "
 
 gdb_test "maint agent-eval &gdb_long_test < &gdb_short_test" "" "maint agent-eval &gdb_long_test < &gdb_short_test"
 
+
+gdb_test "maint agent-eval long_long = 12" "" "maint agent long_long = 12"
+
+gdb_test "maint agent-eval gdb_char_test = 19" "" "maint agent gdb_char_test = 19"
+
+gdb_test "maint agent-eval gdb_short_test = 24" "" "maint agent gdb_short_test = 24"
+
+gdb_test "maint agent-eval gdb_int_test = 35" "" "maint agent gdb_int_test = 35"
+
+gdb_test "maint agent-eval gdb_long_test = 45" "" "maint agent gdb_long_test = 45"
+
+gdb_test "maint agent-eval -at gdb_recursion_test, depth = 100" "" "maint agent -at gdb_recursion_test, depth = 100"
