aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-i386.c173
1 files changed, 81 insertions, 92 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index c6a1521..bb02347 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1655,24 +1655,36 @@ operand_type_equal (const union i386_operand_type *x,
}
static INLINE bool
-is_cpu (const insn_template *t, enum i386_cpu cpu)
+_is_cpu (const i386_cpu_attr *a, enum i386_cpu cpu)
{
switch (cpu)
{
- case Cpu287: return t->cpu.bitfield.cpu287;
- case Cpu387: return t->cpu.bitfield.cpu387;
- case Cpu3dnow: return t->cpu.bitfield.cpu3dnow;
- case Cpu3dnowA: return t->cpu.bitfield.cpu3dnowa;
- case CpuAVX: return t->cpu.bitfield.cpuavx;
- case CpuHLE: return t->cpu.bitfield.cpuhle;
- case CpuAVX512F: return t->cpu.bitfield.cpuavx512f;
- case CpuAVX512VL: return t->cpu.bitfield.cpuavx512vl;
- case Cpu64: return t->cpu.bitfield.cpu64;
- case CpuNo64: return t->cpu.bitfield.cpuno64;
+ case Cpu287: return a->bitfield.cpu287;
+ case Cpu387: return a->bitfield.cpu387;
+ case Cpu3dnow: return a->bitfield.cpu3dnow;
+ case Cpu3dnowA: return a->bitfield.cpu3dnowa;
+ case CpuAVX: return a->bitfield.cpuavx;
+ case CpuHLE: return a->bitfield.cpuhle;
+ case CpuAVX512F: return a->bitfield.cpuavx512f;
+ case CpuAVX512VL: return a->bitfield.cpuavx512vl;
+ case Cpu64: return a->bitfield.cpu64;
+ case CpuNo64: return a->bitfield.cpuno64;
default:
gas_assert (cpu < CpuAttrEnums);
}
- return t->cpu.bitfield.isa == cpu + 1u;
+ return a->bitfield.isa == cpu + 1u;
+}
+
+static INLINE bool
+is_cpu (const insn_template *t, enum i386_cpu cpu)
+{
+ return _is_cpu(&t->cpu, cpu);
+}
+
+static INLINE bool
+maybe_cpu (const insn_template *t, enum i386_cpu cpu)
+{
+ return _is_cpu(&t->cpu_any, cpu);
}
static i386_cpu_flags cpu_flags_from_attr (i386_cpu_attr a)
@@ -1863,96 +1875,68 @@ static INLINE bool need_evex_encoding (void)
static int
cpu_flags_match (const insn_template *t)
{
- i386_cpu_flags x = cpu_flags_from_attr (t->cpu);
+ i386_cpu_flags cpu, active, all = cpu_flags_from_attr (t->cpu);
+ i386_cpu_flags any = cpu_flags_from_attr (t->cpu_any);
int match = cpu_flags_check_cpu64 (t) ? CPU_FLAGS_64BIT_MATCH : 0;
- x.bitfield.cpu64 = 0;
- x.bitfield.cpuno64 = 0;
+ all.bitfield.cpu64 = 0;
+ all.bitfield.cpuno64 = 0;
+ gas_assert (!any.bitfield.cpu64);
+ gas_assert (!any.bitfield.cpuno64);
- if (cpu_flags_all_zero (&x))
+ if (cpu_flags_all_zero (&all) && cpu_flags_all_zero (&any))
{
/* This instruction is available on all archs. */
- match |= CPU_FLAGS_ARCH_MATCH;
+ return match | CPU_FLAGS_ARCH_MATCH;
}
- else
- {
- /* This instruction is available only on some archs. */
- i386_cpu_flags active, cpu;
- if (flag_code != CODE_64BIT)
- active = cpu_flags_and_not (cpu_arch_flags, cpu_64_flags);
- else
- active = cpu_arch_flags;
+ /* This instruction is available only on some archs. */
- /* Dual VEX/EVEX templates may need stripping of one of the flags. */
- if (t->opcode_modifier.vex && t->opcode_modifier.evex)
+ /* Dual VEX/EVEX templates may need stripping of one of the flags. */
+ if (t->opcode_modifier.vex && t->opcode_modifier.evex)
+ {
+ /* Dual AVX/AVX512 templates need to retain AVX512* only if we already
+ know that EVEX encoding will be needed. */
+ if ((any.bitfield.cpuavx || any.bitfield.cpuavx2 || any.bitfield.cpufma)
+ && (any.bitfield.cpuavx512f || any.bitfield.cpuavx512vl))
{
- /* Dual AVX/AVX512F templates need to retain AVX512F only if we already
- know that EVEX encoding will be needed. */
- if ((x.bitfield.cpuavx || x.bitfield.cpuavx2)
- && x.bitfield.cpuavx512f)
+ if (need_evex_encoding ())
{
- if (need_evex_encoding ())
- {
- x.bitfield.cpuavx = 0;
- x.bitfield.cpuavx2 = 0;
- }
- /* need_evex_encoding() isn't reliable before operands were
- parsed. */
- else if (i.operands)
- {
- x.bitfield.cpuavx512f = 0;
- x.bitfield.cpuavx512vl = 0;
- if (x.bitfield.cpufma && !active.bitfield.cpufma)
- x.bitfield.cpuavx = 0;
- }
+ any.bitfield.cpuavx = 0;
+ any.bitfield.cpuavx2 = 0;
+ any.bitfield.cpufma = 0;
+ }
+ /* need_evex_encoding() isn't reliable before operands were
+ parsed. */
+ else if (i.operands)
+ {
+ any.bitfield.cpuavx512f = 0;
+ any.bitfield.cpuavx512vl = 0;
}
}
+ }
- /* AVX512VL is no standalone feature - match it and then strip it. */
- if (x.bitfield.cpuavx512vl && !active.bitfield.cpuavx512vl)
- return match;
- x.bitfield.cpuavx512vl = 0;
-
+ if (flag_code != CODE_64BIT)
+ active = cpu_flags_and_not (cpu_arch_flags, cpu_64_flags);
+ else
+ active = cpu_arch_flags;
+ cpu = cpu_flags_and (all, active);
+ if (cpu_flags_equal (&cpu, &all))
+ {
/* AVX and AVX2 present at the same time express an operand size
dependency - strip AVX2 for the purposes here. The operand size
dependent check occurs in check_vecOperands(). */
- if (x.bitfield.cpuavx && x.bitfield.cpuavx2)
- x.bitfield.cpuavx2 = 0;
-
- cpu = cpu_flags_and (x, active);
- if (!cpu_flags_all_zero (&cpu))
- {
- if (t->cpu.bitfield.cpuavx && t->cpu.bitfield.cpuavx512f)
- {
- if ((need_evex_encoding ()
- ? cpu.bitfield.cpuavx512f
- : cpu.bitfield.cpuavx)
- && (!x.bitfield.cpufma || cpu.bitfield.cpufma
- || active.bitfield.cpuavx512f)
- && (!x.bitfield.cpugfni || cpu.bitfield.cpugfni)
- && (!x.bitfield.cpuvaes || cpu.bitfield.cpuvaes)
- && (!x.bitfield.cpuvpclmulqdq || cpu.bitfield.cpuvpclmulqdq))
- match |= CPU_FLAGS_ARCH_MATCH;
- }
- else if (x.bitfield.cpuavx)
- {
- /* We need to check a few extra flags with AVX. */
- if (cpu.bitfield.cpuavx
- && (!t->opcode_modifier.sse2avx
- || (sse2avx && !i.prefix[DATA_PREFIX]))
- && (!x.bitfield.cpuaes || cpu.bitfield.cpuaes)
- && (!x.bitfield.cpugfni || cpu.bitfield.cpugfni)
- && (!x.bitfield.cpupclmulqdq || cpu.bitfield.cpupclmulqdq))
- match |= CPU_FLAGS_ARCH_MATCH;
- }
- else if (x.bitfield.cpuavx2 && cpu.bitfield.cpuavx2)
- match |= CPU_FLAGS_ARCH_MATCH;
- else if (x.bitfield.cpuavx512f)
+ if (any.bitfield.cpuavx && any.bitfield.cpuavx2)
+ any.bitfield.cpuavx2 = 0;
+
+ cpu = cpu_flags_and (any, active);
+ if (cpu_flags_all_zero (&any) || !cpu_flags_all_zero (&cpu))
+ {
+ if (all.bitfield.cpuavx)
{
- /* We need to check a few extra flags with AVX512F. */
- if (cpu.bitfield.cpuavx512f
- && (!x.bitfield.cpugfni || cpu.bitfield.cpugfni))
+ /* We need to check SSE2AVX with AVX. */
+ if (!t->opcode_modifier.sse2avx
+ || (sse2avx && !i.prefix[DATA_PREFIX]))
match |= CPU_FLAGS_ARCH_MATCH;
}
else
@@ -3679,20 +3663,25 @@ install_template (const insn_template *t)
/* Dual VEX/EVEX templates need stripping one of the possible variants. */
if (t->opcode_modifier.vex && t->opcode_modifier.evex)
{
- if ((is_cpu (t, CpuAVX) || is_cpu (t, CpuAVX2))
- && is_cpu (t, CpuAVX512F))
+ if ((maybe_cpu (t, CpuAVX) || maybe_cpu (t, CpuAVX2)
+ || maybe_cpu (t, CpuFMA))
+ && (maybe_cpu (t, CpuAVX512F) || maybe_cpu (t, CpuAVX512VL)))
{
if (need_evex_encoding ())
{
i.tm.opcode_modifier.vex = 0;
- i.tm.cpu.bitfield.cpuavx = 0;
- if (is_cpu (&i.tm, CpuAVX2))
- i.tm.cpu.bitfield.isa = 0;
+ i.tm.cpu.bitfield.cpuavx512f = i.tm.cpu_any.bitfield.cpuavx512f;
+ i.tm.cpu.bitfield.cpuavx512vl = i.tm.cpu_any.bitfield.cpuavx512vl;
}
else
{
i.tm.opcode_modifier.evex = 0;
- i.tm.cpu.bitfield.cpuavx512f = 0;
+ if (i.tm.cpu_any.bitfield.cpuavx)
+ i.tm.cpu.bitfield.cpuavx = 1;
+ else if (!i.tm.cpu.bitfield.isa)
+ i.tm.cpu.bitfield.isa = i.tm.cpu_any.bitfield.isa;
+ else
+ gas_assert (i.tm.cpu.bitfield.isa == i.tm.cpu_any.bitfield.isa);
}
}
}
@@ -6570,7 +6559,7 @@ check_VecOperands (const insn_template *t)
/* Somewhat similarly, templates specifying both AVX and AVX2 are
requiring AVX2 support if the actual operand size is YMMword. */
- if (is_cpu (t, CpuAVX) && is_cpu (t, CpuAVX2)
+ if (maybe_cpu (t, CpuAVX) && maybe_cpu (t, CpuAVX2)
&& !cpu_arch_flags.bitfield.cpuavx2)
{
for (op = 0; op < t->operands; ++op)