gcc-armv6+.hpp
Go to the documentation of this file.
1 #ifndef BOOST_DETAIL_ATOMIC_GCC_ARMV6P_HPP
2 #define BOOST_DETAIL_ATOMIC_GCC_ARMV6P_HPP
3 
4 // Distributed under the Boost Software License, Version 1.0.
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Copyright (c) 2009 Helge Bahmann
9 // Copyright (c) 2009 Phil Endecott
10 // ARM Code by Phil Endecott, based on other architectures.
11 
12 // From the ARM Architecture Reference Manual for architecture v6:
13 //
14 // LDREX{<cond>} <Rd>, [<Rn>]
15 // <Rd> Specifies the destination register for the memory word addressed by <Rd>
16 // <Rn> Specifies the register containing the address.
17 //
18 // STREX{<cond>} <Rd>, <Rm>, [<Rn>]
19 // <Rd> Specifies the destination register for the returned status value.
20 // 0 if the operation updates memory
21 // 1 if the operation fails to update memory
22 // <Rm> Specifies the register containing the word to be stored to memory.
23 // <Rn> Specifies the register containing the address.
24 // Rd must not be the same register as Rm or Rn.
25 //
26 // ARM v7 is like ARM v6 plus:
27 // There are half-word and byte versions of the LDREX and STREX instructions,
28 // LDREXH, LDREXB, STREXH and STREXB.
29 // There are also double-word versions, LDREXD and STREXD.
30 // (Actually it looks like these are available from version 6k onwards.)
31 // FIXME these are not yet used; should be mostly a matter of copy-and-paste.
32 // I think you can supply an immediate offset to the address.
33 //
34 // A memory barrier is effected using a "co-processor 15" instruction,
35 // though a separate assembler mnemonic is available for it in v7.
36 
37 #define BOOST_ATOMIC_CHAR_LOCK_FREE 2
38 #define BOOST_ATOMIC_CHAR16_T_LOCK_FREE 2
39 #define BOOST_ATOMIC_CHAR32_T_LOCK_FREE 2
40 #define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 2
41 #define BOOST_ATOMIC_SHORT_LOCK_FREE 2
42 #define BOOST_ATOMIC_INT_LOCK_FREE 2
43 #define BOOST_ATOMIC_LONG_LOCK_FREE 2
44 #define BOOST_ATOMIC_LLONG_LOCK_FREE 0
45 #define BOOST_ATOMIC_ADDRESS_LOCK_FREE 2
46 #define BOOST_ATOMIC_BOOL_LOCK_FREE 2
47 
48 namespace boost {
49 namespace detail {
50 namespace atomic {
51 
52 // "Thumb 1" is a subset of the ARM instruction set that uses a 16-bit encoding. It
53 // doesn't include all instructions and in particular it doesn't include the co-processor
54 // instruction used for the memory barrier or the load-locked/store-conditional
55 // instructions. So, if we're compiling in "Thumb 1" mode, we need to wrap all of our
56 // asm blocks with code to temporarily change to ARM mode.
57 //
58 // You can only change between ARM and Thumb modes when branching using the bx instruction.
59 // bx takes an address specified in a register. The least significant bit of the address
60 // indicates the mode, so 1 is added to indicate that the destination code is Thumb.
61 // A temporary register is needed for the address and is passed as an argument to these
62 // macros. It must be one of the "low" registers accessible to Thumb code, specified
63 // usng the "l" attribute in the asm statement.
64 //
65 // Architecture v7 introduces "Thumb 2", which does include (almost?) all of the ARM
66 // instruction set. So in v7 we don't need to change to ARM mode; we can write "universal
67 // assembler" which will assemble to Thumb 2 or ARM code as appropriate. The only thing
68 // we need to do to make this "universal" assembler mode work is to insert "IT" instructions
69 // to annotate the conditional instructions. These are ignored in other modes (e.g. v6),
70 // so they can always be present.
71 
72 #if defined(__thumb__) && !defined(__ARM_ARCH_7A__)
73 // FIXME also other v7 variants.
74 #define BOOST_ATOMIC_ARM_ASM_START(TMPREG) "adr " #TMPREG ", 1f\n" "bx " #TMPREG "\n" ".arm\n" ".align 4\n" "1: "
75 #define BOOST_ATOMIC_ARM_ASM_END(TMPREG) "adr " #TMPREG ", 1f + 1\n" "bx " #TMPREG "\n" ".thumb\n" ".align 2\n" "1: "
76 
77 #else
78 // The tmpreg is wasted in this case, which is non-optimal.
79 #define BOOST_ATOMIC_ARM_ASM_START(TMPREG)
80 #define BOOST_ATOMIC_ARM_ASM_END(TMPREG)
81 #endif
82 
83 #if defined(__ARM_ARCH_7A__)
84 // FIXME ditto.
85 #define BOOST_ATOMIC_ARM_DMB "dmb\n"
86 #else
87 #define BOOST_ATOMIC_ARM_DMB "mcr\tp15, 0, r0, c7, c10, 5\n"
88 #endif
89 
90 static inline void
92 {
93  int brtmp;
94  __asm__ __volatile__ (
98  : "=&l" (brtmp) :: "memory"
99  );
100 }
101 
102 static inline void
104 {
105  switch(order) {
109  arm_barrier();
111  default:;
112  }
113 }
114 
115 static inline void
117 {
118  switch(order) {
122  arm_barrier();
123  default:;
124  }
125 }
126 
127 static inline void
129 {
130  platform_fence_before(order);
131 }
132 
133 static inline void
135 {
136  if (order == memory_order_seq_cst)
137  arm_barrier();
138 }
139 
140 static inline void
142 {
143  platform_fence_after(order);
144 }
145 
146 template<typename T>
147 bool
148 platform_cmpxchg32(T & expected, T desired, volatile T * ptr)
149 {
150  int success;
151  int tmp;
152  __asm__ (
154  "mov %1, #0\n" // success = 0
155  "ldrex %0, %3\n" // expected' = *(&i)
156  "teq %0, %4\n" // flags = expected'==expected
157  "ittt eq\n"
158  "strexeq %2, %5, %3\n" // if (flags.equal) *(&i) = desired, tmp = !OK
159  "teqeq %2, #0\n" // if (flags.equal) flags = tmp==0
160  "moveq %1, #1\n" // if (flags.equal) success = 1
162  : "=&r" (expected), // %0
163  "=&r" (success), // %1
164  "=&l" (tmp), // %2
165  "+Q" (*ptr) // %3
166  : "r" (expected), // %4
167  "r" (desired) // %5
168  : "cc"
169  );
170  return success;
171 }
172 
173 
174 }
175 }
176 
177 #define BOOST_ATOMIC_THREAD_FENCE 2
178 static inline void
180 {
181  switch(order) {
187  default:;
188  }
189 }
190 
191 #define BOOST_ATOMIC_SIGNAL_FENCE 2
192 static inline void
194 {
195  __asm__ __volatile__ ("" ::: "memory");
196 }
197 
198 }
199 
200 #undef BOOST_ATOMIC_ARM_ASM_START
201 #undef BOOST_ATOMIC_ARM_ASM_END
202 
204 
205 #endif
static void platform_fence_before_store(memory_order order)
Definition: gcc-armv6+.hpp:128
#define BOOST_ATOMIC_ARM_ASM_START(TMPREG)
Definition: gcc-armv6+.hpp:79
Definition: base.hpp:116
static void atomic_signal_fence(memory_order)
Definition: gcc-armv6+.hpp:193
static void platform_fence_after_load(memory_order order)
Definition: gcc-armv6+.hpp:141
static void atomic_thread_fence(memory_order order)
Definition: gcc-armv6+.hpp:179
static void platform_fence_after_store(memory_order order)
Definition: gcc-armv6+.hpp:134
static void platform_fence_after(memory_order order)
Definition: gcc-armv6+.hpp:116
static void arm_barrier(void)
Definition: gcc-armv6+.hpp:91
#define BOOST_ATOMIC_ARM_ASM_END(TMPREG)
Definition: gcc-armv6+.hpp:80
bool platform_cmpxchg32(T &expected, T desired, volatile T *ptr)
Definition: gcc-armv6+.hpp:148
#define BOOST_ATOMIC_ARM_DMB
Definition: gcc-armv6+.hpp:87
static void platform_fence_before(memory_order order)
Definition: gcc-armv6+.hpp:103


rosatomic
Author(s): Josh Faust
autogenerated on Fri Apr 5 2019 02:16:35