aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2022-05-27 08:48:58 +0200
committerJan Beulich <jbeulich@suse.com>2022-05-27 08:48:58 +0200
commit7063667edb6a663163c2adba754b5abbbe67dc46 (patch)
tree915694f647592bf8fe74d4b68b781efaf88f30dd /gas/config
parentcf665fee1d6c9efa2e59af496cd132393732306d (diff)
downloadgdb-7063667edb6a663163c2adba754b5abbbe67dc46.zip
gdb-7063667edb6a663163c2adba754b5abbbe67dc46.tar.gz
gdb-7063667edb6a663163c2adba754b5abbbe67dc46.tar.bz2
x86/Intel: allow MASM representation of embedded rounding / SAE
MASM doesn't support the separate operand form; the modifier belongs after the instruction instead. Accept this form alongside the original (now legacy) one. Short of having access to a MASM version to actually check in how far "after the instruction" is a precise statement in their documentation, allow both that and the SDM mandated form where the modifier is on the last register operand (with a possible immediate operand following). Sadly the split out function, at least for the time being, needs to cast away constness at some point, as the two callers disagree in this regard. Adjust some, but not all of the testcases.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-i386-intel.c5
-rw-r--r--gas/config/tc-i386.c55
2 files changed, 38 insertions, 22 deletions
diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c
index 80aeb5d..0991f4f 100644
--- a/gas/config/tc-i386-intel.c
+++ b/gas/config/tc-i386-intel.c
@@ -600,6 +600,7 @@ i386_intel_operand (char *operand_string, int got_a_float)
segT exp_seg;
expressionS exp, *expP;
char suffix = 0;
+ bool rc_sae_modifier = i.rounding.type != rc_none && i.rounding.modifier;
int ret;
/* Handle vector immediates. */
@@ -898,7 +899,9 @@ i386_intel_operand (char *operand_string, int got_a_float)
i.types[this_operand].bitfield.unspecified = 0;
++i.reg_operands;
- if (i.rounding.type != rc_none && temp.bitfield.class != Reg)
+ if ((i.rounding.type != rc_none && !i.rounding.modifier
+ && temp.bitfield.class != Reg)
+ || rc_sae_modifier)
{
unsigned int j;
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 59fe32a..a3c6443 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -371,6 +371,9 @@ struct _i386_insn
rz,
saeonly
} type;
+ /* In Intel syntax the operand modifier form is supposed to be used, but
+ we continue to accept the immediate forms as well. */
+ bool modifier;
} rounding;
/* Broadcasting attributes.
@@ -10624,6 +10627,32 @@ pe_directive_secidx (int dummy ATTRIBUTE_UNUSED)
}
#endif
+/* Handle Rounding Control / SAE specifiers. */
+
+static char *
+RC_SAE_specifier (const char *pstr)
+{
+ unsigned int j;
+
+ for (j = 0; j < ARRAY_SIZE (RC_NamesTable); j++)
+ {
+ if (!strncmp (pstr, RC_NamesTable[j].name, RC_NamesTable[j].len))
+ {
+ if (i.rounding.type != rc_none)
+ {
+ as_bad (_("duplicated `{%s}'"), RC_NamesTable[j].name);
+ return NULL;
+ }
+
+ i.rounding.type = RC_NamesTable[j].type;
+
+ return (char *)(pstr + RC_NamesTable[j].len);
+ }
+ }
+
+ return NULL;
+}
+
/* Handle Vector operations. */
static char *
@@ -10745,6 +10774,9 @@ check_VecOperations (char *op_string)
op_string++;
}
+ else if (intel_syntax
+ && (op_string = RC_SAE_specifier (op_string)) != NULL)
+ i.rounding.modifier = true;
else
goto unknown_vec_op;
@@ -11406,32 +11438,13 @@ i386_index_check (const char *operand_string)
static int
RC_SAE_immediate (const char *imm_start)
{
- unsigned int match_found, j;
const char *pstr = imm_start;
if (*pstr != '{')
return 0;
- pstr++;
- match_found = 0;
- for (j = 0; j < ARRAY_SIZE (RC_NamesTable); j++)
- {
- if (!strncmp (pstr, RC_NamesTable[j].name, RC_NamesTable[j].len))
- {
- if (i.rounding.type != rc_none)
- {
- as_bad (_("duplicated `%s'"), imm_start);
- return 0;
- }
-
- i.rounding.type = RC_NamesTable[j].type;
-
- pstr += RC_NamesTable[j].len;
- match_found = 1;
- break;
- }
- }
- if (!match_found)
+ pstr = RC_SAE_specifier (pstr + 1);
+ if (pstr == NULL)
return 0;
if (*pstr++ != '}')