+2016-01-29 Andrew Senkevich <andrew.senkevich@intel.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/tc-i386.c (avoid_fence): New.
+ (output_insn): Encode as lock addl $0x0, (%{r,e}sp) if avoid_fence
+ is true.
+ (OPTION_FENCE_AS_LOCK_ADD): New.
+ (md_longopts): Add -mfence-as-lock-add.
+ (md_parse_option): Handle -mfence-as-lock-add.
+ (md_show_usage): Add -mfence-as-lock-add=[no|yes].
+ * doc/c-i386.texi (-mfence-as-lock-add): Document.
+ * gas/i386/i386.exp: Run new tests.
+ * gas/i386/fence-as-lock-add.s: New.
+ * gas/i386/fence-as-lock-add-yes.d: Likewise.
+ * gas/i386/fence-as-lock-add-no.d: Likewise.
+ * gas/i386/x86-64-fence-as-lock-add-yes.d: Likewise.
+ * gas/i386/x86-64-fence-as-lock-add-no.d: Likewise.
+
2016-01-27 H.J. Lu <hongjiu.lu@intel.com>
* configure.ac (compressed_debug_sections): Remove trailing `]'.
specified explicitly. */
static int omit_lock_prefix = 0;
+/* 1 if the assembler should encode lfence, mfence, and sfence as
+ "lock addl $0, (%{re}sp)". */
+static int avoid_fence = 0;
+
static enum check_kind
{
check_none = 0,
unsigned int j;
unsigned int prefix;
+ if (avoid_fence
+ && i.tm.base_opcode == 0xfae
+ && i.operands == 1
+ && i.imm_operands == 1
+ && (i.op[0].imms->X_add_number == 0xe8
+ || i.op[0].imms->X_add_number == 0xf0
+ || i.op[0].imms->X_add_number == 0xf8))
+ {
+ /* Encode lfence, mfence, and sfence as
+ f0 83 04 24 00 lock addl $0x0, (%{re}sp). */
+ offsetT val = 0x240483f0ULL;
+ p = frag_more (5);
+ md_number_to_chars (p, val, 5);
+ return;
+ }
+
/* Some processors fail on LOCK prefix. This options makes
assembler ignore LOCK prefix and serves as a workaround. */
if (omit_lock_prefix)
#define OPTION_MSHARED (OPTION_MD_BASE + 21)
#define OPTION_MAMD64 (OPTION_MD_BASE + 22)
#define OPTION_MINTEL64 (OPTION_MD_BASE + 23)
+#define OPTION_MFENCE_AS_LOCK_ADD (OPTION_MD_BASE + 24)
struct option md_longopts[] =
{
{"mbig-obj", no_argument, NULL, OPTION_MBIG_OBJ},
#endif
{"momit-lock-prefix", required_argument, NULL, OPTION_MOMIT_LOCK_PREFIX},
+ {"mfence-as-lock-add", required_argument, NULL, OPTION_MFENCE_AS_LOCK_ADD},
{"mevexrcig", required_argument, NULL, OPTION_MEVEXRCIG},
{"mamd64", no_argument, NULL, OPTION_MAMD64},
{"mintel64", no_argument, NULL, OPTION_MINTEL64},
as_fatal (_("invalid -momit-lock-prefix= option: `%s'"), arg);
break;
+ case OPTION_MFENCE_AS_LOCK_ADD:
+ if (strcasecmp (arg, "yes") == 0)
+ avoid_fence = 1;
+ else if (strcasecmp (arg, "no") == 0)
+ avoid_fence = 0;
+ else
+ as_fatal (_("invalid -mfence-as-lock-add= option: `%s'"), arg);
+ break;
+
case OPTION_MAMD64:
cpu_arch_flags.bitfield.cpuamd64 = 1;
cpu_arch_flags.bitfield.cpuintel64 = 0;
-momit-lock-prefix=[no|yes]\n\
strip all lock prefixes\n"));
fprintf (stream, _("\
+ -mfence-as-lock-add=[no|yes]\n\
+ encode lfence, mfence and sfence as\n\
+ lock addl $0x0, (%%{re}sp)\n"));
+ fprintf (stream, _("\
-mamd64 accept only AMD64 ISA\n"));
fprintf (stream, _("\
-mintel64 accept only Intel64 ISA\n"));
@option{-momit-lock-prefix=@var{no}} will encode lock prefix as usual,
which is the default.
+@cindex @samp{-mfence-as-lock-add=} option, i386
+@cindex @samp{-mfence-as-lock-add=} option, x86-64
+@item -mfence-as-lock-add=@var{no}
+@itemx -mfence-as-lock-add=@var{yes}
+These options control how the assembler should encode lfence, mfence and
+sfence.
+@option{-mfence-as-lock-add=@var{yes}} will encode lfence, mfence and
+sfence as @samp{lock addl $0x0, (%rsp)} in 64-bit mode and
+@samp{lock addl $0x0, (%esp)} in 32-bit mode.
+@option{-mfence-as-lock-add=@var{no}} will encode lfence, mfence and
+sfence as usual, which is the default.
+
@cindex @samp{-mevexrcig=} option, i386
@cindex @samp{-mevexrcig=} option, x86-64
@item -mevexrcig=@var{rne}
--- /dev/null
+#source: fence-as-lock-add.s
+#as: -mfence-as-lock-add=no
+#objdump: -dw
+#name: i386 fence as lock add = no
+
+.*: +file format .*i386.*
+
+Disassembly of section .text:
+
+0+ <main>:
+[ ]*[a-f0-9]+: 0f ae e8[ ]* lfence
+[ ]*[a-f0-9]+: 0f ae f0[ ]* mfence
+[ ]*[a-f0-9]+: 0f ae f8[ ]* sfence
+#pass
--- /dev/null
+#source: fence-as-lock-add.s
+#as: -mfence-as-lock-add=yes
+#objdump: -dw
+#name: i386 fence as lock add = yes
+
+.*: +file format .*i386.*
+
+Disassembly of section .text:
+
+0+ <main>:
+[ ]*[a-f0-9]+: f0 83 04 24 00[ ]* lock addl \$0x0,\(%esp\)
+[ ]*[a-f0-9]+: f0 83 04 24 00[ ]* lock addl \$0x0,\(%esp\)
+[ ]*[a-f0-9]+: f0 83 04 24 00[ ]* lock addl \$0x0,\(%esp\)
+#pass
--- /dev/null
+ .text
+.globl main
+main:
+ lfence
+ mfence
+ sfence
run_dump_test "avx512dq_vl"
run_dump_test "omit-lock-yes"
run_dump_test "omit-lock-no"
+ run_dump_test "fence-as-lock-add-yes"
+ run_dump_test "fence-as-lock-add-no"
run_dump_test "avx512dq-rcigrd-intel"
run_dump_test "avx512dq-rcigrd"
run_dump_test "avx512dq-rcigrne-intel"
run_dump_test "x86-64-mwaitx-bdver4"
run_list_test "x86-64-mwaitx-reg"
run_dump_test "x86-64-ospke"
+ run_dump_test "x86-64-fence-as-lock-add-yes"
+ run_dump_test "x86-64-fence-as-lock-add-no"
if { ![istarget "*-*-aix*"]
&& ![istarget "*-*-beos*"]
--- /dev/null
+#source: fence-as-lock-add.s
+#as: -mfence-as-lock-add=no
+#objdump: -dw
+#name: x86-64 fence as lock add = no
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <main>:
+[ ]*[a-f0-9]+: 0f ae e8[ ]* lfence
+[ ]*[a-f0-9]+: 0f ae f0[ ]* mfence
+[ ]*[a-f0-9]+: 0f ae f8[ ]* sfence
+#pass
--- /dev/null
+#source: fence-as-lock-add.s
+#as: -mfence-as-lock-add=yes
+#objdump: -dw
+#name: x86-64 fence as lock add = yes
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <main>:
+[ ]*[a-f0-9]+: f0 83 04 24 00[ ]* lock addl \$0x0,\(%rsp\)
+[ ]*[a-f0-9]+: f0 83 04 24 00[ ]* lock addl \$0x0,\(%rsp\)
+[ ]*[a-f0-9]+: f0 83 04 24 00[ ]* lock addl \$0x0,\(%rsp\)
+#pass