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#ifndef _ASM_FPU_H 11#define _ASM_FPU_H 12 13#include <linux/sched.h> 14#include <linux/thread_info.h> 15#include <linux/bitops.h> 16 17#include <asm/mipsregs.h> 18#include <asm/cpu.h> 19#include <asm/cpu-features.h> 20#include <asm/hazards.h> 21#include <asm/processor.h> 22#include <asm/current.h> 23 24#ifdef CONFIG_MIPS_MT_FPAFF 25#include <asm/mips_mt.h> 26#endif 27 28struct sigcontext; 29struct sigcontext32; 30 31extern void fpu_emulator_init_fpu(void); 32extern void _init_fpu(void); 33extern void _save_fp(struct task_struct *); 34extern void _restore_fp(struct task_struct *); 35 36#define __enable_fpu() \ 37do { \ 38 set_c0_status(ST0_CU1); \ 39 enable_fpu_hazard(); \ 40} while (0) 41 42#define __disable_fpu() \ 43do { \ 44 clear_c0_status(ST0_CU1); \ 45 disable_fpu_hazard(); \ 46} while (0) 47 48#define enable_fpu() \ 49do { \ 50 if (cpu_has_fpu) \ 51 __enable_fpu(); \ 52} while (0) 53 54#define disable_fpu() \ 55do { \ 56 if (cpu_has_fpu) \ 57 __disable_fpu(); \ 58} while (0) 59 60 61#define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU) 62 63static inline int __is_fpu_owner(void) 64{ 65 return test_thread_flag(TIF_USEDFPU); 66} 67 68static inline int is_fpu_owner(void) 69{ 70 return cpu_has_fpu && __is_fpu_owner(); 71} 72 73static inline void __own_fpu(void) 74{ 75 __enable_fpu(); 76 KSTK_STATUS(current) |= ST0_CU1; 77 set_thread_flag(TIF_USEDFPU); 78} 79 80static inline void own_fpu_inatomic(int restore) 81{ 82 if (cpu_has_fpu && !__is_fpu_owner()) { 83 __own_fpu(); 84 if (restore) 85 _restore_fp(current); 86 } 87} 88 89static inline void own_fpu(int restore) 90{ 91 preempt_disable(); 92 own_fpu_inatomic(restore); 93 preempt_enable(); 94} 95 96static inline void lose_fpu(int save) 97{ 98 preempt_disable(); 99 if (is_fpu_owner()) { 100 if (save) 101 _save_fp(current); 102 KSTK_STATUS(current) &= ~ST0_CU1; 103 clear_thread_flag(TIF_USEDFPU); 104 __disable_fpu(); 105 } 106 preempt_enable(); 107} 108 109static inline void init_fpu(void) 110{ 111 preempt_disable(); 112 if (cpu_has_fpu) { 113 __own_fpu(); 114 _init_fpu(); 115 } else { 116 fpu_emulator_init_fpu(); 117 } 118 preempt_enable(); 119} 120 121static inline void save_fp(struct task_struct *tsk) 122{ 123 if (cpu_has_fpu) 124 _save_fp(tsk); 125} 126 127static inline void restore_fp(struct task_struct *tsk) 128{ 129 if (cpu_has_fpu) 130 _restore_fp(tsk); 131} 132 133static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) 134{ 135 if (tsk == current) { 136 preempt_disable(); 137 if (is_fpu_owner()) 138 _save_fp(current); 139 preempt_enable(); 140 } 141 142 return tsk->thread.fpu.fpr; 143} 144 145#endif /* _ASM_FPU_H */ 146