diff options
-rw-r--r-- | cpu-i386.h | 46 | ||||
-rw-r--r-- | exec.h | 12 | ||||
-rw-r--r-- | 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 @@ -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 */ |