aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2024-05-24 11:50:38 +0200
committerJan Beulich <jbeulich@suse.com>2024-05-24 11:50:38 +0200
commitacd86c81f04405719471410302fe7f8e407d539c (patch)
tree5c8a85a65f8eeb250c7d9e7176dd0aa29d5ec90b /gas/config/tc-i386.c
parentdb7814f3e5f0df1647d62d95f70285d41ec7585f (diff)
downloadbinutils-acd86c81f04405719471410302fe7f8e407d539c.zip
binutils-acd86c81f04405719471410302fe7f8e407d539c.tar.gz
binutils-acd86c81f04405719471410302fe7f8e407d539c.tar.bz2
x86: correct VCVT{,U}SI2SD
Properly reject inappropriate suffixes (No_lSuf / No_qSuf mistakenly omitted by cf665fee1d6c ["x86: re-work AVX512 embedded rounding / SAE"]), to avoid emitting bad or arbitrarily guessed instructions. Interestingly check_{long,qword}_suffix() don't help here, which perhaps is another indication that the way they work right now isn't quite appropriate. Sadly correcting just the templates breaks operand ambiguity detection, since so far that worked from a single template permitting more than one suffix. Here we have ambiguity though which can now be noticed only when taking all (matching) templates together. Therefore we need to determine further matching templates (see code comments for constraints), to then accumulate permitted suffixes across all of them.
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index a84e999..1e580b9 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -172,7 +172,7 @@ static void optimize_imm (void);
static bool optimize_disp (const insn_template *t);
static const insn_template *match_template (char);
static int check_string (void);
-static int process_suffix (void);
+static int process_suffix (const insn_template *);
static int check_byte_reg (void);
static int check_long_reg (void);
static int check_qword_reg (void);
@@ -6949,7 +6949,7 @@ md_assemble (char *line)
if (use_unaligned_vector_move)
encode_with_unaligned_vector_move ();
- if (!process_suffix ())
+ if (!process_suffix (t))
return;
/* Check if IP-relative addressing requirements can be satisfied. */
@@ -8361,12 +8361,16 @@ check_VecOperands (const insn_template *t)
if (operand_type_check (i.types[op], disp)
&& i.op[op].disps->X_op == O_constant)
{
+ /* Make sure to leave i.types[op].bitfield.disp8 alone upon
+ secondary invocations of match_template(). */
if (fits_in_disp8 (i.op[op].disps->X_add_number))
{
- i.types[op].bitfield.disp8 = 1;
+ if (!i.tm.mnem_off)
+ i.types[op].bitfield.disp8 = 1;
return 0;
}
- i.types[op].bitfield.disp8 = 0;
+ if (!i.tm.mnem_off)
+ i.types[op].bitfield.disp8 = 0;
}
}
@@ -9184,6 +9188,11 @@ match_template (char mnem_suffix)
return NULL;
}
+ /* Don't emit diagnostics or install the template when one was already
+ installed, i.e. when called from process_suffix(). */
+ if (i.tm.mnem_off)
+ return t;
+
if (!quiet_warnings)
{
if (!intel_syntax
@@ -9290,7 +9299,7 @@ check_string (void)
}
static int
-process_suffix (void)
+process_suffix (const insn_template *t)
{
bool is_movx = false;
@@ -9465,6 +9474,39 @@ process_suffix (void)
if (flag_code == CODE_64BIT && !i.tm.opcode_modifier.no_qsuf)
suffixes |= 1 << 5;
+ /* Operand size may be ambiguous only across multiple templates. Avoid
+ the extra effort though if we already know that multiple suffixes /
+ operand sizes are allowed. Also limit this to non-SIMD operand sizes
+ (i.e. ones expressable via suffixes) for now.
+ There's one special case though that needs excluding: Insns taking
+ Disp<N> operands also match templates permitting BaseIndex. JMP in
+ particular would thus wrongly trigger the check further down. Cover
+ JUMP_DWORD insns here as well, just in case. */
+ if (i.tm.opcode_modifier.jump != JUMP
+ && i.tm.opcode_modifier.jump != JUMP_DWORD)
+ while (!(suffixes & (suffixes - 1)))
+ {
+ /* Sadly check_VecOperands(), running ahead of install_template(),
+ may update i.memshift. Save and restore the value here. */
+ unsigned int memshift = i.memshift;
+
+ current_templates.start = t + 1;
+ t = match_template (0);
+ i.memshift = memshift;
+ if (t == NULL)
+ break;
+ if (!t->opcode_modifier.no_bsuf)
+ suffixes |= 1 << 0;
+ if (!t->opcode_modifier.no_wsuf)
+ suffixes |= 1 << 1;
+ if (!t->opcode_modifier.no_lsuf)
+ suffixes |= 1 << 2;
+ if (!t->opcode_modifier.no_ssuf)
+ suffixes |= 1 << 4;
+ if (flag_code == CODE_64BIT && !t->opcode_modifier.no_qsuf)
+ suffixes |= 1 << 5;
+ }
+
/* 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. */