List:Internals« Previous MessageNext Message »
From:Pat Beirne Date:February 6 2001 6:47am
Subject:Patch for ARM version
View as plain text  
Subject: building MySQL on ARM/StrongARM
Versions: all 3.23.*, tested on 3.23.32
Linux: 2.2.14
Glibc: 2.1.0
GCC: 2.95.2



Thanks for a great program.

I work with the NetWinder, a Linux machine based on the
StrongARM processor. The MySQL code deals well with little-endian
machines and big-endian machines, but the ARM is (unfortunately)
a hybrid.

Ints are stored as little-endian. Doubles are stored as
two consecutive little-endian words, with the MOST SIGNIFICANT
WORD FIRST!.

Gnu tools handle this case with the #include <endian.h> file,
which now has a #define __FLOAT_WORD_ORDER.

So, here are the three cases that can exist:
1. i386
	__BYTE_ORDER == __LITTLE_ENDIAN
	__FLOAT_WORD_ORDER == __LITTLE_ENDIAN
2. PPC, 68000
	__BYTE_ORDER == __BIG_ENDIAN
	__FLOAT_WORD_ORDER == __BIG_ENDIAN
3. ARM
	__BYTE_ORDER == __LITTLE_ENDIAN
	__FLOAT_WORD_ORDER == __BIG_ENDIAN

Also, the ARM processors are very sensitive to
aligned access.

I patched/changed 4 files:

sql/filesort.cc
	change change_double_for_sort() to include
        the byte-juggling appropriate for this case
sql/field.cc
	change Field_double::cmp(const char*, const char*)
        to deal with the byte-juggling
        and Field_double::sort_string(char*, uint)
        for the same reason
include/myisampack.h
	mi_float8store/get() are changed similarly.
include/global.h and include/my_global.h
	doublestore/get() are redefined so that
	they do the scrambling; later in the .h file,
        float8store/get() is defined in terms of
        doublestore/get()

The changes in sql/field.cc could probably be done without
the #define, just by replacing the memcpy() with a call
to doubleget(). I did not do this, because I did not check
a build on an i386 machine.

After these changes, all the "mysql-test" cases work.

I did not discover any other files which might be affected
by this endian thing.

I used #ifdef's based on the __FLOAT_WORD_ORDER and __LITTLE_ENDIAN
defines. Is this portable enough?

A patch agains 3.23.32 follows. After the patch, please do
      "cp include/global.h include/my_global.h"
      

Pat Beirne
March Networks
pbeirne@stripped


--- sql/filesort.cc.orig	Wed Jan 24 07:47:48 2001
+++ sql/filesort.cc	Wed Jan 24 23:18:23 2001
@@ -932,8 +932,13 @@
 #else
     {
       uchar *ptr= (uchar*) &nr;
+#if (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
+      tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
+      tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
+#else
       tmp[0]= ptr[7]; tmp[1]=ptr[6]; tmp[2]= ptr[5]; tmp[3]=ptr[4];
       tmp[4]= ptr[3]; tmp[5]=ptr[2]; tmp[6]= ptr[1]; tmp[7]=ptr[0];
+#endif
     }
 #endif
     if (tmp[0] & 128)				/* Negative */

--- field.cc.orig	Mon Jan 22 08:37:04 2001
+++ field.cc	Tue Feb  6 00:12:16 2001
@@ -2106,8 +2106,14 @@
   else
 #endif
   {
+/* could this ALWAYS be 2 calls to doubleget() ?? */
+#if (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
+    doubleget(a, a_ptr);
+    doubleget(b, b_ptr);
+#else
     memcpy_fixed(&a,a_ptr,sizeof(double));
     memcpy_fixed(&b,b_ptr,sizeof(double));
+#endif
   }
   return (a < b) ? -1 : (a > b) ? 1 : 0;
 }
@@ -2127,7 +2133,12 @@
   }
   else
 #endif
+/* could this ALWAYS be 2 calls to doubleget() ?? */
+#if (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
+    doubleget(nr,ptr);
+#else
     memcpy_fixed(&nr,ptr,sizeof(nr));
+#endif
   change_double_for_sort(nr, (byte*) to);
 }
 


     
--- include/myisampack.h.orig	Thu Jan 25 01:06:22 2001
+++ include/myisampack.h	Thu Jan 25 01:05:52 2001
@@ -167,6 +167,28 @@
 			      ((byte*) &def_temp)[3]=(M)[0];\
 			      (V)=def_temp; }
 
