Merge with Linux 2.4.0-test6-pre2.
[linux-2.6/linux-mips.git] / include / asm-m68k / system.h
blob64dab98d8ec9f90cd295c0b32a0dc81273857c96
1 #ifndef _M68K_SYSTEM_H
2 #define _M68K_SYSTEM_H
4 #include <linux/config.h> /* get configuration macros */
5 #include <linux/linkage.h>
6 #include <asm/segment.h>
7 #include <asm/entry.h>
9 #define prepare_to_switch() do { } while(0)
12 * switch_to(n) should switch tasks to task ptr, first checking that
13 * ptr isn't the current task, in which case it does nothing. This
14 * also clears the TS-flag if the task we switched to has used the
15 * math co-processor latest.
18 * switch_to() saves the extra registers, that are not saved
19 * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
20 * a0-a1. Some of these are used by schedule() and its predecessors
21 * and so we might get see unexpected behaviors when a task returns
22 * with unexpected register values.
24 * syscall stores these registers itself and none of them are used
25 * by syscall after the function in the syscall has been called.
27 * Beware that resume now expects *next to be in d1 and the offset of
28 * tss to be in a1. This saves a few instructions as we no longer have
29 * to push them onto the stack and read them back right after.
31 * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
33 * Changed 96/09/19 by Andreas Schwab
34 * pass prev in a0, next in a1, offset of tss in d1, and whether
35 * the mm structures are shared in d2 (to avoid atc flushing).
37 asmlinkage void resume(void);
38 #define switch_to(prev,next,last) { \
39 register void *_prev __asm__ ("a0") = (prev); \
40 register void *_next __asm__ ("a1") = (next); \
41 register void *_last __asm__ ("d1"); \
42 __asm__ __volatile__("jbsr " SYMBOL_NAME_STR(resume) \
43 : "=d" (_last) : "a" (_prev), "a" (_next) \
44 : "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1"); \
45 (last) = _last; \
49 /* interrupt control.. */
50 #if 0
51 #define __sti() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
52 #else
53 #include <asm/hardirq.h>
54 #define __sti() ({ \
55 if (!local_irq_count[smp_processor_id()]) \
56 asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory"); \
58 #endif
59 #define __cli() asm volatile ("oriw #0x0700,%%sr": : : "memory")
60 #define __save_flags(x) asm volatile ("movew %%sr,%0":"=d" (x) : : "memory")
61 #define __restore_flags(x) asm volatile ("movew %0,%%sr": :"d" (x) : "memory")
63 /* For spinlocks etc */
64 #define local_irq_save(x) ({ __save_flags(x); __cli(); })
65 #define local_irq_restore(x) __restore_flags(x)
66 #define local_irq_disable() __cli()
67 #define local_irq_enable() __sti()
69 #define cli() __cli()
70 #define sti() __sti()
71 #define save_flags(x) __save_flags(x)
72 #define restore_flags(x) __restore_flags(x)
76 * Force strict CPU ordering.
77 * Not really required on m68k...
79 #define nop() asm volatile ("nop"::)
80 #define mb() asm volatile ("" : : :"memory")
81 #define rmb() asm volatile ("" : : :"memory")
82 #define wmb() asm volatile ("" : : :"memory")
83 #define set_mb(var, value) do { xchg(&var, value); } while (0)
84 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
87 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
88 #define tas(ptr) (xchg((ptr),1))
90 struct __xchg_dummy { unsigned long a[100]; };
91 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
93 #ifndef CONFIG_RMW_INSNS
94 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
96 unsigned long tmp, flags;
98 save_flags(flags);
99 cli();
101 switch (size) {
102 case 1:
103 __asm__ __volatile__
104 ("moveb %2,%0\n\t"
105 "moveb %1,%2"
106 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
107 break;
108 case 2:
109 __asm__ __volatile__
110 ("movew %2,%0\n\t"
111 "movew %1,%2"
112 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
113 break;
114 case 4:
115 __asm__ __volatile__
116 ("movel %2,%0\n\t"
117 "movel %1,%2"
118 : "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
119 break;
121 restore_flags(flags);
122 return tmp;
124 #else
125 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
127 switch (size) {
128 case 1:
129 __asm__ __volatile__
130 ("moveb %2,%0\n\t"
131 "1:\n\t"
132 "casb %0,%1,%2\n\t"
133 "jne 1b"
134 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
135 break;
136 case 2:
137 __asm__ __volatile__
138 ("movew %2,%0\n\t"
139 "1:\n\t"
140 "casw %0,%1,%2\n\t"
141 "jne 1b"
142 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
143 break;
144 case 4:
145 __asm__ __volatile__
146 ("movel %2,%0\n\t"
147 "1:\n\t"
148 "casl %0,%1,%2\n\t"
149 "jne 1b"
150 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
151 break;
153 return x;
155 #endif
157 #endif /* _M68K_SYSTEM_H */