base/include/asm/rtai_fpu.h

Go to the documentation of this file.
00001 /*
00002  *   This program is free software; you can redistribute it and/or modify
00003  *   it under the terms of the GNU General Public License as published by
00004  *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
00005  *   USA; either version 2 of the License, or (at your option) any later
00006  *   version.
00007  *
00008  *   This program is distributed in the hope that it will be useful,
00009  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *   GNU General Public License for more details.
00012  *
00013  *   You should have received a copy of the GNU General Public License
00014  *   along with this program; if not, write to the Free Software
00015  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016  */
00017 
00018 /* 
00019  * Part of this code acked from Linux i387.h and i387.c:
00020  * Copyright (C) 1994 Linus Torvalds,
00021  * Copyright (C) 2000 Gareth Hughes <gareth@valinux.com>,
00022  * original idea of an RTAI own header file for the FPU stuff:
00023  * Copyright (C) 2000 Pierre Cloutier <pcloutier@PoseidonControls.com>,
00024  * this final rewrite and cleanup:
00025  * Copyright (C) 2005 Paolo Mantegazza <mantegazza@aero.polimi.it>.
00026  */
00027 
00028 #ifndef _RTAI_ASM_I386_FPU_H
00029 #define _RTAI_ASM_I386_FPU_H
00030 
00031 #ifndef __cplusplus
00032 #include <asm/processor.h>
00033 #endif /* !__cplusplus */
00034 
00035 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
00036 typedef union i387_union FPU_ENV;
00037 #define TASK_FPENV(tsk)  (&(tsk)->thread.i387)
00038 #else
00039 typedef union thread_xstate FPU_ENV;
00040 #define TASK_FPENV(tsk)  ((tsk)->thread.xstate)
00041 #endif
00042    
00043 #ifdef CONFIG_RTAI_FPU_SUPPORT
00044 
00045 // RAW FPU MANAGEMENT FOR USAGE FROM WHAT/WHEREVER RTAI DOES IN KERNEL
00046 
00047 #define enable_fpu()  do { \
00048     __asm__ __volatile__ ("clts"); \
00049 } while(0)
00050 
00051 #define save_fpcr_and_enable_fpu(fpcr)  do { \
00052     __asm__ __volatile__ ("movl %%cr0, %0; clts": "=r" (fpcr)); \
00053 } while (0)
00054 
00055 #define restore_fpcr(fpcr)  do { \
00056     if (fpcr & 8) { \
00057         __asm__ __volatile__ ("movl %%cr0, %0": "=r" (fpcr)); \
00058         __asm__ __volatile__ ("movl %0, %%cr0": :"r" (fpcr | 8)); \
00059     } \
00060 } while (0)
00061 
00062 // initialise the hard fpu unit directly
00063 #define init_hard_fpenv() do { \
00064     __asm__ __volatile__ ("clts; fninit"); \
00065     if (cpu_has_xmm) { \
00066         unsigned long __mxcsr = (0xffbfu & 0x1f80u); \
00067         __asm__ __volatile__ ("ldmxcsr %0": : "m" (__mxcsr)); \
00068     } \
00069 } while (0)
00070 
00071 // initialise the given fpenv union, without touching the related hard fpu unit
00072 #define __init_fpenv(fpenv)  do { \
00073     if (cpu_has_fxsr) { \
00074         memset(&(fpenv)->fxsave, 0, sizeof(struct i387_fxsave_struct));\
00075         (fpenv)->fxsave.cwd = 0x37f; \
00076         if (cpu_has_xmm) { \
00077             (fpenv)->fxsave.mxcsr = 0x1f80; \
00078         } \
00079     } else { \
00080         memset(&(fpenv)->fsave, 0, sizeof(struct i387_fsave_struct)); \
00081         (fpenv)->fsave.cwd = 0xffff037fu; \
00082         (fpenv)->fsave.swd = 0xffff0000u; \
00083         (fpenv)->fsave.twd = 0xffffffffu; \
00084         (fpenv)->fsave.fos = 0xffff0000u; \
00085     } \
00086 } while (0)
00087 
00088 #define __save_fpenv(fpenv)  do { \
00089     if (cpu_has_fxsr) { \
00090         __asm__ __volatile__ ("fxsave %0; fnclex": "=m" ((fpenv)->fxsave)); \
00091     } else { \
00092         __asm__ __volatile__ ("fnsave %0; fwait": "=m" ((fpenv)->fsave)); \
00093     } \
00094 } while (0)
00095 
00096 #define __restore_fpenv(fpenv)  do { \
00097     if (cpu_has_fxsr) { \
00098         __asm__ __volatile__ ("fxrstor %0": : "m" ((fpenv)->fxsave)); \
00099     } else { \
00100         __asm__ __volatile__ ("frstor %0": : "m" ((fpenv)->fsave)); \
00101     } \
00102 } while (0)
00103 
00104 // FPU MANAGEMENT DRESSED FOR IN KTHREAD/THREAD/PROCESS FPU USAGE FROM RTAI
00105 
00106 // Macros used for RTAI own kernel space tasks, where it uses the FPU env union
00107 #define init_fpenv(fpenv)  do { __init_fpenv(&(fpenv)); } while (0)
00108 #define save_fpenv(fpenv)  do { __save_fpenv(&(fpenv)); } while (0)
00109 #define restore_fpenv(fpenv)  do { __restore_fpenv(&(fpenv)); } while (0)
00110 
00111 // Macros used for user space, where Linux might use eother a pointer or the FPU env union
00112 #define init_hard_fpu(lnxtsk)  do { \
00113     init_hard_fpenv(); \
00114     set_lnxtsk_uses_fpu(lnxtsk); \
00115     set_lnxtsk_using_fpu(lnxtsk); \
00116 } while (0)
00117 
00118 #define init_fpu(lnxtsk)  do { \
00119     __init_fpenv(TASK_FPENV(lnxtsk)); \
00120     set_lnxtsk_uses_fpu(lnxtsk); \
00121 } while (0)
00122 
00123 #define restore_fpu(lnxtsk)  do { \
00124     enable_fpu(); \
00125     __restore_fpenv(TASK_FPENV(lnxtsk)); \
00126     set_lnxtsk_using_fpu(lnxtsk); \
00127 } while (0)
00128 
00129 #else /* !CONFIG_RTAI_FPU_SUPPORT */
00130 
00131 #define enable_fpu()
00132 #define save_fpcr_and_enable_fpu(fpcr)
00133 #define restore_fpcr(fpcr)
00134 #define init_hard_fpenv()
00135 #define init_fpenv(fpenv)
00136 #define save_fpenv(fpenv)
00137 #define restore_fpenv(fpenv)
00138 #define init_hard_fpu(lnxtsk)
00139 #define init_fpu(lnxtsk)
00140 #define restore_fpu(lnxtsk)
00141 
00142 #endif /* CONFIG_RTAI_FPU_SUPPORT */
00143 
00144 
00145 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00146 
00147 #define set_lnxtsk_uses_fpu(lnxtsk) \
00148     do { (lnxtsk)->used_math = 1; } while(0)
00149 #define clear_lnxtsk_uses_fpu(lnxtsk) \
00150     do { (lnxtsk)->used_math = 0; } while(0)
00151 #define lnxtsk_uses_fpu(lnxtsk)  ((lnxtsk)->used_math)
00152 
00153 #define set_lnxtsk_using_fpu(lnxtsk) \
00154     do { (lnxtsk)->flags |= PF_USEDFPU; } while(0)
00155 
00156 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
00157 
00158 
00159 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
00160 
00161 #define set_lnxtsk_uses_fpu(lnxtsk) \
00162     do { (lnxtsk)->used_math = 1; } while(0)
00163 #define clear_lnxtsk_uses_fpu(lnxtsk) \
00164     do { (lnxtsk)->used_math = 0; } while(0)
00165 #define lnxtsk_uses_fpu(lnxtsk)  ((lnxtsk)->used_math)
00166 
00167 #define set_lnxtsk_using_fpu(lnxtsk) \
00168     do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
00169 //  do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
00170 
00171 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) */
00172 
00173 
00174 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
00175 
00176 #define set_lnxtsk_uses_fpu(lnxtsk) \
00177     do { set_stopped_child_used_math(lnxtsk); } while(0)
00178 #define clear_lnxtsk_uses_fpu(lnxtsk) \
00179     do { clear_stopped_child_used_math(lnxtsk); } while(0)
00180 #define lnxtsk_uses_fpu(lnxtsk)  (tsk_used_math(lnxtsk))
00181 
00182 #define set_lnxtsk_using_fpu(lnxtsk) \
00183     do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
00184 //  do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
00185 
00186 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) */
00187 
00188 
00189 #endif /* !_RTAI_ASM_I386_FPU_H */

Generated on Tue Feb 2 17:46:04 2010 for RTAI API by  doxygen 1.4.7