aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog10
-rw-r--r--gas/config/tc-i386.c65
-rw-r--r--gas/testsuite/gas/i386/x86-64-sse2avx.d27
-rw-r--r--gas/testsuite/gas/i386/x86-64-sse2avx.s39
4 files changed, 112 insertions, 29 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 835a552..c2fa02d 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,15 @@
2020-06-25 Jan Beulich <jbeulich@suse.com>
+ * config/tc-i386.c (process_operands): Translate explicit REX
+ prefix into i.rex for SSE2AVX templates.
+ (set_rex_vrex): New helper.
+ (build_modrm_byte): Use it.
+ * testsuite/gas/i386/x86-64-sse2avx.s: Add cases with explict
+ REX prefixes.
+ * testsuite/gas/i386/x86-64-sse2avx.d: Adjust expectations.
+
+2020-06-25 Jan Beulich <jbeulich@suse.com>
+
* config/tc-i386.c (cpu_flags_match): Only match SSE2AVX
templates when there's no data size prefix.
(md_assemble): Reject data size prefix also for legacy encoded
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 5a652a9..c84192e 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -7408,6 +7408,15 @@ process_operands (void)
unnecessary segment overrides. */
const seg_entry *default_seg = 0;
+ if (i.tm.opcode_modifier.sse2avx)
+ {
+ /* Legacy encoded insns allow explicit REX prefixes, so these prefixes
+ need converting. */
+ i.rex |= i.prefix[REX_PREFIX] & (REX_W | REX_R | REX_X | REX_B);
+ i.prefix[REX_PREFIX] = 0;
+ i.rex_encoding = 0;
+ }
+
if (i.tm.opcode_modifier.sse2avx && i.tm.opcode_modifier.vexvvvv)
{
unsigned int dupl = i.operands;
@@ -7645,6 +7654,25 @@ process_operands (void)
return 1;
}
+static INLINE void set_rex_vrex (const reg_entry *r, unsigned int rex_bit,
+ bfd_boolean do_sse2avx)
+{
+ if (r->reg_flags & RegRex)
+ {
+ if (i.rex & rex_bit)
+ as_bad (_("same type of prefix used twice"));
+ i.rex |= rex_bit;
+ }
+ else if (do_sse2avx && (i.rex & rex_bit) && i.vex.register_specifier)
+ {
+ gas_assert (i.vex.register_specifier == r);
+ i.vex.register_specifier += 8;
+ }
+
+ if (r->reg_flags & RegVRex)
+ i.vrex |= rex_bit;
+}
+
static const seg_entry *
build_modrm_byte (void)
{
@@ -7875,27 +7903,15 @@ build_modrm_byte (void)
else
i.has_regxmm = TRUE;
}
- if ((i.op[dest].regs->reg_flags & RegRex) != 0)
- i.rex |= REX_R;
- if ((i.op[dest].regs->reg_flags & RegVRex) != 0)
- i.vrex |= REX_R;
- if ((i.op[source].regs->reg_flags & RegRex) != 0)
- i.rex |= REX_B;
- if ((i.op[source].regs->reg_flags & RegVRex) != 0)
- i.vrex |= REX_B;
+ set_rex_vrex (i.op[dest].regs, REX_R, i.tm.opcode_modifier.sse2avx);
+ set_rex_vrex (i.op[source].regs, REX_B, FALSE);
}
else
{
i.rm.reg = i.op[source].regs->reg_num;
i.rm.regmem = i.op[dest].regs->reg_num;
- if ((i.op[dest].regs->reg_flags & RegRex) != 0)
- i.rex |= REX_B;
- if ((i.op[dest].regs->reg_flags & RegVRex) != 0)
- i.vrex |= REX_B;
- if ((i.op[source].regs->reg_flags & RegRex) != 0)
- i.rex |= REX_R;
- if ((i.op[source].regs->reg_flags & RegVRex) != 0)
- i.vrex |= REX_R;
+ set_rex_vrex (i.op[dest].regs, REX_B, i.tm.opcode_modifier.sse2avx);
+ set_rex_vrex (i.op[source].regs, REX_R, FALSE);
}
if (flag_code != CODE_64BIT && (i.rex & REX_R))
{
@@ -7945,10 +7961,7 @@ build_modrm_byte (void)
}
}
i.sib.index = i.index_reg->reg_num;
- if ((i.index_reg->reg_flags & RegRex) != 0)
- i.rex |= REX_X;
- if ((i.index_reg->reg_flags & RegVRex) != 0)
- i.vrex |= REX_X;
+ set_rex_vrex (i.index_reg, REX_X, FALSE);
}
default_seg = &ds;
@@ -8314,18 +8327,14 @@ build_modrm_byte (void)
if (i.tm.extension_opcode != None)
{
i.rm.regmem = i.op[op].regs->reg_num;
- if ((i.op[op].regs->reg_flags & RegRex) != 0)
- i.rex |= REX_B;
- if ((i.op[op].regs->reg_flags & RegVRex) != 0)
- i.vrex |= REX_B;
+ set_rex_vrex (i.op[op].regs, REX_B,
+ i.tm.opcode_modifier.sse2avx);
}
else
{
i.rm.reg = i.op[op].regs->reg_num;
- if ((i.op[op].regs->reg_flags & RegRex) != 0)
- i.rex |= REX_R;
- if ((i.op[op].regs->reg_flags & RegVRex) != 0)
- i.vrex |= REX_R;
+ set_rex_vrex (i.op[op].regs, REX_R,
+ i.tm.opcode_modifier.sse2avx);
}
}
diff --git a/gas/testsuite/gas/i386/x86-64-sse2avx.d b/gas/testsuite/gas/i386/x86-64-sse2avx.d
index bb9976e..8eed2db 100644
--- a/gas/testsuite/gas/i386/x86-64-sse2avx.d
+++ b/gas/testsuite/gas/i386/x86-64-sse2avx.d
@@ -711,6 +711,33 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: c5 d9 73 d4 64 vpsrlq \$0x64,%xmm4,%xmm4
[ ]*[a-f0-9]+: c5 d9 71 d4 64 vpsrlw \$0x64,%xmm4,%xmm4
[ ]*[a-f0-9]+: c5 f9 c5 cc 64 vpextrw \$0x64,%xmm4,%ecx
+[ ]*[a-f0-9]+: c5 f8 58 c0 vaddps %xmm0,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c5 f8 58 04 00 vaddps \(%rax,%rax(,1)?\),%xmm0,%xmm0
+[ ]*[a-f0-9]+: c5 f8 58 c0 vaddps %xmm0,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c5 f8 58 04 00 vaddps \(%rax,%rax(,1)?\),%xmm0,%xmm0
+[ ]*[a-f0-9]+: c5 38 58 c0 vaddps %xmm0,%xmm8,%xmm8
+[ ]*[a-f0-9]+: c5 38 58 04 00 vaddps \(%rax,%rax(,1)?\),%xmm8,%xmm8
+[ ]*[a-f0-9]+: c4 a1 78 58 c0 vaddps %xmm0,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 a1 78 58 04 00 vaddps \(%rax,%r8(,1)?\),%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 c1 78 58 c0 vaddps %xmm8,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 c1 78 58 04 00 vaddps \(%r8,%rax(,1)?\),%xmm0,%xmm0
+[ ]*[a-f0-9]+: c5 3a 10 c0 vmovss %xmm0,%xmm8,%xmm8
+[ ]*[a-f0-9]+: c4 c1 7a 10 c0 vmovss %xmm8,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c5 7a 11 c0 vmovss %xmm8,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 c1 3a 11 c0 vmovss %xmm0,%xmm8,%xmm8
+[ ]*[a-f0-9]+: c4 c1 39 71 f0 00 vpsllw \$(0x)?0,%xmm8,%xmm8
+[ ]*[a-f0-9]+: c5 79 c5 c0 00 vpextrw \$(0x)?0,%xmm0,%r8d
+[ ]*[a-f0-9]+: c4 c1 79 c5 c0 00 vpextrw \$(0x)?0,%xmm8,%eax
+[ ]*[a-f0-9]+: c4 63 79 14 c0 00 vpextrb \$(0x)?0,%xmm8,%eax
+[ ]*[a-f0-9]+: c4 c3 79 14 c0 00 vpextrb \$(0x)?0,%xmm0,%r8d
+[ ]*[a-f0-9]+: c4 63 39 4a c0 00 vblendvps %xmm0,%xmm0,%xmm8,%xmm8
+[ ]*[a-f0-9]+: c4 c3 79 4a c0 00 vblendvps %xmm0,%xmm8,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 63 39 4a c0 00 vblendvps %xmm0,%xmm0,%xmm8,%xmm8
+[ ]*[a-f0-9]+: c4 c3 79 4a c0 00 vblendvps %xmm0,%xmm8,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 e1 fb 2a 00 vcvtsi2sdq \(%rax\),%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 e1 fa 2a 00 vcvtsi2ssq \(%rax\),%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 e3 f9 61 c0 00 vpcmpestriq \$(0x)?0,%xmm0,%xmm0
+[ ]*[a-f0-9]+: c4 e3 f9 60 c0 00 vpcmpestrmq \$(0x)?0,%xmm0,%xmm0
[ ]*[a-f0-9]+: c5 f8 ae 11 vldmxcsr \(%rcx\)
[ ]*[a-f0-9]+: c5 f8 ae 19 vstmxcsr \(%rcx\)
[ ]*[a-f0-9]+: c5 f8 5b f4 vcvtdq2ps %xmm4,%xmm6
diff --git a/gas/testsuite/gas/i386/x86-64-sse2avx.s b/gas/testsuite/gas/i386/x86-64-sse2avx.s
index 08d1b25..1d3cda1 100644
--- a/gas/testsuite/gas/i386/x86-64-sse2avx.s
+++ b/gas/testsuite/gas/i386/x86-64-sse2avx.s
@@ -802,6 +802,44 @@ _start:
# Tests for op imm8, xmm, regl
pextrw $100,%xmm4,%ecx
+# Tests for REX prefix conversion
+ {rex} addps %xmm0, %xmm0
+ {rex} addps (%rax,%rax), %xmm0
+ rex addps %xmm0, %xmm0
+ rex addps (%rax,%rax), %xmm0
+ rexx addps %xmm0, %xmm0
+ rexx addps (%rax,%rax), %xmm0
+ rexy addps %xmm0, %xmm0
+ rexy addps (%rax,%rax), %xmm0
+ rexz addps %xmm0, %xmm0
+ rexz addps (%rax,%rax), %xmm0
+
+ {load} rexx movss %xmm0, %xmm0
+ {load} rexz movss %xmm0, %xmm0
+
+ {store} rexx movss %xmm0, %xmm0
+ {store} rexz movss %xmm0, %xmm0
+
+ rexz psllw $0, %xmm0
+
+ rexx pextrw $0, %xmm0, %eax
+ rexz pextrw $0, %xmm0, %eax
+
+ rexx pextrb $0, %xmm0, %eax
+ rexz pextrb $0, %xmm0, %eax
+
+ rexx blendvps %xmm0, %xmm0, %xmm0
+ rexz blendvps %xmm0, %xmm0, %xmm0
+
+ rexx blendvps %xmm0, %xmm0
+ rexz blendvps %xmm0, %xmm0
+
+ rex64 cvtsi2sd (%rax), %xmm0
+ rex64 cvtsi2ss (%rax), %xmm0
+
+ rex64 pcmpestri $0, %xmm0, %xmm0
+ rex64 pcmpestrm $0, %xmm0, %xmm0
+
.intel_syntax noprefix
# Tests for op mem64
@@ -1505,4 +1543,3 @@ _start:
# Tests for op imm8, xmm, regl
pextrw ecx,xmm4,100
-