#ifndef ATOMIC64_H
#define ATOMIC64_H

#ifdef __i386
#define ATOMIC_DOUBLE_STORE(__dest, __newvalue) \
    __asm__ __volatile__("fstpl\t%0" \
        : "=m" (__dest)     /* outputs */ \
        : "t"  (__newvalue) /* inputs */ \
        : "st"              /* pops stack */ \
    );
#define ATOMIC_INT64_STORE(__dest, __newvalue) \
    __asm__ __volatile__( \
        "fildq\t%1\n\t" \
        "fistpq\t%0" \
        : "=m" (__dest)     /* outputs */ \
        : "m"  (__newvalue) /* inputs */ \
        : "st(7)"           /* need one free on fp stack*/ \
    );
#else
#define ATOMIC_DOUBLE_STORE(__dest, __newvalue) \
    (__dest) = (__newvalue)
#define ATOMIC_INT64_STORE(__dest, __newvalue) \
    (__dest) = (__newvalue)
#endif

#ifdef __cplusplus
struct atomic_double {
    volatile double value;

    const atomic_double &operator=(const double &d) {
        ATOMIC_DOUBLE_STORE(value, d);
        return *this;
    }

    operator double() const {
        double result;
        ATOMIC_DOUBLE_STORE(result, value);
        return result;
    }
};

template<class T>
struct _atomic64 {
    volatile T value;

    const _atomic64 &operator=(const T &d) {
        ATOMIC_INT64_STORE(value, d);
        return *this;
    }

    operator T() const {
        T result;
        ATOMIC_INT64_STORE(result, value);
        return result; }
};

typedef _atomic64<unsigned long long> atomic_u64;
typedef _atomic64<long long> atomic_s64;
#endif

#endif
