public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Jan Beulich <jbeulich@suse.com>
To: Binutils <binutils@sourceware.org>
Subject: [PATCH 1/6] x86: derive opcode encoding space attribute from base opcode
Date: Fri, 26 Mar 2021 11:50:07 +0100	[thread overview]
Message-ID: <13839f88-9792-fdd7-f2a0-35b60da985d2@suse.com> (raw)
In-Reply-To: <287ad145-1fe3-2477-327a-30e8d45a4be7@suse.com>

Just like is already done for VEX/XOP/EVEX encoded insns, record the
encoding space information in the respective opcode modifier field. Do
this again without changing the source table, but rather by deriving the
values from their existing source representation.

gas/
2021-03-XX  Jan Beulich  <jbeulich@suse.com>

	* config/tc-i386.c (optimize_encoding): Replace VEX-encoding
	checks by opcodespace ones.
	(insert_lfence_before): Likewise.
	(maybe_fused_with_jcc_p): Likewise.
	(add_branch_padding_frag_p): Likewise.
	(output_disp): Likewise.
	(load_insn_p): Re-arrange checks to key applicable ones off of
	an opcodespace check.
	(md_assemble): Adjust opcode checks.
	(check_byte_reg): Likewise.
	(process_operands): Likewise.
	(i386_index_check): Likewise.
	(process_suffix): Likewise. New local variable is_movx. Adjust
	movsx/movzx and crc32 handling.
	(output_insn): Adjust opcode checks. Drop no longer reachable
	case labels. Output legacy encoding prefixes in addition to the
	base_opcode byte(s). Rework counting of prefixes for extended
	opcode maps.
	* config/tc-i386-intel.c (i386_intel_simplify_register): Adjust
	opcode checks.

opcodes/
2021-03-XX  Jan Beulich  <jbeulich@suse.com>

	* i386-gen.c (process_i386_opcode_modifier): New parameter
	"space". 
	(output_i386_opcode): New local variable "space". Adjust
	process_i386_opcode_modifier() invocation.
	(process_i386_opcodes): Adjust process_i386_opcode_modifier()
	invocation.
	* i386-tbl.h: Re-generate.

--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -318,9 +318,11 @@ i386_intel_simplify_register (expression
 
       if (intel_state.in_scale
 	  || (t->opcode_modifier.opcodeprefix == PREFIX_0XF3
-	      && t->base_opcode == 0x0f1b /* bndmk */)
+	      && t->opcode_modifier.opcodespace == SPACE_0F
+	      && t->base_opcode == 0x1b /* bndmk */)
 	  || (t->opcode_modifier.opcodeprefix == PREFIX_NONE
-	      && (t->base_opcode & ~1) == 0x0f1a /* bnd{ld,st}x */)
+	      && t->opcode_modifier.opcodespace == SPACE_0F
+	      && (t->base_opcode & ~1) == 0x1a /* bnd{ld,st}x */)
 	  || i386_regtab[reg_num].reg_type.bitfield.baseindex)
 	intel_state.index = i386_regtab + reg_num;
       else
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4040,7 +4040,7 @@ optimize_encoding (void)
   unsigned int j;
 
   if (optimize_for_space
-      && !is_any_vex_encoding (&i.tm)
+      && i.tm.opcode_modifier.opcodespace == SPACE_BASE
       && i.reg_operands == 1
       && i.imm_operands == 1
       && !i.types[1].bitfield.byte
@@ -4072,7 +4072,7 @@ optimize_encoding (void)
 	}
     }
   else if (flag_code == CODE_64BIT
-	   && !is_any_vex_encoding (&i.tm)
+	   && i.tm.opcode_modifier.opcodespace == SPACE_BASE
 	   && ((i.types[1].bitfield.qword
 		&& i.reg_operands == 1
 		&& i.imm_operands == 1
@@ -4138,7 +4138,7 @@ optimize_encoding (void)
     }
   else if (optimize > 1
 	   && !optimize_for_space
-	   && !is_any_vex_encoding (&i.tm)
+	   && 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
@@ -4343,9 +4343,15 @@ load_insn_p (void)
       if (i.tm.opcode_modifier.anysize)
 	return 0;
 
-      /* pop, popf, popa.   */
-      if (strcmp (i.tm.name, "pop") == 0
-	  || i.tm.base_opcode == 0x9d
+      /* pop.   */
+      if (strcmp (i.tm.name, "pop") == 0)
+	return 1;
+    }
+
+  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE)
+    {
+      /* popf, popa.   */
+      if (i.tm.base_opcode == 0x9d
 	  || i.tm.base_opcode == 0x61)
 	return 1;
 
@@ -4375,7 +4381,7 @@ load_insn_p (void)
 	  && i.tm.extension_opcode == 2)
 	return 1;
     }
-  else
+  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)
@@ -4390,40 +4396,14 @@ load_insn_p (void)
       if (i.tm.base_opcode >= 0x80 && i.tm.base_opcode <= 0x83)
 	return 1;
 
