about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--buildtools/endiangen.c6
-rw-r--r--common.mk4
-rw-r--r--converter/pbm/pbmtog3.c1
-rw-r--r--lib/util/wordaccess.h30
-rw-r--r--lib/util/wordaccess_64_le.h48
-rw-r--r--lib/util/wordaccess_gcc3_be.h17
-rw-r--r--lib/util/wordaccess_gcc3_le.h56
-rw-r--r--lib/util/wordaccess_generic.h74
-rw-r--r--lib/util/wordintclz.h93
9 files changed, 136 insertions, 193 deletions
diff --git a/buildtools/endiangen.c b/buildtools/endiangen.c
index 07560c10..6b88b896 100644
--- a/buildtools/endiangen.c
+++ b/buildtools/endiangen.c
@@ -59,9 +59,9 @@ byteOrder(void) {
 
 
 static unsigned int
-bitsPerWord(void) {
+bitsPerLong(void) {
 
-    return MAX(sizeof(long), sizeof(int)) * 8;
+    return sizeof(long) * 8;
 }
 
 
@@ -87,7 +87,7 @@ main(int argc, char **argv) {
            byteOrder() == ENDIAN_LITTLE ? "LITTLE_ENDIAN" : "BIG_ENDIAN");
     printf("#endif\n");
     printf("\n");
-    printf("#define BITS_PER_WORD %u\n", bitsPerWord());
+    printf("#define BITS_PER_LONG %u\n", bitsPerLong());
 
     return 0;
 }
diff --git a/common.mk b/common.mk
index 277c71a9..9e13a7c8 100644
--- a/common.mk
+++ b/common.mk
@@ -125,8 +125,8 @@ IMPORTINC_LIB_HEADERS := \
 IMPORTINC_LIB_UTIL_HEADERS := \
   bitarith.h bitreverse.h filename.h intcode.h floatcode.h mallocvar.h\
   nsleep.h nstring.h pm_c_util.h shhopt.h \
-  wordaccess.h wordaccess_64_le.h wordaccess_gcc3_be.h wordaccess_gcc3_le.h \
-  wordaccess_generic.h \
+  wordaccess.h wordaccess_64_le.h wordaccess_gcc3_be.h wordaccess_generic.h \
+  wordintclz.h
 
 IMPORTINC_HEADERS := \
   $(IMPORTINC_ROOT_HEADERS) \
diff --git a/converter/pbm/pbmtog3.c b/converter/pbm/pbmtog3.c
index 44d9a26b..f53bfaa0 100644
--- a/converter/pbm/pbmtog3.c
+++ b/converter/pbm/pbmtog3.c
@@ -23,6 +23,7 @@
 #include "mallocvar.h"
 #include "bitreverse.h"
 #include "wordaccess.h"
+#include "wordintclz.h"
 #include "g3.h"
 #include "pbm.h"
 
diff --git a/lib/util/wordaccess.h b/lib/util/wordaccess.h
index 08034361..2eaa2b24 100644
--- a/lib/util/wordaccess.h
+++ b/lib/util/wordaccess.h
@@ -36,31 +36,39 @@
    work with that.
 
    We also assume that a char is 8 bits.
+
+   HAVE_GCC_BITCOUNT and HAVE_GCC_BSWAP are set in pm_config.h
+
+   BITS_PER_LONG is the number of bits in long int.
 */
 
 #include "pm_config.h"
 
-#if (!defined(WORDACCESS_GENERIC) \
-     && defined(__GNUC__) && defined(__GLIBC__) \
-     && (__GNUC__ * 100 + __GNUC_MINOR__ >= 304) )
-
-    #if BYTE_ORDER==BIG_ENDIAN    /* defined by GCC */
+#if (!defined(WORDACCESS_GENERIC) && HAVE_GCC_BITCOUNT )
 
+    #if BYTE_ORDER == BIG_ENDIAN    /* See pm_config.h */
+        /* Sun Sparc 64, etc */ 
         #include "wordaccess_gcc3_be.h"
 
-    #elif defined(__ia64__) || defined(__amd64__) || defined(__x86_64__)
-         /* all these macros are defined by GCC */
-
+    #elif (BITS_PER_LONG == 64)
+        /* AMD Athlon 64, Intel x86_64, Intel Itanium, etc. */
         #include "wordaccess_64_le.h"
 
-    #else
+    #elif (BITS_PER_LONG == 32)
+        /* Intel x86_32 (80386, 80486, Pentium), etc. */
+        #include "wordaccess_generic.h"
 
-        #include "wordaccess_gcc3_le.h"
+    #else
+        /* Extremely rare case.
+           If long is neither 32 nor 64 bits, (say, 128) it comes here.
+        */
+        #define WORDACCESS_GENERIC
+        #include "wordaccess_generic.h"
 
     #endif
 
 #else
-
+    /* Non GCC, GCC prior to v.3.4 or WORDACCESS_GENERIC defined  */
     #include "wordaccess_generic.h"
 
 #endif
