FPU

From OSDev.wiki
Revision as of 23:58, 28 March 2009 by osdev>01000101
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.

ex:

uint16_t FPU_CW;

void set_fpu_control_word(const uint16_t cw)
{
    if(cpuid_features.FPU) // checks for the FPU flag
    {
        // FSTCW = Store FPU Control Word 
        // FLDCW = Load FPU Control Word
        asm volatile("fldcw (%0);    "    // sets the FPU control word to "cw"
                     "fstcw (%1);    "    // store the FPU control word into FPU_CW
                     ::"r"(cw), "r"(&FPU_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(0xB7F);
    }
}

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 0x33f, 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