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 #ifndef _ASM_FPU_H 12 #define _ASM_FPU_H 13 14 #include <linux/config.h> 15 #include <linux/sched.h> 16 17 #include <asm/mipsregs.h> 18 #include <asm/cpu.h> 19 #include <asm/bitops.h> 20 #include <asm/processor.h> 21 #include <asm/current.h> 22 23 struct sigcontext; 24 25 extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); 26 extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); 27 28 extern void fpu_emulator_init_fpu(void); 29 extern void _init_fpu(void); 30 extern void _save_fp(struct task_struct *); 31 extern void _restore_fp(struct task_struct *); 32 33 #if defined(CONFIG_CPU_SB1) 34 #define __enable_fpu_hazard() \ 35 do { \ 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() \ 46 do { \ 47 asm("nop;nop;nop;nop"); /* max. hazard */ \ 48 } while (0) 49 #endif 50 51 #define __enable_fpu() \ 52 do { \ 53 set_c0_status(ST0_CU1); \ 54 __enable_fpu_hazard(); \ 55 } while (0) 56 57 #define __disable_fpu() \ 58 do { \ 59 clear_c0_status(ST0_CU1); \ 60 /* We don't care about the c0 hazard here */ \ 61 } while (0) 62 63 #define enable_fpu() \ 64 do { \ 65 if (cpu_has_fpu) \ 66 __enable_fpu(); \ 67 } while (0) 68 69 #define disable_fpu() \ 70 do { \ 71 if (cpu_has_fpu) \ 72 __disable_fpu(); \ 73 } while (0) 74 75 76 #define clear_fpu_owner() do { current->flags &= ~PF_USEDFPU; } while(0) 77 is_fpu_owner(void)78static inline int is_fpu_owner(void) 79 { 80 return cpu_has_fpu && ((current->flags & PF_USEDFPU) != 0); 81 } 82 own_fpu(void)83static inline void own_fpu(void) 84 { 85 if (cpu_has_fpu) { 86 __enable_fpu(); 87 KSTK_STATUS(current) |= ST0_CU1; 88 current->flags |= PF_USEDFPU; 89 } 90 } 91 lose_fpu(void)92static inline void lose_fpu(void) 93 { 94 if (cpu_has_fpu) { 95 KSTK_STATUS(current) &= ~ST0_CU1; 96 current->flags &= ~PF_USEDFPU; 97 __disable_fpu(); 98 } 99 } 100 init_fpu(void)101static inline void init_fpu(void) 102 { 103 if (cpu_has_fpu) { 104 _init_fpu(); 105 } else { 106 fpu_emulator_init_fpu(); 107 } 108 } 109 save_fp(struct task_struct * tsk)110static inline void save_fp(struct task_struct *tsk) 111 { 112 if (cpu_has_fpu) 113 _save_fp(tsk); 114 } 115 restore_fp(struct task_struct * tsk)116static inline void restore_fp(struct task_struct *tsk) 117 { 118 if (cpu_has_fpu) 119 _restore_fp(tsk); 120 } 121 get_fpu_regs(struct task_struct * tsk)122static inline unsigned long long *get_fpu_regs(struct task_struct *tsk) 123 { 124 if (cpu_has_fpu) { 125 if ((tsk == current) && is_fpu_owner()) 126 _save_fp(current); 127 return (unsigned long long *)&tsk->thread.fpu.hard.fp_regs[0]; 128 } else { 129 return (unsigned long long *)tsk->thread.fpu.soft.regs; 130 } 131 } 132 133 #endif /* _ASM_FPU_H */ 134