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 *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 *)&tsk->thread.fpu.hard.fp_regs[0]; 129 } else { 130 return (unsigned long *)tsk->thread.fpu.soft.regs; 131 } 132} 133 134#endif /* _ASM_FPU_H */ 135 136