import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / arch / ppc / kernel / bitops.c
1 /*
2  * BK Id: SCCS/s.bitops.c 1.10 09/21/01 03:00:33 dan
3  */
4 /*
5  * Copyright (C) 1996 Paul Mackerras.
6  */
7
8 #include <linux/kernel.h>
9 #include <asm/bitops.h>
10
11 /*
12  * If the bitops are not inlined in bitops.h, they are defined here.
13  *  -- paulus
14  */
15 #if !__INLINE_BITOPS
16 void set_bit(int nr, volatile void * addr)
17 {
18         unsigned long old;
19         unsigned long mask = 1 << (nr & 0x1f);
20         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
21         
22         __asm__ __volatile__(SMP_WMB "\n\
23 1:      lwarx   %0,0,%3 \n\
24         or      %0,%0,%2 \n"
25         PPC405_ERR77(0,%3)
26 "       stwcx.  %0,0,%3 \n\
27         bne     1b"
28         SMP_MB
29         : "=&r" (old), "=m" (*p)
30         : "r" (mask), "r" (p), "m" (*p)
31         : "cc" );
32 }
33
34 void clear_bit(int nr, volatile void *addr)
35 {
36         unsigned long old;
37         unsigned long mask = 1 << (nr & 0x1f);
38         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
39
40         __asm__ __volatile__(SMP_WMB "\n\
41 1:      lwarx   %0,0,%3 \n\
42         andc    %0,%0,%2 \n"
43         PPC405_ERR77(0,%3)
44 "       stwcx.  %0,0,%3 \n\
45         bne     1b"
46         SMP_MB
47         : "=&r" (old), "=m" (*p)
48         : "r" (mask), "r" (p), "m" (*p)
49         : "cc");
50 }
51
52 void change_bit(int nr, volatile void *addr)
53 {
54         unsigned long old;
55         unsigned long mask = 1 << (nr & 0x1f);
56         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
57
58         __asm__ __volatile__(SMP_WMB "\n\
59 1:      lwarx   %0,0,%3 \n\
60         xor     %0,%0,%2 \n"
61         PPC405_ERR77(0,%3)
62 "       stwcx.  %0,0,%3 \n\
63         bne     1b"
64         SMP_MB
65         : "=&r" (old), "=m" (*p)
66         : "r" (mask), "r" (p), "m" (*p)
67         : "cc");
68 }
69
70 int test_and_set_bit(int nr, volatile void *addr)
71 {
72         unsigned int old, t;
73         unsigned int mask = 1 << (nr & 0x1f);
74         volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
75
76         __asm__ __volatile__(SMP_WMB "\n\
77 1:      lwarx   %0,0,%4 \n\
78         or      %1,%0,%3 \n"
79         PPC405_ERR77(0,%4)
80 "       stwcx.  %1,0,%4 \n\
81         bne     1b"
82         SMP_MB
83         : "=&r" (old), "=&r" (t), "=m" (*p)
84         : "r" (mask), "r" (p), "m" (*p)
85         : "cc");
86
87         return (old & mask) != 0;
88 }
89
90 int test_and_clear_bit(int nr, volatile void *addr)
91 {
92         unsigned int old, t;
93         unsigned int mask = 1 << (nr & 0x1f);
94         volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
95
96         __asm__ __volatile__(SMP_WMB "\n\
97 1:      lwarx   %0,0,%4 \n\
98         andc    %1,%0,%3 \n"
99         PPC405_ERR77(0,%4)
100 "       stwcx.  %1,0,%4 \n\
101         bne     1b"
102         SMP_MB
103         : "=&r" (old), "=&r" (t), "=m" (*p)
104         : "r" (mask), "r" (p), "m" (*p)
105         : "cc");
106
107         return (old & mask) != 0;
108 }
109
110 int test_and_change_bit(int nr, volatile void *addr)
111 {
112         unsigned int old, t;
113         unsigned int mask = 1 << (nr & 0x1f);
114         volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
115
116         __asm__ __volatile__(SMP_WMB "\n\
117 1:      lwarx   %0,0,%4 \n\
118         xor     %1,%0,%3 \n"
119         PPC405_ERR77(0,%4)
120 "       stwcx.  %1,0,%4 \n\
121         bne     1b"
122         SMP_MB
123         : "=&r" (old), "=&r" (t), "=m" (*p)
124         : "r" (mask), "r" (p), "m" (*p)
125         : "cc");
126
127         return (old & mask) != 0;
128 }
129 #endif /* !__INLINE_BITOPS */