x86/Solaris: support Sun form of CMOVcc

Message ID e3d203cc-f4c1-434e-982f-8c7f676fd6af@suse.com
State New
Headers
Series x86/Solaris: support Sun form of CMOVcc |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Jan Beulich Nov. 18, 2024, 10:51 a.m. UTC
  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
---
While it's unclear whether the doc will ever be updated to cover APX,
CCMPcc and CTESTcc would naturally also want these alternative forms,
for also having (permitting) operand size suffixes.
  

Patch

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -7752,6 +7752,33 @@  parse_insn (const char *line, char *mnem
 	  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;
--- /dev/null
+++ b/gas/testsuite/gas/i386/solaris/cmov.d
@@ -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
--- /dev/null
+++ b/gas/testsuite/gas/i386/solaris/cmov.s
@@ -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
--- a/gas/testsuite/gas/i386/solaris/solaris.exp
+++ b/gas/testsuite/gas/i386/solaris/solaris.exp
@@ -32,6 +32,8 @@  if [expr ([istarget "i*86-*-*"] || [ista
     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"