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))