| CMP Game Media Group Presents: | ||
![]() |
|
|
|
|
||
|
Processor Detection and a Pentium III Update
Since writing my last column, I received a great deal of e-mail about invalid instruction exceptions while debugging DirectX code on Pentium III machines. It appears that DirectX under Windows 98 leaves SIMD exceptions enabled and because the operating system does not support SIMD exceptions these show up as invalid instruction exceptions. To fix the problem you need a new version of the vmcpd.vxd system file, at the moment this file is only on the DirectX 7 beta CD and it is only available for Windows 98. Installing the new system file solves the problem. Also, I was sent email by Sean Skelton of Ubi Soft showing a small change to make the dot product code from last month slightly faster. Sean’s code is listed below. // Load the vectors movaps xmm0, lv //
xmm0 = [-, lz, ly, lx] // Do the math mulps xmm0, xmm1
// xmm0 = [-, lz*nz, ly*ny, lx*nx] And now onto this month's problem of detecting the processor(s) within the machine. There are many reasons why you might need to detect the make and model of a user's processor. For example, your game might use instructions which are only present on a certain make and model of processor, or you may have to load a completely different EXE or DLL for a certain family of processor. In either case, you need to be able to detect the make, model and most importantly, the features of a processor. In this article I hope to describe some of the more tricky elements, and along the way I'll develop a C++ class that does the grunt work for you and provides a set of easy to use member functions providing information ranging from the manufacturer to clock speed. A DLL would be the ideal place for such code but I’ll leave that as an exercise for you. How do I reliably detect the processor within a machine and its feature set? Detecting the model of processor and FPU (if present) contained within a machine prior to the release of the Intel 486 was tricky, and the code relied on detecting architecture-specific behavior and there was no such thing as clones so it was perfectly valid to assume any given processor was made by Intel. Detecting the processor within Windows is a little easier – the processor must be at least a 386, because protected mode is required for Win32 and therefore the detection code can be all 32 bit. The 386 is the minimum processor the remainder of this article will be concerned with. For those of you that want to detect the 8086/8088, bits 12-15 of the FLAGS register (remember 16-bit registers?) are always set and on the 286 in real mode these bits are always clear. To differentiate the 386 from the 486, you have to try to set the alignment bit (bit 18) in EFLAGS. This bit was added to the 486 and cannot be set on the 386. If it is determined that the processor is a 486, don’t forget to restore the EFLAGS register to its original state. This is shown in the code below: pushfd The 486 was the first processor to have a signature containing model and stepping information, from which code could determine the feature set. The only problem was that the signature was placed in the EDX register after a reset, but it was lost if the BIOS did not take a copy of it. Some BIOSes had calls to return the signature or they placed it at a specific address in the BIOS data segment, but knowing this does not help from within a Windows application. The data contained within the signature register is shown below: Signature layout in EDX register Stepping: Bits 0 – 3 Revision of the family and model Model: Bits 4 - 7 Model within the family, such as Pentium III Family: Bits 8 - 11 Architecture Family, all Pentium II and III processors are family 6 Type: Bits 12 - 13 Type of the processor such as OEM or overdrive etc. NOTE: The type field is not used by the code within this article due to the Pentium Overdrive (Type 01) for Pentium processors identifying themselves as OEM processors (Type 00), these processors will be reported as standard Pentium processors. The Pentium Overdrive for 486 processors does not have this problem and will be reported correctly. The 486 Pentium Overdrive processor is identified through its unique stepping. The very late model 486s solved the signature problem by implementing a new instruction called CPUID, which among other information returns the processor signature and enables identification of the processor at any time. To determine if a processor implements the CPUID instruction, try to toggle the state of the ID bit in EFLAGS (bit 21). If the bit can be changed, CPUID is present. It is very important that you first determine that the processor is at least 486 before toggling the ID bit, because this bit can be changed on a 386, which does not implement the CPUID instruction, and trying to executing it will generate an invalid instruction exception. I’ll talk more about CPUID later, but without it and without the initial signature from reset, we can only detect the processor as a 386 or 486 and we cannot determine the make, model or definite feature set. Detecting the presence of a floating-point unit (FPU) seems pretty much irrelevant these days, but you still should check and fail gracefully if an FPU is not present. I bet most modern applications don’t do this, and generally assuming the presence of an FPU is unlikely to cause any problems (but this was not always the case). The 486 was the first model to have a built-in FPU, but it was only in the DX models. The SX did not have an internal floating-point unit, but you can add a 80487 floating point co-processor. So that even if a 486 is detected, you still cannot assume an FPU is present. The first processor on which it was safe to assume the presence of an FPU was the Pentium. |
|
Copyright
© 2000 CMP Media Inc. All rights reserved.
Privacy Policy |