|
@@ -35,8 +35,6 @@
|
|
|
* TARGET_WORDS_BIGENDIAN : same for target cpu
|
|
|
*/
|
|
|
|
|
|
-#include "softfloat.h"
|
|
|
-
|
|
|
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
|
|
#define BSWAP_NEEDED
|
|
|
#endif
|
|
@@ -114,64 +112,6 @@ static inline void tswap64s(uint64_t *s)
|
|
|
#define bswaptls(s) bswap64s(s)
|
|
|
#endif
|
|
|
|
|
|
-typedef union {
|
|
|
- float32 f;
|
|
|
- uint32_t l;
|
|
|
-} CPU_FloatU;
|
|
|
-
|
|
|
-/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
|
|
|
- endian ! */
|
|
|
-typedef union {
|
|
|
- float64 d;
|
|
|
-#if defined(HOST_WORDS_BIGENDIAN)
|
|
|
- struct {
|
|
|
- uint32_t upper;
|
|
|
- uint32_t lower;
|
|
|
- } l;
|
|
|
-#else
|
|
|
- struct {
|
|
|
- uint32_t lower;
|
|
|
- uint32_t upper;
|
|
|
- } l;
|
|
|
-#endif
|
|
|
- uint64_t ll;
|
|
|
-} CPU_DoubleU;
|
|
|
-
|
|
|
-typedef union {
|
|
|
- floatx80 d;
|
|
|
- struct {
|
|
|
- uint64_t lower;
|
|
|
- uint16_t upper;
|
|
|
- } l;
|
|
|
-} CPU_LDoubleU;
|
|
|
-
|
|
|
-typedef union {
|
|
|
- float128 q;
|
|
|
-#if defined(HOST_WORDS_BIGENDIAN)
|
|
|
- struct {
|
|
|
- uint32_t upmost;
|
|
|
- uint32_t upper;
|
|
|
- uint32_t lower;
|
|
|
- uint32_t lowest;
|
|
|
- } l;
|
|
|
- struct {
|
|
|
- uint64_t upper;
|
|
|
- uint64_t lower;
|
|
|
- } ll;
|
|
|
-#else
|
|
|
- struct {
|
|
|
- uint32_t lowest;
|
|
|
- uint32_t lower;
|
|
|
- uint32_t upper;
|
|
|
- uint32_t upmost;
|
|
|
- } l;
|
|
|
- struct {
|
|
|
- uint64_t lower;
|
|
|
- uint64_t upper;
|
|
|
- } ll;
|
|
|
-#endif
|
|
|
-} CPU_QuadU;
|
|
|
-
|
|
|
/* CPU memory access without any memory or io remapping */
|
|
|
|
|
|
/*
|
|
@@ -207,392 +147,8 @@ typedef union {
|
|
|
* user : user mode access using soft MMU
|
|
|
* kernel : kernel mode access using soft MMU
|
|
|
*/
|
|
|
-static inline int ldub_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(uint8_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldsb_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(int8_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stb_p(void *ptr, int v)
|
|
|
-{
|
|
|
- *(uint8_t *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-/* 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(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
|
|
|
-
|
|
|
-/* conservative code for little endian unaligned accesses */
|
|
|
-static inline int lduw_le_p(const void *ptr)
|
|
|
-{
|
|
|
-#ifdef _ARCH_PPC
|
|
|
- int val;
|
|
|
- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
|
|
|
- return val;
|
|
|
-#else
|
|
|
- const uint8_t *p = ptr;
|
|
|
- return p[0] | (p[1] << 8);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldsw_le_p(const void *ptr)
|
|
|
-{
|
|
|
-#ifdef _ARCH_PPC
|
|
|
- int val;
|
|
|
- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
|
|
|
- return (int16_t)val;
|
|
|
-#else
|
|
|
- const uint8_t *p = ptr;
|
|
|
- return (int16_t)(p[0] | (p[1] << 8));
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldl_le_p(const void *ptr)
|
|
|
-{
|
|
|
-#ifdef _ARCH_PPC
|
|
|
- int val;
|
|
|
- __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
|
|
|
- return val;
|
|
|
-#else
|
|
|
- const uint8_t *p = ptr;
|
|
|
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline uint64_t ldq_le_p(const void *ptr)
|
|
|
-{
|
|
|
- const uint8_t *p = ptr;
|
|
|
- uint32_t v1, v2;
|
|
|
- v1 = ldl_le_p(p);
|
|
|
- v2 = ldl_le_p(p + 4);
|
|
|
- return v1 | ((uint64_t)v2 << 32);
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stw_le_p(void *ptr, int v)
|
|
|
-{
|
|
|
-#ifdef _ARCH_PPC
|
|
|
- __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
|
|
|
-#else
|
|
|
- uint8_t *p = ptr;
|
|
|
- p[0] = v;
|
|
|
- p[1] = v >> 8;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stl_le_p(void *ptr, int v)
|
|
|
-{
|
|
|
-#ifdef _ARCH_PPC
|
|
|
- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
|
|
|
-#else
|
|
|
- uint8_t *p = ptr;
|
|
|
- p[0] = v;
|
|
|
- p[1] = v >> 8;
|
|
|
- p[2] = v >> 16;
|
|
|
- p[3] = v >> 24;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stq_le_p(void *ptr, uint64_t v)
|
|
|
-{
|
|
|
- uint8_t *p = ptr;
|
|
|
- stl_le_p(p, (uint32_t)v);
|
|
|
- stl_le_p(p + 4, v >> 32);
|
|
|
-}
|
|
|
-
|
|
|
-/* float access */
|
|
|
-
|
|
|
-static inline float32 ldfl_le_p(const void *ptr)
|
|
|
-{
|
|
|
- union {
|
|
|
- float32 f;
|
|
|
- uint32_t i;
|
|
|
- } u;
|
|
|
- u.i = ldl_le_p(ptr);
|
|
|
- return u.f;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfl_le_p(void *ptr, float32 v)
|
|
|
-{
|
|
|
- union {
|
|
|
- float32 f;
|
|
|
- uint32_t i;
|
|
|
- } u;
|
|
|
- u.f = v;
|
|
|
- stl_le_p(ptr, u.i);
|
|
|
-}
|
|
|
-
|
|
|
-static inline float64 ldfq_le_p(const void *ptr)
|
|
|
-{
|
|
|
- CPU_DoubleU u;
|
|
|
- u.l.lower = ldl_le_p(ptr);
|
|
|
- u.l.upper = ldl_le_p(ptr + 4);
|
|
|
- return u.d;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfq_le_p(void *ptr, float64 v)
|
|
|
-{
|
|
|
- CPU_DoubleU u;
|
|
|
- u.d = v;
|
|
|
- stl_le_p(ptr, u.l.lower);
|
|
|
- stl_le_p(ptr + 4, u.l.upper);
|
|
|
-}
|
|
|
-
|
|
|
-#else
|
|
|
-
|
|
|
-static inline int lduw_le_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(uint16_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldsw_le_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(int16_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldl_le_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(uint32_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline uint64_t ldq_le_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(uint64_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stw_le_p(void *ptr, int v)
|
|
|
-{
|
|
|
- *(uint16_t *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stl_le_p(void *ptr, int v)
|
|
|
-{
|
|
|
- *(uint32_t *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stq_le_p(void *ptr, uint64_t v)
|
|
|
-{
|
|
|
- *(uint64_t *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-/* float access */
|
|
|
-
|
|
|
-static inline float32 ldfl_le_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(float32 *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline float64 ldfq_le_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(float64 *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfl_le_p(void *ptr, float32 v)
|
|
|
-{
|
|
|
- *(float32 *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfq_le_p(void *ptr, float64 v)
|
|
|
-{
|
|
|
- *(float64 *)ptr = v;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
|
|
|
-
|
|
|
-static inline int lduw_be_p(const void *ptr)
|
|
|
-{
|
|
|
-#if defined(__i386__)
|
|
|
- int val;
|
|
|
- asm volatile ("movzwl %1, %0\n"
|
|
|
- "xchgb %b0, %h0\n"
|
|
|
- : "=q" (val)
|
|
|
- : "m" (*(uint16_t *)ptr));
|
|
|
- return val;
|
|
|
-#else
|
|
|
- const uint8_t *b = ptr;
|
|
|
- return ((b[0] << 8) | b[1]);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldsw_be_p(const void *ptr)
|
|
|
-{
|
|
|
-#if defined(__i386__)
|
|
|
- int val;
|
|
|
- asm volatile ("movzwl %1, %0\n"
|
|
|
- "xchgb %b0, %h0\n"
|
|
|
- : "=q" (val)
|
|
|
- : "m" (*(uint16_t *)ptr));
|
|
|
- return (int16_t)val;
|
|
|
-#else
|
|
|
- const uint8_t *b = ptr;
|
|
|
- return (int16_t)((b[0] << 8) | b[1]);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldl_be_p(const void *ptr)
|
|
|
-{
|
|
|
-#if defined(__i386__) || defined(__x86_64__)
|
|
|
- int val;
|
|
|
- asm volatile ("movl %1, %0\n"
|
|
|
- "bswap %0\n"
|
|
|
- : "=r" (val)
|
|
|
- : "m" (*(uint32_t *)ptr));
|
|
|
- return val;
|
|
|
-#else
|
|
|
- const uint8_t *b = ptr;
|
|
|
- return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline uint64_t ldq_be_p(const void *ptr)
|
|
|
-{
|
|
|
- uint32_t a,b;
|
|
|
- a = ldl_be_p(ptr);
|
|
|
- b = ldl_be_p((uint8_t *)ptr + 4);
|
|
|
- return (((uint64_t)a<<32)|b);
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stw_be_p(void *ptr, int v)
|
|
|
-{
|
|
|
-#if defined(__i386__)
|
|
|
- asm volatile ("xchgb %b0, %h0\n"
|
|
|
- "movw %w0, %1\n"
|
|
|
- : "=q" (v)
|
|
|
- : "m" (*(uint16_t *)ptr), "0" (v));
|
|
|
-#else
|
|
|
- uint8_t *d = (uint8_t *) ptr;
|
|
|
- d[0] = v >> 8;
|
|
|
- d[1] = v;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stl_be_p(void *ptr, int v)
|
|
|
-{
|
|
|
-#if defined(__i386__) || defined(__x86_64__)
|
|
|
- asm volatile ("bswap %0\n"
|
|
|
- "movl %0, %1\n"
|
|
|
- : "=r" (v)
|
|
|
- : "m" (*(uint32_t *)ptr), "0" (v));
|
|
|
-#else
|
|
|
- uint8_t *d = (uint8_t *) ptr;
|
|
|
- d[0] = v >> 24;
|
|
|
- d[1] = v >> 16;
|
|
|
- d[2] = v >> 8;
|
|
|
- d[3] = v;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stq_be_p(void *ptr, uint64_t v)
|
|
|
-{
|
|
|
- stl_be_p(ptr, v >> 32);
|
|
|
- stl_be_p((uint8_t *)ptr + 4, v);
|
|
|
-}
|
|
|
-
|
|
|
-/* float access */
|
|
|
-
|
|
|
-static inline float32 ldfl_be_p(const void *ptr)
|
|
|
-{
|
|
|
- union {
|
|
|
- float32 f;
|
|
|
- uint32_t i;
|
|
|
- } u;
|
|
|
- u.i = ldl_be_p(ptr);
|
|
|
- return u.f;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfl_be_p(void *ptr, float32 v)
|
|
|
-{
|
|
|
- union {
|
|
|
- float32 f;
|
|
|
- uint32_t i;
|
|
|
- } u;
|
|
|
- u.f = v;
|
|
|
- stl_be_p(ptr, u.i);
|
|
|
-}
|
|
|
-
|
|
|
-static inline float64 ldfq_be_p(const void *ptr)
|
|
|
-{
|
|
|
- CPU_DoubleU u;
|
|
|
- u.l.upper = ldl_be_p(ptr);
|
|
|
- u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
|
|
|
- return u.d;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfq_be_p(void *ptr, float64 v)
|
|
|
-{
|
|
|
- CPU_DoubleU u;
|
|
|
- u.d = v;
|
|
|
- stl_be_p(ptr, u.l.upper);
|
|
|
- stl_be_p((uint8_t *)ptr + 4, u.l.lower);
|
|
|
-}
|
|
|
-
|
|
|
-#else
|
|
|
-
|
|
|
-static inline int lduw_be_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(uint16_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldsw_be_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(int16_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline int ldl_be_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(uint32_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline uint64_t ldq_be_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(uint64_t *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stw_be_p(void *ptr, int v)
|
|
|
-{
|
|
|
- *(uint16_t *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stl_be_p(void *ptr, int v)
|
|
|
-{
|
|
|
- *(uint32_t *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stq_be_p(void *ptr, uint64_t v)
|
|
|
-{
|
|
|
- *(uint64_t *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-/* float access */
|
|
|
-
|
|
|
-static inline float32 ldfl_be_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(float32 *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline float64 ldfq_be_p(const void *ptr)
|
|
|
-{
|
|
|
- return *(float64 *)ptr;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfl_be_p(void *ptr, float32 v)
|
|
|
-{
|
|
|
- *(float32 *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-static inline void stfq_be_p(void *ptr, float64 v)
|
|
|
-{
|
|
|
- *(float64 *)ptr = v;
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
|
|
|
-/* target CPU memory access functions */
|
|
|
+/* target-endianness CPU memory access functions */
|
|
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
|
|
#define lduw_p(p) lduw_be_p(p)
|
|
|
#define ldsw_p(p) ldsw_be_p(p)
|