From e4e00185b58fd15c74913f19f4d5fb311b239e21 Mon Sep 17 00:00:00 2001 From: Andrew Senkevich Date: Fri, 29 Jan 2016 15:46:50 +0300 Subject: [PATCH] Add option -mfence-as-lock-add=[no|yes]. With -mfence-as-lock-add=yes lfence, mfence and sfence will be encoded as lock addl $0x0, (%{r,e}sp). gas/: * 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/testsuite/: * 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. --- gas/ChangeLog | 18 ++++++++++ gas/config/tc-i386.c | 35 +++++++++++++++++++ gas/doc/c-i386.texi | 12 +++++++ gas/testsuite/gas/i386/fence-as-lock-add-no.d | 14 ++++++++ .../gas/i386/fence-as-lock-add-yes.d | 14 ++++++++ gas/testsuite/gas/i386/fence-as-lock-add.s | 6 ++++ gas/testsuite/gas/i386/i386.exp | 4 +++ .../gas/i386/x86-64-fence-as-lock-add-no.d | 14 ++++++++ .../gas/i386/x86-64-fence-as-lock-add-yes.d | 14 ++++++++ 9 files changed, 131 insertions(+) create mode 100644 gas/testsuite/gas/i386/fence-as-lock-add-no.d create mode 100644 gas/testsuite/gas/i386/fence-as-lock-add-yes.d create mode 100644 gas/testsuite/gas/i386/fence-as-lock-add.s create mode 100644 gas/testsuite/gas/i386/x86-64-fence-as-lock-add-no.d create mode 100644 gas/testsuite/gas/i386/x86-64-fence-as-lock-add-yes.d diff --git a/gas/ChangeLog b/gas/ChangeLog index b210227fc03..a4bfa720c1e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,21 @@ +2016-01-29 Andrew Senkevich + H.J. Lu + + * 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 * configure.ac (compressed_debug_sections): Remove trailing `]'. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 62f247c7af4..3a98b21d955 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -552,6 +552,10 @@ static int allow_index_reg = 0; 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, @@ -6956,6 +6960,22 @@ output_insn (void) 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) @@ -9622,6 +9642,7 @@ const char *md_shortopts = "qn"; #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[] = { @@ -9653,6 +9674,7 @@ 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}, @@ -9972,6 +9994,15 @@ md_parse_option (int c, char *arg) 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; @@ -10152,6 +10183,10 @@ md_show_usage (FILE *stream) -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")); diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi index 2f6485df478..357851a3126 100644 --- a/gas/doc/c-i386.texi +++ b/gas/doc/c-i386.texi @@ -327,6 +327,18 @@ single-thread computers @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} diff --git a/gas/testsuite/gas/i386/fence-as-lock-add-no.d b/gas/testsuite/gas/i386/fence-as-lock-add-no.d new file mode 100644 index 00000000000..208306668d8 --- /dev/null +++ b/gas/testsuite/gas/i386/fence-as-lock-add-no.d @@ -0,0 +1,14 @@ +#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+
: +[ ]*[a-f0-9]+: 0f ae e8[ ]* lfence +[ ]*[a-f0-9]+: 0f ae f0[ ]* mfence +[ ]*[a-f0-9]+: 0f ae f8[ ]* sfence +#pass diff --git a/gas/testsuite/gas/i386/fence-as-lock-add-yes.d b/gas/testsuite/gas/i386/fence-as-lock-add-yes.d new file mode 100644 index 00000000000..4ee63007fae --- /dev/null +++ b/gas/testsuite/gas/i386/fence-as-lock-add-yes.d @@ -0,0 +1,14 @@ +#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+
: +[ ]*[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 diff --git a/gas/testsuite/gas/i386/fence-as-lock-add.s b/gas/testsuite/gas/i386/fence-as-lock-add.s new file mode 100644 index 00000000000..5ecb1d99f2b --- /dev/null +++ b/gas/testsuite/gas/i386/fence-as-lock-add.s @@ -0,0 +1,6 @@ + .text +.globl main +main: + lfence + mfence + sfence diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index e23a4e59685..b9144c4a9d4 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -303,6 +303,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] 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" @@ -731,6 +733,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t 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*"] diff --git a/gas/testsuite/gas/i386/x86-64-fence-as-lock-add-no.d b/gas/testsuite/gas/i386/x86-64-fence-as-lock-add-no.d new file mode 100644 index 00000000000..9277448a270 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-fence-as-lock-add-no.d @@ -0,0 +1,14 @@ +#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+
: +[ ]*[a-f0-9]+: 0f ae e8[ ]* lfence +[ ]*[a-f0-9]+: 0f ae f0[ ]* mfence +[ ]*[a-f0-9]+: 0f ae f8[ ]* sfence +#pass diff --git a/gas/testsuite/gas/i386/x86-64-fence-as-lock-add-yes.d b/gas/testsuite/gas/i386/x86-64-fence-as-lock-add-yes.d new file mode 100644 index 00000000000..9451cd80a34 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-fence-as-lock-add-yes.d @@ -0,0 +1,14 @@ +#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+
: +[ ]*[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 -- 2.30.2