Main Page | Modules | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

fpu.h

Go to the documentation of this file.
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

Generated on Mon Sep 26 14:20:10 2005 for Fiasco by  doxygen 1.4.2