about summary refs log tree commit diff
path: root/lib/util
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2013-05-02 16:24:22 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2013-05-02 16:24:22 +0000
commit67b7c93971748e23254c2768545c15631fc111b9 (patch)
treec27a89b14a09d01bead559753ae2fad04296e032 /lib/util
parent62f18c5e354db1cd2584a6267ddbd9ac8bff80e4 (diff)
downloadnetpbm-mirror-67b7c93971748e23254c2768545c15631fc111b9.tar.gz
netpbm-mirror-67b7c93971748e23254c2768545c15631fc111b9.tar.xz
netpbm-mirror-67b7c93971748e23254c2768545c15631fc111b9.zip
Fix unaligned memory access on Sparc
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1892 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/util')
-rw-r--r--lib/util/wordaccess.h51
-rw-r--r--lib/util/wordaccess_be_aligned.h35
-rw-r--r--lib/util/wordaccess_be_unaligned.h (renamed from lib/util/wordaccess_gcc3_be.h)7
-rw-r--r--lib/util/wordaccess_generic.h6
4 files changed, 65 insertions, 34 deletions
diff --git a/lib/util/wordaccess.h b/lib/util/wordaccess.h
index 2eaa2b24..09a896c4 100644
--- a/lib/util/wordaccess.h
+++ b/lib/util/wordaccess.h
@@ -44,33 +44,32 @@
 
 #include "pm_config.h"
 
-#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 (BITS_PER_LONG == 64)
-        /* AMD Athlon 64, Intel x86_64, Intel Itanium, etc. */
-        #include "wordaccess_64_le.h"
-
-    #elif (BITS_PER_LONG == 32)
-        /* Intel x86_32 (80386, 80486, Pentium), etc. */
-        #include "wordaccess_generic.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
-
+#if defined(WORDACCESS_GENERIC)
+  /* User wants this, regardless of whether machine can do better */
+  #include "wordaccess_generic.h"
+#elif BYTE_ORDER == BIG_ENDIAN
+  #if UNALIGNED_OK
+     #include wordaccess_be_unaligned.h
+  #else
+    /* Sparc */
+    #include wordaccess_be_aligned.h
+  #endif
+#elif HAVE_GCC_BITCOUNT
+  #if (BITS_PER_LONG == 64)
+    /* AMD Athlon 64, Intel x86_64, Intel Itanium, etc. */
+    #include "wordaccess_64_le.h"
+  #elif (BITS_PER_LONG == 32)
+    /* Intel x86_32 (80386, 80486, Pentium), etc. */
+      #include "wordaccess_generic.h"
+  #else
+     /* Extremely rare case.
+        If long is neither 32 nor 64 bits, (say, 128) it comes here.
+     */
+     #include "wordaccess_generic.h"
+  #endif
 #else
-    /* Non GCC, GCC prior to v.3.4 or WORDACCESS_GENERIC defined  */
-    #include "wordaccess_generic.h"
-
+  /* Non GCC or GCC prior to v.3.4; little-endian  */
+  #include "wordaccess_generic.h"
 #endif
 
 #endif
diff --git a/lib/util/wordaccess_be_aligned.h b/lib/util/wordaccess_be_aligned.h
new file mode 100644
index 00000000..0d5809e6
--- /dev/null
+++ b/lib/util/wordaccess_be_aligned.h
@@ -0,0 +1,35 @@
+/*=============================================================================
+  This file is the part of wordaccess.h for use under with big-endian
+  machines that require word accesses to be word-aligned.
+*===========================================================================*/
+
+typedef unsigned long int wordint;
+typedef unsigned char wordintBytes[sizeof(wordint)];
+
+static __inline__ wordint
+bytesToWordint(wordintBytes bytes) {
+    uint16_t const hi = *((uint16_t *) (bytes + 0));
+    uint16_t const mh = *((uint16_t *) (bytes + 2));
+    uint16_t const ml = *((uint16_t *) (bytes + 4));
+    uint16_t const lo = *((uint16_t *) (bytes + 6));
+    return
+        (((wordint) hi) << 48) |
+        (((wordint) mh) << 32) |
+        (((wordint) ml) << 24) |
+        (((wordint) lo) <<  0);
+}
+
+
+
+static __inline__ void
+wordintToBytes(wordintBytes * const bytesP,
+               wordint        const wordInt) {
+    uint16_t const hi = ((wordInt >> 48) & 0xFF)
+    uint16_t const mh = ((wordInt >> 32) & 0xFF);
+    uint16_t const ml = ((wordInt >> 24) & 0xFF);
+    uint16_t const lo = ((wordInt >>  0) & 0xFF);
+    *(uint16_t *)(bytesP + 0) = hi;
+    *(uint16_t *)(bytesP + 2) = mh;
+    *(uint16_t *)(bytesP + 4) = ml;
+    *(uint16_t *)(bytesP + 6) = lo;
+}
diff --git a/lib/util/wordaccess_gcc3_be.h b/lib/util/wordaccess_be_unaligned.h
index 5aa63521..95b68ac7 100644
--- a/lib/util/wordaccess_gcc3_be.h
+++ b/lib/util/wordaccess_be_unaligned.h
@@ -1,9 +1,6 @@
 /*=============================================================================
-  This file is the part of wordaccess.h for use under these
-  conditions:
-
-  * GCC (>=3.4), GLIBC
-  * Big-Endian machines
+  This file is the part of wordaccess.h for use on a big-endian machine
+  that does not require word accesses to be word-aligned.
 *===========================================================================*/
 
 typedef unsigned long int wordint;
diff --git a/lib/util/wordaccess_generic.h b/lib/util/wordaccess_generic.h
index 94cc8124..6e0a20ef 100644
--- a/lib/util/wordaccess_generic.h
+++ b/lib/util/wordaccess_generic.h
@@ -1,11 +1,11 @@
 /*=============================================================================
 
-  This file is the part of wordaccess.h for use under these
+  This file is the part of wordaccess.h for use under any of these
   conditions:
 
-  * Compilers other than GCC
+  * Compiler other than GCC
   * GCC before version 3.4
-  * Specified by the user with WORDACCESS_GENERIC
+  * Requested by the user with WORDACCESS_GENERIC
 =============================================================================*/
 
 #include "intcode.h"