00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef _RTAI_ASM_X8664_FPU_H
00031 #define _RTAI_ASM_X8664_FPU_H
00032
00033 #ifndef __cplusplus
00034 #include <asm/processor.h>
00035 #endif
00036
00037 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
00038 typedef union i387_union FPU_ENV;
00039 #define TASK_FPENV(tsk) (&(tsk)->thread.i387.fxsave)
00040 #else
00041 typedef union thread_xstate FPU_ENV;
00042 #define TASK_FPENV(tsk) (&(tsk)->thread.xstate->fxsave)
00043 #endif
00044
00045 #ifdef CONFIG_RTAI_FPU_SUPPORT
00046
00047
00048
00049 #define enable_fpu() do { \
00050 __asm__ __volatile__ ("clts"); \
00051 } while(0)
00052
00053 #define save_fpcr_and_enable_fpu(fpcr) do { \
00054 fpcr = read_cr0(); \
00055 enable_fpu(); \
00056 } while (0)
00057
00058 #define restore_fpcr(fpcr) do { \
00059 if (fpcr & 8) { \
00060 unsigned long flags; \
00061 rtai_hw_save_flags_and_cli(flags); \
00062 fpcr = read_cr0(); \
00063 write_cr0(8 | fpcr); \
00064 rtai_hw_restore_flags(flags); \
00065 } \
00066 } while (0)
00067
00068
00069 #define init_hard_fpenv() do { \
00070 unsigned long __mxcsr; \
00071 __asm__ __volatile__ ("clts; fninit"); \
00072 __mxcsr = 0xffbfUL & 0x1f80UL; \
00073 __asm__ __volatile__ ("ldmxcsr %0": : "m" (__mxcsr)); \
00074 } while (0)
00075
00076
00077 #define __init_fpenv(fpenv) do { \
00078 memset(fpenv, 0, sizeof(struct i387_fxsave_struct)); \
00079 (fpenv)->cwd = 0x37f; \
00080 (fpenv)->mxcsr = 0x1f80; \
00081 } while (0)
00082
00083
00084
00085 static inline int __save_fpenv(struct i387_fxsave_struct __user *fx)
00086 {
00087 int err;
00088
00089 asm volatile("1: rex64/fxsave (%[fx])\n\t"
00090 "2:\n"
00091 ".section .fixup,\"ax\"\n"
00092 "3: movl $-1,%[err]\n"
00093 " jmp 2b\n"
00094 ".previous\n"
00095 ".section __ex_table,\"a\"\n"
00096 " .align 8\n"
00097 " .quad 1b,3b\n"
00098 ".previous"
00099 : [err] "=r" (err), "=m" (*fx)
00100 : [fx] "cdaSDb" (fx), "0" (0));
00101
00102 return err;
00103 }
00104
00105 static inline int __restore_fpenv(struct i387_fxsave_struct *fx)
00106 {
00107 int err;
00108
00109 asm volatile("1: rex64/fxrstor (%[fx])\n\t"
00110 "2:\n"
00111 ".section .fixup,\"ax\"\n"
00112 "3: movl $-1,%[err]\n"
00113 " jmp 2b\n"
00114 ".previous\n"
00115 ".section __ex_table,\"a\"\n"
00116 " .align 8\n"
00117 " .quad 1b,3b\n"
00118 ".previous"
00119 : [err] "=r" (err)
00120 : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
00121
00122 return err;
00123 }
00124
00125 #define init_fpenv(fpenv) do { __init_fpenv(&(fpenv).fxsave); } while (0)
00126 #define save_fpenv(fpenv) do { __save_fpenv(&(fpenv).fxsave); } while (0)
00127 #define restore_fpenv(fpenv) do { __restore_fpenv(&(fpenv).fxsave); } while (0)
00128
00129
00130
00131 #define init_hard_fpu(lnxtsk) do { \
00132 init_hard_fpenv(); \
00133 set_lnxtsk_uses_fpu(lnxtsk); \
00134 set_lnxtsk_using_fpu(lnxtsk); \
00135 } while (0)
00136
00137 #define init_fpu(lnxtsk) do { \
00138 __init_fpenv(TASK_FPENV(lnxtsk)); \
00139 set_lnxtsk_uses_fpu(lnxtsk); \
00140 } while (0)
00141
00142 #define restore_fpu(lnxtsk) do { \
00143 enable_fpu(); \
00144 __restore_fpenv(TASK_FPENV(lnxtsk)); \
00145 set_lnxtsk_using_fpu(lnxtsk); \
00146 } while (0)
00147
00148 #else
00149
00150 #define enable_fpu()
00151 #define save_fpcr_and_enable_fpu(fpcr)
00152 #define restore_fpcr(fpcr)
00153 #define init_hard_fpenv()
00154 #define init_fpenv(fpenv)
00155 #define save_fpenv(fpenv)
00156 #define restore_fpenv(fpenv)
00157 #define init_hard_fpu(lnxtsk)
00158 #define init_fpu(lnxtsk)
00159 #define restore_fpu(lnxtsk)
00160
00161 #endif
00162
00163 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
00164
00165 #define set_lnxtsk_uses_fpu(lnxtsk) \
00166 do { (lnxtsk)->used_math = 1; } while(0)
00167 #define clear_lnxtsk_uses_fpu(lnxtsk) \
00168 do { (lnxtsk)->used_math = 0; } while(0)
00169 #define lnxtsk_uses_fpu(lnxtsk) ((lnxtsk)->used_math)
00170
00171 #define set_lnxtsk_using_fpu(lnxtsk) \
00172 do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
00173
00174
00175 #endif
00176
00177
00178 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
00179
00180 #define set_lnxtsk_uses_fpu(lnxtsk) \
00181 do { set_stopped_child_used_math(lnxtsk); } while(0)
00182 #define clear_lnxtsk_uses_fpu(lnxtsk) \
00183 do { clear_stopped_child_used_math(lnxtsk); } while(0)
00184 #define lnxtsk_uses_fpu(lnxtsk) (tsk_used_math(lnxtsk))
00185
00186 #define set_lnxtsk_using_fpu(lnxtsk) \
00187 do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
00188
00189
00190 #endif
00191
00192 #endif