v2 / thirdparty / libatomic_ops / atomic_ops / sysdeps / gcc / riscv.h
100 lines · 84 sloc · 3.48 KB · f53b5d737fd636890520101e736ad29e20d3c322
Raw
1/*
2 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
3 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
4 *
5 * Permission is hereby granted to use or copy this program
6 * for any purpose, provided the above notices are retained on all copies.
7 * Permission to modify the code and to distribute modified code is granted,
8 * provided the above notices are retained, and a notice that the code was
9 * modified is included with the above copyright notice.
10 */
11
12#if defined(__clang__) || defined(AO_PREFER_BUILTIN_ATOMICS)
13 /* All __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros are still missing. */
14 /* The operations are lock-free even for the types smaller than word. */
15# define AO_GCC_FORCE_HAVE_CAS
16#else
17
18 /* As of gcc-7.5, CAS and arithmetic atomic operations for char and */
19 /* short are supported by the compiler but require -latomic flag. */
20# if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)
21# define AO_NO_char_ARITHM
22# endif
23# if !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)
24# define AO_NO_short_ARITHM
25# endif
26#endif /* !__clang__ */
27
28#if defined(__riscv_zacas) && __riscv_xlen == 64 && !defined(AO_NO_DOUBLE_CAS)
29 /* TODO: Support also rv32, i.e. use amocas.w. */
30
31# define AO_SKIPATOMIC_double_load
32# define AO_SKIPATOMIC_double_load_acquire
33# define AO_SKIPATOMIC_double_store
34# define AO_SKIPATOMIC_double_store_release
35
36# include "../standard_ao_double_t.h"
37
38 AO_INLINE int
39 AO_double_compare_and_swap(volatile AO_double_t *addr,
40 AO_double_t old_val, AO_double_t new_val)
41 {
42 AO_double_t expected = old_val;
43
44 __asm__ __volatile__("amocas.q %0, %z2, %1"
45 : "+rJ" (expected.AO_whole), "+A" (*addr)
46 : "rJ" (new_val.AO_whole));
47 return expected.AO_whole == old_val.AO_whole;
48 }
49# define AO_HAVE_double_compare_and_swap
50
51 AO_INLINE int
52 AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,
53 AO_double_t old_val, AO_double_t new_val)
54 {
55 AO_double_t expected = old_val;
56
57 __asm__ __volatile__("amocas.q.aq %0, %z2, %1"
58 : "+rJ" (expected.AO_whole), "+A" (*addr)
59 : "rJ" (new_val.AO_whole));
60 return expected.AO_whole == old_val.AO_whole;
61 }
62# define AO_HAVE_double_compare_and_swap_acquire
63
64 AO_INLINE int
65 AO_double_compare_and_swap_release(volatile AO_double_t *addr,
66 AO_double_t old_val, AO_double_t new_val)
67 {
68 AO_double_t expected = old_val;
69
70 __asm__ __volatile__("amocas.q.rl %0, %z2, %1"
71 : "+rJ" (expected.AO_whole), "+A" (*addr)
72 : "rJ" (new_val.AO_whole));
73 return expected.AO_whole == old_val.AO_whole;
74 }
75# define AO_HAVE_double_compare_and_swap_release
76
77 AO_INLINE int
78 AO_double_compare_and_swap_full(volatile AO_double_t *addr,
79 AO_double_t old_val, AO_double_t new_val)
80 {
81 AO_double_t expected = old_val;
82
83 __asm__ __volatile__("amocas.q.aqrl %0, %z2, %1"
84 : "+rJ" (expected.AO_whole), "+A" (*addr)
85 : "rJ" (new_val.AO_whole));
86 return expected.AO_whole == old_val.AO_whole;
87 }
88# define AO_HAVE_double_compare_and_swap_full
89
90#endif /* __riscv_zacas */
91
92#include "generic.h"
93
94#undef AO_GCC_FORCE_HAVE_CAS
95#undef AO_NO_char_ARITHM
96#undef AO_NO_short_ARITHM
97#undef AO_SKIPATOMIC_double_load
98#undef AO_SKIPATOMIC_double_load_acquire
99#undef AO_SKIPATOMIC_double_store
100#undef AO_SKIPATOMIC_double_store_release
101