From a95c67907cce5b03269581b77f014ec51b98da36 Mon Sep 17 00:00:00 2001
From: bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Date: Mon, 9 Jun 2003 15:29:55 +0000
Subject: [PATCH] arm support

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@221 c046a42c-6fe2-441c-8c8c-71466251a162
---
 cpu-i386.h       | 46 ++++++++++++++++++++++++++++++++++++++--------
 exec.h           | 12 ++++++++++++
 translate-i386.c | 11 +++++++++++
 3 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/cpu-i386.h b/cpu-i386.h
index d277144b62..8d7e1d612e 100644
--- a/cpu-i386.h
+++ b/cpu-i386.h
@@ -238,7 +238,10 @@ static inline void stb(void *ptr, int v)
     *(uint8_t *)ptr = v;
 }
 
-#ifdef WORDS_BIGENDIAN
+/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
+   kernel handles unaligned load/stores may give better results, but
+   it is a system wide setting : bad */
+#if defined(WORDS_BIGENDIAN) || defined(__arm__)
 
 /* conservative code for little endian unaligned accesses */
 static inline int lduw(void *ptr)
@@ -329,24 +332,50 @@ static inline float ldfl(void *ptr)
     return u.f;
 }
 
+static inline void stfl(void *ptr, float v)
+{
+    union {
+        float f;
+        uint32_t i;
+    } u;
+    u.f = v;
+    stl(ptr, u.i);
+}
+
+#if defined(__arm__) && !defined(WORDS_BIGENDIAN)
+
+/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
 static inline double ldfq(void *ptr)
 {
     union {
         double d;
-        uint64_t i;
+        uint32_t tab[2];
     } u;
-    u.i = ldq(ptr);
+    u.tab[1] = ldl(ptr);
+    u.tab[0] = ldl(ptr + 4);
     return u.d;
 }
 
-static inline void stfl(void *ptr, float v)
+static inline void stfq(void *ptr, double v)
 {
     union {
-        float f;
-        uint32_t i;
+        double d;
+        uint32_t tab[2];
     } u;
-    u.f = v;
-    stl(ptr, u.i);
+    u.d = v;
+    stl(ptr, u.tab[1]);
+    stl(ptr + 4, u.tab[0]);
+}
+
+#else
+static inline double ldfq(void *ptr)
+{
+    union {
+        double d;
+        uint64_t i;
+    } u;
+    u.i = ldq(ptr);
+    return u.d;
 }
 
 static inline void stfq(void *ptr, double v)
@@ -358,6 +387,7 @@ static inline void stfq(void *ptr, double v)
     u.d = v;
     stq(ptr, u.i);
 }
+#endif
 
 #else
 
diff --git a/exec.h b/exec.h
index d8fc640b63..b6ba663640 100644
--- a/exec.h
+++ b/exec.h
@@ -246,6 +246,18 @@ static inline int testandset (int *p)
 }
 #endif
 
+#ifdef __arm__
+static inline int testandset (int *spinlock)
+{
+    register unsigned int ret;
+    __asm__ __volatile__("swp %0, %1, [%2]"
+                         : "=r"(ret)
+                         : "0"(1), "r"(spinlock));
+    
+    return ret;
+}
+#endif
+
 typedef int spinlock_t;
 
 #define SPIN_LOCK_UNLOCKED 0
diff --git a/translate-i386.c b/translate-i386.c
index 3802c5e925..c7d34b60a8 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -104,6 +104,16 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop)
 
 #endif
 
+#ifdef __arm__
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+    register unsigned long _beg __asm ("a1") = start;
+    register unsigned long _end __asm ("a2") = stop;
+    register unsigned long _flg __asm ("a3") = 0;
+    __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
+}
+#endif
+
 extern FILE *logfile;
 extern int loglevel;
 
@@ -166,6 +176,7 @@ enum {
     NB_OPS,
 };
 
+#include "dyngen.h"
 #include "op-i386.h"
 
 /* operand size */
-- 
GitLab