diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2008-12-23 15:14:15 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2008-12-23 15:14:15 +0000 |
commit | fa99fab2229b2e05faf2d2939e841c1d4a0b82b6 (patch) | |
tree | 2f5f3bdefffb30c8e8834c1ce2f9b66809ff73f4 /gas/config | |
parent | feddcd0d460b9d7810013e54c39132b25bcd512b (diff) | |
download | gdb-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.c | 59 |
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], - ®xmm) - && !operand_type_equal (&i.tm.operand_types[dest], - ®ymm))) + || (!operand_type_equal (&op, ®xmm) + && !operand_type_equal (&op, ®ymm))) abort (); i.vex.register_specifier = i.op[dest].regs; dest++; |