mn10300: add cc clobbers to asm statements
[linux-3.10.git] / arch / mn10300 / include / asm / system.h
1 /* MN10300 System definitions
2  *
3  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 #ifndef _ASM_SYSTEM_H
12 #define _ASM_SYSTEM_H
13
14 #include <asm/cpu-regs.h>
15
16 #ifdef __KERNEL__
17 #ifndef __ASSEMBLY__
18
19 #include <linux/kernel.h>
20
21 struct task_struct;
22 struct thread_struct;
23
24 extern asmlinkage
25 struct task_struct *__switch_to(struct thread_struct *prev,
26                                 struct thread_struct *next,
27                                 struct task_struct *prev_task);
28
29 /* context switching is now performed out-of-line in switch_to.S */
30 #define switch_to(prev, next, last)                                     \
31 do {                                                                    \
32         current->thread.wchan = (u_long) __builtin_return_address(0);   \
33         (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \
34         mb();                                                           \
35         current->thread.wchan = 0;                                      \
36 } while (0)
37
38 #define arch_align_stack(x) (x)
39
40 #define nop() asm volatile ("nop")
41
42 #endif /* !__ASSEMBLY__ */
43
44 /*
45  * Force strict CPU ordering.
46  * And yes, this is required on UP too when we're talking
47  * to devices.
48  *
49  * For now, "wmb()" doesn't actually do anything, as all
50  * Intel CPU's follow what Intel calls a *Processor Order*,
51  * in which all writes are seen in the program order even
52  * outside the CPU.
53  *
54  * I expect future Intel CPU's to have a weaker ordering,
55  * but I'd also expect them to finally get their act together
56  * and add some real memory barriers if so.
57  *
58  * Some non intel clones support out of order store. wmb() ceases to be a
59  * nop for these.
60  */
61
62 #define mb()    asm volatile ("": : :"memory")
63 #define rmb()   mb()
64 #define wmb()   asm volatile ("": : :"memory")
65
66 #ifdef CONFIG_SMP
67 #define smp_mb()        mb()
68 #define smp_rmb()       rmb()
69 #define smp_wmb()       wmb()
70 #else
71 #define smp_mb()        barrier()
72 #define smp_rmb()       barrier()
73 #define smp_wmb()       barrier()
74 #endif
75
76 #define set_mb(var, value)  do { var = value;  mb(); } while (0)
77 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
78
79 #define read_barrier_depends()          do {} while (0)
80 #define smp_read_barrier_depends()      do {} while (0)
81
82 /*****************************************************************************/
83 /*
84  * interrupt control
85  * - "disabled": run in IM1/2
86  *   - level 0 - GDB stub
87  *   - level 1 - virtual serial DMA (if present)
88  *   - level 5 - normal interrupt priority
89  *   - level 6 - timer interrupt
90  * - "enabled":  run in IM7
91  */
92 #ifdef CONFIG_MN10300_TTYSM
93 #define MN10300_CLI_LEVEL       EPSW_IM_2
94 #else
95 #define MN10300_CLI_LEVEL       EPSW_IM_1
96 #endif
97
98 #define local_save_flags(x)                     \
99 do {                                            \
100         typecheck(unsigned long, x);            \
101         asm volatile(                           \
102                 "       mov epsw,%0     \n"     \
103                 : "=d"(x)                       \
104                 );                              \
105 } while (0)
106
107 #define local_irq_disable()                                             \
108 do {                                                                    \
109         asm volatile(                                                   \
110                 "       and %0,epsw     \n"                             \
111                 "       or %1,epsw      \n"                             \
112                 "       nop             \n"                             \
113                 "       nop             \n"                             \
114                 "       nop             \n"                             \
115                 :                                                       \
116                 : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)       \
117                 );                                                      \
118 } while (0)
119
120 #define local_irq_save(x)                       \
121 do {                                            \
122         local_save_flags(x);                    \
123         local_irq_disable();                    \
124 } while (0)
125
126 /*
127  * we make sure local_irq_enable() doesn't cause priority inversion
128  */
129 #ifndef __ASSEMBLY__
130
131 extern unsigned long __mn10300_irq_enabled_epsw;
132
133 #endif
134
135 #define local_irq_enable()                                              \
136 do {                                                                    \
137         unsigned long tmp;                                              \
138                                                                         \
139         asm volatile(                                                   \
140                 "       mov     epsw,%0         \n"                     \
141                 "       and     %1,%0           \n"                     \
142                 "       or      %2,%0           \n"                     \
143                 "       mov     %0,epsw         \n"                     \
144                 : "=&d"(tmp)                                            \
145                 : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw)        \
146                 : "cc"                                                  \
147                 );                                                      \
148 } while (0)
149
150 #define local_irq_restore(x)                    \
151 do {                                            \
152         typecheck(unsigned long, x);            \
153         asm volatile(                           \
154                 "       mov %0,epsw     \n"     \
155                 "       nop             \n"     \
156                 "       nop             \n"     \
157                 "       nop             \n"     \
158                 :                               \
159                 : "d"(x)                        \
160                 : "memory", "cc"                \
161                 );                              \
162 } while (0)
163
164 #define irqs_disabled()                         \
165 ({                                              \
166         unsigned long flags;                    \
167         local_save_flags(flags);                \
168         (flags & EPSW_IM) <= MN10300_CLI_LEVEL; \
169 })
170
171 /* hook to save power by halting the CPU
172  * - called from the idle loop
173  * - must reenable interrupts (which takes three instruction cycles to complete)
174  */
175 #define safe_halt()                                                     \
176 do {                                                                    \
177         asm volatile("  or      %0,epsw \n"                             \
178                      "  nop             \n"                             \
179                      "  nop             \n"                             \
180                      "  bset    %2,(%1) \n"                             \
181                      :                                                  \
182                      : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)\
183                      : "cc"                                             \
184                      );                                                 \
185 } while (0)
186
187 #define STI     or EPSW_IE|EPSW_IM,epsw
188 #define CLI     and ~EPSW_IM,epsw; or EPSW_IE|MN10300_CLI_LEVEL,epsw; nop; nop; nop
189
190 /*****************************************************************************/
191 /*
192  * MN10300 doesn't actually have an exchange instruction
193  */
194 #ifndef __ASSEMBLY__
195
196 struct __xchg_dummy { unsigned long a[100]; };
197 #define __xg(x) ((struct __xchg_dummy *)(x))
198
199 static inline
200 unsigned long __xchg(volatile unsigned long *m, unsigned long val)
201 {
202         unsigned long retval;
203         unsigned long flags;
204
205         local_irq_save(flags);
206         retval = *m;
207         *m = val;
208         local_irq_restore(flags);
209         return retval;
210 }
211
212 #define xchg(ptr, v)                                            \
213         ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr),    \
214                                      (unsigned long)(v)))
215
216 static inline unsigned long __cmpxchg(volatile unsigned long *m,
217                                       unsigned long old, unsigned long new)
218 {
219         unsigned long retval;
220         unsigned long flags;
221
222         local_irq_save(flags);
223         retval = *m;
224         if (retval == old)
225                 *m = new;
226         local_irq_restore(flags);
227         return retval;
228 }
229
230 #define cmpxchg(ptr, o, n)                                      \
231         ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \
232                                         (unsigned long)(o),     \
233                                         (unsigned long)(n)))
234
235 #endif /* !__ASSEMBLY__ */
236
237 #endif /* __KERNEL__ */
238 #endif /* _ASM_SYSTEM_H */