summaryrefslogtreecommitdiffstats
path: root/llvm/atomic/coremu-template.h
blob: 66b185c23651ed60cf3ab6100fa14d343008563f (plain)
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
OpenPOWER on IntegriCloud