forked from Imagelibrary/binutils-gdb
gas/
2008-04-18 H.J. Lu <hongjiu.lu@intel.com> * config/tc-i386.c (build_modrm_byte): Swap REG and NDS for FMA. gas/testsuite/ 2008-04-18 H.J. Lu <hongjiu.lu@intel.com> * gas/i386/arch-10.d: Updated. * gas/i386/avx.d: Likewise. * gas/i386/avx-intel.d: Likewise. * gas/i386/x86-64-arch-2.d: Likewise. * gas/i386/x86-64-avx.d: Likewise. * gas/i386/x86-64-avx-intel.d: Likewise. opcodes/ 2008-04-18 H.J. Lu <hongjiu.lu@intel.com> * i386-dis.c (OP_VEX_FMA): New. (OP_EX_VexImmW): Likewise. (VexFMA): Likewise. (Vex128FMA): Likewise. (EXVexImmW): Likewise. (get_vex_imm8): Likewise. (OP_EX_VexReg): Likewise. (vex_i4_done): Renamed to ... (vex_w_done): This. (prefix_table): Replace EXVexW with EXVexImmW on vpermil2ps and vpermil2pd. Replace Vex/Vex128 with VexFMA/Vex128FMA on FMA instructions. (print_insn): Updated. (OP_EX_VexW): Rewrite to swap register in VEX with EX. (OP_REG_VexI4): Check invalid high registers.
This commit is contained in:
@@ -1,3 +1,21 @@
|
||||
2008-04-18 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* i386-dis.c (OP_VEX_FMA): New.
|
||||
(OP_EX_VexImmW): Likewise.
|
||||
(VexFMA): Likewise.
|
||||
(Vex128FMA): Likewise.
|
||||
(EXVexImmW): Likewise.
|
||||
(get_vex_imm8): Likewise.
|
||||
(OP_EX_VexReg): Likewise.
|
||||
(vex_i4_done): Renamed to ...
|
||||
(vex_w_done): This.
|
||||
(prefix_table): Replace EXVexW with EXVexImmW on vpermil2ps
|
||||
and vpermil2pd. Replace Vex/Vex128 with VexFMA/Vex128FMA on
|
||||
FMA instructions.
|
||||
(print_insn): Updated.
|
||||
(OP_EX_VexW): Rewrite to swap register in VEX with EX.
|
||||
(OP_REG_VexI4): Check invalid high registers.
|
||||
|
||||
2008-04-16 Dwarakanath Rajagopal <dwarak.rajagopal@amd.com>
|
||||
Michael Meissner <michael.meissner@amd.com>
|
||||
|
||||
|
||||
@@ -92,8 +92,10 @@ static void OP_MS (int, int);
|
||||
static void OP_XS (int, int);
|
||||
static void OP_M (int, int);
|
||||
static void OP_VEX (int, int);
|
||||
static void OP_VEX_FMA (int, int);
|
||||
static void OP_EX_Vex (int, int);
|
||||
static void OP_EX_VexW (int, int);
|
||||
static void OP_EX_VexImmW (int, int);
|
||||
static void OP_XMM_Vex (int, int);
|
||||
static void OP_XMM_VexW (int, int);
|
||||
static void OP_REG_VexI4 (int, int);
|
||||
@@ -371,11 +373,14 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
|
||||
#define Vex128 { OP_VEX, vex128_mode }
|
||||
#define Vex256 { OP_VEX, vex256_mode }
|
||||
#define VexI4 { VEXI4_Fixup, 0}
|
||||
#define VexFMA { OP_VEX_FMA, vex_mode }
|
||||
#define Vex128FMA { OP_VEX_FMA, vex128_mode }
|
||||
#define EXdVex { OP_EX_Vex, d_mode }
|
||||
#define EXqVex { OP_EX_Vex, q_mode }
|
||||
#define EXVexW { OP_EX_VexW, x_mode }
|
||||
#define EXdVexW { OP_EX_VexW, d_mode }
|
||||
#define EXqVexW { OP_EX_VexW, q_mode }
|
||||
#define EXVexImmW { OP_EX_VexImmW, x_mode }
|
||||
#define XMVex { OP_XMM_Vex, 0 }
|
||||
#define XMVexW { OP_XMM_VexW, 0 }
|
||||
#define XMVexI4 { OP_REG_VexI4, x_mode }
|
||||
@@ -1937,7 +1942,7 @@ static struct
|
||||
vex;
|
||||
static unsigned char need_vex;
|
||||
static unsigned char need_vex_reg;
|
||||
static unsigned char vex_i4_done;
|
||||
static unsigned char vex_w_done;
|
||||
|
||||
/* If we are accessing mod/rm/reg without need_modrm set, then the
|
||||
values are stale. Hitting this abort likely indicates that you
|
||||
@@ -4698,7 +4703,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vpermil2ps", { XMVexW, Vex, EXVexW, EXVexW, VPERMIL2 } },
|
||||
{ "vpermil2ps", { XMVexW, Vex, EXVexImmW, EXVexImmW, VPERMIL2 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4706,7 +4711,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vpermil2pd", { XMVexW, Vex, EXVexW, EXVexW, VPERMIL2 } },
|
||||
{ "vpermil2pd", { XMVexW, Vex, EXVexImmW, EXVexImmW, VPERMIL2 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4738,7 +4743,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmaddsubps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmaddsubps", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4746,7 +4751,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmaddsubpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmaddsubpd", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4754,7 +4759,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmsubaddps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmsubaddps", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4762,7 +4767,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmsubaddpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmsubaddpd", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4802,7 +4807,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmaddps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmaddps", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4810,7 +4815,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmaddpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmaddpd", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4834,7 +4839,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmsubps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmsubps", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4842,7 +4847,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfmsubpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfmsubpd", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4866,7 +4871,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfnmaddps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfnmaddps", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4874,7 +4879,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfnmaddpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfnmaddpd", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4898,7 +4903,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfnmsubps", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfnmsubps", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -4906,7 +4911,7 @@ static const struct dis386 prefix_table[][4] = {
|
||||
{
|
||||
{ "(bad)", { XX } },
|
||||
{ "(bad)", { XX } },
|
||||
{ "vfnmsubpd", { XMVexW, Vex, EXVexW, EXVexW, VexI4 } },
|
||||
{ "vfnmsubpd", { XMVexW, VexFMA, EXVexW, EXVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
@@ -8859,49 +8864,49 @@ static const struct dis386 vex_len_table[][2] = {
|
||||
|
||||
/* VEX_LEN_3A6A_P_2 */
|
||||
{
|
||||
{ "vfmaddss", { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "vfmaddss", { XMVexW, Vex128FMA, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
/* VEX_LEN_3A6B_P_2 */
|
||||
{
|
||||
{ "vfmaddsd", { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "vfmaddsd", { XMVexW, Vex128FMA, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
/* VEX_LEN_3A6E_P_2 */
|
||||
{
|
||||
{ "vfmsubss", { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "vfmsubss", { XMVexW, Vex128FMA, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
/* VEX_LEN_3A6F_P_2 */
|
||||
{
|
||||
{ "vfmsubsd", { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "vfmsubsd", { XMVexW, Vex128FMA, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
/* VEX_LEN_3A7A_P_2 */
|
||||
{
|
||||
{ "vfnmaddss", { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "vfnmaddss", { XMVexW, Vex128FMA, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
/* VEX_LEN_3A7B_P_2 */
|
||||
{
|
||||
{ "vfnmaddsd", { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "vfnmaddsd", { XMVexW, Vex128FMA, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
/* VEX_LEN_3A7E_P_2 */
|
||||
{
|
||||
{ "vfnmsubss", { XMVexW, Vex128, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "vfnmsubss", { XMVexW, Vex128FMA, EXdVexW, EXdVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
|
||||
/* VEX_LEN_3A7F_P_2 */
|
||||
{
|
||||
{ "vfnmsubsd", { XMVexW, Vex128, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "vfnmsubsd", { XMVexW, Vex128FMA, EXqVexW, EXqVexW, VexI4 } },
|
||||
{ "(bad)", { XX } },
|
||||
},
|
||||
};
|
||||
@@ -10184,7 +10189,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
|
||||
{
|
||||
need_vex = 0;
|
||||
need_vex_reg = 0;
|
||||
vex_i4_done = 0;
|
||||
vex_w_done = 0;
|
||||
dp = get_valid_dis386 (dp, info);
|
||||
if (dp != NULL && putop (dp->name, sizeflag) == 0)
|
||||
{
|
||||
@@ -13276,88 +13281,79 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
|
||||
oappend (scratchbuf + intel_syntax);
|
||||
}
|
||||
|
||||
static void
|
||||
OP_EX_VexW (int bytemode, int sizeflag)
|
||||
/* Get the VEX immediate byte without moving codep. */
|
||||
|
||||
static unsigned char
|
||||
get_vex_imm8 (int sizeflag)
|
||||
{
|
||||
int reg = -1;
|
||||
static unsigned char vex_i4;
|
||||
int bytes_before_imm = 0;
|
||||
|
||||
if (!vex_i4_done)
|
||||
/* Skip mod/rm byte. */
|
||||
MODRM_CHECK;
|
||||
codep++;
|
||||
|
||||
if (modrm.mod != 3)
|
||||
{
|
||||
int bytes_before_imm = 0;
|
||||
|
||||
/* Skip mod/rm byte once. We will be called twice. */
|
||||
MODRM_CHECK;
|
||||
codep++;
|
||||
|
||||
if (modrm.mod != 3)
|
||||
/* There are SIB/displacement bytes. */
|
||||
if ((sizeflag & AFLAG) || address_mode == mode_64bit)
|
||||
{
|
||||
/* There are SIB/displacement bytes. */
|
||||
if ((sizeflag & AFLAG) || address_mode == mode_64bit)
|
||||
/* 32/64 bit address mode */
|
||||
int base = modrm.rm;
|
||||
|
||||
/* Check SIB byte. */
|
||||
if (base == 4)
|
||||
{
|
||||
/* 32/64 bit address mode */
|
||||
int base = modrm.rm;
|
||||
|
||||
/* Check SIB byte. */
|
||||
if (base == 4)
|
||||
{
|
||||
FETCH_DATA (the_info, codep + 1);
|
||||
base = *codep & 7;
|
||||
bytes_before_imm++;
|
||||
}
|
||||
|
||||
switch (modrm.mod)
|
||||
{
|
||||
case 0:
|
||||
/* When modrm.rm == 5 or modrm.rm == 4 and base in
|
||||
SIB == 5, there is a 4 byte displacement. */
|
||||
if (base != 5)
|
||||
/* No displacement. */
|
||||
break;
|
||||
case 2:
|
||||
/* 4 byte displacement. */
|
||||
bytes_before_imm += 4;
|
||||
break;
|
||||
case 1:
|
||||
/* 1 byte displacement. */
|
||||
bytes_before_imm++;
|
||||
break;
|
||||
}
|
||||
FETCH_DATA (the_info, codep + 1);
|
||||
base = *codep & 7;
|
||||
bytes_before_imm++;
|
||||
}
|
||||
else
|
||||
{ /* 16 bit address mode */
|
||||
switch (modrm.mod)
|
||||
{
|
||||
case 0:
|
||||
/* When modrm.rm == 6, there is a 2 byte
|
||||
displacement. */
|
||||
if (modrm.rm != 6)
|
||||
/* No displacement. */
|
||||
break;
|
||||
case 2:
|
||||
/* 2 byte displacement. */
|
||||
bytes_before_imm += 2;
|
||||
break;
|
||||
case 1:
|
||||
/* 1 byte displacement. */
|
||||
bytes_before_imm++;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (modrm.mod)
|
||||
{
|
||||
case 0:
|
||||
/* When modrm.rm == 5 or modrm.rm == 4 and base in
|
||||
SIB == 5, there is a 4 byte displacement. */
|
||||
if (base != 5)
|
||||
/* No displacement. */
|
||||
break;
|
||||
case 2:
|
||||
/* 4 byte displacement. */
|
||||
bytes_before_imm += 4;
|
||||
break;
|
||||
case 1:
|
||||
/* 1 byte displacement. */
|
||||
bytes_before_imm++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* 16 bit address mode */
|
||||
switch (modrm.mod)
|
||||
{
|
||||
case 0:
|
||||
/* When modrm.rm == 6, there is a 2 byte displacement. */
|
||||
if (modrm.rm != 6)
|
||||
/* No displacement. */
|
||||
break;
|
||||
case 2:
|
||||
/* 2 byte displacement. */
|
||||
bytes_before_imm += 2;
|
||||
break;
|
||||
case 1:
|
||||
/* 1 byte displacement. */
|
||||
bytes_before_imm++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FETCH_DATA (the_info, codep + bytes_before_imm + 1);
|
||||
vex_i4 = codep [bytes_before_imm];
|
||||
vex_i4_done = 1;
|
||||
if (vex.w)
|
||||
reg = vex_i4 >> 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!vex.w)
|
||||
reg = vex_i4 >> 4;
|
||||
}
|
||||
|
||||
FETCH_DATA (the_info, codep + bytes_before_imm + 1);
|
||||
return codep [bytes_before_imm];
|
||||
}
|
||||
|
||||
static void
|
||||
OP_EX_VexReg (int bytemode, int sizeflag, int reg)
|
||||
{
|
||||
if (reg == -1 && modrm.mod != 3)
|
||||
{
|
||||
OP_E_memory (bytemode, sizeflag, 0);
|
||||
@@ -13390,6 +13386,89 @@ OP_EX_VexW (int bytemode, int sizeflag)
|
||||
oappend (scratchbuf + intel_syntax);
|
||||
}
|
||||
|
||||
static void
|
||||
OP_EX_VexImmW (int bytemode, int sizeflag)
|
||||
{
|
||||
int reg = -1;
|
||||
static unsigned char vex_imm8;
|
||||
|
||||
if (!vex_w_done)
|
||||
{
|
||||
vex_imm8 = get_vex_imm8 (sizeflag);
|
||||
if (vex.w)
|
||||
reg = vex_imm8 >> 4;
|
||||
vex_w_done = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!vex.w)
|
||||
reg = vex_imm8 >> 4;
|
||||
}
|
||||
|
||||
OP_EX_VexReg (bytemode, sizeflag, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
OP_EX_VexW (int bytemode, int sizeflag)
|
||||
{
|
||||
int reg = -1;
|
||||
|
||||
if (!vex_w_done)
|
||||
{
|
||||
vex_w_done = 1;
|
||||
if (vex.w)
|
||||
reg = vex.register_specifier;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!vex.w)
|
||||
reg = vex.register_specifier;
|
||||
}
|
||||
|
||||
OP_EX_VexReg (bytemode, sizeflag, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
OP_VEX_FMA (int bytemode, int sizeflag)
|
||||
{
|
||||
int reg = get_vex_imm8 (sizeflag) >> 4;
|
||||
|
||||
if (reg > 7 && address_mode != mode_64bit)
|
||||
BadOp ();
|
||||
|
||||
switch (vex.length)
|
||||
{
|
||||
case 128:
|
||||
switch (bytemode)
|
||||
{
|
||||
case vex_mode:
|
||||
case vex128_mode:
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf (scratchbuf, "%%xmm%d", reg);
|
||||
break;
|
||||
case 256:
|
||||
switch (bytemode)
|
||||
{
|
||||
case vex_mode:
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf (scratchbuf, "%%ymm%d", reg);
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
oappend (scratchbuf + intel_syntax);
|
||||
}
|
||||
|
||||
static void
|
||||
VEXI4_Fixup (int bytemode ATTRIBUTE_UNUSED,
|
||||
int sizeflag ATTRIBUTE_UNUSED)
|
||||
@@ -13414,6 +13493,9 @@ OP_REG_VexI4 (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
|
||||
BadOp ();
|
||||
|
||||
reg >>= 4;
|
||||
if (reg > 7 && address_mode != mode_64bit)
|
||||
BadOp ();
|
||||
|
||||
switch (vex.length)
|
||||
{
|
||||
case 128:
|
||||
|
||||
Reference in New Issue
Block a user