AMD64.CPUID.Mod 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  1. MODULE CPUID; (** AUTHOR "staubesv"; PURPOSE "Intel/AMD CPUID Information"; *)
  2. (**
  3. * The purpose of this module is to dump processor information provided by the CPUID instruction in a human readable format.
  4. * It is not part (and not intended to be part) of the kernel.
  5. *
  6. * Usage:
  7. *
  8. * CPUID.Show ~ displays the processor name and the most relevant features
  9. * CPUID.ShowDetailed ~ displays all information provided by CPUID
  10. *
  11. * System.Free CPUID ~
  12. *
  13. * Notes:
  14. * - The CPUID instruction is supported by CPUs >= 80486
  15. *
  16. * References:
  17. *
  18. * [1] Intel Processor Identification and the CPUID Instruction, Application Note 485, December 2007
  19. * [2] AMD CPUID Specification, Revision 2.18, January 2006
  20. *)
  21. IMPORT
  22. SYSTEM, Streams, Commands, Options;
  23. CONST
  24. (** CpuInformation.type encoding *)
  25. Intel* = 0;
  26. Amd* = 1;
  27. Other* = 2;
  28. (* CpuInformation.features encoding *)
  29. PBE* = 31; (** INTEL: Pending Break Enable *)
  30. IA64* = 30; (** INTEL: IA64 Capabilities *)
  31. TM* = 29; (** INTEL: Thermal Monitor supported *)
  32. HTT* = 28; (** Hyper-Threading Technology *)
  33. SS* = 27; (** INTEL: Self-Snoop *)
  34. SSE2* = 26; (** SSE2 extensions *)
  35. SSE* = 25; (** SSE extensions *)
  36. FXSR* = 24; (** FXSAVE and FXRSTOR instructions *)
  37. MMX* = 23; (** MMX instructions *)
  38. ACPI* = 22; (** INTEL: Thermal Monitor and Software Controlled Clock Facilities supported *)
  39. DS* = 21; (** INTEL: Debug Store *)
  40. CLFLUSH* = 19; (** CLFLUSH instruction *)
  41. PSN* = 18; (** INTEL: Processor serial number is present and enabled *)
  42. PSE36* = 17; (** Page-size extension *)
  43. PAT* = 16; (** Page attribute table *)
  44. CMOV* = 15; (** CMOV & FCMOV conditional move instructions *)
  45. MCA* = 14; (** Machine check architecture *)
  46. PGE* = 13; (** Page global extension *)
  47. MTRR* = 12; (** Memory-type range registers *)
  48. SysEnterSysExit* = 11; (** SYSENTER & SYSEXIT instructions *)
  49. APIC* = 9; (** APIC exists and is enabled *)
  50. CMPXCH8B* = 8; (** CMPXCHGB8 instruction *)
  51. MCE* = 7; (** Machine check exception *)
  52. PAE* = 6; (** Physical-address extendions (support for physical addresss > 32b) *)
  53. MSR* = 5; (** Model-specific registers with RDMSR & WRMSR instructions *)
  54. TSC* = 4; (** Time stamp counter with RDTSC and RDTSCP instruction support *)
  55. PSE* = 3; (** Page-size extensions (4MB pages) *)
  56. DE* = 2; (** Debugging extensions, I/O breakpoints *)
  57. VME* = 1; (** Virtual-mode enhancements *)
  58. FPU* = 0; (** Floating point unit on chip *)
  59. (** CpuIformation.features2 encoding *)
  60. SSE4_2* = 20; (** INTEL: Streaming SIMD Extensions 4.2*)
  61. SSE4_1* = 19; (** INTEL: Streaming SIMD Extensions 4.1*)
  62. DCA* = 18; (** INTEL: Direct Access Cache *)
  63. PDCM* =15; (** INTEL: Performance Capabilities MSR*)
  64. XTPR* = 14; (** INTEL: Send Task Priority Messages *)
  65. CMPXCHG16B* = 13; (** CMPXCHG16B instruction *)
  66. CID* = 10; (** INTEL: Context ID *)
  67. SSSE3* = 9; (** INTEL: Supplemental Streaming SIMD Extensions 3 *)
  68. TM2* = 8; (** INTEL: Thermal Monitor 2 *)
  69. EST* = 7; (** INTEL: Enhanced Intel SpeedStep Technology *)
  70. SMX* = 6; (** INTEL: Safer Mode Extensions *)
  71. VMX* = 5; (** INTEL: Virtual Machine Extensions *)
  72. DS_CPL* = 4; (** INTEL: CPL Qualified Debug Store *)
  73. MONITOR* = 3; (** INTEL: Monitor/MWAIT *)
  74. DTES64* = 2; (** INTEL: 64-Bit Debug Store *)
  75. SSE3* = 0; (** SSE3 extensions *)
  76. (** CpuInformation.extFeatures encoding (AMD) *)
  77. Amd3DNow* = 31; (** AMD: 3DNow! instructions *)
  78. Amd3DNowExt* = 32; (** AMD: AMD extensions to 3DNow! *)
  79. LM* = 29; (** Long Mode supported (64bit support), IA-32e*)
  80. RDTSCP* = 27; (** AMD: RDTSCP instruction *)
  81. FFXSR* = 25; (** AMD: FXSAVE & FXRSTOR instruction optimizations *)
  82. MmxExt* = 22; (** AMD: AMD extensions to MMX instructins *)
  83. NX* = 20; (** No-execute page protection *)
  84. SysCallSysRet* = 11; (** SYSCALL & SYSRET instructions *)
  85. (** Bits 24..23, 17..12, 9..0 contain the same information as cpuInfo.features *)
  86. (** CpuInformation.extFeatures2 encoding (AMD) *)
  87. AltMovCr8* = 4; (** AMD: LOCK MOV CR0 means MOV CR8 *)
  88. SVM* = 2; (** AMD: Secure virtual machine feature *)
  89. CmpLegacy* = 1; (** AMD: Core multi-processing legacy mode *)
  90. LahfSahf* = 0; (** LAHF & SAHF instruction support in 64-bit mode *)
  91. (** CpuInformation.powerManagement encoding (AMD) *)
  92. AMD7_TscInvariant* = 8; (** TSC rate is ensured to be invariant across all P-States, C-States and stop-grant transitions *)
  93. AMD7_STC* = 5; (** Software Thermal Control is supported *)
  94. AMD7_TM* = 4; (** Hardware Thermal Control is supported *)
  95. AMD7_TTP* = 3; (** THERMTRIP is supported *)
  96. AMD7_VID* = 2; (** Voltage ID control is supported *)
  97. AMD7_FID* = 1; (** Frequency ID control is supported *)
  98. AMD7_TS* = 0; (** Temperature sensor *)
  99. TYPE
  100. CpuInformation* = RECORD
  101. cputype- : LONGINT; (* Intel, Amd or Other *)
  102. (** Standard Function 0: Processor Vendor and Largest Standard Function *)
  103. largestStandardFunction- : LONGINT;
  104. vendor- : ARRAY 13 OF CHAR;
  105. (** Standard Function 1: Family, Model, Stepping Identifiers *)
  106. family-, model-, stepping- : LONGINT;
  107. type- : LONGINT; (* INTEL *)
  108. features-, features2- : SET;
  109. localApicId-, logicalProcessorCount- : LONGINT;
  110. clflushSize- : LONGINT; (* specifies the size of a cache line flushed by the CLFLUSH instruction [in bytes] *)
  111. brandId- : LONGINT;
  112. (** Extended Function 0: Largest Extended Function *)
  113. largestExtendedFunction- : LONGINT;
  114. (** Extended Function 1: Features *)
  115. extFeatures-, extFeatures2- : SET;
  116. (** Extended Function 2-4: Processor name *)
  117. processorName- : ARRAY 48 OF CHAR;
  118. (** AMD-Specific *)
  119. (** Level 1 Cache and TLB *)
  120. (** L1 2M/4M pages TLB associativity & size *)
  121. l1DataTlbAssociativity2M4M- : LONGINT;
  122. l1DataTlbSize2M4M- : LONGINT;
  123. l1InstrTlbAssociativity2M4M- : LONGINT;
  124. l1InstrTlbSize2M4M- : LONGINT;
  125. (** L1 4K pages TLB associativity & size *)
  126. l1DataTlbAssociativity4K- : LONGINT;
  127. l1DataTlbSize4K- : LONGINT;
  128. l1InstrTlbAssociativity4K- : LONGINT;
  129. l1InstrTlbSize4K- : LONGINT;
  130. (** L1 data cache characteristics *)
  131. l1DcSize- : LONGINT; (* KB *)
  132. l1DcAssociativity- : LONGINT;
  133. l1DcLinesPerTag- : LONGINT; (* AMD *)
  134. l1DcLineSize- : LONGINT;
  135. (** L1 instruction cache characteristics *)
  136. l1IcSize- : LONGINT; (* KB *)
  137. l1IcAssociativity- : LONGINT;
  138. l1IcLinesPerTag- : LONGINT; (* AMD *)
  139. l1IcLineSize- : LONGINT;
  140. (** Level 2 Cache and TLB *)
  141. unifiedTlb- : BOOLEAN; (* if TRUE, one TLB for all 4K/2M/4M pages *)
  142. (** L2 2M/4M pages TLB associativity & size *)
  143. l2DataTlbAssociativity2M4M- : LONGINT;
  144. l2DataTlbSize2M4M- : LONGINT;
  145. l2InstrTlbAssociativity2M4M- : LONGINT;
  146. l2InstrTlbSize2M4M- : LONGINT;
  147. (** L2 4K pages TLB associativity & size *)
  148. l2DataTlbAssociativity4K- : LONGINT;
  149. l2DataTlbSize4K- : LONGINT;
  150. l2InstrTlbAssociativity4K- : LONGINT;
  151. l2InstrTlbSize4K- : LONGINT;
  152. l2CacheSize- : LONGINT; (* KB *)
  153. l2Associativity- : LONGINT; (* encoded *)
  154. l2LinesPerTag- : LONGINT; (* AMD *)
  155. l2LineSize- : LONGINT;
  156. (** Extended function 7: Advanced Power Management Information *)
  157. powerManagement- : SET; (* AMD *)
  158. (** Extended function 8: Long Mode Address Size Identifiers *)
  159. linAddrSize- : LONGINT; (* maximum linear byte address size in bits *)
  160. physAddrSize- : LONGINT; (* maximum physical byte address size in bits *)
  161. apicIdCoreIdSize- : LONGINT; (* AMD *)
  162. numberOfCores- : LONGINT; (* AMD *)
  163. (** Extended function A: SVM Revision and Feature Identification *)
  164. svmRev- : LONGINT; (* AMD *)
  165. nasid- : LONGINT; (** AMD: Number of address space identifiers *)
  166. END;
  167. (** CPU identification *)
  168. PROCEDURE CPUID(function : LONGINT; VAR peax, pebx, pecx, pedx : SET);
  169. CODE {SYSTEM.AMD64, SYSTEM.Pentium}
  170. MOV EAX, [RBP + function] ; CPUID function parameter
  171. MOV RSI, [RBP + pecx] ; required for INTEL standard function4.
  172. MOV ECX, [RSI]
  173. CPUID ; execute CPUID
  174. MOV RSI, [RBP + peax] ; copy EAX into eax
  175. MOV [RSI], EAX
  176. MOV RSI, [RBP + pebx] ; copy EBX into ebx
  177. MOV [RSI], EBX
  178. MOV RSI, [RBP + pecx] ; copy ECX into ecx
  179. MOV [RSI], ECX
  180. MOV RSI, [RBP + pedx] ; copy EDX into edx
  181. MOV [RSI], EDX
  182. END CPUID;
  183. (* If the CPUID instruction is supported, the ID flag (bit 21) of the EFLAGS register is r/w *)
  184. PROCEDURE CpuIdSupported() : BOOLEAN;
  185. CODE {SYSTEM.AMD64}
  186. PUSHFQ ; save RFLAGS
  187. POP RAX ; store RFLAGS in RAX
  188. MOV RBX, RAX ; save RBX for later testing
  189. XOR RAX, 00200000H ; toggle bit 21
  190. PUSH RAX ; push to stack
  191. POPFQ ; save changed RAX to RFLAGS
  192. PUSHFQ ; push RFLAGS to TOS
  193. POP RAX ; store RFLAGS in RAX
  194. CMP RAX, RBX ; see if bit 21 has changed
  195. SETNE AL; ; return TRUE if bit 21 has changed, FALSE otherwise
  196. END CpuIdSupported;
  197. (* Standard Function 0: Processor Vendor and Largest Standard Function Number *)
  198. PROCEDURE StandardFunction0(VAR cpuInfo: CpuInformation);
  199. VAR eax, ebx, ecx, edx : SET;
  200. BEGIN
  201. CPUID(0H, eax, ebx, ecx, edx);
  202. cpuInfo.largestStandardFunction := SYSTEM.VAL(LONGINT, eax);
  203. GetString(cpuInfo.vendor, 0, ebx);
  204. GetString(cpuInfo.vendor, 4, edx);
  205. GetString(cpuInfo.vendor, 8, ecx);
  206. cpuInfo.vendor[12] := 0X;
  207. IF cpuInfo.vendor = "GenuineIntel" THEN cpuInfo.cputype := Intel;
  208. ELSIF cpuInfo.vendor = "AuthenticAMD" THEN cpuInfo.cputype := Amd;
  209. ELSE cpuInfo.cputype := Other;
  210. END;
  211. END StandardFunction0;
  212. (* Standard Function 1: Family, Model, Stepping Identifiers *)
  213. PROCEDURE StandardFunction1(VAR cpuInfo : CpuInformation);
  214. CONST
  215. ExtendedFamily = {20..27}; ExtendedModel = {16..19};
  216. BaseFamily = {8..11}; BaseModel = {4..7}; BaseStepping = {0..3};
  217. LocalApicId = {24..31}; LogicalProcessorCount = {16..23}; CLFlush = {8..15}; BrandId = {0..7};
  218. VAR
  219. eax, ebx, ecx, edx : SET;
  220. BEGIN
  221. CPUID(1H, eax, ebx, ecx, edx);
  222. (* EAX *)
  223. cpuInfo.stepping := SYSTEM.VAL(LONGINT, eax * BaseStepping);
  224. cpuInfo.model := SYSTEM.VAL(LONGINT, LSH(eax * BaseModel, -4));
  225. cpuInfo.family := SYSTEM.VAL(LONGINT, LSH(eax * BaseFamily, -8));
  226. IF cpuInfo.family < 0FH THEN
  227. cpuInfo.family := cpuInfo.family + SYSTEM.VAL(LONGINT, LSH(eax * ExtendedFamily, -20));
  228. cpuInfo.model := cpuInfo.model + SYSTEM.VAL(LONGINT, LSH(eax * ExtendedModel, -12));
  229. END;
  230. (* EBX *)
  231. cpuInfo.localApicId := SYSTEM.VAL(LONGINT, LSH(ebx * LocalApicId, -24));
  232. cpuInfo.logicalProcessorCount := SYSTEM.VAL(LONGINT, LSH(ebx * LogicalProcessorCount, - 16));
  233. cpuInfo.clflushSize := SYSTEM.VAL(LONGINT, LSH(ebx * CLFlush, -8)) * 8;
  234. cpuInfo.brandId := SYSTEM.VAL(LONGINT, ebx * BrandId);
  235. (* ECX *)
  236. cpuInfo.features2 := ecx;
  237. (* EDX *)
  238. cpuInfo.features := edx;
  239. IF cpuInfo.cputype = Intel THEN
  240. cpuInfo.type := SYSTEM.VAL(LONGINT, LSH(edx * {12..13}, -12));
  241. END;
  242. END StandardFunction1;
  243. (** INTEL: Standard Function 4: deterministic cache parameters
  244. Cache Type: eax*{0..4}
  245. 0 = Null, no more caches
  246. 1 = Data Cache
  247. 2 = Instruction Cache
  248. 3 = Unified Cache
  249. 4-31 = Reserved
  250. *)
  251. PROCEDURE IntelStandardFunction4(wr: Streams.Writer );
  252. VAR
  253. eax, ebx, ecx, edx : SET;
  254. cores, threads, cachelevel, cachetype: LONGINT;
  255. selfinit, fullassoc, waysofassoc, physlinepart, syscoherline, numofsets, prefetchstride: LONGINT;
  256. cachesize: LONGINT;
  257. k: LONGINT;
  258. BEGIN
  259. k := 0;
  260. LOOP (* iterate over ecx = 0,1,2,3.. until eax*{0..4}=0 *)
  261. ecx := SYSTEM.VAL(SET,k) ;
  262. CPUID(4H, eax, ebx,ecx, edx);
  263. cachetype := SYSTEM.VAL(LONGINT, eax *{0..4});
  264. IF cachetype=0 THEN EXIT; END;
  265. wr.String("CacheType: "); wr.Int(cachetype,0);
  266. IF cachetype=1 THEN wr.String(" [Data Cache]");
  267. ELSIF cachetype=2 THEN wr.String(" [Instruction Cache]");
  268. ELSIF cachetype=3 THEN wr.String(" [Unified Cache]");
  269. ELSIF cachetype=4 THEN wr.String(" [Reserved]");
  270. END;
  271. wr.Ln;
  272. cachelevel := SYSTEM.VAL(LONGINT, LSH(eax *{5..7} , -5));
  273. wr.String("Cache Level: "); wr.Int(cachelevel,0); wr.Ln;
  274. cores := SYSTEM.VAL(LONGINT, LSH(eax *{26..31}, -26)) + 1;
  275. threads := SYSTEM.VAL(LONGINT, LSH(eax *{14..25} , -14)) +1;
  276. fullassoc := SYSTEM.VAL(LONGINT, LSH(eax *{9},-9));
  277. selfinit := SYSTEM.VAL(LONGINT, LSH(eax *{8},-8));
  278. waysofassoc := SYSTEM.VAL(LONGINT, LSH(ebx *{22..31},-22)) +1;
  279. physlinepart := SYSTEM.VAL(LONGINT, LSH(ebx *{12..21},-12)) +1;
  280. syscoherline := SYSTEM.VAL(LONGINT, ebx *{0..11}) +1 ;
  281. numofsets := SYSTEM.VAL(LONGINT, ecx ) +1;
  282. prefetchstride := SYSTEM.VAL(LONGINT, edx*{0..9} );
  283. wr.String("Maximum number of processor cores per package: "); wr.Int(cores,0); wr.Ln;
  284. wr.String("Maximum number of threads sharing this cache: "); wr.Int(threads,0); wr.Ln;
  285. wr.String("Full Associative cache: "); wr.Int(fullassoc,0); wr.Ln;
  286. wr.String("Self initializing cache: "); wr.Int(selfinit,0); wr.Ln;
  287. wr.String("Ways of associativity: "); wr.Int(waysofassoc,0); wr.Ln;
  288. wr.String("Physical line partitions: "); wr.Int(physlinepart,0); wr.Ln;
  289. wr.String("System coherency line: "); wr.Int(syscoherline,0); wr.Ln;
  290. wr.String("Number of sets: "); wr.Int(numofsets,0); wr.Ln;
  291. wr.String("Prefetch stride: "); wr.Int(prefetchstride,0); wr.Ln;
  292. cachesize:= waysofassoc * physlinepart * syscoherline * numofsets;
  293. wr.String("This Cache Size (Bytes) : "); wr.Int(cachesize,0); wr.Ln;
  294. wr.String("****************************"); wr.Ln;
  295. wr.Update;
  296. INC(k);
  297. END;
  298. END IntelStandardFunction4;
  299. (** INTEL: MONITOR/ MWAIT Parameters *)
  300. PROCEDURE IntelStandardFunction5(w: Streams.Writer);
  301. VAR
  302. eax, ebx, ecx, edx : SET;
  303. smallestMon, largestMon : LONGINT;
  304. supporttreatingInterrup, supportMonMwait: BOOLEAN;
  305. numofC0, numofC1, numofC2, numofC3, numofC4: LONGINT;
  306. BEGIN
  307. CPUID(5H, eax, ebx,ecx, edx);
  308. smallestMon := SYSTEM.VAL(LONGINT, eax*{0..15});
  309. largestMon := SYSTEM.VAL(LONGINT, ebx*{0..15} );
  310. supporttreatingInterrup := SYSTEM.VAL(BOOLEAN,LSH(ecx*{1},-1));
  311. supportMonMwait := SYSTEM.VAL(BOOLEAN,ecx*{0});
  312. numofC4 := SYSTEM.VAL(LONGINT,LSH(edx*{16..19},-16));
  313. numofC3 := SYSTEM.VAL(LONGINT,LSH(edx*{12..15},-12));
  314. numofC2 := SYSTEM.VAL(LONGINT,LSH(edx*{8..11},-8));
  315. numofC1 := SYSTEM.VAL(LONGINT,LSH(edx*{4..7},-4));
  316. numofC0 := SYSTEM.VAL(LONGINT, edx*{0..3});
  317. w.String("Smallest Monitor size (bytes) = "); w.Int(smallestMon, 0 ); w.Ln;
  318. w.String("Largest Monitor size (bytes) = "); w.Int(largestMon, 0 ); w.Ln;
  319. w.String("Support treating Interrupt as break-events for MOITOR/MWAIT : ");
  320. IF supporttreatingInterrup THEN w.String("TRUE") ELSE w.String("FALSE") END;
  321. w.Ln;
  322. w.String(" MOITOR/MWAIT extensions supported : ");
  323. IF supportMonMwait THEN w.String("TRUE") ELSE w.String("FALSE") END;
  324. w.Ln;
  325. w.String(" Number of C4 sub states supported : "); w.Int(numofC4, 0); w.Ln;
  326. w.String(" Number of C3 sub states supported : "); w.Int(numofC3, 0); w.Ln;
  327. w.String(" Number of C2 sub states supported : "); w.Int(numofC2, 0); w.Ln;
  328. w.String(" Number of C1 sub states supported : "); w.Int(numofC1, 0); w.Ln;
  329. w.String(" Number of C0 sub states supported : "); w.Int(numofC0, 0); w.Ln;
  330. w.Update;
  331. END IntelStandardFunction5;
  332. (** INTEL: Digital Termal Sensor and Power Management Parameters *)
  333. PROCEDURE IntelStandardFunction6(w: Streams.Writer);
  334. VAR
  335. eax, ebx, ecx, edx : SET;
  336. digitalTermalSensorCapabilitiy: LONGINT;
  337. numberofInterruptThreshold: LONGINT;
  338. hardwareCoordFeedbackCap: LONGINT;
  339. BEGIN
  340. CPUID(6H, eax, ebx,ecx, edx);
  341. digitalTermalSensorCapabilitiy := SYSTEM.VAL(LONGINT, eax*{0});
  342. numberofInterruptThreshold := SYSTEM.VAL(LONGINT, ebx*{0..3} );
  343. hardwareCoordFeedbackCap := SYSTEM.VAL(LONGINT, ecx*{0});
  344. w.String("Digital termal Sensor Capabilitiy = "); w.Int(digitalTermalSensorCapabilitiy,0 ); w.Ln;
  345. w.String("Number of Interrupt Thresholds = "); w.Int(numberofInterruptThreshold,0 ); w.Ln;
  346. w.String("Hardware Coordination Feedback Capablity = "); w.Int(hardwareCoordFeedbackCap,0 ); w.Ln;
  347. w.Update;
  348. END IntelStandardFunction6;
  349. (** INTEL: Direct Cache Access (DCA) Parameters *)
  350. PROCEDURE IntelStandardFunction9(w: Streams.Writer);
  351. VAR
  352. eax, ebx, ecx, edx : SET;
  353. BEGIN
  354. CPUID(9H, eax, ebx,ecx, edx);
  355. w.String("Value of PLATFORM_DCA_CAP MSR Bits : "); w.Set(eax); w.Ln;
  356. (* w.String("ebx: RESERVED: "); w.Set(ebx); w.Ln;
  357. w.String("ecx: RESERVED: "); w.Set(ecx); w.Ln;
  358. w.String("edx: RESERVED: "); w.Set(edx); w.Ln;
  359. *)
  360. w.Update;
  361. END IntelStandardFunction9;
  362. (** INTEL: Architectural Performance Monitor Features *)
  363. PROCEDURE IntelStandardFunction0A(w: Streams.Writer);
  364. VAR
  365. eax, ebx, ecx, edx : SET;
  366. lenEBX: LONGINT;
  367. bitwidthCounter: LONGINT;
  368. numberofCountCore: LONGINT;
  369. verID: LONGINT;
  370. brachMispredict: LONGINT;
  371. branchInstruct: LONGINT;
  372. cacheMisses: LONGINT;
  373. cacheReference: LONGINT;
  374. referenceCycle: LONGINT;
  375. instructionRetired: LONGINT;
  376. CoreCycle: LONGINT;
  377. bitwidthFunction: LONGINT;
  378. numberofFunction: LONGINT;
  379. BEGIN
  380. CPUID(0AH, eax, ebx,ecx, edx);
  381. lenEBX := SYSTEM.VAL(LONGINT, LSH(eax * {24..31}, -24));
  382. bitwidthCounter:=SYSTEM.VAL(LONGINT, LSH(eax * {16..23}, -16));
  383. numberofCountCore:=SYSTEM.VAL(LONGINT, LSH(eax * {8..15}, -8));
  384. verID := SYSTEM.VAL(LONGINT,eax*{0..7});
  385. brachMispredict:=SYSTEM.VAL(LONGINT,LSH(ebx*{6},-6) );
  386. branchInstruct:=SYSTEM.VAL(LONGINT,LSH(ebx*{5},-5) );
  387. cacheMisses:=SYSTEM.VAL(LONGINT,LSH(ebx*{4},-4) );
  388. cacheReference := SYSTEM.VAL(LONGINT,LSH(ebx*{3},-3) );
  389. referenceCycle := SYSTEM.VAL(LONGINT,LSH(ebx*{2},-2) );
  390. instructionRetired := SYSTEM.VAL(LONGINT,LSH(ebx*{1},-1) );
  391. CoreCycle := SYSTEM.VAL(LONGINT,ebx*{0} );
  392. bitwidthFunction := SYSTEM.VAL(LONGINT,LSH(ecx*{5..12},-5) );
  393. numberofFunction :=SYSTEM.VAL(LONGINT,ecx*{0..4} );
  394. w.String("Length of EBX bit vector = "); w.Int(lenEBX ,0 ); w.Ln;
  395. w.String("Bit width of counter = "); w.Int(bitwidthCounter,0 ); w.Ln;
  396. w.String("Number of counter per logical processor = "); w.Int(numberofCountCore,0 );w.Ln;
  397. w.String("Version ID = "); w.Int(verID ,0 );w.Ln;
  398. w.String("Branch mispredict retired event = "); w.Int(brachMispredict,0 );w.Ln;
  399. w.String("Branch Instruction retired event = "); w.Int(branchInstruct,0 );w.Ln;
  400. w.String("Last-level cache misses event = "); w.Int(cacheMisses,0 );w.Ln;
  401. w.String("Last-level cache reference event = "); w.Int(cacheReference ,0 );w.Ln;
  402. w.String("Reference cycles event = "); w.Int(referenceCycle ,0 );w.Ln;
  403. w.String("Instruction retired event = "); w.Int(instructionRetired ,0 );w.Ln;
  404. w.String("Core cycle event = "); w.Int(CoreCycle ,0 );w.Ln;
  405. w.String("Bit width of fixed-function performance counters = "); w.Int(bitwidthFunction ,0 );w.Ln;
  406. w.String("Number of fixed-function performance counters ="); w.Int(numberofFunction ,0 );w.Ln;
  407. w.Update;
  408. END IntelStandardFunction0A;
  409. PROCEDURE ExtendedFunction0(VAR cpuInfo : CpuInformation);
  410. VAR eax, ebx, ecx, edx : SET;
  411. BEGIN
  412. eax := {};
  413. CPUID(LONGINT(80000000H), eax, ebx, ecx, edx);
  414. (* The largest extended function as value from offset 8000000H. Since we don't have unsigned integers, ignore the MSB *)
  415. cpuInfo.largestExtendedFunction := SYSTEM.VAL(LONGINT, eax - {31});
  416. (* ebx, ecx & edx contain the same information as in standard function 0 *)
  417. END ExtendedFunction0;
  418. PROCEDURE ExtendedFunction1(VAR cpuInfo : CpuInformation);
  419. VAR eax, ebx, ecx, edx : SET;
  420. BEGIN
  421. CPUID(LONGINT(80000001H), eax, ebx, ecx, edx);
  422. (* eax contains the same information as in standard function 1 *)
  423. (* ebx: brandid, ignore so far*)
  424. cpuInfo.extFeatures2 := ecx;
  425. cpuInfo.extFeatures := edx;
  426. END ExtendedFunction1;
  427. PROCEDURE ExtendedFunction2to4(VAR cpuInfo : CpuInformation);
  428. VAR eax, ebx, ecx, edx : SET;
  429. BEGIN
  430. CPUID(LONGINT(80000002H), eax, ebx, ecx, edx);
  431. GetString(cpuInfo.processorName, 0, eax);
  432. GetString(cpuInfo.processorName, 4, ebx);
  433. GetString(cpuInfo.processorName, 8, ecx);
  434. GetString(cpuInfo.processorName, 12, edx);
  435. IF cpuInfo.largestExtendedFunction < 3 THEN RETURN END;
  436. CPUID(LONGINT(80000003H), eax, ebx, ecx, edx);
  437. GetString(cpuInfo.processorName, 16, eax);
  438. GetString(cpuInfo.processorName, 20, ebx);
  439. GetString(cpuInfo.processorName, 24, ecx);
  440. GetString(cpuInfo.processorName, 28, edx);
  441. IF cpuInfo.largestExtendedFunction < 4 THEN RETURN END;
  442. CPUID(LONGINT(80000004H), eax, ebx, ecx, edx);
  443. GetString(cpuInfo.processorName, 32, eax);
  444. GetString(cpuInfo.processorName, 36, ebx);
  445. GetString(cpuInfo.processorName, 40, ecx);
  446. GetString(cpuInfo.processorName, 44, edx);
  447. END ExtendedFunction2to4;
  448. PROCEDURE AmdExtendedFunction5(VAR cpuInfo : CpuInformation);
  449. VAR eax, ebx, ecx, edx : SET;
  450. BEGIN
  451. CPUID(LONGINT(80000005H), eax, ebx, ecx, edx);
  452. (* EAX *)
  453. cpuInfo.l1DataTlbAssociativity2M4M := SYSTEM.VAL(LONGINT, LSH(eax * {24..31}, -24));
  454. cpuInfo.l1DataTlbSize2M4M := SYSTEM.VAL(LONGINT, LSH(eax * {16..23}, -16));
  455. cpuInfo. l1InstrTlbAssociativity2M4M := SYSTEM.VAL(LONGINT, LSH(eax * {8..15}, -8));
  456. cpuInfo. l1InstrTlbSize2M4M := SYSTEM.VAL(LONGINT, eax * {0..7});
  457. (* EBX *)
  458. cpuInfo.l1DataTlbAssociativity4K := SYSTEM.VAL(LONGINT, LSH(ebx * {24..31}, -24));
  459. cpuInfo.l1DataTlbSize4K := SYSTEM.VAL(LONGINT, LSH(ebx * {16..23}, -16));
  460. cpuInfo.l1InstrTlbAssociativity4K := SYSTEM.VAL(LONGINT, LSH(ebx * {8..15}, -8));
  461. cpuInfo.l1InstrTlbSize4K := SYSTEM.VAL(LONGINT, ebx * {0..7});
  462. (* ECX *)
  463. cpuInfo.l1DcSize := SYSTEM.VAL(LONGINT, LSH(ecx * {24..31}, -24));
  464. cpuInfo.l1DcAssociativity := SYSTEM.VAL(LONGINT, LSH(ecx * {16..23}, -16));
  465. cpuInfo.l1DcLinesPerTag := SYSTEM.VAL(LONGINT, LSH(ecx * {8..15}, -8));
  466. cpuInfo.l1DcLineSize := SYSTEM.VAL(LONGINT, ecx * {0..7});
  467. (* EDX *)
  468. cpuInfo.l1IcSize := SYSTEM.VAL(LONGINT, LSH(edx * {24..31}, -24));
  469. cpuInfo.l1IcAssociativity := SYSTEM.VAL(LONGINT, LSH(edx * {16..23}, -16));
  470. cpuInfo.l1IcLinesPerTag := SYSTEM.VAL(LONGINT, LSH(edx * {8..15}, -8));
  471. cpuInfo.l1IcLineSize := SYSTEM.VAL(LONGINT, edx * {0..7});
  472. END AmdExtendedFunction5;
  473. (** AMD: L2 Cache and TLB Identifiers *)
  474. PROCEDURE AmdExtendedFunction6(VAR cpuInfo : CpuInformation);
  475. VAR eax, ebx, ecx, edx : SET;
  476. BEGIN
  477. CPUID(LONGINT(80000006H), eax, ebx, ecx, edx);
  478. cpuInfo.unifiedTlb := (eax * {16..31} = {}) & (ebx * {16..31} = {});
  479. IF ~cpuInfo.unifiedTlb THEN
  480. cpuInfo.l2DataTlbAssociativity2M4M := SYSTEM.VAL(LONGINT, LSH(eax * {28..31}, -28));
  481. cpuInfo.l2DataTlbSize2M4M := SYSTEM.VAL(LONGINT, LSH(eax * {16..27}, -16));
  482. cpuInfo.l2InstrTlbAssociativity2M4M := SYSTEM.VAL(LONGINT, LSH(eax * {12..15}, -12));
  483. cpuInfo.l2InstrTlbSize2M4M := SYSTEM.VAL(LONGINT, eax * {0..11});
  484. END;
  485. cpuInfo.l2DataTlbAssociativity4K := SYSTEM.VAL(LONGINT, LSH(ebx * {28..31}, -28));
  486. cpuInfo.l2DataTlbSize4K := SYSTEM.VAL(LONGINT, LSH(ebx * {16..27}, -16));
  487. cpuInfo.l2InstrTlbAssociativity4K := SYSTEM.VAL(LONGINT, LSH(ebx * {12..15}, -12));
  488. cpuInfo.l2InstrTlbSize4K := SYSTEM.VAL(LONGINT, ebx * {0..11});
  489. cpuInfo.l2CacheSize := SYSTEM.VAL(LONGINT, LSH(ecx * {16..31}, -16));
  490. cpuInfo.l2Associativity := SYSTEM.VAL(LONGINT, LSH(ecx * {12..15}, -12));
  491. cpuInfo.l2LinesPerTag := SYSTEM.VAL(LONGINT, LSH(ecx * {8..11}, -8));
  492. cpuInfo.l2LineSize := SYSTEM.VAL(LONGINT, ecx * {0..7});
  493. END AmdExtendedFunction6;
  494. (* INTEL: Extended L2 Cache Features *)
  495. PROCEDURE IntelExtendedFunction6(VAR cpuInfo : CpuInformation);
  496. VAR eax, ebx, ecx, edx : SET;
  497. BEGIN
  498. CPUID(LONGINT(80000006H), eax, ebx, ecx, edx);
  499. cpuInfo.l2CacheSize := SYSTEM.VAL(LONGINT, LSH(ecx * {16..31}, -16));
  500. cpuInfo.l2Associativity := SYSTEM.VAL(LONGINT, LSH(ecx * {12..15}, -12));
  501. cpuInfo.l2LineSize := SYSTEM.VAL(LONGINT, ecx * {0..7});
  502. END IntelExtendedFunction6;
  503. (* AMD: Advanced Power Management Information *)
  504. PROCEDURE AmdExtendedFunction7(VAR cpuInfo : CpuInformation);
  505. VAR eax, ebx, ecx, edx : SET;
  506. BEGIN
  507. CPUID(LONGINT(80000007H), eax, ebx, ecx, edx);
  508. cpuInfo.powerManagement := edx;
  509. END AmdExtendedFunction7;
  510. (* Long Mode Address Size Identifiers *)
  511. PROCEDURE ExtendedFunction8(VAR cpuInfo : CpuInformation);
  512. VAR eax, ebx, ecx, edx : SET;
  513. BEGIN
  514. CPUID(LONGINT(80000008H), eax, ebx, ecx, edx);
  515. cpuInfo.linAddrSize := SYSTEM.VAL(LONGINT, LSH(eax * {8..15}, -8));
  516. cpuInfo.physAddrSize := SYSTEM.VAL(LONGINT, eax * {0..7});
  517. IF cpuInfo.cputype = Amd THEN
  518. cpuInfo.apicIdCoreIdSize := SYSTEM.VAL(LONGINT, LSH(ecx * {12..15}, -12));
  519. cpuInfo.numberOfCores := SYSTEM.VAL(LONGINT, ecx * {0..7}) + 1;
  520. END;
  521. END ExtendedFunction8;
  522. (* AMD: SVM Revision and Feature Identification *)
  523. PROCEDURE AmdExtendedFunctionA(VAR cpuInfo : CpuInformation);
  524. VAR eax, ebx, ecx, edx : SET;
  525. BEGIN
  526. CPUID(LONGINT(8000000AH), eax, ebx, ecx, edx);
  527. cpuInfo.svmRev := SYSTEM.VAL(LONGINT, eax * {0..7});
  528. cpuInfo.nasid := SYSTEM.VAL(LONGINT, ebx);
  529. END AmdExtendedFunctionA;
  530. PROCEDURE GetString(VAR string : ARRAY OF CHAR; offset : LONGINT; register : SET);
  531. BEGIN
  532. string[offset] :=CHR(SYSTEM.VAL(LONGINT, register * {0..7}));
  533. string[offset+1] := CHR(SYSTEM.VAL(LONGINT, LSH(register * {8..15}, -8)));
  534. string[offset+2] := CHR(SYSTEM.VAL(LONGINT, LSH(register * {16..23}, -16)));
  535. string[offset+3] := CHR(SYSTEM.VAL(LONGINT, LSH(register * {24..31}, -24)));
  536. END GetString;
  537. PROCEDURE GetCpuInformation(VAR cpuInfo : CpuInformation);
  538. BEGIN
  539. StandardFunction0(cpuInfo);
  540. IF cpuInfo.largestStandardFunction >= 1 THEN StandardFunction1(cpuInfo); END;
  541. ExtendedFunction0(cpuInfo);
  542. IF cpuInfo.largestExtendedFunction >= 1 THEN
  543. ExtendedFunction1(cpuInfo);
  544. IF cpuInfo.largestExtendedFunction >= 2 THEN
  545. ExtendedFunction2to4(cpuInfo);
  546. IF cpuInfo.largestExtendedFunction >= 5 THEN
  547. IF cpuInfo.cputype = Amd THEN AmdExtendedFunction5(cpuInfo); END;
  548. IF cpuInfo.largestExtendedFunction >= 6 THEN
  549. IF cpuInfo.cputype = Amd THEN
  550. AmdExtendedFunction6(cpuInfo);
  551. ELSE
  552. IntelExtendedFunction6(cpuInfo);
  553. END;
  554. IF cpuInfo.largestExtendedFunction >= 7 THEN
  555. IF cpuInfo.cputype = Amd THEN AmdExtendedFunction7(cpuInfo); END;
  556. IF cpuInfo.largestExtendedFunction >= 8 THEN
  557. ExtendedFunction8(cpuInfo);
  558. IF cpuInfo.largestExtendedFunction >= 0AH THEN
  559. IF cpuInfo.cputype = Amd THEN AmdExtendedFunctionA(cpuInfo); END;
  560. END;
  561. END;
  562. END;
  563. END;
  564. END;
  565. END;
  566. END;
  567. END GetCpuInformation;
  568. PROCEDURE ShowExtFeatures2Amd(w : Streams.Writer; register : SET);
  569. BEGIN
  570. IF AltMovCr8 IN register THEN w.String("[AltMovCR8]"); END;
  571. IF SVM IN register THEN w.String("[SVM]"); END;
  572. IF CmpLegacy IN register THEN w.String("[CMP legacy]"); END;
  573. IF LahfSahf IN register THEN w.String("[LahfSahf]"); END;
  574. END ShowExtFeatures2Amd;
  575. PROCEDURE ShowExtFeaturesAmd(w : Streams.Writer; register : SET);
  576. BEGIN
  577. IF Amd3DNow IN register THEN w.String("[3DNow!]"); END;
  578. IF Amd3DNowExt IN register THEN w.String("[3DNow!Ext]"); END;
  579. IF LM IN register THEN w.String("[LongMode]"); END;
  580. IF RDTSCP IN register THEN w.String("[RDTSCP]"); END;
  581. IF FFXSR IN register THEN w.String("[FFXSR]"); END;
  582. IF MmxExt IN register THEN w.String("[MMXExt]"); END;
  583. IF NX IN register THEN w.String("[NX]"); END;
  584. IF SysCallSysRet IN register THEN w.String("[SysCallSysRet]"); END;
  585. END ShowExtFeaturesAmd;
  586. PROCEDURE ShowPowerManagementAmd(w : Streams.Writer; register : SET);
  587. BEGIN
  588. IF AMD7_TscInvariant IN register THEN w.String("[TSCInvariant]"); END;
  589. IF AMD7_STC IN register THEN w.String("[STC]"); END;
  590. IF AMD7_TM IN register THEN w.String("[TM]"); END;
  591. IF AMD7_TTP IN register THEN w.String("[TTP]"); END;
  592. IF AMD7_VID IN register THEN w.String("[VID]"); END;
  593. IF AMD7_FID IN register THEN w.String("[FID]"); END;
  594. IF AMD7_TS IN register THEN w.String("[TS]"); END;
  595. END ShowPowerManagementAmd;
  596. PROCEDURE ShowLongModeAS(w : Streams.Writer; cpuInfo : CpuInformation);
  597. BEGIN
  598. w.String(" Maximum linear byte address size: "); w.Int(cpuInfo.linAddrSize, 0); w.String(" bits"); w.Ln;
  599. w.String(" Maximum physical byte address size: "); w.Int(cpuInfo.physAddrSize, 0); w.String(" bits"); w.Ln;
  600. IF cpuInfo.cputype = Amd THEN
  601. w.String(" APIC ID Core ID Size: "); w.Int(cpuInfo.apicIdCoreIdSize, 0); w.String(" bits"); w.Ln;
  602. w.String(" Number of CPU cores: "); w.Int(cpuInfo.numberOfCores, 0);
  603. END;
  604. END ShowLongModeAS;
  605. PROCEDURE ShowFeatures2(w : Streams.Writer; register : SET);
  606. BEGIN
  607. IF DCA IN register THEN w.String("[DCA]"); END; (* INTEL *)
  608. IF XTPR IN register THEN w.String("[xTPR]"); END; (* INTEL *)
  609. IF CMPXCHG16B IN register THEN w.String("[CMPXCHG16B]"); END;
  610. IF CID IN register THEN w.String("[CID]"); END; (* INTEL *)
  611. IF SSSE3 IN register THEN w.String("[SSSE3]"); END; (* INTEL *)
  612. IF TM2 IN register THEN w.String("[TM2]"); END; (* INTEL *)
  613. IF EST IN register THEN w.String("[EST]"); END; (* INTEL *)
  614. IF VMX IN register THEN w.String("[VMX]"); END; (* INTEL *)
  615. IF DS_CPL IN register THEN w.String("[DS_CPL]"); END; (* INTEL *)
  616. IF MONITOR IN register THEN w.String("[MONITOR]"); END; (* INTEL *)
  617. IF SSE3 IN register THEN w.String("[SSE3]"); END;
  618. IF DTES64 IN register THEN w.String("[DTES64]"); END; (* INTEL *)
  619. IF SSE4_2 IN register THEN w.String("[SSE4_2]"); END; (* INTEL *)
  620. IF SSE4_1 IN register THEN w.String("[SSE4_1]"); END; (* INTEL *)
  621. IF PDCM IN register THEN w.String("[PDCM]"); END; (* INTEL *)
  622. IF SMX IN register THEN w.String("[SMX]"); END; (* INTEL *)
  623. END ShowFeatures2;
  624. PROCEDURE ShowFeatures(w : Streams.Writer; register : SET);
  625. BEGIN
  626. IF PBE IN register THEN w.String("[PBE]"); END; (* INTEL *)
  627. IF IA64 IN register THEN w.String("[IA64]"); END; (* INTEL *)
  628. IF TM IN register THEN w.String("[TM]"); END; (* INTEL *)
  629. IF HTT IN register THEN w.String("[HTT]"); END;
  630. IF SS IN register THEN w.String("[SelfSnoop]"); END; (* INTEL *)
  631. IF SSE2 IN register THEN w.String("[SSE2]"); END;
  632. IF SSE IN register THEN w.String("[SSE]"); END;
  633. IF FXSR IN register THEN w.String("[FXSR]"); END;
  634. IF MMX IN register THEN w.String("[MMX]"); END;
  635. IF ACPI IN register THEN w.String("[ACPI]"); END; (* INTEL *)
  636. IF DS IN register THEN w.String("[DebugStore]"); END; (* INTEL *)
  637. IF CLFLUSH IN register THEN w.String("[CLFLUSH]"); END;
  638. IF PSN IN register THEN w.String("[ProcessorSerialNumber]"); END; (* INTEL *)
  639. IF PSE36 IN register THEN w.String("[PSE36]"); END;
  640. IF PAT IN register THEN w.String("[PAT]"); END;
  641. IF CMOV IN register THEN w.String("[CMOV]"); END;
  642. IF MCA IN register THEN w.String("[MCA]"); END;
  643. IF PGE IN register THEN w.String("[PGE]"); END;
  644. IF MTRR IN register THEN w.String("[MTRR]"); END;
  645. IF SysEnterSysExit IN register THEN w.String("[SysEnterSysExit]"); END;
  646. IF APIC IN register THEN w.String("[APIC]"); END;
  647. IF CMPXCH8B IN register THEN w.String("[CMPXCH8B]"); END;
  648. IF MCE IN register THEN w.String("[MCE]"); END;
  649. IF PAE IN register THEN w.String("[PAE]"); END;
  650. IF MSR IN register THEN w.String("[MSR]"); END;
  651. IF TSC IN register THEN w.String("[TSC]"); END;
  652. IF PSE IN register THEN w.String("[PSE]"); END;
  653. IF DE IN register THEN w.String("[DE]"); END;
  654. IF VME IN register THEN w.String("[VME]"); END;
  655. IF FPU IN register THEN w.String("[FPU]"); END;
  656. END ShowFeatures;
  657. PROCEDURE ShowL1Associativity(w : Streams.Writer; value : LONGINT);
  658. BEGIN
  659. IF value = 0 THEN w.String("Reserved");
  660. ELSIF value = 1 THEN w.String("Direct mapped");
  661. ELSIF value = 0FFH THEN w.String("Fully associative");
  662. ELSE
  663. w.Int(value, 0); w.String("-way associative");
  664. END;
  665. END ShowL1Associativity;
  666. PROCEDURE ShowL2Associativity(w : Streams.Writer; value : LONGINT);
  667. BEGIN
  668. IF value = 0 THEN w.String("disabled");
  669. ELSIF value = 1 THEN w.String("Direct mapped");
  670. ELSIF value = 2 THEN w.String("2-way associative");
  671. ELSIF value = 4 THEN w.String("4-way associative");
  672. ELSIF value = 6 THEN w.String("8-way associative");
  673. ELSIF value = 8 THEN w.String("16-way associative");
  674. ELSIF value = 0FH THEN w.String("Fully associative");
  675. ELSE w.String("unknown");
  676. END;
  677. END ShowL2Associativity;
  678. PROCEDURE AmdShowL1TlbAndCache(w : Streams.Writer; cpuInfo : CpuInformation);
  679. BEGIN
  680. w.String(" TLB: "); w.Ln;
  681. w.String(" 2M/4M Data TLB: "); w.Int(cpuInfo.l1DataTlbSize2M4M, 0); w.String(" entries, ");
  682. ShowL1Associativity(w, cpuInfo.l1DataTlbAssociativity2M4M);
  683. w.Ln;
  684. w.String(" 2M/4M Instr TLB: "); w.Int(cpuInfo.l1InstrTlbSize2M4M, 0); w.String(" entries, ");
  685. ShowL1Associativity(w, cpuInfo.l1InstrTlbAssociativity2M4M);
  686. w.Ln;
  687. w.String(" 4K Data TLB: "); w.Int(cpuInfo.l1DataTlbSize4K, 0); w.String(" entries, ");
  688. ShowL1Associativity(w, cpuInfo.l1DataTlbAssociativity4K);
  689. w.Ln;
  690. w.String(" 4K Instr TLB: "); w.Int(cpuInfo.l1InstrTlbSize4K, 0); w.String(" entries, ");
  691. ShowL1Associativity(w, cpuInfo.l1InstrTlbAssociativity4K);
  692. w.Ln;
  693. w.String(" Level 1 cache: "); w.Ln;
  694. w.String(" Data: "); w.Int(cpuInfo.l1DcSize, 0); w.String("KB, "); ShowL1Associativity(w, cpuInfo.l1DcAssociativity);
  695. w.String(", Lines per Tag: "); w.Int(cpuInfo.l1DcLinesPerTag, 0); w.String(", Line size: "); w.Int(cpuInfo.l1DcLineSize, 0);
  696. w.String(" Bytes");
  697. w.Ln;
  698. w.String(" Instr: "); w.Int(cpuInfo.l1IcSize, 0); w.String("KB, "); ShowL1Associativity(w, cpuInfo.l1IcAssociativity);
  699. w.String(", Lines per Tag: "); w.Int(cpuInfo.l1IcLinesPerTag, 0);
  700. w.String(", Line size: "); w.Int(cpuInfo.l1IcLineSize, 0); w.String(" Bytes");
  701. END AmdShowL1TlbAndCache;
  702. PROCEDURE AmdShowL2TlbAndCache(w : Streams.Writer; cpuInfo : CpuInformation);
  703. BEGIN
  704. w.String(" TLB: "); w.Ln;
  705. IF ~cpuInfo.unifiedTlb THEN
  706. w.String(" 2M/4M Data TLB: "); w.Int(cpuInfo.l2DataTlbSize2M4M, 0); w.String(" entries, ");
  707. ShowL2Associativity(w, cpuInfo.l2DataTlbAssociativity2M4M);
  708. w.Ln;
  709. w.String(" 2M/4M Instr TLB: "); w.Int(cpuInfo.l2InstrTlbSize2M4M, 0); w.String(" entries, ");
  710. ShowL2Associativity(w, cpuInfo.l2InstrTlbAssociativity2M4M);
  711. w.Ln;
  712. ELSE
  713. w.String("Unified TLB for 4K/2M/4M: "); w.Ln;
  714. END;
  715. w.String(" 4K Data TLB: "); w.Int(cpuInfo.l2DataTlbSize4K, 0); w.String(" entries, ");
  716. ShowL2Associativity(w, cpuInfo.l2DataTlbAssociativity4K);
  717. w.Ln;
  718. w.String(" 4K Instr TLB: "); w.Int(cpuInfo.l2InstrTlbSize4K, 0); w.String(" entries, ");
  719. ShowL2Associativity(w, cpuInfo.l2InstrTlbAssociativity4K);
  720. w.Ln;
  721. w.String(" Level 2 cache: "); w.Ln;
  722. w.String(" Size: "); w.Int(cpuInfo.l2CacheSize, 0); w.String("KB, ");
  723. ShowL2Associativity(w, cpuInfo.l2Associativity);
  724. IF cpuInfo.cputype = Amd THEN
  725. w.String(", Lines per Tag: "); w.Int(cpuInfo.l2LinesPerTag, 0);
  726. END;
  727. w.String(", Line size: "); w.Int(cpuInfo.l2LineSize, 0); w.String(" Bytes");
  728. END AmdShowL2TlbAndCache;
  729. PROCEDURE AmdShowSVM(w : Streams.Writer; cpuInfo : CpuInformation);
  730. BEGIN
  731. w.String(" SVM Revision: "); w.Hex(cpuInfo.svmRev, -2); w.String("H"); w.Ln;
  732. w.String(" Number of address space identifiers (ASID): "); w.Int(cpuInfo.nasid, 0); w.Ln;
  733. END AmdShowSVM;
  734. PROCEDURE IntelShowCacheDescriptors(w : Streams.Writer);
  735. VAR eax, ebx, ecx, edx : SET; i : LONGINT;
  736. PROCEDURE ShowReg(reg : SET; isEax : BOOLEAN);
  737. VAR s: ARRAY 128 OF CHAR;
  738. BEGIN
  739. IF ~(31 IN reg )THEN
  740. IF ~isEax THEN
  741. IF reg * {0..7} # {} THEN GetCacheIntel(w, SYSTEM.VAL(LONGINT, reg * {0..7}), s); w.String(s); w.Ln; END;
  742. END;
  743. IF reg * {8..15} # {} THEN GetCacheIntel(w, SYSTEM.VAL(LONGINT, LSH(reg * {8..15},-8)), s); w.String(s); w.Ln; END;
  744. IF reg * {16..23} # {} THEN GetCacheIntel(w, SYSTEM.VAL(LONGINT,LSH( reg * {16..23},-16)), s); w.String(s); w.Ln; END;
  745. IF reg * {24..31} # {} THEN GetCacheIntel(w, SYSTEM.VAL(LONGINT, LSH(reg * {24..31},-24)), s); w.String(s); w.Ln; END;
  746. END;
  747. END ShowReg;
  748. BEGIN
  749. CPUID(2H, eax, ebx, ecx, edx);
  750. ShowReg(eax, TRUE);
  751. ShowReg(ebx, FALSE);
  752. ShowReg(ecx, FALSE);
  753. ShowReg(edx, FALSE);
  754. i := SYSTEM.VAL(LONGINT, eax * {0..7}) - 1;
  755. WHILE (i > 0) DO
  756. CPUID(2H, eax, ebx, ecx, edx);
  757. ShowReg(eax, TRUE);
  758. ShowReg(ebx, FALSE);
  759. ShowReg(ecx, FALSE);
  760. ShowReg(edx, FALSE);
  761. DEC(i);
  762. END;
  763. END IntelShowCacheDescriptors;
  764. PROCEDURE GetCacheIntel*(w : Streams.Writer; value : LONGINT; VAR s: ARRAY OF CHAR);
  765. BEGIN
  766. CASE value OF
  767. |00H: s := "Null";
  768. |01H: s := "Instruction TLB: 4KB Pages, 4-way set associative, 32 entries";
  769. |02H: s := "Instruction TLB: 4MB Pages, fully associative, 2 entries";
  770. |03H: s := "Data TLB: 4KB Pages, 4-way set associative, 64 entries";
  771. |04H: s := "Data TLB: 4MB Pages, 4-way set associative, 8 entries";
  772. |05H: s := "DataTLB: 4MB Pages, 4-way set associative, 32 entries";
  773. |06H: s := "L1 instruction cache, 8KB, 4-way set associative, 32 byte line size";
  774. |08H: s := "L1 instruction cache, 16KB, 4-way set associative, 32-byte line size";
  775. |0AH: s := "L1 data cache, 8KB, 2-way set associative, 32-byte line size";
  776. |0CH: s := "L1 data cache, 16KB, 4-way set associative, 32-byte line size";
  777. |22H: s := "L3 cache, 512KB, 4-way set associative, sectored cache, 64-byte line size";
  778. |23H: s := "L3 cache, 1MB, 8-way set associative, sectored cache, 64-byte line size";
  779. |25H: s := "L3 cache, 2MB, 8-way set associative, sectored cache, 64-byte line size";
  780. |29H: s := "L3 cache, 4MB, 8-way set associative, sectored cache, 64-byte line size";
  781. |2CH: s := "L1 data cache, 32KB, 8-way set associative, 64-byte line size";
  782. |30H: s := "L1 instruction cache, 32KB, 8-way set associative, 64-byte line size";
  783. |39H: s := "L2 cache, 128KB, 4-way set associative, sectored cache, 64-byte line size";
  784. |3AH: s := "L2 cache, 192KB, 6-way set associative, sectored cache, 64-byte line size";
  785. |3BH: s := "L2 cache, 128KB, 2-way set associative, sectored cache, 64-byte line size";
  786. |3CH: s := "L2 cache, 256KB, 4-way set associative, sectored cache, 64-byte line size";
  787. |3DH: s := "L2 cache, 384KB, 6-way set associative, sectored cache, 64-byte line size";
  788. |3EH: s := "L2 cache, 512KB, 4-way set associative, sectored cache, 64-byte line size";
  789. |40H: s := "No L2 cache or, if processor contains valid L2 cache, no L2 cache";
  790. |41H: s := "L2 cache, 128KB, 4-way set associative, 32-byte line size";
  791. |42H: s := "L2 cache, 256KB, 4-way set associative, 32-byte line size";
  792. |43H: s := "L2 cache, 512KB, 4-way set associative, 32-byte line size";
  793. |44H: s := "L2 cache, 1MB, 4-way set associative, 32-byte line size";
  794. |45H: s := "L2 cache, 2MB, 4-way set associative, 32-byte line size";
  795. |46H: s := "L3 cache, 4MB, 4-way set associative, 64-byte line size";
  796. |47H: s := "L3 cache, 8MB, 8-way set associative, 64-byte line size";
  797. |49H: s := "L2 cache, 4MB, 16-way set associative, 64-byte line size";
  798. |4AH: s := "L3 cache, 6MB, 12-way set associative, 64-byte line size";
  799. |4BH: s := "L3 cache, 8MB, 16-way set associative, 64-byte line size";
  800. |4CH: s := "L3 cache, 12MB, 12-way set associative, 64-byte line size";
  801. |4DH: s := "L3 cache, 16MB, 16-way set associative, 64-byte line size";
  802. |4EH: s:="2nd-level cache: 6MB, 24-way set associative, 64-byte line size";
  803. |50H: s := "Instruction TLB: 4KB, 2MB or 4MB pages, fully associative, 64 entries";
  804. |51H: s := "Instruction TLB: 4KB, 2MB or 4MB pages, fully associative, 128 entries";
  805. |52H: s := "Instruction TLB: 4KB, 2MB or 4MB pages, fully associative, 256 entries";
  806. |56H: s := "L0 Data TLB: 4MB pages, 4-way set associative, 16 entries";
  807. |57H: s := "L0 Data TLB: 4KB pages, 4-way set associative, 16 entries";
  808. |5BH: s := "Data TLB: 4KB or 4MB pages, fully associative, 64 entries";
  809. |5CH: s := "Data TLB: 4KB or 4MB pages, fully associative, 128 entries";
  810. |5DH: s := "Data TLB: 4KB or 4MB pages, fully associative, 256 entries";
  811. |60H: s := "L1 data cache, 16KB, 8-way set associative, sectored cache, 64-byte line size";
  812. |66H: s := "L1 data cache, 8KB, 4-way set associative, sectored cache, 64-byte line size";
  813. |67H: s := "L1 data cache, 16KB, 4-way set associative, sectored cache, 64-byte line size";
  814. |68H: s := "L1 data cache, 32KB, 4-way set associative, sectored cache, 64-byte line size";
  815. |70H: s := "Trace cache: 12 Kuops, 8-way set associative";
  816. |71H: s := "Trace cache: 16 Kuops, 8-way set associative";
  817. |72H: s := "Trace cache: 32 Kuops, 8-way set associative";
  818. |73H: s := "Trace cache: 64 Kuops, 8-way set associative";
  819. |78H: s := "L2 cache, 1MB, 4-way set associative, 64-byte line size";
  820. |79H: s := "L2 cache, 128KB, 8-way set associative, sectored cache, 64-byte line size";
  821. |7AH: s := "L2 cache, 256KB, 8-way set associative, sectored cache, 64-byte line size";
  822. |7BH: s := "L2 cache, 512KB, 8-way set associative, sectored cache, 64-byte line size";
  823. |7CH: s := "L2 cache, 1MB, 8-way set associative, sectored cache, 64-byte line size";
  824. |7DH: s := "L2 cache, 2MB, 8-way set associative, 64-byte line size";
  825. |7FH: s := "L2 cache, 512KB, 2-way set associative, 64-byte line size";
  826. |82H: s := "L2 cache, 256KB, 8-way set associative, 32-byte line size";
  827. |83H: s := "L2 cache, 512KB, 8-way set associative, 32-byte line size";
  828. |84H: s := "L2 cache, 1MB, 8-way set associative, 32-byte line size";
  829. |85H: s := "L2 cache, 2MB, 8-way set associative, 32-byte line size";
  830. |86H: s := "L2 cache, 512KB, 4-way set associative, 64-byte line size";
  831. |87H: s := "L2 cache, 1MB, 8-way set associative, 64-byte line size";
  832. |0B0H: s := "Instruction TLB: 4KB Pages, 4-way set associative, 128 entries";
  833. |0B1H: s := "Instruction TLB: 2M/4M pages, 4-way set associative, 2M: 4 entries, 4M: 8 entries";
  834. |0B3H: s := "Data TLB: 4KB pages, 4-way set associative, 128 entries";
  835. |0B4H: s := "Data TLB: 4KB pages, 4-way set associative, 256 entries";
  836. |0F0H: s := "64-byte Prefetching";
  837. |0F1H: s := "128-byte Prefetching";
  838. ELSE
  839. s := "Entry not defined";
  840. END;
  841. END GetCacheIntel;
  842. PROCEDURE IntelShowL2TlbAndCache(w : Streams.Writer; cpuInfo : CpuInformation);
  843. BEGIN
  844. w.String(" Level 2 cache: "); w.Ln;
  845. w.String(" Size: "); w.Int(cpuInfo.l2CacheSize, 0); w.String("KB, ");
  846. ShowL2Associativity(w, cpuInfo.l2Associativity);
  847. w.String(", Line size: "); w.Int(cpuInfo.l2LineSize, 0); w.String(" Bytes"); w.Ln;
  848. END IntelShowL2TlbAndCache;
  849. PROCEDURE ShowDetailedCpuInformation(w : Streams.Writer; cpuInfo : CpuInformation);
  850. BEGIN
  851. w.String("Standard Function 0: Processor Vendor and Largest Standard Function: "); w.Ln;
  852. w.String(" Vendor: "); w.String(cpuInfo.vendor); w.Ln;
  853. w.String(" Largest Standard Function: "); w.Int(cpuInfo.largestStandardFunction, 0); w.Ln;
  854. w.Ln;
  855. IF cpuInfo.largestStandardFunction >= 1 THEN
  856. w.String("Standard Function 1: Family, Model, Stepping Identifiers: "); w.Ln;
  857. w.String(" Family: "); w.Hex(cpuInfo.family, -2); w.String("H, Model: "); w.Hex(cpuInfo.model, -2);
  858. w.String("H, Stepping: "); w.Hex(cpuInfo.stepping, -2); w.Char("H");
  859. IF cpuInfo.cputype = Intel THEN
  860. w.String(", type: "); w.Int(cpuInfo.type, 0);
  861. CASE cpuInfo.type OF
  862. |0: w.String(" (Original OEM processor)");
  863. |1: w.String(" (OverDrive processor)");
  864. |2: w.String(" (Dual processor)");
  865. |3: w.String(" (Intel reserved)");
  866. ELSE
  867. w.String(" (Out of range)");
  868. END;
  869. END;
  870. w.Ln;
  871. w.String(" Local APIC Initial ID: "); w.Int(cpuInfo.localApicId, 0);
  872. w.String(", Logical processor count: "); w.Int(cpuInfo.logicalProcessorCount, 0);
  873. w.Ln;
  874. w.String(" CLFLUSH line size: "); w.Int(cpuInfo.clflushSize, 0); w.String(" Bytes");
  875. w.String(", BrandId: "); w.Int(cpuInfo.brandId, 0);
  876. w.Ln;
  877. w.String(" Features: "); ShowFeatures2(w, cpuInfo.features2); ShowFeatures(w, cpuInfo.features); w.Ln;
  878. w.Ln;
  879. END;
  880. IF (cpuInfo.largestStandardFunction >= 2) & (cpuInfo.cputype = Intel) THEN
  881. w.String("Standard Function 2: Cache Descriptors: "); w.Ln;
  882. IntelShowCacheDescriptors(w);
  883. w.Ln;
  884. END;
  885. IF (cpuInfo.largestStandardFunction >=4) THEN
  886. IF cpuInfo.cputype=Intel THEN
  887. w.String("INTEL Standard Function 4: Deterministic Cache Parameters : "); w.Ln;
  888. IntelStandardFunction4(w);
  889. w.Ln;
  890. END;
  891. END;
  892. IF (cpuInfo.largestStandardFunction >=5) THEN
  893. IF cpuInfo.cputype=Intel THEN
  894. w.String("INTEL Standard Function 5: MONITOR/ MWAIT Parameters : "); w.Ln;
  895. IntelStandardFunction5(w);
  896. w.Ln;
  897. END;
  898. END;
  899. IF (cpuInfo.largestStandardFunction >=6) THEN
  900. IF cpuInfo.cputype=Intel THEN
  901. w.String("INTEL Standard Function 6: Digital Termal Sensor and Power Management Parameters : "); w.Ln;
  902. IntelStandardFunction6(w);
  903. w.Ln;
  904. END;
  905. END;
  906. IF (cpuInfo.largestStandardFunction >=9) THEN
  907. IF cpuInfo.cputype=Intel THEN
  908. w.String("INTEL: Direct Cache Access (DCA) Parameters : "); w.Ln;
  909. IntelStandardFunction9(w);
  910. w.Ln;
  911. END;
  912. END;
  913. IF (cpuInfo.largestStandardFunction >9) THEN
  914. IF cpuInfo.cputype=Intel THEN
  915. w.String("INTEL Standard Function 0A: Architectural Performance Monitor Features: "); w.Ln;
  916. IntelStandardFunction0A(w);
  917. w.Ln;
  918. END;
  919. END;
  920. w.String("Extended Function 0: Largest Extended Function: "); w.Ln;
  921. w.String(" Largest Extended Function: "); w.Int(cpuInfo.largestExtendedFunction, 0); w.Ln;
  922. w.Ln;
  923. IF cpuInfo.largestExtendedFunction >= 1 THEN
  924. w.String("Extended Function 1: Features: "); w.Ln;
  925. w.String(" Extended features: "); ShowExtFeatures2Amd(w, cpuInfo.extFeatures2); ShowExtFeaturesAmd(w, cpuInfo.extFeatures); w.Ln;
  926. w.Ln;
  927. END;
  928. IF cpuInfo.largestExtendedFunction >= 2 THEN
  929. w.String("Extended Function 2-4: Processor Name: "); w.Ln;
  930. w.String(" Processor Name: "); w.String(cpuInfo.processorName); w.Ln;
  931. w.Ln;
  932. END;
  933. IF cpuInfo.largestExtendedFunction < 5 THEN RETURN; END;
  934. IF cpuInfo.cputype = Amd THEN
  935. w.String("AMD Extended Function 5: L1 Cache and TLB Identifiers: "); w.Ln;
  936. AmdShowL1TlbAndCache(w, cpuInfo); w.Ln;
  937. w.Ln;
  938. END;
  939. IF cpuInfo.largestExtendedFunction < 6 THEN RETURN; END;
  940. IF cpuInfo.cputype = Amd THEN
  941. w.String("AMD Extended Function 6: L2 Cache and TLB Identifiers: "); w.Ln;
  942. AmdShowL2TlbAndCache(w, cpuInfo); w.Ln;
  943. w.Ln;
  944. ELSIF cpuInfo.cputype=Intel THEN
  945. w.String("INTEL Extended Function 6: L2 Cache Features: "); w.Ln;
  946. IntelShowL2TlbAndCache(w, cpuInfo);
  947. w.Ln;
  948. END;
  949. IF cpuInfo.largestExtendedFunction < 7 THEN RETURN END;
  950. IF cpuInfo.cputype = Amd THEN
  951. w.String("AMD Extended Function 7: Advanced Power Management Information: "); w.Ln;
  952. w.String(" Features: "); ShowPowerManagementAmd(w, cpuInfo.powerManagement); w.Ln;
  953. w.Ln;
  954. END;
  955. IF cpuInfo.largestExtendedFunction < 8 THEN RETURN; END;
  956. IF (cpuInfo.cputype = Amd) OR (cpuInfo.cputype=Intel) THEN
  957. w.String("Extended Function 8: Long Mode Address Size Identifiers: "); w.Ln;
  958. ShowLongModeAS(w, cpuInfo); w.Ln;
  959. w.Ln;
  960. END;
  961. IF cpuInfo.largestExtendedFunction < 0AH THEN RETURN END;
  962. IF cpuInfo.cputype = Amd THEN
  963. w.String("AMD Extended Function A: SVM Revision and Feature Identification: "); w.Ln;
  964. AmdShowSVM(w, cpuInfo); w.Ln;
  965. w.Ln;
  966. END;
  967. END ShowDetailedCpuInformation;
  968. PROCEDURE ShowCpuInformation(w : Streams.Writer; cpuInfo : CpuInformation);
  969. PROCEDURE ShowFlag(flag : LONGINT; register : SET);
  970. BEGIN
  971. IF flag IN register THEN w.String("Yes"); ELSE w.String("No"); END;
  972. END ShowFlag;
  973. BEGIN
  974. IF cpuInfo.largestExtendedFunction >= 2 THEN
  975. w.String("Prozessor: "); w.String(cpuInfo.processorName); w.Ln;
  976. END;
  977. w.String(" Vendor: "); w.String(cpuInfo.vendor);
  978. IF cpuInfo.largestStandardFunction >= 1 THEN
  979. w.String(", Family: "); w.Hex(cpuInfo.family, -2); w.Char("H");
  980. w.String(", Model: "); w.Hex(cpuInfo.model, -2); w.Char("H");
  981. w.String(", Stepping: "); w.Hex(cpuInfo.stepping, -2); w.Char("H");
  982. w.Ln;
  983. IF HTT IN cpuInfo.features THEN
  984. w.String("Logical processor count: "); w.Int(cpuInfo.logicalProcessorCount, 0); w.Ln;
  985. END;
  986. w.String("Features: "); w.Ln;
  987. w.String(" MMX: "); ShowFlag(MMX, cpuInfo.features);
  988. w.String(", SSE: "); ShowFlag(SSE, cpuInfo.features);
  989. w.String(", SSE2: "); ShowFlag(SSE2, cpuInfo.features);
  990. w.String(", SSE3: "); ShowFlag(SSE3, cpuInfo.features2);
  991. w.String(", Supplemental SSE3: "); ShowFlag(SSSE3, cpuInfo.features2);
  992. END;
  993. w.Ln;
  994. IF cpuInfo.largestExtendedFunction >= 1 THEN
  995. w.String(" Extended 3DNow!: "); ShowFlag(Amd3DNowExt, cpuInfo.extFeatures);
  996. w.String(", 3DNow!: "); ShowFlag(Amd3DNow, cpuInfo.extFeatures);
  997. w.String(", AMD MMX Extensions: "); ShowFlag(MmxExt, cpuInfo.extFeatures);
  998. w.Ln;
  999. w.String(" 64bit instructions: "); ShowFlag(LM, cpuInfo.extFeatures);
  1000. w.Ln;
  1001. END;
  1002. IF (cpuInfo.cputype = Amd) & (cpuInfo.largestExtendedFunction >= 8) THEN
  1003. w.String(" Number of CPU cores: "); w.Int(cpuInfo.numberOfCores, 0); w.Ln;
  1004. END;
  1005. END ShowCpuInformation;
  1006. PROCEDURE Show*(context : Commands.Context); (** ["-d"|"--details"] ~ *)
  1007. VAR cpuInfo : CpuInformation; options : Options.Options;
  1008. BEGIN
  1009. NEW(options);
  1010. options.Add("d", "details", Options.Flag);
  1011. IF options.Parse(context.arg, context.error) THEN
  1012. IF CpuIdSupported() THEN
  1013. GetCpuInformation(cpuInfo);
  1014. IF options.GetFlag("details") THEN
  1015. ShowDetailedCpuInformation(context.out, cpuInfo);
  1016. ELSE
  1017. ShowCpuInformation(context.out, cpuInfo);
  1018. END;
  1019. ELSE
  1020. context.out.String("CPUID instruction is not supported."); context.out.Ln;
  1021. END;
  1022. END;
  1023. END Show;
  1024. END CPUID.
  1025. System.Free CPUID ~
  1026. CPUID.Show ~