-      /* bt, bts, btr, btc.  */
-      if (i.tm.base_opcode == 0xfba
-	  && (i.tm.extension_opcode >= 4 && i.tm.extension_opcode <= 7))
-	return 1;
-
       /* rol, ror, rcl, rcr, shl/sal, shr, sar. */
       if ((base_opcode == 0xc1
 	   || (i.tm.base_opcode >= 0xd0 && i.tm.base_opcode <= 0xd3))
 	  && i.tm.extension_opcode != 6)
 	return 1;
 
-      /* cmpxchg8b, cmpxchg16b, xrstors, vmptrld.  */
-      if (i.tm.base_opcode == 0xfc7
-	  && i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE
-	  && (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3
-	      || i.tm.extension_opcode == 6))
-	return 1;
-
-      /* fxrstor, ldmxcsr, xrstor.  */
-      if (i.tm.base_opcode == 0xfae
-	  && (i.tm.extension_opcode == 1
-	      || i.tm.extension_opcode == 2
-	      || i.tm.extension_opcode == 5))
-	return 1;
-
-      /* lgdt, lidt, lmsw.  */
-      if (i.tm.base_opcode == 0xf01
-	  && (i.tm.extension_opcode == 2
-	      || i.tm.extension_opcode == 3
-	      || i.tm.extension_opcode == 6))
-	return 1;
-
       /* Check for x87 instructions.  */
-      if (i.tm.base_opcode >= 0xd8 && i.tm.base_opcode <= 0xdf)
+      if (base_opcode >= 0xd8 && base_opcode <= 0xdf)
 	{
 	  /* Skip fst, fstp, fstenv, fstcw.  */
 	  if (i.tm.base_opcode == 0xd9
@@ -4462,6 +4442,34 @@ load_insn_p (void)
 	  return 1;
 	}
     }
+  else if (i.tm.opcode_modifier.opcodespace == SPACE_0F)
+    {
+      /* bt, bts, btr, btc.  */
+      if (i.tm.base_opcode == 0xba
+	  && (i.tm.extension_opcode >= 4 && i.tm.extension_opcode <= 7))
+	return 1;
+
+      /* cmpxchg8b, cmpxchg16b, xrstors, vmptrld.  */
+      if (i.tm.base_opcode == 0xc7
+	  && i.tm.opcode_modifier.opcodeprefix == PREFIX_NONE
+	  && (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3
+	      || i.tm.extension_opcode == 6))
+	return 1;
+
+      /* fxrstor, ldmxcsr, xrstor.  */
+      if (i.tm.base_opcode == 0xae
+	  && (i.tm.extension_opcode == 1
+	      || i.tm.extension_opcode == 2
+	      || i.tm.extension_opcode == 5))
+	return 1;
+
+      /* lgdt, lidt, lmsw.  */
+      if (i.tm.base_opcode == 0x01
+	  && (i.tm.extension_opcode == 2
+	      || i.tm.extension_opcode == 3
+	      || i.tm.extension_opcode == 6))
+	return 1;
+    }
 
   dest = i.operands - 1;
 
@@ -4471,8 +4479,8 @@ load_insn_p (void)
       && i.types[dest].bitfield.imm8)
     dest--;
 
