public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] x86: handle immediate operands for .insn
@ 2023-03-31  6:23 Jan Beulich
  0 siblings, 0 replies; only message in thread
From: Jan Beulich @ 2023-03-31  6:23 UTC (permalink / raw)
  To: bfd-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c032bc4fe7b1bfc29d82e84d39d32557b77aea19

commit c032bc4fe7b1bfc29d82e84d39d32557b77aea19
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Mar 31 08:22:28 2023 +0200

    x86: handle immediate operands for .insn
    
    Since we have no insn suffix and it's also not realistic to infer
    immediate size from the size of other (typically register) operands
    (like optimize_imm() does), and since we also don't have a template
    telling us permitted size(s), a new syntax construct is introduced to
    allow size (and signedness) specification. In the absence of such, the
    size is inferred from significant bits (which obviously may yield
    inconsistent results at least for effectively negative values, depending
    on whether BFD64 is enabled), and only if supplied expressions can be
    evaluated at parsing time. Being explicit is generally recommended to
    users.
    
    Size specification is permitted at bit granularity, but of course the
    eventually emitted immediate values will be padded up to 8-, 16-, 32-,
    or 64-bit fields.

Diff:
---
 gas/config/tc-i386-intel.c       |   9 +++-
 gas/config/tc-i386.c             | 102 ++++++++++++++++++++++++++++++++++++++-
 gas/testsuite/gas/i386/insn-32.d |  13 +++++
 gas/testsuite/gas/i386/insn-32.s |  24 +++++++++
 gas/testsuite/gas/i386/insn-64.d |  13 ++++-
 gas/testsuite/gas/i386/insn-64.s |  25 ++++++++++
 6 files changed, 182 insertions(+), 4 deletions(-)

diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c
index 98262bd3248..5a2bf6d865c 100644
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -965,7 +965,8 @@ i386_intel_operand (char *operand_string, int got_a_float)
       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, int got_a_float)
 	   || intel_state.is_mem)
     {
       /* Memory operand.  */
+      if (i.imm_bits[this_operand])
+	{
+	  as_bad (_("invalid operand"));
+	  return 0;
+	}
+
       if (i.mem_operands)
 	{
 	  /* Handle
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c8e68d5bc5d..ea2ed0d818e 100644
--- 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;
 
@@ -5923,6 +5927,10 @@ swap_2_operands (unsigned int xchg1, unsigned int xchg2)
   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)
@@ -10188,7 +10196,8 @@ output_imm (fragS *insn_start_frag, offsetT insn_start_off)
 
 	      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;
@@ -11216,6 +11225,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];
 
@@ -11396,10 +11456,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;
 
@@ -11409,6 +11470,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.  */
@@ -11547,6 +11629,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);
diff --git a/gas/testsuite/gas/i386/insn-32.d b/gas/testsuite/gas/i386/insn-32.d
index d898a71e437..c2d8202bd2e 100644
--- a/gas/testsuite/gas/i386/insn-32.d
+++ b/gas/testsuite/gas/i386/insn-32.d
@@ -1,5 +1,7 @@
+#as: --divide
 #objdump: -dw
 #name: .insn (32-bit code)
+#xfail: *-*-darwin*
 
 .*: +file format .*
 
@@ -10,6 +12,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 +20,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 +33,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 +50,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
diff --git a/gas/testsuite/gas/i386/insn-32.s b/gas/testsuite/gas/i386/insn-32.s
index d54ad3bb3c8..20bae326959 100644
--- 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
diff --git a/gas/testsuite/gas/i386/insn-64.d b/gas/testsuite/gas/i386/insn-64.d
index 0f1ec882a51..0c1f0c53770 100644
--- a/gas/testsuite/gas/i386/insn-64.d
+++ b/gas/testsuite/gas/i386/insn-64.d
@@ -1,5 +1,7 @@
-#objdump: -dw
+#as: --divide
+#objdump: -dwr
 #name: .insn (64-bit code)
+#xfail: *-*-darwin*
 
 .*: +file format .*
 
@@ -18,8 +20,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|ff) ){4}01[ 	]+lock xorb \$(0x)?1,[-x01]+\(%rip\) *# .*: (R_X86_64_PC32	lock-(0x)?5|IMAGE_REL_AMD64_REL32	lock)
 [ 	]*[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|IMAGE_REL_AMD64_ADDR32)	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|fc) ((00|ff) ){3}13 12 23 21[ 	]+cmpl   \$0x21231213,[-x04]+\(%rip\) *# .*: (R_X86_64_PC32	var-(0x)?8|IMAGE_REL_AMD64_REL32	var)
 [ 	]*[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 +37,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
diff --git a/gas/testsuite/gas/i386/insn-64.s b/gas/testsuite/gas/i386/insn-64.s
index 9dfdd3a622b..3152ec94f17 100644
--- 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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-03-31  6:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-31  6:23 [binutils-gdb] x86: handle immediate operands for .insn Jan Beulich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).