public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/3] x86: assorted opcode processing adjustments
@ 2023-02-03  7:30 Jan Beulich
  2023-02-03  7:32 ` [PATCH 1/3] x86: improve special casing of certain insns Jan Beulich
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jan Beulich @ 2023-02-03  7:30 UTC (permalink / raw)
  To: Binutils; +Cc: H.J. Lu

The first change follows what was already done for Intel syntax code.
The second is finally doing what I was meaning to do for quite some
time, noticing the inefficiencies once again while preparing patch 1.
The third change is perhaps just a first step towards re-arranging
how we represent template attributes; see there for possible further
steps.

1: improve special casing of certain insns
2: simplify a few expressions
3: move (and rename) opcodespace attribute

Jan

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] x86: improve special casing of certain insns
  2023-02-03  7:30 [PATCH 0/3] x86: assorted opcode processing adjustments Jan Beulich
@ 2023-02-03  7:32 ` Jan Beulich
  2023-02-03  7:32 ` [PATCH 2/3] x86: simplify a few expressions Jan Beulich
  2023-02-03  7:33 ` [PATCH 3/3] x86: move (and rename) opcodespace attribute Jan Beulich
  2 siblings, 0 replies; 4+ messages in thread
From: Jan Beulich @ 2023-02-03  7:32 UTC (permalink / raw)
  To: Binutils; +Cc: H.J. Lu

Now that we have identifiers for the mnemonic strings we can avoid
opcode based comparisons, for (in many cases) being more expensive and
(in a few cases) being a little fragile and not self-documenting.

Note that the MOV optimization can be engaged by the earlier LEA one,
and hence LEA also needs checking for there.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -3487,8 +3487,7 @@ want_disp32 (const insn_template *t)
 {
   return flag_code != CODE_64BIT
 	 || i.prefix[ADDR_PREFIX]
-	 || (t->base_opcode == 0x8d
-	     && t->opcode_modifier.opcodespace == SPACE_BASE
+	 || (t->mnem_off == MN_lea
 	     && (!i.types[1].bitfield.qword
 		|| t->opcode_modifier.size == SIZE32));
 }
@@ -4096,8 +4095,7 @@ optimize_encoding (void)
 {
   unsigned int j;
 
-  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
-      && i.tm.base_opcode == 0x8d)
+  if (i.tm.mnem_off == MN_lea)
     {
       /* Optimize: -O:
 	   lea symbol, %rN    -> mov $symbol, %rN
@@ -4245,15 +4243,12 @@ optimize_encoding (void)
     }
 
   if (optimize_for_space
-      && i.tm.opcode_modifier.opcodespace == SPACE_BASE
+      && i.tm.mnem_off == MN_test
       && i.reg_operands == 1
       && i.imm_operands == 1
       && !i.types[1].bitfield.byte
       && i.op[0].imms->X_op == O_constant
-      && fits_in_imm7 (i.op[0].imms->X_add_number)
-      && (i.tm.base_opcode == 0xa8
-	  || (i.tm.base_opcode == 0xf6
-	      && i.tm.extension_opcode == 0x0)))
+      && fits_in_imm7 (i.op[0].imms->X_add_number))
     {
       /* Optimize: -Os:
 	   test $imm7, %r64/%r32/%r16  -> test $imm7, %r8
@@ -4286,12 +4281,11 @@ optimize_encoding (void)
 		     && i.tm.extension_opcode == None
 		     && fits_in_unsigned_long (i.op[0].imms->X_add_number))
 		    || (fits_in_imm31 (i.op[0].imms->X_add_number)
-			&& ((i.tm.base_opcode == 0x24
-			     || i.tm.base_opcode == 0xa8)
+			&& (i.tm.base_opcode == 0x24
 			    || (i.tm.base_opcode == 0x80
 				&& i.tm.extension_opcode == 0x4)
-			    || ((i.tm.base_opcode == 0xf6
-				 || (i.tm.base_opcode | 1) == 0xc7)
+			    || i.tm.mnem_off == MN_test
+			    || ((i.tm.base_opcode | 1) == 0xc7
 				&& i.tm.extension_opcode == 0x0)))
 		    || (fits_in_imm7 (i.op[0].imms->X_add_number)
 			&& i.tm.base_opcode == 0x83
@@ -4299,11 +4293,9 @@ optimize_encoding (void)
 	       || (i.types[0].bitfield.qword
 		   && ((i.reg_operands == 2
 			&& i.op[0].regs == i.op[1].regs
-			&& (i.tm.base_opcode == 0x30
-			    || i.tm.base_opcode == 0x28))
-		       || (i.reg_operands == 1
-			   && i.operands == 1
-			   && i.tm.base_opcode == 0x30)))))
+			&& (i.tm.mnem_off == MN_xor
+			    || i.tm.mnem_off == MN_sub))
+		       || i.tm.mnem_off == MN_clr))))
     {
       /* Optimize: -O:
 	   andq $imm31, %r64   -> andl $imm31, %r32
@@ -4328,7 +4320,7 @@ optimize_encoding (void)
 	}
       i.types[1].bitfield.dword = 1;
       i.types[1].bitfield.qword = 0;
-      if (i.tm.base_opcode == 0xb8 || (i.tm.base_opcode | 1) == 0xc7)
+      if (i.tm.mnem_off == MN_mov || i.tm.mnem_off == MN_lea)
 	{
 	  /* Handle
 	       movq $imm31, %r64   -> movl $imm31, %r32
@@ -4351,11 +4343,9 @@ optimize_encoding (void)
     }
   else if (optimize > 1
 	   && !optimize_for_space
-	   && i.tm.opcode_modifier.opcodespace == SPACE_BASE
 	   && i.reg_operands == 2
 	   && i.op[0].regs == i.op[1].regs
-	   && ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8
-	       || (i.tm.base_opcode & ~(Opcode_D | 1)) == 0x20)
+	   && (i.tm.mnem_off == MN_and || i.tm.mnem_off == MN_or)
 	   && (flag_code != CODE_64BIT || !i.types[0].bitfield.dword))
     {
       /* Optimize: -O2:
@@ -4580,12 +4570,7 @@ load_insn_p (void)
 
   if (any_vex_p)
     {
-      /* vldmxcsr.  */
-      if (i.tm.base_opcode == 0xae
-	  && i.tm.opcode_modifier.vex
-	  && i.tm.opcode_modifier.opcodespace == SPACE_0F
-	  && i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE
-	  && i.tm.extension_opcode == 2)
+      if (i.tm.mnem_off == MN_vldmxcsr)
 	return 1;
     }
   else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
@@ -4699,9 +4684,7 @@ load_insn_p (void)
 	  || (base_opcode | 2) == 0x87))
     return 1;
 
