From a95c67907cce5b03269581b77f014ec51b98da36 Mon Sep 17 00:00:00 2001 From: bellard 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 | 52 ++++++++++++++++++++++++++++++++++++++---------- exec.h | 12 +++++++++++ translate-i386.c | 11 ++++++++++ 3 files changed, 64 insertions(+), 11 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,16 +332,6 @@ static inline float ldfl(void *ptr) return u.f; } -static inline double ldfq(void *ptr) -{ - union { - double d; - uint64_t i; - } u; - u.i = ldq(ptr); - return u.d; -} - static inline void stfl(void *ptr, float v) { union { @@ -349,6 +342,42 @@ static inline void stfl(void *ptr, float 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; + uint32_t tab[2]; + } u; + u.tab[1] = ldl(ptr); + u.tab[0] = ldl(ptr + 4); + return u.d; +} + +static inline void stfq(void *ptr, double v) +{ + union { + double d; + uint32_t tab[2]; + } u; + 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) { union { @@ -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 */