x86: integrate broadcast_op into struct _i386_insn

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.
This commit is contained in:
Jan Beulich
2021-03-30 14:06:09 +02:00
parent 6225c532b4
commit 5273a3cd48
2 changed files with 52 additions and 43 deletions

View File

@ -1,3 +1,17 @@
2021-03-30 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.
2021-03-30 Jan Beulich <jbeulich@suse.com> 2021-03-30 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (reg_k0): New. * config/tc-i386.c (reg_k0): New.

View File

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