/* tc-i386.c -- Assemble code for the Intel 80386
- Copyright (C) 1989-2020 Free Software Foundation, Inc.
+ Copyright (C) 1989-2021 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
/* Use ZMM state. */
xstate_zmm = 1 << 3 | xstate_ymm,
/* Use TMM state. */
- xstate_tmm = 1 << 4
+ xstate_tmm = 1 << 4,
+ /* Use MASK state. */
+ xstate_mask = 1 << 5
} xstate;
/* Has GOTPC or TLS relocation. */
CPU_ZNVER1_FLAGS, 0 },
{ STRING_COMMA_LEN ("znver2"), PROCESSOR_ZNVER,
CPU_ZNVER2_FLAGS, 0 },
+ { STRING_COMMA_LEN ("znver3"), PROCESSOR_ZNVER,
+ CPU_ZNVER3_FLAGS, 0 },
{ STRING_COMMA_LEN ("btver1"), PROCESSOR_BT,
CPU_BTVER1_FLAGS, 0 },
{ STRING_COMMA_LEN ("btver2"), PROCESSOR_BT,
CPU_AVX512_VNNI_FLAGS, 0 },
{ STRING_COMMA_LEN (".avx512_bitalg"), PROCESSOR_UNKNOWN,
CPU_AVX512_BITALG_FLAGS, 0 },
+ { STRING_COMMA_LEN (".avx_vnni"), PROCESSOR_UNKNOWN,
+ CPU_AVX_VNNI_FLAGS, 0 },
{ STRING_COMMA_LEN (".clzero"), PROCESSOR_UNKNOWN,
CPU_CLZERO_FLAGS, 0 },
{ STRING_COMMA_LEN (".mwaitx"), PROCESSOR_UNKNOWN,
CPU_AVX512_BF16_FLAGS, 0 },
{ STRING_COMMA_LEN (".avx512_vp2intersect"), PROCESSOR_UNKNOWN,
CPU_AVX512_VP2INTERSECT_FLAGS, 0 },
+ { STRING_COMMA_LEN (".tdx"), PROCESSOR_UNKNOWN,
+ CPU_TDX_FLAGS, 0 },
{ STRING_COMMA_LEN (".enqcmd"), PROCESSOR_UNKNOWN,
CPU_ENQCMD_FLAGS, 0 },
{ STRING_COMMA_LEN (".serialize"), PROCESSOR_UNKNOWN,
CPU_SEV_ES_FLAGS, 0 },
{ STRING_COMMA_LEN (".tsxldtrk"), PROCESSOR_UNKNOWN,
CPU_TSXLDTRK_FLAGS, 0 },
+ { STRING_COMMA_LEN (".kl"), PROCESSOR_UNKNOWN,
+ CPU_KL_FLAGS, 0 },
+ { STRING_COMMA_LEN (".widekl"), PROCESSOR_UNKNOWN,
+ CPU_WIDEKL_FLAGS, 0 },
+ { STRING_COMMA_LEN (".uintr"), PROCESSOR_UNKNOWN,
+ CPU_UINTR_FLAGS, 0 },
+ { STRING_COMMA_LEN (".hreset"), PROCESSOR_UNKNOWN,
+ CPU_HRESET_FLAGS, 0 },
};
static const noarch_entry cpu_noarch[] =
{ STRING_COMMA_LEN ("noavx512_vbmi2"), CPU_ANY_AVX512_VBMI2_FLAGS },
{ STRING_COMMA_LEN ("noavx512_vnni"), CPU_ANY_AVX512_VNNI_FLAGS },
{ STRING_COMMA_LEN ("noavx512_bitalg"), CPU_ANY_AVX512_BITALG_FLAGS },
+ { STRING_COMMA_LEN ("noavx_vnni"), CPU_ANY_AVX_VNNI_FLAGS },
{ STRING_COMMA_LEN ("noibt"), CPU_ANY_IBT_FLAGS },
{ STRING_COMMA_LEN ("noshstk"), CPU_ANY_SHSTK_FLAGS },
{ STRING_COMMA_LEN ("noamx_int8"), CPU_ANY_AMX_INT8_FLAGS },
{ STRING_COMMA_LEN ("noavx512_bf16"), CPU_ANY_AVX512_BF16_FLAGS },
{ STRING_COMMA_LEN ("noavx512_vp2intersect"),
CPU_ANY_AVX512_VP2INTERSECT_FLAGS },
+ { STRING_COMMA_LEN ("notdx"), CPU_ANY_TDX_FLAGS },
{ STRING_COMMA_LEN ("noenqcmd"), CPU_ANY_ENQCMD_FLAGS },
{ STRING_COMMA_LEN ("noserialize"), CPU_ANY_SERIALIZE_FLAGS },
{ STRING_COMMA_LEN ("notsxldtrk"), CPU_ANY_TSXLDTRK_FLAGS },
+ { STRING_COMMA_LEN ("nokl"), CPU_ANY_KL_FLAGS },
+ { STRING_COMMA_LEN ("nowidekl"), CPU_ANY_WIDEKL_FLAGS },
+ { STRING_COMMA_LEN ("nouintr"), CPU_ANY_UINTR_FLAGS },
+ { STRING_COMMA_LEN ("nohreset"), CPU_ANY_HRESET_FLAGS },
};
#ifdef I386COFF
/* different name --> ship out current template list;
add to hash table; & begin anew. */
core_optab->end = optab;
- str_hash_insert (op_hash, (optab - 1)->name, (void *) core_optab);
+ if (str_hash_insert (op_hash, (optab - 1)->name, core_optab, 0))
+ as_fatal (_("duplicate %s"), (optab - 1)->name);
+
if (optab->name == NULL)
break;
core_optab = XNEW (templates);
unsigned int regtab_size = i386_regtab_size;
for (regtab = i386_regtab; regtab_size--; regtab++)
- str_hash_insert (reg_hash, regtab->reg_name, (void *) regtab);
+ if (str_hash_insert (reg_hash, regtab->reg_name, regtab, 0) != NULL)
+ as_fatal (_("duplicate %s"), regtab->reg_name);
}
/* Fill in lexical tables: mnemonic_chars, operand_chars. */
&& i.dir_encoding == dir_encoding_default
&& i.operands == i.reg_operands
&& operand_type_equal (&i.types[0], &i.types[i.operands - 1])
- && i.tm.opcode_modifier.vexopcode == VEX0F
+ && i.tm.opcode_modifier.opcodeprefix == VEX0F
&& (i.tm.opcode_modifier.load || i.tm.opcode_modifier.d)
&& i.rex == REX_B)
{
union i386_op temp_op;
i386_operand_type temp_type;
- gas_assert (i.tm.opcode_modifier.vexopcode == VEX0F);
+ gas_assert (i.tm.opcode_modifier.opcodeprefix == VEX0F);
gas_assert (!i.tm.opcode_modifier.sae);
gas_assert (operand_type_equal (&i.types[i.operands - 2],
&i.types[i.operands - 3]));
/* Use 2-byte VEX prefix if possible. */
if (w == 0
&& i.vec_encoding != vex_encoding_vex3
- && i.tm.opcode_modifier.vexopcode == VEX0F
+ && i.tm.opcode_modifier.opcodeprefix == VEX0F
&& (i.rex & (REX_W | REX_X | REX_B)) == 0)
{
/* 2-byte VEX prefix. */
i.vex.length = 3;
- switch (i.tm.opcode_modifier.vexopcode)
+ switch (i.tm.opcode_modifier.opcodeprefix)
{
case VEX0F:
m = 0x1;
static INLINE bfd_boolean
is_any_vex_encoding (const insn_template *t)
{
- return t->opcode_modifier.vex || t->opcode_modifier.vexopcode
- || is_evex_encoding (t);
+ return t->opcode_modifier.vex || is_evex_encoding (t);
}
/* Build the EVEX prefix. */
i.vex.bytes[0] = 0x62;
/* mmmm bits. */
- switch (i.tm.opcode_modifier.vexopcode)
+ switch (i.tm.opcode_modifier.opcodeprefix)
{
case VEX0F:
m = 1;
static int
check_hle (void)
{
- switch (i.tm.opcode_modifier.hleprefixok)
+ switch (i.tm.opcode_modifier.prefixok)
{
default:
abort ();
- case HLEPrefixNone:
+ case PrefixLock:
+ case PrefixNone:
+ case PrefixNoTrack:
+ case PrefixRep:
as_bad (_("invalid instruction `%s' after `%s'"),
i.tm.name, i.hle_prefix);
return 0;
- case HLEPrefixLock:
+ case PrefixHLELock:
if (i.prefix[LOCK_PREFIX])
return 1;
as_bad (_("missing `lock' with `%s'"), i.hle_prefix);
return 0;
- case HLEPrefixAny:
+ case PrefixHLEAny:
return 1;
- case HLEPrefixRelease:
+ case PrefixHLERelease:
if (i.prefix[HLE_PREFIX] != XRELEASE_PREFIX_OPCODE)
{
as_bad (_("instruction `%s' after `xacquire' not allowed"),
/* vldmxcsr. */
if (i.tm.base_opcode == 0xae
&& i.tm.opcode_modifier.vex
- && i.tm.opcode_modifier.vexopcode == VEX0F
+ && i.tm.opcode_modifier.opcodeprefix == VEX0F
&& i.tm.extension_opcode == 2)
return 1;
}
/* cmpxchg8b, cmpxchg16b, xrstors. */
if (i.tm.base_opcode == 0xfc7
+ && i.tm.opcode_modifier.opcodeprefix == 0
&& (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3))
return 1;
/* vmptrld */
if (i.tm.base_opcode == 0xfc7
+ && i.tm.opcode_modifier.opcodeprefix == 0
&& i.tm.extension_opcode == 6)
return 1;
return;
/* Check if REP prefix is OK. */
- if (i.rep_prefix && !i.tm.opcode_modifier.repprefixok)
+ if (i.rep_prefix && i.tm.opcode_modifier.prefixok != PrefixRep)
{
as_bad (_("invalid instruction `%s' after `%s'"),
i.tm.name, i.rep_prefix);
/* Check for lock without a lockable instruction. Destination operand
must be memory unless it is xchg (0x86). */
if (i.prefix[LOCK_PREFIX]
- && (!i.tm.opcode_modifier.islockable
+ && (i.tm.opcode_modifier.prefixok < PrefixLock
|| i.mem_operands == 0
|| (i.tm.base_opcode != 0x86
&& !(i.flags[i.operands - 1] & Operand_Mem))))
as_bad (_("expecting valid branch instruction after `bnd'"));
/* Check NOTRACK prefix. */
- if (i.notrack_prefix && !i.tm.opcode_modifier.notrackprefixok)
+ if (i.notrack_prefix && i.tm.opcode_modifier.prefixok != PrefixNoTrack)
as_bad (_("expecting indirect branch instruction after `notrack'"));
if (i.tm.cpu_flags.bitfield.cpumpx)
i.xstate |= xstate_mmx;
break;
case RegMask:
- i.xstate |= xstate_zmm;
+ i.xstate |= xstate_mask;
break;
case RegSIMD:
if (i.tm.operand_types[j].bitfield.tmmword)
case QWORD_MNEM_SUFFIX:
i.suffix = mnem_p[-1];
mnem_p[-1] = '\0';
- current_templates = (const templates *) str_hash_find (op_hash,
- mnemonic);
+ current_templates
+ = (const templates *) str_hash_find (op_hash, mnemonic);
break;
case SHORT_MNEM_SUFFIX:
case LONG_MNEM_SUFFIX:
{
i.suffix = mnem_p[-1];
mnem_p[-1] = '\0';
- current_templates = (const templates *) str_hash_find (op_hash,
- mnemonic);
+ current_templates
+ = (const templates *) str_hash_find (op_hash, mnemonic);
}
break;
else
i.suffix = LONG_MNEM_SUFFIX;
mnem_p[-1] = '\0';
- current_templates = (const templates *) str_hash_find (op_hash,
- mnemonic);
+ current_templates
+ = (const templates *) str_hash_find (op_hash, mnemonic);
}
break;
}
if (cpu_flags_match (t) != CPU_FLAGS_PERFECT_MATCH)
continue;
+ /* Check Pseudo Prefix. */
+ i.error = unsupported;
+ if (t->opcode_modifier.pseudovexprefix
+ && !(i.vec_encoding == vex_encoding_vex
+ || i.vec_encoding == vex_encoding_vex3))
+ continue;
+
/* Check AT&T mnemonic. */
i.error = unsupported_with_intel_mnemonic;
if (intel_mnemonic && t->opcode_modifier.attmnemonic)
j = i.imm_operands + (t->operands > i.imm_operands + 1);
if (((i.suffix == QWORD_MNEM_SUFFIX
&& flag_code != CODE_64BIT
- && (t->base_opcode != 0x0fc7
- || t->extension_opcode != 1 /* cmpxchg8b */))
+ && !(t->base_opcode == 0xfc7
+ && i.tm.opcode_modifier.opcodeprefix == 0
+ && t->extension_opcode == 1) /* cmpxchg8b */)
|| (i.suffix == LONG_MNEM_SUFFIX
&& !cpu_arch_flags.bitfield.cpui386))
&& (intel_syntax
static int
process_suffix (void)
{
+ bfd_boolean is_crc32 = FALSE;
+
/* If matched instruction specifies an explicit instruction mnemonic
suffix, use it. */
if (i.tm.opcode_modifier.size == SIZE16)
&& !i.tm.opcode_modifier.addrprefixopreg)
{
unsigned int numop = i.operands;
+ /* CRC32 */
+ is_crc32 = (i.tm.base_opcode == 0xf38f0
+ && i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2);
/* movsx/movzx want only their source operand considered here, for the
ambiguity checking below. The suffix will be replaced afterwards
--i.operands;
/* crc32 needs REX.W set regardless of suffix / source operand size. */
- if (i.tm.base_opcode == 0xf20f38f0
- && i.tm.operand_types[1].bitfield.qword)
+ if (is_crc32 && i.tm.operand_types[1].bitfield.qword)
i.rex |= REX_W;
/* If there's no instruction mnemonic suffix we try to invent one
Destination register type is more significant than source
register type. crc32 in SSE4.2 prefers source register
type. */
- unsigned int op = i.tm.base_opcode != 0xf20f38f0 ? i.operands : 1;
+ unsigned int op = is_crc32 ? 1 : i.operands;
while (op--)
if (i.tm.operand_types[op].bitfield.instance == InstanceNone
break;
case 0:
- /* Select word/dword/qword operation with explict data sizing prefix
+ /* Select word/dword/qword operation with explicit data sizing prefix
when there are no suitable register operands. */
if (i.tm.opcode_modifier.w
&& (i.prefix[DATA_PREFIX] || (i.prefix[REX_PREFIX] & REX_W))
|| i.tm.operand_types[0].bitfield.instance == RegD
|| i.tm.operand_types[1].bitfield.instance == RegD
/* CRC32 */
- || i.tm.base_opcode == 0xf20f38f0))))
+ || is_crc32))))
i.tm.base_opcode |= 1;
break;
}
unsigned int op;
enum { need_word, need_dword, need_qword } need;
+ /* Check the register operand for the address size prefix if
+ the memory operand has no real registers, like symbol, DISP
+ or symbol(%rip). */
+ if (i.mem_operands == 1
+ && i.reg_operands == 1
+ && i.operands == 2
+ && i.types[1].bitfield.class == Reg
+ && (flag_code == CODE_32BIT
+ ? i.op[1].regs->reg_type.bitfield.word
+ : i.op[1].regs->reg_type.bitfield.dword)
+ && ((i.base_reg == NULL && i.index_reg == NULL)
+ || (i.base_reg
+ && i.base_reg->reg_num == RegIP
+ && i.base_reg->reg_type.bitfield.qword))
+ && !add_prefix (ADDR_PREFIX_OPCODE))
+ return 0;
+
if (flag_code == CODE_32BIT)
need = i.prefix[ADDR_PREFIX] ? need_word : need_dword;
else if (i.prefix[ADDR_PREFIX])
continue;
/* crc32 only wants its source operand checked here. */
- if (i.tm.base_opcode == 0xf20f38f0 && op)
+ if (i.tm.base_opcode == 0xf38f0
+ && i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2
+ && op != 0)
continue;
/* Any other register is bad. */
if (!object_64bit)
return FALSE;
+ if (s == NULL)
+ return FALSE;
+
/* Weak or undefined symbol need PLT32 relocation. */
if (S_IS_WEAK (s) || !S_IS_DEFINED (s))
return TRUE;
else
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[1].imms, 0, reloc (size, 0, 0, i.reloc[1]));
- if (i.op[0].imms->X_op != O_constant)
- as_bad (_("can't handle non absolute segment in `%s'"),
- i.tm.name);
- md_number_to_chars (p + size, (valueT) i.op[0].imms->X_add_number, 2);
+
+ p += size;
+ if (i.op[0].imms->X_op == O_constant)
+ md_number_to_chars (p, (valueT) i.op[0].imms->X_add_number, 2);
+ else
+ fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
+ i.op[0].imms, 0, reloc (2, 0, 0, i.reloc[0]));
}
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
if (IS_ELF && x86_used_note && now_seg != absolute_section)
{
- if (i.tm.cpu_flags.bitfield.cpucmov)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_CMOV;
- if (i.tm.cpu_flags.bitfield.cpusse)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE;
- if (i.tm.cpu_flags.bitfield.cpusse2)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE2;
- if (i.tm.cpu_flags.bitfield.cpusse3)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE3;
- if (i.tm.cpu_flags.bitfield.cpussse3)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSSE3;
- if (i.tm.cpu_flags.bitfield.cpusse4_1)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE4_1;
- if (i.tm.cpu_flags.bitfield.cpusse4_2)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_SSE4_2;
- if (i.tm.cpu_flags.bitfield.cpuavx)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX;
- if (i.tm.cpu_flags.bitfield.cpuavx2)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX2;
- if (i.tm.cpu_flags.bitfield.cpufma)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_FMA;
- if (i.tm.cpu_flags.bitfield.cpuavx512f)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512F;
- if (i.tm.cpu_flags.bitfield.cpuavx512cd)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512CD;
- if (i.tm.cpu_flags.bitfield.cpuavx512er)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512ER;
- if (i.tm.cpu_flags.bitfield.cpuavx512pf)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512PF;
- if (i.tm.cpu_flags.bitfield.cpuavx512vl)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512VL;
- if (i.tm.cpu_flags.bitfield.cpuavx512dq)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512DQ;
- if (i.tm.cpu_flags.bitfield.cpuavx512bw)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512BW;
- if (i.tm.cpu_flags.bitfield.cpuavx512_4fmaps)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS;
- if (i.tm.cpu_flags.bitfield.cpuavx512_4vnniw)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW;
- if (i.tm.cpu_flags.bitfield.cpuavx512_bitalg)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_BITALG;
- if (i.tm.cpu_flags.bitfield.cpuavx512ifma)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_IFMA;
- if (i.tm.cpu_flags.bitfield.cpuavx512vbmi)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VBMI;
- if (i.tm.cpu_flags.bitfield.cpuavx512_vbmi2)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2;
- if (i.tm.cpu_flags.bitfield.cpuavx512_vnni)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_VNNI;
- if (i.tm.cpu_flags.bitfield.cpuavx512_bf16)
- x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_AVX512_BF16;
+ if ((i.xstate & xstate_tmm) == xstate_tmm
+ || i.tm.cpu_flags.bitfield.cpuamx_tile)
+ x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_TMM;
if (i.tm.cpu_flags.bitfield.cpu8087
|| i.tm.cpu_flags.bitfield.cpu287
|| i.tm.cpu_flags.bitfield.cpu687
|| i.tm.cpu_flags.bitfield.cpufisttp)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_X87;
+
if ((i.xstate & xstate_mmx)
|| i.tm.base_opcode == 0xf77 /* emms */
|| i.tm.base_opcode == 0xf0e /* femms */)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MMX;
- if ((i.xstate & xstate_xmm))
+
+ if (i.index_reg)
+ {
+ if (i.index_reg->reg_type.bitfield.zmmword)
+ i.xstate |= xstate_zmm;
+ else if (i.index_reg->reg_type.bitfield.ymmword)
+ i.xstate |= xstate_ymm;
+ else if (i.index_reg->reg_type.bitfield.xmmword)
+ i.xstate |= xstate_xmm;
+ }
+
+ /* vzeroall / vzeroupper */
+ if (i.tm.base_opcode == 0x77 && i.tm.cpu_flags.bitfield.cpuavx)
+ i.xstate |= xstate_ymm;
+
+ if ((i.xstate & xstate_xmm)
+ /* ldmxcsr / stmxcsr */
+ || (i.tm.base_opcode == 0xfae && i.tm.cpu_flags.bitfield.cpusse)
+ /* vldmxcsr / vstmxcsr */
+ || (i.tm.base_opcode == 0xae && i.tm.cpu_flags.bitfield.cpuavx)
+ || i.tm.cpu_flags.bitfield.cpuwidekl
+ || i.tm.cpu_flags.bitfield.cpukl)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XMM;
+
if ((i.xstate & xstate_ymm) == xstate_ymm)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_YMM;
if ((i.xstate & xstate_zmm) == xstate_zmm)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_ZMM;
+ if (i.mask || (i.xstate & xstate_mask) == xstate_mask)
+ x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_MASK;
if (i.tm.cpu_flags.bitfield.cpufxsr)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_FXSR;
if (i.tm.cpu_flags.bitfield.cpuxsave)
if (i.tm.cpu_flags.bitfield.cpuxsavec)
x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_XSAVEC;
- if ((i.xstate & xstate_tmm) == xstate_tmm
- || i.tm.cpu_flags.bitfield.cpuamx_tile)
- x86_feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_TMM;
+ if (x86_feature_2_used
+ || i.tm.cpu_flags.bitfield.cpucmov
+ || i.tm.cpu_flags.bitfield.cpusyscall
+ || (i.tm.base_opcode == 0xfc7
+ && i.tm.opcode_modifier.opcodeprefix == 0
+ && i.tm.extension_opcode == 1) /* cmpxchg8b */)
+ x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_BASELINE;
+ if (i.tm.cpu_flags.bitfield.cpusse3
+ || i.tm.cpu_flags.bitfield.cpussse3
+ || i.tm.cpu_flags.bitfield.cpusse4_1
+ || i.tm.cpu_flags.bitfield.cpusse4_2
+ || i.tm.cpu_flags.bitfield.cpucx16
+ || i.tm.cpu_flags.bitfield.cpupopcnt
+ /* LAHF-SAHF insns in 64-bit mode. */
+ || (flag_code == CODE_64BIT
+ && (i.tm.base_opcode | 1) == 0x9f))
+ x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_V2;
+ if (i.tm.cpu_flags.bitfield.cpuavx
+ || i.tm.cpu_flags.bitfield.cpuavx2
+ /* Any VEX encoded insns execpt for CpuAVX512F, CpuAVX512BW,
+ CpuAVX512DQ, LPW, TBM and AMX. */
+ || (i.tm.opcode_modifier.vex
+ && !i.tm.cpu_flags.bitfield.cpuavx512f
+ && !i.tm.cpu_flags.bitfield.cpuavx512bw
+ && !i.tm.cpu_flags.bitfield.cpuavx512dq
+ && !i.tm.cpu_flags.bitfield.cpulwp
+ && !i.tm.cpu_flags.bitfield.cputbm
+ && !(x86_feature_2_used & GNU_PROPERTY_X86_FEATURE_2_TMM))
+ || i.tm.cpu_flags.bitfield.cpuf16c
+ || i.tm.cpu_flags.bitfield.cpufma
+ || i.tm.cpu_flags.bitfield.cpulzcnt
+ || i.tm.cpu_flags.bitfield.cpumovbe
+ || i.tm.cpu_flags.bitfield.cpuxsaves
+ || (x86_feature_2_used
+ & (GNU_PROPERTY_X86_FEATURE_2_XSAVE
+ | GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT
+ | GNU_PROPERTY_X86_FEATURE_2_XSAVEC)) != 0)
+ x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_V3;
+ if (i.tm.cpu_flags.bitfield.cpuavx512f
+ || i.tm.cpu_flags.bitfield.cpuavx512bw
+ || i.tm.cpu_flags.bitfield.cpuavx512dq
+ || i.tm.cpu_flags.bitfield.cpuavx512vl
+ /* Any EVEX encoded insns except for AVX512ER, AVX512PF and
+ VNNIW. */
+ || (i.tm.opcode_modifier.evex
+ && !i.tm.cpu_flags.bitfield.cpuavx512er
+ && !i.tm.cpu_flags.bitfield.cpuavx512pf
+ && !i.tm.cpu_flags.bitfield.cpuavx512_4vnniw))
+ x86_isa_1_used |= GNU_PROPERTY_X86_ISA_1_V4;
}
#endif
char *p;
unsigned char *q;
unsigned int j;
- unsigned int prefix;
enum mf_cmp_kind mf_cmp;
if (avoid_fence
don't need the explicit prefix. */
if (!i.tm.opcode_modifier.vex && !i.tm.opcode_modifier.evex)
{
- switch (i.tm.opcode_length)
+ switch (i.tm.opcode_modifier.opcodeprefix)
{
- case 3:
- if (i.tm.base_opcode & 0xff000000)
- {
- prefix = (i.tm.base_opcode >> 24) & 0xff;
- if (!i.tm.cpu_flags.bitfield.cpupadlock
- || prefix != REPE_PREFIX_OPCODE
- || (i.prefix[REP_PREFIX] != REPE_PREFIX_OPCODE))
- add_prefix (prefix);
- }
+ case PREFIX_0X66:
+ add_prefix (0x66);
break;
- case 2:
- if ((i.tm.base_opcode & 0xff0000) != 0)
+ case PREFIX_0XF2:
+ add_prefix (0xf2);
+ break;
+ case PREFIX_0XF3:
+ if (!i.tm.cpu_flags.bitfield.cpupadlock
+ || (i.prefix[REP_PREFIX] != 0xf3))
+ add_prefix (0xf3);
+ break;
+ case PREFIX_NONE:
+ switch (i.tm.opcode_length)
{
- prefix = (i.tm.base_opcode >> 16) & 0xff;
- add_prefix (prefix);
+ case 3:
+ case 2:
+ case 1:
+ break;
+ case 0:
+ /* Check for pseudo prefixes. */
+ as_bad_where (insn_start_frag->fr_file,
+ insn_start_frag->fr_line,
+ _("pseudo prefix without instruction"));
+ return;
+ default:
+ abort ();
}
break;
- case 1:
- break;
- case 0:
- /* Check for pseudo prefixes. */
- as_bad_where (insn_start_frag->fr_file,
- insn_start_frag->fr_line,
- _("pseudo prefix without instruction"));
- return;
default:
abort ();
}
int len;
const enum bfd_reloc_code_real rel[2];
const i386_operand_type types64;
+ bfd_boolean need_GOT_symbol;
} gotrel[] = {
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
{ STRING_COMMA_LEN ("SIZE"), { BFD_RELOC_SIZE32,
BFD_RELOC_SIZE32 },
- OPERAND_TYPE_IMM32_64 },
+ OPERAND_TYPE_IMM32_64, FALSE },
#endif
{ STRING_COMMA_LEN ("PLTOFF"), { _dummy_first_bfd_reloc_code_real,
BFD_RELOC_X86_64_PLTOFF64 },
- OPERAND_TYPE_IMM64 },
+ OPERAND_TYPE_IMM64, TRUE },
{ STRING_COMMA_LEN ("PLT"), { BFD_RELOC_386_PLT32,
BFD_RELOC_X86_64_PLT32 },
- OPERAND_TYPE_IMM32_32S_DISP32 },
+ OPERAND_TYPE_IMM32_32S_DISP32, FALSE },
{ STRING_COMMA_LEN ("GOTPLT"), { _dummy_first_bfd_reloc_code_real,
BFD_RELOC_X86_64_GOTPLT64 },
- OPERAND_TYPE_IMM64_DISP64 },
+ OPERAND_TYPE_IMM64_DISP64, TRUE },
{ STRING_COMMA_LEN ("GOTOFF"), { BFD_RELOC_386_GOTOFF,
BFD_RELOC_X86_64_GOTOFF64 },
- OPERAND_TYPE_IMM64_DISP64 },
+ OPERAND_TYPE_IMM64_DISP64, TRUE },
{ STRING_COMMA_LEN ("GOTPCREL"), { _dummy_first_bfd_reloc_code_real,
BFD_RELOC_X86_64_GOTPCREL },
- OPERAND_TYPE_IMM32_32S_DISP32 },
+ OPERAND_TYPE_IMM32_32S_DISP32, TRUE },
{ STRING_COMMA_LEN ("TLSGD"), { BFD_RELOC_386_TLS_GD,
BFD_RELOC_X86_64_TLSGD },
- OPERAND_TYPE_IMM32_32S_DISP32 },
+ OPERAND_TYPE_IMM32_32S_DISP32, TRUE },
{ STRING_COMMA_LEN ("TLSLDM"), { BFD_RELOC_386_TLS_LDM,
_dummy_first_bfd_reloc_code_real },
- OPERAND_TYPE_NONE },
+ OPERAND_TYPE_NONE, TRUE },
{ STRING_COMMA_LEN ("TLSLD"), { _dummy_first_bfd_reloc_code_real,
BFD_RELOC_X86_64_TLSLD },
- OPERAND_TYPE_IMM32_32S_DISP32 },
+ OPERAND_TYPE_IMM32_32S_DISP32, TRUE },
{ STRING_COMMA_LEN ("GOTTPOFF"), { BFD_RELOC_386_TLS_IE_32,
BFD_RELOC_X86_64_GOTTPOFF },
- OPERAND_TYPE_IMM32_32S_DISP32 },
+ OPERAND_TYPE_IMM32_32S_DISP32, TRUE },
{ STRING_COMMA_LEN ("TPOFF"), { BFD_RELOC_386_TLS_LE_32,
BFD_RELOC_X86_64_TPOFF32 },
- OPERAND_TYPE_IMM32_32S_64_DISP32_64 },
+ OPERAND_TYPE_IMM32_32S_64_DISP32_64, TRUE },
{ STRING_COMMA_LEN ("NTPOFF"), { BFD_RELOC_386_TLS_LE,
_dummy_first_bfd_reloc_code_real },
- OPERAND_TYPE_NONE },
+ OPERAND_TYPE_NONE, TRUE },
{ STRING_COMMA_LEN ("DTPOFF"), { BFD_RELOC_386_TLS_LDO_32,
BFD_RELOC_X86_64_DTPOFF32 },
- OPERAND_TYPE_IMM32_32S_64_DISP32_64 },
+ OPERAND_TYPE_IMM32_32S_64_DISP32_64, TRUE },
{ STRING_COMMA_LEN ("GOTNTPOFF"),{ BFD_RELOC_386_TLS_GOTIE,
_dummy_first_bfd_reloc_code_real },
- OPERAND_TYPE_NONE },
+ OPERAND_TYPE_NONE, TRUE },
{ STRING_COMMA_LEN ("INDNTPOFF"),{ BFD_RELOC_386_TLS_IE,
_dummy_first_bfd_reloc_code_real },
- OPERAND_TYPE_NONE },
+ OPERAND_TYPE_NONE, TRUE },
{ STRING_COMMA_LEN ("GOT"), { BFD_RELOC_386_GOT32,
BFD_RELOC_X86_64_GOT32 },
- OPERAND_TYPE_IMM32_32S_64_DISP32 },
+ OPERAND_TYPE_IMM32_32S_64_DISP32, TRUE },
{ STRING_COMMA_LEN ("TLSDESC"), { BFD_RELOC_386_TLS_GOTDESC,
BFD_RELOC_X86_64_GOTPC32_TLSDESC },
- OPERAND_TYPE_IMM32_32S_DISP32 },
+ OPERAND_TYPE_IMM32_32S_DISP32, TRUE },
{ STRING_COMMA_LEN ("TLSCALL"), { BFD_RELOC_386_TLS_DESC_CALL,
BFD_RELOC_X86_64_TLSDESC_CALL },
- OPERAND_TYPE_IMM32_32S_DISP32 },
+ OPERAND_TYPE_IMM32_32S_DISP32, TRUE },
};
char *cp;
unsigned int j;
*types = gotrel[j].types64;
}
- if (j != 0 && GOT_symbol == NULL)
+ if (gotrel[j].need_GOT_symbol && GOT_symbol == NULL)
GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
/* The length of the first part of our input line. */
kind = "string address";
- if (current_templates->start->opcode_modifier.repprefixok)
+ if (current_templates->start->opcode_modifier.prefixok == PrefixRep)
{
int es_op = current_templates->end[-1].opcode_modifier.isstring
- IS_STRING_ES_OP0;
&& current_templates->end[-1].operand_types[1]
.bitfield.baseindex))
op = 1;
- expected_reg = (const reg_entry *)str_hash_find (reg_hash, di_si[addr_mode][op == es_op]);
+ expected_reg
+ = (const reg_entry *) str_hash_find (reg_hash,
+ di_si[addr_mode][op == es_op]);
}
else
- expected_reg = (const reg_entry *)str_hash_find (reg_hash, bx[addr_mode]);
+ expected_reg
+ = (const reg_entry *)str_hash_find (reg_hash, bx[addr_mode]);
if (i.base_reg != expected_reg
|| i.index_reg
list = bfd_target_list ();
for (l = list; *l != NULL; l++)
- if (CONST_STRNEQ (*l, "elf64-x86-64")
+ if (startswith (*l, "elf64-x86-64")
|| strcmp (*l, "coff-x86-64") == 0
|| strcmp (*l, "pe-x86-64") == 0
|| strcmp (*l, "pei-x86-64") == 0
list = bfd_target_list ();
for (l = list; *l != NULL; l++)
- if (CONST_STRNEQ (*l, "elf32-x86-64"))
+ if (startswith (*l, "elf32-x86-64"))
{
default_arch = "x86_64:32";
break;
bfd_vma
x86_64_section_word (char *str, size_t len)
{
- if (len == 5 && flag_code == CODE_64BIT && CONST_STRNEQ (str, "large"))
+ if (len == 5 && flag_code == CODE_64BIT && startswith (str, "large"))
return SHF_X86_64_LARGE;
return -1;