#endif
#endif
-#ifndef REGISTER_WARNINGS
-#define REGISTER_WARNINGS 1
-#endif
-
#ifndef INFER_ADDR_PREFIX
#define INFER_ADDR_PREFIX 1
#endif
unsigned int prefixes;
unsigned char prefix[MAX_PREFIXES];
+ /* Register is in low 3 bits of opcode. */
+ bfd_boolean short_form;
+
/* The operand to a branch insn indicates an absolute branch. */
bfd_boolean jumpabsolute;
{ STRING_COMMA_LEN ("nossse3"), CPU_ANY_SSSE3_FLAGS },
{ STRING_COMMA_LEN ("nosse4.1"), CPU_ANY_SSE4_1_FLAGS },
{ STRING_COMMA_LEN ("nosse4.2"), CPU_ANY_SSE4_2_FLAGS },
- { STRING_COMMA_LEN ("nosse4"), CPU_ANY_SSE4_1_FLAGS },
+ { STRING_COMMA_LEN ("nosse4"), CPU_ANY_SSE4_FLAGS },
{ STRING_COMMA_LEN ("noavx"), CPU_ANY_AVX_FLAGS },
{ STRING_COMMA_LEN ("noavx2"), CPU_ANY_AVX2_FLAGS },
{ STRING_COMMA_LEN ("noavx512f"), CPU_ANY_AVX512F_FLAGS },
return x;
}
+static const i386_cpu_flags avx512 = CPU_ANY_AVX512F_FLAGS;
+
#define CPU_FLAGS_ARCH_MATCH 0x1
#define CPU_FLAGS_64BIT_MATCH 0x2
/* If given types g0 and g1 are registers they must be of the same type
unless the expected operand type register overlap is null.
- Memory operand size of certain SIMD instructions is also being checked
- here. */
+ Some Intel syntax memory operand size checking also happens here. */
static INLINE int
operand_type_register_match (i386_operand_type g0,
&& g0.bitfield.class != RegSIMD
&& (!operand_type_check (g0, anymem)
|| g0.bitfield.unspecified
- || t0.bitfield.class != RegSIMD))
+ || (t0.bitfield.class != Reg
+ && t0.bitfield.class != RegSIMD)))
return 1;
if (g1.bitfield.class != Reg
&& g1.bitfield.class != RegSIMD
&& (!operand_type_check (g1, anymem)
|| g1.bitfield.unspecified
- || t1.bitfield.class != RegSIMD))
+ || (t1.bitfield.class != Reg
+ && t1.bitfield.class != RegSIMD)))
return 1;
if (g0.bitfield.byte == g1.bitfield.byte
i.tm.base_opcode = 0xb8;
i.tm.extension_opcode = None;
i.tm.opcode_modifier.w = 0;
- i.tm.opcode_modifier.shortform = 1;
i.tm.opcode_modifier.modrm = 0;
}
}
{
unsigned int op;
i386_cpu_flags cpu;
- static const i386_cpu_flags avx512 = CPU_ANY_AVX512F_FLAGS;
/* Templates allowing for ZMMword as well as YMMword and/or XMMword for
any one operand are implicity requiring AVX512VL support if the actual
break;
case intel64:
/* -mintel64: Don't accept AMD64. */
- if (t->opcode_modifier.isa64 == AMD64)
+ if (t->opcode_modifier.isa64 == AMD64 && flag_code == CODE_64BIT)
continue;
break;
}
/* Accept FLDENV et al without suffix. */
&& (i.tm.opcode_modifier.no_ssuf || i.tm.opcode_modifier.floatmf))
{
- unsigned int suffixes;
+ unsigned int suffixes, evex = 0;
suffixes = !i.tm.opcode_modifier.no_bsuf;
if (!i.tm.opcode_modifier.no_wsuf)
if (flag_code == CODE_64BIT && !i.tm.opcode_modifier.no_qsuf)
suffixes |= 1 << 5;
- /* Are multiple suffixes allowed? */
+ /* 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. */
+ if (intel_syntax)
+ {
+ i386_cpu_flags cpu = cpu_flags_and (i.tm.cpu_flags, avx512);
+
+ if (!cpu_flags_all_zero (&cpu) && !i.broadcast)
+ {
+ unsigned int op;
+
+ for (op = 0; op < i.tm.operands; ++op)
+ {
+ if (!cpu_arch_flags.bitfield.cpuavx512vl)
+ {
+ if (i.tm.operand_types[op].bitfield.ymmword)
+ i.tm.operand_types[op].bitfield.xmmword = 0;
+ if (i.tm.operand_types[op].bitfield.zmmword)
+ i.tm.operand_types[op].bitfield.ymmword = 0;
+ if (!i.tm.opcode_modifier.evex
+ || i.tm.opcode_modifier.evex == EVEXDYN)
+ i.tm.opcode_modifier.evex = EVEX512;
+ }
+
+ if (i.tm.operand_types[op].bitfield.xmmword
+ + i.tm.operand_types[op].bitfield.ymmword
+ + i.tm.operand_types[op].bitfield.zmmword < 2)
+ continue;
+
+ /* Any properly sized operand disambiguates the insn. */
+ if (i.types[op].bitfield.xmmword
+ || i.types[op].bitfield.ymmword
+ || i.types[op].bitfield.zmmword)
+ {
+ suffixes &= ~(7 << 6);
+ evex = 0;
+ break;
+ }
+
+ if ((i.flags[op] & Operand_Mem)
+ && i.tm.operand_types[op].bitfield.unspecified)
+ {
+ if (i.tm.operand_types[op].bitfield.xmmword)
+ suffixes |= 1 << 6;
+ if (i.tm.operand_types[op].bitfield.ymmword)
+ suffixes |= 1 << 7;
+ if (i.tm.operand_types[op].bitfield.zmmword)
+ suffixes |= 1 << 8;
+ evex = EVEX512;
+ }
+ }
+ }
+ }
+
+ /* Are multiple suffixes / operand sizes allowed? */
if (suffixes & (suffixes - 1))
{
if (intel_syntax
if (i.tm.opcode_modifier.floatmf)
i.suffix = SHORT_MNEM_SUFFIX;
+ else if (evex)
+ i.tm.opcode_modifier.evex = evex;
else if (flag_code == CODE_16BIT)
i.suffix = WORD_MNEM_SUFFIX;
else if (!i.tm.opcode_modifier.no_lsuf)
}
}
+ if (!i.tm.opcode_modifier.modrm && i.reg_operands && i.tm.operands < 3)
+ i.short_form = (i.tm.operand_types[0].bitfield.class == Reg)
+ != (i.tm.operand_types[1].bitfield.class == Reg);
+
/* Change the opcode based on the operand size given by i.suffix. */
switch (i.suffix)
{
/* It's not a byte, select word/dword operation. */
if (i.tm.opcode_modifier.w)
{
- if (i.tm.opcode_modifier.shortform)
+ if (i.short_form)
i.tm.base_opcode |= 8;
else
i.tm.base_opcode |= 1;
&& i.tm.operand_types[op].bitfield.word)
continue;
- /* crc32 doesn't generate this warning. */
- if (i.tm.base_opcode == 0xf20f38f0)
+ /* crc32 only wants its source operand checked here. */
+ if (i.tm.base_opcode == 0xf20f38f0 && op)
continue;
- if ((i.types[op].bitfield.word
- || i.types[op].bitfield.dword
- || i.types[op].bitfield.qword)
- && i.op[op].regs->reg_num < 4
- /* Prohibit these changes in 64bit mode, since the lowering
- would be more complicated. */
- && flag_code != CODE_64BIT)
- {
-#if REGISTER_WARNINGS
- if (!quiet_warnings)
- as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
- register_prefix,
- (i.op[op].regs + (i.types[op].bitfield.word
- ? REGNAM_AL - REGNAM_AX
- : REGNAM_AL - REGNAM_EAX))->reg_name,
- register_prefix,
- i.op[op].regs->reg_name,
- i.suffix);
-#endif
- continue;
- }
/* Any other register is bad. */
if (i.types[op].bitfield.class == Reg
|| i.types[op].bitfield.class == RegMMX
i.suffix);
return 0;
}
- /* Warn if the e or r prefix on a general reg is present. */
- else if ((!quiet_warnings || flag_code == CODE_64BIT)
- && (i.types[op].bitfield.dword
+ /* Error if the e or r prefix on a general reg is present. */
+ else if ((i.types[op].bitfield.dword
|| i.types[op].bitfield.qword)
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& i.tm.operand_types[op].bitfield.word)
{
- /* Prohibit these changes in the 64bit mode, since the
- lowering is more complicated. */
- if (flag_code == CODE_64BIT)
- {
- as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
- register_prefix, i.op[op].regs->reg_name,
- i.suffix);
- return 0;
- }
-#if REGISTER_WARNINGS
- as_warn (_("using `%s%s' instead of `%s%s' due to `%c' suffix"),
- register_prefix,
- (i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name,
- register_prefix, i.op[op].regs->reg_name, i.suffix);
-#endif
+ as_bad (_("incorrect register `%s%s' used with `%c' suffix"),
+ register_prefix, i.op[op].regs->reg_name,
+ i.suffix);
+ return 0;
}
return 1;
}
on one of their operands, the default segment is ds. */
default_seg = &ds;
}
- else if (i.tm.opcode_modifier.shortform)
+ else if (i.short_form)
{
/* The register or float register operand is in operand
0 or 1. */