diff options
-rw-r--r-- | gas/ChangeLog | 14 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 110 |
2 files changed, 69 insertions, 55 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 49cbc6b..94c7cc4 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,19 @@ 2021-03-30 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. + +2021-03-30 Jan Beulich <jbeulich@suse.com> + * config/tc-i386.c (swap_2_operands): Switch parameters to unsigned. (struct RC_Operation): Switch operand field to unsigned. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 03bd7b6..d5baf95 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -214,6 +214,8 @@ static const char *default_arch = DEFAULT_ARCH; 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, unsigned int xchg2) 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 *t) /* 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 *t) 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 *t) } 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 *t) 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 *t) 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 *t) } /* 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, char *op_end) 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, char *op_end) /* 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, char *op_end) 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; |