FPU: Difference between revisions

49 bytes added ,  29 days ago
m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Bot: Replace deprecated source tag with syntaxhighlight)
Line 21:
 
The common way of testing the presence of an FPU is to have it write it's status somewhere and then check if it actually did.
<sourcesyntaxhighlight lang="asm">
MOV EDX, CR0 ; Start probe, get CR0
AND EDX, (-1) - (CR0_TS + CR0_EM) ; clear TS and EM to force fpu access
Line 32:
 
.testword: DW 0x55AA ; store garbage to be able to detect a change
</syntaxhighlight>
</source>
 
To distinguish a 287 and a 387 FPU, you can try if it can see the difference between +infinity and -infinity.
Line 42:
:If the EM bit is set, all FPU and vector operations will cause a #UD so they can be '''EM'''ulated in software. Should be off to be actually able to use the FPU
'''CR0.ET''' (bit 4)
:This bit is used on the 386 to tell it how to communicate with the coprocessor, which is 0 for an 287, and 1 for a 387 or later. This bit is hardwired to 1 on 486+
'''CR0.NE''' (bit 5)
:When set, enables '''N'''ative '''E'''xception handling which will use the FPU exceptions. When cleared, an exception is sent via the interrupt controller. Should be on for 486+, but not on 386s because they lack that bit.
Line 68:
== FPU state ==
When the FPU is configured, the only thing left to do is to initialize its registers to their proper states. FNINIT will reset the user-visible part of the FPU stack. This will set precision to 64-bit and rounding to nearest, which should be correct for most operations. It will also mask all exceptions from causing an interrupt. You can change the control by issuing an FLDCW. To diagnose broken code, you usually want to enable exceptions for invalid operands and stack overflows (bit 0). Bit 2 allows you to catch divisions by zero as well. Some examples:
<sourcesyntaxhighlight lang="asm">; FLDCW requires a 16-bit memory operand, immediates do not work
FLDCW [value_37F] ; writes 0x37f into the control word: the value written by F(N)INIT
FLDCW [value_37E] ; writes 0x37e, the default with invalid operand exceptions enabled
FLDCW [value_37A] ; writes 0x37a, both division by zero and invalid operands cause exceptions.</sourcesyntaxhighlight>
 
 
Line 91:
== Rent-a-coder ==
These functions can be used with GCC (or TCC) to perform some FPU operations without resorting to dedicated assembly:
<sourcesyntaxhighlight lang="c">void fpu_load_control_word(const uint16_t control)
{
asm volatile("fldcw %0;"::"m"(control));
}</sourcesyntaxhighlight>
 
==See Also==