aboutsummaryrefslogtreecommitdiff
path: root/opcodes/i386-dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r--opcodes/i386-dis.c83
1 files changed, 69 insertions, 14 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 9c5063e..e2c7b1b 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -107,6 +107,7 @@ static bool DistinctDest_Fixup (instr_info *, int, int);
static bool PREFETCHI_Fixup (instr_info *, int, int);
static bool PUSH2_POP2_Fixup (instr_info *, int, int);
static bool JMPABS_Fixup (instr_info *, int, int);
+static bool CFCMOV_Fixup (instr_info *, int, int);
static void ATTRIBUTE_PRINTF_3 i386_dis_printf (const disassemble_info *,
enum disassembler_style,
@@ -228,6 +229,7 @@ struct instr_info
bool b;
bool no_broadcast;
bool nf;
+ bool u;
}
vex;
@@ -4041,7 +4043,7 @@ static const struct dis386 prefix_table[][4] = {
{ "vbcstnebf162ps", { XM, Mw }, 0 },
{ "vbcstnesh2ps", { XM, Mw }, 0 },
},
-
+
/* PREFIX_VEX_0F38D2_W_0 */
{
{ "vpdpwuud", { XM, Vex, EXx }, 0 },
@@ -9028,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:
@@ -9061,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;
@@ -9085,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)
@@ -10248,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;
}
@@ -10560,7 +10584,14 @@ putop (instr_info *ins, const char *in_template, int sizeflag)
}
}
else if (l == 1 && last[0] == 'C')
- break;
+ {
+ if (ins->vex.nd && !ins->vex.nf)
+ break;
+ *ins->obufp++ = 'c';
+ *ins->obufp++ = 'f';
+ /* Skip printing {evex} */
+ evex_printed = true;
+ }
else if (l == 1 && last[0] == 'N')
{
if (ins->vex.nf)
@@ -12397,9 +12428,9 @@ OP_I (instr_info *ins, int bytemode, int sizeflag)
break;
case const_1_mode:
if (ins->intel_syntax)
- oappend (ins, "1");
+ oappend_with_style (ins, "1", dis_style_immediate);
else
- oappend (ins, "$1");
+ oappend_with_style (ins, "$1", dis_style_immediate);
return true;
default:
oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
@@ -12981,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
@@ -14040,3 +14072,26 @@ JMPABS_Fixup (instr_info *ins, int bytemode, int sizeflag)
return OP_IMREG (ins, bytemode, sizeflag);
return OP_OFF64 (ins, bytemode, sizeflag);
}
+
+static bool
+CFCMOV_Fixup (instr_info *ins, int opnd, int sizeflag)
+{
+ /* EVEX.NF is used as a direction bit in the 2-operand case to reverse the
+ source and destination operands. */
+ bool dstmem = !ins->vex.nd && ins->vex.nf;
+
+ if (opnd == 0)
+ {
+ if (dstmem)
+ return OP_E (ins, v_swap_mode, sizeflag);
+ return OP_G (ins, v_mode, sizeflag);
+ }
+
+ /* These bits have been consumed and should be cleared. */
+ ins->vex.nf = false;
+ ins->vex.mask_register_specifier = 0;
+
+ if (dstmem)
+ return OP_G (ins, v_mode, sizeflag);
+ return OP_E (ins, v_mode, sizeflag);
+}