This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] x86: Apply standalone prefixes to the following instruction
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: Florian Weimer <fweimer at redhat dot com>
- Cc: Binutils <binutils at sourceware dot org>
- Date: Fri, 19 Jul 2019 10:17:32 -0700
- Subject: Re: [PATCH] x86: Apply standalone prefixes to the following instruction
- References: <CAMe9rOohqV49DVBVRr_kNTyT6ruNYJZgTCWkq4B-Bmh+VRAM=Q@mail.gmail.com> <87zhlas747.fsf@oldenburg2.str.redhat.com>
On Fri, Jul 19, 2019 at 2:31 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > Standalone prefixes should be applied to the following instruction,
> > instead of being treated as regular instructions. An error should be
> > issued when a standalone prefix is at the end of source or isn't
> > followed by an instruction in the same section.
>
> glibc used to do this:
>
> | #define __arch_c_compare_and_exchange_val_8_acq(mem, newval, oldval) \
> | ({ __typeof (*mem) ret; \
> | __asm __volatile ("cmpl $0, %%fs:%P5\n\t" \
> | "je 0f\n\t" \
> | "lock\n" \
> | "0:\tcmpxchgb %b2, %1" \
> | : "=a" (ret), "=m" (*mem) \
> | : "q" (newval), "m" (*mem), "0" (oldval), \
> | "i" (offsetof (tcbhead_t, multiple_threads))); \
> | ret; })
>
> Will this still work?
>
":" between prefixes and instruction is a special case. Here is the updated
patch to add i386_frob_colon so that i386 can output all pending stand-alone
prefixes when seeing a colon in the same frag.
--
H.J.
From e72df470f74cd3f716eb7a0fb78979faccc27c69 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Thu, 18 Jul 2019 14:57:37 -0700
Subject: [PATCH] x86: Apply standalone prefixes to the following instruction
Standalone prefixes should be applied to the following instruction,
instead of being treated as regular instructions. An error should be
issued when a standalone prefix is at the end of source or isn't
followed by an instruction in the same section. tc_frob_colon is
added to colon so that i386 can output all pending stand-alone prefixes
when seeing a colon in the same frag.
PR gas/24821
* symbols.c (colon): Call tc_frob_colon if defined.
* config/tc-i386.c (_i386_insn): Add prev.
(check_hle): Also check i.prev.name for prefix name.
(i386_frob_colon): New function.
(i386_md_end): Likewise.
(md_assemble): Apply the standalone prefix to the current
instruction. Issue an error if a standalone prefix isn't
followed by an instruction in the same section.
(output_insn): Remember the standalone prefix and add it to the
following instruction.
* config/tc-i386.h (i386_md_end): New.
(md_end): Likewise.
(i386_frob_colon): Likewise.
(tc_frob_colon): Likewise.
* testsuite/gas/i386/i386.exp: Run prefix-2, prefix-3, prefix-4,
x86-64-prefix-3 and x86-64-prefix-4.
* testsuite/gas/i386/ilp32/rex.d: Updated.
* testsuite/gas/i386/omit-lock-no.d: Likewise.
* testsuite/gas/i386/omit-lock-yes.d: Likewise.
* testsuite/gas/i386/rex.d: Likewise.
* testsuite/gas/i386/white.l: Likewise.
* testsuite/gas/i386/omit-lock.s: Replace standalone lock
with ds.
* testsuite/gas/i386/prefix-2.l: New file.
* testsuite/gas/i386/prefix-2.s: Likewise.
* testsuite/gas/i386/prefix-3.d: Likewise.
* testsuite/gas/i386/prefix-4.s: Likewise.
* testsuite/gas/i386/prefix-4.d: Likewise.
* testsuite/gas/i386/prefix-3.s: Likewise.
* testsuite/gas/i386/x86-64-prefix-3.d: Likewise.
* testsuite/gas/i386/x86-64-prefix-4.d: Likewise.
* testsuite/gas/i386/rex.s: Add nop after REX prefixes.
---
gas/config/tc-i386.c | 140 +++++++++++++++++++++--
gas/config/tc-i386.h | 6 +
gas/symbols.c | 4 +
gas/testsuite/gas/i386/i386.exp | 8 ++
gas/testsuite/gas/i386/ilp32/rex.d | 32 +++---
gas/testsuite/gas/i386/omit-lock-no.d | 2 +-
gas/testsuite/gas/i386/omit-lock-yes.d | 2 +-
gas/testsuite/gas/i386/omit-lock.s | 2 +-
gas/testsuite/gas/i386/prefix-2.l | 7 ++
gas/testsuite/gas/i386/prefix-2.s | 16 +++
gas/testsuite/gas/i386/prefix-3.d | 13 +++
gas/testsuite/gas/i386/prefix-3.s | 20 ++++
gas/testsuite/gas/i386/prefix-4.d | 12 ++
gas/testsuite/gas/i386/prefix-4.s | 13 +++
gas/testsuite/gas/i386/rex.d | 32 +++---
gas/testsuite/gas/i386/rex.s | 19 ++-
gas/testsuite/gas/i386/white.l | 4 +-
gas/testsuite/gas/i386/x86-64-prefix-3.d | 17 +++
gas/testsuite/gas/i386/x86-64-prefix-4.d | 15 +++
19 files changed, 318 insertions(+), 46 deletions(-)
create mode 100644 gas/testsuite/gas/i386/prefix-2.l
create mode 100644 gas/testsuite/gas/i386/prefix-2.s
create mode 100644 gas/testsuite/gas/i386/prefix-3.d
create mode 100644 gas/testsuite/gas/i386/prefix-3.s
create mode 100644 gas/testsuite/gas/i386/prefix-4.d
create mode 100644 gas/testsuite/gas/i386/prefix-4.s
create mode 100644 gas/testsuite/gas/i386/x86-64-prefix-3.d
create mode 100644 gas/testsuite/gas/i386/x86-64-prefix-4.d
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 2710dcec72..31200b11cb 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -431,6 +431,25 @@ struct _i386_insn
/* Error message. */
enum i386_error error;
+
+ /* Information of previous instruction. */
+ struct
+ {
+ fragS *frag;
+ const char *name;
+ const char *file;
+ unsigned int line;
+ int error_count;
+ enum
+ {
+ insn_unknown,
+ prefix_notrack,
+ prefix_hle,
+ prefix_bnd,
+ prefix_rep,
+ prefix_other
+ } type;
+ } prev;
};
typedef struct _i386_insn i386_insn;
@@ -3902,7 +3921,8 @@ check_hle (void)
abort ();
case HLEPrefixNone:
as_bad (_("invalid instruction `%s' after `%s'"),
- i.tm.name, i.hle_prefix);
+ i.tm.name,
+ i.hle_prefix ? i.hle_prefix : i.prev.name);
return 0;
case HLEPrefixLock:
if (i.prefix[LOCK_PREFIX])
@@ -4230,6 +4250,39 @@ optimize_encoding (void)
}
}
+/* Additioanl processing for colon. */
+
+void
+i386_frob_colon (const char *name ATTRIBUTE_UNUSED)
+{
+ if (i.prev.name
+ && i.prev.type != insn_unknown
+ && i.prev.frag == frag_now)
+ {
+ /* Output all pending stand-alone prefixes when seeing a colon in
+ the same frag. */
+ unsigned char *q;
+ unsigned int j;
+ for (j = ARRAY_SIZE (i.prefix), q = i.prefix; j > 0; j--, q++)
+ if (*q)
+ FRAG_APPEND_1_CHAR (*q);
+ i.prev.name = NULL;
+ }
+}
+
+/* Issue an error if there is a stand-alone prefix at the end of
+ source. */
+
+void
+i386_md_end (void)
+{
+ if (i.prev.name
+ && i.prev.type != insn_unknown
+ && i.prev.error_count == had_errors ())
+ as_bad_where (i.prev.file, i.prev.line,
+ _("stand-alone `%s' prefix"), i.prev.name);
+}
+
/* This is the guts of the machine-dependent assembler. LINE points to a
machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to. */
@@ -4242,7 +4295,30 @@ md_assemble (char *line)
const insn_template *t;
/* Initialize globals. */
- memset (&i, '\0', sizeof (i));
+ if (i.prev.name
+ && i.prev.type != insn_unknown
+ && i.prev.error_count == had_errors ())
+ {
+ /* If there are no new errors since the previous stand-alone
+ prefix, add prefix to the current instruction. */
+ const fragS *fr;
+
+ for (fr = i.prev.frag; fr && fr != frag_now; fr = fr->fr_next)
+ ;
+
+ if (fr != frag_now)
+ {
+ /* Issue an error if the current instruction isn't in the
+ same section. */
+ as_bad_where (i.prev.file, i.prev.line,
+ _("stand-alone `%s' prefix"),
+ i.prev.name);
+ /* Discard the previous stand-alone prefix. */
+ memset (&i, '\0', sizeof (i));
+ }
+ }
+ else
+ memset (&i, '\0', sizeof (i));
for (j = 0; j < MAX_OPERANDS; j++)
i.reloc[j] = NO_RELOC;
memset (disp_expressions, '\0', sizeof (disp_expressions));
@@ -4344,16 +4420,22 @@ md_assemble (char *line)
return;
/* Check if REP prefix is OK. */
- if (i.rep_prefix && !i.tm.opcode_modifier.repprefixok)
+ if ((i.rep_prefix
+ || (i.prev.name
+ && i.prev.type == prefix_rep
+ && !i.tm.opcode_modifier.isprefix))
+ && !i.tm.opcode_modifier.repprefixok)
{
as_bad (_("invalid instruction `%s' after `%s'"),
- i.tm.name, i.rep_prefix);
+ i.tm.name,
+ i.rep_prefix ? i.rep_prefix : i.prev.name);
return;
}
/* Check for lock without a lockable instruction. Destination operand
must be memory unless it is xchg (0x86). */
if (i.prefix[LOCK_PREFIX]
+ && !i.tm.opcode_modifier.isprefix
&& (!i.tm.opcode_modifier.islockable
|| i.mem_operands == 0
|| (i.tm.base_opcode != 0x86
@@ -4371,15 +4453,25 @@ md_assemble (char *line)
}
/* Check if HLE prefix is OK. */
- if (i.hle_prefix && !check_hle ())
+ if ((i.hle_prefix
+ || (i.prev.name
+ && i.prev.type == prefix_hle
+ && !i.tm.opcode_modifier.isprefix))
+ && !check_hle ())
return;
/* Check BND prefix. */
- if (i.bnd_prefix && !i.tm.opcode_modifier.bndprefixok)
+ if ((i.bnd_prefix
+ || (i.prev.name
+ && i.prev.type == prefix_bnd
+ && !i.tm.opcode_modifier.isprefix))
+ && !i.tm.opcode_modifier.bndprefixok)
as_bad (_("expecting valid branch instruction after `bnd'"));
/* Check NOTRACK prefix. */
- if (i.notrack_prefix && !i.tm.opcode_modifier.notrackprefixok)
+ if ((i.notrack_prefix
+ || (i.prev.name && i.prev.type == prefix_notrack))
+ && !i.tm.opcode_modifier.notrackprefixok)
as_bad (_("expecting indirect branch instruction after `notrack'"));
if (i.tm.cpu_flags.bitfield.cpumpx)
@@ -8314,6 +8406,40 @@ output_insn (void)
insn_start_frag = frag_now;
insn_start_off = frag_now_fix ();
+ if (i.tm.opcode_modifier.isprefix && i.tm.opcode_length == 1)
+ {
+ /* Remember the stand-alone prefix. */
+ i.prev.name = i.tm.name;
+ i.prev.frag = insn_start_frag;
+ i.prev.file = as_where (&i.prev.line);
+
+ /* Save the current error count. */
+ i.prev.error_count = had_errors ();
+
+ /* Add the prefix to the following instruction. */
+ i.prev.type = prefix_other;
+ switch (add_prefix (i.tm.base_opcode))
+ {
+ case PREFIX_DS:
+ if (i.tm.cpu_flags.bitfield.cpuibt)
+ i.prev.type = prefix_notrack;
+ break;
+ case PREFIX_REP:
+ if (i.tm.cpu_flags.bitfield.cpuhle)
+ i.prev.type = prefix_hle;
+ else if (i.tm.cpu_flags.bitfield.cpumpx)
+ i.prev.type = prefix_bnd;
+ else
+ i.prev.type = prefix_rep;
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+ else
+ i.prev.name = NULL;
+
/* Output jumps. */
if (i.tm.opcode_modifier.jump)
output_branch ();
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index b02a25671f..8d1a4d09cf 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -194,6 +194,12 @@ extern int i386_need_index_operator (void);
extern const struct relax_type md_relax_table[];
#define TC_GENERIC_RELAX_TABLE md_relax_table
+extern void i386_md_end (void);
+#define md_end() i386_md_end ()
+
+extern void i386_frob_colon (const char *);
+#define tc_frob_colon(name) i386_frob_colon (name)
+
extern int optimize_align_code;
#define md_do_align(n, fill, len, max, around) \
diff --git a/gas/symbols.c b/gas/symbols.c
index 918028f875..2a3efd7ee0 100644
--- a/gas/symbols.c
+++ b/gas/symbols.c
@@ -458,6 +458,10 @@ colon (/* Just seen "x:" - rattle symbols & frags. */
obj_frob_colon (sym_name);
#endif
+#ifdef tc_frob_colon
+ tc_frob_colon (sym_name);
+#endif
+
if ((symbolP = symbol_find (sym_name)) != 0)
{
S_CLEAR_WEAKREFR (symbolP);
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 988f3fffb2..2d5c147471 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -567,6 +567,10 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]]
run_dump_test "property-1"
run_dump_test "property-2"
+ run_list_test "prefix-2"
+ run_dump_test "prefix-3"
+ run_dump_test "prefix-4"
+
if { [gas_64_check] } then {
run_dump_test "att-regs"
run_dump_test "intel-regs"
@@ -1088,6 +1092,10 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
run_dump_test "evex-no-scale-64"
run_dump_test "x86-64-property-1"
run_dump_test "x86-64-property-2"
+
+ run_list_test "prefix-2"
+ run_dump_test "x86-64-prefix-3"
+ run_dump_test "x86-64-prefix-4"
}
set ASFLAGS "$old_ASFLAGS"
diff --git a/gas/testsuite/gas/i386/ilp32/rex.d b/gas/testsuite/gas/i386/ilp32/rex.d
index d8bc1b528c..189461961a 100644
--- a/gas/testsuite/gas/i386/ilp32/rex.d
+++ b/gas/testsuite/gas/i386/ilp32/rex.d
@@ -28,20 +28,20 @@ Disassembly of section .text:
[ ]*[0-9a-f]+:[ ]+9b dd 30\s+fsave\s+\(%rax\)
[ ]*[0-9a-f]+:[ ]+9b 41 dd 30\s+fsave\s+\(%r8\)
[ ]*[0-9a-f]+:[ ]+40 c5 f9 28 00[ ]+rex vmovapd \(%rax\),%xmm0
-[ ]*[0-9a-f]+:[ ]+40[ ]+rex
-[ ]*[0-9a-f]+:[ ]+41[ ]+rex.B
-[ ]*[0-9a-f]+:[ ]+42[ ]+rex.X
-[ ]*[0-9a-f]+:[ ]+43[ ]+rex.XB
-[ ]*[0-9a-f]+:[ ]+44[ ]+rex.R
-[ ]*[0-9a-f]+:[ ]+45[ ]+rex.RB
-[ ]*[0-9a-f]+:[ ]+46[ ]+rex.RX
-[ ]*[0-9a-f]+:[ ]+47[ ]+rex.RXB
-[ ]*[0-9a-f]+:[ ]+48[ ]+rex.W
-[ ]*[0-9a-f]+:[ ]+49[ ]+rex.WB
-[ ]*[0-9a-f]+:[ ]+4a[ ]+rex.WX
-[ ]*[0-9a-f]+:[ ]+4b[ ]+rex.WXB
-[ ]*[0-9a-f]+:[ ]+4c[ ]+rex.WR
-[ ]*[0-9a-f]+:[ ]+4d[ ]+rex.WRB
-[ ]*[0-9a-f]+:[ ]+4e[ ]+rex.WRX
-[ ]*[0-9a-f]+:[ ]+4f[ ]+rex.WRXB
+[ ]*[0-9a-f]+:[ ]+40 90[ ]+rex xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+41 90[ ]+xchg[ ]+%eax,%r8d
+[ ]*[0-9a-f]+:[ ]+42 90[ ]+rex.X xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+43 90[ ]+rex.XB xchg %eax,%r8d
+[ ]*[0-9a-f]+:[ ]+44 90[ ]+rex.R xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+45 90[ ]+rex.RB xchg %eax,%r8d
+[ ]*[0-9a-f]+:[ ]+46 90[ ]+rex.RX xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+47 90[ ]+rex.RXB xchg %eax,%r8d
+[ ]*[0-9a-f]+:[ ]+48 90[ ]+rex.W nop
+[ ]*[0-9a-f]+:[ ]+49 90[ ]+xchg[ ]+%rax,%r8
+[ ]*[0-9a-f]+:[ ]+4a 90[ ]+rex.WX xchg %rax,%rax
+[ ]*[0-9a-f]+:[ ]+4b 90[ ]+rex.WXB xchg %rax,%r8
+[ ]*[0-9a-f]+:[ ]+4c 90[ ]+rex.WR xchg %rax,%rax
+[ ]*[0-9a-f]+:[ ]+4d 90[ ]+rex.WRB xchg %rax,%r8
+[ ]*[0-9a-f]+:[ ]+4e 90[ ]+rex.WRX xchg %rax,%rax
+[ ]*[0-9a-f]+:[ ]+4f 90[ ]+rex.WRXB xchg %rax,%r8
#pass
diff --git a/gas/testsuite/gas/i386/omit-lock-no.d b/gas/testsuite/gas/i386/omit-lock-no.d
index 87f796f3a8..a35dfe7cd2 100644
--- a/gas/testsuite/gas/i386/omit-lock-no.d
+++ b/gas/testsuite/gas/i386/omit-lock-no.d
@@ -8,5 +8,5 @@
Disassembly of section .text:
0+ <main>:
- 0: f0 f0 83 00 01 lock lock addl \$0x1,\(%eax\)
+ 0: 3e f0 83 00 01 lock addl \$0x1,%ds:\(%eax\)
#pass
diff --git a/gas/testsuite/gas/i386/omit-lock-yes.d b/gas/testsuite/gas/i386/omit-lock-yes.d
index 67f0ef196e..1e17e52a24 100644
--- a/gas/testsuite/gas/i386/omit-lock-yes.d
+++ b/gas/testsuite/gas/i386/omit-lock-yes.d
@@ -8,5 +8,5 @@
Disassembly of section .text:
0+ <main>:
- 0: 83 00 01 addl \$0x1,\(%eax\)
+ 0: 3e 83 00 01 addl \$0x1,%ds:\(%eax\)
#pass
diff --git a/gas/testsuite/gas/i386/omit-lock.s b/gas/testsuite/gas/i386/omit-lock.s
index 248a9be1fe..1e52498399 100644
--- a/gas/testsuite/gas/i386/omit-lock.s
+++ b/gas/testsuite/gas/i386/omit-lock.s
@@ -1,5 +1,5 @@
.text
.globl main
main:
- lock
+ ds
lock addl $0x1,(%eax)
diff --git a/gas/testsuite/gas/i386/prefix-2.l b/gas/testsuite/gas/i386/prefix-2.l
new file mode 100644
index 0000000000..5dd3a6cd38
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix-2.l
@@ -0,0 +1,7 @@
+.*.s: Assembler messages:
+.*.s:3: Error: same type of prefix used twice
+.*.s:6: Error: invalid instruction `movups' after `rep'
+.*.s:8: Error: expecting valid branch instruction after `bnd'
+.*.s:9: Error: stand-alone `rep' prefix
+.*.s:12: Error: invalid instruction `movups' after `repz'
+.*.s:16: Error: stand-alone `lock' prefix
diff --git a/gas/testsuite/gas/i386/prefix-2.s b/gas/testsuite/gas/i386/prefix-2.s
new file mode 100644
index 0000000000..74977772b1
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix-2.s
@@ -0,0 +1,16 @@
+ .text
+ rep
+ rep
+ repz stosb
+ rep
+ movups foo, %xmm0
+ bnd
+ movups foo, %xmm0
+ rep
+ .pushsection .foo,"ax",@progbits
+ repz
+ movups foo, %xmm0
+ .popsection
+ movups foo, %xmm1
+ bnd
+ lock
diff --git a/gas/testsuite/gas/i386/prefix-3.d b/gas/testsuite/gas/i386/prefix-3.d
new file mode 100644
index 0000000000..4647730307
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix-3.d
@@ -0,0 +1,13 @@
+#objdump: -dw
+#name: i386 prefix 3
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <test>:
+ +[a-f0-9]+: 65 f3 f0 0f c1 05 00 00 00 00 xrelease lock xadd %eax,%gs:0x0
+ +[a-f0-9]+: f3 aa rep stos %al,%es:\(%edi\)
+ +[a-f0-9]+: f2 e9 fc ff ff ff bnd jmp [a-f0-9]+ <test\+0x[a-f0-9]+>
+ +[a-f0-9]+: f3 c3 repz ret
+#pass
diff --git a/gas/testsuite/gas/i386/prefix-3.s b/gas/testsuite/gas/i386/prefix-3.s
new file mode 100644
index 0000000000..7bf48746cf
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix-3.s
@@ -0,0 +1,20 @@
+ .text
+test:
+ gs
+ lock
+ xrelease
+ .p2align 4
+ xaddl %eax, foo
+ rep
+
+
+ stosb
+ bnd
+
+ jmp foo
+ rep
+ ret
+.ifdef __64_bit__
+ rex64
+ call foo
+.endif
diff --git a/gas/testsuite/gas/i386/prefix-4.d b/gas/testsuite/gas/i386/prefix-4.d
new file mode 100644
index 0000000000..f297ebce64
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix-4.d
@@ -0,0 +1,12 @@
+#objdump: -dw
+#name: i386 prefix 4
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <test>:
+ +[a-f0-9]+: 74 03 je 5 <test\+0x5>
+ +[a-f0-9]+: 77 02 ja 6 <test\+0x6>
+ +[a-f0-9]+: f0 f3 0f b0 0d 00 00 00 00 lock xrelease cmpxchg %cl,0x0
+#pass
diff --git a/gas/testsuite/gas/i386/prefix-4.s b/gas/testsuite/gas/i386/prefix-4.s
new file mode 100644
index 0000000000..943d28cc11
--- /dev/null
+++ b/gas/testsuite/gas/i386/prefix-4.s
@@ -0,0 +1,13 @@
+ .text
+test:
+ je 0f
+ ja 1f
+ lock
+0:
+ xrelease
+ .data
+foo:
+ .byte 0
+ .text
+1:
+ cmpxchgb %cl, foo
diff --git a/gas/testsuite/gas/i386/rex.d b/gas/testsuite/gas/i386/rex.d
index 22c0c7f30a..79111c8158 100644
--- a/gas/testsuite/gas/i386/rex.d
+++ b/gas/testsuite/gas/i386/rex.d
@@ -27,20 +27,20 @@ Disassembly of section .text:
[ ]*[0-9a-f]+:[ ]+9b dd 30\s+fsave\s+\(%rax\)
[ ]*[0-9a-f]+:[ ]+9b 41 dd 30\s+fsave\s+\(%r8\)
[ ]*[0-9a-f]+:[ ]+40 c5 f9 28 00[ ]+rex vmovapd \(%rax\),%xmm0
-[ ]*[0-9a-f]+:[ ]+40[ ]+rex
-[ ]*[0-9a-f]+:[ ]+41[ ]+rex.B
-[ ]*[0-9a-f]+:[ ]+42[ ]+rex.X
-[ ]*[0-9a-f]+:[ ]+43[ ]+rex.XB
-[ ]*[0-9a-f]+:[ ]+44[ ]+rex.R
-[ ]*[0-9a-f]+:[ ]+45[ ]+rex.RB
-[ ]*[0-9a-f]+:[ ]+46[ ]+rex.RX
-[ ]*[0-9a-f]+:[ ]+47[ ]+rex.RXB
-[ ]*[0-9a-f]+:[ ]+48[ ]+rex.W
-[ ]*[0-9a-f]+:[ ]+49[ ]+rex.WB
-[ ]*[0-9a-f]+:[ ]+4a[ ]+rex.WX
-[ ]*[0-9a-f]+:[ ]+4b[ ]+rex.WXB
-[ ]*[0-9a-f]+:[ ]+4c[ ]+rex.WR
-[ ]*[0-9a-f]+:[ ]+4d[ ]+rex.WRB
-[ ]*[0-9a-f]+:[ ]+4e[ ]+rex.WRX
-[ ]*[0-9a-f]+:[ ]+4f[ ]+rex.WRXB
+[ ]*[0-9a-f]+:[ ]+40 90[ ]+rex xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+41 90[ ]+xchg[ ]+%eax,%r8d
+[ ]*[0-9a-f]+:[ ]+42 90[ ]+rex.X xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+43 90[ ]+rex.XB xchg %eax,%r8d
+[ ]*[0-9a-f]+:[ ]+44 90[ ]+rex.R xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+45 90[ ]+rex.RB xchg %eax,%r8d
+[ ]*[0-9a-f]+:[ ]+46 90[ ]+rex.RX xchg %eax,%eax
+[ ]*[0-9a-f]+:[ ]+47 90[ ]+rex.RXB xchg %eax,%r8d
+[ ]*[0-9a-f]+:[ ]+48 90[ ]+rex.W nop
+[ ]*[0-9a-f]+:[ ]+49 90[ ]+xchg[ ]+%rax,%r8
+[ ]*[0-9a-f]+:[ ]+4a 90[ ]+rex.WX xchg %rax,%rax
+[ ]*[0-9a-f]+:[ ]+4b 90[ ]+rex.WXB xchg %rax,%r8
+[ ]*[0-9a-f]+:[ ]+4c 90[ ]+rex.WR xchg %rax,%rax
+[ ]*[0-9a-f]+:[ ]+4d 90[ ]+rex.WRB xchg %rax,%r8
+[ ]*[0-9a-f]+:[ ]+4e 90[ ]+rex.WRX xchg %rax,%rax
+[ ]*[0-9a-f]+:[ ]+4f 90[ ]+rex.WRXB xchg %rax,%r8
#pass
diff --git a/gas/testsuite/gas/i386/rex.s b/gas/testsuite/gas/i386/rex.s
index c1490ccdee..c33e538686 100644
--- a/gas/testsuite/gas/i386/rex.s
+++ b/gas/testsuite/gas/i386/rex.s
@@ -28,21 +28,36 @@ _start:
# Test prefixes family.
rex
+ nop
rex.B
+ nop
rex.X
+ nop
rex.XB
+ nop
rex.R
+ nop
rex.RB
+ nop
rex.RX
+ nop
rex.RXB
+ nop
rex.W
+ nop
rex.WB
+ nop
rex.WX
+ nop
rex.WXB
+ nop
rex.WR
+ nop
rex.WRB
+ nop
rex.WRX
+ nop
rex.WRXB
-# Make sure that the above rex prefix won't become the rex prefix for
-# the padding.
+ nop
rex
+ nop
diff --git a/gas/testsuite/gas/i386/white.l b/gas/testsuite/gas/i386/white.l
index 876c9d525f..c0ab623a09 100644
--- a/gas/testsuite/gas/i386/white.l
+++ b/gas/testsuite/gas/i386/white.l
@@ -3,8 +3,8 @@ GAS LISTING .*
1 # test handling of whitespace, and upper-case
2 .TeXt
- 3 0000 36 ss
- 4 0001 8803 mov % al , \( % ebx \)
+ 3 ss
+ 4 0000 368803 mov % al , \( % ebx \)
5 0003 C705D711 00007B00 0000 mOvl \$ 123 , 4567
6 000d 678A787B ADDr16 mov 123 \( % bx , % si , 1 \) , % bh
7 0011 FFE0 jmp \* % eax
diff --git a/gas/testsuite/gas/i386/x86-64-prefix-3.d b/gas/testsuite/gas/i386/x86-64-prefix-3.d
new file mode 100644
index 0000000000..2c29e3651a
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefix-3.d
@@ -0,0 +1,17 @@
+#name: x86-64 prefix 3
+#source: prefix-3.s
+#as: -defsym __64_bit__=1
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <test>:
+ +[a-f0-9]+: 65 f3 f0 0f c1 04 25 00 00 00 00 xrelease lock xadd %eax,%gs:0x0
+ +[a-f0-9]+: f3 aa rep stos %al,%es:\(%rdi\)
+ +[a-f0-9]+: f2 e9 00 00 00 00 bnd jmpq [a-f0-9]+ <test\+0x[a-f0-9]+>
+ +[a-f0-9]+: f3 c3 repz retq
+ +[a-f0-9]+: 48 e8 00 00 00 00 callq [a-f0-9]+ <test\+0x[a-f0-9]+>
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-prefix-4.d b/gas/testsuite/gas/i386/x86-64-prefix-4.d
new file mode 100644
index 0000000000..555a6d740b
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-prefix-4.d
@@ -0,0 +1,15 @@
+#name: x86-64 prefix 4
+#source: prefix-4.s
+#as: -defsym __64_bit__=1
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <test>:
+ +[a-f0-9]+: 74 03 je 5 <test\+0x5>
+ +[a-f0-9]+: 77 02 ja 6 <test\+0x6>
+ +[a-f0-9]+: f0 f3 0f b0 0c 25 00 00 00 00 lock xrelease cmpxchg %cl,0x0
+#pass
--
2.20.1