FPU

From OSDev.wiki
Jump to navigation Jump to search
This page is a stub.
You can help the wiki by accurately adding more contents to it.

x87 Floating-Point Unit

Programming

Initialize the FPU

In order to utilize the FPU from within the 32-bit protected mode environment, one must first initialize it before use. If used before being setup properly would result in an exception. The following code shows how to init the FPU so that datatypes such as float, double, and long double can be used without generating an exception.

Example:

 
 void set_fpu_control_word(const uint16_t cw)
 {
     if(cpuid_features.FPU) // checks for the FPU flag
     {
         // FLDCW = Load FPU Control Word
         asm volatile("fldcw %0;    "    // sets the FPU control word to "cw"
                      ::"m"(cw)); 
     }
 }
 
 void setup_x87_fpu()
 {
    size_t cr4; // backup of CR4
    
    if(cpuid_features.FPU) // checks for the FPU flag
    {
        // place CR4 into our variable
        __asm__ __volatile__("mov %%cr4, %0;" : "=r" (cr4));
    
        // set the OSFXSR bit
        cr4 |= 0x200;
    
        // reload CR4 and INIT the FPU (FINIT)
        __asm__ __volatile__("mov %0, %%cr4; finit;" : : "r"(cr4));
    
        // set the FPU Control Word
        set_fpu_control_word(0x37F);
     }
 }

Setting the 9th bit (OSFXSR) in the CR4 tells the CPU that we intend on using the FXSAVE, FXRSTOR, and SSEx instructions. If this bit is not set, a #UD exception will be generated on use of the FPU or any SSE instructions.

The 'mode' variable is set to 0x37f, but what exactly does this mean when loading the FPU control word? Bits 0-5 of the control word are various interrupt masks, when set they mask the interrupt from reaching the CPU and (most likely) causing a fault if proper handling doesn't exist. Bit 7 is the IEM, which stands for the Interrupt Enable Mask, and should only be set if there are interrupts that will be UNMASKED. Bits 8-11 are for two things, the PC (Precision Control) and RC (Rounding Control). In our case, we have the PC fully set (default) which corresponds to 64-bit precision. The RC is set to the default of 0 and will round to the nearest and to the even-most value if split.

References

http://www.website.masmforum.com/tutorials/fptute/fpuchap1.htm