00001 // AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- 00002 00003 #ifndef fpu_h 00004 #define fpu_h 00005 00006 #include "initcalls.h" 00007 00008 // 00009 // INTERFACE definition follows 00010 // 00011 00012 00013 class slab_cache_anon; 00014 class Context; 00015 class Fpu_state; 00016 /* 00017 * Fiasco 00018 * Floating point unit code 00019 */ 00020 00021 00022 00023 class Fpu 00024 { 00025 public: 00026 00027 static Context *owner(); 00028 static void set_owner(Context *owner); 00029 static bool is_owner(Context *owner); 00030 00031 // all the following methods are arch dependent 00032 static void init() FIASCO_INIT; 00033 static unsigned const state_size(); 00034 static unsigned const state_align(); 00035 static void init_state( Fpu_state *); 00036 static void restore_state( Fpu_state * ); 00037 static void save_state( Fpu_state * ); 00038 static void disable(); 00039 static void enable(); 00040 00041 private: 00042 00043 static Context *_owner; 00044 private: 00045 00046 private: 00047 struct fpu_regs // saved FPU registers 00048 { 00049 long cwd; 00050 long swd; 00051 long twd; 00052 long fip; 00053 long fcs; 00054 long foo; 00055 long fos; 00056 long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ 00057 }; 00058 00059 struct sse_regs 00060 { 00061 unsigned short cwd; 00062 unsigned short swd; 00063 unsigned short twd; 00064 unsigned short fop; 00065 long fip; 00066 long fcs; 00067 long foo; 00068 long fos; 00069 long mxcsr; 00070 long reserved; 00071 long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ 00072 long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ 00073 long padding[56]; 00074 }; 00075 }; 00076 00077 // 00078 // IMPLEMENTATION includes follow (for use by inline functions) 00079 // 00080 00081 00082 #include <cstring> 00083 #include "fpu_state.h" 00084 00085 #include <cassert> 00086 #include "cpu.h" 00087 #include "regdefs.h" 00088 00089 // 00090 // IMPLEMENTATION of inline functions (and needed classes) 00091 // 00092 00093 00094 00095 00096 inline Context * Fpu::owner() 00097 { 00098 return _owner; 00099 } 00100 00101 00102 00103 inline void Fpu::set_owner(Context *owner) 00104 { 00105 _owner = owner; 00106 } 00107 00108 00109 00110 inline bool Fpu::is_owner(Context *owner) 00111 { 00112 return _owner == owner; 00113 } 00114 00115 00116 /* 00117 * Initialize FPU or SSE state 00118 * We don't use finit, because it is slow. Initializing the context in 00119 * memory and fetching it via restore_state is supposedly faster 00120 */ 00121 00122 inline void 00123 Fpu::init_state(Fpu_state *s) 00124 { 00125 if ((Cpu::features() & FEAT_FXSR)) { 00126 00127 sse_regs *sse = reinterpret_cast<sse_regs *>(s->state_buffer()); 00128 00129 memset (sse, 0, sizeof (*sse)); 00130 sse->cwd = 0x37f; 00131 00132 if ((Cpu::features() & FEAT_SSE)) 00133 sse->mxcsr = 0x1f80; 00134 00135 } else { 00136 00137 fpu_regs *fpu = reinterpret_cast<fpu_regs *>(s->state_buffer()); 00138 00139 memset (fpu, 0, sizeof (*fpu)); 00140 fpu->cwd = 0xffff037f; 00141 fpu->swd = 0xffff0000; 00142 fpu->twd = 0xffffffff; 00143 fpu->fos = 0xffff0000; 00144 } 00145 } 00146 00147 00153 inline unsigned const 00154 Fpu::state_size() 00155 { 00156 return (Cpu::features() & FEAT_FXSR) ? sizeof (sse_regs) : 00157 sizeof (fpu_regs); 00158 } 00159 00160 00166 inline unsigned const 00167 Fpu::state_align() 00168 { 00169 return (Cpu::features() & FEAT_FXSR) ? 16 : 4; 00170 } 00171 00172 00173 /* 00174 * Save FPU or SSE state 00175 */ 00176 00177 inline void 00178 Fpu::save_state(Fpu_state *s) 00179 { 00180 assert (s->state_buffer()); 00181 00182 // Both fxsave and fnsave are non-waiting instructions and thus 00183 // cannot cause exception #16 for pending FPU exceptions. 00184 00185 if ((Cpu::features() & FEAT_FXSR)) 00186 asm volatile ("fxsave (%0)" : : "r" (s->state_buffer()) : "memory"); 00187 else 00188 asm volatile ("fnsave (%0)" : : "r" (s->state_buffer()) : "memory"); 00189 } 00190 00191 00192 /* 00193 * Restore a saved FPU or SSE state 00194 */ 00195 00196 inline void 00197 Fpu::restore_state(Fpu_state *s) 00198 { 00199 assert (s->state_buffer()); 00200 00201 // Only fxrstor is a non-waiting instruction and thus 00202 // cannot cause exception #16 for pending FPU exceptions. 00203 00204 if ((Cpu::features() & FEAT_FXSR)) 00205 asm volatile ("fxrstor (%0)" : : "r" (s->state_buffer())); 00206 00207 else { 00208 00209 // frstor is a waiting instruction and we must make sure no 00210 // FPU exceptions are pending here. We distinguish two cases: 00211 // 1) If we had a previous FPU owner, we called save_state before and 00212 // invoked fnsave which re-initialized the FPU and cleared exceptions 00213 // 2) Otherwise we call fnclex instead to clear exceptions. 00214 00215 if (!Fpu::owner()) 00216 asm volatile ("fnclex"); 00217 00218 asm volatile ("frstor (%0)" : : "r" (s->state_buffer())); 00219 } 00220 } 00221 00222 00223 /* 00224 * Mark the FPU busy. The next attempt to use it will yield a trap. 00225 */ 00226 00227 inline void 00228 Fpu::disable() 00229 { 00230 Cpu::set_cr0 (Cpu::get_cr0() | CR0_TS); 00231 } 00232 00233 00234 /* 00235 * Mark the FPU no longer busy. Subsequent FPU access won't trap. 00236 */ 00237 00238 inline void 00239 Fpu::enable() 00240 { 00241 asm volatile ("clts"); 00242 } 00243 00244 #endif // fpu_h