diff options
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 54 |
1 files changed, 34 insertions, 20 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 59ec771..e2c7b1b 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -229,6 +229,7 @@ struct instr_info bool b; bool no_broadcast; bool nf; + bool u; } vex; @@ -1809,8 +1810,6 @@ struct dis386 { in MAP4. "ZU" => print 'zu' if EVEX.ZU=1. "SC" => print suffix SCC for SCC insns - "SW" => print '.s' to indicate operands were swapped when suffix_always is - true. "YK" keep unused, to avoid ambiguity with the combined use of Y and K. "YX" keep unused, to avoid ambiguity with the combined use of Y and X. "LQ" => print 'l' ('d' in Intel mode) or 'q' for memory operand, cond @@ -9031,6 +9030,8 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) if (!(*ins->codep & 0x4)) ins->rex2 |= REX_X; + ins->vex.u = *ins->codep & 0x4; + switch ((*ins->codep & 0x3)) { case 0: @@ -9064,9 +9065,9 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) if (ins->address_mode != mode_64bit) { /* Report bad for !evex_default and when two fixed values of evex - change.. */ - if (ins->evex_type != evex_default - || (ins->rex2 & (REX_B | REX_X))) + change. */ + if (ins->evex_type != evex_default || (ins->rex2 & REX_B) + || ((ins->rex2 & REX_X) && (ins->modrm.mod != 3))) return &bad_opcode; /* In 16/32-bit mode silently ignore following bits. */ ins->rex &= ~REX_B; @@ -9088,14 +9089,22 @@ get_valid_dis386 (const struct dis386 *dp, instr_info *ins) if (!fetch_modrm (ins)) return &err_opcode; - if (ins->modrm.mod == 3 && (ins->rex2 & REX_X)) + /* When modrm.mod != 3, the U bit is used by APX for bit X4. + When modrm.mod == 3, the U bit is used by AVX10. The U bit and + the b bit should not be zero at the same time. */ + if (ins->modrm.mod == 3 && !ins->vex.u && !ins->vex.b) return &bad_opcode; /* Set vector length. For EVEX-promoted instructions, evex.ll == 0b00, which has the same encoding as vex.length == 128 and they can share the same processing with vex.length in OP_VEX. */ if (ins->modrm.mod == 3 && ins->vex.b && ins->evex_type != evex_from_legacy) - ins->vex.length = 512; + { + if (ins->vex.u) + ins->vex.length = 512; + else + ins->vex.length = 256; + } else { switch (ins->vex.ll) @@ -10251,9 +10260,21 @@ static const char *const scc_suffix[16] = { static void swap_operand (instr_info *ins) { - ins->mnemonicendp[0] = '.'; - ins->mnemonicendp[1] = 's'; - ins->mnemonicendp[2] = '\0'; + char *p = ins->mnemonicendp; + + if (p[-1] == '}') + { + while (*--p != '{') + { + if (p <= ins->obuf + 2) + abort (); + } + if (p[-1] == ' ') + --p; + } + memmove (p + 2, p, ins->mnemonicendp - p + 1); + p[0] = '.'; + p[1] = 's'; ins->mnemonicendp += 2; } @@ -10929,14 +10950,6 @@ putop (instr_info *ins, const char *in_template, int sizeflag) *ins->obufp++ = ins->vex.w ? 'd': 's'; else if (last[0] == 'B') *ins->obufp++ = ins->vex.w ? 'w': 'b'; - else if (last[0] == 'S') - { - if (ins->modrm.mod == 3 && (sizeflag & SUFFIX_ALWAYS)) - { - *ins->obufp++ = '.'; - *ins->obufp++ = 's'; - } - } else abort (); } @@ -12999,14 +13012,15 @@ OP_EX (instr_info *ins, int bytemode, int sizeflag) USED_REX (REX_B); if (ins->rex & REX_B) reg += 8; - if (ins->rex2 & REX_B) - reg += 16; if (ins->vex.evex) { USED_REX (REX_X); if ((ins->rex & REX_X)) reg += 16; + ins->rex2_used &= ~REX_B; } + else if (ins->rex2 & REX_B) + reg += 16; if ((sizeflag & SUFFIX_ALWAYS) && (bytemode == x_swap_mode |