 arch/x86/include/asm/uaccess.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 5838fa911aa0..33597722cfc1 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -411,6 +411,24 @@ struct __large_struct { unsigned long buf[100]; };
  * we do not write to any memory gcc knows about, so there are no
  * aliasing issues.
  */
+#ifdef CC_HAVE_ASM_GOTO
+#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
+do {	__label__ error_label;						\
+	asm goto(ASM_STAC "\n"						\
+		 "1:	mov"itype" %"rtype"0,%1\n"			\
+		 "	" ASM_CLAC "\n"					\
+		 _ASM_EXTABLE(1b,%l[error_label])			\
+		 : /* no outputs */					\
+		 : ltype(x), "m" (__m(addr))				\
+		 : /* no clobbers */					\
+		 : error_label);					\
+	err = 0;							\
+	break;								\
+error_label:								\
+	asm volatile(ASM_CLAC);						\
+	err = errret;							\
+} while (0)
+#else
 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
 	asm volatile(ASM_STAC "\n"					\
 		     "1:	mov"itype" %"rtype"1,%2\n"		\
@@ -422,6 +440,7 @@ struct __large_struct { unsigned long buf[100]; };
 		     _ASM_EXTABLE(1b, 3b)				\
 		     : "=r"(err)					\
 		     : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
+#endif
 
 #define __put_user_asm_ex(x, addr, itype, rtype, ltype)			\
 	asm volatile("1:	mov"itype" %"rtype"0,%1\n"		\