-  /* add, or, adc, sbb, and, sub, xor, cmp, test, xchg, xadd  */
-  if (!any_vex_p
+  /* 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
@@ -4481,8 +4489,12 @@ load_insn_p (void)
 	  || base_opcode == 0x29
 	  || base_opcode == 0x31
 	  || base_opcode == 0x39
-	  || (i.tm.base_opcode >= 0x84 && i.tm.base_opcode <= 0x87)
-	  || base_opcode == 0xfc1))
+	  || (base_opcode | 2) == 0x87))
+    return 1;
+
+  /* xadd.  */
+  if (i.tm.opcode_modifier.opcodespace == SPACE_0F
+      && base_opcode == 0xc1)
     return 1;
 
   /* Check for load instruction.  */
@@ -4527,7 +4539,7 @@ insert_lfence_before (void)
 {
   char *p;
 
-  if (is_any_vex_encoding (&i.tm))
+  if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
     return;
 
   if (i.tm.base_opcode == 0xff
@@ -4908,7 +4920,8 @@ md_assemble (char *line)
   /* 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.base_opcode == INT_OPCODE
+  if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
+      && i.tm.base_opcode == INT_OPCODE
       && !i.tm.opcode_modifier.modrm
       && i.op[0].imms->X_add_number == 3)
     {
@@ -6289,7 +6302,8 @@ match_template (char mnem_suffix)
       j = i.imm_operands + (t->operands > i.imm_operands + 1);
       if (((i.suffix == QWORD_MNEM_SUFFIX
 	    && flag_code != CODE_64BIT
-	    && !(t->base_opcode == 0xfc7
+	    && !(t->opcode_modifier.opcodespace == SPACE_0F
+		 && t->base_opcode == 0xc7
 		 && t->opcode_modifier.opcodeprefix == PREFIX_NONE
 		 && t->extension_opcode == 1) /* cmpxchg8b */)
 	   || (i.suffix == LONG_MNEM_SUFFIX
@@ -6740,7 +6754,7 @@ check_string (void)
 static int
 process_suffix (void)
 {
-  bfd_boolean is_crc32 = FALSE;
+  bfd_boolean is_crc32 = FALSE, is_movx = FALSE;
 
   /* If matched instruction specifies an explicit instruction mnemonic
      suffix, use it.  */
@@ -6755,17 +6769,23 @@ process_suffix (void)
 	   && !i.tm.opcode_modifier.addrprefixopreg)
     {
       unsigned int numop = i.operands;
+
+      /* MOVSX/MOVZX */
+      is_movx = (i.tm.opcode_modifier.opcodespace == SPACE_0F
+		 && (i.tm.base_opcode | 8) == 0xbe)
+		|| (i.tm.opcode_modifier.opcodespace == SPACE_BASE
+		    && i.tm.base_opcode == 0x63
+		    && i.tm.cpu_flags.bitfield.cpu64);
+
       /* CRC32 */
-      is_crc32 = (i.tm.base_opcode == 0xf38f0
+      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).  */
-      if (((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w)
-	  || (i.tm.base_opcode == 0x63
-	      && i.tm.opcode_modifier.opcodespace == SPACE_BASE
-	      && i.tm.cpu_flags.bitfield.cpu64))
+      if (is_movx && (i.tm.opcode_modifier.w || i.tm.base_opcode == 0x63))
 	--i.operands;
 
       /* crc32 needs REX.W set regardless of suffix / source operand size.  */
@@ -6803,8 +6823,7 @@ process_suffix (void)
 
 	  /* As an exception, movsx/movzx silently default to a byte source
 	     in AT&T mode.  */
-	  if ((i.tm.base_opcode | 8) == 0xfbe && i.tm.opcode_modifier.w
-	      && !i.suffix && !intel_syntax)
+	  if (is_movx && i.tm.opcode_modifier.w && !i.suffix && !intel_syntax)
 	    i.suffix = BYTE_MNEM_SUFFIX;
 	}
       else if (i.suffix == BYTE_MNEM_SUFFIX)
@@ -6883,7 +6902,8 @@ 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.base_opcode == 0x0f01 /* [ls][gi]dt */
+	       || (i.tm.opcode_modifier.opcodespace == SPACE_0F
+		   && i.tm.base_opcode == 0x01 /* [ls][gi]dt */
 		   && i.tm.extension_opcode <= 3)))
     {
       switch (flag_code)
@@ -7011,10 +7031,7 @@ process_suffix (void)
 
 	  if (i.tm.opcode_modifier.floatmf)
 	    i.suffix = SHORT_MNEM_SUFFIX;
-	  else if ((i.tm.base_opcode | 8) == 0xfbe
-		   || (i.tm.base_opcode == 0x63
-		       && i.tm.opcode_modifier.opcodespace == SPACE_BASE
-		       && i.tm.cpu_flags.bitfield.cpu64))
+	  else if (is_movx)
 	    /* handled below */;
 	  else if (evex)
 	    i.tm.opcode_modifier.evex = evex;
@@ -7027,10 +7044,7 @@ process_suffix (void)
 	}
     }
 
-  if ((i.tm.base_opcode | 8) == 0xfbe
-      || (i.tm.base_opcode == 0x63
-	  && i.tm.opcode_modifier.opcodespace == SPACE_BASE
-	  && i.tm.cpu_flags.bitfield.cpu64))
+  if (is_movx)
     {
       /* In Intel syntax, movsx/movzx must have a "suffix" (checked above).
 	 In AT&T syntax, if there is no suffix (warned about above), the default
@@ -7252,7 +7266,8 @@ check_byte_reg (void)
 	continue;
 
       /* crc32 only wants its source operand checked here.  */
-      if (i.tm.base_opcode == 0xf38f0
+      if (i.tm.base_opcode == 0xf0
+	  && i.tm.opcode_modifier.opcodespace == SPACE_0F38
 	  && i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2
 	  && op != 0)
 	continue;
@@ -7678,21 +7693,23 @@ process_operands (void)
       if (flag_code != CODE_64BIT
 	  ? i.tm.base_opcode == POP_SEG_SHORT
 	    && i.op[0].regs->reg_num == 1
-	  : (i.tm.base_opcode | 1) == POP_SEG386_SHORT
+	  : (i.tm.base_opcode | 1) == (POP_SEG386_SHORT & 0xff)
 	    && i.op[0].regs->reg_num < 4)
 	{
 	  as_bad (_("you can't `%s %s%s'"),
 		  i.tm.name, register_prefix, i.op[0].regs->reg_name);
 	  return 0;
 	}
-      if ( i.op[0].regs->reg_num > 3 && i.opcode_length == 1 )
+      if (i.op[0].regs->reg_num > 3
+	  && i.tm.opcode_modifier.opcodespace == SPACE_BASE )
 	{
-	  i.tm.base_opcode ^= POP_SEG_SHORT ^ POP_SEG386_SHORT;
-	  i.opcode_length = 2;
+	  i.tm.base_opcode ^= (POP_SEG_SHORT ^ POP_SEG386_SHORT) & 0xff;
+	  i.tm.opcode_modifier.opcodespace = SPACE_0F;
 	}
       i.tm.base_opcode |= (i.op[0].regs->reg_num << 3);
     }
-  else if ((i.tm.base_opcode & ~0x3) == MOV_AX_DISP32)
+  else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
+	   && (i.tm.base_opcode & ~3) == MOV_AX_DISP32)
     {
       default_seg = &ds;
     }
@@ -8949,8 +8966,8 @@ maybe_fused_with_jcc_p (enum mf_cmp_kind
   if (i.base_reg && i.base_reg->reg_num == RegIP)
     return 0;
 
-  /* No VEX/EVEX encoding.  */
-  if (is_any_vex_encoding (&i.tm))
+  /* No opcodes outside of base encoding space.  */
+  if (i.tm.opcode_modifier.opcodespace != SPACE_BASE)
     return 0;
 
   /* add, sub without add/sub m, imm.  */
@@ -9073,7 +9090,8 @@ add_branch_padding_frag_p (enum align_br
   /* NB: Don't work with COND_JUMP86 without i386.  */
   if (!align_branch_power
       || now_seg == absolute_section
-      || !cpu_arch_flags.bitfield.cpui386)
+      || !cpu_arch_flags.bitfield.cpui386
+      || i.tm.opcode_modifier.opcodespace != SPACE_BASE)
     return 0;
 
   add_padding = 0;
@@ -9096,8 +9114,6 @@ add_branch_padding_frag_p (enum align_br
 	    add_padding = 1;
 	}
     }
-  else if (is_any_vex_encoding (&i.tm))
-    return 0;
   else if ((i.tm.base_opcode | 1) == 0xc3)
     {
       /* Near ret.  */
@@ -9181,8 +9197,10 @@ output_insn (void)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87;
 
       if ((i.xstate & xstate_mmx)
-	  || i.tm.base_opcode == 0xf77 /* emms */
-	  || i.tm.base_opcode == 0xf0e /* femms */)
+	  || (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 */)))
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MMX;
 
       if (i.index_reg)
