Semantics of bsrq()/fls() differs on x64 and aarch64, e.g. following sample
inputs produce different results:

x64:                            aarch64:

bsrq(0x1) = 0                   bsrq(0x1) = 63
bsrq(0xffffffffffffffff) = 63   bsrq(0xffffffffffffffff) = 0
bsrq(0x8000000000000000) = 63   bsrq(0x8000000000000000) = 0
bsrq(0x80000000) = 31           bsrq(0x80000000) = 32
bsrq(0x8008) = 15               bsrq(0x8008) = 48

bsrl(0x1) = 0                   bsrl(0x1) = 63
bsrl(0xffffffff) = 31           bsrl(0xffffffff) = 32
bsrl(0x80000000) = 31           bsrl(0x80000000) = 32
bsrl(0x8008) = 15               bsrl(0x8008) = 48

fsl(0x1) = 1                    fsl(0x1) = 64
fsl(0xffffffff) = 32            fsl(0xffffffff) = 33
fsl(0x80000000) = 32            fsl(0x80000000) = 33
fsl(0x8008) = 16                fsl(0x8008) = 49

Which is not quite a behaviour bitops user expects.
Use GCC built-ins to overcome this, which provide consistent behaviour across
all platforms. Arch-specific instructions generated to avoid loops, so this
should not hurt performance.

Signed-off-by: Sergiy Kibrik <sergiy.kib...@globallogic.com>
---
 arch/aarch64/bitops.h | 31 -------------------------------
 arch/x64/bitops.h     | 31 -------------------------------
 bsd/porting/netport.h |  2 +-
 core/xen_intr.cc      |  2 +-
 include/osv/bitops.h  | 27 +++++++++++++++++++++++++++
 5 files changed, 29 insertions(+), 64 deletions(-)
 delete mode 100644 arch/aarch64/bitops.h
 delete mode 100644 arch/x64/bitops.h
 create mode 100644 include/osv/bitops.h

diff --git a/arch/aarch64/bitops.h b/arch/aarch64/bitops.h
deleted file mode 100644
index 0e04197..0000000
--- a/arch/aarch64/bitops.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2014 Huawei Technologies Duesseldorf GmbH
- *
- * This work is open source software, licensed under the terms of the
- * BSD license as described in the LICENSE file in the top-level directory.
- */
-
-#ifndef ARCH_BITOPS_H_
-#define ARCH_BITOPS_H_
-static inline unsigned int
-bsrl(unsigned int mask)
-{
-    unsigned int result;
-    asm volatile("clz %1,%0" : "=r" (result) : "r" (mask));
-    return result;
-}
-
-static inline unsigned long
-bsrq(unsigned long mask)
-{
-    unsigned long result;
-    asm volatile("clz %1,%0" : "=r" (result) : "r" (mask));
-    return result;
-}
-
-static inline int
-fls(int mask)
-{
-    return (mask == 0 ? mask : (int)bsrl((unsigned int)mask) + 1);
-}
-#endif /* ARCH_BITOPS_H */
diff --git a/arch/x64/bitops.h b/arch/x64/bitops.h
deleted file mode 100644
index b5f77da..0000000
--- a/arch/x64/bitops.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 Cloudius Systems, Ltd.
- *
- * This work is open source software, licensed under the terms of the
- * BSD license as described in the LICENSE file in the top-level directory.
- */
-
-#ifndef ARCH_BITOPS_H_
-#define ARCH_BITOPS_H_
-static inline unsigned int 
-bsrl(unsigned int mask)
-{
-    unsigned int result;
-    asm volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
-    return result;
-}
-
-static inline unsigned long
-bsrq(unsigned long mask)
-{
-    unsigned long result;
-    asm volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask));
-    return result;
-}
-
-static inline int
-fls(int mask)
-{
-    return (mask == 0 ? mask : (int)bsrl((unsigned int)mask) + 1);
-}
-#endif
diff --git a/bsd/porting/netport.h b/bsd/porting/netport.h
index 784298c..2604a4a 100644
--- a/bsd/porting/netport.h
+++ b/bsd/porting/netport.h
@@ -19,7 +19,7 @@
 #include <osv/debug.h>
 #define __NEED_socklen_t
 #include <bits/alltypes.h>
-#include "bitops.h"
+#include <osv/bitops.h>
 
 __BEGIN_DECLS
 
diff --git a/core/xen_intr.cc b/core/xen_intr.cc
index 45a1869..6ea52e5 100644
--- a/core/xen_intr.cc
+++ b/core/xen_intr.cc
@@ -9,7 +9,7 @@
 #include <osv/xen_intr.hh>
 #include <bsd/porting/bus.h>
 #include <machine/intr_machdep.h>
-#include "bitops.h"
+#include <osv/bitops.h>
 #include <osv/debug.hh>
 
 #include <osv/trace.hh>
diff --git a/include/osv/bitops.h b/include/osv/bitops.h
new file mode 100644
index 0000000..82b1b93
--- /dev/null
+++ b/include/osv/bitops.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 Cloudius Systems, Ltd.
+ *
+ * This work is open source software, licensed under the terms of the
+ * BSD license as described in the LICENSE file in the top-level directory.
+ */
+
+#ifndef ARCH_BITOPS_H_
+#define ARCH_BITOPS_H_
+static inline unsigned int
+bsrl(unsigned int mask)
+{
+    return sizeof(mask) * 8 - __builtin_clz(mask) - 1;
+}
+
+static inline unsigned long
+bsrq(unsigned long mask)
+{
+    return sizeof(mask) * 8 - __builtin_clzl(mask) - 1;
+}
+
+static inline int
+fls(int mask)
+{
+    return (mask == 0 ? mask : (int)bsrl((unsigned int)mask) + 1);
+}
+#endif
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to