1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
/* The following code may be included multiple times in a single file. */
#if DATA_BITS == 64
# define DATA_TYPE uint64_t
# define SUFFIX q
#elif DATA_BITS == 32
# define DATA_TYPE uint32_t
# define SUFFIX l
#elif DATA_BITS == 16
# define DATA_TYPE uint16_t
# define SUFFIX w
#elif DATA_BITS == 8
# define DATA_TYPE uint8_t
# define SUFFIX b
#else
#error unsupported data size
#endif
static __inline__ void coremu_glue(atomic_inc, SUFFIX)(DATA_TYPE *p) {
asm volatile(
LOCK_PREFIX "inc"coremu_str(SUFFIX)" %0"
: "+m"(*p)
:
: "cc");
}
static __inline__ void coremu_glue(atomic_dec, SUFFIX)(DATA_TYPE *p) {
asm volatile(
LOCK_PREFIX "dec"coremu_str(SUFFIX)" %0"
: "+m"(*p)
:
: "cc");
}
static __inline__ void coremu_glue(atomic_add, SUFFIX)(DATA_TYPE* addr,
DATA_TYPE val) {
asm volatile(
LOCK_PREFIX "add"coremu_str(SUFFIX)" %1, %0"
: "+m"(*addr)
: "a"(val)
: "cc");
}
/* swap the value VAL and *p.
* Return the value swapped out from memory. */
static inline DATA_TYPE coremu_glue(atomic_exchange, SUFFIX)(
DATA_TYPE *p, DATA_TYPE val)
{
DATA_TYPE out;
__asm __volatile(
"lock; xchg"coremu_str(SUFFIX)" %1,%2 \n\t"
: "=a" (out), "+m" (*p)
: "a" (val)
);
return out;
}
/* Return previous value in addr. So if the return value is the same as oldval,
* swap occured. */
static __inline__ DATA_TYPE coremu_glue(atomic_compare_exchange, SUFFIX)(DATA_TYPE *addr,
DATA_TYPE oldval, DATA_TYPE newval) {
asm volatile(
LOCK_PREFIX "cmpxchg"coremu_str(SUFFIX)" %2, %1"
: "+a"(oldval), "+m"(*addr)
: "q"(newval)
: "cc");
return oldval;
}
static __inline__ void coremu_glue(atomic_and, SUFFIX)(DATA_TYPE *addr,
DATA_TYPE mask) {
asm volatile(
LOCK_PREFIX "and"coremu_str(SUFFIX)" %1, %0"
: "+m"(*addr)
: "r"(mask)
: "cc");
}
static __inline__ void coremu_glue(atomic_or, SUFFIX)(DATA_TYPE *addr,
DATA_TYPE mask) {
asm volatile(
LOCK_PREFIX "or"coremu_str(SUFFIX)" %1, %0"
: "+m"(*addr)
: "r"(mask)
: "cc");
}
static __inline__ DATA_TYPE coremu_glue(atomic_xadd, SUFFIX)(
DATA_TYPE* addr, DATA_TYPE val) {
asm volatile(
LOCK_PREFIX "xadd"coremu_str(SUFFIX)" %0, %1"
: "+a"(val), "+m"(*addr)
:
: "cc");
return val;
}
#undef DATA_BITS
#undef DATA_TYPE
#undef SUFFIX
|