aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2008-01-15 13:32:13 +0200
committerLasse Collin <lasse.collin@tukaani.org>2008-01-15 13:32:13 +0200
commit10437b5b567f6a025ff16c45a572e417a0a9cc26 (patch)
treeba8b5193ebc795865aa1bea387081b5ad77e52ef /src/liblzma/common
parentFixed assembler detection in configure.ac, and added (diff)
downloadxz-10437b5b567f6a025ff16c45a572e417a0a9cc26.tar.xz
Added bsr.h.
Diffstat (limited to 'src/liblzma/common')
-rw-r--r--src/liblzma/common/Makefile.am1
-rw-r--r--src/liblzma/common/bsr.h61
2 files changed, 62 insertions, 0 deletions
diff --git a/src/liblzma/common/Makefile.am b/src/liblzma/common/Makefile.am
index 4eb9d54e..a2eacfd8 100644
--- a/src/liblzma/common/Makefile.am
+++ b/src/liblzma/common/Makefile.am
@@ -24,6 +24,7 @@ libcommon_la_CPPFLAGS = \
libcommon_la_SOURCES = \
common.h \
sysdefs.h \
+ bsr.h \
allocator.c \
block_private.h \
extra.c \
diff --git a/src/liblzma/common/bsr.h b/src/liblzma/common/bsr.h
new file mode 100644
index 00000000..fd5d3b04
--- /dev/null
+++ b/src/liblzma/common/bsr.h
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file bsr.h
+/// \brief Bit scan reverse
+//
+// This code has been put into the public domain.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BSR_H
+#define LZMA_BSR_H
+
+// NOTE: Both input and output variables for lzma_bsr must be uint32_t.
+
+#if defined(__GNUC__) && (defined (HAVE_ASM_X86) || defined(HAVE_ASM_X86_64))
+# define lzma_bsr(dest, n) \
+ __asm__("bsrl %1, %0" : "=r" (dest) : "rm" (n))
+
+#else
+# define lzma_bsr(dest, n) dest = lzma_bsr_helper(n)
+
+static inline uint32_t
+lzma_bsr_helper(uint32_t n)
+{
+ assert(n != 0);
+
+ uint32_t i = 31;
+
+ if ((n & UINT32_C(0xFFFF0000)) == 0) {
+ n <<= 16;
+ i = 15;
+ }
+
+ if ((n & UINT32_C(0xFF000000)) == 0) {
+ n <<= 8;
+ i -= 8;
+ }
+
+ if ((n & UINT32_C(0xF0000000)) == 0) {
+ n <<= 4;
+ i -= 4;
+ }
+
+ if ((n & UINT32_C(0xC0000000)) == 0) {
+ n <<= 2;
+ i -= 2;
+ }
+
+ if ((n & UINT32_C(0x80000000)) == 0)
+ --i;
+
+ return i;
+}
+
+#endif
+
+#endif