--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -288,6 +288,7 @@ struct _i386_insn
     unsigned int flags[MAX_OPERANDS];
 #define Operand_PCrel 1
 #define Operand_Mem   2
+#define Operand_Signed 4 /* .insn only */
 
     /* Relocation type for operand */
     enum bfd_reloc_code_real reloc[MAX_OPERANDS];
@@ -310,6 +311,9 @@ struct _i386_insn
     /* .insn allows for reserved opcode spaces.  */
     unsigned char insn_opcode_space;
 
+    /* .insn also allows (requires) specifying immediate size.  */
+    unsigned char imm_bits[MAX_OPERANDS];
+
     /* Register is in low 3 bits of opcode.  */
     bool short_form;
 
@@ -5938,6 +5942,10 @@ swap_2_operands (unsigned int xchg1, uns
   i.reloc[xchg2] = i.reloc[xchg1];
   i.reloc[xchg1] = temp_reloc;
 
+  temp_flags = i.imm_bits[xchg2];
+  i.imm_bits[xchg2] = i.imm_bits[xchg1];
+  i.imm_bits[xchg1] = temp_flags;
+
   if (i.mask.reg)
     {
       if (i.mask.operand == xchg1)
@@ -10203,7 +10211,8 @@ output_imm (fragS *insn_start_frag, offs
 
 	      if (i.types[n].bitfield.imm32s
 		  && (i.suffix == QWORD_MNEM_SUFFIX
-		      || (!i.suffix && i.tm.opcode_modifier.no_lsuf)))
+		      || (!i.suffix && i.tm.opcode_modifier.no_lsuf)
+		      || dot_insn ()))
 		sign = 1;
 	      else
 		sign = 0;
@@ -11231,6 +11240,57 @@ s_insn (int dummy ATTRIBUTE_UNUSED)
       if (i.disp_operands && !optimize_disp (&i.tm))
 	goto done;
 
+      /* Establish size for immediate operands.  */
+      for (j = 0; j < i.imm_operands; ++j)
+	{
+	  expressionS *expP = i.op[j].imms;
+
+	  gas_assert (operand_type_check (i.types[j], imm));
+	  operand_type_set (&i.types[j], 0);
+
+	  if (i.imm_bits[j] > 32)
+	    i.types[j].bitfield.imm64 = 1;
+	  else if (i.imm_bits[j] > 16)
+	    {
+	      if (flag_code == CODE_64BIT && (i.flags[j] & Operand_Signed))
+		i.types[j].bitfield.imm32s = 1;
+	      else
+		i.types[j].bitfield.imm32 = 1;
+	    }
+	  else if (i.imm_bits[j] > 8)
+	    i.types[j].bitfield.imm16 = 1;
+	  else if (i.imm_bits[j] > 0)
+	    {
+	      if (i.flags[j] & Operand_Signed)
+		i.types[j].bitfield.imm8s = 1;
+	      else
+		i.types[j].bitfield.imm8 = 1;
+	    }
+	  else if (expP->X_op == O_constant)
+	    {
+	      i.types[j] = smallest_imm_type (expP->X_add_number);
+	      i.types[j].bitfield.imm1 = 0;
+	      /* Oddly enough imm_size() checks imm64 first, so the bit needs
+		 zapping since smallest_imm_type() sets it unconditionally.  */
+	      if (flag_code != CODE_64BIT)
+		{
+		  i.types[j].bitfield.imm64 = 0;
+		  i.types[j].bitfield.imm32s = 0;
+		  i.types[j].bitfield.imm32 = 1;
+		}
+	      else if (i.types[j].bitfield.imm32 || i.types[j].bitfield.imm32s)
+		i.types[j].bitfield.imm64 = 0;
+	    }
+	  else
+	    /* Non-constant expressions are sized heuristically.  */
+	    switch (flag_code)
+	      {
+	      case CODE_64BIT: i.types[j].bitfield.imm32s = 1; break;
+	      case CODE_32BIT: i.types[j].bitfield.imm32 = 1; break;
+	      case CODE_16BIT: i.types[j].bitfield.imm16 = 1; break;
+	      }
+	}
+
       for (j = 0; j < i.operands; ++j)
 	i.tm.operand_types[j] = i.types[j];
 
@@ -11411,10 +11471,11 @@ check_VecOperations (char *op_string)
 	  else if (dot_insn () && *op_string == ':')
 	    {
 	    dot_insn_modifier:
-	      if (op_string[1] == 'd')
+	      switch (op_string[1])
 		{
 		  unsigned long n;
 
+		case 'd':
 		  if (i.memshift < 32)
 		    goto duplicated_vec_op;
 
@@ -11424,6 +11485,27 @@ check_VecOperations (char *op_string)
 		      ++i.memshift;
 		  if (i.memshift < 32 && n == 1)
 		    op_string = end_op;
+		  break;
+
+		case 's': case 'u':
+		  /* This isn't really a "vector" operation, but a sign/size
+		     specifier for immediate operands of .insn.  Note that AT&T
+		     syntax handles the same in i386_immediate().  */
+		  if (!intel_syntax)
+		    break;
+
+		  if (i.imm_bits[this_operand])
+		    goto duplicated_vec_op;
+
+		  n = strtoul (op_string + 2, &end_op, 0);
+		  if (n && n <= (flag_code == CODE_64BIT ? 64 : 32))
+		    {
+		      i.imm_bits[this_operand] = n;
+		      if (op_string[1] == 's')
+			i.flags[this_operand] |= Operand_Signed;
+		      op_string = end_op;
+		    }
+		  break;
 		}
 	    }
 	  /* Check masking operation.  */
@@ -11562,6 +11644,22 @@ i386_immediate (char *imm_start)
 
   exp_seg = expression (exp);
 
+  /* For .insn immediates there may be a size specifier.  */
+  if (dot_insn () && *input_line_pointer == '{' && input_line_pointer[1] == ':'
+      && (input_line_pointer[2] == 's' || input_line_pointer[2] == 'u'))
+    {
+      char *e;
+      unsigned long n = strtoul (input_line_pointer + 3, &e, 0);
+
+      if (*e == '}' && n && n <= (flag_code == CODE_64BIT ? 64 : 32))
+	{
+	  i.imm_bits[this_operand] = n;
+	  if (input_line_pointer[2] == 's')
+	    i.flags[this_operand] |= Operand_Signed;
+	  input_line_pointer = e + 1;
+	}
+    }
+
   SKIP_WHITESPACE ();
   if (*input_line_pointer)
     as_bad (_("junk `%s' after expression"), input_line_pointer);
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -965,7 +965,8 @@ i386_intel_operand (char *operand_string
       i386_operand_type temp;
 
       /* Register operand.  */
-      if (intel_state.base || intel_state.index || intel_state.seg)
+      if (intel_state.base || intel_state.index || intel_state.seg
+          || i.imm_bits[this_operand])
 	{
 	  as_bad (_("invalid operand"));
 	  return 0;
@@ -998,6 +999,12 @@ i386_intel_operand (char *operand_string
 	   || intel_state.is_mem)
     {
       /* Memory operand.  */
+      if (i.imm_bits[this_operand])
+	{
+	  as_bad (_("invalid operand"));
+	  return 0;
+	}
+
       if (i.mem_operands)
 	{
 	  /* Handle
--- a/gas/testsuite/gas/i386/insn-32.d
+++ b/gas/testsuite/gas/i386/insn-32.d
@@ -10,6 +10,7 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	f3 90[ 	]+pause
 [ 	]*[a-f0-9]+:	f3 90[ 	]+pause
 [ 	]*[a-f0-9]+:	d9 ee[ 	]+fldz
+[ 	]*[a-f0-9]+:	d9 ee[ 	]+fldz
 [ 	]*[a-f0-9]+:	f3 0f 01 e8[ 	]+setssbsy
 [ 	]*[a-f0-9]+:	8b c1[ 	]+mov    %ecx,%eax
 [ 	]*[a-f0-9]+:	66 8b c8[ 	]+mov    %ax,%cx
@@ -17,7 +18,10 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	8b 0c 05 44 44 00 00[ 	]+mov    0x4444\(,%eax,1\),%ecx
 [ 	]*[a-f0-9]+:	66 0f b6 cc[ 	]+movzbw %ah,%cx
 [ 	]*[a-f0-9]+:	0f b7 c8[ 	]+movzwl %ax,%ecx
+[ 	]*[a-f0-9]+:	64 f0 80 30 01[ 	]+lock xorb \$(0x)?1,%fs:\(%eax\)
 [ 	]*[a-f0-9]+:	0f ca[ 	]+bswap  %edx
+[ 	]*[a-f0-9]+:	c7 f8 02 00 00 00[ 	]+xbegin [0-9a-f]+ <insn\+.*>
+[ 	]*[a-f0-9]+:	e2 f8[ 	]+loop   [0-9a-f]+ <insn\+.*>
 [ 	]*[a-f0-9]+:	c5 fc 77[ 	]+vzeroall
 [ 	]*[a-f0-9]+:	c4 e1 7c 77[ 	]+vzeroall
 [ 	]*[a-f0-9]+:	c5 f1 58 d0[ 	]+vaddpd %xmm0,%xmm1,%xmm2
@@ -27,6 +31,9 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	c4 e3 69 68 19 00[ 	]+vfmaddps %xmm0,\(%ecx\),%xmm2,%xmm3
 [ 	]*[a-f0-9]+:	c4 e3 e9 68 19 00[ 	]+vfmaddps \(%ecx\),%xmm0,%xmm2,%xmm3
 [ 	]*[a-f0-9]+:	c4 e3 e9 68 18 10[ 	]+vfmaddps \(%eax\),%xmm1,%xmm2,%xmm3
+[ 	]*[a-f0-9]+:	c4 e3 69 48 19 00[ 	]+vpermil2ps \$(0x)?0,%xmm0,\(%ecx\),%xmm2,%xmm3
+[ 	]*[a-f0-9]+:	c4 e3 e9 48 19 02[ 	]+vpermil2ps \$(0x)?2,\(%ecx\),%xmm0,%xmm2,%xmm3
+[ 	]*[a-f0-9]+:	c4 e3 e9 48 18 13[ 	]+vpermil2ps \$(0x)?3,\(%eax\),%xmm1,%xmm2,%xmm3
 [ 	]*[a-f0-9]+:	c5 f8 92 c8[ 	]+kmovw  %eax,%k1
 [ 	]*[a-f0-9]+:	c5 f8 93 c1[ 	]+kmovw  %k1,%eax
 [ 	]*[a-f0-9]+:	62 f1 74 18 58 d0[ 	]+vaddps \{rn-sae\},%zmm0,%zmm1,%zmm2
@@ -41,4 +48,8 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	62 f5 fd 58 5a 40 01[ 	]+vcvtpd2ph (0x)?8\(%eax\)\{1to8\},%xmm0
 [ 	]*[a-f0-9]+:	62 f5 7c 48 5a 40 01[ 	]+vcvtph2pd 0x10\(%eax\),%zmm0
 [ 	]*[a-f0-9]+:	62 f5 7c 58 5a 40 01[ 	]+vcvtph2pd (0x)?2\(%eax\)\{1to8\},%zmm0
+[ 	]*[a-f0-9]+:	62 f3 7d 28 66 40 01 ff[ 	]+vfpclasspsy \$0xff,0x20\(%eax\),%k0
+[ 	]*[a-f0-9]+:	62 f3 7d 28 66 40 01 ff[ 	]+vfpclasspsy \$0xff,0x20\(%eax\),%k0
+[ 	]*[a-f0-9]+:	62 f3 7d 38 66 40 01 ff[ 	]+vfpclassps \$0xff,(0x)?4\(%eax\)\{1to8\},%k0
+[ 	]*[a-f0-9]+:	62 f3 7d 38 66 40 01 ff[ 	]+vfpclassps \$0xff,(0x)?4\(%eax\)\{1to8\},%k0
 #pass
--- a/gas/testsuite/gas/i386/insn-32.s
+++ b/gas/testsuite/gas/i386/insn-32.s
@@ -9,6 +9,7 @@ insn:
 
 	# fldz
 	.insn 0xd9ee
+	.insn 0xd9, $0xee
 
 	# setssbsy
 	.insn 0xf30f01e8
@@ -23,9 +24,20 @@ insn:
 	.insn 0x0fb6, %ah, %cx
 	.insn 0x0fb7, %eax, %ecx
 
+	# xorb
+	.insn lock 0x80/6, $1, %fs:(%eax)
+
 	# bswap
 	.insn 0x0fc8+r, %edx
 
+1:
+	# xbegin 3f
+	.insn 0xc7f8, $3f-2f{:s32}
+2:
+	# loop 1b
+	.insn 0xe2, $1b-3f{:s8}
+3:
+
 	# vzeroall
 	.insn VEX.256.0F.WIG 0x77
 	.insn {vex3} VEX.L1 0x0f77
@@ -43,6 +55,11 @@ insn:
 	.insn VEX.66.0F3A.W1 0x68, %xmm0, (%ecx), %xmm2, %xmm3
 	.insn VEX.66.0F3A.W1 0x68, (%eax), %xmm1, %xmm2, %xmm3
 
+	# vpermil2ps
+	.insn VEX.66.0F3A.W0 0x48, $0, %xmm0, (%ecx), %xmm2, %xmm3
+	.insn VEX.66.0F3A.W1 0x48, $2, %xmm0, (%ecx), %xmm2, %xmm3
+	.insn VEX.66.0F3A.W1 0x48, $3, (%eax), %xmm1, %xmm2, %xmm3
+
 	# kmovw
 	.insn VEX.L0.0F.W0 0x92, %eax, %k1
 	.insn VEX.L0.0F.W0 0x93, %k1, %eax
@@ -68,3 +85,10 @@ insn:
 	# vcvtph2pd
 	.insn EVEX.M5.W0 0x5a, 16(%eax){:d16}, %zmm0
 	.insn EVEX.M5.W0 0x5a, 2(%eax){1to8:d2}, %zmm0
+
+	.intel_syntax noprefix
+	# vfpclassps
+	.insn EVEX.256.66.0f3a.W0 0x66, k0, [eax+32], 0xff
+	.insn EVEX.66.0f3a.W0 0x66, k0, ymmword ptr [eax+32], 0xff
+	.insn EVEX.256.66.0f3a.W0 0x66, k0, [eax+4]{1to8}, 0xff
+	.insn EVEX.66.0f3a.W0 0x66, k0, dword ptr [eax+4]{1to8}, 0xff
--- a/gas/testsuite/gas/i386/insn-64.d
+++ b/gas/testsuite/gas/i386/insn-64.d
@@ -1,4 +1,4 @@
-#objdump: -dw
+#objdump: -dwr
 #name: .insn (64-bit code)
 
 .*: +file format .*
@@ -18,8 +18,14 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	66 0f be cc[ 	]+movsbw %ah,%cx
 [ 	]*[a-f0-9]+:	0f bf c8[ 	]+movswl %ax,%ecx
 [ 	]*[a-f0-9]+:	48 63 c8[ 	]+movslq %eax,%rcx
+[ 	]*[a-f0-9]+:	f0 80 35 00 00 00 00 01[ 	]+lock xorb \$(0x)?1,(0x)?0\(%rip\) *# .*: R_X86_64_PC32	lock-(0x)?5
 [ 	]*[a-f0-9]+:	48 0f ca[ 	]+bswap  %rdx
 [ 	]*[a-f0-9]+:	41 0f c8[ 	]+bswap  %r8d
+[ 	]*[a-f0-9]+:	c7 f8 02 00 00 00[ 	]+xbegin [0-9a-f]+ <insn\+.*>
+[ 	]*[a-f0-9]+:	e2 f8[ 	]+loop   [0-9a-f]+ <insn\+.*>
+[ 	]*[a-f0-9]+:	05 00 00 00 00[ 	]+add    \$(0x)?0,%eax	.*: R_X86_64_32	var
+[ 	]*[a-f0-9]+:	48 05 00 00 00 00[ 	]+add    \$(0x)?0,%rax	.*: R_X86_64_32S	var
+[ 	]*[a-f0-9]+:	81 3d 00 00 00 00 13 12 23 21[ 	]+cmpl   \$0x21231213,(0x)?0\(%rip\) *# .*: R_X86_64_PC32	var-(0x)?8
 [ 	]*[a-f0-9]+:	c5 fc 77[ 	]+vzeroall
 [ 	]*[a-f0-9]+:	c4 e1 7c 77[ 	]+vzeroall
 [ 	]*[a-f0-9]+:	c4 c1 71 58 d0[ 	]+vaddpd %xmm8,%xmm1,%xmm2
@@ -29,6 +35,9 @@ Disassembly of section .text:
 [ 	]*[a-f0-9]+:	c4 e3 69 68 19 80[ 	]+vfmaddps %xmm8,\(%rcx\),%xmm2,%xmm3
 [ 	]*[a-f0-9]+:	67 c4 e3 e9 68 19 00[ 	]+vfmaddps \(%ecx\),%xmm0,%xmm2,%xmm3
 [ 	]*[a-f0-9]+:	c4 c3 e9 68 18 10[ 	]+vfmaddps \(%r8\),%xmm1,%xmm2,%xmm3
+[ 	]*[a-f0-9]+:	c4 e3 69 48 19 80[ 	]+vpermil2ps \$(0x)0,%xmm8,\(%rcx\),%xmm2,%xmm3
+[ 	]*[a-f0-9]+:	67 c4 e3 e9 48 19 02[ 	]+vpermil2ps \$(0x)2,\(%ecx\),%xmm0,%xmm2,%xmm3
+[ 	]*[a-f0-9]+:	c4 c3 e9 48 18 13[ 	]+vpermil2ps \$(0x)3,\(%r8\),%xmm1,%xmm2,%xmm3
 [ 	]*[a-f0-9]+:	c4 c1 78 92 c8[ 	]+kmovw  %r8d,%k1
 [ 	]*[a-f0-9]+:	c5 78 93 c1[ 	]+kmovw  %k1,%r8d
 [ 	]*[a-f0-9]+:	62 b1 74 38 58 d0[ 	]+vaddps \{rd-sae\},%zmm16,%zmm1,%zmm2
--- a/gas/testsuite/gas/i386/insn-64.s
+++ b/gas/testsuite/gas/i386/insn-64.s
@@ -24,10 +24,30 @@ insn:
 	.insn 0x0fbf, %eax, %ecx
 	.insn 0x63, %rax, %rcx
 
+	# xorb
+	.insn lock 0x80/6, $1, lock(%rip)
+
 	# bswap
 	.insn 0x0fc8+r, %rdx
 	.insn 0x0fc8+r, %r8d
 
+1:
+	# xbegin 3f
+	.insn 0xc7f8, $3f-2f{:s32}
+2:
+	# loop 1b
+	.insn 0xe2, $1b-3f{:s8}
+3:
+
+	# add $var, %eax
+	.insn 0x05, $var{:u32}
+
+	# add $var, %rax
+	.insn rex.w 0x05, $var{:s32}
+
+	# cmpl (32-bit immediate split into two 16-bit halves)
+	.insn 0x81/7, $0x1213, $0x2123, var(%rip)
+
 	# vzeroall
 	.insn VEX.256.0F.WIG 0x77
 	.insn {vex3} VEX.L1 0x0f77
@@ -45,6 +65,11 @@ insn:
 	.insn VEX.66.0F3A.W1 0x68, %xmm0, (%ecx), %xmm2, %xmm3
 	.insn VEX.66.0F3A.W1 0x68, (%r8), %xmm1, %xmm2, %xmm3
 
+	# vpermil2ps
+	.insn VEX.66.0F3A.W0 0x48, $0, %xmm8, (%rcx), %xmm2, %xmm3
+	.insn VEX.66.0F3A.W1 0x48, $2, %xmm0, (%ecx), %xmm2, %xmm3
+	.insn VEX.66.0F3A.W1 0x48, $3, (%r8), %xmm1, %xmm2, %xmm3
+
 	# kmovw
 	.insn VEX.L0.0F.W0 0x92, %r8d, %k1
 	.insn VEX.L0.0F.W0 0x93, %k1, %r8d
