diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index db3527b..972a533 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2016-08-22  Tom Tromey  <tom@tromey.com>
+
+	PR gdb/11616:
+	* dwarf2read.c (decode_locdesc): Handle DW_OP_form_tls_address.
+	* dwarf2loc.c (dwarf2_compile_expr_to_ax): Handle
+	DW_OP_form_tls_address.
+	(locexpr_describe_location_piece): Likewise.
+	* dwarf2expr.h (struct dwarf_expr_context_funcs): Update comment.
+	* dwarf2expr.c (execute_stack_op): Handle DW_OP_form_tls_address.
+	(ctx_no_get_tls_address): Mention DW_OP_form_tls_address.
+	* compile/compile-loc2c.c (struct insn_info): Update comment.
+	(compute_stack_depth_worker): Handle DW_OP_form_tls_address.
+
 2016-08-19  Yao Qi  <yao.qi@linaro.org>
 
 	* aarch64-tdep.c (aarch64_analyze_prologue): Handle register
diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c
index 1a267b8..e8bef55 100644
--- a/gdb/compile/compile-loc2c.c
+++ b/gdb/compile/compile-loc2c.c
@@ -48,9 +48,9 @@ struct insn_info
 
   unsigned int label : 1;
 
-  /* Whether this instruction is DW_OP_GNU_push_tls_address.  This is
-     a hack until we can add a feature to glibc to let us properly
-     generate code for TLS.  */
+  /* Whether this instruction is DW_OP_GNU_push_tls_address or
+     DW_OP_form_tls_address.  This is a hack until we can add a
+     feature to glibc to let us properly generate code for TLS.  */
 
   unsigned int is_tls : 1;
 };
@@ -323,6 +323,7 @@ compute_stack_depth_worker (int start, int *need_tempvar,
 	  break;
 
 	case DW_OP_GNU_push_tls_address:
+	case DW_OP_form_tls_address:
 	  info[ndx].is_tls = 1;
 	  break;
 
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index 7bf3c78..7eb1982 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -1257,6 +1257,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  break;
 
 	case DW_OP_GNU_push_tls_address:
+	case DW_OP_form_tls_address:
 	  /* Variable is at a constant offset in the thread-local
 	  storage block into the objfile for the current thread and
 	  the dynamic linker module containing this expression.  Here
@@ -1533,7 +1534,7 @@ ctx_no_get_frame_pc (void *baton)
 CORE_ADDR
 ctx_no_get_tls_address (void *baton, CORE_ADDR offset)
 {
-  error (_("%s is invalid in this context"), "DW_OP_GNU_push_tls_address");
+  error (_("%s is invalid in this context"), "DW_OP_form_tls_address");
 }
 
 /* Stub dwarf_expr_context_funcs.dwarf_call implementation.  */
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 3d7ca00..cbab45b 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -56,7 +56,7 @@ struct dwarf_expr_context_funcs
   CORE_ADDR (*get_frame_pc) (void *baton);
 
   /* Return the thread-local storage address for
-     DW_OP_GNU_push_tls_address.  */
+     DW_OP_GNU_push_tls_address or DW_OP_form_tls_address.  */
   CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset);
 
   /* Execute DW_AT_location expression for the DWARF expression subroutine in
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index e60475f..946ddf8 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -3571,6 +3571,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
 	  break;
 
 	case DW_OP_GNU_push_tls_address:
+	case DW_OP_form_tls_address:
 	  unimplemented (op);
 	  break;
 
@@ -3907,7 +3908,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 	   && (data[0] == DW_OP_addr
 	       || (addr_size == 4 && data[0] == DW_OP_const4u)
 	       || (addr_size == 8 && data[0] == DW_OP_const8u))
-	   && data[1 + addr_size] == DW_OP_GNU_push_tls_address
+	   && (data[1 + addr_size] == DW_OP_GNU_push_tls_address
+	       || data[1 + addr_size] == DW_OP_form_tls_address)
 	   && piece_end_p (data + 2 + addr_size, end))
     {
       ULONGEST offset;
@@ -3930,7 +3932,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
 	   && data + 1 + (leb128_size = skip_leb128 (data + 1, end)) < end
 	   && data[0] == DW_OP_GNU_const_index
 	   && leb128_size > 0
-	   && data[1 + leb128_size] == DW_OP_GNU_push_tls_address
+	   && (data[1 + leb128_size] == DW_OP_GNU_push_tls_address
+	       || data[1 + leb128_size] == DW_OP_form_tls_address)
 	   && piece_end_p (data + 2 + leb128_size, end))
     {
       uint64_t offset;
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 924b417..9ad2caa 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -20817,6 +20817,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
 	  break;
 
         case DW_OP_GNU_push_tls_address:
+	case DW_OP_form_tls_address:
 	  /* The top of the stack has the offset from the beginning
 	     of the thread control block at which the variable is located.  */
 	  /* Nothing should follow this operator, so the top of stack would
