0001
0002
0003
0004
0005
0006
0007
0008 #ifndef _ASM_ARC_ATOMIC64_ARCV2_H
0009 #define _ASM_ARC_ATOMIC64_ARCV2_H
0010
0011 typedef struct {
0012 s64 __aligned(8) counter;
0013 } atomic64_t;
0014
0015 #define ATOMIC64_INIT(a) { (a) }
0016
0017 static inline s64 arch_atomic64_read(const atomic64_t *v)
0018 {
0019 s64 val;
0020
0021 __asm__ __volatile__(
0022 " ldd %0, [%1] \n"
0023 : "=r"(val)
0024 : "r"(&v->counter));
0025
0026 return val;
0027 }
0028
0029 static inline void arch_atomic64_set(atomic64_t *v, s64 a)
0030 {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 __asm__ __volatile__(
0043 " std %0, [%1] \n"
0044 :
0045 : "r"(a), "r"(&v->counter)
0046 : "memory");
0047 }
0048
0049 #define ATOMIC64_OP(op, op1, op2) \
0050 static inline void arch_atomic64_##op(s64 a, atomic64_t *v) \
0051 { \
0052 s64 val; \
0053 \
0054 __asm__ __volatile__( \
0055 "1: \n" \
0056 " llockd %0, [%1] \n" \
0057 " " #op1 " %L0, %L0, %L2 \n" \
0058 " " #op2 " %H0, %H0, %H2 \n" \
0059 " scondd %0, [%1] \n" \
0060 " bnz 1b \n" \
0061 : "=&r"(val) \
0062 : "r"(&v->counter), "ir"(a) \
0063 : "cc"); \
0064 } \
0065
0066 #define ATOMIC64_OP_RETURN(op, op1, op2) \
0067 static inline s64 arch_atomic64_##op##_return_relaxed(s64 a, atomic64_t *v) \
0068 { \
0069 s64 val; \
0070 \
0071 __asm__ __volatile__( \
0072 "1: \n" \
0073 " llockd %0, [%1] \n" \
0074 " " #op1 " %L0, %L0, %L2 \n" \
0075 " " #op2 " %H0, %H0, %H2 \n" \
0076 " scondd %0, [%1] \n" \
0077 " bnz 1b \n" \
0078 : [val] "=&r"(val) \
0079 : "r"(&v->counter), "ir"(a) \
0080 : "cc"); \
0081 \
0082 return val; \
0083 }
0084
0085 #define arch_atomic64_add_return_relaxed arch_atomic64_add_return_relaxed
0086 #define arch_atomic64_sub_return_relaxed arch_atomic64_sub_return_relaxed
0087
0088 #define ATOMIC64_FETCH_OP(op, op1, op2) \
0089 static inline s64 arch_atomic64_fetch_##op##_relaxed(s64 a, atomic64_t *v) \
0090 { \
0091 s64 val, orig; \
0092 \
0093 __asm__ __volatile__( \
0094 "1: \n" \
0095 " llockd %0, [%2] \n" \
0096 " " #op1 " %L1, %L0, %L3 \n" \
0097 " " #op2 " %H1, %H0, %H3 \n" \
0098 " scondd %1, [%2] \n" \
0099 " bnz 1b \n" \
0100 : "=&r"(orig), "=&r"(val) \
0101 : "r"(&v->counter), "ir"(a) \
0102 : "cc"); \
0103 \
0104 return orig; \
0105 }
0106
0107 #define arch_atomic64_fetch_add_relaxed arch_atomic64_fetch_add_relaxed
0108 #define arch_atomic64_fetch_sub_relaxed arch_atomic64_fetch_sub_relaxed
0109
0110 #define arch_atomic64_fetch_and_relaxed arch_atomic64_fetch_and_relaxed
0111 #define arch_atomic64_fetch_andnot_relaxed arch_atomic64_fetch_andnot_relaxed
0112 #define arch_atomic64_fetch_or_relaxed arch_atomic64_fetch_or_relaxed
0113 #define arch_atomic64_fetch_xor_relaxed arch_atomic64_fetch_xor_relaxed
0114
0115 #define ATOMIC64_OPS(op, op1, op2) \
0116 ATOMIC64_OP(op, op1, op2) \
0117 ATOMIC64_OP_RETURN(op, op1, op2) \
0118 ATOMIC64_FETCH_OP(op, op1, op2)
0119
0120 ATOMIC64_OPS(add, add.f, adc)
0121 ATOMIC64_OPS(sub, sub.f, sbc)
0122
0123 #undef ATOMIC64_OPS
0124 #define ATOMIC64_OPS(op, op1, op2) \
0125 ATOMIC64_OP(op, op1, op2) \
0126 ATOMIC64_FETCH_OP(op, op1, op2)
0127
0128 ATOMIC64_OPS(and, and, and)
0129 ATOMIC64_OPS(andnot, bic, bic)
0130 ATOMIC64_OPS(or, or, or)
0131 ATOMIC64_OPS(xor, xor, xor)
0132
0133 #define arch_atomic64_andnot arch_atomic64_andnot
0134
0135 #undef ATOMIC64_OPS
0136 #undef ATOMIC64_FETCH_OP
0137 #undef ATOMIC64_OP_RETURN
0138 #undef ATOMIC64_OP
0139
0140 static inline s64
0141 arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new)
0142 {
0143 s64 prev;
0144
0145 smp_mb();
0146
0147 __asm__ __volatile__(
0148 "1: llockd %0, [%1] \n"
0149 " brne %L0, %L2, 2f \n"
0150 " brne %H0, %H2, 2f \n"
0151 " scondd %3, [%1] \n"
0152 " bnz 1b \n"
0153 "2: \n"
0154 : "=&r"(prev)
0155 : "r"(ptr), "ir"(expected), "r"(new)
0156 : "cc");
0157
0158 smp_mb();
0159
0160 return prev;
0161 }
0162
0163 static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new)
0164 {
0165 s64 prev;
0166
0167 smp_mb();
0168
0169 __asm__ __volatile__(
0170 "1: llockd %0, [%1] \n"
0171 " scondd %2, [%1] \n"
0172 " bnz 1b \n"
0173 "2: \n"
0174 : "=&r"(prev)
0175 : "r"(ptr), "r"(new)
0176 : "cc");
0177
0178 smp_mb();
0179
0180 return prev;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 static inline s64 arch_atomic64_dec_if_positive(atomic64_t *v)
0192 {
0193 s64 val;
0194
0195 smp_mb();
0196
0197 __asm__ __volatile__(
0198 "1: llockd %0, [%1] \n"
0199 " sub.f %L0, %L0, 1 # w0 - 1, set C on borrow\n"
0200 " sub.c %H0, %H0, 1 # if C set, w1 - 1\n"
0201 " brlt %H0, 0, 2f \n"
0202 " scondd %0, [%1] \n"
0203 " bnz 1b \n"
0204 "2: \n"
0205 : "=&r"(val)
0206 : "r"(&v->counter)
0207 : "cc");
0208
0209 smp_mb();
0210
0211 return val;
0212 }
0213 #define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 static inline s64 arch_atomic64_fetch_add_unless(atomic64_t *v, s64 a, s64 u)
0225 {
0226 s64 old, temp;
0227
0228 smp_mb();
0229
0230 __asm__ __volatile__(
0231 "1: llockd %0, [%2] \n"
0232 " brne %L0, %L4, 2f # continue to add since v != u \n"
0233 " breq.d %H0, %H4, 3f # return since v == u \n"
0234 "2: \n"
0235 " add.f %L1, %L0, %L3 \n"
0236 " adc %H1, %H0, %H3 \n"
0237 " scondd %1, [%2] \n"
0238 " bnz 1b \n"
0239 "3: \n"
0240 : "=&r"(old), "=&r" (temp)
0241 : "r"(&v->counter), "r"(a), "r"(u)
0242 : "cc");
0243
0244 smp_mb();
0245
0246 return old;
0247 }
0248 #define arch_atomic64_fetch_add_unless arch_atomic64_fetch_add_unless
0249
0250 #endif