Skip to content

Commit a37e037

Browse files
pfalconMaureenHelm
authored andcommitted
toolchain: gcc: Add compiler barrier at the end of UNALIGNED_PUT()
compiler_barrier() is itself defined down in this file. Without adding it, newer versions of GCC (7+) for ARM Cortex-M may mistakenly coalesce multiple strb/strh/str (store byte/half-word/word) instructions, which support unaligned access on some sub-architectures (Cortex-M3 and higher, but not on Cortex-M0), into strd (store double), which doesn't support unaligned access. Fixes: #6307 Signed-off-by: Paul Sokolovsky <[email protected]>
1 parent e8d0e72 commit a37e037

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

include/toolchain/gcc.h

+25
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,29 @@ __extension__ ({ \
6666
__p->__v; \
6767
})
6868

69+
70+
#if __GNUC__ >= 7 && defined(CONFIG_ARM)
71+
72+
/* Version of UNALIGNED_PUT() which issues a compiler_barrier() after
73+
* the store. It is required to workaround an apparent optimization
74+
* bug in GCC for ARM Cortex-M3 and higher targets, when multiple
75+
* byte, half-word and word stores (strb, strh, str instructions),
76+
* which support unaligned access, can be coalesced into store double
77+
* (strd) instruction, which doesn't support unaligned access (the
78+
* compilers in question do this optimization ignoring __packed__
79+
* attribute).
80+
*/
81+
#define UNALIGNED_PUT(v, p) \
82+
do { \
83+
struct __attribute__((__packed__)) { \
84+
__typeof__(*p) __v; \
85+
} *__p = (__typeof__(__p)) (p); \
86+
__p->__v = (v); \
87+
compiler_barrier(); \
88+
} while (0)
89+
90+
#else
91+
6992
#define UNALIGNED_PUT(v, p) \
7093
do { \
7194
struct __attribute__((__packed__)) { \
@@ -74,6 +97,8 @@ do { \
7497
__p->__v = (v); \
7598
} while (0)
7699

100+
#endif
101+
77102
/* Double indirection to ensure section names are expanded before
78103
* stringification
79104
*/

0 commit comments

Comments
 (0)