Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get sbcl to print out the value of a CPU register?

Is there a way I can get SBCL to take the value of a CPU register at a certain point in my program and print it as an integer?

Would I have to use gdb?

like image 247
Samuel Edwin Ward Avatar asked Mar 11 '13 23:03

Samuel Edwin Ward


People also ask

What is Sbcl Mac?

Steel Bank Common Lisp (SBCL) is a high performance Common Lisp compiler. It is open source / free software, with a permissive license.

Is Common Lisp fast?

Common Lisp is AOT compiled to the metal so it starts up fast and runs fast. CL is often within a factor of 2 of C speed and dramatically faster than plain Python.

How do I exit Sbcl?

Running SBCL To quit SBCL, type (quit) .


2 Answers

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:

Dmitry Kaliyanov's article "Добавление примитивов виртуальной машины SBCL" ("Adding primitive virtual machines of SBCL", in Russian)

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.

like image 180
nrz Avatar answered Nov 09 '22 04:11

nrz


Another source of a cpuid example (that supports 64bit too) is from the excellent stmx library for CL.

  • the defknown form
  • the vop
  • the wrapper function
like image 35
Baggers Avatar answered Nov 09 '22 03:11

Baggers