-  /* xadd.  */
-  if (i.tm.opcode_modifier.opcodespace == SPACE_0F
-      && base_opcode == 0xc1)
+  if (i.tm.mnem_off == MN_xadd)
     return 1;
 
   /* Check for load instruction.  */
@@ -5361,12 +5344,8 @@ md_assemble (char *line)
       i.rex &= REX_OPCODE;
     }
 
-  /* Handle conversion of 'int $3' --> special int3 insn.  XOP or FMA4
-     instructions may define INT_OPCODE as well, so avoid this corner
-     case for those instructions that use MODRM.  */
-  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
-      && i.tm.base_opcode == INT_OPCODE
-      && !i.tm.opcode_modifier.modrm
+  /* Handle conversion of 'int $3' --> special int3 insn.  */
+  if (i.tm.mnem_off == MN_int
       && i.op[0].imms->X_add_number == 3)
     {
       i.tm.base_opcode = INT3_OPCODE;
@@ -5476,10 +5455,7 @@ static INLINE bool q_suffix_allowed(cons
 	 || (t->opcode_modifier.opcodespace == SPACE_BASE
 	     && t->base_opcode == 0xdf
 	     && (t->extension_opcode & 1)) /* fild / fistp / fisttp */
-	 || (t->opcode_modifier.opcodespace == SPACE_0F
-	     && t->base_opcode == 0xc7
-	     && t->opcode_modifier.opcodeprefix == PREFIX_NONE
-	     && t->extension_opcode == 1) /* cmpxchg8b */;
+	 || t->mnem_off == MN_cmpxchg8b;
 }
 
 static const char *
@@ -7201,7 +7177,7 @@ check_string (void)
 static int
 process_suffix (void)
 {
-  bool is_crc32 = false, is_movx = false;
+  bool is_movx = false;
 
   /* If matched instruction specifies an explicit instruction mnemonic
      suffix, use it.  */
@@ -7224,11 +7200,6 @@ process_suffix (void)
 		    && i.tm.base_opcode == 0x63
 		    && i.tm.cpu_flags.bitfield.cpu64);
 
-      /* CRC32 */
-      is_crc32 = (i.tm.base_opcode == 0xf0
-		  && i.tm.opcode_modifier.opcodespace == SPACE_0F38
-		  && i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2);
-
       /* movsx/movzx want only their source operand considered here, for the
 	 ambiguity checking below.  The suffix will be replaced afterwards
 	 to represent the destination (register).  */
@@ -7236,7 +7207,7 @@ process_suffix (void)
 	--i.operands;
 
       /* crc32 needs REX.W set regardless of suffix / source operand size.  */
-      if (is_crc32 && i.tm.operand_types[1].bitfield.qword)
+      if (i.tm.mnem_off == MN_crc32 && i.tm.operand_types[1].bitfield.qword)
         i.rex |= REX_W;
 
       /* If there's no instruction mnemonic suffix we try to invent one
@@ -7247,7 +7218,7 @@ process_suffix (void)
 	     Destination register type is more significant than source
 	     register type.  crc32 in SSE4.2 prefers source register
 	     type. */
-	  unsigned int op = is_crc32 ? 1 : i.operands;
+	  unsigned int op = i.tm.mnem_off == MN_crc32 ? 1 : i.operands;
 
 	  while (op--)
 	    if (i.tm.operand_types[op].bitfield.instance == InstanceNone
@@ -7571,8 +7542,7 @@ process_suffix (void)
 		      /* InOutPortReg */
 		      || i.tm.operand_types[0].bitfield.instance == RegD
 		      || i.tm.operand_types[1].bitfield.instance == RegD
-		      /* CRC32 */
-		      || is_crc32))))
+		      || i.tm.mnem_off == MN_crc32))))
 	i.tm.base_opcode |= 1;
       break;
     }
@@ -7691,10 +7661,7 @@ check_byte_reg (void)
 	continue;
 
       /* crc32 only wants its source operand checked here.  */
-      if (i.tm.base_opcode == 0xf0
-	  && i.tm.opcode_modifier.opcodespace == SPACE_0F38
-	  && i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2
-	  && op != 0)
+      if (i.tm.mnem_off == MN_crc32 && op != 0)
 	continue;
 
       /* Any other register is bad.  */
