Merge git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-mn10300
[pandora-kernel.git] / arch / mn10300 / include / asm / fpu.h
index 64a2b83..b7625de 100644 (file)
 #ifndef _ASM_FPU_H
 #define _ASM_FPU_H
 
-#include <asm/processor.h>
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+#include <asm/exceptions.h>
 #include <asm/sigcontext.h>
-#include <asm/user.h>
 
 #ifdef __KERNEL__
 
-/* the task that owns the FPU state */
+extern asmlinkage void fpu_disabled(void);
+
+#ifdef CONFIG_FPU
+
+#ifdef CONFIG_LAZY_SAVE_FPU
+/* the task that currently owns the FPU state */
 extern struct task_struct *fpu_state_owner;
+#endif
 
-#define set_using_fpu(tsk)                             \
-do {                                                   \
-       (tsk)->thread.fpu_flags |= THREAD_USING_FPU;    \
-} while (0)
+#if (THREAD_USING_FPU & ~0xff)
+#error THREAD_USING_FPU must be smaller than 0x100.
+#endif
 
-#define clear_using_fpu(tsk)                           \
-do {                                                   \
-       (tsk)->thread.fpu_flags &= ~THREAD_USING_FPU;   \
-} while (0)
+static inline void set_using_fpu(struct task_struct *tsk)
+{
+       asm volatile(
+               "bset %0,(0,%1)"
+               :
+               : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
+               : "memory", "cc");
+}
 
-#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
+static inline void clear_using_fpu(struct task_struct *tsk)
+{
+       asm volatile(
+               "bclr %0,(0,%1)"
+               :
+               : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags)
+               : "memory", "cc");
+}
 
-#define unlazy_fpu(tsk)                                        \
-do {                                                   \
-       preempt_disable();                              \
-       if (fpu_state_owner == (tsk))                   \
-               fpu_save(&tsk->thread.fpu_state);       \
-       preempt_enable();                               \
-} while (0)
-
-#define exit_fpu()                             \
-do {                                           \
-       struct task_struct *__tsk = current;    \
-       preempt_disable();                      \
-       if (fpu_state_owner == __tsk)           \
-               fpu_state_owner = NULL;         \
-       preempt_enable();                       \
-} while (0)
-
-#define flush_fpu()                                    \
-do {                                                   \
-       struct task_struct *__tsk = current;            \
-       preempt_disable();                              \
-       if (fpu_state_owner == __tsk) {                 \
-               fpu_state_owner = NULL;                 \
-               __tsk->thread.uregs->epsw &= ~EPSW_FE;  \
-       }                                               \
-       preempt_enable();                               \
-       clear_using_fpu(__tsk);                         \
-} while (0)
+#define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU)
 
-extern asmlinkage void fpu_init_state(void);
 extern asmlinkage void fpu_kill_state(struct task_struct *);
-extern asmlinkage void fpu_disabled(struct pt_regs *, enum exception_code);
 extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
-
-#ifdef CONFIG_FPU
+extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code);
+extern asmlinkage void fpu_init_state(void);
 extern asmlinkage void fpu_save(struct fpu_state_struct *);
-extern asmlinkage void fpu_restore(struct fpu_state_struct *);
-#else
-#define fpu_save(a)
-#define fpu_restore(a)
-#endif /* CONFIG_FPU  */
-
-/*
- * signal frame handlers
- */
 extern int fpu_setup_sigcontext(struct fpucontext *buf);
 extern int fpu_restore_sigcontext(struct fpucontext *buf);
 
+static inline void unlazy_fpu(struct task_struct *tsk)
+{
+       preempt_disable();
+#ifndef CONFIG_LAZY_SAVE_FPU
+       if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
+               fpu_save(&tsk->thread.fpu_state);
+               tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
+               tsk->thread.uregs->epsw &= ~EPSW_FE;
+       }
+#else
+       if (fpu_state_owner == tsk)
+               fpu_save(&tsk->thread.fpu_state);
+#endif
+       preempt_enable();
+}
+
+static inline void exit_fpu(void)
+{
+#ifdef CONFIG_LAZY_SAVE_FPU
+       struct task_struct *tsk = current;
+
+       preempt_disable();
+       if (fpu_state_owner == tsk)
+               fpu_state_owner = NULL;
+       preempt_enable();
+#endif
+}
+
+static inline void flush_fpu(void)
+{
+       struct task_struct *tsk = current;
+
+       preempt_disable();
+#ifndef CONFIG_LAZY_SAVE_FPU
+       if (tsk->thread.fpu_flags & THREAD_HAS_FPU) {
+               tsk->thread.fpu_flags &= ~THREAD_HAS_FPU;
+               tsk->thread.uregs->epsw &= ~EPSW_FE;
+       }
+#else
+       if (fpu_state_owner == tsk) {
+               fpu_state_owner = NULL;
+               tsk->thread.uregs->epsw &= ~EPSW_FE;
+       }
+#endif
+       preempt_enable();
+       clear_using_fpu(tsk);
+}
+
+#else /* CONFIG_FPU */
+
+extern asmlinkage
+void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
+#define fpu_invalid_op unexpected_fpu_exception
+#define fpu_exception unexpected_fpu_exception
+
+struct task_struct;
+struct fpu_state_struct;
+static inline bool is_using_fpu(struct task_struct *tsk) { return false; }
+static inline void set_using_fpu(struct task_struct *tsk) {}
+static inline void clear_using_fpu(struct task_struct *tsk) {}
+static inline void fpu_init_state(void) {}
+static inline void fpu_save(struct fpu_state_struct *s) {}
+static inline void fpu_kill_state(struct task_struct *tsk) {}
+static inline void unlazy_fpu(struct task_struct *tsk) {}
+static inline void exit_fpu(void) {}
+static inline void flush_fpu(void) {}
+static inline int fpu_setup_sigcontext(struct fpucontext *buf) { return 0; }
+static inline int fpu_restore_sigcontext(struct fpucontext *buf) { return 0; }
+#endif /* CONFIG_FPU  */
+
 #endif /* __KERNEL__ */
+#endif /* !__ASSEMBLY__ */
 #endif /* _ASM_FPU_H */