diff options
author | Lili Cui <lili.cui@intel.com> | 2020-07-10 05:17:29 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2020-07-10 05:18:34 -0700 |
commit | 260cd341da23b7551e11719fb55f1d2f23523082 (patch) | |
tree | f03e517ffdaf36cf7ab838b48374b2e9905d3c1b /gas/config | |
parent | af2b31864802e6ca75b2c98ce4a4a7deb9d5c608 (diff) | |
download | gdb-260cd341da23b7551e11719fb55f1d2f23523082.zip gdb-260cd341da23b7551e11719fb55f1d2f23523082.tar.gz gdb-260cd341da23b7551e11719fb55f1d2f23523082.tar.bz2 |
x86: Add support for Intel AMX instructions
gas/
* doc/c-i386.texi: Document amx_int8, amx_bf16 and amx_tile.
* config/tc-i386.c (i386_error): Add invalid_sib_address.
(cpu_arch): Add .amx_int8, .amx_bf16 and .amx_tile.
(cpu_noarch): Add noamx_int8, noamx_bf16 and noamx_tile.
(match_simd_size): Add tmmword check.
(operand_type_match): Add tmmword.
(type_names): Add rTMM.
(i386_error): Add invalid_tmm_register_set.
(check_VecOperands): Handle invalid_sib_address and
invalid_tmm_register_set.
(match_template): Handle invalid_sib_address.
(build_modrm_byte): Handle non-vector SIB and zmmword.
(i386_index_check): Disallow RegIP for non-vector SIB.
(check_register): Handle zmmword.
* testsuite/gas/i386/i386.exp: Add AMX new tests.
* testsuite/gas/i386/intel-regs.d: Add tmm.
* testsuite/gas/i386/intel-regs.s: Add tmm.
* testsuite/gas/i386/x86-64-amx-intel.d: New.
* testsuite/gas/i386/x86-64-amx-inval.l: New.
* testsuite/gas/i386/x86-64-amx-inval.s: New.
* testsuite/gas/i386/x86-64-amx.d: New.
* testsuite/gas/i386/x86-64-amx.s: New.
* testsuite/gas/i386/x86-64-amx-bad.d: New.
* testsuite/gas/i386/x86-64-amx-bad.s: New.
opcodes/
* i386-dis.c (TMM): New.
(EXtmm): Likewise.
(VexTmm): Likewise.
(MVexSIBMEM): Likewise.
(tmm_mode): Likewise.
(vex_sibmem_mode): Likewise.
(REG_VEX_0F3849_X86_64_P_0_W_0_M_1): Likewise.
(MOD_VEX_0F3849_X86_64_P_0_W_0): Likewise.
(MOD_VEX_0F3849_X86_64_P_2_W_0): Likewise.
(MOD_VEX_0F3849_X86_64_P_3_W_0): Likewise.
(MOD_VEX_0F384B_X86_64_P_1_W_0): Likewise.
(MOD_VEX_0F384B_X86_64_P_2_W_0): Likewise.
(MOD_VEX_0F384B_X86_64_P_3_W_0): Likewise.
(MOD_VEX_0F385C_X86_64_P_1_W_0): Likewise.
(MOD_VEX_0F385E_X86_64_P_0_W_0): Likewise.
(MOD_VEX_0F385E_X86_64_P_1_W_0): Likewise.
(MOD_VEX_0F385E_X86_64_P_2_W_0): Likewise.
(MOD_VEX_0F385E_X86_64_P_3_W_0): Likewise.
(RM_VEX_0F3849_X86_64_P_0_W_0_M_1_R_0): Likewise.
(PREFIX_VEX_0F3849_X86_64): Likewise.
(PREFIX_VEX_0F384B_X86_64): Likewise.
(PREFIX_VEX_0F385C_X86_64): Likewise.
(PREFIX_VEX_0F385E_X86_64): Likewise.
(X86_64_VEX_0F3849): Likewise.
(X86_64_VEX_0F384B): Likewise.
(X86_64_VEX_0F385C): Likewise.
(X86_64_VEX_0F385E): Likewise.
(VEX_LEN_0F3849_X86_64_P_0_W_0_M_0): Likewise.
(VEX_LEN_0F3849_X86_64_P_0_W_0_M_1_REG_0_RM_0): Likewise.
(VEX_LEN_0F3849_X86_64_P_2_W_0_M_0): Likewise.
(VEX_LEN_0F3849_X86_64_P_3_W_0_M_0): Likewise.
(VEX_LEN_0F384B_X86_64_P_1_W_0_M_0): Likewise.
(VEX_LEN_0F384B_X86_64_P_2_W_0_M_0): Likewise.
(VEX_LEN_0F384B_X86_64_P_3_W_0_M_0): Likewise.
(VEX_LEN_0F385C_X86_64_P_1_W_0_M_0): Likewise.
(VEX_LEN_0F385E_X86_64_P_0_W_0_M_0): Likewise.
(VEX_LEN_0F385E_X86_64_P_1_W_0_M_0): Likewise.
(VEX_LEN_0F385E_X86_64_P_2_W_0_M_0): Likewise.
(VEX_LEN_0F385E_X86_64_P_3_W_0_M_0): Likewise.
(VEX_W_0F3849_X86_64_P_0): Likewise.
(VEX_W_0F3849_X86_64_P_2): Likewise.
(VEX_W_0F3849_X86_64_P_3): Likewise.
(VEX_W_0F384B_X86_64_P_1): Likewise.
(VEX_W_0F384B_X86_64_P_2): Likewise.
(VEX_W_0F384B_X86_64_P_3): Likewise.
(VEX_W_0F385C_X86_64_P_1): Likewise.
(VEX_W_0F385E_X86_64_P_0): Likewise.
(VEX_W_0F385E_X86_64_P_1): Likewise.
(VEX_W_0F385E_X86_64_P_2): Likewise.
(VEX_W_0F385E_X86_64_P_3): Likewise.
(names_tmm): Likewise.
(att_names_tmm): Likewise.
(intel_operand_size): Handle void_mode.
(OP_XMM): Handle tmm_mode.
(OP_EX): Likewise.
(OP_VEX): Likewise.
* i386-gen.c (cpu_flag_init): Add entries for CpuAMX_INT8,
CpuAMX_BF16 and CpuAMX_TILE.
(operand_type_shorthands): Add RegTMM.
(operand_type_init): Likewise.
(operand_types): Add Tmmword.
(cpu_flag_init): Add CPU_AMX_INT8, CpuAMX_BF16 and CpuAMX_TILE.
(cpu_flags): Add CpuAMX_INT8, CpuAMX_BF16 and CpuAMX_TILE.
* i386-opc.h (CpuAMX_INT8): New.
(CpuAMX_BF16): Likewise.
(CpuAMX_TILE): Likewise.
(SIBMEM): Likewise.
(Tmmword): Likewise.
(i386_cpu_flags): Add cpuamx_int8, cpuamx_bf16 and cpuamx_tile.
(i386_opcode_modifier): Extend width of fields vexvvvv and sib.
(i386_operand_type): Add tmmword.
* i386-opc.tbl: Add AMX instructions.
* i386-reg.tbl: Add AMX registers.
* i386-init.h: Regenerated.
* i386-tbl.h: Likewise.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-i386.c | 97 |
1 files changed, 84 insertions, 13 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index bb51133..0e42914 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -290,8 +290,10 @@ enum i386_error unsupported_with_intel_mnemonic, unsupported_syntax, unsupported, + invalid_sib_address, invalid_vsib_address, invalid_vector_register_set, + invalid_tmm_register_set, unsupported_vector_index_register, unsupported_broadcast, broadcast_needed, @@ -372,6 +374,9 @@ struct _i386_insn /* Has ZMM register operands. */ bfd_boolean has_regzmm; + /* Has TMM register operands. */ + bfd_boolean has_regtmm; + /* Has GOTPC or TLS relocation. */ bfd_boolean has_gotpc_tls_reloc; @@ -1201,6 +1206,12 @@ static const arch_entry cpu_arch[] = CPU_WAITPKG_FLAGS, 0 }, { STRING_COMMA_LEN (".cldemote"), PROCESSOR_UNKNOWN, CPU_CLDEMOTE_FLAGS, 0 }, + { STRING_COMMA_LEN (".amx_int8"), PROCESSOR_UNKNOWN, + CPU_AMX_INT8_FLAGS, 0 }, + { STRING_COMMA_LEN (".amx_bf16"), PROCESSOR_UNKNOWN, + CPU_AMX_BF16_FLAGS, 0 }, + { STRING_COMMA_LEN (".amx_tile"), PROCESSOR_UNKNOWN, + CPU_AMX_TILE_FLAGS, 0 }, { STRING_COMMA_LEN (".movdiri"), PROCESSOR_UNKNOWN, CPU_MOVDIRI_FLAGS, 0 }, { STRING_COMMA_LEN (".movdir64b"), PROCESSOR_UNKNOWN, @@ -1259,6 +1270,9 @@ static const noarch_entry cpu_noarch[] = { STRING_COMMA_LEN ("noavx512_bitalg"), CPU_ANY_AVX512_BITALG_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 ("noamx_bf16"), CPU_ANY_AMX_BF16_FLAGS }, + { STRING_COMMA_LEN ("noamx_tile"), CPU_ANY_AMX_TILE_FLAGS }, { STRING_COMMA_LEN ("nomovdiri"), CPU_ANY_MOVDIRI_FLAGS }, { STRING_COMMA_LEN ("nomovdir64b"), CPU_ANY_MOVDIR64B_FLAGS }, { STRING_COMMA_LEN ("noavx512_bf16"), CPU_ANY_AVX512_BF16_FLAGS }, @@ -2159,7 +2173,9 @@ match_simd_size (const insn_template *t, unsigned int wanted, || (i.types[given].bitfield.ymmword && !t->operand_types[wanted].bitfield.ymmword) || (i.types[given].bitfield.zmmword - && !t->operand_types[wanted].bitfield.zmmword)); + && !t->operand_types[wanted].bitfield.zmmword) + || (i.types[given].bitfield.tmmword + && !t->operand_types[wanted].bitfield.tmmword)); } /* Return 1 if there is no conflict in any size between operand GIVEN @@ -2296,6 +2312,7 @@ operand_type_match (i386_operand_type overlap, temp.bitfield.xmmword = 0; temp.bitfield.ymmword = 0; temp.bitfield.zmmword = 0; + temp.bitfield.tmmword = 0; if (operand_type_all_zero (&temp)) goto mismatch; @@ -3304,6 +3321,7 @@ const type_names[] = { OPERAND_TYPE_REGXMM, "rXMM" }, { OPERAND_TYPE_REGYMM, "rYMM" }, { OPERAND_TYPE_REGZMM, "rZMM" }, + { OPERAND_TYPE_REGTMM, "rTMM" }, { OPERAND_TYPE_REGMASK, "Mask reg" }, }; @@ -5790,7 +5808,7 @@ check_VecOperands (const insn_template *t) /* For VSIB byte, we need a vector register for index, and all vector registers must be distinct. */ - if (t->opcode_modifier.sib) + if (t->opcode_modifier.sib && t->opcode_modifier.sib != SIBMEM) { if (!i.index_reg || !((t->opcode_modifier.sib == VECSIB128 @@ -5849,6 +5867,23 @@ check_VecOperands (const insn_template *t) } } + /* For AMX instructions with three tmmword operands, all tmmword operand must be + distinct */ + if (t->operand_types[0].bitfield.tmmword + && i.reg_operands == 3) + { + if (register_number (i.op[0].regs) + == register_number (i.op[1].regs) + || register_number (i.op[0].regs) + == register_number (i.op[2].regs) + || register_number (i.op[1].regs) + == register_number (i.op[2].regs)) + { + i.error = invalid_tmm_register_set; + return 1; + } + } + /* Check if broadcast is supported by the instruction and is applied to the memory operand. */ if (i.broadcast) @@ -6584,12 +6619,18 @@ match_template (char mnem_suffix) as_bad (_("unsupported instruction `%s'"), current_templates->start->name); return NULL; + case invalid_sib_address: + err_msg = _("invalid SIB address"); + break; case invalid_vsib_address: err_msg = _("invalid VSIB address"); break; case invalid_vector_register_set: err_msg = _("mask, index, and destination registers must be distinct"); break; + case invalid_tmm_register_set: + err_msg = _("all tmm registers must be distinct"); + break; case unsupported_vector_index_register: err_msg = _("unsupported vector index register"); break; @@ -7923,8 +7964,11 @@ build_modrm_byte (void) else if (i.op[dest].regs->reg_type.bitfield.class == RegSIMD || i.op[source].regs->reg_type.bitfield.class == RegSIMD) { - if (i.types[dest].bitfield.zmmword - || i.types[source].bitfield.zmmword) + if (i.types[dest].bitfield.tmmword + || i.types[source].bitfield.tmmword) + i.has_regtmm = TRUE; + else if (i.types[dest].bitfield.zmmword + || i.types[source].bitfield.zmmword) i.has_regzmm = TRUE; else if (i.types[dest].bitfield.ymmword || i.types[source].bitfield.ymmword) @@ -7966,7 +8010,9 @@ build_modrm_byte (void) if (i.tm.opcode_modifier.sib) { - if (i.index_reg->reg_num == RegIZ) + /* The index register of VSIB shouldn't be RegIZ. */ + if (i.tm.opcode_modifier.sib != SIBMEM + && i.index_reg->reg_num == RegIZ) abort (); i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; @@ -7989,8 +8035,19 @@ build_modrm_byte (void) i.types[op].bitfield.disp32s = 1; } } - i.sib.index = i.index_reg->reg_num; - set_rex_vrex (i.index_reg, REX_X, FALSE); + + /* Since the mandatory SIB always has index register, so + the code logic remains unchanged. The non-mandatory SIB + without index register is allowed and will be handled + later. */ + if (i.index_reg) + { + if (i.index_reg->reg_num == RegIZ) + i.sib.index = NO_INDEX_REGISTER; + else + i.sib.index = i.index_reg->reg_num; + set_rex_vrex (i.index_reg, REX_X, FALSE); + } } default_seg = &ds; @@ -8004,7 +8061,9 @@ build_modrm_byte (void) { i386_operand_type newdisp; - gas_assert (!i.tm.opcode_modifier.sib); + /* Both check for VSIB and mandatory non-vector SIB. */ + gas_assert (!i.tm.opcode_modifier.sib + || i.tm.opcode_modifier.sib == SIBMEM); /* Operand is just <disp> */ if (flag_code == CODE_64BIT) { @@ -8142,7 +8201,11 @@ build_modrm_byte (void) i.sib.scale = i.log2_scale_factor; if (i.index_reg == 0) { - gas_assert (!i.tm.opcode_modifier.sib); + /* Only check for VSIB. */ + gas_assert (i.tm.opcode_modifier.sib != VECSIB128 + && i.tm.opcode_modifier.sib != VECSIB256 + && i.tm.opcode_modifier.sib != VECSIB512); + /* <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. @@ -8267,7 +8330,9 @@ build_modrm_byte (void) break; if (i.types[op].bitfield.class == RegSIMD) { - if (i.types[op].bitfield.zmmword) + if (i.types[op].bitfield.tmmword) + i.has_regtmm = TRUE; + else if (i.types[op].bitfield.zmmword) i.has_regzmm = TRUE; else if (i.types[op].bitfield.ymmword) i.has_regymm = TRUE; @@ -10931,9 +10996,10 @@ i386_index_check (const char *operand_string) || !i.index_reg->reg_type.bitfield.baseindex))) goto bad_address; - /* bndmk, bndldx, and bndstx have special restrictions. */ + /* bndmk, bndldx, bndstx and mandatory non-vector SIB have special restrictions. */ if (current_templates->start->base_opcode == 0xf30f1b - || (current_templates->start->base_opcode & ~1) == 0x0f1a) + || (current_templates->start->base_opcode & ~1) == 0x0f1a + || current_templates->start->opcode_modifier.sib == SIBMEM) { /* They cannot use RIP-relative addressing. */ if (i.base_reg && i.base_reg->reg_num == RegIP) @@ -10943,7 +11009,7 @@ i386_index_check (const char *operand_string) } /* bndldx and bndstx ignore their scale factor. */ - if (current_templates->start->base_opcode != 0xf30f1b + if ((current_templates->start->base_opcode & ~1) == 0x0f1a && i.log2_scale_factor) as_warn (_("register scaling is being ignored here")); } @@ -12445,6 +12511,11 @@ static bfd_boolean check_register (const reg_entry *r) } } + if (r->reg_type.bitfield.tmmword + && (!cpu_arch_flags.bitfield.cpuamx_tile + || flag_code != CODE_64BIT)) + return FALSE; + if (r->reg_type.bitfield.class == RegBND && !cpu_arch_flags.bitfield.cpumpx) return FALSE; |