#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;
0 if att syntax. */
static int intel_syntax = 0;
-/* 1 for Intel64 ISA,
- 0 if AMD64 ISA. */
-static int intel64;
+static enum x86_64_isa
+{
+ amd64 = 1, /* AMD64 ISA. */
+ intel64 /* Intel64 ISA. */
+} isa64;
/* 1 for intel mnemonic,
0 if att mnemonic. */
/* 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;
}
}
if (intel_mnemonic && t->opcode_modifier.attmnemonic)
continue;
- /* Check AT&T/Intel syntax and Intel64/AMD64 ISA. */
+ /* Check AT&T/Intel syntax. */
i.error = unsupported_syntax;
if ((intel_syntax && t->opcode_modifier.attsyntax)
- || (!intel_syntax && t->opcode_modifier.intelsyntax)
- || (intel64 && t->opcode_modifier.amd64)
- || (!intel64 && t->opcode_modifier.intel64))
+ || (!intel_syntax && t->opcode_modifier.intelsyntax))
continue;
+ /* Check Intel64/AMD64 ISA. */
+ switch (isa64)
+ {
+ default:
+ /* Default: Don't accept Intel64. */
+ if (t->opcode_modifier.isa64 == INTEL64)
+ continue;
+ break;
+ case amd64:
+ /* -mamd64: Don't accept Intel64 and Intel64 only. */
+ if (t->opcode_modifier.isa64 >= INTEL64)
+ continue;
+ break;
+ case intel64:
+ /* -mintel64: Don't accept AMD64. */
+ if (t->opcode_modifier.isa64 == AMD64 && flag_code == CODE_64BIT)
+ continue;
+ break;
+ }
+
/* Check the suffix. */
i.error = invalid_instruction_suffix;
if ((t->opcode_modifier.no_bsuf && suffix_check.no_bsuf)
Destination register type is more significant than source
register type. crc32 in SSE4.2 prefers source register
type. */
- if (i.tm.base_opcode == 0xf20f38f0
- && i.types[0].bitfield.class == Reg)
- {
- if (i.types[0].bitfield.byte)
- i.suffix = BYTE_MNEM_SUFFIX;
- else if (i.types[0].bitfield.word)
- i.suffix = WORD_MNEM_SUFFIX;
- else if (i.types[0].bitfield.dword)
- i.suffix = LONG_MNEM_SUFFIX;
- else if (i.types[0].bitfield.qword)
- i.suffix = QWORD_MNEM_SUFFIX;
- }
-
- if (!i.suffix)
- {
- int op;
-
- if (i.tm.base_opcode == 0xf20f38f0)
- {
- /* We have to know the operand size for crc32. */
- as_bad (_("ambiguous memory operand size for `%s`"),
- i.tm.name);
- return 0;
- }
+ unsigned int op = i.tm.base_opcode != 0xf20f38f0 ? i.operands : 1;
- for (op = i.operands; --op >= 0;)
- if (i.tm.operand_types[op].bitfield.instance == InstanceNone
- || i.tm.operand_types[op].bitfield.instance == Accum)
- {
- if (i.types[op].bitfield.class != Reg)
- continue;
- if (i.types[op].bitfield.byte)
- i.suffix = BYTE_MNEM_SUFFIX;
- else if (i.types[op].bitfield.word)
- i.suffix = WORD_MNEM_SUFFIX;
- else if (i.types[op].bitfield.dword)
- i.suffix = LONG_MNEM_SUFFIX;
- else if (i.types[op].bitfield.qword)
- i.suffix = QWORD_MNEM_SUFFIX;
- else
- continue;
- break;
- }
- }
+ while (op--)
+ if (i.tm.operand_types[op].bitfield.instance == InstanceNone
+ || i.tm.operand_types[op].bitfield.instance == Accum)
+ {
+ if (i.types[op].bitfield.class != Reg)
+ continue;
+ if (i.types[op].bitfield.byte)
+ i.suffix = BYTE_MNEM_SUFFIX;
+ else if (i.types[op].bitfield.word)
+ i.suffix = WORD_MNEM_SUFFIX;
+ else if (i.types[op].bitfield.dword)
+ i.suffix = LONG_MNEM_SUFFIX;
+ else if (i.types[op].bitfield.qword)
+ i.suffix = QWORD_MNEM_SUFFIX;
+ else
+ continue;
+ break;
+ }
}
else if (i.suffix == BYTE_MNEM_SUFFIX)
{
else
abort ();
}
- else if (i.tm.opcode_modifier.defaultsize
- && !i.suffix
- /* exclude fldenv/frstor/fsave/fstenv */
- && i.tm.opcode_modifier.no_ssuf
- /* exclude sysret */
- && i.tm.base_opcode != 0x0f07)
+ else if (i.tm.opcode_modifier.defaultsize && !i.suffix)
{
i.suffix = stackop_size;
if (stackop_size == LONG_MNEM_SUFFIX)
i.tm.name);
}
}
- else if (intel_syntax
- && !i.suffix
+ else if (!i.suffix
&& (i.tm.opcode_modifier.jump == JUMP_ABSOLUTE
|| i.tm.opcode_modifier.jump == JUMP_BYTE
|| i.tm.opcode_modifier.jump == JUMP_INTERSEGMENT
}
}
- if (!i.suffix)
+ if (!i.suffix
+ && (!i.tm.opcode_modifier.defaultsize
+ /* Also cover lret/retf/iret in 64-bit mode. */
+ || (flag_code == CODE_64BIT
+ && !i.tm.opcode_modifier.no_lsuf
+ && !i.tm.opcode_modifier.no_qsuf))
+ && !i.tm.opcode_modifier.ignoresize
+ /* Accept FLDENV et al without suffix. */
+ && (i.tm.opcode_modifier.no_ssuf || i.tm.opcode_modifier.floatmf))
{
- if (!intel_syntax)
+ unsigned int suffixes;
+
+ suffixes = !i.tm.opcode_modifier.no_bsuf;
+ if (!i.tm.opcode_modifier.no_wsuf)
+ suffixes |= 1 << 1;
+ if (!i.tm.opcode_modifier.no_lsuf)
+ suffixes |= 1 << 2;
+ if (!i.tm.opcode_modifier.no_ldsuf)
+ suffixes |= 1 << 3;
+ if (!i.tm.opcode_modifier.no_ssuf)
+ suffixes |= 1 << 4;
+ if (flag_code == CODE_64BIT && !i.tm.opcode_modifier.no_qsuf)
+ suffixes |= 1 << 5;
+
+ /* Are multiple suffixes allowed? */
+ if (suffixes & (suffixes - 1))
{
- if (i.tm.opcode_modifier.w)
+ if (intel_syntax
+ && (!i.tm.opcode_modifier.defaultsize
+ || operand_check == check_error))
{
- as_bad (_("no instruction mnemonic suffix given and "
- "no register operands; can't size instruction"));
+ as_bad (_("ambiguous operand size for `%s'"), i.tm.name);
return 0;
}
- }
- else
- {
- unsigned int suffixes;
-
- suffixes = !i.tm.opcode_modifier.no_bsuf;
- if (!i.tm.opcode_modifier.no_wsuf)
- suffixes |= 1 << 1;
- if (!i.tm.opcode_modifier.no_lsuf)
- suffixes |= 1 << 2;
- if (!i.tm.opcode_modifier.no_ldsuf)
- suffixes |= 1 << 3;
- if (!i.tm.opcode_modifier.no_ssuf)
- suffixes |= 1 << 4;
- if (flag_code == CODE_64BIT && !i.tm.opcode_modifier.no_qsuf)
- suffixes |= 1 << 5;
-
- /* There are more than suffix matches. */
- if (i.tm.opcode_modifier.w
- || ((suffixes & (suffixes - 1))
- && !i.tm.opcode_modifier.defaultsize
- && !i.tm.opcode_modifier.ignoresize))
+ if (operand_check == check_error)
{
- as_bad (_("ambiguous operand size for `%s'"), i.tm.name);
+ as_bad (_("no instruction mnemonic suffix given and "
+ "no register operands; can't size `%s'"), i.tm.name);
return 0;
}
+ if (operand_check == check_warning)
+ as_warn (_("%s; using default for `%s'"),
+ intel_syntax
+ ? _("ambiguous operand size")
+ : _("no instruction mnemonic suffix given and "
+ "no register operands"),
+ i.tm.name);
+
+ if (i.tm.opcode_modifier.floatmf)
+ i.suffix = SHORT_MNEM_SUFFIX;
+ else if (flag_code == CODE_16BIT)
+ i.suffix = WORD_MNEM_SUFFIX;
+ else if (!i.tm.opcode_modifier.no_lsuf)
+ i.suffix = LONG_MNEM_SUFFIX;
+ else
+ i.suffix = QWORD_MNEM_SUFFIX;
}
}
+ 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 prefix on a general reg is missing. */
- else if ((!quiet_warnings || flag_code == CODE_64BIT)
- && i.types[op].bitfield.word
+ /* Error if the e prefix on a general reg is missing. */
+ else if (i.types[op].bitfield.word
&& (i.tm.operand_types[op].bitfield.class == Reg
|| i.tm.operand_types[op].bitfield.instance == Accum)
&& i.tm.operand_types[op].bitfield.dword)
{
- /* 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_EAX - REGNAM_AX)->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;
}
/* Warn if the r prefix on a general reg is present. */
else if (i.types[op].bitfield.qword
&& i.tm.operand_types[op].bitfield.dword)
{
if (intel_syntax
- && i.tm.opcode_modifier.toqword
+ && (i.tm.opcode_modifier.toqword
+ /* Also convert to QWORD for MOVSXD. */
+ || i.tm.base_opcode == 0x63)
&& i.types[0].bitfield.class != RegSIMD)
{
/* Convert to QWORD. We want REX byte. */
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. */
&& i.rm.regmem == 5))
&& (i.rm.mode == 2
|| (i.rm.mode == 0 && i.rm.regmem == 5))
+ && !is_any_vex_encoding(&i.tm)
&& ((i.operands == 1
&& i.tm.base_opcode == 0xff
&& (i.rm.reg == 2 || i.rm.reg == 4))
|| (i.operands == 2
&& (i.tm.base_opcode == 0x8b
|| i.tm.base_opcode == 0x85
- || (i.tm.base_opcode & 0xc7) == 0x03))))
+ || (i.tm.base_opcode & ~0x38) == 0x03))))
{
if (object_64bit)
{
if (t->opcode_modifier.jump
!= current_templates->start->opcode_modifier.jump)
break;
- if (t->opcode_modifier.intel64)
+ if ((t->opcode_modifier.isa64 >= INTEL64))
has_intel64 = TRUE;
}
if (t < current_templates->end)
break;
case OPTION_MAMD64:
- intel64 = 0;
+ isa64 = amd64;
break;
case OPTION_MINTEL64:
- intel64 = 1;
+ isa64 = intel64;
break;
case 'O':