Line 216... |
Line 216... |
invalid_instruction_suffix,
|
invalid_instruction_suffix,
|
bad_imm4,
|
bad_imm4,
|
old_gcc_only,
|
old_gcc_only,
|
unsupported_with_intel_mnemonic,
|
unsupported_with_intel_mnemonic,
|
unsupported_syntax,
|
unsupported_syntax,
|
unsupported
|
unsupported,
|
|
invalid_vsib_address,
|
|
unsupported_vector_index_register
|
};
|
};
|
|
|
struct _i386_insn
|
struct _i386_insn
|
{
|
{
|
/* TM holds the template for the insn were currently assembling. */
|
/* TM holds the template for the insn were currently assembling. */
|
Line 677... |
Line 679... |
CPU_SSE4_2_FLAGS, 0, 0 },
|
CPU_SSE4_2_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".nosse"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".nosse"), PROCESSOR_UNKNOWN,
|
CPU_ANY_SSE_FLAGS, 0, 1 },
|
CPU_ANY_SSE_FLAGS, 0, 1 },
|
{ STRING_COMMA_LEN (".avx"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".avx"), PROCESSOR_UNKNOWN,
|
CPU_AVX_FLAGS, 0, 0 },
|
CPU_AVX_FLAGS, 0, 0 },
|
|
{ STRING_COMMA_LEN (".avx2"), PROCESSOR_UNKNOWN,
|
|
CPU_AVX2_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".noavx"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".noavx"), PROCESSOR_UNKNOWN,
|
CPU_ANY_AVX_FLAGS, 0, 1 },
|
CPU_ANY_AVX_FLAGS, 0, 1 },
|
{ STRING_COMMA_LEN (".vmx"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".vmx"), PROCESSOR_UNKNOWN,
|
CPU_VMX_FLAGS, 0, 0 },
|
CPU_VMX_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".smx"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".smx"), PROCESSOR_UNKNOWN,
|
Line 699... |
Line 703... |
CPU_FSGSBASE_FLAGS, 0, 0 },
|
CPU_FSGSBASE_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".rdrnd"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".rdrnd"), PROCESSOR_UNKNOWN,
|
CPU_RDRND_FLAGS, 0, 0 },
|
CPU_RDRND_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".f16c"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".f16c"), PROCESSOR_UNKNOWN,
|
CPU_F16C_FLAGS, 0, 0 },
|
CPU_F16C_FLAGS, 0, 0 },
|
|
{ STRING_COMMA_LEN (".bmi2"), PROCESSOR_UNKNOWN,
|
|
CPU_BMI2_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".fma"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".fma"), PROCESSOR_UNKNOWN,
|
CPU_FMA_FLAGS, 0, 0 },
|
CPU_FMA_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".fma4"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".fma4"), PROCESSOR_UNKNOWN,
|
CPU_FMA4_FLAGS, 0, 0 },
|
CPU_FMA4_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".xop"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".xop"), PROCESSOR_UNKNOWN,
|
Line 711... |
Line 717... |
CPU_LWP_FLAGS, 0, 0 },
|
CPU_LWP_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".movbe"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".movbe"), PROCESSOR_UNKNOWN,
|
CPU_MOVBE_FLAGS, 0, 0 },
|
CPU_MOVBE_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".ept"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".ept"), PROCESSOR_UNKNOWN,
|
CPU_EPT_FLAGS, 0, 0 },
|
CPU_EPT_FLAGS, 0, 0 },
|
|
{ STRING_COMMA_LEN (".lzcnt"), PROCESSOR_UNKNOWN,
|
|
CPU_LZCNT_FLAGS, 0, 0 },
|
|
{ STRING_COMMA_LEN (".invpcid"), PROCESSOR_UNKNOWN,
|
|
CPU_INVPCID_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".clflush"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".clflush"), PROCESSOR_UNKNOWN,
|
CPU_CLFLUSH_FLAGS, 0, 0 },
|
CPU_CLFLUSH_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".nop"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".nop"), PROCESSOR_UNKNOWN,
|
CPU_NOP_FLAGS, 0, 0 },
|
CPU_NOP_FLAGS, 0, 0 },
|
{ STRING_COMMA_LEN (".syscall"), PROCESSOR_UNKNOWN,
|
{ STRING_COMMA_LEN (".syscall"), PROCESSOR_UNKNOWN,
|
Line 3832... |
Line 3842... |
/* We only support 64bit displacement on constants. */
|
/* We only support 64bit displacement on constants. */
|
i.types[op].bitfield.disp64 = 0;
|
i.types[op].bitfield.disp64 = 0;
|
}
|
}
|
}
|
}
|
|
|
|
/* Check if operands are valid for the instruction. */
|
|
|
|
static int
|
|
check_VecOperands (const insn_template *t)
|
|
{
|
|
/* Without VSIB byte, we can't have a vector register for index. */
|
|
if (!t->opcode_modifier.vecsib
|
|
&& i.index_reg
|
|
&& (i.index_reg->reg_type.bitfield.regxmm
|
|
|| i.index_reg->reg_type.bitfield.regymm))
|
|
{
|
|
i.error = unsupported_vector_index_register;
|
|
return 1;
|
|
}
|
|
|
|
/* For VSIB byte, we need a vector register for index and no PC
|
|
relative addressing is allowed. */
|
|
if (t->opcode_modifier.vecsib
|
|
&& (!i.index_reg
|
|
|| !((t->opcode_modifier.vecsib == VecSIB128
|
|
&& i.index_reg->reg_type.bitfield.regxmm)
|
|
|| (t->opcode_modifier.vecsib == VecSIB256
|
|
&& i.index_reg->reg_type.bitfield.regymm))
|
|
|| (i.base_reg && i.base_reg->reg_num == RegRip)))
|
|
{
|
|
i.error = invalid_vsib_address;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
/* Check if operands are valid for the instruction. Update VEX
|
/* Check if operands are valid for the instruction. Update VEX
|
operand types. */
|
operand types. */
|
|
|
static int
|
static int
|
VEX_check_operands (const insn_template *t)
|
VEX_check_operands (const insn_template *t)
|
Line 4168... |
Line 4210... |
{
|
{
|
found_reverse_match = 0;
|
found_reverse_match = 0;
|
continue;
|
continue;
|
}
|
}
|
|
|
|
/* Check if vector operands are valid. */
|
|
if (check_VecOperands (t))
|
|
continue;
|
|
|
/* Check if VEX operands are valid. */
|
/* Check if VEX operands are valid. */
|
if (VEX_check_operands (t))
|
if (VEX_check_operands (t))
|
continue;
|
continue;
|
|
|
/* We've found a match; break out of loop. */
|
/* We've found a match; break out of loop. */
|
Line 4214... |
Line 4260... |
err_msg = _("unsupported syntax");
|
err_msg = _("unsupported syntax");
|
break;
|
break;
|
case unsupported:
|
case unsupported:
|
err_msg = _("unsupported");
|
err_msg = _("unsupported");
|
break;
|
break;
|
|
case invalid_vsib_address:
|
|
err_msg = _("invalid VSIB address");
|
|
break;
|
|
case unsupported_vector_index_register:
|
|
err_msg = _("unsupported vector index register");
|
|
break;
|
}
|
}
|
as_bad (_("%s for `%s'"), err_msg,
|
as_bad (_("%s for `%s'"), err_msg,
|
current_templates->start->name);
|
current_templates->start->name);
|
return NULL;
|
return NULL;
|
}
|
}
|
Line 5410... |
Line 5462... |
for (op = 0; op < i.operands; op++)
|
for (op = 0; op < i.operands; op++)
|
if (operand_type_check (i.types[op], anymem))
|
if (operand_type_check (i.types[op], anymem))
|
break;
|
break;
|
gas_assert (op < i.operands);
|
gas_assert (op < i.operands);
|
|
|
|
if (i.tm.opcode_modifier.vecsib)
|
|
{
|
|
if (i.index_reg->reg_num == RegEiz
|
|
|| i.index_reg->reg_num == RegRiz)
|
|
abort ();
|
|
|
|
i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
|
|
if (!i.base_reg)
|
|
{
|
|
i.sib.base = NO_BASE_REGISTER;
|
|
i.sib.scale = i.log2_scale_factor;
|
|
i.types[op].bitfield.disp8 = 0;
|
|
i.types[op].bitfield.disp16 = 0;
|
|
i.types[op].bitfield.disp64 = 0;
|
|
if (flag_code != CODE_64BIT)
|
|
{
|
|
/* Must be 32 bit */
|
|
i.types[op].bitfield.disp32 = 1;
|
|
i.types[op].bitfield.disp32s = 0;
|
|
}
|
|
else
|
|
{
|
|
i.types[op].bitfield.disp32 = 0;
|
|
i.types[op].bitfield.disp32s = 1;
|
|
}
|
|
}
|
|
i.sib.index = i.index_reg->reg_num;
|
|
if ((i.index_reg->reg_flags & RegRex) != 0)
|
|
i.rex |= REX_X;
|
|
}
|
|
|
default_seg = &ds;
|
default_seg = &ds;
|
|
|
if (i.base_reg == 0)
|
if (i.base_reg == 0)
|
{
|
{
|
i.rm.mode = 0;
|
i.rm.mode = 0;
|
if (!i.disp_operands)
|
if (!i.disp_operands)
|
|
{
|
fake_zero_displacement = 1;
|
fake_zero_displacement = 1;
|
|
/* Instructions with VSIB byte need 32bit displacement
|
|
if there is no base register. */
|
|
if (i.tm.opcode_modifier.vecsib)
|
|
i.types[op].bitfield.disp32 = 1;
|
|
}
|
if (i.index_reg == 0)
|
if (i.index_reg == 0)
|
{
|
{
|
|
gas_assert (!i.tm.opcode_modifier.vecsib);
|
/* Operand is just <disp> */
|
/* Operand is just <disp> */
|
if (flag_code == CODE_64BIT)
|
if (flag_code == CODE_64BIT)
|
{
|
{
|
/* 64bit mode overwrites the 32bit absolute
|
/* 64bit mode overwrites the 32bit absolute
|
addressing by RIP relative addressing and
|
addressing by RIP relative addressing and
|
Line 5444... |
Line 5534... |
{
|
{
|
i.rm.regmem = NO_BASE_REGISTER;
|
i.rm.regmem = NO_BASE_REGISTER;
|
i.types[op] = disp32;
|
i.types[op] = disp32;
|
}
|
}
|
}
|
}
|
else /* !i.base_reg && i.index_reg */
|
else if (!i.tm.opcode_modifier.vecsib)
|
{
|
{
|
|
/* !i.base_reg && i.index_reg */
|
if (i.index_reg->reg_num == RegEiz
|
if (i.index_reg->reg_num == RegEiz
|
|| i.index_reg->reg_num == RegRiz)
|
|| i.index_reg->reg_num == RegRiz)
|
i.sib.index = NO_INDEX_REGISTER;
|
i.sib.index = NO_INDEX_REGISTER;
|
else
|
else
|
i.sib.index = i.index_reg->reg_num;
|
i.sib.index = i.index_reg->reg_num;
|
Line 5476... |
Line 5567... |
}
|
}
|
/* RIP addressing for 64bit mode. */
|
/* RIP addressing for 64bit mode. */
|
else if (i.base_reg->reg_num == RegRip ||
|
else if (i.base_reg->reg_num == RegRip ||
|
i.base_reg->reg_num == RegEip)
|
i.base_reg->reg_num == RegEip)
|
{
|
{
|
|
gas_assert (!i.tm.opcode_modifier.vecsib);
|
i.rm.regmem = NO_BASE_REGISTER;
|
i.rm.regmem = NO_BASE_REGISTER;
|
i.types[op].bitfield.disp8 = 0;
|
i.types[op].bitfield.disp8 = 0;
|
i.types[op].bitfield.disp16 = 0;
|
i.types[op].bitfield.disp16 = 0;
|
i.types[op].bitfield.disp32 = 0;
|
i.types[op].bitfield.disp32 = 0;
|
i.types[op].bitfield.disp32s = 1;
|
i.types[op].bitfield.disp32s = 1;
|
Line 5488... |
Line 5580... |
if (! i.disp_operands)
|
if (! i.disp_operands)
|
fake_zero_displacement = 1;
|
fake_zero_displacement = 1;
|
}
|
}
|
else if (i.base_reg->reg_type.bitfield.reg16)
|
else if (i.base_reg->reg_type.bitfield.reg16)
|
{
|
{
|
|
gas_assert (!i.tm.opcode_modifier.vecsib);
|
switch (i.base_reg->reg_num)
|
switch (i.base_reg->reg_num)
|
{
|
{
|
case 3: /* (%bx) */
|
case 3: /* (%bx) */
|
if (i.index_reg == 0)
|
if (i.index_reg == 0)
|
i.rm.regmem = 7;
|
i.rm.regmem = 7;
|
Line 5531... |
Line 5624... |
i.types[op].bitfield.disp32s = 1;
|
i.types[op].bitfield.disp32s = 1;
|
else
|
else
|
i.types[op].bitfield.disp32 = 1;
|
i.types[op].bitfield.disp32 = 1;
|
}
|
}
|
|
|
|
if (!i.tm.opcode_modifier.vecsib)
|
i.rm.regmem = i.base_reg->reg_num;
|
i.rm.regmem = i.base_reg->reg_num;
|
if ((i.base_reg->reg_flags & RegRex) != 0)
|
if ((i.base_reg->reg_flags & RegRex) != 0)
|
i.rex |= REX_B;
|
i.rex |= REX_B;
|
i.sib.base = i.base_reg->reg_num;
|
i.sib.base = i.base_reg->reg_num;
|
/* x86-64 ignores REX prefix bit here to avoid decoder
|
/* x86-64 ignores REX prefix bit here to avoid decoder
|
Line 5553... |
Line 5647... |
default_seg = &ss;
|
default_seg = &ss;
|
}
|
}
|
i.sib.scale = i.log2_scale_factor;
|
i.sib.scale = i.log2_scale_factor;
|
if (i.index_reg == 0)
|
if (i.index_reg == 0)
|
{
|
{
|
|
gas_assert (!i.tm.opcode_modifier.vecsib);
|
/* <disp>(%esp) becomes two byte modrm with no index
|
/* <disp>(%esp) becomes two byte modrm with no index
|
register. We've already stored the code for esp
|
register. We've already stored the code for esp
|
in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING.
|
in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING.
|
Any base register besides %esp will not use the
|
Any base register besides %esp will not use the
|
extra modrm byte. */
|
extra modrm byte. */
|
i.sib.index = NO_INDEX_REGISTER;
|
i.sib.index = NO_INDEX_REGISTER;
|
}
|
}
|
else
|
else if (!i.tm.opcode_modifier.vecsib)
|
{
|
{
|
if (i.index_reg->reg_num == RegEiz
|
if (i.index_reg->reg_num == RegEiz
|
|| i.index_reg->reg_num == RegRiz)
|
|| i.index_reg->reg_num == RegRiz)
|
i.sib.index = NO_INDEX_REGISTER;
|
i.sib.index = NO_INDEX_REGISTER;
|
else
|
else
|
Line 7122... |
Line 7217... |
&& !i.base_reg->reg_type.bitfield.reg32))
|
&& !i.base_reg->reg_type.bitfield.reg32))
|
&& (i.index_reg
|
&& (i.index_reg
|
|| i.base_reg->reg_num !=
|
|| i.base_reg->reg_num !=
|
(i.prefix[ADDR_PREFIX] == 0 ? RegRip : RegEip)))
|
(i.prefix[ADDR_PREFIX] == 0 ? RegRip : RegEip)))
|
|| (i.index_reg
|
|| (i.index_reg
|
|
&& !(i.index_reg->reg_type.bitfield.regxmm
|
|
|| i.index_reg->reg_type.bitfield.regymm)
|
&& (!i.index_reg->reg_type.bitfield.baseindex
|
&& (!i.index_reg->reg_type.bitfield.baseindex
|
|| (i.prefix[ADDR_PREFIX] == 0
|
|| (i.prefix[ADDR_PREFIX] == 0
|
&& i.index_reg->reg_num != RegRiz
|
&& i.index_reg->reg_num != RegRiz
|
&& !i.index_reg->reg_type.bitfield.reg64
|
&& !i.index_reg->reg_type.bitfield.reg64
|
)
|
)
|
Line 7155... |
Line 7252... |
{
|
{
|
/* 32bit checks. */
|
/* 32bit checks. */
|
if ((i.base_reg
|
if ((i.base_reg
|
&& !i.base_reg->reg_type.bitfield.reg32)
|
&& !i.base_reg->reg_type.bitfield.reg32)
|
|| (i.index_reg
|
|| (i.index_reg
|
|
&& !i.index_reg->reg_type.bitfield.regxmm
|
|
&& !i.index_reg->reg_type.bitfield.regymm
|
&& ((!i.index_reg->reg_type.bitfield.reg32
|
&& ((!i.index_reg->reg_type.bitfield.reg32
|
&& i.index_reg->reg_num != RegEiz)
|
&& i.index_reg->reg_num != RegEiz)
|
|| !i.index_reg->reg_type.bitfield.baseindex)))
|
|| !i.index_reg->reg_type.bitfield.baseindex)))
|
ok = 0;
|
ok = 0;
|
}
|
}
|