static void swap_2_operands (int, int);
static void optimize_imm (void);
static void optimize_disp (void);
-static const insn_template *match_template (void);
+static const insn_template *match_template (char);
static int check_string (void);
static int process_suffix (void);
static int check_byte_reg (void);
explicit segment overrides are given. */
const seg_entry *seg[2];
+ /* Copied first memory operand string, for re-checking. */
+ char *memop1_string;
+
/* PREFIX holds all the given prefix opcodes (usually null).
PREFIXES is the number of prefix opcodes. */
unsigned int prefixes;
0 if att syntax. */
static int intel_syntax = 0;
+/* 1 for Intel64 ISA,
+ 0 if AMD64 ISA. */
+static int intel64;
+
/* 1 for intel mnemonic,
0 if att mnemonic. */
static int intel_mnemonic = !SYSV386_COMPAT;
CPU_287_FLAGS, 0 },
{ STRING_COMMA_LEN (".387"), PROCESSOR_UNKNOWN,
CPU_387_FLAGS, 0 },
+ { STRING_COMMA_LEN (".687"), PROCESSOR_UNKNOWN,
+ CPU_687_FLAGS, 0 },
{ STRING_COMMA_LEN (".mmx"), PROCESSOR_UNKNOWN,
CPU_MMX_FLAGS, 0 },
{ STRING_COMMA_LEN (".sse"), PROCESSOR_UNKNOWN,
CPU_SE1_FLAGS, 0 },
{ STRING_COMMA_LEN (".clwb"), PROCESSOR_UNKNOWN,
CPU_CLWB_FLAGS, 0 },
- { STRING_COMMA_LEN (".pcommit"), PROCESSOR_UNKNOWN,
- CPU_PCOMMIT_FLAGS, 0 },
{ STRING_COMMA_LEN (".avx512ifma"), PROCESSOR_UNKNOWN,
CPU_AVX512IFMA_FLAGS, 0 },
{ STRING_COMMA_LEN (".avx512vbmi"), PROCESSOR_UNKNOWN,
CPU_AVX512VBMI_FLAGS, 0 },
+ { STRING_COMMA_LEN (".avx512_4fmaps"), PROCESSOR_UNKNOWN,
+ CPU_AVX512_4FMAPS_FLAGS, 0 },
+ { STRING_COMMA_LEN (".avx512_4vnniw"), PROCESSOR_UNKNOWN,
+ CPU_AVX512_4VNNIW_FLAGS, 0 },
{ STRING_COMMA_LEN (".clzero"), PROCESSOR_UNKNOWN,
CPU_CLZERO_FLAGS, 0 },
{ STRING_COMMA_LEN (".mwaitx"), PROCESSOR_UNKNOWN,
CPU_OSPKE_FLAGS, 0 },
{ STRING_COMMA_LEN (".rdpid"), PROCESSOR_UNKNOWN,
CPU_RDPID_FLAGS, 0 },
+ { STRING_COMMA_LEN (".ptwrite"), PROCESSOR_UNKNOWN,
+ CPU_PTWRITE_FLAGS, 0 },
};
static const noarch_entry cpu_noarch[] =
{
{ STRING_COMMA_LEN ("no87"), CPU_ANY_X87_FLAGS },
+ { STRING_COMMA_LEN ("no287"), CPU_ANY_287_FLAGS },
+ { STRING_COMMA_LEN ("no387"), CPU_ANY_387_FLAGS },
+ { STRING_COMMA_LEN ("no687"), CPU_ANY_687_FLAGS },
{ STRING_COMMA_LEN ("nommx"), CPU_ANY_MMX_FLAGS },
{ STRING_COMMA_LEN ("nosse"), CPU_ANY_SSE_FLAGS },
+ { STRING_COMMA_LEN ("nosse2"), CPU_ANY_SSE2_FLAGS },
+ { STRING_COMMA_LEN ("nosse3"), CPU_ANY_SSE3_FLAGS },
+ { 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 ("noavx"), CPU_ANY_AVX_FLAGS },
+ { STRING_COMMA_LEN ("noavx2"), CPU_ANY_AVX2_FLAGS },
+ { STRING_COMMA_LEN ("noavx512f"), CPU_ANY_AVX512F_FLAGS },
+ { STRING_COMMA_LEN ("noavx512cd"), CPU_ANY_AVX512CD_FLAGS },
+ { STRING_COMMA_LEN ("noavx512er"), CPU_ANY_AVX512ER_FLAGS },
+ { STRING_COMMA_LEN ("noavx512pf"), CPU_ANY_AVX512PF_FLAGS },
+ { STRING_COMMA_LEN ("noavx512dq"), CPU_ANY_AVX512DQ_FLAGS },
+ { STRING_COMMA_LEN ("noavx512bw"), CPU_ANY_AVX512BW_FLAGS },
+ { STRING_COMMA_LEN ("noavx512vl"), CPU_ANY_AVX512VL_FLAGS },
+ { STRING_COMMA_LEN ("noavx512ifma"), CPU_ANY_AVX512IFMA_FLAGS },
+ { STRING_COMMA_LEN ("noavx512vbmi"), CPU_ANY_AVX512VBMI_FLAGS },
+ { STRING_COMMA_LEN ("noavx512_4fmaps"), CPU_ANY_AVX512_4FMAPS_FLAGS },
+ { STRING_COMMA_LEN ("noavx512_4vnniw"), CPU_ANY_AVX512_4VNNIW_FLAGS },
};
#ifdef I386COFF
case 3:
if (x->array[2])
return 0;
+ /* Fall through. */
case 2:
if (x->array[1])
return 0;
+ /* Fall through. */
case 1:
return !x->array[0];
default:
{
case 3:
x->array[2] = v;
+ /* Fall through. */
case 2:
x->array[1] = v;
+ /* Fall through. */
case 1:
x->array[0] = v;
+ /* Fall through. */
break;
default:
abort ();
case 3:
if (x->array[2] != y->array[2])
return 0;
+ /* Fall through. */
case 2:
if (x->array[1] != y->array[1])
return 0;
+ /* Fall through. */
case 1:
return x->array[0] == y->array[0];
break;
case 3:
if (x->array[2])
return 0;
+ /* Fall through. */
case 2:
if (x->array[1])
return 0;
+ /* Fall through. */
case 1:
return !x->array[0];
default:
case 3:
if (x->array[2] != y->array[2])
return 0;
+ /* Fall through. */
case 2:
if (x->array[1] != y->array[1])
return 0;
+ /* Fall through. */
case 1:
return x->array[0] == y->array[0];
break;
{
case 3:
x.array [2] &= y.array [2];
+ /* Fall through. */
case 2:
x.array [1] &= y.array [1];
+ /* Fall through. */
case 1:
x.array [0] &= y.array [0];
break;
{
case 3:
x.array [2] |= y.array [2];
+ /* Fall through. */
case 2:
x.array [1] |= y.array [1];
+ /* Fall through. */
case 1:
x.array [0] |= y.array [0];
break;
{
case 3:
x.array [2] &= ~y.array [2];
+ /* Fall through. */
case 2:
x.array [1] &= ~y.array [1];
+ /* Fall through. */
case 1:
x.array [0] &= ~y.array [0];
break;
return x;
}
-static int
-valid_iamcu_cpu_flags (const i386_cpu_flags *flags)
-{
- if (cpu_arch_isa == PROCESSOR_IAMCU)
- {
- static const i386_cpu_flags iamcu_flags = CPU_IAMCU_COMPAT_FLAGS;
- i386_cpu_flags compat_flags;
- compat_flags = cpu_flags_and_not (*flags, iamcu_flags);
- return cpu_flags_all_zero (&compat_flags);
- }
- else
- return 1;
-}
-
#define CPU_FLAGS_ARCH_MATCH 0x1
#define CPU_FLAGS_64BIT_MATCH 0x2
#define CPU_FLAGS_AES_MATCH 0x4
/* This instruction is available only on some archs. */
i386_cpu_flags cpu = cpu_arch_flags;
- cpu.bitfield.cpu64 = 0;
- cpu.bitfield.cpuno64 = 0;
cpu = cpu_flags_and (x, cpu);
if (!cpu_flags_all_zero (&cpu))
{
{
case 3:
x.array [2] &= y.array [2];
+ /* Fall through. */
case 2:
x.array [1] &= y.array [1];
+ /* Fall through. */
case 1:
x.array [0] &= y.array [0];
break;
{
case 3:
x.array [2] |= y.array [2];
+ /* Fall through. */
case 2:
x.array [1] |= y.array [1];
+ /* Fall through. */
case 1:
x.array [0] |= y.array [0];
break;
{
case 3:
x.array [2] ^= y.array [2];
+ /* Fall through. */
case 2:
x.array [1] ^= y.array [1];
+ /* Fall through. */
case 1:
x.array [0] ^= y.array [0];
break;
flags = cpu_flags_or (cpu_arch_flags,
cpu_arch[j].flags);
- if (!valid_iamcu_cpu_flags (&flags))
- as_fatal (_("`%s' isn't valid for Intel MCU"),
- cpu_arch[j].name);
- else if (!cpu_flags_equal (&flags, &cpu_arch_flags))
+ if (!cpu_flags_equal (&flags, &cpu_arch_flags))
{
if (cpu_sub_arch_name)
{
md_assemble (char *line)
{
unsigned int j;
- char mnemonic[MAX_MNEM_SIZE];
+ char mnemonic[MAX_MNEM_SIZE], mnem_suffix;
const insn_template *t;
/* Initialize globals. */
line = parse_insn (line, mnemonic);
if (line == NULL)
return;
+ mnem_suffix = i.suffix;
line = parse_operands (line, mnemonic);
this_operand = -1;
+ xfree (i.memop1_string);
+ i.memop1_string = NULL;
if (line == NULL)
return;
making sure the overlap of the given operands types is consistent
with the template operand types. */
- if (!(t = match_template ()))
+ if (!(t = match_template (mnem_suffix)))
return;
if (sse_check != check_none
if (i.bnd_prefix && !i.tm.opcode_modifier.bndprefixok)
as_bad (_("expecting valid branch instruction after `bnd'"));
- if (i.tm.cpu_flags.bitfield.cpumpx
- && flag_code == CODE_64BIT
- && i.prefix[ADDR_PREFIX])
- as_bad (_("32-bit address isn't allowed in 64-bit MPX instructions."));
+ if (i.tm.cpu_flags.bitfield.cpumpx)
+ {
+ if (flag_code == CODE_64BIT && i.prefix[ADDR_PREFIX])
+ as_bad (_("32-bit address isn't allowed in 64-bit MPX instructions."));
+ else if (flag_code != CODE_16BIT
+ ? i.prefix[ADDR_PREFIX]
+ : i.mem_operands && !i.prefix[ADDR_PREFIX])
+ as_bad (_("16-bit address isn't allowed in MPX instructions"));
+ }
/* Insert BND prefix. */
if (add_bnd_prefix
if (intel_syntax && (intel_float_operand (mnemonic) & 2))
i.suffix = SHORT_MNEM_SUFFIX;
else
+ /* Fall through. */
case BYTE_MNEM_SUFFIX:
case QWORD_MNEM_SUFFIX:
i.suffix = mnem_p[-1];
case 5:
case 4:
swap_2_operands (1, i.operands - 2);
+ /* Fall through. */
case 3:
case 2:
swap_2_operands (0, i.operands - 1);
}
static const insn_template *
-match_template (void)
+match_template (char mnem_suffix)
{
/* Points to template once we've found it. */
const insn_template *t;
i386_operand_type overlap0, overlap1, overlap2, overlap3;
i386_operand_type overlap4;
unsigned int found_reverse_match;
- i386_opcode_modifier suffix_check;
+ i386_opcode_modifier suffix_check, mnemsuf_check;
i386_operand_type operand_types [MAX_OPERANDS];
int addr_prefix_disp;
unsigned int j;
else if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX)
suffix_check.no_ldsuf = 1;
+ memset (&mnemsuf_check, 0, sizeof (mnemsuf_check));
+ if (intel_syntax)
+ {
+ switch (mnem_suffix)
+ {
+ case BYTE_MNEM_SUFFIX: mnemsuf_check.no_bsuf = 1; break;
+ case WORD_MNEM_SUFFIX: mnemsuf_check.no_wsuf = 1; break;
+ case SHORT_MNEM_SUFFIX: mnemsuf_check.no_ssuf = 1; break;
+ case LONG_MNEM_SUFFIX: mnemsuf_check.no_lsuf = 1; break;
+ case QWORD_MNEM_SUFFIX: mnemsuf_check.no_qsuf = 1; break;
+ }
+ }
+
/* Must have right number of operands. */
i.error = number_of_operands_mismatch;
if (intel_mnemonic && t->opcode_modifier.attmnemonic)
continue;
- /* Check AT&T/Intel syntax. */
+ /* Check AT&T/Intel syntax and Intel64/AMD64 ISA. */
i.error = unsupported_syntax;
if ((intel_syntax && t->opcode_modifier.attsyntax)
- || (!intel_syntax && t->opcode_modifier.intelsyntax))
+ || (!intel_syntax && t->opcode_modifier.intelsyntax)
+ || (intel64 && t->opcode_modifier.amd64)
+ || (!intel64 && t->opcode_modifier.intel64))
continue;
/* Check the suffix, except for some instructions in intel mode. */
|| (t->opcode_modifier.no_qsuf && suffix_check.no_qsuf)
|| (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf)))
continue;
+ /* In Intel mode all mnemonic suffixes must be explicitly allowed. */
+ if ((t->opcode_modifier.no_bsuf && mnemsuf_check.no_bsuf)
+ || (t->opcode_modifier.no_wsuf && mnemsuf_check.no_wsuf)
+ || (t->opcode_modifier.no_lsuf && mnemsuf_check.no_lsuf)
+ || (t->opcode_modifier.no_ssuf && mnemsuf_check.no_ssuf)
+ || (t->opcode_modifier.no_qsuf && mnemsuf_check.no_qsuf)
+ || (t->opcode_modifier.no_ldsuf && mnemsuf_check.no_ldsuf))
+ continue;
if (!operand_size_match (t))
continue;
else if (t->opcode_modifier.d)
goto check_reverse;
}
+ /* Fall through. */
case 3:
/* If we swap operand in encoding, we match the next one. */
if (i.swap_operand && t->opcode_modifier.s)
continue;
+ /* Fall through. */
case 4:
case 5:
overlap1 = operand_type_and (i.types[1], operand_types[1]);
case 5:
overlap4 = operand_type_and (i.types[4],
operand_types[4]);
+ /* Fall through. */
case 4:
overlap3 = operand_type_and (i.types[3],
operand_types[3]);
+ /* Fall through. */
case 3:
overlap2 = operand_type_and (i.types[2],
operand_types[2]);
i.types[4],
operand_types[4]))
continue;
+ /* Fall through. */
case 4:
if (!operand_type_match (overlap3, i.types[3])
|| (check_register
i.types[3],
operand_types[3])))
continue;
+ /* Fall through. */
case 3:
/* Here we make use of the fact that there are no
reverse match 3 operand instructions, and all 3
i.suffix = QWORD_MNEM_SUFFIX;
break;
}
+ /* Fall through. */
case CODE_32BIT:
if (!i.tm.opcode_modifier.no_lsuf)
i.suffix = LONG_MNEM_SUFFIX;
/* Warn if the r prefix on a general reg is missing. */
else if ((i.types[op].bitfield.reg16
|| i.types[op].bitfield.reg32)
- && (i.tm.operand_types[op].bitfield.reg32
+ && (i.tm.operand_types[op].bitfield.reg64
|| i.tm.operand_types[op].bitfield.acc))
{
/* Prohibit these changes in the 64bit mode, since the
i.reg_operands--;
i.tm.operands--;
}
+ else if (i.tm.opcode_modifier.implicitquadgroup)
+ {
+ /* The second operand must be {x,y,z}mmN, where N is a multiple of 4. */
+ gas_assert (i.operands >= 2
+ && (operand_type_equal (&i.types[1], ®xmm)
+ || operand_type_equal (&i.types[1], ®ymm)
+ || operand_type_equal (&i.types[1], ®zmm)));
+ unsigned int regnum = register_number (i.op[1].regs);
+ unsigned int first_reg_in_group = regnum & ~3;
+ unsigned int last_reg_in_group = first_reg_in_group + 3;
+ if (regnum != first_reg_in_group) {
+ as_warn (_("the second source register `%s%s' implicitly denotes"
+ " `%s%.3s%d' to `%s%.3s%d' source group in `%s'"),
+ register_prefix, i.op[1].regs->reg_name,
+ register_prefix, i.op[1].regs->reg_name, first_reg_in_group,
+ register_prefix, i.op[1].regs->reg_name, last_reg_in_group,
+ i.tm.name);
+ }
+ }
else if (i.tm.opcode_modifier.regkludge)
{
/* The imul $imm, %reg instruction is converted into
{
case 2:
*p++ = i.tm.base_opcode >> 8;
+ /* Fall through. */
case 1:
*p++ = i.tm.base_opcode;
break;
kind = "string address";
- if (current_templates->start->opcode_modifier.w)
+ if (current_templates->start->opcode_modifier.repprefixok)
{
i386_operand_type type = current_templates->end[-1].operand_types[0];
|| i.index_reg->reg_num == RegEiz))
|| !i.index_reg->reg_type.bitfield.baseindex)))
goto bad_address;
+
+ /* bndmk, bndldx, and bndstx have special restrictions. */
+ if (current_templates->start->base_opcode == 0xf30f1b
+ || (current_templates->start->base_opcode & ~1) == 0x0f1a)
+ {
+ /* They cannot use RIP-relative addressing. */
+ if (i.base_reg && i.base_reg->reg_num == RegRip)
+ {
+ as_bad (_("`%s' cannot be used here"), operand_string);
+ return 0;
+ }
+
+ /* bndldx and bndstx ignore their scale factor. */
+ if (current_templates->start->base_opcode != 0xf30f1b
+ && i.log2_scale_factor)
+ as_warn (_("register scaling is being ignored here"));
+ }
}
else
{
return 1;
}
+/* Only string instructions can have a second memory operand, so
+ reduce current_templates to just those if it contains any. */
+static int
+maybe_adjust_templates (void)
+{
+ const insn_template *t;
+
+ gas_assert (i.mem_operands == 1);
+
+ for (t = current_templates->start; t < current_templates->end; ++t)
+ if (t->opcode_modifier.isstring)
+ break;
+
+ if (t < current_templates->end)
+ {
+ static templates aux_templates;
+ bfd_boolean recheck;
+
+ aux_templates.start = t;
+ for (; t < current_templates->end; ++t)
+ if (!t->opcode_modifier.isstring)
+ break;
+ aux_templates.end = t;
+
+ /* Determine whether to re-check the first memory operand. */
+ recheck = (aux_templates.start != current_templates->start
+ || t != current_templates->end);
+
+ current_templates = &aux_templates;
+
+ if (recheck)
+ {
+ i.mem_operands = 0;
+ if (i.memop1_string != NULL
+ && i386_index_check (i.memop1_string) == 0)
+ return 0;
+ i.mem_operands = 1;
+ }
+ }
+
+ return 1;
+}
+
/* Parse OPERAND_STRING into the i386_insn structure I. Returns zero
on error. */
char *vop_start;
do_memory_reference:
+ if (i.mem_operands == 1 && !maybe_adjust_templates ())
+ return 0;
if ((i.mem_operands == 1
&& !current_templates->start->opcode_modifier.isstring)
|| i.mem_operands == 2)
if (i386_index_check (operand_string) == 0)
return 0;
i.types[this_operand].bitfield.mem = 1;
+ if (i.mem_operands == 0)
+ i.memop1_string = xstrdup (operand_string);
i.mem_operands++;
}
else
&& !cpu_arch_flags.bitfield.cpu387)
return (const reg_entry *) NULL;
- if (r->reg_type.bitfield.regmmx && !cpu_arch_flags.bitfield.cpummx)
+ if (r->reg_type.bitfield.regmmx && !cpu_arch_flags.bitfield.cpuregmmx)
return (const reg_entry *) NULL;
- if (r->reg_type.bitfield.regxmm && !cpu_arch_flags.bitfield.cpusse)
+ if (r->reg_type.bitfield.regxmm && !cpu_arch_flags.bitfield.cpuregxmm)
return (const reg_entry *) NULL;
- if (r->reg_type.bitfield.regymm && !cpu_arch_flags.bitfield.cpuavx)
+ if (r->reg_type.bitfield.regymm && !cpu_arch_flags.bitfield.cpuregymm)
return (const reg_entry *) NULL;
- if ((r->reg_type.bitfield.regzmm || r->reg_type.bitfield.regmask)
- && !cpu_arch_flags.bitfield.cpuavx512f)
+ if (r->reg_type.bitfield.regzmm && !cpu_arch_flags.bitfield.cpuregzmm)
+ return (const reg_entry *) NULL;
+
+ if (r->reg_type.bitfield.regmask
+ && !cpu_arch_flags.bitfield.cpuregmask)
return (const reg_entry *) NULL;
/* Don't allow fake index register unless allow_index_reg isn't 0. */
flags = cpu_flags_or (cpu_arch_flags,
cpu_arch[j].flags);
- if (!valid_iamcu_cpu_flags (&flags))
- as_fatal (_("`%s' isn't valid for Intel MCU"), arch);
- else if (!cpu_flags_equal (&flags, &cpu_arch_flags))
+ if (!cpu_flags_equal (&flags, &cpu_arch_flags))
{
if (cpu_sub_arch_name)
{
break;
case OPTION_MAMD64:
- cpu_arch_flags.bitfield.cpuamd64 = 1;
- cpu_arch_flags.bitfield.cpuintel64 = 0;
- cpu_arch_isa_flags.bitfield.cpuamd64 = 1;
- cpu_arch_isa_flags.bitfield.cpuintel64 = 0;
+ intel64 = 0;
break;
case OPTION_MINTEL64:
- cpu_arch_flags.bitfield.cpuamd64 = 0;
- cpu_arch_flags.bitfield.cpuintel64 = 1;
- cpu_arch_isa_flags.bitfield.cpuamd64 = 0;
- cpu_arch_isa_flags.bitfield.cpuintel64 = 1;
+ intel64 = 1;
break;
default:
cpu_arch_tune_flags = cpu_arch_isa_flags;
}
}
- else
+ else if (cpu_arch_isa != PROCESSOR_IAMCU)
as_fatal (_("Intel MCU doesn't support `%s' architecture"),
cpu_arch_name);
}
return NULL;
}
#endif
+ /* Fall through. */
case BFD_RELOC_X86_64_PLT32:
case BFD_RELOC_X86_64_GOT32:
code = fixp->fx_r_type;
break;
}
+ /* Fall through. */
default:
if (fixp->fx_pcrel)
{