Previous: Intel_CPU Package Specification, Up: A Complete Example
Intel_CPU
Package Bodypackage body Intel_CPU is --------------------------- -- Detect FPU presence -- --------------------------- -- There is a FPU present if we can set values to the FPU Status -- and Control Words. function Has_FPU return Boolean is Register : Unsigned_16; -- processor register to store a word begin -- check if we can change the status word Asm ( -- the assembler code "finit" & LF & HT & -- reset status word "movw $0x5A5A, %%ax" & LF & HT & -- set value status word "fnstsw %0" & LF & HT & -- save status word "movw %%ax, %0", -- store status word -- output stored in Register -- register must be a memory location Outputs => Unsigned_16'Asm_output ("=m", Register), -- tell compiler that we used eax Clobber => "eax"); -- if the status word is zero, there is no FPU if Register = 0 then return False; -- no status word end if; -- check status word value -- check if we can get the control word Asm ( -- the assembler code "fnstcw %0", -- save the control word -- output into Register -- register must be a memory location Outputs => Unsigned_16'Asm_output ("=m", Register)); -- check the relevant bits if (Register and 16#103F#) /= 16#003F# then return False; -- no control word end if; -- check control word value -- FPU found return True; end Has_FPU; -------------------------------- -- Detect CPUID instruction -- -------------------------------- -- The processor supports the CPUID instruction if it is possible -- to change the value of ID flag bit in the EFLAGS register. function Has_CPUID return Boolean is Original_Flags, Modified_Flags : Processor_Register; -- EFLAG contents before and after changing the ID flag begin -- try flipping the ID flag in the EFLAGS register Asm ( -- the assembler code "pushfl" & LF & HT & -- push EFLAGS on stack "pop %%eax" & LF & HT & -- pop EFLAGS into eax "movl %%eax, %0" & LF & HT & -- save EFLAGS content "xor $0x200000, %%eax" & LF & HT & -- flip ID flag "push %%eax" & LF & HT & -- push EFLAGS on stack "popfl" & LF & HT & -- load EFLAGS register "pushfl" & LF & HT & -- push EFLAGS on stack "pop %1", -- save EFLAGS content -- output values, may be anything -- Original_Flags is %0 -- Modified_Flags is %1 Outputs => (Processor_Register'Asm_output ("=g", Original_Flags), Processor_Register'Asm_output ("=g", Modified_Flags)), -- tell compiler eax is destroyed Clobber => "eax"); -- check if CPUID is supported if Original_Flags(ID_Flag) /= Modified_Flags(ID_Flag) then return True; -- ID flag was modified else return False; -- ID flag unchanged end if; -- check for CPUID end Has_CPUID; ------------------------------- -- Get CPUID support level -- ------------------------------- function CPUID_Level return Natural is Level : Unsigned_32; -- returned support level begin -- execute CPUID, storing the results in the Level register Asm ( -- the assembler code "cpuid", -- execute CPUID -- zero is stored in eax -- returning the support level in eax Inputs => Unsigned_32'Asm_input ("a", 0), -- eax is stored in Level Outputs => Unsigned_32'Asm_output ("=a", Level), -- tell compiler ebx, ecx and edx registers are destroyed Clobber => "ebx, ecx, edx"); -- return the support level return Natural (Level); end CPUID_Level; -------------------------------- -- Get CPU Vendor ID String -- -------------------------------- -- The vendor ID string is returned in the ebx, ecx and edx register -- after executing the CPUID instruction with eax set to zero. -- In case of a true Intel processor the string returned is -- "GenuineIntel" function Vendor_ID return String is Ebx, Ecx, Edx : Unsigned_Register; -- registers containing the vendor ID string Vendor_ID : String (1 .. 12); -- the vendor ID string begin -- execute CPUID, storing the results in the processor registers Asm ( -- the assembler code "cpuid", -- execute CPUID -- zero stored in eax -- vendor ID string returned in ebx, ecx and edx Inputs => Unsigned_32'Asm_input ("a", 0), -- ebx is stored in Ebx -- ecx is stored in Ecx -- edx is stored in Edx Outputs => (Unsigned_Register'Asm_output ("=b", Ebx), Unsigned_Register'Asm_output ("=c", Ecx), Unsigned_Register'Asm_output ("=d", Edx))); -- now build the vendor ID string Vendor_ID( 1) := Character'Val (Ebx.L1); Vendor_ID( 2) := Character'Val (Ebx.H1); Vendor_ID( 3) := Character'Val (Ebx.L2); Vendor_ID( 4) := Character'Val (Ebx.H2); Vendor_ID( 5) := Character'Val (Edx.L1); Vendor_ID( 6) := Character'Val (Edx.H1); Vendor_ID( 7) := Character'Val (Edx.L2); Vendor_ID( 8) := Character'Val (Edx.H2); Vendor_ID( 9) := Character'Val (Ecx.L1); Vendor_ID(10) := Character'Val (Ecx.H1); Vendor_ID(11) := Character'Val (Ecx.L2); Vendor_ID(12) := Character'Val (Ecx.H2); -- return string return Vendor_ID; end Vendor_ID; ------------------------------- -- Get processor signature -- ------------------------------- function Signature return Processor_Signature is Result : Processor_Signature; -- processor signature returned begin -- execute CPUID, storing the results in the Result variable Asm ( -- the assembler code "cpuid", -- execute CPUID -- one is stored in eax -- processor signature returned in eax Inputs => Unsigned_32'Asm_input ("a", 1), -- eax is stored in Result Outputs => Processor_Signature'Asm_output ("=a", Result), -- tell compiler that ebx, ecx and edx are also destroyed Clobber => "ebx, ecx, edx"); -- return processor signature return Result; end Signature; ------------------------------ -- Get processor features -- ------------------------------ function Features return Processor_Features is Result : Processor_Features; -- processor features returned begin -- execute CPUID, storing the results in the Result variable Asm ( -- the assembler code "cpuid", -- execute CPUID -- one stored in eax -- processor features returned in edx Inputs => Unsigned_32'Asm_input ("a", 1), -- edx is stored in Result Outputs => Processor_Features'Asm_output ("=d", Result), -- tell compiler that ebx and ecx are also destroyed Clobber => "ebx, ecx"); -- return processor signature return Result; end Features; end Intel_CPU;