diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2011-06-10 21:27:36 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2011-06-10 21:27:36 +0000 |
commit | 84bb10bcb62190a3ae93ab29d1d430d3d867a6b3 (patch) | |
tree | acad147ed247edcdc5b9005dcf054a29b5fabc77 /gas/config/tc-i386.c | |
parent | 1f1f769d367925f35765c3b683caff6e592372f3 (diff) | |
download | binutils-redhat-84bb10bcb62190a3ae93ab29d1d430d3d867a6b3.tar.gz |
Support AVX Programming Reference (June, 2011).
gas/
2011-06-10 H.J. Lu <hongjiu.lu@intel.com>
AVX Programming Reference (June, 2011)
* config/tc-i386.c (i386_error): Add invalid_vsib_address and
unsupported_vector_index_register.
(cpu_arch): Add .avx2, .bmi2, .lzcnt and .invpcid.
(check_VecOperands): New.
(match_template): Call check_VecOperands. Handle
invalid_vsib_address and unsupported_vector_index_register.
(build_modrm_byte): Support VecSIB. Check register-only source
operand when two source operands are swapped.
(i386_index_check): Allow Xmm/Ymm index registers.
* doc/c-i386.texi: Document avx2/.avx2, bmi2/.bmi2, lzcnt/.lzcnt
and invpcid./invpcid.
gas/testsuite/
2011-06-10 H.J. Lu <hongjiu.lu@intel.com>
AVX Programming Reference (June, 2011)
* gas/i386/arch-10-1.l: Updated.
* gas/i386/arch-10-2.l: Likewise.
* gas/i386/arch-10-3.l: Likewise.
* gas/i386/arch-10-4.l: Likewise.
* gas/i386/arch-10.s: Add LZCNT to comments.
* gas/i386/x86-64-arch-2.s: Likewise.
* gas/i386/arch-10-lzcnt.d: New.
* gas/i386/avx-gather-intel.d: Likewise.
* gas/i386/avx-gather.d: Likewise.
* gas/i386/avx-gather.s: Likewise.
* gas/i386/avx2-intel.d: Likewise.
* gas/i386/avx2.d: Likewise.
* gas/i386/avx2.s: Likewise
* gas/i386/avx256int-intel.d: Likewise.
* gas/i386/avx256int.d: Likewise.
* gas/i386/avx256int.s: Likewise.
* gas/i386/bmi2-intel.d: Likewise.
* gas/i386/bmi2.d: Likewise.
* gas/i386/bmi2.s: Likewise.
* gas/i386/inval-invpcid.l:Likewise.
* gas/i386/inval-invpcid.s: Likewise.
* gas/i386/invpcid-intel.d: Likewise.
* gas/i386/invpcid.d: Likewise.
* gas/i386/invpcid.s: Likewise.
* gas/i386/x86-64-arch-2-lzcnt.d: Likewise.
* gas/i386/x86-64-avx-gather-intel.d: Likewise.
* gas/i386/x86-64-avx-gather.d: Likewise.
* gas/i386/x86-64-avx-gather.s: Likewise.
* gas/i386/x86-64-avx2-intel.d: Likewise.
* gas/i386/x86-64-avx2.d: Likewise.
* gas/i386/x86-64-avx2.s: Likewise.
* gas/i386/x86-64-avx256int-intel.d: Likewise.
* gas/i386/x86-64-avx256int.d: Likewise.
* gas/i386/x86-64-avx256int.s: Likewise.
* gas/i386/x86-64-bmi2-intel.d: Likewise.
* gas/i386/x86-64-bmi2.d: Likewise.
* gas/i386/x86-64-bmi2.s: Likewise.
* gas/i386/x86-64-inval-invpcid.l: Likewise.
* gas/i386/x86-64-inval-invpcid.s: Likewise.
* gas/i386/x86-64-invpcid-intel.d: Likewise.
* gas/i386/x86-64-invpcid.d: Likewise.
* gas/i386/x86-64-invpcid.s: Likewise.
opcodes/
2011-06-10 H.J. Lu <hongjiu.lu@intel.com>
AVX Programming Reference (June, 2011)
* i386-dis.c (XMGatherQ): New.
* i386-dis.c (EXxmm_mb): New.
(EXxmm_mb): Likewise.
(EXxmm_mw): Likewise.
(EXxmm_md): Likewise.
(EXxmm_mq): Likewise.
(EXxmmdw): Likewise.
(EXxmmqd): Likewise.
(VexGatherQ): Likewise.
(MVexVSIBDWpX): Likewise.
(MVexVSIBQWpX): Likewise.
(xmm_mb_mode): Likewise.
(xmm_mw_mode): Likewise.
(xmm_md_mode): Likewise.
(xmm_mq_mode): Likewise.
(xmmdw_mode): Likewise.
(xmmqd_mode): Likewise.
(ymmxmm_mode): Likewise.
(vex_vsib_d_w_dq_mode): Likewise.
(vex_vsib_q_w_dq_mode): Likewise.
(MOD_VEX_0F385A_PREFIX_2): Likewise.
(MOD_VEX_0F388C_PREFIX_2): Likewise.
(MOD_VEX_0F388E_PREFIX_2): Likewise.
(PREFIX_0F3882): Likewise.
(PREFIX_VEX_0F3816): Likewise.
(PREFIX_VEX_0F3836): Likewise.
(PREFIX_VEX_0F3845): Likewise.
(PREFIX_VEX_0F3846): Likewise.
(PREFIX_VEX_0F3847): Likewise.
(PREFIX_VEX_0F3858): Likewise.
(PREFIX_VEX_0F3859): Likewise.
(PREFIX_VEX_0F385A): Likewise.
(PREFIX_VEX_0F3878): Likewise.
(PREFIX_VEX_0F3879): Likewise.
(PREFIX_VEX_0F388C): Likewise.
(PREFIX_VEX_0F388E): Likewise.
(PREFIX_VEX_0F3890..PREFIX_VEX_0F3893): Likewise.
(PREFIX_VEX_0F38F5): Likewise.
(PREFIX_VEX_0F38F6): Likewise.
(PREFIX_VEX_0F3A00): Likewise.
(PREFIX_VEX_0F3A01): Likewise.
(PREFIX_VEX_0F3A02): Likewise.
(PREFIX_VEX_0F3A38): Likewise.
(PREFIX_VEX_0F3A39): Likewise.
(PREFIX_VEX_0F3A46): Likewise.
(PREFIX_VEX_0F3AF0): Likewise.
(VEX_LEN_0F3816_P_2): Likewise.
(VEX_LEN_0F3819_P_2): Likewise.
(VEX_LEN_0F3836_P_2): Likewise.
(VEX_LEN_0F385A_P_2_M_0): Likewise.
(VEX_LEN_0F38F5_P_0): Likewise.
(VEX_LEN_0F38F5_P_1): Likewise.
(VEX_LEN_0F38F5_P_3): Likewise.
(VEX_LEN_0F38F6_P_3): Likewise.
(VEX_LEN_0F38F7_P_1): Likewise.
(VEX_LEN_0F38F7_P_2): Likewise.
(VEX_LEN_0F38F7_P_3): Likewise.
(VEX_LEN_0F3A00_P_2): Likewise.
(VEX_LEN_0F3A01_P_2): Likewise.
(VEX_LEN_0F3A38_P_2): Likewise.
(VEX_LEN_0F3A39_P_2): Likewise.
(VEX_LEN_0F3A46_P_2): Likewise.
(VEX_LEN_0F3AF0_P_3): Likewise.
(VEX_W_0F3816_P_2): Likewise.
(VEX_W_0F3818_P_2): Likewise.
(VEX_W_0F3819_P_2): Likewise.
(VEX_W_0F3836_P_2): Likewise.
(VEX_W_0F3846_P_2): Likewise.
(VEX_W_0F3858_P_2): Likewise.
(VEX_W_0F3859_P_2): Likewise.
(VEX_W_0F385A_P_2_M_0): Likewise.
(VEX_W_0F3878_P_2): Likewise.
(VEX_W_0F3879_P_2): Likewise.
(VEX_W_0F3A00_P_2): Likewise.
(VEX_W_0F3A01_P_2): Likewise.
(VEX_W_0F3A02_P_2): Likewise.
(VEX_W_0F3A38_P_2): Likewise.
(VEX_W_0F3A39_P_2): Likewise.
(VEX_W_0F3A46_P_2): Likewise.
(MOD_VEX_0F3818_PREFIX_2): Removed.
(MOD_VEX_0F3819_PREFIX_2): Likewise.
(VEX_LEN_0F60_P_2..VEX_LEN_0F6D_P_2): Likewise.
(VEX_LEN_0F70_P_1..VEX_LEN_0F76_P_2): Likewise.
(VEX_LEN_0FD1_P_2..VEX_LEN_0FD5_P_2): Likewise.
(VEX_LEN_0FD7_P_2_M_1..VEX_LEN_0F3819_P_2_M_0): Likewise.
(VEX_LEN_0F381C_P_2..VEX_LEN_0F3840_P_2): Likewise.
(VEX_LEN_0F3A0E_P_2): Likewise.
(VEX_LEN_0F3A0F_P_2): Likewise.
(VEX_LEN_0F3A42_P_2): Likewise.
(VEX_LEN_0F3A4C_P_2): Likewise.
(VEX_W_0F3818_P_2_M_0): Likewise.
(VEX_W_0F3819_P_2_M_0): Likewise.
(prefix_table): Updated.
(three_byte_table): Likewise.
(vex_table): Likewise.
(vex_len_table): Likewise.
(vex_w_table): Likewise.
(mod_table): Likewise.
(putop): Handle "LW".
(intel_operand_size): Handle xmm_mb_mode, xmm_mw_mode,
xmm_md_mode, xmm_mq_mode, xmmdw_mode, xmmqd_mode, ymmxmm_mode,
vex_vsib_d_w_dq_mode, vex_vsib_q_w_dq_mode.
(OP_EX): Likewise.
(OP_E_memory): Handle vex_vsib_d_w_dq_mode and
vex_vsib_q_w_dq_mode.
(OP_XMM): Handle vex_vsib_q_w_dq_mode.
(OP_VEX): Likewise.
* i386-gen.c (cpu_flag_init): Add CpuAVX2 to CPU_ANY_SSE_FLAGS
and CPU_ANY_AVX_FLAGS. Add CPU_BMI2_FLAGS, CPU_LZCNT_FLAGS,
CPU_INVPCID_FLAGS and CPU_AVX2_FLAGS.
(cpu_flags): Add CpuAVX2, CpuBMI2, CpuLZCNT and CpuINVPCID.
(opcode_modifiers): Add VecSIB.
* i386-opc.h (CpuAVX2): New.
(CpuBMI2): Likewise.
(CpuLZCNT): Likewise.
(CpuINVPCID): Likewise.
(VecSIB128): Likewise.
(VecSIB256): Likewise.
(VecSIB): Likewise.
(i386_cpu_flags): Add cpuavx2, cpubmi2, cpulzcnt and cpuinvpcid.
(i386_opcode_modifier): Add vecsib.
* i386-opc.tbl: Add invpcid, AVX2 and BMI2 instructions.
* i386-init.h: Regenerated.
* i386-tbl.h: Likewise.
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r-- | gas/config/tc-i386.c | 109 |
1 files changed, 104 insertions, 5 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 8bbf9db483..7d40bbc2bc 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -218,7 +218,9 @@ enum i386_error old_gcc_only, unsupported_with_intel_mnemonic, unsupported_syntax, - unsupported + unsupported, + invalid_vsib_address, + unsupported_vector_index_register }; struct _i386_insn @@ -679,6 +681,8 @@ static const arch_entry cpu_arch[] = CPU_ANY_SSE_FLAGS, 0, 1 }, { STRING_COMMA_LEN (".avx"), PROCESSOR_UNKNOWN, CPU_AVX_FLAGS, 0, 0 }, + { STRING_COMMA_LEN (".avx2"), PROCESSOR_UNKNOWN, + CPU_AVX2_FLAGS, 0, 0 }, { STRING_COMMA_LEN (".noavx"), PROCESSOR_UNKNOWN, CPU_ANY_AVX_FLAGS, 0, 1 }, { STRING_COMMA_LEN (".vmx"), PROCESSOR_UNKNOWN, @@ -701,6 +705,8 @@ static const arch_entry cpu_arch[] = CPU_RDRND_FLAGS, 0, 0 }, { STRING_COMMA_LEN (".f16c"), PROCESSOR_UNKNOWN, CPU_F16C_FLAGS, 0, 0 }, + { STRING_COMMA_LEN (".bmi2"), PROCESSOR_UNKNOWN, + CPU_BMI2_FLAGS, 0, 0 }, { STRING_COMMA_LEN (".fma"), PROCESSOR_UNKNOWN, CPU_FMA_FLAGS, 0, 0 }, { STRING_COMMA_LEN (".fma4"), PROCESSOR_UNKNOWN, @@ -713,6 +719,10 @@ static const arch_entry cpu_arch[] = CPU_MOVBE_FLAGS, 0, 0 }, { STRING_COMMA_LEN (".ept"), PROCESSOR_UNKNOWN, 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, CPU_CLFLUSH_FLAGS, 0, 0 }, { STRING_COMMA_LEN (".nop"), PROCESSOR_UNKNOWN, @@ -3834,6 +3844,38 @@ optimize_disp (void) } } +/* 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 operand types. */ @@ -4170,6 +4212,10 @@ check_reverse: continue; } + /* Check if vector operands are valid. */ + if (check_VecOperands (t)) + continue; + /* Check if VEX operands are valid. */ if (VEX_check_operands (t)) continue; @@ -4216,6 +4262,12 @@ check_reverse: case unsupported: err_msg = _("unsupported"); 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, current_templates->start->name); @@ -5412,15 +5464,53 @@ build_modrm_byte (void) break; 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; if (i.base_reg == 0) { i.rm.mode = 0; 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) { + gas_assert (!i.tm.opcode_modifier.vecsib); /* Operand is just <disp> */ if (flag_code == CODE_64BIT) { @@ -5446,8 +5536,9 @@ build_modrm_byte (void) 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 || i.index_reg->reg_num == RegRiz) i.sib.index = NO_INDEX_REGISTER; @@ -5478,6 +5569,7 @@ build_modrm_byte (void) else if (i.base_reg->reg_num == RegRip || i.base_reg->reg_num == RegEip) { + gas_assert (!i.tm.opcode_modifier.vecsib); i.rm.regmem = NO_BASE_REGISTER; i.types[op].bitfield.disp8 = 0; i.types[op].bitfield.disp16 = 0; @@ -5490,6 +5582,7 @@ build_modrm_byte (void) } else if (i.base_reg->reg_type.bitfield.reg16) { + gas_assert (!i.tm.opcode_modifier.vecsib); switch (i.base_reg->reg_num) { case 3: /* (%bx) */ @@ -5533,7 +5626,8 @@ build_modrm_byte (void) i.types[op].bitfield.disp32 = 1; } - i.rm.regmem = i.base_reg->reg_num; + if (!i.tm.opcode_modifier.vecsib) + i.rm.regmem = i.base_reg->reg_num; if ((i.base_reg->reg_flags & RegRex) != 0) i.rex |= REX_B; i.sib.base = i.base_reg->reg_num; @@ -5555,6 +5649,7 @@ build_modrm_byte (void) i.sib.scale = i.log2_scale_factor; if (i.index_reg == 0) { + gas_assert (!i.tm.opcode_modifier.vecsib); /* <disp>(%esp) becomes two byte modrm with no index register. We've already stored the code for esp in i.rm.regmem ie. ESCAPE_TO_TWO_BYTE_ADDRESSING. @@ -5562,7 +5657,7 @@ build_modrm_byte (void) extra modrm byte. */ i.sib.index = NO_INDEX_REGISTER; } - else + else if (!i.tm.opcode_modifier.vecsib) { if (i.index_reg->reg_num == RegEiz || i.index_reg->reg_num == RegRiz) @@ -7124,6 +7219,8 @@ i386_index_check (const char *operand_string) || i.base_reg->reg_num != (i.prefix[ADDR_PREFIX] == 0 ? RegRip : RegEip))) || (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.prefix[ADDR_PREFIX] == 0 && i.index_reg->reg_num != RegRiz @@ -7157,6 +7254,8 @@ i386_index_check (const char *operand_string) if ((i.base_reg && !i.base_reg->reg_type.bitfield.reg32) || (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_num != RegEiz) || !i.index_reg->reg_type.bitfield.baseindex))) |