Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / atomic / detail / ops_msvc_x86.hpp
1 /*
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * Copyright (c) 2009 Helge Bahmann
7  * Copyright (c) 2012 Tim Blechmann
8  * Copyright (c) 2014 Andrey Semashev
9  */
10 /*!
11  * \file   atomic/detail/ops_msvc_x86.hpp
12  *
13  * This header contains implementation of the \c operations template.
14  */
15
16 #ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
17 #define BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_
18
19 #include <boost/memory_order.hpp>
20 #include <boost/type_traits/make_signed.hpp>
21 #include <boost/atomic/detail/config.hpp>
22 #include <boost/atomic/detail/interlocked.hpp>
23 #include <boost/atomic/detail/storage_type.hpp>
24 #include <boost/atomic/detail/operations_fwd.hpp>
25 #include <boost/atomic/capabilities.hpp>
26 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
27 #include <boost/cstdint.hpp>
28 #include <boost/atomic/detail/ops_cas_based.hpp>
29 #endif
30 #include <boost/atomic/detail/ops_msvc_common.hpp>
31 #if !defined(_M_IX86) && !(defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8) && defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16))
32 #include <boost/atomic/detail/ops_extending_cas_based.hpp>
33 #endif
34
35 #ifdef BOOST_HAS_PRAGMA_ONCE
36 #pragma once
37 #endif
38
39 #if defined(BOOST_MSVC)
40 #pragma warning(push)
41 // frame pointer register 'ebx' modified by inline assembly code. See the note below.
42 #pragma warning(disable: 4731)
43 #endif
44
45 #if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2))
46 extern "C" void _mm_mfence(void);
47 #if defined(BOOST_MSVC)
48 #pragma intrinsic(_mm_mfence)
49 #endif
50 #endif
51
52 namespace boost {
53 namespace atomics {
54 namespace detail {
55
56 /*
57  * Implementation note for asm blocks.
58  *
59  * http://msdn.microsoft.com/en-us/data/k1a8ss06%28v=vs.105%29
60  *
61  * Some SSE types require eight-byte stack alignment, forcing the compiler to emit dynamic stack-alignment code.
62  * To be able to access both the local variables and the function parameters after the alignment, the compiler
63  * maintains two frame pointers. If the compiler performs frame pointer omission (FPO), it will use EBP and ESP.
64  * If the compiler does not perform FPO, it will use EBX and EBP. To ensure code runs correctly, do not modify EBX
65  * in asm code if the function requires dynamic stack alignment as it could modify the frame pointer.
66  * Either move the eight-byte aligned types out of the function, or avoid using EBX.
67  *
68  * Since we have no way of knowing that the compiler uses FPO, we have to always save and restore ebx
69  * whenever we have to clobber it. Additionally, we disable warning C4731 above so that the compiler
70  * doesn't spam about ebx use.
71  */
72
73 struct msvc_x86_operations_base
74 {
75     static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT
76     {
77 #if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2))
78         // Use mfence only if SSE2 is available
79         _mm_mfence();
80 #else
81         long tmp;
82         BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&tmp, 0);
83 #endif
84     }
85
86     static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT
87     {
88         BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
89     }
90
91     static BOOST_FORCEINLINE void fence_after(memory_order) BOOST_NOEXCEPT
92     {
93         BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
94     }
95
96     static BOOST_FORCEINLINE void fence_after_load(memory_order) BOOST_NOEXCEPT
97     {
98         BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
99
100         // On x86 and x86_64 there is no need for a hardware barrier,
101         // even if seq_cst memory order is requested, because all
102         // seq_cst writes are implemented with lock-prefixed operations
103         // or xchg which has implied lock prefix. Therefore normal loads
104         // are already ordered with seq_cst stores on these architectures.
105     }
106 };
107
108 template< typename T, typename Derived >
109 struct msvc_x86_operations :
110     public msvc_x86_operations_base
111 {
112     typedef T storage_type;
113
114     static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
115     {
116         if (order != memory_order_seq_cst)
117         {
118             fence_before(order);
119             storage = v;
120             fence_after(order);
121         }
122         else
123         {
124             Derived::exchange(storage, v, order);
125         }
126     }
127
128     static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT
129     {
130         storage_type v = storage;
131         fence_after_load(order);
132         return v;
133     }
134
135     static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
136     {
137         typedef typename make_signed< storage_type >::type signed_storage_type;
138         return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order);
139     }
140
141     static BOOST_FORCEINLINE bool compare_exchange_weak(
142         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
143     {
144         return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order);
145     }
146
147     static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
148     {
149         return !!Derived::exchange(storage, (storage_type)1, order);
150     }
151
152     static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
153     {
154         store(storage, (storage_type)0, order);
155     }
156
157     static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
158     {
159         return true;
160     }
161 };
162
163 template< bool Signed >
164 struct operations< 4u, Signed > :
165     public msvc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > >
166 {
167     typedef msvc_x86_operations< typename make_storage_type< 4u, Signed >::type, operations< 4u, Signed > > base_type;
168     typedef typename base_type::storage_type storage_type;
169
170     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
171     {
172         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v));
173     }
174
175     static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
176     {
177         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v));
178     }
179
180     static BOOST_FORCEINLINE bool compare_exchange_strong(
181         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
182     {
183         storage_type previous = expected;
184         storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous));
185         expected = old_val;
186         return (previous == old_val);
187     }
188
189 #if defined(BOOST_ATOMIC_INTERLOCKED_AND)
190     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
191     {
192         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v));
193     }
194 #else
195     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
196     {
197         storage_type res = storage;
198         while (!compare_exchange_strong(storage, res, res & v, order, memory_order_relaxed)) {}
199         return res;
200     }
201 #endif
202
203 #if defined(BOOST_ATOMIC_INTERLOCKED_OR)
204     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
205     {
206         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v));
207     }
208 #else
209     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
210     {
211         storage_type res = storage;
212         while (!compare_exchange_strong(storage, res, res | v, order, memory_order_relaxed)) {}
213         return res;
214     }
215 #endif
216
217 #if defined(BOOST_ATOMIC_INTERLOCKED_XOR)
218     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
219     {
220         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v));
221     }
222 #else
223     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
224     {
225         storage_type res = storage;
226         while (!compare_exchange_strong(storage, res, res ^ v, order, memory_order_relaxed)) {}
227         return res;
228     }
229 #endif
230 };
231
232 #if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8)
233
234 template< bool Signed >
235 struct operations< 1u, Signed > :
236     public msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
237 {
238     typedef msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
239     typedef typename base_type::storage_type storage_type;
240
241     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
242     {
243         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(&storage, v));
244     }
245
246     static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
247     {
248         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(&storage, v));
249     }
250
251     static BOOST_FORCEINLINE bool compare_exchange_strong(
252         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
253     {
254         storage_type previous = expected;
255         storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(&storage, desired, previous));
256         expected = old_val;
257         return (previous == old_val);
258     }
259
260     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
261     {
262         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8(&storage, v));
263     }
264
265     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
266     {
267         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8(&storage, v));
268     }
269
270     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
271     {
272         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8(&storage, v));
273     }
274 };
275
276 #elif defined(_M_IX86)
277
278 template< bool Signed >
279 struct operations< 1u, Signed > :
280     public msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > >
281 {
282     typedef msvc_x86_operations< typename make_storage_type< 1u, Signed >::type, operations< 1u, Signed > > base_type;
283     typedef typename base_type::storage_type storage_type;
284
285     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
286     {
287         base_type::fence_before(order);
288         __asm
289         {
290             mov edx, storage
291             movzx eax, v
292             lock xadd byte ptr [edx], al
293             mov v, al
294         };
295         base_type::fence_after(order);
296         return v;
297     }
298
299     static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
300     {
301         base_type::fence_before(order);
302         __asm
303         {
304             mov edx, storage
305             movzx eax, v
306             xchg byte ptr [edx], al
307             mov v, al
308         };
309         base_type::fence_after(order);
310         return v;
311     }
312
313     static BOOST_FORCEINLINE bool compare_exchange_strong(
314         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT
315     {
316         base_type::fence_before(success_order);
317         bool success;
318         __asm
319         {
320             mov esi, expected
321             mov edi, storage
322             movzx eax, byte ptr [esi]
323             movzx edx, desired
324             lock cmpxchg byte ptr [edi], dl
325             mov byte ptr [esi], al
326             sete success
327         };
328         // The success and failure fences are equivalent anyway
329         base_type::fence_after(success_order);
330         return success;
331     }
332
333     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
334     {
335         base_type::fence_before(order);
336         int backup;
337         __asm
338         {
339             mov backup, ebx
340             xor edx, edx
341             mov edi, storage
342             movzx ebx, v
343             movzx eax, byte ptr [edi]
344             align 16
345         again:
346             mov dl, al
347             and dl, bl
348             lock cmpxchg byte ptr [edi], dl
349             jne again
350             mov v, al
351             mov ebx, backup
352         };
353         base_type::fence_after(order);
354         return v;
355     }
356
357     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
358     {
359         base_type::fence_before(order);
360         int backup;
361         __asm
362         {
363             mov backup, ebx
364             xor edx, edx
365             mov edi, storage
366             movzx ebx, v
367             movzx eax, byte ptr [edi]
368             align 16
369         again:
370             mov dl, al
371             or dl, bl
372             lock cmpxchg byte ptr [edi], dl
373             jne again
374             mov v, al
375             mov ebx, backup
376         };
377         base_type::fence_after(order);
378         return v;
379     }
380
381     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
382     {
383         base_type::fence_before(order);
384         int backup;
385         __asm
386         {
387             mov backup, ebx
388             xor edx, edx
389             mov edi, storage
390             movzx ebx, v
391             movzx eax, byte ptr [edi]
392             align 16
393         again:
394             mov dl, al
395             xor dl, bl
396             lock cmpxchg byte ptr [edi], dl
397             jne again
398             mov v, al
399             mov ebx, backup
400         };
401         base_type::fence_after(order);
402         return v;
403     }
404 };
405
406 #else
407
408 template< bool Signed >
409 struct operations< 1u, Signed > :
410     public extending_cas_based_operations< operations< 4u, Signed >, 1u, Signed >
411 {
412 };
413
414 #endif
415
416 #if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16)
417
418 template< bool Signed >
419 struct operations< 2u, Signed > :
420     public msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
421 {
422     typedef msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
423     typedef typename base_type::storage_type storage_type;
424
425     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
426     {
427         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(&storage, v));
428     }
429
430     static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
431     {
432         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(&storage, v));
433     }
434
435     static BOOST_FORCEINLINE bool compare_exchange_strong(
436         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
437     {
438         storage_type previous = expected;
439         storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(&storage, desired, previous));
440         expected = old_val;
441         return (previous == old_val);
442     }
443
444     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
445     {
446         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16(&storage, v));
447     }
448
449     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
450     {
451         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16(&storage, v));
452     }
453
454     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
455     {
456         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16(&storage, v));
457     }
458 };
459
460 #elif defined(_M_IX86)
461
462 template< bool Signed >
463 struct operations< 2u, Signed > :
464     public msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > >
465 {
466     typedef msvc_x86_operations< typename make_storage_type< 2u, Signed >::type, operations< 2u, Signed > > base_type;
467     typedef typename base_type::storage_type storage_type;
468
469     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
470     {
471         base_type::fence_before(order);
472         __asm
473         {
474             mov edx, storage
475             movzx eax, v
476             lock xadd word ptr [edx], ax
477             mov v, ax
478         };
479         base_type::fence_after(order);
480         return v;
481     }
482
483     static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
484     {
485         base_type::fence_before(order);
486         __asm
487         {
488             mov edx, storage
489             movzx eax, v
490             xchg word ptr [edx], ax
491             mov v, ax
492         };
493         base_type::fence_after(order);
494         return v;
495     }
496
497     static BOOST_FORCEINLINE bool compare_exchange_strong(
498         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT
499     {
500         base_type::fence_before(success_order);
501         bool success;
502         __asm
503         {
504             mov esi, expected
505             mov edi, storage
506             movzx eax, word ptr [esi]
507             movzx edx, desired
508             lock cmpxchg word ptr [edi], dx
509             mov word ptr [esi], ax
510             sete success
511         };
512         // The success and failure fences are equivalent anyway
513         base_type::fence_after(success_order);
514         return success;
515     }
516
517     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
518     {
519         base_type::fence_before(order);
520         int backup;
521         __asm
522         {
523             mov backup, ebx
524             xor edx, edx
525             mov edi, storage
526             movzx ebx, v
527             movzx eax, word ptr [edi]
528             align 16
529         again:
530             mov dx, ax
531             and dx, bx
532             lock cmpxchg word ptr [edi], dx
533             jne again
534             mov v, ax
535             mov ebx, backup
536         };
537         base_type::fence_after(order);
538         return v;
539     }
540
541     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
542     {
543         base_type::fence_before(order);
544         int backup;
545         __asm
546         {
547             mov backup, ebx
548             xor edx, edx
549             mov edi, storage
550             movzx ebx, v
551             movzx eax, word ptr [edi]
552             align 16
553         again:
554             mov dx, ax
555             or dx, bx
556             lock cmpxchg word ptr [edi], dx
557             jne again
558             mov v, ax
559             mov ebx, backup
560         };
561         base_type::fence_after(order);
562         return v;
563     }
564
565     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
566     {
567         base_type::fence_before(order);
568         int backup;
569         __asm
570         {
571             mov backup, ebx
572             xor edx, edx
573             mov edi, storage
574             movzx ebx, v
575             movzx eax, word ptr [edi]
576             align 16
577         again:
578             mov dx, ax
579             xor dx, bx
580             lock cmpxchg word ptr [edi], dx
581             jne again
582             mov v, ax
583             mov ebx, backup
584         };
585         base_type::fence_after(order);
586         return v;
587     }
588 };
589
590 #else
591
592 template< bool Signed >
593 struct operations< 2u, Signed > :
594     public extending_cas_based_operations< operations< 4u, Signed >, 2u, Signed >
595 {
596 };
597
598 #endif
599
600
601 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B)
602
603 template< bool Signed >
604 struct msvc_dcas_x86
605 {
606     typedef typename make_storage_type< 8u, Signed >::type storage_type;
607
608     // Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, 8.1.1. Guaranteed Atomic Operations:
609     //
610     // The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
611     // * Reading or writing a quadword aligned on a 64-bit boundary
612     //
613     // Luckily, the memory is almost always 8-byte aligned in our case because atomic<> uses 64 bit native types for storage and dynamic memory allocations
614     // have at least 8 byte alignment. The only unfortunate case is when atomic is placeod on the stack and it is not 8-byte aligned (like on 32 bit Windows).
615
616     static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
617     {
618         storage_type volatile* p = &storage;
619         if (((uint32_t)p & 0x00000007) == 0)
620         {
621 #if defined(_M_IX86_FP) && _M_IX86_FP >= 2
622 #if defined(__AVX__)
623             __asm
624             {
625                 mov edx, p
626                 vmovq xmm4, v
627                 vmovq qword ptr [edx], xmm4
628             };
629 #else
630             __asm
631             {
632                 mov edx, p
633                 movq xmm4, v
634                 movq qword ptr [edx], xmm4
635             };
636 #endif
637 #else
638             __asm
639             {
640                 mov edx, p
641                 fild v
642                 fistp qword ptr [edx]
643             };
644 #endif
645         }
646         else
647         {
648             int backup;
649             __asm
650             {
651                 mov backup, ebx
652                 mov edi, p
653                 mov ebx, dword ptr [v]
654                 mov ecx, dword ptr [v + 4]
655                 mov eax, dword ptr [edi]
656                 mov edx, dword ptr [edi + 4]
657                 align 16
658             again:
659                 lock cmpxchg8b qword ptr [edi]
660                 jne again
661                 mov ebx, backup
662             };
663         }
664     }
665
666     static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
667     {
668         storage_type const volatile* p = &storage;
669         storage_type value;
670
671         if (((uint32_t)p & 0x00000007) == 0)
672         {
673 #if defined(_M_IX86_FP) && _M_IX86_FP >= 2
674 #if defined(__AVX__)
675             __asm
676             {
677                 mov edx, p
678                 vmovq xmm4, qword ptr [edx]
679                 vmovq value, xmm4
680             };
681 #else
682             __asm
683             {
684                 mov edx, p
685                 movq xmm4, qword ptr [edx]
686                 movq value, xmm4
687             };
688 #endif
689 #else
690             __asm
691             {
692                 mov edx, p
693                 fild qword ptr [edx]
694                 fistp value
695             };
696 #endif
697         }
698         else
699         {
700             // We don't care for comparison result here; the previous value will be stored into value anyway.
701             // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b.
702             __asm
703             {
704                 mov edi, p
705                 mov eax, ebx
706                 mov edx, ecx
707                 lock cmpxchg8b qword ptr [edi]
708                 mov dword ptr [value], eax
709                 mov dword ptr [value + 4], edx
710             };
711         }
712
713         return value;
714     }
715
716     static BOOST_FORCEINLINE bool compare_exchange_strong(
717         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
718     {
719         storage_type volatile* p = &storage;
720 #if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64)
721         const storage_type old_val = (storage_type)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(p, desired, expected);
722         const bool result = (old_val == expected);
723         expected = old_val;
724         return result;
725 #else
726         bool result;
727         int backup;
728         __asm
729         {
730             mov backup, ebx
731             mov edi, p
732             mov esi, expected
733             mov ebx, dword ptr [desired]
734             mov ecx, dword ptr [desired + 4]
735             mov eax, dword ptr [esi]
736             mov edx, dword ptr [esi + 4]
737             lock cmpxchg8b qword ptr [edi]
738             mov dword ptr [esi], eax
739             mov dword ptr [esi + 4], edx
740             mov ebx, backup
741             sete result
742         };
743         return result;
744 #endif
745     }
746
747     static BOOST_FORCEINLINE bool compare_exchange_weak(
748         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
749     {
750         return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
751     }
752
753     static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
754     {
755         return true;
756     }
757 };
758
759 template< bool Signed >
760 struct operations< 8u, Signed > :
761     public cas_based_operations< msvc_dcas_x86< Signed > >
762 {
763 };
764
765 #elif defined(_M_AMD64)
766
767 template< bool Signed >
768 struct operations< 8u, Signed > :
769     public msvc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > >
770 {
771     typedef msvc_x86_operations< typename make_storage_type< 8u, Signed >::type, operations< 8u, Signed > > base_type;
772     typedef typename base_type::storage_type storage_type;
773
774     static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
775     {
776         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(&storage, v));
777     }
778
779     static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
780     {
781         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(&storage, v));
782     }
783
784     static BOOST_FORCEINLINE bool compare_exchange_strong(
785         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
786     {
787         storage_type previous = expected;
788         storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(&storage, desired, previous));
789         expected = old_val;
790         return (previous == old_val);
791     }
792
793     static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
794     {
795         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64(&storage, v));
796     }
797
798     static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
799     {
800         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64(&storage, v));
801     }
802
803     static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
804     {
805         return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64(&storage, v));
806     }
807 };
808
809 #endif
810
811 #if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
812
813 template< bool Signed >
814 struct msvc_dcas_x86_64
815 {
816     typedef typename make_storage_type< 16u, Signed >::type storage_type;
817
818     static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT
819     {
820         storage_type value = const_cast< storage_type& >(storage);
821         while (!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, v, &value)) {}
822     }
823
824     static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT
825     {
826         storage_type value = storage_type();
827         BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, value, &value);
828         return value;
829     }
830
831     static BOOST_FORCEINLINE bool compare_exchange_strong(
832         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT
833     {
834         return !!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, desired, &expected);
835     }
836
837     static BOOST_FORCEINLINE bool compare_exchange_weak(
838         storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
839     {
840         return compare_exchange_strong(storage, expected, desired, success_order, failure_order);
841     }
842
843     static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile&) BOOST_NOEXCEPT
844     {
845         return true;
846     }
847 };
848
849 template< bool Signed >
850 struct operations< 16u, Signed > :
851     public cas_based_operations< msvc_dcas_x86_64< Signed > >
852 {
853 };
854
855 #endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B)
856
857 BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT
858 {
859     BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
860     if (order == memory_order_seq_cst)
861         msvc_x86_operations_base::hardware_full_fence();
862     BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
863 }
864
865 BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT
866 {
867     if (order != memory_order_relaxed)
868         BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
869 }
870
871 } // namespace detail
872 } // namespace atomics
873 } // namespace boost
874
875 #if defined(BOOST_MSVC)
876 #pragma warning(pop)
877 #endif
878
879 #endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_X86_HPP_INCLUDED_