*** empty log message ***
[sb-simd.git] / sbcl-src / src / compiler / x86 / vm.lisp
blob168f5e1604e3f214996891932b9294823f7861c8
1 ;;;; miscellaneous VM definition noise for the x86
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!VM")
14 ;;; the size of an INTEGER representation of a SYSTEM-AREA-POINTER, i.e.
15 ;;; size of a native memory address
16 (deftype sap-int () '(unsigned-byte 32))
18 ;;;; register specs
20 (eval-when (:compile-toplevel :load-toplevel :execute)
21 (defvar *byte-register-names* (make-array 8 :initial-element nil))
22 (defvar *word-register-names* (make-array 16 :initial-element nil))
23 (defvar *dword-register-names* (make-array 16 :initial-element nil))
24 (defvar *float-register-names* (make-array 8 :initial-element nil))
25 (defvar *xmmword-register-names* (make-array 8 :initial-element nil)))
27 (macrolet ((defreg (name offset size)
28 (let ((offset-sym (symbolicate name "-OFFSET"))
29 (names-vector (symbolicate "*" size "-REGISTER-NAMES*")))
30 `(progn
31 (eval-when (:compile-toplevel :load-toplevel :execute)
32 ;; EVAL-WHEN is necessary because stuff like #.EAX-OFFSET
33 ;; (in the same file) depends on compile-time evaluation
34 ;; of the DEFCONSTANT. -- AL 20010224
35 (def!constant ,offset-sym ,offset))
36 (setf (svref ,names-vector ,offset-sym)
37 ,(symbol-name name)))))
38 ;; FIXME: It looks to me as though DEFREGSET should also
39 ;; define the related *FOO-REGISTER-NAMES* variable.
40 (defregset (name &rest regs)
41 `(eval-when (:compile-toplevel :load-toplevel :execute)
42 (defparameter ,name
43 (list ,@(mapcar (lambda (name)
44 (symbolicate name "-OFFSET"))
45 regs))))))
47 ;; byte registers
49 ;; Note: the encoding here is different than that used by the chip.
50 ;; We use this encoding so that the compiler thinks that AX (and
51 ;; EAX) overlap AL and AH instead of AL and CL.
52 (defreg al 0 :byte)
53 (defreg ah 1 :byte)
54 (defreg cl 2 :byte)
55 (defreg ch 3 :byte)
56 (defreg dl 4 :byte)
57 (defreg dh 5 :byte)
58 (defreg bl 6 :byte)
59 (defreg bh 7 :byte)
60 (defregset *byte-regs* al ah cl ch dl dh bl bh)
62 ;; word registers
63 (defreg ax 0 :word)
64 (defreg cx 2 :word)
65 (defreg dx 4 :word)
66 (defreg bx 6 :word)
67 (defreg sp 8 :word)
68 (defreg bp 10 :word)
69 (defreg si 12 :word)
70 (defreg di 14 :word)
71 (defregset *word-regs* ax cx dx bx si di)
73 ;; double word registers
74 (defreg eax 0 :dword)
75 (defreg ecx 2 :dword)
76 (defreg edx 4 :dword)
77 (defreg ebx 6 :dword)
78 (defreg esp 8 :dword)
79 (defreg ebp 10 :dword)
80 (defreg esi 12 :dword)
81 (defreg edi 14 :dword)
82 (defregset *dword-regs* eax ecx edx ebx esi edi)
84 ;; floating point registers
85 (defreg fr0 0 :float)
86 (defreg fr1 1 :float)
87 (defreg fr2 2 :float)
88 (defreg fr3 3 :float)
89 (defreg fr4 4 :float)
90 (defreg fr5 5 :float)
91 (defreg fr6 6 :float)
92 (defreg fr7 7 :float)
93 (defregset *float-regs* fr0 fr1 fr2 fr3 fr4 fr5 fr6 fr7)
95 ;; sse registers
96 (defreg xmm0 0 :xmmword)
97 (defreg xmm1 1 :xmmword)
98 (defreg xmm2 2 :xmmword)
99 (defreg xmm3 3 :xmmword)
100 (defreg xmm4 4 :xmmword)
101 (defreg xmm5 5 :xmmword)
102 (defreg xmm6 6 :xmmword)
103 (defreg xmm7 7 :xmmword)
104 (defregset *xmm-regs* xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7)
106 ;; registers used to pass arguments
108 ;; the number of arguments/return values passed in registers
109 (def!constant register-arg-count 3)
110 ;; names and offsets for registers used to pass arguments
111 (eval-when (:compile-toplevel :load-toplevel :execute)
112 (defparameter *register-arg-names* '(edx edi esi)))
113 (defregset *register-arg-offsets* edx edi esi))
115 ;;;; SB definitions
117 ;;; Despite the fact that there are only 8 different registers, we consider
118 ;;; them 16 in order to describe the overlap of byte registers. The only
119 ;;; thing we need to represent is what registers overlap. Therefore, we
120 ;;; consider bytes to take one unit, and words or dwords to take two. We
121 ;;; don't need to tell the difference between words and dwords, because
122 ;;; you can't put two words in a dword register.
123 (define-storage-base registers :finite :size 16)
125 ;;; jrd changed this from size 1 to size 8. It doesn't seem to make much
126 ;;; sense to use the 387's idea of a stack; 8 separate registers is easier
127 ;;; to deal with.
128 ;;; the old way:
129 ;;; (define-storage-base float-registers :finite :size 1)
130 ;;; the new way:
131 (define-storage-base float-registers :finite :size 8)
133 (define-storage-base xmm-registers :finite :size 8)
135 (define-storage-base stack :unbounded :size 8)
136 (define-storage-base constant :non-packed)
137 (define-storage-base immediate-constant :non-packed)
138 (define-storage-base noise :unbounded :size 2)
140 ;;;; SC definitions
142 ;;; a handy macro so we don't have to keep changing all the numbers whenever
143 ;;; we insert a new storage class
145 (defmacro !define-storage-classes (&rest classes)
146 (collect ((forms))
147 (let ((index 0))
148 (dolist (class classes)
149 (let* ((sc-name (car class))
150 (constant-name (symbolicate sc-name "-SC-NUMBER")))
151 (forms `(define-storage-class ,sc-name ,index
152 ,@(cdr class)))
153 (forms `(def!constant ,constant-name ,index))
154 (incf index))))
155 `(progn
156 ,@(forms))))
158 ;;; The DEFINE-STORAGE-CLASS call for CATCH-BLOCK refers to the size
159 ;;; of CATCH-BLOCK. The size of CATCH-BLOCK isn't calculated until
160 ;;; later in the build process, and the calculation is entangled with
161 ;;; code which has lots of predependencies, including dependencies on
162 ;;; the prior call of DEFINE-STORAGE-CLASS. The proper way to
163 ;;; unscramble this would be to untangle the code, so that the code
164 ;;; which calculates the size of CATCH-BLOCK can be separated from the
165 ;;; other lots-of-dependencies code, so that the code which calculates
166 ;;; the size of CATCH-BLOCK can be executed early, so that this value
167 ;;; is known properly at this point in compilation. However, that
168 ;;; would be a lot of editing of code that I (WHN 19990131) can't test
169 ;;; until the project is complete. So instead, I set the correct value
170 ;;; by hand here (a sort of nondeterministic guess of the right
171 ;;; answer:-) and add an assertion later, after the value is
172 ;;; calculated, that the original guess was correct.
174 ;;; (What a KLUDGE! Anyone who wants to come in and clean up this mess
175 ;;; has my gratitude.) (FIXME: Maybe this should be me..)
176 (eval-when (:compile-toplevel :load-toplevel :execute)
177 (def!constant kludge-nondeterministic-catch-block-size 6))
179 (!define-storage-classes
181 ;; non-immediate constants in the constant pool
182 (constant constant)
184 ;; some FP constants can be generated in the i387 silicon
185 (fp-constant immediate-constant)
187 (immediate immediate-constant)
190 ;; the stacks
193 ;; the control stack
194 (control-stack stack) ; may be pointers, scanned by GC
196 ;; the non-descriptor stacks
197 (signed-stack stack) ; (signed-byte 32)
198 (unsigned-stack stack) ; (unsigned-byte 32)
199 (character-stack stack) ; non-descriptor characters.
200 (sap-stack stack) ; System area pointers.
201 (single-stack stack) ; single-floats
202 (double-stack stack :element-size 2) ; double-floats.
203 (xmm-stack stack :element-size 4) ; xmm
204 #!+long-float
205 (long-stack stack :element-size 3) ; long-floats.
206 (complex-single-stack stack :element-size 2) ; complex-single-floats
207 (complex-double-stack stack :element-size 4) ; complex-double-floats
208 #!+long-float
209 (complex-long-stack stack :element-size 6) ; complex-long-floats
212 ;; magic SCs
215 (ignore-me noise)
218 ;; things that can go in the integer registers
221 ;; On the X86, we don't have to distinguish between descriptor and
222 ;; non-descriptor registers, because of the conservative GC.
223 ;; Therefore, we use different scs only to distinguish between
224 ;; descriptor and non-descriptor values and to specify size.
226 ;; immediate descriptor objects. Don't have to be seen by GC, but nothing
227 ;; bad will happen if they are. (fixnums, characters, header values, etc).
228 (any-reg registers
229 :locations #.*dword-regs*
230 :element-size 2
231 ; :reserve-locations (#.eax-offset)
232 :constant-scs (immediate)
233 :save-p t
234 :alternate-scs (control-stack))
236 ;; pointer descriptor objects -- must be seen by GC
237 (descriptor-reg registers
238 :locations #.*dword-regs*
239 :element-size 2
240 ; :reserve-locations (#.eax-offset)
241 :constant-scs (constant immediate)
242 :save-p t
243 :alternate-scs (control-stack))
245 ;; non-descriptor characters
246 (character-reg registers
247 :locations #!-sb-unicode #.*byte-regs*
248 #!+sb-unicode #.*dword-regs*
249 #!-sb-unicode #!-sb-unicode
250 :reserve-locations (#.ah-offset #.al-offset)
251 :constant-scs (immediate)
252 :save-p t
253 :alternate-scs (character-stack))
255 ;; non-descriptor SAPs (arbitrary pointers into address space)
256 (sap-reg registers
257 :locations #.*dword-regs*
258 :element-size 2
259 ; :reserve-locations (#.eax-offset)
260 :constant-scs (immediate)
261 :save-p t
262 :alternate-scs (sap-stack))
264 ;; non-descriptor (signed or unsigned) numbers
265 (signed-reg registers
266 :locations #.*dword-regs*
267 :element-size 2
268 ; :reserve-locations (#.eax-offset)
269 :constant-scs (immediate)
270 :save-p t
271 :alternate-scs (signed-stack))
272 (unsigned-reg registers
273 :locations #.*dword-regs*
274 :element-size 2
275 ; :reserve-locations (#.eax-offset)
276 :constant-scs (immediate)
277 :save-p t
278 :alternate-scs (unsigned-stack))
280 ;; miscellaneous objects that must not be seen by GC. Used only as
281 ;; temporaries.
282 (word-reg registers
283 :locations #.*word-regs*
284 :element-size 2
285 ; :reserve-locations (#.ax-offset)
287 (byte-reg registers
288 :locations #.*byte-regs*
289 ; :reserve-locations (#.al-offset #.ah-offset)
292 ;; that can go in the floating point registers
294 ;; non-descriptor SINGLE-FLOATs
295 (single-reg float-registers
296 :locations (0 1 2 3 4 5 6 7)
297 :constant-scs (fp-constant)
298 :save-p t
299 :alternate-scs (single-stack))
301 ;; non-descriptor DOUBLE-FLOATs
302 (double-reg float-registers
303 :locations (0 1 2 3 4 5 6 7)
304 :constant-scs (fp-constant)
305 :save-p t
306 :alternate-scs (double-stack))
308 ;; non-descriptor XMMs
309 (xmm-reg xmm-registers
310 :locations #.*xmm-regs*
311 :save-p t
312 :alternate-scs (xmm-stack))
314 ;; non-descriptor LONG-FLOATs
315 #!+long-float
316 (long-reg float-registers
317 :locations (0 1 2 3 4 5 6 7)
318 :constant-scs (fp-constant)
319 :save-p t
320 :alternate-scs (long-stack))
322 (complex-single-reg float-registers
323 :locations (0 2 4 6)
324 :element-size 2
325 :constant-scs ()
326 :save-p t
327 :alternate-scs (complex-single-stack))
329 (complex-double-reg float-registers
330 :locations (0 2 4 6)
331 :element-size 2
332 :constant-scs ()
333 :save-p t
334 :alternate-scs (complex-double-stack))
336 #!+long-float
337 (complex-long-reg float-registers
338 :locations (0 2 4 6)
339 :element-size 2
340 :constant-scs ()
341 :save-p t
342 :alternate-scs (complex-long-stack))
344 ;; a catch or unwind block
345 (catch-block stack :element-size kludge-nondeterministic-catch-block-size))
347 (eval-when (:compile-toplevel :load-toplevel :execute)
348 (defparameter *byte-sc-names*
349 '(#!-sb-unicode character-reg byte-reg #!-sb-unicode character-stack))
350 (defparameter *word-sc-names* '(word-reg))
351 (defparameter *dword-sc-names*
352 '(any-reg descriptor-reg sap-reg signed-reg unsigned-reg control-stack
353 signed-stack unsigned-stack sap-stack single-stack
354 #!+sb-unicode character-reg #!+sb-unicode character-stack constant))
355 ;;; added by jrd. I guess the right thing to do is to treat floats
356 ;;; as a separate size...
358 ;;; These are used to (at least) determine operand size.
359 (defparameter *float-sc-names* '(single-reg))
360 (defparameter *double-sc-names* '(double-reg double-stack))
361 (defparameter *xmmword-sc-names* '(xmm-reg))
362 ) ; EVAL-WHEN
364 ;;;; miscellaneous TNs for the various registers
366 (macrolet ((def-misc-reg-tns (sc-name &rest reg-names)
367 (collect ((forms))
368 (dolist (reg-name reg-names)
369 (let ((tn-name (symbolicate reg-name "-TN"))
370 (offset-name (symbolicate reg-name "-OFFSET")))
371 ;; FIXME: It'd be good to have the special
372 ;; variables here be named with the *FOO*
373 ;; convention.
374 (forms `(defparameter ,tn-name
375 (make-random-tn :kind :normal
376 :sc (sc-or-lose ',sc-name)
377 :offset
378 ,offset-name)))))
379 `(progn ,@(forms)))))
381 (def-misc-reg-tns unsigned-reg eax ebx ecx edx ebp esp edi esi)
382 (def-misc-reg-tns word-reg ax bx cx dx bp sp di si)
383 (def-misc-reg-tns byte-reg al ah bl bh cl ch dl dh)
384 (def-misc-reg-tns single-reg fr0 fr1 fr2 fr3 fr4 fr5 fr6 fr7)
385 (def-misc-reg-tns xmm-reg xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7))
387 ;;; TNs for registers used to pass arguments
388 (defparameter *register-arg-tns*
389 (mapcar (lambda (register-arg-name)
390 (symbol-value (symbolicate register-arg-name "-TN")))
391 *register-arg-names*))
393 ;;; FIXME: doesn't seem to be used in SBCL
395 ;;; added by pw
396 (defparameter fp-constant-tn
397 (make-random-tn :kind :normal
398 :sc (sc-or-lose 'fp-constant)
399 :offset 31)) ; Offset doesn't get used.
402 ;;; If value can be represented as an immediate constant, then return
403 ;;; the appropriate SC number, otherwise return NIL.
404 (!def-vm-support-routine immediate-constant-sc (value)
405 (typecase value
406 ((or (integer #.sb!xc:most-negative-fixnum #.sb!xc:most-positive-fixnum)
407 #-sb-xc-host system-area-pointer character)
408 (sc-number-or-lose 'immediate))
409 (symbol
410 (when (static-symbol-p value)
411 (sc-number-or-lose 'immediate)))
412 (single-float
413 (when (or (eql value 0f0) (eql value 1f0))
414 (sc-number-or-lose 'fp-constant)))
415 (double-float
416 (when (or (eql value 0d0) (eql value 1d0))
417 (sc-number-or-lose 'fp-constant)))
418 #!+long-float
419 (long-float
420 (when (or (eql value 0l0) (eql value 1l0)
421 (eql value pi)
422 (eql value (log 10l0 2l0))
423 (eql value (log 2.718281828459045235360287471352662L0 2l0))
424 (eql value (log 2l0 10l0))
425 (eql value (log 2l0 2.718281828459045235360287471352662L0)))
426 (sc-number-or-lose 'fp-constant)))))
428 ;;;; miscellaneous function call parameters
430 ;;; offsets of special stack frame locations
431 (def!constant ocfp-save-offset 0)
432 (def!constant return-pc-save-offset 1)
433 (def!constant code-save-offset 2)
435 ;;; FIXME: This is a bad comment (changed since when?) and there are others
436 ;;; like it in this file. It'd be nice to clarify them. Failing that deleting
437 ;;; them or flagging them with KLUDGE might be better than nothing.
439 ;;; names of these things seem to have changed. these aliases by jrd
440 (def!constant lra-save-offset return-pc-save-offset)
442 (def!constant cfp-offset ebp-offset) ; pfw - needed by stuff in /code
443 ; related to signal context stuff
445 ;;; This is used by the debugger.
446 (def!constant single-value-return-byte-offset 2)
448 ;;; This function is called by debug output routines that want a pretty name
449 ;;; for a TN's location. It returns a thing that can be printed with PRINC.
450 (!def-vm-support-routine location-print-name (tn)
451 (declare (type tn tn))
452 (let* ((sc (tn-sc tn))
453 (sb (sb-name (sc-sb sc)))
454 (offset (tn-offset tn)))
455 (ecase sb
456 (registers
457 (let* ((sc-name (sc-name sc))
458 (name-vec (cond ((member sc-name *byte-sc-names*)
459 *byte-register-names*)
460 ((member sc-name *word-sc-names*)
461 *word-register-names*)
462 ((member sc-name *dword-sc-names*)
463 *dword-register-names*))))
464 (or (and name-vec
465 (< -1 offset (length name-vec))
466 (svref name-vec offset))
467 ;; FIXME: Shouldn't this be an ERROR?
468 (format nil "<unknown reg: off=~W, sc=~A>" offset sc-name))))
469 (float-registers (format nil "FR~D" offset))
470 (xmm-registers (format nil "XMM~D" offset))
471 (stack (format nil "S~D" offset))
472 (constant (format nil "Const~D" offset))
473 (immediate-constant "Immed")
474 (noise (symbol-name (sc-name sc))))))
475 ;;; FIXME: Could this, and everything that uses it, be made #!+SB-SHOW?