public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/7] x86: assorted simplifications / tidying
@ 2021-03-26 13:44 Jan Beulich
  2021-03-26 13:46 ` [PATCH 1/7] x86: make swap_2_operands() have unsigned parameters Jan Beulich
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:44 UTC (permalink / raw)
  To: Binutils

Or so I hope. While generally independent, if in doubt this goes on
top of "[PATCH 0/6] x86: further opcode table compaction plus fallout"
sent earlier today.

1: make swap_2_operands() have unsigned parameters
2: integrate mask_op into struct _i386_insn
3: integrate broadcast_op into struct _i386_insn
4: integrate rc_op into struct _i386_insn
5: adjust st(<N>) parsing
6: drop REGNAM_{AL,AX,EAX}
7: drop seg_entry

Jan

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

* [PATCH 1/7] x86: make swap_2_operands() have unsigned parameters
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
@ 2021-03-26 13:46 ` Jan Beulich
  2021-03-26 13:47 ` [PATCH 2/7] x86: integrate mask_op into struct _i386_insn Jan Beulich
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:46 UTC (permalink / raw)
  To: Binutils

All callers pass unsigned values (in some cases by virtue of passing
non-negative literal numbers).

This in turn requires struct {Mask,RC,Broadcast}_Operation's "operand"
fields to become unsigned, in turn allowing to reduce the amount of
casting needed (the two new casts that are necessary cast _to_
"unsigned" instead of _from_, as that's the form that'll never case
undefined behavior).

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

	* config/tc-i386.c (swap_2_operands): Switch parameters to
	unsigned.
	(struct RC_Operation): Switch operand field to unsigned.
	(struct Mask_Operation): Likewise.
	(struct Broadcast_Operation): Likewise.
	(build_evex_prefix): Drop cast.
	(check_VecOperands): Likewise.
	(build_modrm_byte): Likewise.
	(output_imm): Likewise.
	(check_VecOperations): Add casts to unsigned.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -177,7 +177,7 @@ static const reg_entry *parse_register (
 static char *parse_insn (char *, char *);
 static char *parse_operands (char *, const char *);
 static void swap_operands (void);
-static void swap_2_operands (int, int);
+static void swap_2_operands (unsigned int, unsigned int);
 static enum flag_code i386_addressing_mode (void);
 static void optimize_imm (void);
 static void optimize_disp (void);
@@ -225,7 +225,7 @@ struct RC_Operation
       rz,
       saeonly
     } type;
-  int operand;
+  unsigned int operand;
 };
 
 static struct RC_Operation rc_op;
@@ -238,7 +238,7 @@ struct Mask_Operation
   const reg_entry *mask;
   unsigned int zeroing;
   /* The operand where this operation is associated.  */
-  int operand;
+  unsigned int operand;
 };
 
 static struct Mask_Operation mask_op;
@@ -251,7 +251,7 @@ struct Broadcast_Operation
   int type;
 
   /* Index of broadcasted operand.  */
-  int operand;
+  unsigned int operand;
 
   /* Number of bytes to broadcast.  */
   int bytes;
@@ -3907,7 +3907,7 @@ build_evex_prefix (void)
 		    i.tm.opcode_modifier.evex = EVEX128;
 		    break;
 		  }
-		else if (i.broadcast && (int) op == i.broadcast->operand)
+		else if (i.broadcast && op == i.broadcast->operand)
 		  {
 		    switch (i.broadcast->bytes)
 		      {
@@ -5438,7 +5438,7 @@ parse_operands (char *l, const char *mne
 }
 
 static void
-swap_2_operands (int xchg1, int xchg2)
+swap_2_operands (unsigned int xchg1, unsigned int xchg2)
 {
   union i386_op temp_op;
   i386_operand_type temp_type;
@@ -6018,7 +6018,7 @@ check_VecOperands (const insn_template *
     }
 
   /* Check if masking is applied to dest operand.  */
-  if (i.mask && (i.mask->operand != (int) (i.operands - 1)))
+  if (i.mask && (i.mask->operand != i.operands - 1))
     {
       i.error = mask_not_on_destination;
       return 1;
@@ -6037,7 +6037,7 @@ check_VecOperands (const insn_template *
 	 them is rounding, the rounding operand should be the last
 	 immediate operand.  */
       if (i.imm_operands > 1
-	  && i.rounding->operand != (int) (i.imm_operands - 1))
+	  && i.rounding->operand != i.imm_operands - 1)
 	{
 	  i.error = rc_sae_operand_not_last_imm;
 	  return 1;
@@ -7965,7 +7965,7 @@ build_modrm_byte (void)
 	  /* RC/SAE operand could be between DEST and SRC.  That happens
 	     when one operand is GPR and the other one is XMM/YMM/ZMM
 	     register.  */
-	  if (i.rounding && i.rounding->operand == (int) dest)
+	  if (i.rounding && i.rounding->operand == dest)
 	    dest++;
 
 	  if (i.tm.opcode_modifier.vexvvvv == VEXXDS)
@@ -9865,7 +9865,7 @@ output_imm (fragS *insn_start_frag, offs
   for (n = 0; n < i.operands; n++)
     {
       /* Skip SAE/RC Imm operand in EVEX.  They are already handled.  */
-      if (i.rounding && (int) n == i.rounding->operand)
+      if (i.rounding && n == i.rounding->operand)
 	continue;
 
       if (operand_type_check (i.types[n], imm))
@@ -10447,7 +10447,7 @@ check_VecOperations (char *op_string, ch
 
 		  /* Only "{z}" is allowed here.  No need to check
 		     zeroing mask explicitly.  */
-		  if (i.mask->operand != this_operand)
+		  if (i.mask->operand != (unsigned int) this_operand)
 		    {
 		      as_bad (_("invalid write mask `%s'"), saved);
 		      return NULL;
