]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
x86/Solaris: support Sun form of CMOVcc
authorJan Beulich <jbeulich@suse.com>
Fri, 29 Nov 2024 08:37:13 +0000 (09:37 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 29 Nov 2024 08:37:13 +0000 (09:37 +0100)
Sun specifies an alternative form for CMOVcc [1], which for some reason
we never cared to support, even if - as per gcc's configure checking for
it - it may have been the only permitted form at some point.

While documentation doesn't indicate FCMOVcc to have similar alternative
forms, gcc assumes so. Hence cover FCMOVcc as well.

[1] https://docs.oracle.com/cd/E37838_01/html/E61064/ennbz.html#XALRMeoizm

gas/config/tc-i386.c
gas/testsuite/gas/i386/solaris/cmov.d [new file with mode: 0644]
gas/testsuite/gas/i386/solaris/cmov.s [new file with mode: 0644]
gas/testsuite/gas/i386/solaris/solaris.exp

index ab4e57b95e4cf86e464849dd13eb3d7019ac67f3..55fd2be8b30cd2c7349e863260d608ca8c9e3022 100644 (file)
@@ -7757,6 +7757,33 @@ parse_insn (const char *line, char *mnemonic, enum parse_mode mode)
          else if (pp.disp_encoding != disp_encoding_32bit)
            as_warn (_("ignoring `.d32' suffix due to earlier `{disp<N>}'"));
        }
+#ifdef TE_SOLARIS
+      /* Sun specifies an alternative form for CMOVcc: Size suffix (if any)
+        first, then a dot, then the condition code mnemonic.  */
+      else if ((mnemonic + 4 == dot_p
+               && !memcmp (mnemonic, "cmov", 4))
+              /* While doc doesn't say so, gcc assumes it: Same for FCMOVcc,
+                 except that there's no size suffix to care about.  */
+              || (mnemonic + 5 == dot_p
+                  && !memcmp (mnemonic, "fcmov", 5)))
+       {
+         /* Simply strip the dot.  */
+         memmove (dot_p, dot_p + 1, mnem_p - dot_p);
+         dot_p = mnem_p - 1;
+       }
+      else if (!intel_syntax
+              && mnemonic + 5 == dot_p
+              && !memcmp (mnemonic, "cmov", 4)
+              && strchr ("lqw", TOLOWER (dot_p[-1])))
+       {
+         /* Strip the dot, while moving the suffix.  */
+         char suffix = dot_p[-1];
+
+         memmove (dot_p - 1, dot_p + 1, mnem_p - dot_p);
+         mnem_p[-2] = suffix;
+         dot_p = mnem_p - 1;
+       }
+#endif
       else
        goto check_suffix;
       mnem_p = dot_p;
diff --git a/gas/testsuite/gas/i386/solaris/cmov.d b/gas/testsuite/gas/i386/solaris/cmov.d
new file mode 100644 (file)
index 0000000..16467ad
--- /dev/null
@@ -0,0 +1,27 @@
+#objdump: -dw
+#name: {,F}CMOVcc alternative forms
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <cmov>:
+[      ]*[a-f0-9]+:    0f 47 c8                cmova  %eax,%ecx
+[      ]*[a-f0-9]+:    0f 47 c8                cmova  %eax,%ecx
+[      ]*[a-f0-9]+:    0f 47 c8                cmova  %eax,%ecx
+[      ]*[a-f0-9]+:    0f 47 c8                cmova  %eax,%ecx
+[      ]*[a-f0-9]+:    66 0f 4a c8             cmovp  %ax,%cx
+[      ]*[a-f0-9]+:    66 0f 4a c8             cmovp  %ax,%cx
+[      ]*[a-f0-9]+:    66 0f 4a c8             cmovp  %ax,%cx
+[      ]*[a-f0-9]+:    66 0f 4a c8             cmovp  %ax,%cx
+[      ]*[a-f0-9]+:    0f 4c 08                cmovl  \(%rax\),%ecx
+[      ]*[a-f0-9]+:    0f 4c 08                cmovl  \(%rax\),%ecx
+[      ]*[a-f0-9]+:    0f 4c 08                cmovl  \(%rax\),%ecx
+[      ]*[a-f0-9]+:    0f 4c 08                cmovl  \(%rax\),%ecx
+[      ]*[a-f0-9]+:    48 0f 44 08             cmove  \(%rax\),%rcx
+[      ]*[a-f0-9]+:    48 0f 44 08             cmove  \(%rax\),%rcx
+[      ]*[a-f0-9]+:    48 0f 44 08             cmove  \(%rax\),%rcx
+[      ]*[a-f0-9]+:    48 0f 44 08             cmove  \(%rax\),%rcx
+[      ]*[a-f0-9]+:    da d9                   fcmovu %st\(1\),%st
+[      ]*[a-f0-9]+:    da d9                   fcmovu %st\(1\),%st
+#pass
diff --git a/gas/testsuite/gas/i386/solaris/cmov.s b/gas/testsuite/gas/i386/solaris/cmov.s
new file mode 100644 (file)
index 0000000..e5026ef
--- /dev/null
@@ -0,0 +1,24 @@
+       .text
+cmov:
+       cmova           %eax, %ecx
+       cmov.a          %eax, %ecx
+       cmovnbe         %eax, %ecx
+       cmov.nbe        %eax, %ecx
+
+       cmovpw          %ax, %cx
+       cmovw.p         %ax, %cx
+       cmovpew         %ax, %cx
+       cmovw.pe        %ax, %cx
+
+       cmovll          (%rax), %ecx
+       cmovl.l         (%rax), %ecx
+       cmovngel        (%rax), %ecx
+       cmovl.nge       (%rax), %ecx
+
+       cmovzq          (%rax), %rcx
+       cmovq.z         (%rax), %rcx
+       cmoveq          (%rax), %rcx
+       cmovq.e         (%rax), %rcx
+
+       fcmovu          %st(1), %st
+       fcmov.u         %st(1), %st
index 6e4ddcafc3ff0264b8de400d37f0689a72c68a6d..dccdbf7d5bd8d3fa8539e0ba031422a88302f748 100644 (file)
@@ -32,6 +32,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check] &&
     set ASFLAGS "$ASFLAGS --64 --defsym x86_64=1 --strip-local-absolute"
 
     run_dump_test "reloc64"
+    run_dump_test "cmov"
+
     run_dump_test "x86-64-mpx-branch-1"
     run_dump_test "x86-64-mpx-branch-2"