+#if (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
+#define mi_float8store(T,V) { *(T)= ((byte *) &V)[3];\
+			      *((T)+1)=(char) ((byte *) &V)[2];\
+			      *((T)+2)=(char) ((byte *) &V)[1];\
+			      *((T)+3)=(char) ((byte *) &V)[0];\
+			      *((T)+4)=(char) ((byte *) &V)[7];\
+			      *((T)+5)=(char) ((byte *) &V)[6];\
+			      *((T)+6)=(char) ((byte *) &V)[5];\
+			      *((T)+7)=(char) ((byte *) &V)[4];}
+
+#define mi_float8get(V,M)   { double def_temp;\
+			      ((byte*) &def_temp)[0]=(M)[3];\
+			      ((byte*) &def_temp)[1]=(M)[2];\
+			      ((byte*) &def_temp)[2]=(M)[1];\
+			      ((byte*) &def_temp)[3]=(M)[0];\
+			      ((byte*) &def_temp)[4]=(M)[7];\
+			      ((byte*) &def_temp)[5]=(M)[6];\
+			      ((byte*) &def_temp)[6]=(M)[5];\
+			      ((byte*) &def_temp)[7]=(M)[4];\
+			      (V)=def_temp; }
+
+#else
 #define mi_float8store(T,V) { *(T)= ((byte *) &V)[7];\
 			      *((T)+1)=(char) ((byte *) &V)[6];\
 			      *((T)+2)=(char) ((byte *) &V)[5];\
@@ -186,7 +208,8 @@
 			      ((byte*) &def_temp)[6]=(M)[1];\
 			      ((byte*) &def_temp)[7]=(M)[0];\
 			      (V)=def_temp; }
-#endif
+#endif // __FLOAT_WORD_ORDER			      
+#endif // WORDS_BIGENDIAN
 
 /* Fix to avoid warnings when sizeof(ha_rows) == sizeof(long) */
 
--- global.h.orig	Mon Jan 22 08:37:04 2001
+++ global.h	Mon Feb  5 22:29:51 2001
@@ -811,6 +811,28 @@
 #else
 #define float4get(V,M)   memcpy_fixed((byte*) &V,(byte*) (M),sizeof(float))
 #define float4store(V,M) memcpy_fixed((byte*) V,(byte*) (&M),sizeof(float))
+
+#if (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
+#define doublestore(T,V)    { *(T)= ((byte *) &V)[4];\
+                              *((T)+1)=(char) ((byte *) &V)[5];\
+                              *((T)+2)=(char) ((byte *) &V)[6];\
+                              *((T)+3)=(char) ((byte *) &V)[7];\
+                              *((T)+4)=(char) ((byte *) &V)[0];\
+                              *((T)+5)=(char) ((byte *) &V)[1];\
+                              *((T)+6)=(char) ((byte *) &V)[2];\
+                              *((T)+7)=(char) ((byte *) &V)[3]; }
+#define doubleget(V,M) { double def_temp;\
+                              ((byte*) &def_temp)[0]=(M)[4];\
+                              ((byte*) &def_temp)[1]=(M)[5];\
+                              ((byte*) &def_temp)[2]=(M)[6];\
+                              ((byte*) &def_temp)[3]=(M)[7];\
+                              ((byte*) &def_temp)[4]=(M)[0];\
+                              ((byte*) &def_temp)[5]=(M)[1];\
+                              ((byte*) &def_temp)[6]=(M)[2];\
+                              ((byte*) &def_temp)[7]=(M)[3];\
+			      (V) = def_temp; }
+#endif // __FLOAT_WORD_ORDER
+
 #define float8get(V,M)   doubleget((V),(M))
 #define float8store(V,M) doublestore((V),(M))
 #endif /* WORDS_BIGENDIAN */
@@ -863,7 +885,7 @@
 #ifndef doubleget
 #define doubleget(V,M)	 memcpy_fixed((byte*) &V,(byte*) (M),sizeof(double))
 #define doublestore(T,V) memcpy_fixed((byte*) (T),(byte*) &V,sizeof(double))
-#endif
+#endif // doubleget
 #define longlongget(V,M) memcpy_fixed((byte*) &V,(byte*) (M),sizeof(ulonglong))
 #define longlongstore(T,V) memcpy_fixed((byte*) (T),(byte*) &V,sizeof(ulonglong))
 
Thread
Patch for ARM versionPat Beirne6 Feb
  • Patch for ARM versionMichael Widenius6 Feb