diff --git a/lib/util/wordaccess_64_le.h b/lib/util/wordaccess_64_le.h
index ad316df2..4d148ad2 100644
--- a/lib/util/wordaccess_64_le.h
+++ b/lib/util/wordaccess_64_le.h
@@ -2,28 +2,21 @@
   This file is the part of wordaccess.h for use under these
   conditions:
 
-  * GCC (>=3.4), GLIBC
-  * 64 bit Little-Endian machines (IA64, X86-64, AMD64)
-=============================================================================*/
-   
-/*  
-    64 bit hton and ntoh do not exist.  Here we use bswap_64.
-    
-    While bswap_64 works on 64 bit data, __builtin_clzl works on "long" which
-    may or may not be 64 bits.  Code provided to find the right data type and
-    file off any extra when necessary.
-*/
-
-#include <byteswap.h>  /* See note above on bswap_64 */
-
-#include "pm.h"
+  * GCC (>=3.4)  (__builtin_clz appears in GCC 3.4)
+  * Little-Endian machines (IA64, X86-64, AMD64)
+  * 64 bit long
  
+=============================================================================*/
+
+#include "intcode.h"
+
 typedef uint64_t wordint;
 typedef unsigned char wordintBytes[sizeof(wordint)];
 
+
 static __inline__ wordint