@@ -8160,9 +8127,7 @@ process_operands (void)
     }
 
   if ((i.seg[0] || i.prefix[SEG_PREFIX])
-      && i.tm.base_opcode == 0x8d /* lea */
-      && i.tm.opcode_modifier.opcodespace == SPACE_BASE
-      && !is_any_vex_encoding(&i.tm))
+      && i.tm.mnem_off == MN_lea)
     {
       if (!quiet_warnings)
 	as_warn (_("segment override on `%s' is ineffectual"), insn_name (&i.tm));
@@ -9089,7 +9054,7 @@ output_jump (void)
       break;
 
     case 2:
-      if (i.tm.base_opcode == 0xc7f8)
+      if (i.tm.mnem_off == MN_xbegin)
 	fixP->fx_signed = 1;
       break;
 
@@ -9601,10 +9566,8 @@ output_insn (void)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87;
 
       if ((i.xstate & xstate_mmx)
-	  || (i.tm.opcode_modifier.opcodespace == SPACE_0F
-	      && !is_any_vex_encoding (&i.tm)
-	      && (i.tm.base_opcode == 0x77 /* emms */
-		  || i.tm.base_opcode == 0x0e /* femms */)))
+	  || i.tm.mnem_off == MN_emms
+	  || i.tm.mnem_off == MN_femms)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MMX;
 
       if (i.index_reg)
