about summary refs log tree commit diff
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
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
-rw-r--r--common.mk3
-rw-r--r--doc/HISTORY3
-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
-rw-r--r--pm_config.in.h10
7 files changed, 80 insertions, 35 deletions
diff --git a/common.mk b/common.mk
index b445ea19..4077f2ea 100644
--- a/common.mk
+++ b/common.mk
@@ -144,7 +144,8 @@ IMPORTINC_LIB_UTIL_HEADERS := \
   bitarith.h bitreverse.h filename.h intcode.h floatcode.h io.h \
   matrix.h mallocvar.h \
   nsleep.h nstring.h pm_c_util.h shhopt.h token.h \
-  wordaccess.h wordaccess_64_le.h wordaccess_gcc3_be.h wordaccess_generic.h \
+  wordaccess.h  wordaccess_generic.h wordaccess_64_le.h \
+  wordaccess_be_aligned.h wordaccess_be_unaligned.h \
   wordintclz.h
 
 IMPORTINC_HEADERS := \
diff --git a/doc/HISTORY b/doc/HISTORY
index 578a2bd0..721da7ed 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -19,6 +19,9 @@ not yet  BJH  Release 10.63.00
               middle of the AND mask.  Always broken (program was new in
               Netpbm 9.3 (June 2000)).
 
+              sparc64 pbmtog3: fix bug that causes crash due to unaligned
+              memory access.
+
               install: fix Perl warning in installnetpbm.  Broken in 10.61.
 
               build: fix problem with creating lib/util that already exists.
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"
diff --git a/pm_config.in.h b/pm_config.in.h
index 3e2f781c..d8e578a3 100644
--- a/pm_config.in.h
+++ b/pm_config.in.h
@@ -290,6 +290,16 @@
 #endif
 #endif
 
+/* UNALIGNED_OK means it's OK to do unaligned memory access, e.g.
+   loading an 8-byte word from an address that is not a multiple of 8.
+   On some systems, such an access causes a trap and a signal.
+*/
+
+#if defined(__sparc__)
+# define UNALIGNED_OK 0
+#else
+# define UNALIGNED_OK 1
+#endif
 
 
 /* CONFIGURE: Some systems seem to need more than standard program linkage