diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/config/tc-i386.c | 173 |
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) |