[PATCH] mutex subsystem, add atomic_xchg() to all arches
[linux-2.6.git] / include / asm-mips / interrupt.h
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
7  * Copyright (C) 1996 by Paul M. Antoine
8  * Copyright (C) 1999 Silicon Graphics
9  * Copyright (C) 2000 MIPS Technologies, Inc.
10  */
11 #ifndef _ASM_INTERRUPT_H
12 #define _ASM_INTERRUPT_H
13
14 #include <linux/config.h>
15 #include <asm/hazards.h>
16
17 __asm__ (
18         "       .macro  local_irq_enable                                \n"
19         "       .set    push                                            \n"
20         "       .set    reorder                                         \n"
21         "       .set    noat                                            \n"
22 #ifdef CONFIG_CPU_MIPSR2
23         "       ei                                                      \n"
24 #else
25         "       mfc0    $1,$12                                          \n"
26         "       ori     $1,0x1f                                         \n"
27         "       xori    $1,0x1e                                         \n"
28         "       mtc0    $1,$12                                          \n"
29 #endif
30         "       irq_enable_hazard                                       \n"
31         "       .set    pop                                             \n"
32         "       .endm");
33
34 static inline void local_irq_enable(void)
35 {
36         __asm__ __volatile__(
37                 "local_irq_enable"
38                 : /* no outputs */
39                 : /* no inputs */
40                 : "memory");
41 }
42
43 /*
44  * For cli() we have to insert nops to make sure that the new value
45  * has actually arrived in the status register before the end of this
46  * macro.
47  * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
48  * no nops at all.
49  */
50 __asm__ (
51         "       .macro  local_irq_disable\n"
52         "       .set    push                                            \n"
53         "       .set    noat                                            \n"
54 #ifdef CONFIG_CPU_MIPSR2
55         "       di                                                      \n"
56 #else
57         "       mfc0    $1,$12                                          \n"
58         "       ori     $1,1                                            \n"
59         "       xori    $1,1                                            \n"
60         "       .set    noreorder                                       \n"
61         "       mtc0    $1,$12                                          \n"
62 #endif
63         "       irq_disable_hazard                                      \n"
64         "       .set    pop                                             \n"
65         "       .endm                                                   \n");
66
67 static inline void local_irq_disable(void)
68 {
69         __asm__ __volatile__(
70                 "local_irq_disable"
71                 : /* no outputs */
72                 : /* no inputs */
73                 : "memory");
74 }
75
76 __asm__ (
77         "       .macro  local_save_flags flags                          \n"
78         "       .set    push                                            \n"
79         "       .set    reorder                                         \n"
80         "       mfc0    \\flags, $12                                    \n"
81         "       .set    pop                                             \n"
82         "       .endm                                                   \n");
83
84 #define local_save_flags(x)                                             \
85 __asm__ __volatile__(                                                   \
86         "local_save_flags %0"                                           \
87         : "=r" (x))
88
89 __asm__ (
90         "       .macro  local_irq_save result                           \n"
91         "       .set    push                                            \n"
92         "       .set    reorder                                         \n"
93         "       .set    noat                                            \n"
94 #ifdef CONFIG_CPU_MIPSR2
95         "       di      \\result                                        \n"
96 #else
97         "       mfc0    \\result, $12                                   \n"
98         "       ori     $1, \\result, 1                                 \n"
99         "       xori    $1, 1                                           \n"
100         "       .set    noreorder                                       \n"
101         "       mtc0    $1, $12                                         \n"
102 #endif
103         "       irq_disable_hazard                                      \n"
104         "       .set    pop                                             \n"
105         "       .endm                                                   \n");
106
107 #define local_irq_save(x)                                               \
108 __asm__ __volatile__(                                                   \
109         "local_irq_save\t%0"                                            \
110         : "=r" (x)                                                      \
111         : /* no inputs */                                               \
112         : "memory")
113
114 __asm__ (
115         "       .macro  local_irq_restore flags                         \n"
116         "       .set    noreorder                                       \n"
117         "       .set    noat                                            \n"
118 #if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
119         /*
120          * Slow, but doesn't suffer from a relativly unlikely race
121          * condition we're having since days 1.
122          */
123         "       beqz    \\flags, 1f                                     \n"
124         "        di                                                     \n"
125         "       ei                                                      \n"
126         "1:                                                             \n"
127 #elif defined(CONFIG_CPU_MIPSR2)
128         /*
129          * Fast, dangerous.  Life is fun, life is good.
130          */
131         "       mfc0    $1, $12                                         \n"
132         "       ins     $1, \\flags, 0, 1                               \n"
133         "       mtc0    $1, $12                                         \n"
134 #else
135         "       mfc0    $1, $12                                         \n"
136         "       andi    \\flags, 1                                      \n"
137         "       ori     $1, 1                                           \n"
138         "       xori    $1, 1                                           \n"
139         "       or      \\flags, $1                                     \n"
140         "       mtc0    \\flags, $12                                    \n"
141 #endif
142         "       irq_disable_hazard                                      \n"
143         "       .set    at                                              \n"
144         "       .set    reorder                                         \n"
145         "       .endm                                                   \n");
146
147 #define local_irq_restore(flags)                                        \
148 do {                                                                    \
149         unsigned long __tmp1;                                           \
150                                                                         \
151         __asm__ __volatile__(                                           \
152                 "local_irq_restore\t%0"                                 \
153                 : "=r" (__tmp1)                                         \
154                 : "0" (flags)                                           \
155                 : "memory");                                            \
156 } while(0)
157
158 #define irqs_disabled()                                                 \
159 ({                                                                      \
160         unsigned long flags;                                            \
161         local_save_flags(flags);                                        \
162         !(flags & 1);                                                   \
163 })
164
165 #endif /* _ASM_INTERRUPT_H */