-bytesToWordint(wordintBytes bytes) {
-    return ((wordint) bswap_64(*(wordint *)bytes));
+bytesToWordint(wordintBytes const bytes) {
+    return (wordint) pm_uintFromBigend64(*(bigend64*)bytes);
 }
 
 
@@ -31,24 +24,5 @@ bytesToWordint(wordintBytes bytes) {
 static __inline__ void
 wordintToBytes(wordintBytes * const bytesP,
                wordint        const wordInt) {
-    *(wordint *)bytesP = bswap_64(wordInt);
-}
-
-
-
-static __inline__ unsigned int
-wordintClz(wordint const x){
-
-    unsigned int s;
-
-    if (x == 0)
-        return sizeof(wordint) * 8;
-
-    /* Find the data type closest to 64 bits, and file off any extra. */
-    else if ((s=sizeof(long int)) >= 8)
-        return (__builtin_clzl((long int)x << (s - 8) * 8));
-    else if ((s=sizeof(long long int)) >= 8)
-        return (__builtin_clzll((long long int)x << (s - 8) * 8));
-    else
-        pm_error("Long long int is less than 64 bits on this machine"); 
+     *(bigend64*)bytesP = pm_bigendFromUint64(wordInt);
 }
diff --git a/lib/util/wordaccess_gcc3_be.h b/lib/util/wordaccess_gcc3_be.h
index 6f5d86fc..5aa63521 100644
--- a/lib/util/wordaccess_gcc3_be.h
+++ b/lib/util/wordaccess_gcc3_be.h
@@ -4,16 +4,6 @@
 
   * GCC (>=3.4), GLIBC
   * Big-Endian machines
-  
-  __builtin_clz is available on GCC 3.4 and above
-     
-  Note that the clz scheme does not work and requires adjustment
-  if long type does not make use of all bits for data storage.
-  
-  This is unlikely.  According to GNU MP (http://www.swox.com/gmp/),
-  in rare cases such as Cray, there are smaller data types that take up
-  the same space as long, but leave the higher bits silent.  Currently,
-  there are no known such cases for data type long.
 *===========================================================================*/
 
 typedef unsigned long int wordint;
@@ -31,10 +21,3 @@ wordintToBytes(wordintBytes * const bytesP,
                wordint        const wordInt) {
     *(wordint *)bytesP = wordInt;
 }
-
-
-
-static __inline__ unsigned int
-wordintClz(wordint const x) {
-    return (x==0 ? sizeof(wordint)*8 : __builtin_clzl(x));
-}
diff --git a/lib/util/wordaccess_gcc3_le.h b/lib/util/wordaccess_gcc3_le.h
deleted file mode 100644
index 798566af..00000000
--- a/lib/util/wordaccess_gcc3_le.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*=============================================================================
-
-  This file is the part of wordaccess.h for use under these
-  conditions:
-
-  * GCC (>=3.4), GLIBC
-  * 32 bit Little-Endian machines (intel MPUs 80386, Pentium, etc.)
-  * Other non-Big-Endian machines (very rare)
-  
-=============================================================================*/
-
-typedef uint32_t wordint;
-typedef unsigned char wordintBytes[sizeof(wordint)];
-
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#include "pm.h"
-
-/*
-  Here we use the more widely used functions htonl and ntohl instead of
-  bswap_32.  This makes possible the handling of weird byte ordering
-  (neither Big-Endian nor Little-Endian) schemes, if any.
-*/
-
-static __inline__ wordint
-bytesToWordint(wordintBytes const bytes) {
-    return (wordint) ntohl(*(wordint *)bytes);
-}
-
-
-
-static __inline__ void
-wordintToBytes(wordintBytes * const bytesP,
-               wordint        const wordInt) {
-
-    *(wordint *)bytesP = htonl(wordInt);
-}
-
-
-
-static __inline__ unsigned int
-wordintClz(wordint const x) {
-
-    /* Find the data type closest to 32 bits, and file off any extra.  */
-
-    if (x == 0)
-        return sizeof(wordint) * 8;
-    else if (sizeof(int) >= 4)
-        return __builtin_clz((int)x << (sizeof(int) - 4) * 8);
-    else if (sizeof(long int) >= 4)
-        return __builtin_clzl((long int)x << (sizeof(long int) - 4) * 8);
-    else
-        pm_error("Long int is less than 32 bits on this machine"); 
-}
-
diff --git a/lib/util/wordaccess_generic.h b/lib/util/wordaccess_generic.h
index 7f27ef74..94cc8124 100644
--- a/lib/util/wordaccess_generic.h
+++ b/lib/util/wordaccess_generic.h
@@ -5,85 +5,25 @@
 
   * Compilers other than GCC
   * GCC before version 3.4
-  * c libraries other than Glibc
   * Specified by the user with WORDACCESS_GENERIC
 =============================================================================*/
 
+#include "intcode.h"
+
 typedef uint32_t wordint;
 typedef unsigned char wordintBytes[sizeof(wordint)];
+
     
 static __inline__ wordint
-bytesToWordint(wordintBytes const bytes) {
-    wordint retval;
-    unsigned int i;
+bytesToWordint(wordintBytes  const bytes) {
 
-    /* Note that 'bytes' is a pointer, due to C array degeneration.
-       That means sizeof(bytes) isn't what you think it is.
-    */
-    
-    for (i = 1, retval = bytes[0]; i < sizeof(wordint); ++i) {
-        retval = (retval << 8) + bytes[i];
-    }
-    return retval;
+    return (wordint)  pm_uintFromBigend32( * (bigend32*) bytes);
 }
 
 
-
 static __inline__ void
 wordintToBytes(wordintBytes * const bytesP,
-               wordint        const wordInt) {
-
-    wordint buffer;
-    int i;
-
-    for (i = sizeof(*bytesP)-1, buffer = wordInt; i >= 0; --i) {
-        (*bytesP)[i] = buffer & 0xFF;
-        buffer >>= 8;
-    }
-}
-    
-static unsigned char const clz8[256]= {
-    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
-    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
-};
-
-
-
-static __inline__ unsigned int
-clz16(wordint const x) {
-    if (x >> 8  != 0)
-        return clz8[x >> 8];
-    else
-        return clz8[x] + 8;
-}
-
-
-
-static __inline__  unsigned int
-clz32(wordint const x) {
-    if (x >> 16  != 0)
-        return clz16(x >> 16);
-    else
-        return clz16(x) +16;
-}
-
-
+               wordint    const wordInt) {
 
-static __inline__  unsigned int
-wordintClz(wordint const x) {
-    return clz32(x);
+    * (bigend32*) bytesP = pm_bigendFromUint32((uint32_t)wordInt);
 }
diff --git a/lib/util/wordintclz.h b/lib/util/wordintclz.h
new file mode 100644
index 00000000..32e6ade8
--- /dev/null
+++ b/lib/util/wordintclz.h
@@ -0,0 +1,93 @@
+#ifndef WORDINTCLZ_H_INCLUDED
+#define WORDINTCLZ_H_INCLUDED
+
+#if (!defined(WORDACCESS_GENERIC) && HAVE_GCC_BITCOUNT )
+/* 
+   Compiler is GCC and has __builtin_clz()
+   wordint is long 
+ 
+   __builtin_clz is available on GCC 3.4 and above
+     
+   Note that the clz scheme does not work and requires adjustment
+   if long type does not make use of all bits for data storage.
+  
+   This is unlikely.  According to GNU MP (http://www.swox.com/gmp/),
+   in rare cases such as Cray, there are smaller data types that take up
+   the same space as long, but leave the higher bits silent.
+   Currently, there are no known such cases for data type long.
+ */
+
+static __inline__ unsigned int
+wordintClz(wordint const x){
+
+    assert(sizeof(unsigned long int) == sizeof(wordint));
+
+    if (x == 0)
+        return sizeof(wordint) * 8;
+    else
+        return (__builtin_clzl( (unsigned long int) x ));
+}
+  
+#else
+
+/* wordint is uint32_t: exactly 32 bits wide */
+ 
+static unsigned char const clz8[256]= {
+    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
+};
+
+
+
+static __inline__ unsigned int
+clz16(wordint const x) {
+
+    if (x >> 8 != 0)
+        return clz8[x >> 8];
+    else
+        return clz8[x] + 8;
+}
+
+
+
+static __inline__  unsigned int
+clz32(wordint const x) {
+
+    if (x >> 16 != 0)
+        return clz16(x >> 16);
+    else
+        return clz16(x) + 16;
+}
+
+
+
+static __inline__  unsigned int
+wordintClz(wordint const x) {
+
+    assert(sizeof(wordint) == 4);
+
+    return clz32(x);
+}
+
+/* Another way to calculate leading zeros:
+   x == 0 ? 32 : 31 - floor(log(x)/log(2))
+   (Beware: insufficient precision will cause errors)
+*/
+
+#endif
+
+#endif