summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/minute-ia/atomic.h29
1 files changed, 13 insertions, 16 deletions
diff --git a/core/minute-ia/atomic.h b/core/minute-ia/atomic.h
index 696120ae1d..08f0888cdf 100644
--- a/core/minute-ia/atomic.h
+++ b/core/minute-ia/atomic.h
@@ -13,9 +13,9 @@
#define ATOMIC_OP(asm_op, a, v) do { \
__asm__ __volatile__ ( \
- "lock;" #asm_op " %0, %1\n" \
- : \
- : "r" (v), "m" (*a) \
+ "lock;" #asm_op " %1, %0\n" \
+ : "+m" (*a) \
+ : "ir" (v) \
: "memory"); \
} while (0)
@@ -24,10 +24,10 @@ static inline int bool_compare_and_swap_u32(uint32_t *var, uint32_t old_value,
{
uint32_t _old_value = old_value;
- __asm__ __volatile__("cmpxchg %1, %2\n"
- : "=a"(old_value)
- : "r"(new_value), "m"(*var), "a" (old_value)
- : "memory");
+ __asm__ __volatile__("lock; cmpxchgl %2, %1"
+ : "=a" (old_value), "+m" (*var)
+ : "r" (new_value), "0" (old_value)
+ : "memory");
return (_old_value == old_value);
}
@@ -44,7 +44,7 @@ static inline void atomic_and_u8(uint8_t *addr, uint8_t bits)
static inline void atomic_clear(uint32_t volatile *addr, uint32_t bits)
{
- ATOMIC_OP(btr, addr, bits >> 1);
+ ATOMIC_OP(andl, addr, ~bits);
}
static inline void atomic_or(uint32_t volatile *addr, uint32_t bits)
@@ -69,19 +69,16 @@ static inline void atomic_sub(uint32_t volatile *addr, uint32_t value)
static inline uint32_t atomic_read_clear(uint32_t volatile *addr)
{
- int loc = 0;
+ int ret = 0;
if (*addr == 0)
return 0;
- asm volatile("bsr %1, %0\n"
- "lock; btr %0, %1\n"
- : "=&r" (loc)
- : "m" (*addr)
- : "memory"
- );
+ asm volatile("lock; xchgl %0, %1\n"
+ : "+r" (ret), "+m" (*addr)
+ : : "memory", "cc");
- return (1 << loc);
+ return ret;
}
#endif /* __CROS_EC_ATOMIC_H */