delete ye olde FIXME relating to unbound variable warnings
[sbcl.git] / src / compiler / x86-64 / vm.lisp
1 ;;;; miscellaneous VM definition noise for the x86-64
2
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.
11
12 (in-package "SB!VM")
13
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 64))
17 \f
18 ;;;; register specs
19
20 (eval-when (:compile-toplevel :load-toplevel :execute)
21   (defvar *byte-register-names* (make-array 32 :initial-element nil))
22   (defvar *word-register-names* (make-array 32 :initial-element nil))
23   (defvar *dword-register-names* (make-array 32 :initial-element nil))
24   (defvar *qword-register-names* (make-array 32 :initial-element nil))
25   (defvar *float-register-names* (make-array 16 :initial-element nil)))
26
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))))))
46
47   ;; byte registers
48   ;;
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   ;;
53   ;; High-byte are registers disabled on AMD64, since they can't be
54   ;; encoded for an op that has a REX-prefix and we don't want to
55   ;; add special cases into the code generation. The overlap doesn't
56   ;; therefore exist anymore, but the numbering hasn't been changed
57   ;; to reflect this.
58   (defreg al    0 :byte)
59   (defreg cl    2 :byte)
60   (defreg dl    4 :byte)
61   (defreg bl    6 :byte)
62   (defreg sil  12 :byte)
63   (defreg dil  14 :byte)
64   (defreg r8b  16 :byte)
65   (defreg r9b  18 :byte)
66   (defreg r10b 20 :byte)
67   (defreg r11b 22 :byte)
68   (defreg r12b 24 :byte)
69   (defreg r13b 26 :byte)
70   (defreg r14b 28 :byte)
71   (defreg r15b 30 :byte)
72   (defregset *byte-regs*
73       al cl dl bl sil dil r8b r9b r10b
74       #+nil r11b #+nil r12b r13b r14b r15b)
75
76   ;; word registers
77   (defreg ax 0 :word)
78   (defreg cx 2 :word)
79   (defreg dx 4 :word)
80   (defreg bx 6 :word)
81   (defreg sp 8 :word)
82   (defreg bp 10 :word)
83   (defreg si 12 :word)
84   (defreg di 14 :word)
85   (defreg r8w  16 :word)
86   (defreg r9w  18 :word)
87   (defreg r10w 20 :word)
88   (defreg r11w 22 :word)
89   (defreg r12w 24 :word)
90   (defreg r13w 26 :word)
91   (defreg r14w 28 :word)
92   (defreg r15w 30 :word)
93   (defregset *word-regs* ax cx dx bx si di r8w r9w r10w
94              #+nil r11w #+nil r12w r13w r14w r15w)
95
96   ;; double word registers
97   (defreg eax 0 :dword)
98   (defreg ecx 2 :dword)
99   (defreg edx 4 :dword)
100   (defreg ebx 6 :dword)
101   (defreg esp 8 :dword)
102   (defreg ebp 10 :dword)
103   (defreg esi 12 :dword)
104   (defreg edi 14 :dword)
105   (defreg r8d  16 :dword)
106   (defreg r9d  18 :dword)
107   (defreg r10d 20 :dword)
108   (defreg r11d 22 :dword)
109   (defreg r12d 24 :dword)
110   (defreg r13d 26 :dword)
111   (defreg r14d 28 :dword)
112   (defreg r15d 30 :dword)
113   (defregset *dword-regs* eax ecx edx ebx esi edi r8d r9d r10d
114              #+nil r11d #+nil r12w r13d r14d r15d)
115
116   ;; quadword registers
117   (defreg rax 0 :qword)
118   (defreg rcx 2 :qword)
119   (defreg rdx 4 :qword)
120   (defreg rbx 6 :qword)
121   (defreg rsp 8 :qword)
122   (defreg rbp 10 :qword)
123   (defreg rsi 12 :qword)
124   (defreg rdi 14 :qword)
125   (defreg r8  16 :qword)
126   (defreg r9  18 :qword)
127   (defreg r10 20 :qword)
128   (defreg r11 22 :qword)
129   (defreg r12 24 :qword)
130   (defreg r13 26 :qword)
131   (defreg r14 28 :qword)
132   (defreg r15 30 :qword)
133   ;; for no good reason at the time, r12 and r13 were missed from the
134   ;; list of qword registers.  However
135   ;; <jsnell> r13 is already used as temporary [#lisp irc 2005/01/30]
136   ;; and we're now going to use r12 for the struct thread*
137   ;;
138   ;; Except that now we use r11 instead of r13 as the temporary,
139   ;; since it's got a more compact encoding than r13, and experimentally
140   ;; the temporary gets used more than the other registers that are never
141   ;; wired. -- JES, 2005-11-02
142   (defregset *qword-regs* rax rcx rdx rbx rsi rdi
143              r8 r9 r10 #+nil r11 #+nil r12 r13  r14 r15)
144
145   ;; floating point registers
146   (defreg float0 0 :float)
147   (defreg float1 1 :float)
148   (defreg float2 2 :float)
149   (defreg float3 3 :float)
150   (defreg float4 4 :float)
151   (defreg float5 5 :float)
152   (defreg float6 6 :float)
153   (defreg float7 7 :float)
154   (defreg float8 8 :float)
155   (defreg float9 9 :float)
156   (defreg float10 10 :float)
157   (defreg float11 11 :float)
158   (defreg float12 12 :float)
159   (defreg float13 13 :float)
160   (defreg float14 14 :float)
161   (defreg float15 15 :float)
162   (defregset *float-regs* float0 float1 float2 float3 float4 float5 float6 float7
163              float8 float9 float10 float11 float12 float13 float14 float15)
164
165   ;; registers used to pass arguments
166   ;;
167   ;; the number of arguments/return values passed in registers
168   (def!constant  register-arg-count 3)
169   ;; names and offsets for registers used to pass arguments
170   (eval-when (:compile-toplevel :load-toplevel :execute)
171     (defparameter *register-arg-names* '(rdx rdi rsi)))
172   (defregset    *register-arg-offsets* rdx rdi rsi)
173   #!-win32
174   (defregset    *c-call-register-arg-offsets* rdi rsi rdx rcx r8 r9)
175   #!+win32
176   (defregset    *c-call-register-arg-offsets* rcx rdx r8 r9))
177 \f
178 ;;;; SB definitions
179
180 ;;; There are 16 registers really, but we consider them 32 in order to
181 ;;; describe the overlap of byte registers. The only thing we need to
182 ;;; represent is what registers overlap. Therefore, we consider bytes
183 ;;; to take one unit, and [dq]?words to take two. We don't need to
184 ;;; tell the difference between [dq]?words, because you can't put two
185 ;;; words in a dword register.
186 (define-storage-base registers :finite :size 32)
187
188 (define-storage-base float-registers :finite :size 16)
189
190 (define-storage-base stack :unbounded :size 8)
191 (define-storage-base constant :non-packed)
192 (define-storage-base immediate-constant :non-packed)
193 (define-storage-base noise :unbounded :size 2)
194 \f
195 ;;;; SC definitions
196
197 ;;; a handy macro so we don't have to keep changing all the numbers whenever
198 ;;; we insert a new storage class
199 ;;;
200 (defmacro !define-storage-classes (&rest classes)
201   (collect ((forms))
202     (let ((index 0))
203       (dolist (class classes)
204         (let* ((sc-name (car class))
205                (constant-name (symbolicate sc-name "-SC-NUMBER")))
206           (forms `(define-storage-class ,sc-name ,index
207                     ,@(cdr class)))
208           (forms `(def!constant ,constant-name ,index))
209           (incf index))))
210     `(progn
211        ,@(forms))))
212
213 ;;; The DEFINE-STORAGE-CLASS call for CATCH-BLOCK refers to the size
214 ;;; of CATCH-BLOCK. The size of CATCH-BLOCK isn't calculated until
215 ;;; later in the build process, and the calculation is entangled with
216 ;;; code which has lots of predependencies, including dependencies on
217 ;;; the prior call of DEFINE-STORAGE-CLASS. The proper way to
218 ;;; unscramble this would be to untangle the code, so that the code
219 ;;; which calculates the size of CATCH-BLOCK can be separated from the
220 ;;; other lots-of-dependencies code, so that the code which calculates
221 ;;; the size of CATCH-BLOCK can be executed early, so that this value
222 ;;; is known properly at this point in compilation. However, that
223 ;;; would be a lot of editing of code that I (WHN 19990131) can't test
224 ;;; until the project is complete. So instead, I set the correct value
225 ;;; by hand here (a sort of nondeterministic guess of the right
226 ;;; answer:-) and add an assertion later, after the value is
227 ;;; calculated, that the original guess was correct.
228 ;;;
229 ;;; (What a KLUDGE! Anyone who wants to come in and clean up this mess
230 ;;; has my gratitude.) (FIXME: Maybe this should be me..)
231 (eval-when (:compile-toplevel :load-toplevel :execute)
232   (def!constant kludge-nondeterministic-catch-block-size 5))
233
234 (!define-storage-classes
235
236   ;; non-immediate constants in the constant pool
237   (constant constant)
238
239   (fp-single-zero immediate-constant)
240   (fp-double-zero immediate-constant)
241   (fp-complex-single-zero immediate-constant)
242   (fp-complex-double-zero immediate-constant)
243
244   (fp-single-immediate immediate-constant)
245   (fp-double-immediate immediate-constant)
246   (fp-complex-single-immediate immediate-constant)
247   (fp-complex-double-immediate immediate-constant)
248
249   #!+sb-simd-pack (int-sse-immediate immediate-constant)
250   #!+sb-simd-pack (double-sse-immediate immediate-constant)
251   #!+sb-simd-pack (single-sse-immediate immediate-constant)
252
253   (immediate immediate-constant)
254
255   ;;
256   ;; the stacks
257   ;;
258
259   ;; the control stack
260   (control-stack stack)                 ; may be pointers, scanned by GC
261
262   ;; the non-descriptor stacks
263   ;; XXX alpha backend has :element-size 2 :alignment 2 in these entries
264   (signed-stack stack)                  ; (signed-byte 64)
265   (unsigned-stack stack)                ; (unsigned-byte 64)
266   (character-stack stack)               ; non-descriptor characters.
267   (sap-stack stack)                     ; System area pointers.
268   (single-stack stack)                  ; single-floats
269   (double-stack stack)
270   (complex-single-stack stack)  ; complex-single-floats
271   (complex-double-stack stack :element-size 2)  ; complex-double-floats
272   #!+sb-simd-pack
273   (int-sse-stack stack :element-size 2)
274   #!+sb-simd-pack
275   (double-sse-stack stack :element-size 2)
276   #!+sb-simd-pack
277   (single-sse-stack stack :element-size 2)
278
279   ;;
280   ;; magic SCs
281   ;;
282
283   (ignore-me noise)
284
285   ;;
286   ;; things that can go in the integer registers
287   ;;
288
289   ;; On the X86, we don't have to distinguish between descriptor and
290   ;; non-descriptor registers, because of the conservative GC.
291   ;; Therefore, we use different scs only to distinguish between
292   ;; descriptor and non-descriptor values and to specify size.
293
294   ;; immediate descriptor objects. Don't have to be seen by GC, but nothing
295   ;; bad will happen if they are. (fixnums, characters, header values, etc).
296   (any-reg registers
297            :locations #.*qword-regs*
298            :element-size 2 ; I think this is for the al/ah overlap thing
299            :constant-scs (immediate)
300            :save-p t
301            :alternate-scs (control-stack))
302
303   ;; pointer descriptor objects -- must be seen by GC
304   (descriptor-reg registers
305                   :locations #.*qword-regs*
306                   :element-size 2
307 ;                 :reserve-locations (#.eax-offset)
308                   :constant-scs (constant immediate)
309                   :save-p t
310                   :alternate-scs (control-stack))
311
312   ;; non-descriptor characters
313   (character-reg registers
314                  :locations #!-sb-unicode #.*byte-regs*
315                             #!+sb-unicode #.*qword-regs*
316                  #!+sb-unicode #!+sb-unicode
317                  :element-size 2
318                  #!-sb-unicode #!-sb-unicode
319                  :reserve-locations (#.al-offset)
320                  :constant-scs (immediate)
321                  :save-p t
322                  :alternate-scs (character-stack))
323
324   ;; non-descriptor SAPs (arbitrary pointers into address space)
325   (sap-reg registers
326            :locations #.*qword-regs*
327            :element-size 2
328 ;          :reserve-locations (#.eax-offset)
329            :constant-scs (immediate)
330            :save-p t
331            :alternate-scs (sap-stack))
332
333   ;; non-descriptor (signed or unsigned) numbers
334   (signed-reg registers
335               :locations #.*qword-regs*
336               :element-size 2
337               :constant-scs (immediate)
338               :save-p t
339               :alternate-scs (signed-stack))
340   (unsigned-reg registers
341                 :locations #.*qword-regs*
342                 :element-size 2
343                 :constant-scs (immediate)
344                 :save-p t
345                 :alternate-scs (unsigned-stack))
346
347   ;; miscellaneous objects that must not be seen by GC. Used only as
348   ;; temporaries.
349   (word-reg registers
350             :locations #.*word-regs*
351             :element-size 2
352             )
353   (dword-reg registers
354             :locations #.*dword-regs*
355             :element-size 2
356             )
357   (byte-reg registers
358             :locations #.*byte-regs*
359             )
360
361   ;; that can go in the floating point registers
362
363   ;; non-descriptor SINGLE-FLOATs
364   (single-reg float-registers
365               :locations #.*float-regs*
366               :constant-scs (fp-single-zero fp-single-immediate)
367               :save-p t
368               :alternate-scs (single-stack))
369
370   ;; non-descriptor DOUBLE-FLOATs
371   (double-reg float-registers
372               :locations #.*float-regs*
373               :constant-scs (fp-double-zero fp-double-immediate)
374               :save-p t
375               :alternate-scs (double-stack))
376
377   (complex-single-reg float-registers
378                       :locations #.*float-regs*
379                       :constant-scs (fp-complex-single-zero fp-complex-single-immediate)
380                       :save-p t
381                       :alternate-scs (complex-single-stack))
382
383   (complex-double-reg float-registers
384                       :locations #.*float-regs*
385                       :constant-scs (fp-complex-double-zero fp-complex-double-immediate)
386                       :save-p t
387                       :alternate-scs (complex-double-stack))
388
389   ;; temporary only
390   #!+sb-simd-pack
391   (sse-reg float-registers
392            :locations #.*float-regs*)
393   ;; regular values
394   #!+sb-simd-pack
395   (int-sse-reg float-registers
396                :locations #.*float-regs*
397                :constant-scs (int-sse-immediate)
398                :save-p t
399                :alternate-scs (int-sse-stack))
400   #!+sb-simd-pack
401   (double-sse-reg float-registers
402                   :locations #.*float-regs*
403                   :constant-scs (double-sse-immediate)
404                   :save-p t
405                   :alternate-scs (double-sse-stack))
406   #!+sb-simd-pack
407   (single-sse-reg float-registers
408                   :locations #.*float-regs*
409                   :constant-scs (single-sse-immediate)
410                   :save-p t
411                   :alternate-scs (single-sse-stack))
412
413   ;; a catch or unwind block
414   (catch-block stack :element-size kludge-nondeterministic-catch-block-size))
415
416 (eval-when (:compile-toplevel :load-toplevel :execute)
417 (defparameter *byte-sc-names*
418   '(#!-sb-unicode character-reg byte-reg #!-sb-unicode character-stack))
419 (defparameter *word-sc-names* '(word-reg))
420 (defparameter *dword-sc-names* '(dword-reg))
421 (defparameter *qword-sc-names*
422   '(any-reg descriptor-reg sap-reg signed-reg unsigned-reg control-stack
423     signed-stack unsigned-stack sap-stack single-stack
424     #!+sb-unicode character-reg #!+sb-unicode character-stack constant))
425 ;;; added by jrd. I guess the right thing to do is to treat floats
426 ;;; as a separate size...
427 ;;;
428 ;;; These are used to (at least) determine operand size.
429 (defparameter *float-sc-names* '(single-reg))
430 (defparameter *double-sc-names* '(double-reg double-stack))
431 (defparameter *complex-sc-names* '(complex-single-reg complex-single-stack
432                                    complex-double-reg complex-double-stack))
433 #!+sb-simd-pack
434 (defparameter *oword-sc-names* '(sse-reg int-sse-reg single-sse-reg double-sse-reg
435                                  sse-stack int-sse-stack single-sse-stack double-sse-stack))
436 ) ; EVAL-WHEN
437 \f
438 ;;;; miscellaneous TNs for the various registers
439
440 (macrolet ((def-misc-reg-tns (sc-name &rest reg-names)
441              (collect ((forms))
442                       (dolist (reg-name reg-names)
443                         (let ((tn-name (symbolicate reg-name "-TN"))
444                               (offset-name (symbolicate reg-name "-OFFSET")))
445                           ;; FIXME: It'd be good to have the special
446                           ;; variables here be named with the *FOO*
447                           ;; convention.
448                           (forms `(defparameter ,tn-name
449                                     (make-random-tn :kind :normal
450                                                     :sc (sc-or-lose ',sc-name)
451                                                     :offset
452                                                     ,offset-name)))))
453                       `(progn ,@(forms)))))
454
455   (def-misc-reg-tns unsigned-reg rax rbx rcx rdx rbp rsp rdi rsi
456                     r8 r9 r10 r11 r12 r13 r14 r15)
457   (def-misc-reg-tns dword-reg eax ebx ecx edx ebp esp edi esi
458                     r8d r9d r10d r11d r12d r13d r14d r15d)
459   (def-misc-reg-tns word-reg ax bx cx dx bp sp di si
460                     r8w r9w r10w r11w r12w r13w r14w r15w)
461   (def-misc-reg-tns byte-reg al cl dl bl sil dil r8b r9b r10b
462                     r11b r12b r13b r14b r15b)
463   (def-misc-reg-tns single-reg
464       float0 float1 float2 float3 float4 float5 float6 float7
465       float8 float9 float10 float11 float12 float13 float14 float15))
466
467 (defun reg-in-size (tn size)
468   (make-random-tn :kind :normal
469                   :sc (sc-or-lose
470                        (ecase size
471                          (:byte 'byte-reg)
472                          (:word 'word-reg)
473                          (:dword 'dword-reg)
474                          (:qword 'unsigned-reg)))
475                   :offset (tn-offset tn)))
476
477 ;; A register that's never used by the code generator, and can therefore
478 ;; be used as an assembly temporary in cases where a VOP :TEMPORARY can't
479 ;; be used.
480 (defparameter temp-reg-tn r11-tn)
481
482 ;;; TNs for registers used to pass arguments
483 (defparameter *register-arg-tns*
484   (mapcar (lambda (register-arg-name)
485             (symbol-value (symbolicate register-arg-name "-TN")))
486           *register-arg-names*))
487
488 (defparameter thread-base-tn
489   (make-random-tn :kind :normal :sc (sc-or-lose 'unsigned-reg )
490                   :offset r12-offset))
491
492 ;;; If value can be represented as an immediate constant, then return
493 ;;; the appropriate SC number, otherwise return NIL.
494 (!def-vm-support-routine immediate-constant-sc (value)
495   (typecase value
496     ((or (integer #.sb!xc:most-negative-fixnum #.sb!xc:most-positive-fixnum)
497          character)
498      (sc-number-or-lose 'immediate))
499     (symbol
500      (when (static-symbol-p value)
501        (sc-number-or-lose 'immediate)))
502     (single-float
503        (sc-number-or-lose
504         (if (eql value 0f0) 'fp-single-zero 'fp-single-immediate)))
505     (double-float
506        (sc-number-or-lose
507         (if (eql value 0d0) 'fp-double-zero 'fp-double-immediate)))
508     ((complex single-float)
509        (sc-number-or-lose
510         (if (eql value #c(0f0 0f0))
511             'fp-complex-single-zero
512             'fp-complex-single-immediate)))
513     ((complex double-float)
514        (sc-number-or-lose
515         (if (eql value #c(0d0 0d0))
516             'fp-complex-double-zero
517             'fp-complex-double-immediate)))
518     #!+sb-simd-pack
519     (#+sb-xc-host nil
520      #-sb-xc-host (simd-pack double-float)
521         (sc-number-or-lose 'double-sse-immediate))
522     #!+sb-simd-pack
523     (#+sb-xc-host nil
524      #-sb-xc-host (simd-pack single-float)
525      (sc-number-or-lose 'single-sse-immediate))
526     #!+sb-simd-pack
527     (#+sb-xc-host nil
528      #-sb-xc-host simd-pack
529      (sc-number-or-lose 'int-sse-immediate))))
530
531 (!def-vm-support-routine boxed-immediate-sc-p (sc)
532   (eql sc (sc-number-or-lose 'immediate)))
533 \f
534 ;;;; miscellaneous function call parameters
535
536 ;;; Offsets of special stack frame locations relative to RBP.
537 ;;;
538 ;;; Consider the standard prologue PUSH RBP; MOV RBP, RSP: the return
539 ;;; address is at RBP+8, the old control stack frame pointer is at
540 ;;; RBP, the magic 3rd slot is at RBP-8. Then come the locals from
541 ;;; RBP-16 on.
542 (def!constant return-pc-save-offset 0)
543 (def!constant ocfp-save-offset 1)
544 (def!constant code-save-offset 2)
545 ;;; Let SP be the stack pointer before CALLing, and FP is the frame
546 ;;; pointer after the standard prologue. SP +
547 ;;; FRAME-WORD-OFFSET(SP->FP-OFFSET + I) = FP + FRAME-WORD-OFFSET(I).
548 (def!constant sp->fp-offset 2)
549
550 (declaim (inline frame-word-offset))
551 (defun frame-word-offset (index)
552   (- (1- index)))
553
554 (declaim (inline frame-byte-offset))
555 (defun frame-byte-offset (index)
556   (* (frame-word-offset index) n-word-bytes))
557
558 (def!constant lra-save-offset return-pc-save-offset) ; ?
559
560 ;;; This is used by the debugger.
561 (def!constant single-value-return-byte-offset 3)
562 \f
563 ;;; This function is called by debug output routines that want a pretty name
564 ;;; for a TN's location. It returns a thing that can be printed with PRINC.
565 (!def-vm-support-routine location-print-name (tn)
566   (declare (type tn tn))
567   (let* ((sc (tn-sc tn))
568          (sb (sb-name (sc-sb sc)))
569          (offset (tn-offset tn)))
570     (ecase sb
571       (registers
572        (let* ((sc-name (sc-name sc))
573               (name-vec (cond ((member sc-name *byte-sc-names*)
574                                *byte-register-names*)
575                               ((member sc-name *word-sc-names*)
576                                *word-register-names*)
577                               ((member sc-name *dword-sc-names*)
578                                *dword-register-names*)
579                               ((member sc-name *qword-sc-names*)
580                                *qword-register-names*))))
581          (or (and name-vec
582                   (< -1 offset (length name-vec))
583                   (svref name-vec offset))
584              ;; FIXME: Shouldn't this be an ERROR?
585              (format nil "<unknown reg: off=~W, sc=~A>" offset sc-name))))
586       (float-registers (format nil "FLOAT~D" offset))
587       (stack (format nil "S~D" offset))
588       (constant (format nil "Const~D" offset))
589       (immediate-constant "Immed")
590       (noise (symbol-name (sc-name sc))))))
591 ;;; FIXME: Could this, and everything that uses it, be made #!+SB-SHOW?
592
593 (defun dwords-for-quad (value)
594   (let* ((lo (logand value (1- (ash 1 32))))
595          (hi (ash value -32)))
596     (values lo hi)))
597
598 (defun words-for-dword (value)
599   (let* ((lo (logand value (1- (ash 1 16))))
600          (hi (ash value -16)))
601     (values lo hi)))
602
603 (def!constant cfp-offset rbp-offset) ; pfw - needed by stuff in /code
604
605 (!def-vm-support-routine combination-implementation-style (node)
606   (declare (type sb!c::combination node))
607   (flet ((valid-funtype (args result)
608            (sb!c::valid-fun-use node
609                                 (sb!c::specifier-type
610                                  `(function ,args ,result)))))
611     (case (sb!c::combination-fun-source-name node)
612       (logtest
613        (cond
614          ((or (valid-funtype '(fixnum fixnum) '*)
615               ;; todo: nothing prevents this from testing an unsigned word against
616               ;; a signed word, except for the mess of VOPs it would demand
617               (valid-funtype '((signed-byte 64) (signed-byte 64)) '*)
618               (valid-funtype '((unsigned-byte 64) (unsigned-byte 64)) '*))
619           (values :maybe nil))
620          (t
621           (values :default nil))))
622       (logbitp
623        (cond
624          ((or (and (valid-funtype '#.`((integer 0 ,(- 63 n-fixnum-tag-bits))
625                                        fixnum) '*)
626                    (sb!c::constant-lvar-p
627                     (first (sb!c::basic-combination-args node))))
628               (valid-funtype '((integer 0 63) (signed-byte 64)) '*)
629               (valid-funtype '((integer 0 63) (unsigned-byte 64)) '*))
630           (values :transform '(lambda (index integer)
631                                (%logbitp integer index))))
632          (t
633           (values :default nil))))
634       (t
635        (values :default nil)))))