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;
+}
+