]> rtime.felk.cvut.cz Git - jailhouse.git/blob - hypervisor/arch/arm/include/asm/bitops.h
arm: Fix coding style of asm blocks
[jailhouse.git] / hypervisor / arch / arm / include / asm / bitops.h
1 /*
2  * Jailhouse, a Linux-based partitioning hypervisor
3  *
4  * Copyright (c) Siemens AG, 2013
5  *
6  * Authors:
7  *  Jan Kiszka <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  */
12
13 #ifndef _JAILHOUSE_ASM_BITOPS_H
14 #define _JAILHOUSE_ASM_BITOPS_H
15
16 #include <jailhouse/types.h>
17
18 #ifndef __ASSEMBLY__
19
20 #define BITOPT_ALIGN(bits, addr)                                \
21         do {                                                    \
22                 (addr) = (unsigned long *)((u32)(addr) & ~0x3)  \
23                         + (bits) / BITS_PER_LONG;               \
24                 (bits) %= BITS_PER_LONG;                        \
25         } while (0)
26
27 /* Load the cacheline in exclusive state */
28 #define PRELOAD(addr)                                           \
29         asm volatile (".arch_extension mp\n\t"                  \
30                       "pldw %0\n\t"                             \
31                       : "+Qo" (*(volatile unsigned long *)addr));
32
33 static inline __attribute__((always_inline)) void
34 clear_bit(int nr, volatile unsigned long *addr)
35 {
36         unsigned long ret, val;
37
38         BITOPT_ALIGN(nr, addr);
39
40         PRELOAD(addr);
41         do {
42                 asm volatile (
43                         "ldrex  %1, %2\n\t"
44                         "bic    %1, %3\n\t"
45                         "strex  %0, %1, %2\n\t"
46                         : "=r" (ret), "=r" (val),
47                         /* declare clobbering of this address to the compiler */
48                           "+Qo" (*(volatile unsigned long *)addr)
49                         : "r" (1 << nr));
50         } while (ret);
51 }
52
53 static inline __attribute__((always_inline)) void
54 set_bit(unsigned int nr, volatile unsigned long *addr)
55 {
56         unsigned long ret, val;
57
58         BITOPT_ALIGN(nr, addr);
59
60         PRELOAD(addr);
61         do {
62                 asm volatile (
63                         "ldrex  %1, %2\n\t"
64                         "orr    %1, %3\n\t"
65                         "strex  %0, %1, %2\n\t"
66                         : "=r" (ret), "=r" (val),
67                           "+Qo" (*(volatile unsigned long *)addr)
68                         : "r" (1 << nr));
69         } while (ret);
70 }
71
72 static inline __attribute__((always_inline)) int
73 test_bit(unsigned int nr, const volatile unsigned long *addr)
74 {
75         return ((1UL << (nr % BITS_PER_LONG)) &
76                 (addr[nr / BITS_PER_LONG])) != 0;
77 }
78
79 static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
80 {
81         unsigned long ret, val, test;
82
83         BITOPT_ALIGN(nr, addr);
84
85         PRELOAD(addr);
86         do {
87                 asm volatile (
88                         "ldrex  %1, %3\n\t"
89                         "ands   %2, %1, %4\n\t"
90                         "it     eq\n\t"
91                         "orreq  %1, %4\n\t"
92                         "strex  %0, %1, %3\n\t"
93                         : "=r" (ret), "=r" (val), "=r" (test),
94                           "+Qo" (*(volatile unsigned long *)addr)
95                         : "r" (1 << nr));
96         } while (ret);
97
98         return !!(test);
99 }
100
101
102 /* Count leading zeroes */
103 static inline unsigned long clz(unsigned long word)
104 {
105         unsigned long val;
106         asm volatile ("clz %0, %1" : "=r" (val) : "r" (word));
107         return val;
108 }
109
110 /* Returns the position of the least significant 1, MSB=31, LSB=0*/
111 static inline unsigned long ffsl(unsigned long word)
112 {
113         if (!word)
114                 return 0;
115         asm volatile ("rbit %0, %0" : "+r" (word));
116         return clz(word);
117 }
118
119 static inline unsigned long ffzl(unsigned long word)
120 {
121         return ffsl(~word);
122 }
123
124 /* Extend the value of 'size' bits to a signed long */
125 static inline unsigned long sign_extend(unsigned long val, unsigned int size)
126 {
127         unsigned long mask;
128
129         if (size >= sizeof(unsigned long) * 8)
130                 return val;
131
132         mask = 1U << (size - 1);
133         return (val ^ mask) - mask;
134 }
135
136 #endif /* !__ASSEMBLY__ */
137 #endif /* !_JAILHOUSE_ASM_BITOPS_H */