FPU stub

All about the OSDev Wiki. Discussions about the organization and general structure of articles and how to use the wiki. Request changes here if you don't know how to use the wiki.
Post Reply
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

FPU stub

Post by 01000101 »

I decided to start a page on the x87 FPU. I didn't see any documents on it in the wiki and I think it should at least have a stub (which is what I did, and I will get around to make it a little more robust later). It is an important part of the x86 arch and can provide extremely powerful functionality.

btw, out of curiousity due to the lack of wiki-info, how many of you guys actually implement FPU integers (float, double, long double)?
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Re: FPU stub

Post by piranha »

If I knew more about the FPU, I'd add some (and I'd research it if I had time).

In my opinion, the code you've given is good, but it needs more descriptions (I do know what the instructions mean, but if I was just learning about the FPU for the first time, I'd have some questions):
  • I can see that you're setting a bit in CR4, ok.
    finit must initialize the FPU, alright.
    How did you get that mode? What does it mean? What other modes are there? What does fldcw mean, or whats that instruction do?
The code you gave doesn't compile on my computer. I get "Error: suffix or operands invalid for `movq'".
After changing it to 'mov' it works and executes without dying, but is this ok?

Good start, the wiki needed a page for the FPU.

-JL
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: FPU stub

Post by Combuster »

My kernel has FPU support, including SSE and friends, and with lazy task switching. Basically my approach is to create an FPU image in the task state, drop in the constants needed for SSE to work, then just reload cr0 with the TS bit upon task switch.

Then when the FPU is actually needed, the previous state is stored and the new state loaded.

You are free to post these snippets on the wiki. Probably best if someone doublechecked them in case I misinterpreted something from the manuals - I don't have working 386s and 486s to check if all code paths do what they should.

Code: Select all

DetectCoprocessor:      CPU 386 FPU
                        MOV EDX, CR0                            ; CR0 has a bit on the matter as well
                        AND EDX, CR0_ET                         ; Check Extension Type
                        JZ .nofpu                               ; The processor supports no FPU
                        MOV EDX, CR0                            ; Start probe, get CR0
                        AND EDX, (-1) - (CR0_TS + CR0_EM)       ; clear TS and EM to force fpu access
                        OR EDX, CR0_NE                          ; set NE (workaround no-wait bug)
                        MOV CR0, EDX                            ; store control word
                        FNINIT                                  ; load defaults to FPU
                        FNSTSW [.testword]                      ; store status word. If there's no coprocessor, nothing happens
                        CMP word [.testword], 0                 ; compare the written status
                        JNE .nofpu
.hasfpu:                ; do something when there is an FPU installed

.nofpu:                 ; do something when there isn't an FPU installed
                        RET 
.testword:              DW 0x55AA
Useful for those machines when there's no CPUID to ask, or the coprocessor isn't on-chip

Anyway, if you have a CPU without on-chip FPU, you might want to do paranoia checks on the interrupt handling that it indeed works, otherwise, you should set CR0.NE since that doesn't require your chipset to have that wiring in place.

If you want to enable SSE, you should check the CPUID bits for SSE and Fast save-restore functionality. If your processor can handle that, you can set CR4.OSFXSR and CR4.OSXMMEXCPT.

To switch FPU states you'll have to store the context. Note that this differs when SSE is enabled. FNSAVE/FNRSTOR doesn't store SSE state, FXSAVE/FXRSTOR do but you'll get errors when you try that on a non-sse-enabled machine

Code: Select all

                        ; EDX -> store data
                        ; EAX -> get data

                        CMP dword [sse_enabled], 0
                        JE .fpuonly

                        CPU 686
.fpuandsse:             CLTS
                        FXSAVE [EDX]
                        FXRSTOR [EAX]
                        JMP .done2

.fpuonly:               CLTS
                        FNSAVE [EDX]
                        FRSTOR [EAX]
                        JMP .done2
                        CPU 386
For FPU support, you should write the #NM handler (for handling lazy FPU switches) and #MF handler (for dealing with FPU exceptions)
For SSE, you should write the XF handler as well (for SIMD exceptions).
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: FPU stub

Post by 01000101 »

Thanks for the ideas & code. I'll sift through and hopefully come up with an 'article-like' entry. Also, the reason the 'movq' instruction issued you a warning/error is because I am working in 64-bit mode and was using the 'quad' suffix, using a plain 'mov' instruction will just default to the (largest?) general-purpose register size (which is fine for this). the FLDCW (IIRC) stands for FPU LoaD Control Word and has basic operations such as setting the default precision value.

I'll keep adding on to this wiki article, but I'd really like it if some more FPU-knowledgeable people could contribute as I have a feeling that my contributions will be somewhat limited.
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: FPU stub

Post by 01000101 »

Ok, I added a few explanations and commented the code.
I also threw in a reference page with alot of good info on the FPU.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: FPU stub

Post by AJ »

Combuster wrote:Then when the FPU is actually needed, the previous state is stored and the new state loaded.
I haven't done this yet, but out of interest, how do you know where to store the previous state? Do you simply keep an active pointer to the PCB of the last task that used the FPU?

Cheers,
Adam
Laksen
Member
Member
Posts: 140
Joined: Fri Nov 09, 2007 3:30 am
Location: Aalborg, Denmark

Re: FPU stub

Post by Laksen »

AJ wrote:
Combuster wrote:Then when the FPU is actually needed, the previous state is stored and the new state loaded.
I haven't done this yet, but out of interest, how do you know where to store the previous state? Do you simply keep an active pointer to the PCB of the last task that used the FPU?
That's what the intel documents recommend. You can set the processor up so it only throws a #NM if the TS(Task Switched) bit is set. You can simply clear this bit when you change tasks if you use software multitasking. Then if you get an #NM and the task is another than the last one to invoke a #NM exception then you simply reload the math state from the new task after saving the old tasks mathstate and clear TS before returning from the interrupt

That's what I do and it works fine. You'll have to clear TS as the first operation in the interrupt procedure or else you'll get loads of problems(at least I had, #GPF's, #NM's, etc). Another thing. The 512 byte area where you save the mathstate to must be 16 byte aligned
http://j-software.dk | JPasKernel - My Object Pascal kernel
Post Reply