My original patch only fixed libat_fetch_op; this one applies the same fix to libat_op_fetch, as well.
When using word-wide CAS to emulate atomic fetch-and-op, addresses should be word-aligned to avoid exceptions on some targets. The problem manifested in a new port I'm working on as a failure in test gcc.dg/atomic/stdatomic-op-1.c, and I've confirmed that this patch fixes it. x86_64-unknown-linux still bootstraps, but that is admittedly of little significance, since it doesn't use these routines. 2015-01-09 Andrew Waterman <water...@cs.berkeley.edu> * fop_n.c (libat_fetch_op): Align address to word boundary. (libat_op_fetch): Likewise. --- libatomic/fop_n.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libatomic/fop_n.c b/libatomic/fop_n.c index 307184d..854d648 100644 --- a/libatomic/fop_n.c +++ b/libatomic/fop_n.c @@ -112,9 +112,9 @@ SIZE(C2(libat_fetch_,NAME)) (UTYPE *mptr, UTYPE opval, int smodel) pre_barrier (smodel); - wptr = (UWORD *)mptr; - shift = 0; - mask = -1; + wptr = (UWORD *)((uintptr_t)mptr & -WORDSIZE); + shift = (((uintptr_t)mptr % WORDSIZE) * CHAR_BIT) ^ SIZE(INVERT_MASK); + mask = SIZE(MASK) << shift; wopval = (UWORD)opval << shift; woldval = __atomic_load_n (wptr, __ATOMIC_RELAXED); @@ -136,9 +136,9 @@ SIZE(C3(libat_,NAME,_fetch)) (UTYPE *mptr, UTYPE opval, int smodel) pre_barrier (smodel); - wptr = (UWORD *)mptr; - shift = 0; - mask = -1; + wptr = (UWORD *)((uintptr_t)mptr & -WORDSIZE); + shift = (((uintptr_t)mptr % WORDSIZE) * CHAR_BIT) ^ SIZE(INVERT_MASK); + mask = SIZE(MASK) << shift; wopval = (UWORD)opval << shift; woldval = __atomic_load_n (wptr, __ATOMIC_RELAXED); -- 2.2.1