Use __builtin_bswap* for GUINT*_SWAP_LE_BE if building with GCC
authorSebastian Dröge <slomo@circular-chaos.org>
Sun, 18 Mar 2012 03:28:48 +0000 (23:28 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 18 Mar 2012 03:28:48 +0000 (23:28 -0400)
https://bugzilla.gnome.org/show_bug.cgi?id=531901

glib/gtypes.h
glib/tests/utils.c

index ca9e50d..7e4c8ea 100644 (file)
@@ -181,6 +181,12 @@ typedef const gchar *   (*GTranslateFunc)       (const gchar   *str,
 /* Arch specific stuff for speed
  */
 #if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
+
+#  if __GNUC__ >= 4 && defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 3
+#    define GUINT32_SWAP_LE_BE(val) ((guint32) __builtin_bswap32 ((gint32) val))
+#    define GUINT64_SWAP_LE_BE(val) ((guint64) __builtin_bswap64 ((gint64) val))
+#  endif
+
 #  if defined (__i386__)
 #    define GUINT16_SWAP_LE_BE_IA32(val) \
        (G_GNUC_EXTENSION                                       \
@@ -236,8 +242,12 @@ typedef const gchar *   (*GTranslateFunc)       (const gchar   *str,
           __r.__ll; }))
      /* Possibly just use the constant version and let gcc figure it out? */
 #    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA32 (val))
-#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA32 (val))
-#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA32 (val))
+#    ifndef GUINT32_SWAP_LE_BE
+#      define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA32 (val))
+#    endif
+#    ifndef GUINT64_SWAP_LE_BE
+#      define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA32 (val))
+#    endif
 #  elif defined (__ia64__)
 #    define GUINT16_SWAP_LE_BE_IA64(val) \
        (G_GNUC_EXTENSION                                       \
@@ -272,8 +282,12 @@ typedef const gchar *   (*GTranslateFunc)       (const gchar   *str,
                                   : "r" (__x));                \
           __v; }))
 #    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA64 (val))
-#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA64 (val))
-#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA64 (val))
+#    ifndef GUINT32_SWAP_LE_BE
+#      define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA64 (val))
+#    endif
+#    ifndef GUINT64_SWAP_LE_BE
+#      define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA64 (val))
+#    endif
 #  elif defined (__x86_64__)
 #    define GUINT32_SWAP_LE_BE_X86_64(val) \
        (G_GNUC_EXTENSION                                       \
@@ -297,12 +311,20 @@ typedef const gchar *   (*GTranslateFunc)       (const gchar   *str,
           __v; }))
      /* gcc seems to figure out optimal code for this on its own */
 #    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
-#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_X86_64 (val))
-#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_X86_64 (val))
+#    ifndef GUINT32_SWAP_LE_BE
+#      define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_X86_64 (val))
+#    endif
+#    ifndef GUINT64_SWAP_LE_BE
+#      define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_X86_64 (val))
+#    endif
 #  else /* generic gcc */
 #    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
-#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val))
-#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val))
+#    ifndef GUINT32_SWAP_LE_BE
+#      define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val))
+#    endif
+#    ifndef GUINT64_SWAP_LE_BE
+#      define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val))
+#    endif
 #  endif
 #else /* generic */
 #  define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
index b2c19b3..721a813 100644 (file)
@@ -208,6 +208,29 @@ test_bits (void)
 }
 
 static void
+test_swap (void)
+{
+  guint16 a16, b16;
+  guint32 a32, b32;
+  guint64 a64, b64;
+
+  a16 = 0xaabb;
+  b16 = 0xbbaa;
+
+  g_assert_cmpint (GUINT16_SWAP_LE_BE (a16), ==, b16);
+
+  a32 = 0xaaaabbbb;
+  b32 = 0xbbbbaaaa;
+
+  g_assert_cmpint (GUINT32_SWAP_LE_BE (a32), ==, b32);
+
+  a64 = 0xaaaaaaaabbbbbbbb;
+  b64 = 0xbbbbbbbbaaaaaaaa;
+
+  g_assert_cmpint (GUINT64_SWAP_LE_BE (a64), ==, b64);
+}
+
+static void
 test_find_program (void)
 {
   gchar *res;
@@ -319,6 +342,7 @@ main (int   argc,
   g_test_add_func ("/utils/appname", test_appname);
   g_test_add_func ("/utils/tmpdir", test_tmpdir);
   g_test_add_func ("/utils/bits", test_bits);
+  g_test_add_func ("/utils/swap", test_swap);
   g_test_add_func ("/utils/find-program", test_find_program);
   g_test_add_func ("/utils/debug", test_debug);
   g_test_add_func ("/utils/codeset", test_codeset);