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 struct sigcontext32; 25 26 extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); 27 extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); 28 29 extern asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); 30 extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); 31 32 extern void fpu_emulator_init_fpu(void); 33 extern void _init_fpu(void); 34 extern void _save_fp(struct task_struct *); 35 extern void _restore_fp(struct task_struct *); 36 37 #if defined(CONFIG_CPU_SB1) 38 #define __enable_fpu_hazard() \ 39 do { \ 40 asm(".set push \n\t" \ 41 ".set mips64 \n\t" \ 42 ".set noreorder \n\t" \ 43 "ssnop \n\t" \ 44 "bnezl $0, .+4 \n\t" \ 45 "ssnop \n\t" \ 46 ".set pop"); \ 47 } while (0) 48 #else 49 #define __enable_fpu_hazard() \ 50 do { \ 51 asm("nop;nop;nop;nop"); /* max. hazard */ \ 52 } while (0) 53 #endif 54 55 #define __enable_fpu() \ 56 do { \ 57 set_c0_status(ST0_CU1); \ 58 __enable_fpu_hazard(); \ 59 } while (0) 60 61 #define __disable_fpu() \ 62 do { \ 63 clear_c0_status(ST0_CU1); \ 64 /* We don't care about the c0 hazard here */ \ 65 } while (0) 66 67 #define enable_fpu() \ 68 do { \ 69 if (cpu_has_fpu) \ 70 __enable_fpu(); \ 71 } while (0) 72 73 #define disable_fpu() \ 74 do { \ 75 if (cpu_has_fpu) \ 76 __disable_fpu(); \ 77 } while (0) 78 79 80 #define clear_fpu_owner() do { current->flags &= ~PF_USEDFPU; } while(0) 81 is_fpu_owner(void)82static inline int is_fpu_owner(void) 83 { 84 return cpu_has_fpu && ((current->flags & PF_USEDFPU) != 0); 85 } 86 own_fpu(void)87static inline void own_fpu(void) 88 { 89 if (cpu_has_fpu) { 90 __enable_fpu(); 91 KSTK_STATUS(current) |= ST0_CU1; 92 current->flags |= PF_USEDFPU; 93 } 94 } 95 lose_fpu(void)96static inline void lose_fpu(void) 97 { 98 if (cpu_has_fpu) { 99 KSTK_STATUS(current) &= ~ST0_CU1; 100 current->flags &= ~PF_USEDFPU; 101 __disable_fpu(); 102 } 103 } 104 init_fpu(void)105static inline void init_fpu(void) 106 { 107 if (cpu_has_fpu) { 108 _init_fpu(); 109 } else { 110 fpu_emulator_init_fpu(); 111 } 112 } 113 save_fp(struct task_struct * tsk)114static inline void save_fp(struct task_struct *tsk) 115 { 116 if (cpu_has_fpu) 117 _save_fp(tsk); 118 } 119 restore_fp(struct task_struct * tsk)120static inline void restore_fp(struct task_struct *tsk) 121 { 122 if (cpu_has_fpu) 123 _restore_fp(tsk); 124 } 125 get_fpu_regs(struct task_struct * tsk)126static inline unsigned long *get_fpu_regs(struct task_struct *tsk) 127 { 128 if (cpu_has_fpu) { 129 if ((tsk == current) && is_fpu_owner()) 130 _save_fp(current); 131 return (unsigned long *)&tsk->thread.fpu.hard.fp_regs[0]; 132 } else { 133 return (unsigned long *)tsk->thread.fpu.soft.regs; 134 } 135 } 136 137 #endif /* _ASM_FPU_H */ 138