@@ -9648,10 +9611,7 @@ output_insn (void)
       if (x86_feature_2_used
 	  || i.tm.cpu_flags.bitfield.cpucmov
 	  || i.tm.cpu_flags.bitfield.cpusyscall
-	  || (i.tm.opcode_modifier.opcodespace == SPACE_0F
-	      && i.tm.base_opcode == 0xc7
-	      && i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE
-	      && i.tm.extension_opcode == 1) /* cmpxchg8b */)
+	  || i.tm.mnem_off == MN_cmpxchg8b)
 	x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_BASELINE;
       if (i.tm.cpu_flags.bitfield.cpusse3
 	  || i.tm.cpu_flags.bitfield.cpussse3
@@ -11503,12 +11463,9 @@ i386_index_check (const char *operand_st
 	    goto bad_address;
 
 	  /* bndmk, bndldx, bndstx and mandatory non-vector SIB have special restrictions. */
-	  if ((t->opcode_modifier.opcodeprefix == PREFIX_0XF3
-	       && t->opcode_modifier.opcodespace == SPACE_0F
-	       && t->base_opcode == 0x1b)
-	      || (t->opcode_modifier.opcodeprefix == PREFIX_NONE
-		  && t->opcode_modifier.opcodespace == SPACE_0F
-		  && (t->base_opcode & ~1) == 0x1a)
+	  if (t->mnem_off == MN_bndmk
+	      || t->mnem_off == MN_bndldx
+	      || t->mnem_off == MN_bndstx
 	      || t->opcode_modifier.sib == SIBMEM)
 	    {
 	      /* They cannot use RIP-relative addressing. */
@@ -11519,9 +11476,7 @@ i386_index_check (const char *operand_st
 		}
 
 	      /* bndldx and bndstx ignore their scale factor. */
-	      if (t->opcode_modifier.opcodeprefix == PREFIX_NONE
-		  && t->opcode_modifier.opcodespace == SPACE_0F
-		  && (t->base_opcode & ~1) == 0x1a
+	      if ((t->mnem_off == MN_bndldx || t->mnem_off == MN_bndstx)
 		  && i.log2_scale_factor)
 		as_warn (_("register scaling is being ignored here"));
 	    }


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/3] x86: simplify a few expressions
  2023-02-03  7:30 [PATCH 0/3] x86: assorted opcode processing adjustments Jan Beulich
  2023-02-03  7:32 ` [PATCH 1/3] x86: improve special casing of certain insns Jan Beulich
@ 2023-02-03  7:32 ` Jan Beulich
  2023-02-03  7:33 ` [PATCH 3/3] x86: move (and rename) opcodespace attribute Jan Beulich
  2 siblings, 0 replies; 4+ messages in thread
From: Jan Beulich @ 2023-02-03  7:32 UTC (permalink / raw)
  To: Binutils; +Cc: H.J. Lu

Fold adjacent comparisons when, by ORing in a certain mask, the same
effect can be achieved by a single one. In load_insn_p() this extends
to further uses of an already available local variable.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4576,8 +4576,7 @@ load_insn_p (void)
   else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
     {
       /* test, not, neg, mul, imul, div, idiv.  */
-      if ((i.tm.base_opcode == 0xf6 || i.tm.base_opcode == 0xf7)
-	  && i.tm.extension_opcode != 1)
+      if (base_opcode == 0xf7 && i.tm.extension_opcode != 1)
 	return 1;
 
       /* inc, dec.  */
@@ -4589,13 +4588,12 @@ load_insn_p (void)
 	return 1;
 
       /* rol, ror, rcl, rcr, shl/sal, shr, sar. */
-      if ((base_opcode == 0xc1
-	   || (i.tm.base_opcode >= 0xd0 && i.tm.base_opcode <= 0xd3))
+      if ((base_opcode == 0xc1 || (base_opcode | 2) == 0xd3)
 	  && i.tm.extension_opcode != 6)
 	return 1;
 
       /* Check for x87 instructions.  */
-      if (base_opcode >= 0xd8 && base_opcode <= 0xdf)
+      if ((base_opcode | 6) == 0xdf)
 	{
 	  /* Skip fst, fstp, fstenv, fstcw.  */
 	  if (i.tm.base_opcode == 0xd9
@@ -4638,7 +4636,7 @@ load_insn_p (void)
     {
       /* bt, bts, btr, btc.  */
       if (i.tm.base_opcode == 0xba
-	  && (i.tm.extension_opcode >= 4 && i.tm.extension_opcode <= 7))
+	  && (i.tm.extension_opcode | 3) == 7)
 	return 1;
 
       /* cmpxchg8b, cmpxchg16b, xrstors, vmptrld.  */
@@ -4673,14 +4671,7 @@ load_insn_p (void)
 
   /* add, or, adc, sbb, and, sub, xor, cmp, test, xchg.  */
   if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
-      && (base_opcode == 0x1
-	  || base_opcode == 0x9
-	  || base_opcode == 0x11
-	  || base_opcode == 0x19
-	  || base_opcode == 0x21
-	  || base_opcode == 0x29
-	  || base_opcode == 0x31
-	  || base_opcode == 0x39
+      && ((base_opcode | 0x38) == 0x39
 	  || (base_opcode | 2) == 0x87))
     return 1;
 
@@ -4708,8 +4699,7 @@ insert_lfence_after (void)
 	 chosen by the adversary using an LVI method,
 	 then this data-dependent behavior may leak some aspect
 	 of the secret.  */
-      if (((i.tm.base_opcode | 0x1) == 0xa7
-	   || (i.tm.base_opcode | 0x1) == 0xaf)
+      if (((i.tm.base_opcode | 0x9) == 0xaf)
 	  && i.prefix[REP_PREFIX])
 	{
 	    as_warn (_("`%s` changes flags which would affect control flow behavior"),
@@ -4779,8 +4769,7 @@ insert_lfence_before (void)
 
   /* Output or/not/shl and lfence before near ret.  */
   if (lfence_before_ret != lfence_before_ret_none
-      && (i.tm.base_opcode == 0xc2
-	  || i.tm.base_opcode == 0xc3))
+      && (i.tm.base_opcode | 1) == 0xc3)
     {
       if (last_insn.kind != last_insn_other
 	  && last_insn.seg == now_seg)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 3/3] x86: move (and rename) opcodespace attribute
  2023-02-03  7:30 [PATCH 0/3] x86: assorted opcode processing adjustments Jan Beulich
  2023-02-03  7:32 ` [PATCH 1/3] x86: improve special casing of certain insns Jan Beulich
  2023-02-03  7:32 ` [PATCH 2/3] x86: simplify a few expressions Jan Beulich
@ 2023-02-03  7:33 ` Jan Beulich
  2 siblings, 0 replies; 4+ messages in thread
From: Jan Beulich @ 2023-02-03  7:33 UTC (permalink / raw)
  To: Binutils; +Cc: H.J. Lu

This really isn't a "modifier" and rather ought to live next to the base
opcode anyway. Use the bits we presently have available to fit in the
field, renaming it to opcode_space. As an intended side effect this
helps readability at the use sites, by shortening the references quite a
bit.

In generated code arrange for human readable output, by using the
SPACE_* constants there rather than raw numbers. This may aid debugging
down the road.
---
I'd like to do the same to opcodeprefix, but that's going to be more
intrusive, as we don't have spare bits left in a useful position
(fitting the field right after mnem_off isn't a good idea imo). Hence
I'm considering to do away with i386_opcode_modifier as a structure
altogether, which would tidy use sites quite a bit (like is the case
here). Plus it would shrink total struct size (when, at the same time,
reducing mnem_off to a 16-bit bitfield) and hence overall table size.
Thoughts anyone?

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -3203,8 +3203,8 @@ pte (insn_template *t)
   fprintf (stdout, " %d operands ", t->operands);
   if (opc_pfx[t->opcode_modifier.opcodeprefix])
     fprintf (stdout, "pfx %x ", opc_pfx[t->opcode_modifier.opcodeprefix]);
-  if (opc_spc[t->opcode_modifier.opcodespace])
-    fprintf (stdout, "space %s ", opc_spc[t->opcode_modifier.opcodespace]);
+  if (opc_spc[t->opcode_space])
+    fprintf (stdout, "space %s ", opc_spc[t->opcode_space]);
   fprintf (stdout, "opcode %x ", t->base_opcode);
   if (t->extension_opcode != None)
     fprintf (stdout, "ext %x ", t->extension_opcode);
@@ -3587,7 +3587,7 @@ build_vex_prefix (const insn_template *t
       && i.dir_encoding == dir_encoding_default
       && i.operands == i.reg_operands
       && operand_type_equal (&i.types[0], &i.types[i.operands - 1])
-      && i.tm.opcode_modifier.opcodespace == SPACE_0F
+      && i.tm.opcode_space == SPACE_0F
       && (i.tm.opcode_modifier.load || i.tm.opcode_modifier.d)
       && i.rex == REX_B)
     {
@@ -3633,7 +3633,7 @@ build_vex_prefix (const insn_template *t
       union i386_op temp_op;
       i386_operand_type temp_type;
 
-      gas_assert (i.tm.opcode_modifier.opcodespace == SPACE_0F);
+      gas_assert (i.tm.opcode_space == SPACE_0F);
       gas_assert (!i.tm.opcode_modifier.sae);
       gas_assert (operand_type_equal (&i.types[i.operands - 2],
                                       &i.types[i.operands - 3]));
@@ -3686,7 +3686,7 @@ build_vex_prefix (const insn_template *t
   /* Use 2-byte VEX prefix if possible.  */
   if (w == 0
       && i.vec_encoding != vex_encoding_vex3
-      && i.tm.opcode_modifier.opcodespace == SPACE_0F
+      && i.tm.opcode_space == SPACE_0F
       && (i.rex & (REX_W | REX_X | REX_B)) == 0)
     {
       /* 2-byte VEX prefix.  */
@@ -3707,7 +3707,7 @@ build_vex_prefix (const insn_template *t
       /* 3-byte VEX prefix.  */
       i.vex.length = 3;
 
-      switch (i.tm.opcode_modifier.opcodespace)
+      switch (i.tm.opcode_space)
 	{
 	case SPACE_0F:
 	case SPACE_0F38:
@@ -3725,7 +3725,7 @@ build_vex_prefix (const insn_template *t
 
       /* The high 3 bits of the second VEX byte are 1's compliment
 	 of RXB bits from REX.  */
-      i.vex.bytes[1] = (~i.rex & 0x7) << 5 | i.tm.opcode_modifier.opcodespace;
+      i.vex.bytes[1] = (~i.rex & 0x7) << 5 | i.tm.opcode_space;
 
       i.vex.bytes[2] = (w << 7
 			| register_specifier << 3
@@ -3860,9 +3860,9 @@ build_evex_prefix (void)
 
   /* The high 3 bits of the second EVEX byte are 1's compliment of RXB
      bits from REX.  */
-  gas_assert (i.tm.opcode_modifier.opcodespace >= SPACE_0F);
-  gas_assert (i.tm.opcode_modifier.opcodespace <= SPACE_EVEXMAP6);
-  i.vex.bytes[1] = (~i.rex & 0x7) << 5 | i.tm.opcode_modifier.opcodespace;
+  gas_assert (i.tm.opcode_space >= SPACE_0F);
+  gas_assert (i.tm.opcode_space <= SPACE_EVEXMAP6);
+  i.vex.bytes[1] = (~i.rex & 0x7) << 5 | i.tm.opcode_space;
 
   /* The fifth bit of the second EVEX byte is 1's compliment of the
      REX_R bit in VREX.  */
@@ -4072,14 +4072,14 @@ encode_with_unaligned_vector_move (void)
     case 0x28:	/* Load instructions.  */
     case 0x29:	/* Store instructions.  */
       /* movaps/movapd/vmovaps/vmovapd.  */
-      if (i.tm.opcode_modifier.opcodespace == SPACE_0F
+      if (i.tm.opcode_space == SPACE_0F
 	  && i.tm.opcode_modifier.opcodeprefix <= PREFIX_0X66)
 	i.tm.base_opcode = 0x10 | (i.tm.base_opcode & 1);
       break;
     case 0x6f:	/* Load instructions.  */
     case 0x7f:	/* Store instructions.  */
       /* movdqa/vmovdqa/vmovdqa64/vmovdqa32. */
-      if (i.tm.opcode_modifier.opcodespace == SPACE_0F
+      if (i.tm.opcode_space == SPACE_0F
 	  && i.tm.opcode_modifier.opcodeprefix == PREFIX_0X66)
 	i.tm.opcode_modifier.opcodeprefix = PREFIX_0XF3;
       break;
@@ -4221,7 +4221,7 @@ optimize_encoding (void)
 	    {
 	      if (flag_code != CODE_32BIT)
 		return;
-	      i.tm.opcode_modifier.opcodespace = SPACE_0F;
+	      i.tm.opcode_space = SPACE_0F;
 	      i.tm.base_opcode = 0xb7;
 	    }
 	  else
@@ -4272,7 +4272,7 @@ optimize_encoding (void)
 	}
     }
   else if (flag_code == CODE_64BIT
-	   && i.tm.opcode_modifier.opcodespace == SPACE_BASE
+	   && i.tm.opcode_space == SPACE_BASE
 	   && ((i.types[1].bitfield.qword
 		&& i.reg_operands == 1
 		&& i.imm_operands == 1
@@ -4374,7 +4374,7 @@ optimize_encoding (void)
 		       || i.tm.cpu_flags.bitfield.cpuavx512vl
 		       || (i.tm.operand_types[2].bitfield.zmmword
 			   && i.types[2].bitfield.ymmword))))
-	   && i.tm.opcode_modifier.opcodespace == SPACE_0F
+	   && i.tm.opcode_space == SPACE_0F
 	   && ((i.tm.base_opcode | 2) == 0x57
 	       || i.tm.base_opcode == 0xdf
 	       || i.tm.base_opcode == 0xef
@@ -4545,7 +4545,7 @@ load_insn_p (void)
 	return 1;
     }
 
-  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
+  if (i.tm.opcode_space == SPACE_BASE)
     {
       /* popf, popa.   */
       if (i.tm.base_opcode == 0x9d
@@ -4573,7 +4573,7 @@ load_insn_p (void)
       if (i.tm.mnem_off == MN_vldmxcsr)
 	return 1;
     }
-  else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
+  else if (i.tm.opcode_space == SPACE_BASE)
     {
       /* test, not, neg, mul, imul, div, idiv.  */
       if (base_opcode == 0xf7 && i.tm.extension_opcode != 1)
@@ -4632,7 +4632,7 @@ load_insn_p (void)
 	  return 1;
 	}
     }
-  else if (i.tm.opcode_modifier.opcodespace == SPACE_0F)
+  else if (i.tm.opcode_space == SPACE_0F)
     {
       /* bt, bts, btr, btc.  */
       if (i.tm.base_opcode == 0xba
@@ -4670,7 +4670,7 @@ load_insn_p (void)
     dest--;
 
   /* add, or, adc, sbb, and, sub, xor, cmp, test, xchg.  */
-  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
+  if (i.tm.opcode_space == SPACE_BASE
       && ((base_opcode | 0x38) == 0x39
 	  || (base_opcode | 2) == 0x87))
     return 1;
@@ -4719,7 +4719,7 @@ insert_lfence_before (void)
 {
   char *p;
 
-  if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
+  if (i.tm.opcode_space != SPACE_BASE)
     return;
 
   if (i.tm.base_opcode == 0xff
@@ -4841,9 +4841,9 @@ static INLINE bool may_need_pass2 (const
   return t->opcode_modifier.sse2avx
 	 /* Note that all SSE2AVX templates have at least one operand.  */
 	 ? t->operand_types[t->operands - 1].bitfield.class == RegSIMD
-	 : (t->opcode_modifier.opcodespace == SPACE_0F
+	 : (t->opcode_space == SPACE_0F
 	    && (t->base_opcode | 1) == 0xbf)
-	   || (t->opcode_modifier.opcodespace == SPACE_BASE
+	   || (t->opcode_space == SPACE_BASE
 	       && t->base_opcode == 0x63);
 }
 
@@ -5116,8 +5116,8 @@ md_assemble (char *line)
   if (sse_check != check_none
       /* The opcode space check isn't strictly needed; it's there only to
 	 bypass the logic below when easily possible.  */
-      && t->opcode_modifier.opcodespace >= SPACE_0F
-      && t->opcode_modifier.opcodespace <= SPACE_0F3A
+      && t->opcode_space >= SPACE_0F
+      && t->opcode_space <= SPACE_0F3A
       && !i.tm.cpu_flags.bitfield.cpusse4a
       && !is_any_vex_encoding (t))
     {
@@ -5240,7 +5240,7 @@ md_assemble (char *line)
      instructions (base opcodes: 0x6c, 0x6e, 0xec, 0xee).  */
   if (i.input_output_operand
       && ((i.tm.base_opcode | 0x82) != 0xee
-	  || i.tm.opcode_modifier.opcodespace != SPACE_BASE))
+	  || i.tm.opcode_space != SPACE_BASE))
     {
       as_bad (_("input/output port address isn't allowed with `%s'"),
 	      insn_name (&i.tm));
@@ -5441,7 +5441,7 @@ md_assemble (char *line)
 static INLINE bool q_suffix_allowed(const insn_template *t)
 {
   return flag_code == CODE_64BIT
-	 || (t->opcode_modifier.opcodespace == SPACE_BASE
+	 || (t->opcode_space == SPACE_BASE
 	     && t->base_opcode == 0xdf
 	     && (t->extension_opcode & 1)) /* fild / fistp / fisttp */
 	 || t->mnem_off == MN_cmpxchg8b;
@@ -5678,7 +5678,7 @@ parse_insn (const char *line, char *mnem
 		  if (current_templates != NULL
 		      /* MOVS or CMPS */
 		      && (current_templates->start->base_opcode | 2) == 0xa6
-		      && current_templates->start->opcode_modifier.opcodespace
+		      && current_templates->start->opcode_space
 			 == SPACE_BASE
 		      && mnem_p[-2] == 's')
 		    {
@@ -6853,14 +6853,14 @@ match_template (char mnem_suffix)
 	     zero-extend %eax to %rax.  */
 	  if (flag_code == CODE_64BIT
 	      && t->base_opcode == 0x90
-	      && t->opcode_modifier.opcodespace == SPACE_BASE
+	      && t->opcode_space == SPACE_BASE
 	      && i.types[0].bitfield.instance == Accum
 	      && i.types[0].bitfield.dword
 	      && i.types[1].bitfield.instance == Accum)
 	    continue;
 
 	  if (t->base_opcode == MOV_AX_DISP32
-	      && t->opcode_modifier.opcodespace == SPACE_BASE
+	      && t->opcode_space == SPACE_BASE
 	      && t->mnem_off != MN_movabs)
 	    {
 	      /* Force 0x8b encoding for "mov foo@GOT, %eax".  */
@@ -6972,8 +6972,8 @@ match_template (char mnem_suffix)
 		  found_reverse_match = Opcode_VexW;
 		  goto check_operands_345;
 		}
-	      else if (t->opcode_modifier.opcodespace != SPACE_BASE
-		       && (t->opcode_modifier.opcodespace != SPACE_0F
+	      else if (t->opcode_space != SPACE_BASE
+		       && (t->opcode_space != SPACE_0F
 			   /* MOV to/from CR/DR/TR, as an exception, follow
 			      the base opcode space encoding model.  */
 			   || (t->base_opcode | 7) != 0x27))
@@ -7183,9 +7183,9 @@ process_suffix (void)
       unsigned int numop = i.operands;
 
       /* MOVSX/MOVZX */
-      is_movx = (i.tm.opcode_modifier.opcodespace == SPACE_0F
+      is_movx = (i.tm.opcode_space == SPACE_0F
 		 && (i.tm.base_opcode | 8) == 0xbe)
-		|| (i.tm.opcode_modifier.opcodespace == SPACE_BASE
+		|| (i.tm.opcode_space == SPACE_BASE
 		    && i.tm.base_opcode == 0x63
 		    && i.tm.cpu_flags.bitfield.cpu64);
 
@@ -7289,7 +7289,7 @@ process_suffix (void)
 	   && (i.tm.opcode_modifier.jump == JUMP_ABSOLUTE
 	       || i.tm.opcode_modifier.jump == JUMP_BYTE
 	       || i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT
-	       || (i.tm.opcode_modifier.opcodespace == SPACE_0F
+	       || (i.tm.opcode_space == SPACE_0F
 		   && i.tm.base_opcode == 0x01 /* [ls][gi]dt */
 		   && i.tm.extension_opcode <= 3)))
     {
@@ -7511,7 +7511,7 @@ process_suffix (void)
 	     need rex64. */
 	  && ! (i.operands == 2
 		&& i.tm.base_opcode == 0x90
-		&& i.tm.opcode_modifier.opcodespace == SPACE_BASE
+		&& i.tm.opcode_space == SPACE_BASE
 		&& i.types[0].bitfield.instance == Accum
 		&& i.types[0].bitfield.qword
 		&& i.types[1].bitfield.instance == Accum))
@@ -8083,14 +8083,14 @@ process_operands (void)
 	  return 0;
 	}
       if (i.op[0].regs->reg_num > 3
-	  && i.tm.opcode_modifier.opcodespace == SPACE_BASE )
+	  && i.tm.opcode_space == SPACE_BASE )
 	{
 	  i.tm.base_opcode ^= (POP_SEG_SHORT ^ POP_SEG386_SHORT) & 0xff;
-	  i.tm.opcode_modifier.opcodespace = SPACE_0F;
+	  i.tm.opcode_space = SPACE_0F;
 	}
       i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
     }
-  else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
+  else if (i.tm.opcode_space == SPACE_BASE
 	   && (i.tm.base_opcode & ~3) == MOV_AX_DISP32)
     {
       default_seg = reg_ds;
@@ -9325,7 +9325,7 @@ maybe_fused_with_jcc_p (enum mf_cmp_kind
     return 0;
 
   /* No opcodes outside of base encoding space.  */
-  if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
+  if (i.tm.opcode_space != SPACE_BASE)
     return 0;
 
   /* add, sub without add/sub m, imm.  */
@@ -9449,7 +9449,7 @@ add_branch_padding_frag_p (enum align_br
   if (!align_branch_power
       || now_seg == absolute_section
       || !cpu_arch_flags.bitfield.cpui386
-      || i.tm.opcode_modifier.opcodespace != SPACE_BASE)
+      || i.tm.opcode_space != SPACE_BASE)
     return 0;
 
   add_padding = 0;
@@ -9611,7 +9611,7 @@ output_insn (void)
 	  /* LAHF-SAHF insns in 64-bit mode.  */
 	  || (flag_code == CODE_64BIT
 	      && (i.tm.base_opcode | 1) == 0x9f
-	      && i.tm.opcode_modifier.opcodespace == SPACE_BASE))
+	      && i.tm.opcode_space == SPACE_BASE))
 	x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_V2;
       if (i.tm.cpu_flags.bitfield.cpuavx
 	  || i.tm.cpu_flags.bitfield.cpuavx2
@@ -9870,7 +9870,7 @@ output_insn (void)
       /* Now the opcode; be careful about word order here!  */
       j = i.opcode_length;
       if (!i.vex.length)
-	switch (i.tm.opcode_modifier.opcodespace)
+	switch (i.tm.opcode_space)
 	  {
 	  case SPACE_BASE:
 	    break;
@@ -9895,11 +9895,11 @@ output_insn (void)
 	{
 	  p = frag_more (j);
 	  if (!i.vex.length
-	      && i.tm.opcode_modifier.opcodespace != SPACE_BASE)
+	      && i.tm.opcode_space != SPACE_BASE)
 	    {
 	      *p++ = 0x0f;
-	      if (i.tm.opcode_modifier.opcodespace != SPACE_0F)
-		*p++ = i.tm.opcode_modifier.opcodespace == SPACE_0F38
+	      if (i.tm.opcode_space != SPACE_0F)
+		*p++ = i.tm.opcode_space == SPACE_0F38
 		       ? 0x38 : 0x3a;
 	    }
 
@@ -9971,7 +9971,7 @@ output_insn (void)
 
 	      /* Count prefixes for extended opcode maps.  */
 	      if (!i.vex.length)
-		switch (i.tm.opcode_modifier.opcodespace)
+		switch (i.tm.opcode_space)
 		  {
 		  case SPACE_BASE:
 		    break;
@@ -10209,7 +10209,7 @@ output_disp (fragS *insn_start_frag, off
 			  && i.rm.regmem == 5))
 		  && (i.rm.mode == 2
 		      || (i.rm.mode == 0 && i.rm.regmem == 5))
-		  && i.tm.opcode_modifier.opcodespace == SPACE_BASE
+		  && i.tm.opcode_space == SPACE_BASE
 		  && ((i.operands == 1
 		       && i.tm.base_opcode == 0xff
 		       && (i.rm.reg == 2 || i.rm.reg == 4))
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -430,7 +430,6 @@ static bitfield opcode_modifiers[] =
   BITFIELD (Vex),
   BITFIELD (VexVVVV),
   BITFIELD (VexW),
-  BITFIELD (OpcodeSpace),
   BITFIELD (OpcodePrefix),
   BITFIELD (VexSources),
   BITFIELD (SIB),
@@ -957,10 +956,24 @@ get_element_size (char **opnd, int linen
 
 static void
 process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
-			      unsigned int prefix, char **opnd, int lineno)
+			      unsigned int prefix, const char *extension_opcode,
+			      char **opnd, int lineno)
 {
   char *str, *next, *last;
   bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
+  static const char *const spaces[] = {
+#define SPACE(n) [SPACE_##n] = #n
+    SPACE(BASE),
+    SPACE(0F),
+    SPACE(0F38),
+    SPACE(0F3A),
+    SPACE(EVEXMAP5),
+    SPACE(EVEXMAP6),
+    SPACE(XOP08),
+    SPACE(XOP09),
+    SPACE(XOP0A),
+#undef SPACE
+  };
 
   active_isstring = 0;
 
@@ -978,6 +991,34 @@ process_i386_opcode_modifier (FILE *tabl
 	  if (str)
 	    {
 	      int val = 1;
+
+	      if (strncmp(str, "OpcodeSpace", 11) == 0)
+		{
+		  char *end;
+
+		  if (str[11] != '=')
+		    fail ("%s:%d: Missing value for `OpcodeSpace'\n",
+			  filename, lineno);
+
+		  val = strtol (str + 12, &end, 0);
+		  if (*end)
+		    fail ("%s:%d: Bogus value `%s' for `OpcodeSpace'\n",
+			  filename, lineno, end);
+
+		  if (space)
+		    {
+		      if (val != space)
+			fail ("%s:%d: Conflicting opcode space specifications\n",
+			      filename, lineno);
+		      fprintf (stderr,
+			       "%s:%d: Warning: redundant opcode space specification\n",
+			       filename, lineno);
+		    }
+
+		  space = val;
+		  continue;
+		}
+
 	      if (strcasecmp(str, "Broadcast") == 0)
 		val = get_element_size (opnd, lineno) + BYTE_BROADCAST;
 	      else if (strcasecmp(str, "Disp8MemShift") == 0)
@@ -1002,19 +1043,6 @@ process_i386_opcode_modifier (FILE *tabl
 	    }
 	}
 
-      if (space)
-	{
-	  if (!modifiers[OpcodeSpace].value)
-	    modifiers[OpcodeSpace].value = space;
-	  else if (modifiers[OpcodeSpace].value != space)
-	    fail ("%s:%d: Conflicting opcode space specifications\n",
-		  filename, lineno);
-	  else
-	    fprintf (stderr,
-		     "%s:%d: Warning: redundant opcode space specification\n",
-		     filename, lineno);
-	}
-
       if (prefix)
 	{
 	  if (!modifiers[OpcodePrefix].value)
@@ -1038,6 +1066,13 @@ process_i386_opcode_modifier (FILE *tabl
 		 "%s: %d: W modifier without Word/Dword/Qword operand(s)\n",
 		 filename, lineno);
     }
+
+  if (space >= ARRAY_SIZE (spaces) || !spaces[space])
+    fail ("%s:%d: Unknown opcode space %u\n", filename, lineno, space);
+
+  fprintf (table, " SPACE_%s, %s,\n",
+	   spaces[space], extension_opcode ? extension_opcode : "None");
+
   output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
 }
 
@@ -1257,13 +1292,12 @@ output_i386_opcode (FILE *table, const c
 	  filename, lineno, name, 2 * length, opcode);
 
   ident = mkident (name);
-  fprintf (table, "  { MN_%s, 0x%0*llx%s, %lu, %s,\n",
-	   ident, 2 * (int)length, opcode, end, i,
-	   extension_opcode ? extension_opcode : "None");
+  fprintf (table, "  { MN_%s, 0x%0*llx%s, %u,",
+	   ident, 2 * (int)length, opcode, end, i);
   free (ident);
 
   process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
-				operand_types, lineno);
+				extension_opcode, operand_types, lineno);
 
   process_i386_cpu_flag (table, cpu_flags, NULL, ",", "    ", lineno, CpuMax);
 
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -605,28 +605,6 @@ enum
 #define VEXW1	2
 #define VEXWIG	3
   VexW,
-  /* Opcode encoding space (values chosen to be usable directly in
-     VEX/XOP mmmmm and EVEX mm fields):
-     0: Base opcode space.
-     1: 0F opcode prefix / space.
-     2: 0F38 opcode prefix / space.
-     3: 0F3A opcode prefix / space.
-     5: EVEXMAP5 opcode prefix / space.
-     6: EVEXMAP6 opcode prefix / space.
-     8: XOP 08 opcode space.
-     9: XOP 09 opcode space.
-     A: XOP 0A opcode space.
-   */
-#define SPACE_BASE	0
-#define SPACE_0F	1
-#define SPACE_0F38	2
-#define SPACE_0F3A	3
-#define SPACE_EVEXMAP5	5
-#define SPACE_EVEXMAP6	6
-#define SPACE_XOP08	8
-#define SPACE_XOP09	9
-#define SPACE_XOP0A	0xA
-  OpcodeSpace,
   /* Opcode prefix (values chosen to be usable directly in
      VEX/XOP/EVEX pp fields):
      0: None
@@ -759,7 +737,6 @@ typedef struct i386_opcode_modifier
   unsigned int vex:2;
   unsigned int vexvvvv:2;
   unsigned int vexw:2;
-  unsigned int opcodespace:4;
   unsigned int opcodeprefix:2;
   unsigned int vexsources:2;
   unsigned int sib:3;
@@ -942,8 +919,29 @@ typedef struct insn_template
   /* how many operands */
   unsigned int operands:3;
 
-  /* spare bits */
-  unsigned int :4;
+  /* opcode space */
+  unsigned int opcode_space:4;
+  /* Opcode encoding space (values chosen to be usable directly in
+     VEX/XOP mmmmm and EVEX mm fields):
+     0: Base opcode space.
+     1: 0F opcode prefix / space.
+     2: 0F38 opcode prefix / space.
+     3: 0F3A opcode prefix / space.
+     5: EVEXMAP5 opcode prefix / space.
+     6: EVEXMAP6 opcode prefix / space.
+     8: XOP 08 opcode space.
+     9: XOP 09 opcode space.
+     A: XOP 0A opcode space.
+   */
+#define SPACE_BASE	0
+#define SPACE_0F	1
+#define SPACE_0F38	2
+#define SPACE_0F3A	3
+#define SPACE_EVEXMAP5	5
+#define SPACE_EVEXMAP6	6
+#define SPACE_XOP08	8
+#define SPACE_XOP09	9
+#define SPACE_XOP0A	0xA
 
 /* (Fake) base opcode value for pseudo prefixes.  */
 #define PSEUDO_PREFIX 0


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-02-03  7:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-03  7:30 [PATCH 0/3] x86: assorted opcode processing adjustments Jan Beulich
2023-02-03  7:32 ` [PATCH 1/3] x86: improve special casing of certain insns Jan Beulich
2023-02-03  7:32 ` [PATCH 2/3] x86: simplify a few expressions Jan Beulich
2023-02-03  7:33 ` [PATCH 3/3] x86: move (and rename) opcodespace attribute 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).