@@ -10479,7 +10479,7 @@ check_VecOperations (char *op_string, ch
 
 		  /* Only "{%k}" is allowed here.  No need to check mask
 		     register explicitly.  */
-		  if (i.mask->operand != this_operand)
+		  if (i.mask->operand != (unsigned int) this_operand)
 		    {
 		      as_bad (_("invalid zeroing-masking `%s'"),
 			      saved);


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

* [PATCH 2/7] x86: integrate mask_op into struct _i386_insn
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
  2021-03-26 13:46 ` [PATCH 1/7] x86: make swap_2_operands() have unsigned parameters Jan Beulich
@ 2021-03-26 13:47 ` Jan Beulich
  2021-03-26 13:48 ` [PATCH 3/7] x86: integrate broadcast_op " Jan Beulich
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:47 UTC (permalink / raw)
  To: Binutils

There's no need for the extra level of indirection and the extra storage
needed for the pointer, pointing from one piece of static data to
another. Key checking of masking being in effect off of the register
field of the structure instead.

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

	* config/tc-i386.c (reg_k0): New.
	(mask_op): Delete.
	(struct Mask_Operation): Move ...
	(struct _i386_insn): ... here. Change field "mask".
	(md_begin): Initialize reg_k0.
	(build_evex_prefix): Adjust mask processing.
	(swap_2_operands): Likewise.
	(check_VecOperands): Likewise.
	(check_VecOperations): Likewise.
	(optimize_encoding): Adjust checks for masking.
	(output_insn): Likewise.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -214,6 +214,8 @@ static const char *default_arch = DEFAUL
 static const reg_entry bad_reg = { "<bad>", OPERAND_TYPE_NONE, 0, 0,
 				   { Dw2Inval, Dw2Inval } };
 
+static const reg_entry *reg_k0;
+
 /* This struct describes rounding control and SAE in the instruction.  */
 struct RC_Operation
 {
@@ -230,19 +232,6 @@ struct RC_Operation
 
 static struct RC_Operation rc_op;
 
-/* The struct describes masking, applied to OPERAND in the instruction.
-   MASK is a pointer to the corresponding mask register.  ZEROING tells
-   whether merging or zeroing mask is used.  */
-struct Mask_Operation
-{
-  const reg_entry *mask;
-  unsigned int zeroing;
-  /* The operand where this operation is associated.  */
-  unsigned int operand;
-};
-
-static struct Mask_Operation mask_op;
-
 /* The struct describes broadcasting, applied to OPERAND.  FACTOR is
    broadcast factor.  */
 struct Broadcast_Operation
@@ -393,8 +382,18 @@ struct _i386_insn
     sib_byte sib;
     vex_prefix vex;
 
-    /* Masking attributes.  */
-    struct Mask_Operation *mask;
+    /* Masking attributes.
+
+       The struct describes masking, applied to OPERAND in the instruction.
+       REG is a pointer to the corresponding mask register.  ZEROING tells
+       whether merging or zeroing mask is used.  */
+    struct Mask_Operation
+    {
+      const reg_entry *reg;
+      unsigned int zeroing;
+      /* The operand where this operation is associated.  */
+      unsigned int operand;
+    } mask;
 
     /* Rounding control and SAE attributes.  */
     struct RC_Operation *rounding;
@@ -3093,8 +3092,13 @@ md_begin (void)
     unsigned int regtab_size = i386_regtab_size;
 
     for (regtab = i386_regtab; regtab_size--; regtab++)
-      if (str_hash_insert (reg_hash, regtab->reg_name, regtab, 0) != NULL)
-	as_fatal (_("duplicate %s"), regtab->reg_name);
+      {
+	if (str_hash_insert (reg_hash, regtab->reg_name, regtab, 0) != NULL)
+	  as_fatal (_("duplicate %s"), regtab->reg_name);
+
+	if (regtab->reg_type.bitfield.class == RegMask && !regtab->reg_num)
+	  reg_k0 = regtab;
+      }
   }
 
   /* Fill in lexical tables:  mnemonic_chars, operand_chars.  */
@@ -3871,7 +3875,7 @@ build_evex_prefix (void)
 
   /* The fourth byte of the EVEX prefix.  */
   /* The zeroing-masking bit.  */
-  if (i.mask && i.mask->zeroing)
+  if (i.mask.reg && i.mask.zeroing)
     i.vex.bytes[3] |= 0x80;
 
   /* Don't always set the broadcast bit if there is no RC.  */
@@ -3962,8 +3966,8 @@ build_evex_prefix (void)
 	i.vex.bytes[3] |= 0x10 | (evexrcig << 5);
     }
 
-  if (i.mask && i.mask->mask)
-    i.vex.bytes[3] |= i.mask->mask->reg_num;
+  if (i.mask.reg)
+    i.vex.bytes[3] |= i.mask.reg->reg_num;
 }
 
 static void
@@ -4164,7 +4168,7 @@ optimize_encoding (void)
 	   && i.op[0].regs == i.op[1].regs
 	   && !i.types[2].bitfield.xmmword
 	   && (i.tm.opcode_modifier.vex
-	       || ((!i.mask || i.mask->zeroing)
+	       || ((!i.mask.reg || i.mask.zeroing)
 		   && !i.rounding
 		   && is_evex_encoding (&i.tm)
 		   && (i.vec_encoding != vex_encoding_evex
@@ -4250,7 +4254,7 @@ optimize_encoding (void)
   else if (i.vec_encoding != vex_encoding_evex
 	   && !i.types[0].bitfield.zmmword
 	   && !i.types[1].bitfield.zmmword
-	   && !i.mask
+	   && !i.mask.reg
 	   && !i.broadcast
 	   && is_evex_encoding (&i.tm)
 	   && ((i.tm.base_opcode & ~Opcode_SIMD_IntD) == 0x6f
@@ -5461,12 +5465,12 @@ swap_2_operands (unsigned int xchg1, uns
   i.reloc[xchg2] = i.reloc[xchg1];
   i.reloc[xchg1] = temp_reloc;
 
-  if (i.mask)
+  if (i.mask.reg)
     {
-      if (i.mask->operand == xchg1)
-	i.mask->operand = xchg2;
-      else if (i.mask->operand == xchg2)
-	i.mask->operand = xchg1;
+      if (i.mask.operand == xchg1)
+	i.mask.operand = xchg2;
+      else if (i.mask.operand == xchg2)
+	i.mask.operand = xchg1;
     }
   if (i.broadcast)
     {
@@ -5802,7 +5806,7 @@ check_VecOperands (const insn_template *
 
   /* Check if default mask is allowed.  */
   if (t->opcode_modifier.nodefmask
-      && (!i.mask || i.mask->mask->reg_num == 0))
+      && (!i.mask.reg || i.mask.reg->reg_num == 0))
     {
       i.error = no_default_mask;
       return 1;
@@ -5824,8 +5828,8 @@ check_VecOperands (const insn_template *
 	return 1;
       }
 
-      gas_assert (i.reg_operands == 2 || i.mask);
-      if (i.reg_operands == 2 && !i.mask)
+      gas_assert (i.reg_operands == 2 || i.mask.reg);
+      if (i.reg_operands == 2 && !i.mask.reg)
 	{
 	  gas_assert (i.types[0].bitfield.class == RegSIMD);
 	  gas_assert (i.types[0].bitfield.xmmword
@@ -5849,7 +5853,7 @@ check_VecOperands (const insn_template *
 	    }
 	  as_warn (_("mask, index, and destination registers should be distinct"));
 	}
-      else if (i.reg_operands == 1 && i.mask)
+      else if (i.reg_operands == 1 && i.mask.reg)
 	{
 	  if (i.types[1].bitfield.class == RegSIMD
 	      && (i.types[1].bitfield.xmmword
@@ -5982,14 +5986,14 @@ check_VecOperands (const insn_template *
     op = MAX_OPERANDS - 1; /* Avoid uninitialized variable warning.  */
 
   /* Check if requested masking is supported.  */
-  if (i.mask)
+  if (i.mask.reg)
     {
       switch (t->opcode_modifier.masking)
 	{
 	case BOTH_MASKING:
 	  break;
 	case MERGING_MASKING:
-	  if (i.mask->zeroing)
+	  if (i.mask.zeroing)
 	    {
 	case 0:
 	      i.error = unsupported_masking;
@@ -5998,7 +6002,7 @@ check_VecOperands (const insn_template *
 	  break;
 	case DYNAMIC_MASKING:
 	  /* Memory destinations allow only merging masking.  */
-	  if (i.mask->zeroing && i.mem_operands)
+	  if (i.mask.zeroing && i.mem_operands)
 	    {
 	      /* Find memory operand.  */
 	      for (op = 0; op < i.operands; op++)
@@ -6018,7 +6022,7 @@ check_VecOperands (const insn_template *
     }
 
   /* Check if masking is applied to dest operand.  */
-  if (i.mask && (i.mask->operand != i.operands - 1))
+  if (i.mask.reg && (i.mask.operand != i.operands - 1))
     {
       i.error = mask_not_on_destination;
       return 1;
@@ -9230,7 +9234,7 @@ output_insn (void)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_YMM;
       if ((i.xstate & xstate_zmm) == xstate_zmm)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_ZMM;
-      if (i.mask || (i.xstate & xstate_mask) == xstate_mask)
+      if (i.mask.reg || (i.xstate & xstate_mask) == xstate_mask)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MASK;
       if (i.tm.cpu_flags.bitfield.cpufxsr)
 	x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_FXSR;
@@ -10431,23 +10435,20 @@ check_VecOperations (char *op_string, ch
 		  return NULL;
 		}
 
-	      if (!i.mask)
+	      if (!i.mask.reg)
 		{
-		  mask_op.mask = mask;
-		  mask_op.zeroing = 0;
-		  mask_op.operand = this_operand;
-		  i.mask = &mask_op;
+		  i.mask.reg = mask;
+		  i.mask.operand = this_operand;
 		}
+	      else if (i.mask.reg->reg_num)
+		goto duplicated_vec_op;
 	      else
 		{
-		  if (i.mask->mask)
-		    goto duplicated_vec_op;
-
-		  i.mask->mask = mask;
+		  i.mask.reg = mask;
 
 		  /* Only "{z}" is allowed here.  No need to check
 		     zeroing mask explicitly.  */
-		  if (i.mask->operand != (unsigned int) this_operand)
+		  if (i.mask.operand != (unsigned int) this_operand)
 		    {
 		      as_bad (_("invalid write mask `%s'"), saved);
 		      return NULL;
@@ -10459,27 +10460,26 @@ check_VecOperations (char *op_string, ch
 	  /* Check zeroing-flag for masking operation.  */
 	  else if (*op_string == 'z')
 	    {
-	      if (!i.mask)
+	      if (!i.mask.reg)
 		{
-		  mask_op.mask = NULL;
-		  mask_op.zeroing = 1;
-		  mask_op.operand = this_operand;
-		  i.mask = &mask_op;
+		  i.mask.reg = reg_k0;
+		  i.mask.zeroing = 1;
+		  i.mask.operand = this_operand;
 		}
 	      else
 		{
-		  if (i.mask->zeroing)
+		  if (i.mask.zeroing)
 		    {
 		    duplicated_vec_op:
 		      as_bad (_("duplicated `%s'"), saved);
 		      return NULL;
 		    }
 
-		  i.mask->zeroing = 1;
+		  i.mask.zeroing = 1;
 
 		  /* Only "{%k}" is allowed here.  No need to check mask
 		     register explicitly.  */
-		  if (i.mask->operand != (unsigned int) this_operand)
+		  if (i.mask.operand != (unsigned int) this_operand)
 		    {
 		      as_bad (_("invalid zeroing-masking `%s'"),
 			      saved);
@@ -10512,7 +10512,7 @@ check_VecOperations (char *op_string, ch
       return NULL;
     }
 
-  if (i.mask && i.mask->zeroing && !i.mask->mask)
+  if (i.mask.reg && i.mask.zeroing && !i.mask.reg->reg_num)
     {
       as_bad (_("zeroing-masking only allowed with write mask"));
       return NULL;


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

* [PATCH 3/7] x86: integrate broadcast_op into struct _i386_insn
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
  2021-03-26 13:46 ` [PATCH 1/7] x86: make swap_2_operands() have unsigned parameters Jan Beulich
  2021-03-26 13:47 ` [PATCH 2/7] x86: integrate mask_op into struct _i386_insn Jan Beulich
@ 2021-03-26 13:48 ` Jan Beulich
  2021-03-26 13:48 ` [PATCH 4/7] x86: integrate rc_op " Jan Beulich
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:48 UTC (permalink / raw)
  To: Binutils

There's no need for the extra level of indirection and the extra storage
needed for the pointer, pointing from one piece of static data to
another. Key checking of broadcast being in effect off of the type field
of the structure instead.

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

	* config/tc-i386.c (broadcast_op): Delete.
	(struct Broadcast_Operation): Move ...
	(struct _i386_insn): ... here. Change field "broadcast".
	(match_mem_size): Adjust check for broadcast.
	(optimize_encoding): Likewise.
	(process_suffix): Likewise.
	(build_evex_prefix): Adjust broadcast processing.
	(swap_2_operands): Likewise.
	(check_VecOperations): Likewise.
	(match_template): Likewise.
	(check_VecOperands): Likewise.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -232,22 +232,6 @@ struct RC_Operation
 
 static struct RC_Operation rc_op;
 
-/* The struct describes broadcasting, applied to OPERAND.  FACTOR is
-   broadcast factor.  */
-struct Broadcast_Operation
-{
-  /* Type of broadcast: {1to2}, {1to4}, {1to8}, or {1to16}.  */
-  int type;
-
-  /* Index of broadcasted operand.  */
-  unsigned int operand;
-
-  /* Number of bytes to broadcast.  */
-  int bytes;
-};
-
-static struct Broadcast_Operation broadcast_op;
-
 /* VEX prefix.  */
 typedef struct
 {
@@ -398,8 +382,21 @@ struct _i386_insn
     /* Rounding control and SAE attributes.  */
     struct RC_Operation *rounding;
 
-    /* Broadcasting attributes.  */
-    struct Broadcast_Operation *broadcast;
+    /* Broadcasting attributes.
+
+       The struct describes broadcasting, applied to OPERAND.  TYPE is
+       expresses the broadcast factor.  */
+    struct Broadcast_Operation
+    {
+      /* Type of broadcast: {1to2}, {1to4}, {1to8}, or {1to16}.  */
+      unsigned int type;
+
+      /* Index of broadcasted operand.  */
+      unsigned int operand;
+
+      /* Number of bytes to broadcast.  */
+      unsigned int bytes;
+    } broadcast;
 
     /* Compressed disp8*N attribute.  */
     unsigned int memshift;
@@ -2211,7 +2208,7 @@ match_mem_size (const insn_template *t,
 {
   return (match_operand_size (t, wanted, given)
 	  && !((i.types[given].bitfield.unspecified
-		&& !i.broadcast
+		&& !i.broadcast.type
 		&& !t->operand_types[wanted].bitfield.unspecified)
 	       || (i.types[given].bitfield.fword
 		   && !t->operand_types[wanted].bitfield.fword)
@@ -3911,9 +3908,9 @@ build_evex_prefix (void)
 		    i.tm.opcode_modifier.evex = EVEX128;
 		    break;
 		  }
-		else if (i.broadcast && op == i.broadcast->operand)
+		else if (i.broadcast.type && op == i.broadcast.operand)
 		  {
-		    switch (i.broadcast->bytes)
+		    switch (i.broadcast.bytes)
 		      {
 			case 64:
 			  i.tm.opcode_modifier.evex = EVEX512;
@@ -3955,7 +3952,7 @@ build_evex_prefix (void)
 	}
       i.vex.bytes[3] |= vec_length;
       /* Encode the broadcast bit.  */
-      if (i.broadcast)
+      if (i.broadcast.type)
 	i.vex.bytes[3] |= 0x10;
     }
   else
@@ -4255,7 +4252,7 @@ optimize_encoding (void)
 	   && !i.types[0].bitfield.zmmword
 	   && !i.types[1].bitfield.zmmword
 	   && !i.mask.reg
-	   && !i.broadcast
+	   && !i.broadcast.type
 	   && is_evex_encoding (&i.tm)
 	   && ((i.tm.base_opcode & ~Opcode_SIMD_IntD) == 0x6f
 	       || (i.tm.base_opcode & ~4) == 0xdb
@@ -5472,12 +5469,12 @@ swap_2_operands (unsigned int xchg1, uns
       else if (i.mask.operand == xchg2)
 	i.mask.operand = xchg1;
     }
-  if (i.broadcast)
+  if (i.broadcast.type)
     {
-      if (i.broadcast->operand == xchg1)
-	i.broadcast->operand = xchg2;
-      else if (i.broadcast->operand == xchg2)
-	i.broadcast->operand = xchg1;
+      if (i.broadcast.operand == xchg1)
+	i.broadcast.operand = xchg2;
+      else if (i.broadcast.operand == xchg2)
+	i.broadcast.operand = xchg1;
     }
   if (i.rounding)
     {
@@ -5892,13 +5889,13 @@ check_VecOperands (const insn_template *
 
   /* Check if broadcast is supported by the instruction and is applied
      to the memory operand.  */
-  if (i.broadcast)
+  if (i.broadcast.type)
     {
       i386_operand_type type, overlap;
 
       /* Check if specified broadcast is supported in this instruction,
 	 and its broadcast bytes match the memory operand.  */
-      op = i.broadcast->operand;
+      op = i.broadcast.operand;
       if (!t->opcode_modifier.broadcast
 	  || !(i.flags[op] & Operand_Mem)
 	  || (!i.types[op].bitfield.unspecified
@@ -5909,10 +5906,10 @@ check_VecOperands (const insn_template *
 	  return 1;
 	}
 
-      i.broadcast->bytes = ((1 << (t->opcode_modifier.broadcast - 1))
-			    * i.broadcast->type);
+      i.broadcast.bytes = ((1 << (t->opcode_modifier.broadcast - 1))
+			   * i.broadcast.type);
       operand_type_set (&type, 0);
-      switch (i.broadcast->bytes)
+      switch (i.broadcast.bytes)
 	{
 	case 2:
 	  type.bitfield.word = 1;
@@ -6066,7 +6063,7 @@ check_VecOperands (const insn_template *
   if (t->opcode_modifier.disp8memshift
       && i.disp_encoding != disp_encoding_32bit)
     {
-      if (i.broadcast)
+      if (i.broadcast.type)
 	i.memshift = t->opcode_modifier.broadcast - 1;
       else if (t->opcode_modifier.disp8memshift != DISP8_SHIFT_VL)
 	i.memshift = t->opcode_modifier.disp8memshift;
@@ -6394,8 +6391,8 @@ match_template (char mnem_suffix)
       if (t->opcode_modifier.checkregsize)
 	{
 	  check_register = (1 << t->operands) - 1;
-	  if (i.broadcast)
-	    check_register &= ~(1 << i.broadcast->operand);
+	  if (i.broadcast.type)
+	    check_register &= ~(1 << i.broadcast.operand);
 	}
       else
 	check_register = 0;
@@ -6961,7 +6958,7 @@ process_suffix (void)
       /* For [XYZ]MMWORD operands inspect operand sizes.  While generally
 	 also suitable for AT&T syntax mode, it was requested that this be
 	 restricted to just Intel syntax.  */
-      if (intel_syntax && is_any_vex_encoding (&i.tm) && !i.broadcast)
+      if (intel_syntax && is_any_vex_encoding (&i.tm) && !i.broadcast.type)
 	{
 	  unsigned int op;
 
@@ -10391,9 +10388,9 @@ check_VecOperations (char *op_string, ch
 	  /* Check broadcasts.  */
 	  if (strncmp (op_string, "1to", 3) == 0)
 	    {
-	      int bcst_type;
+	      unsigned int bcst_type;
 
-	      if (i.broadcast)
+	      if (i.broadcast.type)
 		goto duplicated_vec_op;
 
 	      op_string += 3;
@@ -10416,10 +10413,8 @@ check_VecOperations (char *op_string, ch
 		}
 	      op_string++;
 
-	      broadcast_op.type = bcst_type;
-	      broadcast_op.operand = this_operand;
-	      broadcast_op.bytes = 0;
-	      i.broadcast = &broadcast_op;
+	      i.broadcast.type = bcst_type;
+	      i.broadcast.operand = this_operand;
 	    }
 	  /* Check masking operation.  */
 	  else if ((mask = parse_register (op_string, &end_op)) != NULL)


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

* [PATCH 4/7] x86: integrate rc_op into struct _i386_insn
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
                   ` (2 preceding siblings ...)
  2021-03-26 13:48 ` [PATCH 3/7] x86: integrate broadcast_op " Jan Beulich
@ 2021-03-26 13:48 ` Jan Beulich
  2021-03-26 13:49 ` [PATCH 5/7] x86: adjust st(<N>) parsing Jan Beulich
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:48 UTC (permalink / raw)
  To: Binutils

There's no need for the extra level of indirection and the extra storage
needed for the pointer, pointing from one piece of static data to
another. Key checking of rounding being in effect off of the type field
of the structure instead.

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

	* config/tc-i386.c (rc_op): Delete.
	(struct Rounding_Operation): Move ...
	(struct _i386_insn): ... here. Change field "rounding".
	(build_evex_prefix): Adjust rounding processing.
	(swap_2_operands): Likewise.
	(check_VecOperands): Likewise.
	(RC_SAE_immediate): Likewise.
	(optimize_encoding): Adjust check for rounding.
	(build_modrm_byte): Likewise.
	(output_imm): Likewise.
	(md_assemble): Initialize rounding type.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -216,22 +216,6 @@ static const reg_entry bad_reg = { "<bad
 
 static const reg_entry *reg_k0;
 
-/* This struct describes rounding control and SAE in the instruction.  */
-struct RC_Operation
-{
-  enum rc_type
-    {
-      rne = 0,
-      rd,
-      ru,
-      rz,
-      saeonly
-    } type;
-  unsigned int operand;
-};
-
-static struct RC_Operation rc_op;
-
 /* VEX prefix.  */
 typedef struct
 {
@@ -380,7 +364,20 @@ struct _i386_insn
     } mask;
 
     /* Rounding control and SAE attributes.  */
-    struct RC_Operation *rounding;
+    struct RC_Operation
+    {
+      enum rc_type
+	{
+	  rc_none = -1,
+	  rne,
+	  rd,
+	  ru,
+	  rz,
+	  saeonly
+	} type;
+
+      unsigned int operand;
+    } rounding;
 
     /* Broadcasting attributes.
 
@@ -3876,7 +3873,7 @@ build_evex_prefix (void)
     i.vex.bytes[3] |= 0x80;
 
   /* Don't always set the broadcast bit if there is no RC.  */
-  if (!i.rounding)
+  if (i.rounding.type == rc_none)
     {
       /* Encode the vector length.  */
       unsigned int vec_length;
@@ -3955,13 +3952,10 @@ build_evex_prefix (void)
       if (i.broadcast.type)
 	i.vex.bytes[3] |= 0x10;
     }
+  else if (i.rounding.type != saeonly)
+    i.vex.bytes[3] |= 0x10 | (i.rounding.type << 5);
   else
-    {
-      if (i.rounding->type != saeonly)
-	i.vex.bytes[3] |= 0x10 | (i.rounding->type << 5);
-      else
-	i.vex.bytes[3] |= 0x10 | (evexrcig << 5);
-    }
+    i.vex.bytes[3] |= 0x10 | (evexrcig << 5);
 
   if (i.mask.reg)
     i.vex.bytes[3] |= i.mask.reg->reg_num;
@@ -4166,7 +4160,7 @@ optimize_encoding (void)
 	   && !i.types[2].bitfield.xmmword
 	   && (i.tm.opcode_modifier.vex
 	       || ((!i.mask.reg || i.mask.zeroing)
-		   && !i.rounding
+		   && i.rounding.type == rc_none
 		   && is_evex_encoding (&i.tm)
 		   && (i.vec_encoding != vex_encoding_evex
 		       || cpu_arch_isa_flags.bitfield.cpuavx512vl
@@ -4666,6 +4660,7 @@ md_assemble (char *line)
 
   /* Initialize globals.  */
   memset (&i, '\0', sizeof (i));
+  i.rounding.type = rc_none;
   for (j = 0; j < MAX_OPERANDS; j++)
     i.reloc[j] = NO_RELOC;
   memset (disp_expressions, '\0', sizeof (disp_expressions));
@@ -5476,12 +5471,12 @@ swap_2_operands (unsigned int xchg1, uns
       else if (i.broadcast.operand == xchg2)
 	i.broadcast.operand = xchg1;
     }
-  if (i.rounding)
+  if (i.rounding.type != rc_none)
     {
-      if (i.rounding->operand == xchg1)
-	i.rounding->operand = xchg2;
-      else if (i.rounding->operand == xchg2)
-	i.rounding->operand = xchg1;
+      if (i.rounding.operand == xchg1)
+	i.rounding.operand = xchg2;
+      else if (i.rounding.operand == xchg2)
+	i.rounding.operand = xchg1;
     }
 }
 
@@ -6026,10 +6021,10 @@ check_VecOperands (const insn_template *
     }
 
   /* Check RC/SAE.  */
-  if (i.rounding)
+  if (i.rounding.type != rc_none)
     {
       if (!t->opcode_modifier.sae
-	  || (i.rounding->type != saeonly && !t->opcode_modifier.staticrounding))
+	  || (i.rounding.type != saeonly && !t->opcode_modifier.staticrounding))
 	{
 	  i.error = unsupported_rc_sae;
 	  return 1;
@@ -6038,7 +6033,7 @@ check_VecOperands (const insn_template *
 	 them is rounding, the rounding operand should be the last
 	 immediate operand.  */
       if (i.imm_operands > 1
-	  && i.rounding->operand != i.imm_operands - 1)
+	  && i.rounding.operand != i.imm_operands - 1)
 	{
 	  i.error = rc_sae_operand_not_last_imm;
 	  return 1;
@@ -7925,7 +7920,7 @@ build_modrm_byte (void)
 			  && i.imm_operands == 1
 			  && (i.types[0].bitfield.imm8
 			      || i.types[i.operands - 1].bitfield.imm8
-			      || i.rounding)));
+			      || i.rounding.type != rc_none)));
 	  if (i.imm_operands == 2)
 	    source = 2;
 	  else
@@ -7966,7 +7961,7 @@ build_modrm_byte (void)
 	  /* RC/SAE operand could be between DEST and SRC.  That happens
 	     when one operand is GPR and the other one is XMM/YMM/ZMM
 	     register.  */
-	  if (i.rounding && i.rounding->operand == dest)
+	  if (i.rounding.type != rc_none && i.rounding.operand == dest)
 	    dest++;
 
 	  if (i.tm.opcode_modifier.vexvvvv == VEXXDS)
@@ -9866,7 +9861,7 @@ output_imm (fragS *insn_start_frag, offs
   for (n = 0; n < i.operands; n++)
     {
       /* Skip SAE/RC Imm operand in EVEX.  They are already handled.  */
-      if (i.rounding && n == i.rounding->operand)
+      if (i.rounding.type != rc_none && n == i.rounding.operand)
 	continue;
 
       if (operand_type_check (i.types[n], imm))
@@ -11185,17 +11180,15 @@ RC_SAE_immediate (const char *imm_start)
     {
       if (!strncmp (pstr, RC_NamesTable[j].name, RC_NamesTable[j].len))
 	{
-	  if (!i.rounding)
-	    {
-	      rc_op.type = RC_NamesTable[j].type;
-	      rc_op.operand = this_operand;
-	      i.rounding = &rc_op;
-	    }
-	  else
+	  if (i.rounding.type != rc_none)
 	    {
 	      as_bad (_("duplicated `%s'"), imm_start);
 	      return 0;
 	    }
+
+	  i.rounding.type = RC_NamesTable[j].type;
+	  i.rounding.operand = this_operand;
+
 	  pstr += RC_NamesTable[j].len;
 	  match_found = 1;
 	  break;


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

* [PATCH 5/7] x86: adjust st(<N>) parsing
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
                   ` (3 preceding siblings ...)
  2021-03-26 13:48 ` [PATCH 4/7] x86: integrate rc_op " Jan Beulich
@ 2021-03-26 13:49 ` Jan Beulich
  2021-03-26 13:49 ` [PATCH 6/7] x86: drop REGNAM_{AL,AX,EAX} Jan Beulich
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:49 UTC (permalink / raw)
  To: Binutils

st(1) ... st(7) will never be looked up in the hash table, so there's no
point inserting the entries. It's also not really necessary to do a 2nd
hash lookup after parsing the register number, nor is there a real
reason for having both st and st(0) entries. Plus we can easily do away
with the need for st to be first in the table.

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

	* config/tc-i386.c (reg_st0): New.
	(md_begin): Convert to switch(). Initialize reg_st0. Don't
	insert other st(N).
	(parse_real_register): Adjust st(N) processing.

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

	* i386-opc.h (REGNAM_AL, REGNAM_AX, REGNAM_EAX): Adjust values.
	* i386-reg.tbl (st): Move down.
	(st(0)): Delete. Extend comment.
	* i386-tbl.h: Re-generate.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -214,6 +214,7 @@ static const char *default_arch = DEFAUL
 static const reg_entry bad_reg = { "<bad>", OPERAND_TYPE_NONE, 0, 0,
 				   { Dw2Inval, Dw2Inval } };
 
+static const reg_entry *reg_st0;
 static const reg_entry *reg_k0;
 
 /* VEX prefix.  */
@@ -3087,11 +3088,27 @@ md_begin (void)
 
     for (regtab = i386_regtab; regtab_size--; regtab++)
       {
+	switch (regtab->reg_type.bitfield.class)
+	  {
+	  case Reg:
+	    if (regtab->reg_type.bitfield.tbyte)
+	      {
+		/* There's no point inserting st(<N>) in the hash table, as
+		   parentheses aren't included in register_chars[] anyway.  */
+		if (regtab->reg_type.bitfield.instance != Accum)
+		  continue;
+		reg_st0 = regtab;
+	      }
+	    break;
+
+	  case RegMask:
+	    if (!regtab->reg_num)
+	      reg_k0 = regtab;
+	    break;
+	  }
+
 	if (str_hash_insert (reg_hash, regtab->reg_name, regtab, 0) != NULL)
 	  as_fatal (_("duplicate %s"), regtab->reg_name);
-
-	if (regtab->reg_type.bitfield.class == RegMask && !regtab->reg_num)
-	  reg_k0 = regtab;
       }
   }
 
@@ -12712,7 +12729,7 @@ parse_real_register (char *reg_string, c
   r = (const reg_entry *) str_hash_find (reg_hash, reg_name_given);
 
   /* Handle floating point regs, allowing spaces in the (i) part.  */
-  if (r == i386_regtab /* %st is first entry of table  */)
+  if (r == reg_st0)
     {
       if (!cpu_arch_flags.bitfield.cpu8087
 	  && !cpu_arch_flags.bitfield.cpu287
@@ -12736,8 +12753,7 @@ parse_real_register (char *reg_string, c
 	      if (*s == ')')
 		{
 		  *end_op = s + 1;
-		  r = (const reg_entry *) str_hash_find (reg_hash, "st(0)");
-		  know (r);
+		  know (r[fpr].reg_num == fpr);
 		  return r + fpr;
 		}
 	    }
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -991,9 +991,9 @@ typedef struct
 reg_entry;
 
 /* Entries in i386_regtab.  */
-#define REGNAM_AL 1
-#define REGNAM_AX 25
-#define REGNAM_EAX 41
+#define REGNAM_AL 0
+#define REGNAM_AX 24
+#define REGNAM_EAX 40
 
 extern const reg_entry i386_regtab[];
 extern const unsigned int i386_regtab_size;
--- a/opcodes/i386-reg.tbl
+++ b/opcodes/i386-reg.tbl
@@ -18,8 +18,6 @@
 // Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
 // 02110-1301, USA.
 
-// Make %st first as we test for it.
-st, Class=Reg|Instance=Accum|Tbyte, 0, 0, 11, 33
 // 8 bit regs
 al, Class=Reg|Instance=Accum|Byte, 0, 0, Dw2Inval, Dw2Inval
 cl, Class=Reg|Instance=RegC|Byte, 0, 1, Dw2Inval, Dw2Inval
@@ -300,8 +298,8 @@ eip, Dword, RegRex64, RegIP, 8, Dw2Inval
 // for addressing.
 riz, Qword|BaseIndex, RegRex64, RegIZ, Dw2Inval, Dw2Inval
 eiz, Dword|BaseIndex, 0, RegIZ, Dw2Inval, Dw2Inval
-// fp regs.
-st(0), Class=Reg|Instance=Accum|Tbyte, 0, 0, 11, 33
+// fp regs. No need for an explicit st(0) here.
+st, Class=Reg|Instance=Accum|Tbyte, 0, 0, 11, 33
 st(1), Class=Reg|Tbyte, 0, 1, 12, 34
 st(2), Class=Reg|Tbyte, 0, 2, 13, 35
 st(3), Class=Reg|Tbyte, 0, 3, 14, 36


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

* [PATCH 6/7] x86: drop REGNAM_{AL,AX,EAX}
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
                   ` (4 preceding siblings ...)
  2021-03-26 13:49 ` [PATCH 5/7] x86: adjust st(<N>) parsing Jan Beulich
@ 2021-03-26 13:49 ` Jan Beulich
  2021-03-26 13:50 ` [PATCH 7/7] x86: drop seg_entry Jan Beulich
  2021-03-26 21:18 ` [PATCH 0/7] x86: assorted simplifications / tidying H.J. Lu
  7 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:49 UTC (permalink / raw)
  To: Binutils

The former two are unused anyway. And having such constants isn't very
helpful either, when they live in a place where updating the register
table wouldn't even allow noticing the need to adjust these constants.

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

	* config/tc-i386.c (reg_eax): New.
	(md_begin): Initialize reg_eax.
	* config/tc-i386-intel.c (i386_intel_simplify_register): Use
	reg_eax.
	(i386_intel_simplify): Likewise.

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

	* i386-opc.h (REGNAM_AL, REGNAM_AX, REGNAM_EAX): Delete.

--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -335,7 +335,7 @@ i386_intel_simplify_register (expression
   else
     {
       /* esp is invalid as index */
-      intel_state.index = i386_regtab + REGNAM_EAX + ESP_REG_NUM;
+      intel_state.index = reg_eax + ESP_REG_NUM;
     }
   return 2;
 }
@@ -500,7 +500,7 @@ static int i386_intel_simplify (expressi
 		break;
 	      default:
 		/* esp is invalid as index */
-		intel_state.index = i386_regtab + REGNAM_EAX + ESP_REG_NUM;
+		intel_state.index = reg_eax + ESP_REG_NUM;
 		break;
 	      }
 
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -214,6 +214,7 @@ static const char *default_arch = DEFAUL
 static const reg_entry bad_reg = { "<bad>", OPERAND_TYPE_NONE, 0, 0,
 				   { Dw2Inval, Dw2Inval } };
 
+static const reg_entry *reg_eax;
 static const reg_entry *reg_st0;
 static const reg_entry *reg_k0;
 
@@ -3091,7 +3092,12 @@ md_begin (void)
 	switch (regtab->reg_type.bitfield.class)
 	  {
 	  case Reg:
-	    if (regtab->reg_type.bitfield.tbyte)
+	    if (regtab->reg_type.bitfield.dword)
+	      {
+		if (regtab->reg_type.bitfield.instance == Accum)
+		  reg_eax = regtab;
+	      }
+	    else if (regtab->reg_type.bitfield.tbyte)
 	      {
 		/* There's no point inserting st(<N>) in the hash table, as
 		   parentheses aren't included in register_chars[] anyway.  */
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -990,11 +990,6 @@ typedef struct
 }
 reg_entry;
 
-/* Entries in i386_regtab.  */
-#define REGNAM_AL 0
-#define REGNAM_AX 24
-#define REGNAM_EAX 40
-
 extern const reg_entry i386_regtab[];
 extern const unsigned int i386_regtab_size;
 


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

* [PATCH 7/7] x86: drop seg_entry
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
                   ` (5 preceding siblings ...)
  2021-03-26 13:49 ` [PATCH 6/7] x86: drop REGNAM_{AL,AX,EAX} Jan Beulich
@ 2021-03-26 13:50 ` Jan Beulich
  2021-03-26 21:18 ` [PATCH 0/7] x86: assorted simplifications / tidying H.J. Lu
  7 siblings, 0 replies; 9+ messages in thread
From: Jan Beulich @ 2021-03-26 13:50 UTC (permalink / raw)
  To: Binutils

Use struct reg_entry instead for most purposes, with a separate array
holding just the respective opcode prefix bytes.

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

	* config/tc-i386.c (build_modrm_byte): Change return type.
	Change type of "default_seg". Use NULL. Adjust setting of
	"default_seg".
	(reg_ds, reg_es, reg_ss): New.
	(struct _i386_insn): Change type of seg[].
	(md_begin): Initialize reg_ds, reg_es, and reg_ss.
	(swap_operands): Change type of "temp_seg".
	(check_string): Adjust %es check.
	(process_operands): Change type of "default_seg". Use NULL.
	Adjust segment override processing..
	(i386_att_operand): Adjust segment override handling.
	* config/tc-i386-intel.c (i386_intel_operand): Likewise.

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

	* i386-opc.c (cs, ds, ss, es, fs, gs): Delete.
	(i386_seg_prefixes): New.
	* i386-opc.h (cs, ds, ss, es, fs, gs): Delete.
	(i386_seg_prefixes): Declare.

--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -1028,16 +1028,10 @@ i386_intel_operand (char *operand_string
 	      as_warn (_("redundant segment overrides"));
 	      break;
 	    }
-	  switch (i386_regtab[expP->X_add_number].reg_num)
-	    {
-	    case 0: i.seg[i.mem_operands] = &es; break;
-	    case 1: i.seg[i.mem_operands] = &cs; break;
-	    case 2: i.seg[i.mem_operands] = &ss; break;
-	    case 3: i.seg[i.mem_operands] = &ds; break;
-	    case 4: i.seg[i.mem_operands] = &fs; break;
-	    case 5: i.seg[i.mem_operands] = &gs; break;
-	    case RegFlat: i.seg[i.mem_operands] = NULL; break;
-	    }
+	  if (i386_regtab[expP->X_add_number].reg_num == RegFlat)
+	    i.seg[i.mem_operands] = NULL;
+	  else
+	    i.seg[i.mem_operands] = &i386_regtab[expP->X_add_number];
 	}
 
       if (!i386_index_check (operand_string))
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -190,7 +190,7 @@ static int check_qword_reg (void);
 static int check_word_reg (void);
 static int finalize_imm (void);
 static int process_operands (void);
-static const seg_entry *build_modrm_byte (void);
+static const reg_entry *build_modrm_byte (void);
 static void output_insn (void);
 static void output_imm (fragS *, offsetT);
 static void output_disp (fragS *, offsetT);
@@ -215,6 +215,9 @@ static const reg_entry bad_reg = { "<bad
 				   { Dw2Inval, Dw2Inval } };
 
 static const reg_entry *reg_eax;
+static const reg_entry *reg_ds;
+static const reg_entry *reg_es;
+static const reg_entry *reg_ss;
 static const reg_entry *reg_st0;
 static const reg_entry *reg_k0;
 
@@ -308,7 +311,7 @@ struct _i386_insn
 
     /* SEG gives the seg_entries of this insn.  They are zero unless
        explicit segment overrides are given.  */
-    const seg_entry *seg[2];
+    const reg_entry *seg[2];
 
     /* Copied first memory operand string, for re-checking.  */
     char *memop1_string;
@@ -3107,6 +3110,15 @@ md_begin (void)
 	      }
 	    break;
 
+	  case SReg:
+	    switch (regtab->reg_num)
+	      {
+	      case 0: reg_es = regtab; break;
+	      case 2: reg_ss = regtab; break;
+	      case 3: reg_ds = regtab; break;
+	      }
+	    break;
+
 	  case RegMask:
 	    if (!regtab->reg_num)
 	      reg_k0 = regtab;
@@ -5522,7 +5534,7 @@ swap_operands (void)
 
   if (i.mem_operands == 2)
     {
-      const seg_entry *temp_seg;
+      const reg_entry *temp_seg;
       temp_seg = i.seg[0];
       i.seg[0] = i.seg[1];
       i.seg[1] = temp_seg;
@@ -6752,7 +6764,7 @@ check_string (void)
   unsigned int es_op = i.tm.opcode_modifier.isstring - IS_STRING_ES_OP0;
   unsigned int op = i.tm.operand_types[0].bitfield.baseindex ? es_op : 0;
 
-  if (i.seg[op] != NULL && i.seg[op] != &es)
+  if (i.seg[op] != NULL && i.seg[op] != reg_es)
     {
       as_bad (_("`%s' operand %u must use `%ses' segment"),
 	      i.tm.name,
@@ -7543,7 +7555,7 @@ process_operands (void)
   /* Default segment register this instruction will use for memory
      accesses.  0 means unknown.  This is only for optimizing out
      unnecessary segment overrides.  */
-  const seg_entry *default_seg = 0;
+  const reg_entry *default_seg = NULL;
 
   if (i.tm.opcode_modifier.sse2avx)
     {
@@ -7730,13 +7742,13 @@ process_operands (void)
   else if (i.tm.opcode_modifier.opcodespace == SPACE_BASE
 	   && (i.tm.base_opcode & ~3) == MOV_AX_DISP32)
     {
-      default_seg = &ds;
+      default_seg = reg_ds;
     }
   else if (i.tm.opcode_modifier.isstring)
     {
       /* For the string instructions that allow a segment override
 	 on one of their operands, the default segment is ds.  */
-      default_seg = &ds;
+      default_seg = reg_ds;
     }
   else if (i.short_form)
     {
@@ -7789,9 +7801,9 @@ process_operands (void)
      point, and the specified segment prefix will always be used.  */
   if (i.seg[0]
       && i.seg[0] != default_seg
-      && i.seg[0]->seg_prefix != i.prefix[SEG_PREFIX])
+      && i386_seg_prefixes[i.seg[0]->reg_num] != i.prefix[SEG_PREFIX])
     {
-      if (!add_prefix (i.seg[0]->seg_prefix))
+      if (!add_prefix (i386_seg_prefixes[i.seg[0]->reg_num]))
 	return 0;
     }
   return 1;
@@ -7816,10 +7828,10 @@ static INLINE void set_rex_vrex (const r
     i.vrex |= rex_bit;
 }
 
-static const seg_entry *
+static const reg_entry *
 build_modrm_byte (void)
 {
-  const seg_entry *default_seg = 0;
+  const reg_entry *default_seg = NULL;
   unsigned int source, dest;
   int vex_3_sources;
 
@@ -8103,7 +8115,7 @@ build_modrm_byte (void)
 		}
 	    }
 
-	  default_seg = &ds;
+	  default_seg = reg_ds;
 
 	  if (i.base_reg == 0)
 	    {
@@ -8197,7 +8209,7 @@ build_modrm_byte (void)
 		    i.rm.regmem = i.index_reg->reg_num - 6;
 		  break;
 		case 5: /* (%bp)  */
-		  default_seg = &ss;
+		  default_seg = reg_ss;
 		  if (i.index_reg == 0)
 		    {
 		      i.rm.regmem = 6;
@@ -8258,7 +8270,7 @@ build_modrm_byte (void)
 	      if (!(i.base_reg->reg_flags & RegRex)
 		  && (i.base_reg->reg_num == EBP_REG_NUM
 		   || i.base_reg->reg_num == ESP_REG_NUM))
-		  default_seg = &ss;
+		  default_seg = reg_ss;
 	      if (i.base_reg->reg_num == 5 && i.disp_operands == 0)
 		{
 		  fake_zero_displacement = 1;
@@ -11325,27 +11337,7 @@ i386_att_operand (char *operand_string)
 	++op_string;
       if (*op_string == ':' && r->reg_type.bitfield.class == SReg)
 	{
-	  switch (r->reg_num)
-	    {
-	    case 0:
-	      i.seg[i.mem_operands] = &es;
-	      break;
-	    case 1:
-	      i.seg[i.mem_operands] = &cs;
-	      break;
-	    case 2:
-	      i.seg[i.mem_operands] = &ss;
-	      break;
-	    case 3:
-	      i.seg[i.mem_operands] = &ds;
-	      break;
-	    case 4:
-	      i.seg[i.mem_operands] = &fs;
-	      break;
-	    case 5:
-	      i.seg[i.mem_operands] = &gs;
-	      break;
-	    }
+	  i.seg[i.mem_operands] = r;
 
 	  /* Skip the ':' and whitespace.  */
 	  ++op_string;
--- a/opcodes/i386-opc.c
+++ b/opcodes/i386-opc.c
@@ -23,10 +23,12 @@
 #include "i386-opc.h"
 #include "i386-tbl.h"
 
-/* Segment stuff.  */
-const seg_entry cs = { "cs", 0x2e };
-const seg_entry ds = { "ds", 0x3e };
-const seg_entry ss = { "ss", 0x36 };
-const seg_entry es = { "es", 0x26 };
-const seg_entry fs = { "fs", 0x64 };
-const seg_entry gs = { "gs", 0x65 };
+/* To be indexed by segment register number.  */
+const unsigned char i386_seg_prefixes[] = {
+  ES_PREFIX_OPCODE,
+  CS_PREFIX_OPCODE,
+  SS_PREFIX_OPCODE,
+  DS_PREFIX_OPCODE,
+  FS_PREFIX_OPCODE,
+  GS_PREFIX_OPCODE
+};
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -992,17 +992,4 @@ reg_entry;
 
 extern const reg_entry i386_regtab[];
 extern const unsigned int i386_regtab_size;
-
-typedef struct
-{
-  char *seg_name;
-  unsigned int seg_prefix;
-}
-seg_entry;
-
-extern const seg_entry cs;
-extern const seg_entry ds;
-extern const seg_entry ss;
-extern const seg_entry es;
-extern const seg_entry fs;
-extern const seg_entry gs;
+extern const unsigned char i386_seg_prefixes[6];


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

* Re: [PATCH 0/7] x86: assorted simplifications / tidying
  2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
                   ` (6 preceding siblings ...)
  2021-03-26 13:50 ` [PATCH 7/7] x86: drop seg_entry Jan Beulich
@ 2021-03-26 21:18 ` H.J. Lu
  7 siblings, 0 replies; 9+ messages in thread
From: H.J. Lu @ 2021-03-26 21:18 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Binutils

On Fri, Mar 26, 2021 at 6:44 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> Or so I hope. While generally independent, if in doubt this goes on
> top of "[PATCH 0/6] x86: further opcode table compaction plus fallout"
> sent earlier today.
>
> 1: make swap_2_operands() have unsigned parameters
> 2: integrate mask_op into struct _i386_insn
> 3: integrate broadcast_op into struct _i386_insn
> 4: integrate rc_op into struct _i386_insn
> 5: adjust st(<N>) parsing
> 6: drop REGNAM_{AL,AX,EAX}
> 7: drop seg_entry
>

OK for all.

Thanks.


-- 
H.J.

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

end of thread, other threads:[~2021-03-26 21:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-26 13:44 [PATCH 0/7] x86: assorted simplifications / tidying Jan Beulich
2021-03-26 13:46 ` [PATCH 1/7] x86: make swap_2_operands() have unsigned parameters Jan Beulich
2021-03-26 13:47 ` [PATCH 2/7] x86: integrate mask_op into struct _i386_insn Jan Beulich
2021-03-26 13:48 ` [PATCH 3/7] x86: integrate broadcast_op " Jan Beulich
2021-03-26 13:48 ` [PATCH 4/7] x86: integrate rc_op " Jan Beulich
2021-03-26 13:49 ` [PATCH 5/7] x86: adjust st(<N>) parsing Jan Beulich
2021-03-26 13:49 ` [PATCH 6/7] x86: drop REGNAM_{AL,AX,EAX} Jan Beulich
2021-03-26 13:50 ` [PATCH 7/7] x86: drop seg_entry Jan Beulich
2021-03-26 21:18 ` [PATCH 0/7] x86: assorted simplifications / tidying H.J. Lu

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).