aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2008-12-23 15:14:15 +0000
committerH.J. Lu <hjl.tools@gmail.com>2008-12-23 15:14:15 +0000
commitfa99fab2229b2e05faf2d2939e841c1d4a0b82b6 (patch)
tree2f5f3bdefffb30c8e8834c1ce2f9b66809ff73f4 /gas/config
parentfeddcd0d460b9d7810013e54c39132b25bcd512b (diff)
downloadgdb-fa99fab2229b2e05faf2d2939e841c1d4a0b82b6.zip
gdb-fa99fab2229b2e05faf2d2939e841c1d4a0b82b6.tar.gz
gdb-fa99fab2229b2e05faf2d2939e841c1d4a0b82b6.tar.bz2
gas/
2008-12-23 H.J. Lu <hongjiu.lu@intel.com> * config/tc-i386.c (match_template): Changed to return const template *. Handle i.swap_operand for 3 operands. (build_vex_prefix): Take const template *. Swap operand for 2-byte VEX prefix if possible. (md_assemble): Updated. (build_modrm_byte): Handle RegMem bit for SSE2AVX. gas/testsuite/ 2008-12-23 H.J. Lu <hongjiu.lu@intel.com> * gas/i386/i386.exp: Run x86-64-avx-swap and x86-64-avx-swap-intel. * gas/i386/opts.s: Add tests for movsd, movss, vmovsd and vmovss. * gas/i386/x86-64-opts.s: Likewise. * gas/i386/opts.d: Updated. * gas/i386/opts-intel.d: Likewise. * gas/i386/sse2avx-opts.d: Likewise. * gas/i386/sse2avx-opts-intel.d: Likewise. * gas/i386/x86-64-opts.d: Likewise. * gas/i386/x86-64-opts-intel.d: Likewise. * gas/i386/x86-64-sse2avx-opts.d: Likewise. * gas/i386/x86-64-sse2avx-opts-intel.d: Likewise. * gas/i386/x86-64-avx-swap.d: New. * gas/i386/x86-64-avx-swap.s: Likewise. * gas/i386/x86-64-avx-swap-intel.d: Likewise. opcodes/ 2008-12-23 H.J. Lu <hongjiu.lu@intel.com> * i386-dis.c (EXdS): New. (EXdVexS): Likewise. (EXqVexS): Likewise. (d_swap_mode): Likewise. (q_mode): Updated. (prefix_table): Use EXdS on movss and EXqS on movsd. (vex_len_table): Use EXdVexS on vmovss and EXqVexS on vmovsd. (intel_operand_size): Handle d_swap_mode. (OP_EX): Likewise. * i386-opc.h (S): Update comments. * i386-opc.tbl: Add S to movss, movsd, vmovss and vmovsd. * i386-tbl.h: Regenerated.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-i386.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 5505d5c..d3f5d86 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -180,7 +180,7 @@ static void swap_operands (void);
static void swap_2_operands (int, int);
static void optimize_imm (void);
static void optimize_disp (void);
-static int match_template (void);
+static const template *match_template (void);
static int check_string (void);
static int process_suffix (void);
static int check_byte_reg (void);
@@ -2543,7 +2543,7 @@ intel_float_operand (const char *mnemonic)
/* Build the VEX prefix. */
static void
-build_vex_prefix (void)
+build_vex_prefix (const template *t)
{
unsigned int register_specifier;
unsigned int implied_prefix;
@@ -2560,6 +2560,36 @@ build_vex_prefix (void)
else
register_specifier = 0xf;
+ /* Use 2-byte VEX prefix by swappping destination and source
+ operand. */
+ if (!i.swap_operand
+ && i.operands == i.reg_operands
+ && i.tm.opcode_modifier.vex0f
+ && i.tm.opcode_modifier.s
+ && i.rex == REX_B)
+ {
+ unsigned int xchg = i.operands - 1;
+ union i386_op temp_op;
+ i386_operand_type temp_type;
+
+ temp_type = i.types[xchg];
+ i.types[xchg] = i.types[0];
+ i.types[0] = temp_type;
+ temp_op = i.op[xchg];
+ i.op[xchg] = i.op[0];
+ i.op[0] = temp_op;
+
+ assert (i.rm.mode == 3);
+
+ i.rex = REX_R;
+ xchg = i.rm.regmem;
+ i.rm.regmem = i.rm.reg;
+ i.rm.reg = xchg;
+
+ /* Use the next insn. */
+ i.tm = t[1];
+ }
+
vector_length = i.tm.opcode_modifier.vex256 ? 1 : 0;
switch ((i.tm.base_opcode >> 8) & 0xff)
@@ -2691,6 +2721,7 @@ md_assemble (char *line)
{
unsigned int j;
char mnemonic[MAX_MNEM_SIZE];
+ const template *t;
/* Initialize globals. */
memset (&i, '\0', sizeof (i));
@@ -2748,7 +2779,7 @@ md_assemble (char *line)
making sure the overlap of the given operands types is consistent
with the template operand types. */
- if (!match_template ())
+ if (!(t = match_template ()))
return;
if (sse_check != sse_check_none
@@ -2829,7 +2860,7 @@ md_assemble (char *line)
}
if (i.tm.opcode_modifier.vex)
- build_vex_prefix ();
+ build_vex_prefix (t);
/* Handle conversion of 'int $3' --> special int3 insn. */
if (i.tm.base_opcode == INT_OPCODE && i.op[0].imms->X_add_number == 3)
@@ -3548,7 +3579,7 @@ VEX_check_operands (const template *t)
return 0;
}
-static int
+static const template *
match_template (void)
{
/* Points to template once we've found it. */
@@ -3742,6 +3773,9 @@ match_template (void)
}
case 3:
+ /* If we swap operand in encoding, we match the next one. */
+ if (i.swap_operand && t->opcode_modifier.s)
+ continue;
case 4:
case 5:
overlap1 = operand_type_and (i.types[1], operand_types[1]);
@@ -3866,7 +3900,7 @@ check_reverse:
else
as_bad (_("suffix or operands invalid for `%s'"),
current_templates->start->name);
- return 0;
+ return NULL;
}
if (!quiet_warnings)
@@ -3906,7 +3940,7 @@ check_reverse:
i.tm.operand_types[1] = operand_types[0];
}
- return 1;
+ return t;
}
static int
@@ -5325,12 +5359,13 @@ build_modrm_byte (void)
{
/* For instructions with VexNDS, the register-only
source operand must be XMM or YMM register. It is
- encoded in VEX prefix. */
+ encoded in VEX prefix. We need to clear RegMem bit
+ before calling operand_type_equal. */
+ i386_operand_type op = i.tm.operand_types[dest];
+ op.bitfield.regmem = 0;
if ((dest + 1) >= i.operands
- || (!operand_type_equal (&i.tm.operand_types[dest],
- &regxmm)
- && !operand_type_equal (&i.tm.operand_types[dest],
- &regymm)))
+ || (!operand_type_equal (&op, &regxmm)
+ && !operand_type_equal (&op, &regymm)))
abort ();
i.vex.register_specifier = i.op[dest].regs;
dest++;