Hello,

MSVC and ICC (currently Windows version, Linux version soon) have
dedicated intrinsics to read/set EFLAGS register ([1], [2]).

Patch introduces these intrinsics and tests for them.

Bootstrapped. New tests pass.
Although gate is closed patch is obvious.
So, is it ok for trunk?

ChangeLog/
        * config/i386/ia32intrin.h (__readeflags): New.
        (__writeeflags): Ditto.

testsuite/ChangeLog/
        * gcc.target/i386/readeflags-1.c: New.
        * gcc.target/i386/writeeflags-1.c: Ditto.

[1] - http://msdn.microsoft.com/en-us/library/aa983406(v=vs.90).aspx
[2] - http://msdn.microsoft.com/en-us/library/aa983392(v=vs.90).aspx

--
Thanks, K

diff --git a/gcc/config/i386/ia32intrin.h b/gcc/config/i386/ia32intrin.h
index b26dc46..c9e68c5 100644
--- a/gcc/config/i386/ia32intrin.h
+++ b/gcc/config/i386/ia32intrin.h
@@ -238,6 +238,34 @@ __rorq (unsigned long long __X, int __C)
   return (__X >> __C) | (__X << (64 - __C));
 }
 
+/* Read flags register */
+extern __inline unsigned long long
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__readeflags (void)
+{
+  unsigned long long result = 0;
+  __asm__ __volatile__ ("pushf\n\t"
+                       "popq %0\n"
+                       :"=r"(result)
+                       :
+                       :
+                       );
+  return result;
+}
+
+/* Write flags register */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__writeeflags (unsigned long long X)
+{
+  __asm__ __volatile__ ("pushq %0\n\t"
+                       "popf\n"
+                       :
+                       :"r"(X)
+                       :"flags"
+                       );
+}
+
 #define _bswap64(a)            __bswapq(a)
 #define _popcnt64(a)           __popcntq(a)
 #define _lrotl(a,b)            __rolq((a), (b))
@@ -245,6 +273,35 @@ __rorq (unsigned long long __X, int __C)
 #else
 #define _lrotl(a,b)            __rold((a), (b))
 #define _lrotr(a,b)            __rord((a), (b))
+
+/* Read flags register */
+extern __inline unsigned int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__readeflags (void)
+{
+  unsigned int result = 0;
+  __asm__ __volatile__ ("pushf\n\t"
+                       "popl %0\n"
+                       :"=r"(result)
+                       :
+                       :
+                       );
+  return result;
+}
+
+/* Write flags register */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__writeeflags (unsigned int X)
+{
+  __asm__ __volatile__ ("pushl %0\n\t"
+                       "popf\n"
+                       :
+                       :"r"(X)
+                       :"flags"
+                       );
+}
+
 #endif
 
 #define _bit_scan_forward(a)   __bsfd(a)
diff --git a/gcc/testsuite/gcc.target/i386/readeflags-1.c 
b/gcc/testsuite/gcc.target/i386/readeflags-1.c
new file mode 100644
index 0000000..6b2fa7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/readeflags-1.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O0" } */
+
+#include <x86intrin.h>
+
+#ifdef __x86_64__
+#define EFLAGS_TYPE unsigned long long int
+#else
+#define EFLAGS_TYPE unsigned int
+#endif
+
+static EFLAGS_TYPE
+readeflags_test (unsigned int a, unsigned int b)
+{
+  unsigned x = (a == b);
+  return __readeflags ();
+}
+
+int
+main ()
+{
+  EFLAGS_TYPE flags;
+
+  flags = readeflags_test (100, 100);
+
+  if ((flags & 1) != 0)  /* Read CF */
+    abort ();
+
+  flags = readeflags_test (100, 101);
+
+  if ((flags & 1) == 0)  /* Read CF */
+    abort ();
+
+#ifdef DEBUG
+    printf ("PASSED\n");
+#endif
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/writeeflags-1.c 
b/gcc/testsuite/gcc.target/i386/writeeflags-1.c
new file mode 100644
index 0000000..446840c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/writeeflags-1.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-O0" } */
+
+#include <x86intrin.h>
+
+#ifdef __x86_64__
+#define EFLAGS_TYPE unsigned long long int
+#else
+#define EFLAGS_TYPE unsigned int
+#endif
+
+int
+main ()
+{
+  EFLAGS_TYPE flags = 0xD7; /* 111010111b  */
+
+  __writeeflags (flags);
+
+  flags = __readeflags ();
+
+  if ((flags & 0xFF) != 0xD7)
+    abort ();
+
+#ifdef DEBUG
+    printf ("PASSED\n");
+#endif
+
+  return 0;
+}
+

Reply via email to