diff options
Diffstat (limited to 'libc-top-half/musl/arch/mips/atomic_arch.h')
-rw-r--r-- | libc-top-half/musl/arch/mips/atomic_arch.h | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/libc-top-half/musl/arch/mips/atomic_arch.h b/libc-top-half/musl/arch/mips/atomic_arch.h new file mode 100644 index 0000000..1248d17 --- /dev/null +++ b/libc-top-half/musl/arch/mips/atomic_arch.h @@ -0,0 +1,58 @@ +#if __mips_isa_rev < 6 +#define LLSC_M "m" +#else +#define LLSC_M "ZC" +#endif + +#define a_ll a_ll +static inline int a_ll(volatile int *p) +{ + int v; +#if __mips < 2 + __asm__ __volatile__ ( + ".set push ; .set mips2\n\t" + "ll %0, %1" + "\n\t.set pop" + : "=r"(v) : "m"(*p)); +#else + __asm__ __volatile__ ( + "ll %0, %1" + : "=r"(v) : LLSC_M(*p)); +#endif + return v; +} + +#define a_sc a_sc +static inline int a_sc(volatile int *p, int v) +{ + int r; +#if __mips < 2 + __asm__ __volatile__ ( + ".set push ; .set mips2\n\t" + "sc %0, %1" + "\n\t.set pop" + : "=r"(r), "=m"(*p) : "0"(v) : "memory"); +#else + __asm__ __volatile__ ( + "sc %0, %1" + : "=r"(r), "="LLSC_M(*p) : "0"(v) : "memory"); +#endif + return r; +} + +#define a_barrier a_barrier +static inline void a_barrier() +{ +#if __mips < 2 + /* mips2 sync, but using too many directives causes + * gcc not to inline it, so encode with .long instead. */ + __asm__ __volatile__ (".long 0xf" : : : "memory"); +#else + __asm__ __volatile__ ("sync" : : : "memory"); +#endif +} + +#define a_pre_llsc a_barrier +#define a_post_llsc a_barrier + +#undef LLSC_M |