2005-04-16 15:20:36 -07:00
/*
* Copyright ( C ) 2002 MontaVista Software Inc .
* Author : Jun Sun , jsun @ mvista . com or jsun @ junsun . net
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# ifndef _ASM_FPU_H
# define _ASM_FPU_H
# include <linux/sched.h>
# include <linux/thread_info.h>
# include <asm/mipsregs.h>
# include <asm/cpu.h>
# include <asm/cpu-features.h>
2007-05-08 16:09:13 +01:00
# include <asm/hazards.h>
2005-04-16 15:20:36 -07:00
# include <asm/bitops.h>
# include <asm/processor.h>
# include <asm/current.h>
2006-04-05 09:45:47 +01:00
# ifdef CONFIG_MIPS_MT_FPAFF
# include <asm/mips_mt.h>
# endif
2005-04-16 15:20:36 -07:00
struct sigcontext ;
struct sigcontext32 ;
2007-03-10 01:07:45 +09:00
extern asmlinkage int ( * save_fp_context ) ( struct sigcontext __user * sc ) ;
extern asmlinkage int ( * restore_fp_context ) ( struct sigcontext __user * sc ) ;
2005-04-16 15:20:36 -07:00
2007-03-10 01:07:45 +09:00
extern asmlinkage int ( * save_fp_context32 ) ( struct sigcontext32 __user * sc ) ;
extern asmlinkage int ( * restore_fp_context32 ) ( struct sigcontext32 __user * sc ) ;
2005-04-16 15:20:36 -07:00
extern void fpu_emulator_init_fpu ( void ) ;
extern void _init_fpu ( void ) ;
extern void _save_fp ( struct task_struct * ) ;
extern void _restore_fp ( struct task_struct * ) ;
# define __enable_fpu() \
do { \
set_c0_status ( ST0_CU1 ) ; \
2007-05-08 16:09:13 +01:00
enable_fpu_hazard ( ) ; \
2005-04-16 15:20:36 -07:00
} while ( 0 )
# define __disable_fpu() \
do { \
clear_c0_status ( ST0_CU1 ) ; \
2007-05-08 16:09:13 +01:00
disable_fpu_hazard ( ) ; \
2005-04-16 15:20:36 -07:00
} while ( 0 )
# define enable_fpu() \
do { \
if ( cpu_has_fpu ) \
__enable_fpu ( ) ; \
} while ( 0 )
# define disable_fpu() \
do { \
if ( cpu_has_fpu ) \
__disable_fpu ( ) ; \
} while ( 0 )
# define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU)
2005-05-09 13:16:07 +00:00
static inline int __is_fpu_owner ( void )
{
return test_thread_flag ( TIF_USEDFPU ) ;
}
2005-04-16 15:20:36 -07:00
static inline int is_fpu_owner ( void )
{
2005-05-09 13:16:07 +00:00
return cpu_has_fpu & & __is_fpu_owner ( ) ;
2005-04-16 15:20:36 -07:00
}
2007-03-10 01:07:45 +09:00
static inline void __own_fpu ( void )
2005-04-16 15:20:36 -07:00
{
2007-03-10 01:07:45 +09:00
__enable_fpu ( ) ;
KSTK_STATUS ( current ) | = ST0_CU1 ;
set_thread_flag ( TIF_USEDFPU ) ;
}
2007-04-16 23:19:44 +09:00
static inline void own_fpu_inatomic ( int restore )
2007-03-10 01:07:45 +09:00
{
if ( cpu_has_fpu & & ! __is_fpu_owner ( ) ) {
__own_fpu ( ) ;
if ( restore )
_restore_fp ( current ) ;
2005-04-16 15:20:36 -07:00
}
2007-04-16 23:19:44 +09:00
}
static inline void own_fpu ( int restore )
{
preempt_disable ( ) ;
own_fpu_inatomic ( restore ) ;
2007-03-10 01:07:45 +09:00
preempt_enable ( ) ;
2005-04-16 15:20:36 -07:00
}
2007-03-10 01:07:45 +09:00
static inline void lose_fpu ( int save )
2005-04-16 15:20:36 -07:00
{
2007-03-10 01:07:45 +09:00
preempt_disable ( ) ;
if ( is_fpu_owner ( ) ) {
if ( save )
_save_fp ( current ) ;
2005-04-16 15:20:36 -07:00
KSTK_STATUS ( current ) & = ~ ST0_CU1 ;
2005-09-03 15:56:17 -07:00
clear_thread_flag ( TIF_USEDFPU ) ;
2005-04-16 15:20:36 -07:00
__disable_fpu ( ) ;
}
2007-03-10 01:07:45 +09:00
preempt_enable ( ) ;
2005-04-16 15:20:36 -07:00
}
static inline void init_fpu ( void )
{
2007-03-10 01:07:45 +09:00
preempt_disable ( ) ;
2005-04-16 15:20:36 -07:00
if ( cpu_has_fpu ) {
2007-03-10 01:07:45 +09:00
__own_fpu ( ) ;
2005-04-16 15:20:36 -07:00
_init_fpu ( ) ;
} else {
fpu_emulator_init_fpu ( ) ;
}
2007-03-10 01:07:45 +09:00
preempt_enable ( ) ;
2005-04-16 15:20:36 -07:00
}
static inline void save_fp ( struct task_struct * tsk )
{
if ( cpu_has_fpu )
_save_fp ( tsk ) ;
}
static inline void restore_fp ( struct task_struct * tsk )
{
if ( cpu_has_fpu )
_restore_fp ( tsk ) ;
}
static inline fpureg_t * get_fpu_regs ( struct task_struct * tsk )
{
2006-10-09 00:10:01 +09:00
if ( tsk = = current ) {
preempt_disable ( ) ;
if ( is_fpu_owner ( ) )
2005-04-16 15:20:36 -07:00
_save_fp ( current ) ;
2006-10-09 00:10:01 +09:00
preempt_enable ( ) ;
2005-04-16 15:20:36 -07:00
}
2006-05-16 01:26:03 +09:00
return tsk - > thread . fpu . fpr ;
2005-04-16 15:20:36 -07:00
}
# endif /* _ASM_FPU_H */