File: /usr/src/linux/include/asm-m68k/system.h

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