@@ -9200,10 +9218,10 @@ output_insn (void)
 	i.xstate |= xstate_ymm;
 
       if ((i.xstate & xstate_xmm)
-	  /* ldmxcsr / stmxcsr */
-	  || (i.tm.base_opcode == 0xfae && i.tm.cpu_flags.bitfield.cpusse)
-	  /* vldmxcsr / vstmxcsr */
-	  || (i.tm.base_opcode == 0xae && i.tm.cpu_flags.bitfield.cpuavx)
+	  /* ldmxcsr / stmxcsr / vldmxcsr / vstmxcsr */
+	  || (i.tm.base_opcode == 0xae
+	      && (i.tm.cpu_flags.bitfield.cpusse
+		  || i.tm.cpu_flags.bitfield.cpuavx))
 	  || i.tm.cpu_flags.bitfield.cpuwidekl
 	  || i.tm.cpu_flags.bitfield.cpukl)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XMM;
@@ -9226,7 +9244,8 @@ output_insn (void)
       if (x86_feature_2_used
 	  || i.tm.cpu_flags.bitfield.cpucmov
 	  || i.tm.cpu_flags.bitfield.cpusyscall
-	  || (i.tm.base_opcode == 0xfc7
+	  || (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 */)
 	x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_BASELINE;
@@ -9327,9 +9346,9 @@ output_insn (void)
       enum mf_cmp_kind mf_cmp;
 
       if (avoid_fence
-	  && (i.tm.base_opcode == 0xfaee8
-	      || i.tm.base_opcode == 0xfaef0
-	      || i.tm.base_opcode == 0xfaef8))
+	  && (i.tm.base_opcode == 0xaee8
+	      || i.tm.base_opcode == 0xaef0
+	      || i.tm.base_opcode == 0xaef8))
 	{
 	  /* Encode lfence, mfence, and sfence as
 	     f0 83 04 24 00   lock addl $0x0, (%{re}sp).  */
@@ -9411,7 +9430,6 @@ output_insn (void)
 	    case PREFIX_NONE:
 	      switch (i.opcode_length)
 		{
-		case 3:
 		case 2:
 		  break;
 		case 1:
@@ -9482,36 +9500,55 @@ 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)
+	  {
+	  case SPACE_BASE:
+	    break;
+	  case SPACE_0F:
+	    ++j;
+	    break;
+	  case SPACE_0F38:
+	  case SPACE_0F3A:
+	    j += 2;
+	    break;
+	  default:
+	    abort ();
+	  }
+
       if (now_seg == absolute_section)
-	abs_section_offset += i.opcode_length;
-      else if (i.opcode_length == 1)
+	abs_section_offset += j;
+      else if (j == 1)
 	{
 	  FRAG_APPEND_1_CHAR (i.tm.base_opcode);
 	}
       else
 	{
+	  p = frag_more (j);
+	  if (!i.vex.length
+	      && i.tm.opcode_modifier.opcodespace != SPACE_BASE)
+	    {
+	      *p++ = 0x0f;
+	      if (i.tm.opcode_modifier.opcodespace != SPACE_0F)
+		*p++ = i.tm.opcode_modifier.opcodespace == SPACE_0F38
+		       ? 0x38 : 0x3a;
+	    }
+
 	  switch (i.opcode_length)
 	    {
-	    case 4:
-	      p = frag_more (4);
-	      *p++ = (i.tm.base_opcode >> 24) & 0xff;
-	      *p++ = (i.tm.base_opcode >> 16) & 0xff;
-	      break;
-	    case 3:
-	      p = frag_more (3);
-	      *p++ = (i.tm.base_opcode >> 16) & 0xff;
-	      break;
 	    case 2:
-	      p = frag_more (2);
+	      /* Put out high byte first: can't use md_number_to_chars!  */
+	      *p++ = (i.tm.base_opcode >> 8) & 0xff;
+	      /* Fall through.  */
+	    case 1:
+	      *p = i.tm.base_opcode & 0xff;
 	      break;
 	    default:
 	      abort ();
 	      break;
 	    }
 
-	  /* Put out high byte first: can't use md_number_to_chars!  */
-	  *p++ = (i.tm.base_opcode >> 8) & 0xff;
-	  *p = i.tm.base_opcode & 0xff;
 	}
 
       /* Now the modrm byte and sib byte (if present).  */
@@ -9566,28 +9603,16 @@ output_insn (void)
 
 	      /* Count prefixes for extended opcode maps.  */
 	      if (!i.vex.length)
-		switch (i.opcode_length)
+		switch (i.tm.opcode_modifier.opcodespace)
 		  {
-		  case 3:
-		    if (((i.tm.base_opcode >> 16) & 0xff) == 0xf)
-		      {
-			count++;
-			switch ((i.tm.base_opcode >> 8) & 0xff)
-			  {
-			  case 0x38:
-			  case 0x3a:
-			    count++;
-			    break;
-			  default:
-			    break;
-			  }
-		      }
+		  case SPACE_BASE:
 		    break;
-		  case 2:
-		    if (((i.tm.base_opcode >> 8) & 0xff) == 0xf)
-		      count++;
+		  case SPACE_0F:
+		    count++;
 		    break;
-		  case 1:
+		  case SPACE_0F38:
+		  case SPACE_0F3A:
+		    count += 2;
 		    break;
 		  default:
 		    abort ();
@@ -9807,7 +9832,7 @@ output_disp (fragS *insn_start_frag, off
 			  && i.rm.regmem == 5))
 		  && (i.rm.mode == 2
 		      || (i.rm.mode == 0 && i.rm.regmem == 5))
-		  && !is_any_vex_encoding(&i.tm)
+		  && i.tm.opcode_modifier.opcodespace == SPACE_BASE
 		  && ((i.operands == 1
 		       && i.tm.base_opcode == 0xff
 		       && (i.rm.reg == 2 || i.rm.reg == 4))
@@ -11103,9 +11128,11 @@ i386_index_check (const char *operand_st
 
 	  /* bndmk, bndldx, bndstx and mandatory non-vector SIB have special restrictions. */
 	  if ((t->opcode_modifier.opcodeprefix == PREFIX_0XF3
-	       && t->base_opcode == 0x0f1b)
+	       && t->opcode_modifier.opcodespace == SPACE_0F
+	       && t->base_opcode == 0x1b)
 	      || (t->opcode_modifier.opcodeprefix == PREFIX_NONE
-		  && (t->base_opcode & ~1) == 0x0f1a)
+		  && t->opcode_modifier.opcodespace == SPACE_0F
+		  && (t->base_opcode & ~1) == 0x1a)
 	      || t->opcode_modifier.sib == SIBMEM)
 	    {
 	      /* They cannot use RIP-relative addressing. */
@@ -11117,7 +11144,8 @@ i386_index_check (const char *operand_st
 
 	      /* bndldx and bndstx ignore their scale factor. */
 	      if (t->opcode_modifier.opcodeprefix == PREFIX_NONE
-		  && (t->base_opcode & ~1) == 0x0f1a
+		  && t->opcode_modifier.opcodespace == SPACE_0F
+		  && (t->base_opcode & ~1) == 0x1a
 		  && i.log2_scale_factor)
 		as_warn (_("register scaling is being ignored here"));
 	    }
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -1176,8 +1176,8 @@ adjust_broadcast_modifier (char **opnd)
 }
 
 static void
-process_i386_opcode_modifier (FILE *table, char *mod, unsigned int prefix,
-			      char **opnd, int lineno)
+process_i386_opcode_modifier (FILE *table, char *mod, unsigned int space,
+			      unsigned int prefix, char **opnd, int lineno)
 {
   char *str, *next, *last;
   bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
@@ -1220,6 +1220,19 @@ 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)
@@ -1355,7 +1368,7 @@ static void
 output_i386_opcode (FILE *table, const char *name, char *str,
 		    char *last, int lineno)
 {
-  unsigned int i, length, prefix = 0;
+  unsigned int i, length, prefix = 0, space = 0;
   char *base_opcode, *extension_opcode, *end;
   char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
   unsigned long int opcode;
@@ -1427,10 +1440,27 @@ output_i386_opcode (FILE *table, const c
 	opcode &= (1UL << (8 * --length)) - 1;
     }
 
+  /* Transform opcode space encoded in the opcode into opcode modifier
+     representation.  */
+  if (length > 1 && (opcode >> (8 * length - 8)) == 0xf)
+    {
+      switch ((opcode >> (8 * length - 16)) & 0xff)
+	{
+	default:   space = SPACE_0F;   break;
+	case 0x38: space = SPACE_0F38; break;
+	case 0x3A: space = SPACE_0F3A; break;
+	}
+
+      if (space != SPACE_0F && --length == 1)
+	fail (_("%s:%d: %s: unrecognized opcode encoding space\n"),
+	      filename, lineno, name);
+      opcode &= (1UL << (8 * --length)) - 1;
+    }
+
   fprintf (table, "  { \"%s\", 0x%0*lx%s, %s, %lu,\n",
 	   name, 2 * (int)length, opcode, end, extension_opcode, i);
 
-  process_i386_opcode_modifier (table, opcode_modifier, prefix,
+  process_i386_opcode_modifier (table, opcode_modifier, space, prefix,
 				operand_types, lineno);
 
   process_i386_cpu_flag (table, cpu_flags, 0, ",", "    ", lineno);
@@ -1822,7 +1852,7 @@ process_i386_opcodes (FILE *table)
 
   fprintf (table, "  { NULL, 0, 0, 0,\n");
 
-  process_i386_opcode_modifier (table, "0", 0, NULL, -1);
+  process_i386_opcode_modifier (table, "0", 0, 0, NULL, -1);
 
   process_i386_cpu_flag (table, "0", 0, ",", "    ", -1);
 


  reply	other threads:[~2021-03-26 10:50 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-26 10:48 [PATCH 0/6] x86: further opcode table compaction plus fallout Jan Beulich
2021-03-26 10:50 ` Jan Beulich [this message]
2021-03-26 10:50 ` [PATCH 2/6] x86: shrink some struct insn_template fields Jan Beulich
2021-03-29 13:00   ` H.J. Lu
2021-03-29 14:03     ` Jan Beulich
2021-03-29 14:41       ` H.J. Lu
2021-03-29 14:49         ` Jan Beulich
2021-03-29 14:51           ` H.J. Lu
2021-03-26 10:51 ` [PATCH 3/6] x86: undo Prefix_0X<nn> use in opcode table Jan Beulich
2021-03-26 10:51 ` [PATCH 4/6] x86: fold SSE2AVX and their base MMX/SSE templates Jan Beulich
2021-03-29 13:31   ` H.J. Lu
2021-03-26 10:52 ` [PATCH 5/6] x86: VPSADBW's source operands are also commutative Jan Beulich
2021-03-26 10:53 ` [PATCH 6/6] x86: move some opcode table entries Jan Beulich
2021-03-26 21:16 ` [PATCH 0/6] x86: further opcode table compaction plus fallout H.J. Lu
2021-03-29 10:08   ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=13839f88-9792-fdd7-f2a0-35b60da985d2@suse.com \
    --to=jbeulich@suse.com \
    --cc=binutils@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).