1/*
2 * Copyright (C) 2002 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 *
5 * This program is free software; you can redistribute  it and/or modify it
6 * under  the terms of  the GNU General  Public License as published by the
7 * Free Software Foundation;  either version 2 of the  License, or (at your
8 * option) any later version.
9 *
10 */
11
12#ifndef _ASM_FPU_H
13#define _ASM_FPU_H
14
15#include <linux/config.h>
16#include <linux/sched.h>
17
18#include <asm/mipsregs.h>
19#include <asm/cpu.h>
20#include <asm/processor.h>
21#include <asm/current.h>
22
23struct sigcontext;
24
25extern asmlinkage int (*save_fp_context)(struct sigcontext *sc);
26extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
27
28extern void fpu_emulator_init_fpu(void);
29extern void _init_fpu(void);
30extern void _save_fp(struct task_struct *);
31extern void _restore_fp(struct task_struct *);
32
33#if defined(CONFIG_CPU_SB1)
34#define __enable_fpu_hazard()						\
35do {									\
36	asm(".set push		\n\t"					\
37	    ".set mips64	\n\t"					\
38	    ".set noreorder	\n\t"					\
39	    "ssnop		\n\t"					\
40	    "bnezl $0, .+4	\n\t"					\
41	    "ssnop		\n\t"					\
42	    ".set pop");						\
43} while (0)
44#else
45#define __enable_fpu_hazard()                                           \
46do {                                                                    \
47        asm("nop;nop;nop;nop");         /* max. hazard */               \
48} while (0)
49#endif
50
51#define __enable_fpu()							\
52do {									\
53        set_c0_status(ST0_CU1);						\
54        __enable_fpu_hazard();						\
55} while (0)
56
57#define __disable_fpu()							\
58do {									\
59	clear_c0_status(ST0_CU1);					\
60	/* We don't care about the c0 hazard here  */			\
61} while (0)
62
63#define enable_fpu()							\
64do {									\
65	if (mips_cpu.options & MIPS_CPU_FPU)				\
66		__enable_fpu();						\
67} while (0)
68
69#define disable_fpu()							\
70do {									\
71	if (mips_cpu.options & MIPS_CPU_FPU)				\
72		__disable_fpu();					\
73} while (0)
74
75
76#define clear_fpu_owner() do {current->flags &= ~PF_USEDFPU; } while(0)
77
78static inline int is_fpu_owner(void)
79{
80	return (mips_cpu.options & MIPS_CPU_FPU) &&
81		((current->flags & PF_USEDFPU) != 0);
82}
83
84static inline void own_fpu(void)
85{
86	if(mips_cpu.options & MIPS_CPU_FPU) {
87		__enable_fpu();
88		KSTK_STATUS(current) |= ST0_CU1;
89		current->flags |= PF_USEDFPU;
90	}
91}
92
93static inline void loose_fpu(void)
94{
95	if (mips_cpu.options & MIPS_CPU_FPU) {
96		KSTK_STATUS(current) &= ~ST0_CU1;
97		current->flags &= ~PF_USEDFPU;
98		__disable_fpu();
99	}
100}
101
102static inline void init_fpu(void)
103{
104	if (mips_cpu.options & MIPS_CPU_FPU) {
105		_init_fpu();
106	} else {
107		fpu_emulator_init_fpu();
108	}
109}
110
111static inline void save_fp(struct task_struct *tsk)
112{
113	if (mips_cpu.options & MIPS_CPU_FPU)
114		_save_fp(tsk);
115}
116
117static inline void restore_fp(struct task_struct *tsk)
118{
119	if (mips_cpu.options & MIPS_CPU_FPU)
120		_restore_fp(tsk);
121}
122
123static inline unsigned long long *get_fpu_regs(struct task_struct *tsk)
124{
125	if(mips_cpu.options & MIPS_CPU_FPU) {
126		if ((tsk == current) && is_fpu_owner())
127			_save_fp(current);
128		return (unsigned long long *)&tsk->thread.fpu.hard.fp_regs[0];
129	} else {
130		return (unsigned long long *)tsk->thread.fpu.soft.regs;
131	}
132}
133
134#endif /* _ASM_FPU_H */
135
136