Nugget
arch_x86_load.h
1 // Copyright (c) Electronic Arts Inc. All rights reserved.
4 
5 
6 #ifndef EASTL_ATOMIC_INTERNAL_ARCH_X86_LOAD_H
7 #define EASTL_ATOMIC_INTERNAL_ARCH_X86_LOAD_H
8 
9 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
10  #pragma once
11 #endif
12 
13 
15 //
16 // void EASTL_ARCH_ATOMIC_LOAD_*_N(type, type ret, type * ptr)
17 //
18 
19 #if ((defined(__clang__) || defined(EA_COMPILER_GNUC)) && defined(EA_PROCESSOR_X86_64))
20 
21 
30 #define EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, MemoryOrder) \
31  { \
32  EASTL_ATOMIC_FIXED_WIDTH_TYPE_128 expected = 0; \
33  ret = EASTL_ATOMIC_TYPE_PUN_CAST(type, expected); \
34  \
35  /* Compare RDX:RAX with m128. If equal, set ZF and load RCX:RBX into m128. Else, clear ZF and load m128 into RDX:RAX. */ \
36  __asm__ __volatile__ ("lock; cmpxchg16b %2" /* cmpxchg16b sets/clears ZF */ \
37  /* Output Operands */ \
38  : "=a"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[0]), "=d"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[1]), \
39  "+m"(*(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(__uint128_t, (ptr)))) \
40  /* Input Operands */ \
41  : "b"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[0]), "c"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[1]), \
42  "a"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[0]), "d"((EASTL_ATOMIC_TYPE_CAST(uint64_t, &(ret)))[1]) \
43  /* Clobbers */ \
44  : "memory", "cc"); \
45  }
46 
47 
48 #define EASTL_ARCH_ATOMIC_LOAD_RELAXED_128(type, ret, ptr) \
49  EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, RELAXED)
50 
51 #define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128(type, ret, ptr) \
52  EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, ACQUIRE)
53 
54 #define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128(type, ret, ptr) \
55  EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, SEQ_CST)
56 
57 #elif defined(EA_COMPILER_MSVC)
58 
59 
60  #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1920) // >= VS2019
61 
62  #define EASTL_ARCH_ATOMIC_X86_LOAD_N(integralType, bits, type, ret, ptr) \
63  { \
64  integralType retIntegral; \
65  retIntegral = EA_PREPROCESSOR_JOIN(__iso_volatile_load, bits)(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr))); \
66  \
67  ret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral); \
68  }
69 
70  #else
71 
72  #define EASTL_ARCH_ATOMIC_X86_LOAD_N(integralType, bits, type, ret, ptr) \
73  { \
74  integralType retIntegral; \
75  retIntegral = (*(EASTL_ATOMIC_VOLATILE_INTEGRAL_CAST(integralType, (ptr)))); \
76  \
77  ret = EASTL_ATOMIC_TYPE_PUN_CAST(type, retIntegral); \
78  }
79 
80  #endif
81 
82 
83  #define EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, MemoryOrder) \
84  { \
85  EASTL_ATOMIC_FIXED_WIDTH_TYPE_128 expected{0, 0}; \
86  ret = EASTL_ATOMIC_TYPE_PUN_CAST(type, expected); \
87  \
88  bool cmpxchgRetBool; EA_UNUSED(cmpxchgRetBool); \
89  EA_PREPROCESSOR_JOIN(EA_PREPROCESSOR_JOIN(EASTL_ATOMIC_CMPXCHG_STRONG_, MemoryOrder), _128)(type, cmpxchgRetBool, ptr, &(ret), ret); \
90  }
91 
92 
93  #define EASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr) \
94  EASTL_ARCH_ATOMIC_X86_LOAD_N(__int8, 8, type, ret, ptr)
95 
96  #define EASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr) \
97  EASTL_ARCH_ATOMIC_X86_LOAD_N(__int16, 16, type, ret, ptr)
98 
99  #define EASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr) \
100  EASTL_ARCH_ATOMIC_X86_LOAD_N(__int32, 32, type, ret, ptr)
101 
102  #define EASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr) \
103  EASTL_ARCH_ATOMIC_X86_LOAD_N(__int64, 64, type, ret, ptr)
104 
105 
106  #define EASTL_ARCH_ATOMIC_LOAD_RELAXED_8(type, ret, ptr) \
107  EASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr)
108 
109  #define EASTL_ARCH_ATOMIC_LOAD_RELAXED_16(type, ret, ptr) \
110  EASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr)
111 
112  #define EASTL_ARCH_ATOMIC_LOAD_RELAXED_32(type, ret, ptr) \
113  EASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr)
114 
115  #define EASTL_ARCH_ATOMIC_LOAD_RELAXED_64(type, ret, ptr) \
116  EASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr)
117 
118  #define EASTL_ARCH_ATOMIC_LOAD_RELAXED_128(type, ret, ptr) \
119  EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, RELAXED)
120 
121 
122  #define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_8(type, ret, ptr) \
123  EASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr); \
124  EASTL_ATOMIC_COMPILER_BARRIER()
125 
126  #define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_16(type, ret, ptr) \
127  EASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr); \
128  EASTL_ATOMIC_COMPILER_BARRIER()
129 
130  #define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_32(type, ret, ptr) \
131  EASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr); \
132  EASTL_ATOMIC_COMPILER_BARRIER()
133 
134  #define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_64(type, ret, ptr) \
135  EASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr); \
136  EASTL_ATOMIC_COMPILER_BARRIER()
137 
138  #define EASTL_ARCH_ATOMIC_LOAD_ACQUIRE_128(type, ret, ptr) \
139  EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, ACQUIRE)
140 
141 
142  #define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_8(type, ret, ptr) \
143  EASTL_ARCH_ATOMIC_X86_LOAD_8(type, ret, ptr); \
144  EASTL_ATOMIC_COMPILER_BARRIER()
145 
146  #define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_16(type, ret, ptr) \
147  EASTL_ARCH_ATOMIC_X86_LOAD_16(type, ret, ptr); \
148  EASTL_ATOMIC_COMPILER_BARRIER()
149 
150  #define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_32(type, ret, ptr) \
151  EASTL_ARCH_ATOMIC_X86_LOAD_32(type, ret, ptr); \
152  EASTL_ATOMIC_COMPILER_BARRIER()
153 
154  #define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_64(type, ret, ptr) \
155  EASTL_ARCH_ATOMIC_X86_LOAD_64(type, ret, ptr); \
156  EASTL_ATOMIC_COMPILER_BARRIER()
157 
158  #define EASTL_ARCH_ATOMIC_LOAD_SEQ_CST_128(type, ret, ptr) \
159  EASTL_ARCH_ATOMIC_X86_LOAD_128(type, ret, ptr, SEQ_CST)
160 
161 #endif
162 
163 
164 #endif /* EASTL_ATOMIC_INTERNAL_ARCH_X86_LOAD_H */