*** empty log message ***
[sb-simd.git] / cpuid.lisp
blob708d3c94e4ddf4421cb69c7d0a7426cc3e4ed57d
1 #|
2 Copyright (c) 2005 Risto Laakso
3 All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 (defpackage :cpuid (:use :cl))
28 (in-package :cpuid)
31 (defvar +cpu-std-feat-fields+
32 #(:fpu :vme :de :pse :tsc :k86-msr :pae :mce :cmpxchg8b :apic :res10 :sysenter/exit :mtrr :gpe :mca :cmov :pat :pse-36 :psn :clflush :res20 :ds :acpi :mmx :fxsave/rstor :sse :sse2 :self-snoop :htt :tm :res30 :pbe))
34 (defvar +cpu-std-feat-fields-ecx+
35 #(:sse3 :res1 :res2 :monitor :ds-cpl :res5 :res6 :eist :tm2 :res9 :cid :res11 :res12 :cmpxchg16b :stpm :res14 :res15
36 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
38 ;; low bits are mostly same as in std-feat, so skip them..
39 (defvar +cpu-ext-feat-fields+
40 #(0 1 2 3 4 5 6 7 8 9 10 :syscall/ret 12 13 14 15 16 17 18 19 :nx 21 :mmx-ext :mmx 24 25 26 27 28 :longmode/em64t :3dnow-ext :3dnow))
43 (defvar *cpu-features* nil)
44 (defvar *cpu-vendor* nil) ;; eg authenticamd
45 (defvar *cpu-name* nil) ;; eg AMD Athlon XP
46 (defvar *cpu-cache* nil)
49 (defun inspect-cpu ()
51 (let ((array (make-array 8 :element-type '(unsigned-byte 16) :initial-element 0)) c d)
53 ;; vendor
55 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x00000000 array)
57 (let ((temp (make-array 12 :element-type '(unsigned-byte 8) :initial-element 0)))
58 (flet ((load-word (i u v) (setf (aref temp (+ i 3)) (ash (aref array u) -8)
59 (aref temp (+ i 2)) (logand (aref array u) 255)
60 (aref temp (+ i 1)) (ash (aref array v) -8)
61 (aref temp (+ i 0)) (logand (aref array v) 255))))
62 (loop for i from 0 below 12 by 4
63 for (u v) in '((2 3) (6 7) (4 5))
64 do (load-word i u v))
66 (setq *cpu-vendor* (map 'string #'code-char temp))))
69 ;; std features
70 (setq *cpu-features* nil)
72 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x00000001 array)
74 (setq
75 ;; a (logior (ash (aref array 0) 16) (aref array 1))
76 ;; b (logior (ash (aref array 2) 16) (aref array 3))
77 c (logior (ash (aref array 4) 16) (aref array 5))
78 d (logior (ash (aref array 6) 16) (aref array 7)))
80 (loop for i from 0 below 32 do
81 (if (= (ldb (byte 1 i) d) 1)
82 (push (aref +cpu-std-feat-fields+ i) *cpu-features*)))
84 (loop for i from 0 below 32 do
85 (if (= (ldb (byte 1 i) c) 1)
86 (push (aref +cpu-std-feat-fields-ecx+ i) *cpu-features*))))
89 (defun inspect-cpu-ext ()
90 (let ((array (make-array 8 :element-type '(unsigned-byte 16) :initial-element 0))
91 c d (max-ext-func 0))
93 ;; determine max ext func
94 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x80000000 array)
95 (setq max-ext-func (logior (ash (aref array 0) 16) (aref array 1)))
97 ;; ext features (AMD/Intel)
98 (if (>= max-ext-func #x80000001)
99 (progn
100 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x80000001 array)
101 (setq d (logior (ash (aref array 6) 16) (aref array 7)))
103 (loop for i from 0 below 32 do
104 (let ((flag (ldb (byte 1 i) d))
105 (feat (aref +cpu-ext-feat-fields+ i)))
106 (if (and (= flag 1) (keywordp feat))
107 (pushnew feat *cpu-features*))))))
109 ;; cpu name (AMD/Intel)
110 (setq *cpu-name* nil)
111 (if (>= max-ext-func #x80000004)
112 (let ((cpuname #())
113 (temp (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0)))
114 (flet ((load-word (i u v) (setf (aref temp (+ i 3)) (ash (aref array u) -8)
115 (aref temp (+ i 2)) (logand (aref array u) 255)
116 (aref temp (+ i 1)) (ash (aref array v) -8)
117 (aref temp (+ i 0)) (logand (aref array v) 255))))
118 (flet ((conc-word ()
119 (loop for i from 0 below 16 by 4
120 for (u v) in '((0 1) (2 3) (4 5) (6 7))
122 (load-word i u v))
123 (setq cpuname (concatenate '(simple-array (unsigned-byte 8) (*)) cpuname temp))))
125 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x80000002 array) (conc-word)
126 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x80000003 array) (conc-word)
127 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x80000004 array) (conc-word)
130 ;; cut to null
131 (if (position 0 cpuname)
132 (setq cpuname (subseq cpuname 0 (position 0 cpuname))))
133 ;; coerce to string
134 (setq cpuname (map 'string #'code-char cpuname))
135 (setq *cpu-name* cpuname)))
137 ;; cache (AMD)
138 (setq *cpu-cache* nil)
139 (if (>= max-ext-func #x80000005)
140 (progn
141 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x80000005 array)
142 (setq c (logior (ash (aref array 4) 16) (aref array 5))
143 d (logior (ash (aref array 6) 16) (aref array 7)))
145 (push (list :l1-data :size (* 1024 (ldb (byte 8 24) c))) *cpu-cache*)
146 (push (list :l1-inst :size (* 1024 (ldb (byte 8 24) d))) *cpu-cache*)))
149 (if (>= max-ext-func #x80000006)
150 (progn
151 (sb-sys:%primitive sb-vm::%read-cpu/x86 #x80000006 array)
152 (setq c (logior (ash (aref array 4) 16) (aref array 5)))
153 (push (list :l2 :size (* 1024 (ldb (byte 16 16) c))) *cpu-cache*)))
157 (defun dump-cpu ()
159 ;; dump
161 (format t "~&")
162 (format t "Vendor: ~A.~%" *cpu-vendor*)
163 (format t "Features: ~S.~%" *cpu-features*)
164 (format t "cpu: ~A, cache: ~S.~%" *cpu-name* *cpu-cache*)