Hi,
ARISTOS wrote:
Brendan wrote:
If the CPU is an 80486 or later, and if an FPU is present, then the FPU is built into the CPU. Otherwise it's 80386 or older CPU. I assume nobody cares about 80286 or older so I won't go into those cases. For an 80386 the FPU can be an 80387 or an 80287, and if you care you can check if the FPU knows the difference between positive infinity and negative infinity (80387 does know the difference, and for 80287 "+infinity == -infinity").
Now you should know if an FPU is present, and if it's built into the CPU or not, and if it's 80287 or 80387 or later.
If there is no FPU, then set the EM flag in CR0 and clear the MP flag in CR0. Otherwise, clear the EM flag in CR0 and set the MP flag in CR0; and if the FPU is built into the CPU then set the NE flag in CR0 so that FPU errors are reported as an exception (and so that FPU errors aren't reported using the IRQ13 via. the PIC, which is slower and can cause problems with race conditions, etc). In practice, it's easier to refuse to boot if the CPU is 80386 (or older) and always use the "native FPU exception" mechanism (and skip the "is it 80387 or 80287" check too).
If the CPU is 80386 (or CPUs without CPUID were we cannot find the CPUs model), how we know if the FPU is built into the CPU or not?
My code initially does:
- If bit 15 of the flags register is hardwired to 1; then it's an 8086
- If it's not an 8086 and bits 12 and 13 of the flags register can't be modified; then the CPU doesn't support the IOPL field and must be 80286 or 80186
Note that these checks can be done safely in pure 16-bit real mode code running on an 8086 (and don't require a 32-bit CPU); and I don't do anything to determine if the CPU is 80186 or 80286 (I only display a "CPU is too old" error message and halt boot).
After you've determined that the CPU is 80386 or later (and therefore does support 32-bit); you can test if the "alignment check" feature exists by testing if bit 18 in EFLAGS can be modified, and test if CPUID is supported by testing if bit 21 of EFLAGS can be modified. If bit 18 can't be modified then the CPU it must be an 80386; if bit 18 can be modified but bit 21 can't be modified, then it must be an 80486. Otherwise, it supports CPUID and must be 80486 or later.
Once you've determined the CPU type you can use that information to help determine the FPU type (as I described years ago).
Please note that this is mostly just historical information. When I first started OS development 80486 was new, so I started doing "minimum requirement is 80486 or later" for my OS, and just kept doing that because it's easy for me (e.g. I can cut & paste old code without thinking about it much). If I were starting OS development today my OS's minimum requirements would be quite different (possibly "OS requires long mode") so that I could avoid spending time learning about things that aren't very important anymore - I'd still have an "is CPU too old" check that doesn't crash on ancient CPUs, but after that I wouldn't have a reason to care about whether FPU exists or not, or what type of FPU it is, or if the native FPU exceptions are supported, or if there's an FDIV bug, or ...
Cheers,
Brendan