Yes, you can access CPU registers by using VOPs (Virtual Operations). In VOPs you can write code also in assembly, so in that sense you can use VOPs like gcc extended assembly.
So, here's an example VOP and a related function for executing it. The get-cpuid-eax
VOP receives two unsigned 32-bit arguments as input, stores them in eax
and ecx
, executes cpuid
instruction, and returns the value of eax
register after the cpuid
to get-cpuid-eax
function that called the VOP. The get-cpuid-eax
function then stores the value in *result*
. You can print the value easily with (format t "~a" *result*)
.
Note: there is some problem (bug in SBCL or in my code?) that causes this code not to execute without problems always. Recompiling and reloading usually helps. I have confirmed the cpuid
eax
output with both gcc
extended assembly and running a x86-64 assembly program in gdb
. All give the same results for same values in eax
and ecx
.
Edit: changed function & VOP names to get-cpuid-eax
to avoid confusion with variable names.
Edit: fixed code formatting with slimv.
(sb-vm::defknown get-cpuid-eax ((unsigned-byte 32) (unsigned-byte 32)) (unsigned-byte 32) (sb-c::foldable sb-c::flushable sb-c::movable)) (sb-vm::define-vop (get-cpuid-eax) (:policy :fast-safe) (:translate get-cpuid-eax) (:args (my-eax :scs (sb-vm::unsigned-reg) :target eax) (my-ecx :scs (sb-vm::unsigned-reg) :target ecx)) (:arg-types sb-vm::unsigned-num sb-vm::unsigned-num) (:temporary (:sc sb-vm::unsigned-reg :offset sb-vm::eax-offset) eax) (:temporary (:sc sb-vm::unsigned-reg :offset sb-vm::ecx-offset) ecx) (:results (my-result :scs (sb-vm::unsigned-reg))) (:result-types sb-vm::unsigned-num) (:generator 0 (sb-vm::move eax my-eax) (sb-vm::move ecx my-ecx) (sb-vm::inst cpuid) (sb-vm::move my-result eax))) (defun get-cpuid-eax (my-eax my-ecx) (declare (type (unsigned-byte 32) my-eax my-ecx) (optimize (speed 3) (safety 0))) (defparameter *result* (get-cpuid-eax my-eax my-ecx)))
Some websites with short VOPs which I found very useful while coding this:
the Lisp code for Dmitry Kaliyanov's article (above)
Dmitry Ignatiev's blog entry: SBCL, x86, SSE (in Russian)
Christophe Rhodes' presentation slides (pdf): Unportable but fun: Using SBCL Internals
kurohuku's blog entry: "SBCLでCPUID" (in Japanese)
swap-bytes source code file sbcl-vops.lisp
Hope this helps.