Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.git] / arch / sparc / lib / bitops.S
1 /* bitops.S: Low level assembler bit operations.
2  *
3  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
4  */
5
6 #include <asm/ptrace.h>
7 #include <asm/psr.h>
8
9         .text
10         .align  4
11
12         .globl  __bitops_begin
13 __bitops_begin:
14
15         /* Take bits in %g2 and set them in word at %g1,
16          * return whether bits were set in original value
17          * in %g2.  %g4 holds value to restore into %o7
18          * in delay slot of jmpl return, %g3 + %g5 + %g7 can be
19          * used as temporaries and thus is considered clobbered
20          * by all callers.
21          */
22         .globl  ___set_bit
23 ___set_bit:
24         rd      %psr, %g3
25         nop; nop; nop;
26         or      %g3, PSR_PIL, %g5
27         wr      %g5, 0x0, %psr
28         nop; nop; nop
29 #ifdef CONFIG_SMP
30         set     bitops_spinlock, %g5
31 2:      ldstub  [%g5], %g7              ! Spin on the byte lock for SMP.
32         orcc    %g7, 0x0, %g0           ! Did we get it?
33         bne     2b                      ! Nope...
34 #endif
35          ld     [%g1], %g7
36         or      %g7, %g2, %g5
37         and     %g7, %g2, %g2
38 #ifdef CONFIG_SMP
39         st      %g5, [%g1]
40         set     bitops_spinlock, %g5
41         stb     %g0, [%g5]
42 #else
43         st      %g5, [%g1]
44 #endif
45         wr      %g3, 0x0, %psr
46         nop; nop; nop
47         jmpl    %o7, %g0
48          mov    %g4, %o7
49
50         /* Same as above, but clears the bits from %g2 instead. */
51         .globl  ___clear_bit
52 ___clear_bit:
53         rd      %psr, %g3
54         nop; nop; nop
55         or      %g3, PSR_PIL, %g5
56         wr      %g5, 0x0, %psr
57         nop; nop; nop
58 #ifdef CONFIG_SMP
59         set     bitops_spinlock, %g5
60 2:      ldstub  [%g5], %g7              ! Spin on the byte lock for SMP.
61         orcc    %g7, 0x0, %g0           ! Did we get it?
62         bne     2b                      ! Nope...
63 #endif
64          ld     [%g1], %g7
65         andn    %g7, %g2, %g5
66         and     %g7, %g2, %g2
67 #ifdef CONFIG_SMP
68         st      %g5, [%g1]
69         set     bitops_spinlock, %g5
70         stb     %g0, [%g5]
71 #else
72         st      %g5, [%g1]
73 #endif
74         wr      %g3, 0x0, %psr
75         nop; nop; nop
76         jmpl    %o7, %g0
77          mov    %g4, %o7
78
79         /* Same thing again, but this time toggles the bits from %g2. */
80         .globl  ___change_bit
81 ___change_bit:
82         rd      %psr, %g3
83         nop; nop; nop
84         or      %g3, PSR_PIL, %g5
85         wr      %g5, 0x0, %psr
86         nop; nop; nop
87 #ifdef CONFIG_SMP
88         set     bitops_spinlock, %g5
89 2:      ldstub  [%g5], %g7              ! Spin on the byte lock for SMP.
90         orcc    %g7, 0x0, %g0           ! Did we get it?
91         bne     2b                      ! Nope...
92 #endif
93          ld     [%g1], %g7
94         xor     %g7, %g2, %g5
95         and     %g7, %g2, %g2
96 #ifdef CONFIG_SMP
97         st      %g5, [%g1]
98         set     bitops_spinlock, %g5
99         stb     %g0, [%g5]
100 #else
101         st      %g5, [%g1]
102 #endif
103         wr      %g3, 0x0, %psr
104         nop; nop; nop
105         jmpl    %o7, %g0
106          mov    %g4, %o7
107
108         .globl  __bitops_end
109 __bitops_end: