source: trunk/source/compiler/X86/x862.lisp @ 11451

Last change on this file since 11451 was 11451, checked in by rme, 13 years ago

In general aref/aset of 2/3-d arrays, check for array dimension of *
when doing a typed operation.

(This is kind of a follow-on to r11286/r11287)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 437.3 KB
Line 
1;;;-*-Mode: LISP; Package: CCL -*-
2;;;
3;;;   Copyright (C) 2005, Clozure Associates
4;;;   This file is part of OpenMCL. 
5;;;
6;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
7;;;   License , known as the LLGPL and distributed with OpenMCL as the
8;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
9;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
10;;;   conflict, the preamble takes precedence. 
11;;;
12;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
13;;;
14;;;   The LLGPL is also available online at
15;;;   http://opensource.franz.com/preamble.html
16
17(in-package "CCL")
18
19(eval-when (:compile-toplevel :execute)
20  (require "NXENV")
21  (require "X8632ENV")
22  (require "X8664ENV"))
23
24(eval-when (:load-toplevel :execute :compile-toplevel)
25  (require "X86-BACKEND"))
26
27(defparameter *x862-debug-mask* 0)
28(defconstant x862-debug-verbose-bit 0)
29(defconstant x862-debug-vinsns-bit 1)
30(defconstant x862-debug-lcells-bit 2)
31(defparameter *x862-target-lcell-size* 0)
32(defparameter *x862-target-node-size* 0)
33(defparameter *x862-target-dnode-size* 0)
34(defparameter *x862-target-fixnum-shift* 0)
35(defparameter *x862-target-node-shift* 0)
36(defparameter *x862-target-bits-in-word* 0)
37(defparameter *x862-target-num-arg-regs* 0)
38(defparameter *x862-target-num-save-regs* 0)
39(defparameter *x862-target-half-fixnum-type* nil)
40
41(defparameter *x862-operator-supports-u8-target* ())
42(defparameter *x862-operator-supports-push* ())
43(defparameter *x862-tos-reg* ())
44
45;; probably should be elsewhere
46
47(defmacro with-additional-imm-reg ((&rest reserved) &body body)
48  (let ((node (gensym))
49        (bit (gensym)))
50    `(target-arch-case
51      (:x8632
52       (with-node-target (,@reserved) ,node
53         (let* ((,bit (ash 1 (hard-regspec-value ,node)))
54                (*backend-node-temps* (logandc2 *backend-node-temps* ,bit))
55                (*available-backend-node-temps* (logandc2 *available-backend-node-temps* ,bit))
56                (*backend-imm-temps* (logior *backend-imm-temps* ,bit))
57                (*available-backend-imm-temps* (logior *available-backend-imm-temps* ,bit)))
58           (! mark-as-imm ,node)
59           ,@body
60           (! mark-as-node ,node))))
61      (:x8664
62       (progn
63         ,@body)))))
64
65 
66(defun x862-immediate-operand (x)
67  (if (eq (acode-operator x) (%nx1-operator immediate))
68    (cadr x)
69    (compiler-bug "not an immediate: ~s" x)))
70
71(defmacro with-x86-p2-declarations (declsform &body body)
72  `(let* ((*x862-tail-allow* *x862-tail-allow*)
73          (*x862-reckless* *x862-reckless*)
74          (*x862-open-code-inline* *x862-open-code-inline*)
75          (*x862-trust-declarations* *x862-trust-declarations*)
76          (*x862-full-safety* *x862-full-safety*))
77     (x862-decls ,declsform)
78     ,@body))
79
80
81(defmacro with-x86-local-vinsn-macros ((segvar &optional vreg-var xfer-var) &body body)
82  (declare (ignorable xfer-var))
83  (let* ((template-name-var (gensym))
84         (template-temp (gensym))
85         (args-var (gensym))
86         (labelnum-var (gensym))
87         (retvreg-var (gensym))
88         (label-var (gensym)))
89    `(macrolet ((! (,template-name-var &rest ,args-var)                 
90                  (let* ((,template-temp (get-vinsn-template-cell ,template-name-var (backend-p2-vinsn-templates *target-backend*))))
91                    (unless ,template-temp
92                      (warn "VINSN \"~A\" not defined" ,template-name-var))
93                    `(prog1
94                      (%emit-vinsn ,',segvar ',,template-name-var (backend-p2-vinsn-templates *target-backend*) ,@,args-var)
95                      (setq *x862-tos-reg* nil)))))
96       (macrolet ((<- (,retvreg-var)
97                    `(x862-copy-register ,',segvar ,',vreg-var ,,retvreg-var))
98                  (@  (,labelnum-var)
99                    `(backend-gen-label ,',segvar ,,labelnum-var))
100                  (@= (,labelnum-var)
101                    `(x862-emit-aligned-label ,',segvar ,,labelnum-var))
102                  (-> (,label-var)
103                    `(! jump (aref *backend-labels* ,,label-var)))
104                  (^ (&rest branch-args)
105                    `(x862-branch ,',segvar ,',xfer-var ,@branch-args))
106                  (? (&key (class :gpr)
107                          (mode :lisp))
108                   (let* ((class-val
109                           (ecase class
110                             (:gpr hard-reg-class-gpr)
111                             (:fpr hard-reg-class-fpr)
112                             (:crf hard-reg-class-crf)))
113                          (mode-val-or-form
114                           (if (eq class :gpr)
115                             (if (member mode '(:natural :signed-natural))
116                               `(gpr-mode-name-value ,mode)
117                               (gpr-mode-name-value mode))
118                             (if (eq class :fpr)
119                               (if (eq mode :single-float)
120                                 hard-reg-class-fpr-mode-single
121                                 hard-reg-class-fpr-mode-double)
122                               0))))
123                     `(make-unwired-lreg nil
124                       :class ,class-val
125                       :mode ,mode-val-or-form)))
126                  ($ (reg &key (class :gpr) (mode :lisp))
127                   (let* ((class-val
128                           (ecase class
129                             (:gpr hard-reg-class-gpr)
130                             (:fpr hard-reg-class-fpr)
131                             (:crf hard-reg-class-crf)))
132                          (mode-val-or-form
133                           (if (eq class :gpr)
134                             (if (member mode '(:natural :signed-natural))
135                               `(gpr-mode-name-value ,mode)
136                               (gpr-mode-name-value mode))
137                             (if (eq class :fpr)
138                               (if (eq mode :single-float)
139                                 hard-reg-class-fpr-mode-single
140                                 hard-reg-class-fpr-mode-double)
141                               0))))
142                     `(make-wired-lreg ,reg
143                       :class ,class-val
144                       :mode ,mode-val-or-form))))
145         ,@body))))
146
147
148
149(defvar *x86-current-context-annotation* nil)
150(defvar *x862-woi* nil)
151(defvar *x862-open-code-inline* nil)
152(defvar *x862-register-restore-count* 0)
153(defvar *x862-register-restore-ea* nil)
154(defvar *x862-compiler-register-save-label* nil)
155(defvar *x862-valid-register-annotations* 0)
156(defvar *x862-register-annotation-types* nil)
157(defvar *x862-register-ea-annotations* nil)
158(defvar *x862-constant-alist* nil)
159(defvar *x862-double-float-constant-alist* nil)
160(defvar *x862-single-float-constant-alist* nil)
161
162(defparameter *x862-tail-call-aliases*
163  ()
164  #| '((%call-next-method . (%tail-call-next-method . 1))) |#
165 
166)
167
168(defvar *x862-popreg-labels* nil)
169(defvar *x862-popj-labels* nil)
170(defvar *x862-valret-labels* nil)
171(defvar *x862-nilret-labels* nil)
172
173(defvar *x862-icode* nil)
174(defvar *x862-undo-stack* nil)
175(defvar *x862-undo-because* nil)
176
177
178(defvar *x862-cur-afunc* nil)
179(defvar *x862-vstack* 0)
180(defvar *x862-cstack* 0)
181(defvar *x862-undo-count* 0)
182(defvar *x862-returning-values* nil)
183(defvar *x862-vcells* nil)
184(defvar *x862-fcells* nil)
185(defvar *x862-entry-vsp-saved-p* nil)
186
187(defvar *x862-entry-label* nil)
188(defvar *x862-tail-label* nil)
189(defvar *x862-tail-vsp* nil)
190(defvar *x862-tail-nargs* nil)
191(defvar *x862-tail-allow* t)
192(defvar *x862-reckless* nil)
193(defvar *x862-full-safety* nil)
194(defvar *x862-trust-declarations* nil)
195(defvar *x862-entry-vstack* nil)
196(defvar *x862-fixed-nargs* nil)
197(defvar *x862-need-nargs* t)
198
199(defparameter *x862-inhibit-register-allocation* nil)
200(defvar *x862-record-symbols* nil)
201(defvar *x862-recorded-symbols* nil)
202(defvar *x862-emitted-source-notes* nil)
203
204(defvar *x862-result-reg* x8664::arg_z)
205
206(defvar *x862-arg-z* nil)
207(defvar *x862-arg-y* nil)
208(defvar *x862-imm0* nil)
209(defvar *x862-temp0* nil)
210(defvar *x862-temp1* nil)
211(defvar *x862-fn* nil)
212(defvar *x862-fname* nil)
213(defvar *x862-ra0* nil)
214
215(defvar *x862-allocptr* nil)
216
217(defvar *x862-fp0* nil)
218(defvar *x862-fp1* nil)
219
220(declaim (fixnum *x862-vstack* *x862-cstack*))
221
222 
223
224
225
226(defvar *x862-all-lcells* ())
227
228(defun x86-immediate-label (imm)
229  (or (cdr (assoc imm *x862-constant-alist* :test #'eq))
230      (let* ((lab (aref *backend-labels* (backend-get-next-label))))
231        (push (cons imm lab) *x862-constant-alist*)
232        lab)))
233
234(defun x86-double-float-constant-label (imm)
235  (or (cdr (assoc imm *x862-double-float-constant-alist*))
236      (let* ((lab (aref *backend-labels* (backend-get-next-label))))
237        (push (cons imm lab) *x862-double-float-constant-alist*)
238        lab)))
239
240(defun x86-single-float-constant-label (imm)
241  (or (cdr (assoc imm *x862-single-float-constant-alist*))
242      (let* ((lab (aref *backend-labels* (backend-get-next-label))))
243        (push (cons imm lab) *x862-single-float-constant-alist*)
244        lab)))
245
246
247(defun x862-free-lcells ()
248  (without-interrupts 
249   (let* ((prev (pool.data *lcell-freelist*)))
250     (dolist (r *x862-all-lcells*)
251       (setf (lcell-kind r) prev
252             prev r))
253     (setf (pool.data *lcell-freelist*) prev)
254     (setq *x862-all-lcells* nil))))
255
256(defun x862-note-lcell (c)
257  (push c *x862-all-lcells*)
258  c)
259
260(defvar *x862-top-vstack-lcell* ())
261(defvar *x862-bottom-vstack-lcell* ())
262
263(defun x862-new-lcell (kind parent width attributes info)
264  (x862-note-lcell (make-lcell kind parent width attributes info)))
265
266(defun x862-new-vstack-lcell (kind width attributes info)
267  (setq *x862-top-vstack-lcell* (x862-new-lcell kind *x862-top-vstack-lcell* width attributes info)))
268
269(defun x862-reserve-vstack-lcells (n)
270  (dotimes (i n) (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil)))
271
272(defun x862-vstack-mark-top ()
273  (x862-new-lcell :tos *x862-top-vstack-lcell* 0 0 nil))
274
275;;; Alist mapping VARs to lcells/lregs
276(defvar *x862-var-cells* ())
277
278(defun x862-note-var-cell (var cell)
279  ;(format t "~& ~s -> ~s" (var-name var) cell)
280  (push (cons var cell) *x862-var-cells*))
281
282(defun x862-note-top-cell (var)
283  (x862-note-var-cell var *x862-top-vstack-lcell*))
284
285(defun x862-lookup-var-cell (var)
286  (or (cdr (assq var *x862-var-cells*))
287      (and nil (warn "Cell not found for ~s" (var-name var)))))
288
289(defun x862-collect-lcells (kind &optional (bottom *x862-bottom-vstack-lcell*) (top *x862-top-vstack-lcell*))
290  (do* ((res ())
291        (cell top (lcell-parent cell)))
292       ((eq cell bottom) res)
293    (if (null cell)
294      (compiler-bug "Horrible compiler bug.")
295      (if (eq (lcell-kind cell) kind)
296        (push cell res)))))
297
298
299 
300;;; ensure that lcell's offset matches what we expect it to.
301;;; For bootstrapping.
302
303(defun x862-ensure-lcell-offset (c expected)
304  (if c (= (calc-lcell-offset c) expected) (zerop expected)))
305
306(defun x862-check-lcell-depth (&optional (context "wherever"))
307  (when (logbitp x862-debug-verbose-bit *x862-debug-mask*)
308    (let* ((depth (calc-lcell-depth *x862-top-vstack-lcell*)))
309      (or (= depth *x862-vstack*)
310          (warn "~a: lcell depth = ~d, vstack = ~d" context depth *x862-vstack*)))))
311
312(defun x862-do-lexical-reference (seg vreg ea)
313  (when vreg
314    (with-x86-local-vinsn-macros (seg vreg)
315      (if (eq vreg :push)
316        (if (memory-spec-p ea)
317          (if (addrspec-vcell-p ea)
318            (with-node-target () target
319              (x862-stack-to-register seg ea target)
320              (! vcell-ref target target)
321              (! vpush-register target))
322            (! vframe-push (memspec-frame-address-offset ea) *x862-vstack*))
323          (! vpush-register ea))
324        (if (memory-spec-p ea)
325          (ensuring-node-target (target vreg)
326            (progn
327              (x862-stack-to-register seg ea target)
328              (if (addrspec-vcell-p ea)
329                (! vcell-ref target target))))
330          (<- ea))))))
331
332(defun x862-do-lexical-setq (seg vreg ea valreg)
333  (with-x86-local-vinsn-macros (seg vreg)
334    (cond ((typep ea 'lreg)
335            (x862-copy-register seg ea valreg))
336          ((addrspec-vcell-p ea)     ; closed-over vcell
337           (x862-copy-register seg *x862-arg-z* valreg)
338           (let* ((gvector (target-arch-case (:x8632 x8632::temp0)
339                                             (:x8664 x8664::arg_x))))
340             (x862-stack-to-register seg ea gvector)
341             (x862-lri seg *x862-arg-y* 0)
342             (! call-subprim-3 *x862-arg-z* (subprim-name->offset '.SPgvset) gvector *x862-arg-y* *x862-arg-z*)))
343          ((memory-spec-p ea)    ; vstack slot
344           (x862-register-to-stack seg valreg ea))
345          (t
346           (x862-copy-register seg ea valreg)))
347    (when vreg
348      (<- valreg))))
349
350;;; ensure that next-method-var is heap-consed (if it's closed over.)
351;;; it isn't ever setqed, is it ?
352(defun x862-heap-cons-next-method-var (seg var)
353  (with-x86-local-vinsn-macros (seg)
354    (when (eq (ash 1 $vbitclosed)
355              (logand (logior (ash 1 $vbitclosed)
356                              (ash 1 $vbitcloseddownward))
357                      (the fixnum (nx-var-bits var))))
358      (let* ((ea (var-ea var))
359             (arg ($ *x862-arg-z*))
360             (result ($ *x862-arg-z*)))
361        (x862-do-lexical-reference seg arg ea)
362        (x862-set-nargs seg 1)
363        (! ref-constant ($ *x862-fname*) (x86-immediate-label (x862-symbol-entry-locative '%cons-magic-next-method-arg)))
364        (! call-known-symbol arg)
365        (x862-do-lexical-setq seg nil ea result)))))
366
367;;; If we change the order of operands in a binary comparison operation,
368;;; what should the operation change to ? (eg., (< X Y) means the same
369;;; thing as (> Y X)).
370(defparameter *x862-reversed-cr-bits*
371  (vector
372   nil                                  ;o ?
373   nil                                  ;no ?
374   x86::x86-a-bits                      ;b -> a
375   x86::x86-be-bits                     ;ae -> be
376   x86::x86-e-bits                      ;e->e
377   x86::x86-ne-bits                     ;ne->ne
378   x86::x86-ae-bits                     ;be->ae
379   x86::x86-b-bits                      ;a->b
380   nil                                  ;s ?
381   nil                                  ;ns ?
382   nil                                  ;pe ?
383   nil                                  ;po ?
384   x86::x86-g-bits                      ;l->g
385   x86::x86-le-bits                     ;ge->le
386   x86::x86-ge-bits                     ;le->ge
387   x86::x86-l-bits                      ;g->l
388   ))
389
390(defun x862-reverse-cr-bit (cr-bit)
391  (or (svref *x862-reversed-cr-bits* cr-bit)
392      (compiler-bug "Can't reverse CR bit ~d" cr-bit)))
393
394
395(defun acode-condition-to-x86-cr-bit (cond)
396  (condition-to-x86-cr-bit (cadr cond)))
397
398(defun condition-to-x86-cr-bit (cond)
399  (case cond
400    (:EQ (values x86::x86-e-bits t))
401    (:NE (values x86::x86-e-bits nil))
402    (:GT (values x86::x86-le-bits nil))
403    (:LE (values x86::x86-le-bits t))
404    (:LT (values x86::x86-l-bits t))
405    (:GE (values x86::x86-l-bits nil))))
406
407;;; Generate the start and end bits for a RLWINM instruction that
408;;; would be equivalent to to LOGANDing the constant with some value.
409;;; Return (VALUES NIL NIL) if the constant contains more than one
410;;; sequence of consecutive 1-bits, else bit indices.
411;;; The caller generally wants to treat the constant as an (UNSIGNED-BYTE 32);
412;;; since this uses LOGCOUNT and INTEGER-LENGTH to find the significant
413;;; bits, it ensures that the constant is a (SIGNED-BYTE 32) that has
414;;; the same least-significant 32 bits.
415(defun x862-mask-bits (constant)
416  (if (< constant 0) (setq constant (logand #xffffffff constant)))
417  (if (= constant #xffffffff)
418    (values 0 31)
419    (if (zerop constant)
420      (values nil nil)
421      (let* ((signed (if (and (logbitp 31 constant)
422                              (> constant 0))
423                       (- constant (ash 1 32))
424                       constant))
425             (count (logcount signed))
426             (len (integer-length signed))
427             (highbit (logbitp (the fixnum (1- len)) constant)))
428        (declare (fixnum count len))
429        (do* ((i 1 (1+ i))
430              (pos (- len 2) (1- pos)))
431             ((= i count)
432              (let* ((start (- 32 len))
433                     (end (+ count start)))
434                (declare (fixnum start end))
435                (if highbit
436                  (values start (the fixnum (1- end)))
437                  (values (logand 31 end)
438                          (the fixnum (1- start))))))
439          (declare (fixnum i pos))
440          (unless (eq (logbitp pos constant) highbit)
441            (return (values nil nil))))))))
442   
443
444(defun x862-ensure-binding-indices-for-vcells (vcells)
445  (dolist (cell vcells)
446    (ensure-binding-index (car cell)))
447  vcells)
448
449(defun x862-register-mask-byte (count)
450  (if (> count 0)
451    (logior
452     (ash 1 (- x8664::save0 8))
453     (if (> count 1)
454       (logior
455        (ash 1 (- x8664::save1 8))
456        (if (> count 2)
457          (logior
458           (ash 1 (- x8664::save2 8))
459           (if (> count 3)
460             (ash 1 (- x8664::save3 8))
461             0))
462          0))
463       0))
464    0))
465
466(defun x862-encode-register-save-ea (ea count)
467  (if (zerop count)
468    0 
469    (min (- (ash ea (- *x862-target-node-shift*)) count) #xff)))
470
471
472(defun x862-compile (afunc &optional lambda-form *x862-record-symbols*)
473  (progn
474    (dolist (a  (afunc-inner-functions afunc))
475      (unless (afunc-lfun a)
476        (x862-compile a 
477                      (if lambda-form (afunc-lambdaform a))
478                      *x862-record-symbols*))) ; always compile inner guys
479    (let* ((*x862-cur-afunc* afunc)
480           (*x862-returning-values* nil)
481           (*x86-current-context-annotation* nil)
482           (*x862-woi* nil)
483           (*next-lcell-id* -1)
484           (*x862-open-code-inline* nil)
485           (*x862-register-restore-count* nil)
486           (*x862-compiler-register-save-label* nil)
487           (*x862-valid-register-annotations* 0)
488           (*x862-register-ea-annotations* (x862-make-stack 16))
489           (*x862-register-restore-ea* nil)
490           (*x862-constant-alist* nil)
491           (*x862-double-float-constant-alist* nil)
492           (*x862-single-float-constant-alist* nil)
493           (*x862-vstack* 0)
494           (*x862-cstack* 0)
495           (*x86-lap-entry-offset* (target-arch-case
496                                    (:x8632 x8632::fulltag-misc)
497                                    (:x8664 x8664::fulltag-function)))
498           (*x862-result-reg* (target-arch-case
499                               (:x8632 x8632::arg_z)
500                               (:x8664 x8664::arg_z)))
501           (*x862-imm0* (target-arch-case (:x8632 x8632::imm0)
502                                          (:x8664 x8664::imm0)))
503           (*x862-arg-z* (target-arch-case (:x8632 x8632::arg_z)
504                                           (:x8664 x8664::arg_z)))
505           (*x862-arg-y* (target-arch-case (:x8632 x8632::arg_y)
506                                           (:x8664 x8664::arg_y)))
507           (*x862-temp0* (target-arch-case (:x8632 x8632::temp0)
508                                           (:x8664 x8664::temp0)))
509           (*x862-temp1* (target-arch-case (:x8632 x8632::temp1)
510                                           (:x8664 x8664::temp1)))
511           (*x862-fn* (target-arch-case (:x8632 x8632::fn)
512                                        (:x8664 x8664::fn)))
513           (*x862-fname* (target-arch-case (:x8632 x8632::fname)
514                                           (:x8664 x8664::fname)))
515           (*x862-ra0* (target-arch-case (:x8632 x8632::ra0)
516                                         (:x8664 x8664::ra0)))
517           (*x862-allocptr* (target-arch-case (:x8632 x8632::allocptr)
518                                              (:x8664 x8664::allocptr)))
519           (*x862-fp0* (target-arch-case (:x8632 x8632::fp0)
520                                         (:x8664 x8664::fp0)))
521           (*x862-fp1* (target-arch-case (:x8632 x8632::fp1)
522                                         (:x8664 x8664::fp1)))
523           (*x862-target-num-arg-regs* (target-arch-case
524                                        (:x8632 $numx8632argregs)
525                                        (:x8664  $numx8664argregs)))
526           (*x862-target-num-save-regs* (target-arch-case
527                                         (:x8632 $numx8632saveregs)
528                                         (:x8664  $numx8664saveregs)))
529           (*x862-target-lcell-size* (arch::target-lisp-node-size (backend-target-arch *target-backend*)))
530           (*x862-target-fixnum-shift* (arch::target-fixnum-shift (backend-target-arch *target-backend*)))
531           (*x862-target-node-shift* (arch::target-word-shift  (backend-target-arch *target-backend*)))
532           (*x862-target-bits-in-word* (arch::target-nbits-in-word (backend-target-arch *target-backend*)))
533           (*x862-target-node-size* *x862-target-lcell-size*)
534           (*x862-target-half-fixnum-type* `(signed-byte ,(- *x862-target-bits-in-word*
535                                                            (1+ *x862-target-fixnum-shift*))))
536           (*x862-target-dnode-size* (* 2 *x862-target-lcell-size*))
537           (*x862-tos-reg* nil)
538           (*x862-all-lcells* ())
539           (*x862-top-vstack-lcell* nil)
540           (*x862-bottom-vstack-lcell* (x862-new-vstack-lcell :bottom 0 0 nil))
541           (*x862-var-cells* nil)
542           (*backend-vinsns* (backend-p2-vinsn-templates *target-backend*))
543           (*backend-node-regs* (target-arch-case
544                                 (:x8632 x8632-node-regs)
545                                 (:x8664 x8664-node-regs)))
546           (*backend-node-temps* (target-arch-case
547                                  (:x8632 x8632-temp-node-regs)
548                                  (:x8664 x8664-temp-node-regs)))
549           (*available-backend-node-temps* (target-arch-case
550                                            (:x8632 x8632-temp-node-regs)
551                                            (:x8664 x8664-temp-node-regs)))
552           (*backend-imm-temps* (target-arch-case
553                                 (:x8632 x8632-imm-regs)
554                                 (:x8664 x8664-imm-regs)))
555           (*available-backend-imm-temps* (target-arch-case
556                                           (:x8632 x8632-imm-regs)
557                                           (:x8664 x8664-imm-regs)))
558           (*backend-crf-temps* (target-arch-case
559                                 (:x8632 x8632-cr-fields)
560                                 (:x8664 x8664-cr-fields)))
561           (*available-backend-crf-temps* (target-arch-case
562                                           (:x8632 x8632-cr-fields)
563                                           (:x8664 x8664-cr-fields)))
564           (*backend-fp-temps* (target-arch-case
565                                (:x8632 x8632-temp-fp-regs)
566                                (:x8664 x8664-temp-fp-regs)))
567           (*available-backend-fp-temps* (target-arch-case
568                                          (:x8632 x8632-temp-fp-regs)
569                                          (:x8664 x8664-temp-fp-regs)))
570           (bits 0)
571           (*logical-register-counter* -1)
572           (*backend-all-lregs* ())
573           (*x862-popj-labels* nil)
574           (*x862-popreg-labels* nil)
575           (*x862-valret-labels* nil)
576           (*x862-nilret-labels* nil)
577           (*x862-undo-count* 0)
578           (*backend-labels* (x862-make-stack 64 target::subtag-simple-vector))
579           (*x862-undo-stack* (x862-make-stack 64  target::subtag-simple-vector))
580           (*x862-undo-because* (x862-make-stack 64))
581           (*x862-entry-label* nil)
582           (*x862-tail-label* nil)
583           (*x862-tail-vsp* nil)
584           (*x862-tail-nargs* nil)
585           (*x862-inhibit-register-allocation* nil)
586           (*x862-tail-allow* t)
587           (*x862-reckless* nil)
588           (*x862-full-safety* nil)
589           (*x862-trust-declarations* t)
590           (*x862-entry-vstack* nil)
591           (*x862-fixed-nargs* nil)
592           (*x862-need-nargs* t)
593           (fname (afunc-name afunc))
594           (*x862-entry-vsp-saved-p* nil)
595           (*x862-vcells* (x862-ensure-binding-indices-for-vcells (afunc-vcells afunc)))
596           (*x862-fcells* (afunc-fcells afunc))
597           *x862-recorded-symbols*
598           (*x862-emitted-source-notes* '()))
599      (set-fill-pointer
600       *backend-labels*
601       (set-fill-pointer
602        *x862-undo-stack*
603        (set-fill-pointer 
604         *x862-undo-because*
605         0)))
606      (backend-get-next-label)          ; start @ label 1, 0 is confused with NIL in compound cd
607      (with-dll-node-freelist (vinsns *vinsn-freelist*)
608        (unwind-protect
609             (progn
610               (setq bits (x862-toplevel-form vinsns (make-wired-lreg *x862-result-reg*)
611                                              $backend-return (afunc-acode afunc)))
612               (do* ((constants *x862-constant-alist* (cdr constants)))
613                    ((null constants))
614                 (let* ((imm (caar constants)))
615                   (when (x862-symbol-locative-p imm)
616                     (setf (caar constants) (car imm)))))
617               (optimize-vinsns vinsns)
618               (when (logbitp x862-debug-vinsns-bit *x862-debug-mask*)
619                 (format t "~% vinsns for ~s (after generation)" (afunc-name afunc))
620                 (do-dll-nodes (v vinsns) (format t "~&~s" v))
621                 (format t "~%~%"))
622           
623               (with-dll-node-freelist ((frag-list make-frag-list) *frag-freelist*)
624                 (with-dll-node-freelist ((uuo-frag-list make-frag-list) *frag-freelist*)
625                 (let* ((*x86-lap-labels* nil)
626                        (instruction (x86::make-x86-instruction))
627                        (end-code-tag (gensym))
628                        (start-tag (gensym))
629                        (srt-tag (gensym))
630                        debug-info)
631                   (make-x86-lap-label end-code-tag)
632                   (target-arch-case
633                    (:x8664
634                     (x86-lap-directive frag-list :long `(ash (+ (- (:^ ,end-code-tag ) 8)
635                                                                 *x86-lap-entry-offset*) -3))
636                     (x86-lap-directive frag-list :byte 0) ;regsave PC
637                     (x86-lap-directive frag-list :byte 0) ;regsave ea
638                     (x86-lap-directive frag-list :byte 0)) ;regsave mask
639                    (:x8632
640                     (make-x86-lap-label start-tag)
641                     (make-x86-lap-label srt-tag)
642                     (x86-lap-directive frag-list :short `(ash (+ (- (:^ ,end-code-tag) 4)
643                                                                  *x86-lap-entry-offset*) -2))
644                     (emit-x86-lap-label frag-list start-tag)))
645                   (x862-expand-vinsns vinsns frag-list instruction uuo-frag-list)
646                   (when (or *x862-double-float-constant-alist*
647                             *x862-single-float-constant-alist*)
648                     (x86-lap-directive frag-list :align 3)
649                     (dolist (double-pair *x862-double-float-constant-alist*)
650                       (destructuring-bind (dfloat . lab) double-pair
651                         (setf (vinsn-label-info lab) (emit-x86-lap-label frag-list lab))
652                         (multiple-value-bind (high low)
653                             (x862-double-float-bits dfloat)
654                           (x86-lap-directive frag-list :long low)
655                           (x86-lap-directive frag-list :long high))))
656                     (dolist (single-pair *x862-single-float-constant-alist*)
657                       (destructuring-bind (sfloat . lab) single-pair
658                         (setf (vinsn-label-info lab) (emit-x86-lap-label frag-list lab))
659                         (let* ((val (single-float-bits sfloat)))
660                           (x86-lap-directive frag-list :long val)))))
661                   (target-arch-case
662                    (:x8632
663                     (x86-lap-directive frag-list :align 2)
664                     ;; start of self reference table
665                     (x86-lap-directive frag-list :long 0)
666                     (emit-x86-lap-label frag-list srt-tag)
667                     ;; make space for self-reference offsets
668                     (do-dll-nodes (frag frag-list)
669                       (dolist (reloc (frag-relocs frag))
670                         (when (eq (reloc-type reloc) :self)
671                           (x86-lap-directive frag-list :long 0))))
672                     (x86-lap-directive frag-list :long x8632::function-boundary-marker))
673                    (:x8664
674                     (x86-lap-directive frag-list :align 3)
675                     (x86-lap-directive frag-list :quad x8664::function-boundary-marker)))
676
677                   (emit-x86-lap-label frag-list end-code-tag)
678                   
679                   (dolist (c (reverse *x862-constant-alist*))
680                     (let* ((vinsn-label (cdr c)))
681                       (or (vinsn-label-info vinsn-label)
682                           (setf (vinsn-label-info vinsn-label)
683                                 (find-or-create-x86-lap-label
684                                  vinsn-label)))
685                       (emit-x86-lap-label frag-list vinsn-label)
686                       (target-arch-case
687                        (:x8632
688                         (x86-lap-directive frag-list :long 0))
689                        (:x8664
690                         (x86-lap-directive frag-list :quad 0)))))
691
692                   (if (logbitp $fbitnonnullenv (the fixnum (afunc-bits afunc)))
693                     (setq bits (+ bits (ash 1 $lfbits-nonnullenv-bit))))
694                   (setq debug-info (afunc-lfun-info afunc))
695                   (when (logbitp $fbitccoverage (the fixnum (afunc-bits afunc)))
696                     (setq bits (+ bits (ash 1 $lfbits-code-coverage-bit))))
697                   (when lambda-form
698                     (setq debug-info
699                           (list* 'function-lambda-expression lambda-form debug-info)))
700                   (when *x862-recorded-symbols*
701                     (setq debug-info
702                           (list* 'function-symbol-map *x862-recorded-symbols* debug-info)))
703                   (when (and (getf debug-info '%function-source-note) *x862-emitted-source-notes*)
704                     (setq debug-info                     ;; Compressed below
705                           (list* 'pc-source-map *x862-emitted-source-notes* debug-info)))
706                   (when debug-info
707                     (setq bits (logior (ash 1 $lfbits-info-bit) bits)))
708                   (unless (or fname lambda-form *x862-recorded-symbols*)
709                     (setq bits (logior (ash 1 $lfbits-noname-bit) bits)))
710                   (unless (afunc-parent afunc)
711                     (x862-fixup-fwd-refs afunc))
712                   (setf (afunc-all-vars afunc) nil)
713                   (setf (afunc-argsword afunc) bits)
714                   (let* ((regsave-label (if (typep *x862-compiler-register-save-label* 'vinsn-note)
715                                           (vinsn-label-info (vinsn-note-label *x862-compiler-register-save-label*))))
716                          (regsave-mask (if regsave-label (x862-register-mask-byte
717                                                           *x862-register-restore-count*)))
718                          (regsave-addr (if regsave-label (x862-encode-register-save-ea
719                                                           *x862-register-restore-ea*
720                                                           *x862-register-restore-count*))))
721                     (target-arch-case
722                      (:x8632
723                       (when debug-info
724                         (x86-lap-directive frag-list :long 0))
725                       (when fname
726                         (x86-lap-directive frag-list :long 0))
727                       (x86-lap-directive frag-list :long 0))
728                      (:x8664
729                       (when debug-info
730                         (x86-lap-directive frag-list :quad 0))
731                       (when fname
732                         (x86-lap-directive frag-list :quad 0))
733                       (x86-lap-directive frag-list :quad 0)))
734
735                     (relax-frag-list frag-list)
736                     (apply-relocs frag-list)
737                     (fill-for-alignment frag-list)
738                     (target-arch-case
739                      (:x8632
740                       (let* ((label (find-x86-lap-label srt-tag))
741                              (srt-frag (x86-lap-label-frag label))
742                              (srt-index (x86-lap-label-offset label)))
743                         ;; fill in self-reference offsets
744                         (do-dll-nodes (frag frag-list)
745                           (dolist (reloc (frag-relocs frag))
746                             (when (eq (reloc-type reloc) :self)
747                               (setf (frag-ref-32 srt-frag srt-index)
748                                     (+ (frag-address frag) (reloc-pos reloc)))
749                               (incf srt-index 4)))))
750                       ;;(show-frag-bytes frag-list)
751                       ))
752
753                     (x862-lap-process-regsave-info frag-list regsave-label regsave-mask regsave-addr)
754
755                     (when (getf debug-info 'pc-source-map)
756                       (setf (getf debug-info 'pc-source-map) (x862-generate-pc-source-map debug-info)))
757                     (when (getf debug-info 'function-symbol-map)
758                       (setf (getf debug-info 'function-symbol-map) (x862-digest-symbols)))
759
760                     (setf (afunc-lfun afunc)
761                           #+x86-target
762                           (if (eq *host-backend* *target-backend*)
763                             (create-x86-function fname frag-list *x862-constant-alist* bits debug-info)
764                             (cross-create-x86-function fname frag-list *x862-constant-alist* bits debug-info))
765                           #-x86-target
766                           (cross-create-x86-function fname frag-list *x862-constant-alist* bits debug-info)))))))
767          (backend-remove-labels))))
768    afunc))
769
770
771     
772   
773(defun x862-make-stack (size &optional (subtype target::subtag-s16-vector))
774  (make-uarray-1 subtype size t 0 nil nil nil nil t nil))
775
776(defun x862-fixup-fwd-refs (afunc)
777  (dolist (f (afunc-inner-functions afunc))
778    (x862-fixup-fwd-refs f))
779  (let ((fwd-refs (afunc-fwd-refs afunc)))
780    (when fwd-refs
781      (let* ((native-x86-functions #-x86-target nil
782                                   #+x86-target (eq *target-backend*
783                                                    *host-backend*))
784             (v (if native-x86-functions
785                  (function-to-function-vector (afunc-lfun afunc))
786                  (afunc-lfun afunc)))
787             (vlen (uvsize v)))
788        (declare (fixnum vlen))
789        (dolist (ref fwd-refs)
790          (let* ((ref-fun (afunc-lfun ref)))
791            (do* ((i (if native-x86-functions
792                       (%function-code-words
793                        (function-vector-to-function v))
794                       1)
795                     (1+ i)))
796                 ((= i vlen))
797              (declare (fixnum i))
798              (if (eq (%svref v i) ref)
799                (setf (%svref v i) ref-fun)))))))))
800
801(defun x862-generate-pc-source-map (debug-info)
802  (let* ((definition-source-note (getf debug-info '%function-source-note))
803         (emitted-source-notes (getf debug-info 'pc-source-map))
804         (def-start (source-note-start-pos definition-source-note))
805         (n (length emitted-source-notes))
806         (nvalid 0)
807         (max 0)
808         (pc-starts (make-array n))
809         (pc-ends (make-array n))
810         (text-starts (make-array n))
811         (text-ends (make-array n)))
812    (declare (fixnum n nvalid)
813             (dynamic-extent pc-starts pc-ends text-starts text-ends))
814    (dolist (start emitted-source-notes)
815      (let* ((pc-start (x862-vinsn-note-label-address start t))
816             (pc-end (x862-vinsn-note-label-address (vinsn-note-peer start) nil))
817             (source-note (aref (vinsn-note-info start) 0))
818             (text-start (- (source-note-start-pos source-note) def-start))
819             (text-end (- (source-note-end-pos source-note) def-start)))
820        (declare (fixnum pc-start pc-end text-start text-end))
821        (when (and (plusp pc-start)
822                   (plusp pc-end)
823                   (plusp text-start)
824                   (plusp text-end))
825          (if (> pc-start max) (setq max pc-start))
826          (if (> pc-end max) (setq max pc-end))
827          (if (> text-start max) (setq max text-start))
828          (if (> text-end max) (setq max text-end))
829          (setf (svref pc-starts nvalid) pc-start
830                (svref pc-ends nvalid) pc-end
831                (svref text-starts nvalid) text-start
832                (svref text-ends nvalid) text-end)
833          (incf nvalid))))
834    (let* ((nentries (* nvalid 4))
835           (vec (cond ((< max #x100) (make-array nentries :element-type '(unsigned-byte 8)))
836                      ((< max #x10000) (make-array nentries :element-type '(unsigned-byte 16)))
837                      (t (make-array nentries :element-type '(unsigned-byte 32))))))
838      (declare (fixnum nentries))
839      (do* ((i 0 (+ i 4))
840            (j 1 (+ j 4))
841            (k 2 (+ k 4))
842            (l 3 (+ l 4))
843            (idx 0 (1+ idx)))
844          ((= i nentries) vec)
845        (declare (fixnum i j k l idx))
846        (setf (aref vec i) (svref pc-starts idx)
847              (aref vec j) (svref pc-ends idx)
848              (aref vec k) (svref text-starts idx)
849              (aref vec l) (svref text-ends idx))))))
850
851(defun x862-vinsn-note-label-address (note &optional start-p sym)
852  (-
853   (let* ((label (vinsn-note-label note))
854          (lap-label (if label (vinsn-label-info label))))
855     (if lap-label
856       (x86-lap-label-address lap-label)
857       (compiler-bug "Missing or bad ~s label~@[: ~s~]"
858                     (if start-p 'start 'end)
859                     sym)))
860   (target-arch-case
861    (:x8632 x8632::fulltag-misc)        ;xxx?
862    (:x8664 x8664::fulltag-function))))
863
864(defun x862-digest-symbols ()
865  (when *x862-recorded-symbols*
866    (let* ((symlist *x862-recorded-symbols*)
867           (len (length symlist))
868           (syms (make-array len))
869           (ptrs (make-array (%i+  (%i+ len len) len)))
870           (i -1)
871           (j -1))
872      (declare (fixnum i j))
873      (dolist (info symlist (progn (%rplaca symlist syms)
874                                   (%rplacd symlist ptrs)))
875        (destructuring-bind (var sym startlab endlab) info
876          (let* ((ea (var-ea var))
877                 (ea-val (ldb (byte 16 0) ea)))
878            (setf (aref ptrs (incf i)) (if (memory-spec-p ea)
879                                         (logior (ash ea-val 6) #o77)
880                                         ea-val)))
881          (setf (aref syms (incf j)) sym)
882          (setf (aref ptrs (incf i)) (x862-vinsn-note-label-address startlab t sym))
883          (setf (aref ptrs (incf i)) (x862-vinsn-note-label-address endlab nil sym))))
884      *x862-recorded-symbols*)))
885
886(defun x862-decls (decls)
887  (if (fixnump decls)
888    (locally (declare (fixnum decls))
889      (setq *x862-tail-allow* (neq 0 (%ilogand2 $decl_tailcalls decls))
890            *x862-open-code-inline* (neq 0 (%ilogand2 $decl_opencodeinline decls))
891            *x862-full-safety* (neq 0 (%ilogand2 $decl_full_safety decls))
892            *x862-reckless* (neq 0 (%ilogand2 $decl_unsafe decls))
893            *x862-trust-declarations* (neq 0 (%ilogand2 $decl_trustdecls decls))))))
894
895
896(defun %x862-bigger-cdr-than (x y)
897  (declare (cons x y))
898  (> (the fixnum (cdr x)) (the fixnum (cdr y))))
899
900;;; Return an unordered list of "varsets": each var in a varset can be
901;;; assigned a register and all vars in a varset can be assigned the
902;;; same register (e.g., no scope conflicts.)
903
904(defun x862-partition-vars (vars)
905  (labels ((var-weight (var)
906             (let* ((bits (nx-var-bits var)))
907               (declare (fixnum bits))
908               (if (eql 0 (logand bits (logior
909                                        (ash 1 $vbitpuntable)
910                                        (ash -1 $vbitspecial)
911                                        (ash 1 $vbitnoreg))))
912                 (if (eql (logior (ash 1 $vbitclosed) (ash 1 $vbitsetq))
913                          (logand bits (logior (ash 1 $vbitclosed) (ash 1 $vbitsetq))))
914                   0
915                   (%i+ (%ilogand $vrefmask bits) (%ilsr 8 (%ilogand $vsetqmask bits))))
916                 0)))
917           (sum-weights (varlist) 
918             (let ((sum 0))
919               (dolist (v varlist sum) (incf sum (var-weight v)))))
920           (vars-disjoint-p (v1 v2)
921             (if (eq v1 v2)
922               nil
923               (if (memq v1 (var-binding-info v2))
924                 nil
925                 (if (memq v2 (var-binding-info v1))
926                   nil
927                   t)))))
928    (setq vars (%sort-list-no-key
929                ;(delete-if #'(lambda (v) (eql (var-weight v) 0)) vars)
930                (do* ((handle (cons nil vars))
931                      (splice handle))
932                     ((null (cdr splice)) (cdr handle))                 
933                  (declare (dynamic-extent handle) (type cons handle splice))
934                  (if (eql 0 (var-weight (%car (cdr splice))))
935                    (rplacd splice (%cdr (cdr splice)))
936                    (setq splice (cdr splice))))
937                #'(lambda (v1 v2) (%i> (var-weight v1) (var-weight v2)))))
938    ;; This isn't optimal.  It partitions all register-allocatable
939    ;; variables into sets such that
940    ;; 1) no variable is a member of more than one set and
941    ;; 2) all variables in a given set are disjoint from each other
942    ;; A set might have exactly one member.
943    ;; If a register is allocated for any member of a set, it's
944    ;; allocated for all members of that set.
945    (let* ((varsets nil))
946      (do* ((all vars (cdr all)))
947           ((null all))
948        (let* ((var (car all)))
949          (when (dolist (already varsets t)
950                  (when (memq var (car already)) (return)))
951            (let* ((varset (cons var nil)))
952              (dolist (v (cdr all))
953                (when (dolist (already varsets t)
954                        (when (memq v (car already)) (return)))
955                  (when (dolist (d varset t)
956                          (unless (vars-disjoint-p v d) (return)))
957                    (push v varset))))
958              (let* ((weight (sum-weights varset)))
959                (declare (fixnum weight))
960                (if (>= weight 3)
961                  (push (cons (nreverse varset) weight) varsets)))))))
962      varsets)))
963
964;;; Maybe globally allocate registers to symbols naming functions & variables,
965;;; and to simple lexical variables.
966(defun x862-allocate-global-registers (fcells vcells all-vars no-regs)
967  (if (or no-regs (target-arch-case (:x8632 t)))
968    (progn
969      (dolist (c fcells) (%rplacd c nil))
970      (dolist (c vcells) (%rplacd c nil))
971      (values 0 nil))
972    (let* ((maybe (x862-partition-vars all-vars)))
973      (dolist (c fcells) 
974        (if (>= (the fixnum (cdr c)) 3) (push c maybe)))
975      (dolist (c vcells) 
976        (if (>= (the fixnum (cdr c)) 3) (push c maybe)))
977      (do* ((things (%sort-list-no-key maybe #'%x862-bigger-cdr-than) (cdr things))
978            (n 0 (1+ n))
979            (registers (target-arch-case
980                        (:x8632 (error "no nvrs on x8632"))
981                        (:x8664
982                         (if (= (backend-lisp-context-register *target-backend*) x8664::save3)
983                           (list x8664::save0 x8664::save1 x8664::save2)
984                           (list x8664::save0 x8664::save1 x8664::save2 x8664::save3)))))
985            (regno (pop registers) (pop registers))
986            (constant-alist ()))
987           ((or (null things) (null regno))
988            (dolist (cell fcells) (%rplacd cell nil))
989            (dolist (cell vcells) (%rplacd cell nil))
990            (values n constant-alist))
991        (declare (list things)
992                 (fixnum n regno))
993        (let* ((thing (car things)))
994          (if (or (memq thing fcells)
995                  (memq thing vcells))
996            (push (cons thing regno) constant-alist)
997            (dolist (var (car thing))
998              (nx-set-var-bits var 
999                               (%ilogior (%ilogand (%ilognot $vrefmask) (nx-var-bits var))
1000                                 regno
1001                                 (%ilsl $vbitreg 1))))))))))
1002
1003
1004   
1005;;; Vpush the last N non-volatile-registers.
1006(defun x862-save-nvrs (seg n)
1007  (declare (fixnum n))
1008  (target-arch-case
1009   ;; no nvrs on x8632
1010   (:x8664
1011    (when (> n 0)
1012      (setq *x862-compiler-register-save-label* (x862-emit-note seg :regsave))
1013      (with-x86-local-vinsn-macros (seg)
1014        (let* ((mask x8664-nonvolatile-node-regs))
1015          (dotimes (i n)
1016            (let* ((reg (1- (integer-length mask))))
1017              (x862-vpush-register seg reg :regsave reg 0)
1018              (setq mask (logandc2 mask (ash 1 reg)))))))
1019      (setq *x862-register-restore-ea* *x862-vstack*
1020            *x862-register-restore-count* n)))))
1021
1022
1023;;; If there are an indefinite number of args/values on the vstack,
1024;;; we have to restore from a register that matches the compiler's
1025;;; notion of the vstack depth.  This can be computed by the caller
1026;;; (sum of vsp & nargs, or copy of vsp  before indefinite number of
1027;;; args pushed, etc.)
1028
1029
1030(defun x862-restore-nvrs (seg ea nregs &optional (can-pop t))
1031  (target-arch-case
1032   ;; no nvrs on x8632
1033   (:x8664
1034    (when (and ea nregs)
1035      (with-x86-local-vinsn-macros (seg)
1036        (let* ((mask x8664-nonvolatile-node-regs)
1037               (regs ()))
1038          (dotimes (i nregs)
1039            (let* ((reg (1- (integer-length mask))))
1040              (push reg regs)
1041              (setq mask (logandc2 mask (ash 1 reg)))))
1042          (cond (can-pop
1043                 (let* ((diff-in-bytes (- *x862-vstack* ea)))
1044                   (unless (zerop diff-in-bytes)
1045                     (x862-adjust-vstack diff-in-bytes)
1046                     (! vstack-discard (floor diff-in-bytes *x862-target-node-size*)))
1047                   (dolist (reg regs)
1048                     (! vpop-register reg))))
1049                (t
1050                 (dolist (reg regs)
1051                   (! vframe-load reg (- ea *x862-target-node-size*) ea)
1052                   (decf ea *x862-target-node-size*))))))))))
1053
1054
1055(defun x862-bind-lambda (seg lcells req opt rest keys auxen optsupvloc passed-in-regs lexpr &optional inherited
1056                             &aux (vloc 0) (numopt (list-length (%car opt)))
1057                             (nkeys (list-length (%cadr keys))) 
1058                             reg)
1059  (declare (fixnum vloc))
1060  (x862-check-lcell-depth)
1061  (dolist (arg inherited)
1062    (if (memq arg passed-in-regs)
1063      (x862-set-var-ea seg arg (var-ea arg))
1064      (let* ((lcell (pop lcells)))
1065        (if (setq reg (x862-assign-register-var arg))
1066          (x862-init-regvar seg arg reg (x862-vloc-ea vloc))
1067          (x862-bind-var seg arg vloc lcell))
1068        (setq vloc (%i+ vloc *x862-target-node-size*)))))
1069  (dolist (arg req)
1070    (if (memq arg passed-in-regs)
1071      (x862-set-var-ea seg arg (var-ea arg))
1072      (let* ((lcell (pop lcells)))
1073        (if (setq reg (x862-assign-register-var arg))
1074          (x862-init-regvar seg arg reg (x862-vloc-ea vloc))
1075          (x862-bind-var seg arg vloc lcell))
1076        (setq vloc (%i+ vloc *x862-target-node-size*)))))
1077  (when opt
1078    (if (x862-hard-opt-p opt)
1079      (setq vloc (apply #'x862-initopt seg vloc optsupvloc lcells (nthcdr (- (length lcells) numopt) lcells) opt)
1080            lcells (nthcdr numopt lcells))
1081
1082      (dolist (var (%car opt))
1083        (if (memq var passed-in-regs)
1084          (x862-set-var-ea seg var (var-ea var))
1085          (let* ((lcell (pop lcells)))
1086            (if (setq reg (x862-assign-register-var var))
1087              (x862-init-regvar seg var reg (x862-vloc-ea vloc))
1088              (x862-bind-var seg var vloc lcell))
1089            (setq vloc (+ vloc *x862-target-node-size*)))))))
1090
1091  (when rest
1092    (if lexpr
1093      (progn
1094        (if (setq reg (x862-assign-register-var rest))
1095          (progn
1096            (x862-copy-register seg reg *x862-arg-z*)
1097            (x862-set-var-ea seg rest reg))
1098            (let* ((loc *x862-vstack*))
1099              (x862-vpush-register seg *x862-arg-z* :reserved)
1100              (x862-note-top-cell rest)
1101              (x862-bind-var seg rest loc *x862-top-vstack-lcell*))))
1102      (let* ((rvloc (+ vloc (* 2 *x862-target-node-size* nkeys))))
1103        (if (setq reg (x862-assign-register-var rest))
1104          (x862-init-regvar seg rest reg (x862-vloc-ea rvloc))
1105          (x862-bind-var seg rest rvloc (pop lcells))))))
1106    (when keys
1107      (apply #'x862-init-keys seg vloc lcells keys))
1108  (x862-seq-bind seg (%car auxen) (%cadr auxen)))
1109
1110
1111(defun x862-initopt (seg vloc spvloc lcells splcells vars inits spvars)
1112  (with-x86-local-vinsn-macros (seg)
1113    (dolist (var vars vloc)
1114      (let* ((initform (pop inits))
1115             (spvar (pop spvars))
1116             (lcell (pop lcells))
1117             (splcell (pop splcells))
1118             (reg (x862-assign-register-var var))
1119             (regloadedlabel (if reg (backend-get-next-label))))
1120        (unless (nx-null initform)
1121          (let ((skipinitlabel (backend-get-next-label)))
1122            (with-crf-target () crf
1123              (x862-compare-ea-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) (x862-vloc-ea spvloc)  x86::x86-e-bits t))
1124            (if reg
1125              (x862-form seg reg regloadedlabel initform)
1126              (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc)))
1127            (@ skipinitlabel)))
1128        (if reg
1129          (progn
1130            (x862-init-regvar seg var reg (x862-vloc-ea vloc))
1131            (@ regloadedlabel))
1132          (x862-bind-var seg var vloc lcell))
1133        (when spvar
1134          (if (setq reg (x862-assign-register-var spvar))
1135            (x862-init-regvar seg spvar reg (x862-vloc-ea spvloc))
1136            (x862-bind-var seg spvar spvloc splcell))))
1137      (setq vloc (%i+ vloc *x862-target-node-size*))
1138      (if spvloc (setq spvloc (%i+ spvloc *x862-target-node-size*))))))
1139
1140(defun x862-init-keys (seg vloc lcells allow-others keyvars keysupp keyinits keykeys)
1141  (declare (ignore keykeys allow-others))
1142  (with-x86-local-vinsn-macros (seg)
1143    (dolist (var keyvars)
1144      (let* ((spvar (pop keysupp))
1145             (initform (pop keyinits))
1146             (reg (x862-assign-register-var var))
1147             (regloadedlabel (if reg (backend-get-next-label)))
1148             (var-lcell (pop lcells))
1149             (sp-lcell (pop lcells))
1150             (sploc (%i+ vloc *x862-target-node-size*)))
1151        (unless (nx-null initform)
1152          (let ((skipinitlabel (backend-get-next-label)))
1153            (with-crf-target () crf
1154              (x862-compare-ea-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) (x862-vloc-ea sploc)  x86::x86-e-bits t))
1155            (if reg
1156              (x862-form seg reg regloadedlabel initform)
1157              (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc)))
1158            (@ skipinitlabel)))
1159        (if reg
1160          (progn
1161            (x862-init-regvar seg var reg (x862-vloc-ea vloc))
1162            (@ regloadedlabel))
1163          (x862-bind-var seg var vloc var-lcell))
1164        (when spvar
1165          (if (setq reg (x862-assign-register-var spvar))
1166            (x862-init-regvar seg spvar reg (x862-vloc-ea sploc))
1167            (x862-bind-var seg spvar sploc sp-lcell))))
1168      (setq vloc (%i+ vloc (* 2 *x862-target-node-size*))))))
1169
1170;;; Vpush register r, unless var gets a globally-assigned register.
1171;;; Return NIL if register was vpushed, else var.
1172(defun x862-vpush-arg-register (seg reg var)
1173  (when var
1174    (let* ((bits (nx-var-bits var)))
1175      (declare (fixnum bits))
1176      (if (logbitp $vbitreg bits)
1177        var
1178        (progn 
1179          (x862-vpush-register seg reg :reserved)
1180          nil)))))
1181
1182
1183;;; nargs has been validated, arguments defaulted and canonicalized.
1184;;; Save caller's context, then vpush any argument registers that
1185;;; didn't get global registers assigned to their variables.
1186;;; Return a list of vars/nils for each argument register
1187;;;  (nil if vpushed, var if still in arg_reg).
1188(defun x862-argregs-entry (seg revargs &optional variable-args-entry)
1189  (with-x86-local-vinsn-macros (seg)
1190    (let* ((nargs (length revargs))
1191           (reg-vars ()))
1192      (declare (type (unsigned-byte 16) nargs))
1193      (unless variable-args-entry
1194        (if (<= nargs *x862-target-num-arg-regs*) ; caller didn't vpush anything
1195          (! save-lisp-context-no-stack-args)
1196          (let* ((offset (* (the fixnum (- nargs *x862-target-num-arg-regs*)) *x862-target-node-size*)))
1197            (declare (fixnum offset))
1198            (! save-lisp-context-offset offset))))
1199      (target-arch-case
1200       (:x8632
1201        (destructuring-bind (&optional zvar yvar &rest stack-args) revargs
1202          (let* ((nstackargs (length stack-args)))
1203            (x862-set-vstack (* nstackargs *x862-target-node-size*))
1204            (dotimes (i nstackargs)
1205              (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil))
1206            (if (>= nargs 2)
1207              (push (x862-vpush-arg-register seg ($ *x862-arg-y*) yvar) reg-vars))
1208            (if (>= nargs 1)
1209              (push (x862-vpush-arg-register seg ($ *x862-arg-z*) zvar) reg-vars)))))
1210       (:x8664
1211        (destructuring-bind (&optional zvar yvar xvar &rest stack-args) revargs
1212          (let* ((nstackargs (length stack-args)))
1213            (x862-set-vstack (* nstackargs *x862-target-node-size*))
1214            (dotimes (i nstackargs)
1215              (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil))
1216            (if (>= nargs 3)
1217              (push (x862-vpush-arg-register seg ($ x8664::arg_x) xvar) reg-vars))
1218            (if (>= nargs 2)
1219              (push (x862-vpush-arg-register seg ($ *x862-arg-y*) yvar) reg-vars))
1220            (if (>= nargs 1)
1221              (push (x862-vpush-arg-register seg ($ *x862-arg-z*) zvar) reg-vars))))))
1222      reg-vars)))
1223
1224;;; Just required args.
1225;;; Since this is just a stupid bootstrapping port, always save
1226;;; lisp context.
1227(defun x862-req-nargs-entry (seg rev-fixed-args)
1228  (let* ((nargs (length rev-fixed-args)))
1229    (declare (type (unsigned-byte 16) nargs))
1230    (with-x86-local-vinsn-macros (seg)
1231      (unless *x862-reckless*
1232        (! check-exact-nargs nargs))
1233      (x862-argregs-entry seg rev-fixed-args))))
1234
1235;;; No more &optional args than register args; all &optionals default
1236;;; to NIL and none have supplied-p vars.  No &key/&rest.
1237(defun x862-simple-opt-entry (seg rev-opt-args rev-req-args)
1238  (let* ((min (length rev-req-args))
1239         (nopt (length rev-opt-args))
1240         (max (+ min nopt)))
1241    (declare (type (unsigned-byte 16) min nopt max))
1242    (with-x86-local-vinsn-macros (seg)
1243      (unless *x862-reckless*
1244        (if rev-req-args
1245          (! check-min-max-nargs min max)
1246          (! check-max-nargs max)))
1247      (if (> min *x862-target-num-arg-regs*)
1248        (! save-lisp-context-in-frame)
1249        (if (<= max *x862-target-num-arg-regs*)
1250          (! save-lisp-context-no-stack-args)
1251          (! save-lisp-context-variable-arg-count)))
1252      (if (= nopt 1)
1253        (! default-1-arg min)
1254        (if (= nopt 2)
1255          (! default-2-args min)
1256          (! default-3-args min)))
1257      (x862-argregs-entry seg (append rev-opt-args rev-req-args) t))))
1258
1259;;; if "num-fixed" is > 0, we've already ensured that at least that many args
1260;;; were provided; that may enable us to generate better code for saving the
1261;;; argument registers.
1262;;; We're responsible for computing the caller's VSP and saving
1263;;; caller's state.
1264(defun x862-lexpr-entry (seg num-fixed)
1265  (with-x86-local-vinsn-macros (seg)
1266    (! save-lexpr-argregs num-fixed)
1267    ;; The "lexpr" (address of saved nargs register, basically
1268    ;; is now in arg_z
1269    (! build-lexpr-frame)
1270    (dotimes (i num-fixed)
1271      (! copy-lexpr-argument (- num-fixed i)))))
1272
1273
1274(defun x862-structured-initopt (seg lcells vloc context vars inits spvars)
1275  (with-x86-local-vinsn-macros (seg)
1276    (dolist (var vars vloc)
1277      (let* ((initform (pop inits))
1278             (spvar (pop spvars))
1279             (spvloc (%i+ vloc *x862-target-node-size*))
1280             (var-lcell (pop lcells))
1281             (sp-lcell (pop lcells)))
1282        (unless (nx-null initform)
1283          (let ((skipinitlabel (backend-get-next-label)))
1284            (with-crf-target () crf
1285              (x862-compare-ea-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) (x862-vloc-ea spvloc) x86::x86-e-bits t))
1286            (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc))
1287            (@ skipinitlabel)))
1288        (x862-bind-structured-var seg var vloc var-lcell context)
1289        (when spvar
1290          (x862-bind-var seg spvar spvloc sp-lcell)))
1291      (setq vloc (%i+ vloc (* 2 *x862-target-node-size*))))))
1292
1293
1294
1295(defun x862-structured-init-keys (seg lcells vloc context allow-others keyvars keysupp keyinits keykeys)
1296  (declare (ignore keykeys allow-others))
1297  (with-x86-local-vinsn-macros (seg)
1298    (dolist (var keyvars)
1299      (let* ((spvar (pop keysupp))
1300             (initform (pop keyinits))
1301             (sploc (%i+ vloc *x862-target-node-size*))
1302             (var-lcell (pop lcells))
1303             (sp-reg ($ *x862-arg-z*))
1304             (sp-lcell (pop lcells)))
1305        (unless (nx-null initform)
1306          (x862-stack-to-register seg (x862-vloc-ea sploc) sp-reg)
1307          (let ((skipinitlabel (backend-get-next-label)))
1308            (with-crf-target () crf
1309              (x862-compare-register-to-nil seg crf (x862-make-compound-cd 0 skipinitlabel) sp-reg x86::x86-e-bits t))
1310            (x862-register-to-stack seg (x862-one-untargeted-reg-form seg initform ($ *x862-arg-z*)) (x862-vloc-ea vloc))
1311            (@ skipinitlabel)))
1312        (x862-bind-structured-var seg var vloc var-lcell context)
1313        (when spvar
1314          (x862-bind-var seg spvar sploc sp-lcell)))
1315      (setq vloc (%i+ vloc (* 2 *x862-target-node-size*))))))
1316
1317(defun x862-vloc-ea (n &optional vcell-p)
1318  (setq n (make-memory-spec (dpb memspec-frame-address memspec-type-byte n)))
1319  (if vcell-p
1320    (make-vcell-memory-spec n)
1321    n))
1322
1323
1324(defun x862-acode-operator-function (form)
1325  (or (and (acode-p form)
1326           (svref *x862-specials* (%ilogand #.operator-id-mask (acode-operator form))))
1327      (compiler-bug "x862-form ? ~s" form)))
1328
1329(defmacro with-note ((form-var seg-var &rest other-vars) &body body)
1330  (let* ((note (gensym "NOTE"))
1331         (code-note (gensym "CODE-NOTE"))
1332         (source-note (gensym "SOURCE-NOTE"))
1333         (start (gensym "START"))
1334         (end (gensym "END"))
1335         (with-note-body (gensym "WITH-NOTE-BODY")))
1336    `(flet ((,with-note-body (,form-var ,seg-var ,@other-vars)
1337              ,@body))
1338       (let ((,note (acode-note ,form-var)))
1339         (if ,note
1340           (let* ((,code-note (and (code-note-p ,note) ,note))
1341                  (,source-note (if ,code-note
1342                                  (code-note-source-note ,note)
1343                                  ,note))
1344                  (,start (and ,source-note
1345                               (x862-emit-note ,seg-var :source-location-begin ,source-note))))
1346             (prog2
1347                 (when ,code-note
1348                   (with-x86-local-vinsn-macros (,seg-var)
1349                     (x862-store-immediate ,seg-var ,code-note *x862-temp0*)
1350                     (! misc-set-immediate-c-node 0 *x862-temp0* 1)))
1351                 (,with-note-body ,form-var ,seg-var ,@other-vars)
1352               (when ,source-note
1353                 (let ((,end (x862-emit-note ,seg-var :source-location-end)))
1354                   (setf (vinsn-note-peer ,start) ,end
1355                         (vinsn-note-peer ,end) ,start)
1356                   (push ,start *x862-emitted-source-notes*)))))
1357           (,with-note-body ,form-var ,seg-var ,@other-vars))))))
1358
1359(defun x862-toplevel-form (seg vreg xfer form)
1360  (let* ((code-note (acode-note form))
1361         (args (if code-note `(,@(%cdr form) ,code-note) (%cdr form))))
1362    (apply (x862-acode-operator-function form) seg vreg xfer args)))
1363
1364(defun x862-form (seg vreg xfer form)
1365  (with-note (form seg vreg xfer)
1366    (if (nx-null form)
1367      (x862-nil seg vreg xfer)
1368      (if (nx-t form)
1369        (x862-t seg vreg xfer)
1370        (let* ((fn (x862-acode-operator-function form)) ;; also typechecks
1371               (op (acode-operator form)))
1372          (if (and (null vreg)
1373                   (%ilogbitp operator-acode-subforms-bit op)
1374                   (%ilogbitp operator-assignment-free-bit op))
1375            (dolist (f (%cdr form) (x862-branch seg xfer))
1376              (x862-form seg nil nil f ))
1377            (apply fn seg vreg xfer (%cdr form))))))))
1378
1379;;; dest is a float reg - form is acode
1380(defun x862-form-float (seg freg xfer form)
1381  (declare (ignore xfer))
1382  (with-note (form seg freg)
1383    (when (or (nx-null form)(nx-t form))(compiler-bug "x862-form to freg ~s" form))
1384    (when (and (= (get-regspec-mode freg) hard-reg-class-fpr-mode-double)
1385               (x862-form-typep form 'double-float))
1386      ;; kind of screwy - encoding the source type in the dest register spec
1387      (set-node-regspec-type-modes freg hard-reg-class-fpr-type-double))
1388    (let* ((fn (x862-acode-operator-function form)))
1389      (apply fn seg freg nil (%cdr form)))))
1390
1391
1392(defun x862-form-typep (form type)
1393  (acode-form-typep form type *x862-trust-declarations*)
1394)
1395
1396(defun x862-form-type (form)
1397  (acode-form-type form *x862-trust-declarations*))
1398 
1399(defun x862-use-operator (op seg vreg xfer &rest forms)
1400  (declare (dynamic-extent forms))
1401  (apply (svref *x862-specials* (%ilogand operator-id-mask op)) seg vreg xfer forms))
1402
1403;;; Returns true iff lexical variable VAR isn't setq'ed in FORM.
1404;;; Punts a lot ...
1405(defun x862-var-not-set-by-form-p (var form)
1406  (let* ((bits (nx-var-bits var)))
1407    (or (not (%ilogbitp $vbitsetq bits))
1408        (x862-setqed-var-not-set-by-form-p var form (logbitp $vbitclosed bits)))))
1409
1410(defun x862-setqed-var-not-set-by-form-p (var form &optional closed)
1411  (setq form (acode-unwrapped-form form))
1412  (or (atom form)
1413      (x86-constant-form-p form)
1414      (x862-lexical-reference-p form)
1415      (let ((op (acode-operator form))
1416            (subforms nil))
1417        (if (eq op (%nx1-operator setq-lexical))
1418          (and (neq var (cadr form))
1419               (x862-setqed-var-not-set-by-form-p var (caddr form)))
1420          (and (or (not closed)
1421                   (logbitp operator-side-effect-free-bit op))
1422               (flet ((not-set-in-formlist (formlist)
1423                        (dolist (subform formlist t)
1424                          (unless (x862-setqed-var-not-set-by-form-p var subform closed) (return)))))
1425                 (if
1426                   (cond ((%ilogbitp operator-acode-subforms-bit op) (setq subforms (%cdr form)))
1427                         ((%ilogbitp operator-acode-list-bit op) (setq subforms (cadr form))))
1428                   (not-set-in-formlist subforms)
1429                   (and (or (eq op (%nx1-operator call))
1430                            (eq op (%nx1-operator lexical-function-call)))
1431                        (x862-setqed-var-not-set-by-form-p var (cadr form))
1432                        (setq subforms (caddr form))
1433                        (not-set-in-formlist (car subforms))
1434                        (not-set-in-formlist (cadr subforms))))))))))
1435
1436(defun x862-check-fixnum-overflow (seg target &optional labelno)
1437  (with-x86-local-vinsn-macros (seg)
1438    (if *x862-open-code-inline*
1439      (let* ((no-overflow (backend-get-next-label)))
1440        (! set-bigits-and-header-for-fixnum-overflow target (aref *backend-labels* (or labelno no-overflow)))
1441        (! %allocate-uvector target)
1442        (! set-bigits-after-fixnum-overflow target)
1443        (when labelno
1444          (-> labelno))
1445        (@ no-overflow))
1446      (if labelno
1447        (! fix-fixnum-overflow-ool-and-branch target (aref *backend-labels* labelno))
1448        (! fix-fixnum-overflow-ool target)))))
1449
1450(defun x862-nil (seg vreg xfer)
1451  (with-x86-local-vinsn-macros (seg vreg xfer)
1452    (if (eq vreg :push)
1453      (progn
1454        (! vpush-fixnum (target-nil-value))
1455        (^))
1456      (progn
1457        (if (x862-for-value-p vreg)
1458          (ensuring-node-target (target vreg)
1459            (! load-nil target)))
1460        (x862-branch seg (x862-cd-false xfer))))))
1461
1462(defun x862-t (seg vreg xfer)
1463  (with-x86-local-vinsn-macros (seg vreg xfer)
1464    (if (eq vreg :push)
1465      (progn
1466        (! vpush-fixnum (target-t-value))
1467        (^))
1468      (progn
1469        (if (x862-for-value-p vreg)
1470          (ensuring-node-target (target vreg)
1471            (! load-t target)))
1472        (x862-branch seg (x862-cd-true xfer))))))
1473
1474(defun x862-for-value-p (vreg)
1475  (and vreg (not (backend-crf-p vreg))))
1476
1477(defun x862-mvpass (seg form &optional xfer)
1478  (with-x86-local-vinsn-macros (seg)
1479    (x862-form seg  ($ *x862-arg-z*) (logior (or xfer 0) $backend-mvpass-mask) form)))
1480
1481(defun x862-adjust-vstack (delta)
1482  (x862-set-vstack (%i+ *x862-vstack* delta)))
1483
1484(defun x862-set-vstack (new)
1485  (setq *x862-vstack* new))
1486
1487
1488;;; Emit a note at the end of the segment.
1489(defun x862-emit-note (seg class &rest info)
1490  (declare (dynamic-extent info))
1491  (let* ((note (make-vinsn-note class info)))
1492    (append-dll-node (vinsn-note-label note) seg)
1493    note))
1494
1495;;; Emit a note immediately before the target vinsn.
1496(defun x86-prepend-note (vinsn class &rest info)
1497  (declare (dynamic-extent info))
1498  (let* ((note (make-vinsn-note class info)))
1499    (insert-dll-node-before (vinsn-note-label note) vinsn)
1500    note))
1501
1502(defun x862-close-note (seg note)
1503  (let* ((end (close-vinsn-note note)))
1504    (append-dll-node (vinsn-note-label end) seg)
1505    end))
1506
1507
1508
1509
1510
1511
1512(defun x862-stack-to-register (seg memspec reg)
1513  (with-x86-local-vinsn-macros (seg)
1514    (let* ((offset (memspec-frame-address-offset memspec)))
1515      (if (and *x862-tos-reg*
1516               (= offset (- *x862-vstack* *x862-target-node-size*)))
1517        (x862-copy-register seg reg *x862-tos-reg*)
1518        (! vframe-load reg offset  *x862-vstack*)))))
1519
1520(defun x862-lcell-to-register (seg lcell reg)
1521  (with-x86-local-vinsn-macros (seg)
1522    (! lcell-load reg lcell (x862-vstack-mark-top))))
1523
1524(defun x862-register-to-lcell (seg reg lcell)
1525  (with-x86-local-vinsn-macros (seg)
1526    (! lcell-store reg lcell (x862-vstack-mark-top))))
1527
1528(defun x862-register-to-stack (seg reg memspec)
1529  (with-x86-local-vinsn-macros (seg)
1530    (! vframe-store reg (memspec-frame-address-offset memspec) *x862-vstack*)))
1531
1532
1533(defun x862-ea-open (ea)
1534  (if (and ea (not (typep ea 'lreg)) (addrspec-vcell-p ea))
1535    (make-memory-spec (memspec-frame-address-offset ea))
1536    ea))
1537
1538(defun x862-set-NARGS (seg n)
1539  (if (> n call-arguments-limit)
1540    (error "~s exceeded." call-arguments-limit)
1541    (with-x86-local-vinsn-macros (seg)
1542      (! set-nargs n))))
1543
1544(defun x862-assign-register-var (v)
1545  (let ((bits (nx-var-bits v)))
1546    (when (%ilogbitp $vbitreg bits)
1547      (%ilogand bits $vrefmask))))
1548
1549(defun x862-single-float-bits (the-sf)
1550  (single-float-bits the-sf))
1551
1552(defun x862-double-float-bits (the-df)
1553  (double-float-bits the-df))
1554
1555(defun x862-push-immediate (seg xfer form)
1556  (with-x86-local-vinsn-macros (seg)
1557    (if (typep form 'character)
1558      (! vpush-fixnum (logior (ash (char-code form) 8)
1559                              (arch::target-subtag-char (backend-target-arch *target-backend*))))
1560      (let* ((reg (x862-register-constant-p form)))
1561        (if reg
1562          (! vpush-register reg)
1563          (let* ((lab (x86-immediate-label form)))
1564            (! vpush-constant lab)))))
1565    (x862-branch seg xfer)))
1566
1567     
1568(pushnew (%nx1-operator immediate) *x862-operator-supports-push*) 
1569(defun x862-immediate (seg vreg xfer form)
1570  (if (eq vreg :push)
1571    (x862-push-immediate seg xfer form)
1572    (with-x86-local-vinsn-macros (seg vreg xfer)
1573      (if vreg
1574        (if (and (= (hard-regspec-class vreg) hard-reg-class-fpr)
1575                 (or (and (typep form 'double-float) (= (get-regspec-mode vreg) hard-reg-class-fpr-mode-double))
1576                     (and (typep form 'short-float)(= (get-regspec-mode vreg) hard-reg-class-fpr-mode-single))))
1577          (if (zerop form)
1578            (if (eql form 0.0d0)
1579              (! zero-double-float-register vreg)
1580              (! zero-single-float-register vreg))
1581            (if (typep form 'short-float)
1582              (let* ((lab (x86-single-float-constant-label form)))
1583                (! load-single-float-constant vreg lab))
1584              (let* ((lab (x86-double-float-constant-label form)))
1585                (! load-double-float-constant vreg lab))))
1586          (target-arch-case
1587           (:x8632
1588            (if (and (= (hard-regspec-class vreg) hard-reg-class-gpr)
1589                     (member (get-regspec-mode vreg)
1590                             '(hard-reg-class-gpr-mode-u32
1591                               hard-reg-class-gpr-mode-s32
1592                               hard-reg-class-gpr-mode-address))
1593                     (or (typep form '(unsigned-byte 32))
1594                         (typep form '(signed-byte 32))))
1595              ;; The bits fit.  Get them in the register somehow.
1596              (if (typep form '(signed-byte 32))
1597                (x862-lri seg vreg form)
1598                (x862-lriu seg vreg form))
1599              (ensuring-node-target (target vreg)
1600                (if (characterp form)
1601                  (! load-character-constant target (char-code form))
1602                  (x862-store-immediate seg form target)))))
1603           (:x8664
1604            (if (and (typep form '(unsigned-byte 32))
1605                     (= (hard-regspec-class vreg) hard-reg-class-gpr)
1606                     (= (get-regspec-mode vreg)
1607                        hard-reg-class-gpr-mode-u32))
1608              (x862-lri seg vreg form)
1609              (ensuring-node-target
1610                  (target vreg)
1611                (if (characterp form)
1612                  (! load-character-constant target (char-code form))
1613                  (x862-store-immediate seg form target)))))))
1614        (if (and (listp form) *load-time-eval-token* (eq (car form) *load-time-eval-token*))
1615          (x862-store-immediate seg form ($ *x862-temp0*))))
1616      (^))))
1617
1618(defun x862-register-constant-p (form)
1619  (and (consp form)
1620           (or (memq form *x862-vcells*)
1621               (memq form *x862-fcells*))
1622           (%cdr form)))
1623
1624(defun x862-store-immediate (seg imm dest)
1625  (with-x86-local-vinsn-macros (seg)
1626    (let* ((reg (x862-register-constant-p imm)))
1627      (if reg
1628        (x862-copy-register seg dest reg)
1629        (let* ((lab (x86-immediate-label imm)))
1630          (! ref-constant dest lab)))
1631      dest)))
1632
1633
1634;;; Returns label iff form is (local-go <tag>) and can go without adjusting stack.
1635(defun x862-go-label (form)
1636  (let ((current-stack (x862-encode-stack)))
1637    (while (and (acode-p form) (or (eq (acode-operator form) (%nx1-operator progn))
1638                                   (eq (acode-operator form) (%nx1-operator local-tagbody))))
1639      (setq form (caadr form)))
1640    (when (acode-p form)
1641      (let ((op (acode-operator form)))
1642        (if (and (eq op (%nx1-operator local-go))
1643                 (x862-equal-encodings-p (%caddr (%cadr form)) current-stack))
1644          (%cadr (%cadr form))
1645          (if (and (eq op (%nx1-operator local-return-from))
1646                   (nx-null (caddr form)))
1647            (let ((tagdata (car (cadr form))))
1648              (and (x862-equal-encodings-p (cdr tagdata) current-stack)
1649                   (null (caar tagdata))
1650                   (< 0 (cdar tagdata) $backend-mvpass)
1651                   (cdar tagdata)))))))))
1652
1653(defun x862-single-valued-form-p (form)
1654  (setq form (acode-unwrapped-form-value form))
1655  (or (nx-null form)
1656      (nx-t form)
1657      (if (acode-p form)
1658        (let ((op (acode-operator form)))
1659          (or (%ilogbitp operator-single-valued-bit op)
1660              (and (eql op (%nx1-operator values))
1661                   (let ((values (cadr form)))
1662                     (and values (null (cdr values)))))
1663              nil                       ; Learn about functions someday
1664              )))))
1665
1666(defun x862-box-s32 (seg node-dest s32-src)
1667  (with-x86-local-vinsn-macros (seg)
1668    (if (target-arch-case
1669         (:x8632 nil)
1670         (:x8664 t))
1671      (! box-fixnum node-dest s32-src)
1672      (let* ((arg_z ($ *x862-arg-z*))
1673             (imm0 ($ *x862-imm0* :mode :s32)))
1674        (x862-copy-register seg imm0 s32-src)
1675        (! call-subprim (subprim-name->offset '.SPmakes32))
1676        (x862-copy-register seg node-dest arg_z)))))
1677
1678(defun x862-box-s64 (seg node-dest s64-src)
1679  (with-x86-local-vinsn-macros (seg)
1680    (if (target-arch-case
1681         (:x8632 (error "bug"))
1682         (:x8664 *x862-open-code-inline*))
1683      (let* ((no-overflow (backend-get-next-label)))
1684        (! %set-z-flag-if-s64-fits-in-fixnum node-dest s64-src)
1685        (! cbranch-true (aref *backend-labels* no-overflow) x86::x86-e-bits)
1686        (! setup-bignum-alloc-for-s64-overflow s64-src)
1687        (! %allocate-uvector node-dest)
1688        (! set-bigits-after-fixnum-overflow node-dest)
1689        (@ no-overflow))
1690      (let* ((arg_z ($ *x862-arg-z*))
1691             (imm0 (make-wired-lreg *x862-imm0* :mode (get-regspec-mode s64-src))))
1692        (x862-copy-register seg imm0 s64-src)
1693        (! call-subprim (subprim-name->offset '.SPmakes64))
1694        (x862-copy-register seg node-dest arg_z)))))
1695
1696(defun x862-box-u32 (seg node-dest u32-src)
1697  (with-x86-local-vinsn-macros (seg)
1698    (target-arch-case
1699     (:x8632
1700      (let* ((arg_z ($ *x862-arg-z*))
1701             (imm0 ($ *x862-imm0* :mode :u32)))
1702        (x862-copy-register seg imm0 u32-src)
1703        (! call-subprim (subprim-name->offset '.SPmakeu32))
1704        (x862-copy-register seg node-dest arg_z)))
1705     (:x8664
1706      (! box-fixnum node-dest u32-src)))))
1707
1708(defun x862-box-u64 (seg node-dest u64-src)
1709  (with-x86-local-vinsn-macros (seg)
1710    (if (target-arch-case
1711         (:x8632 (error "bug"))
1712         (:x8664 *x862-open-code-inline*))
1713      (let* ((no-overflow (backend-get-next-label)))
1714        (! %set-z-flag-if-u64-fits-in-fixnum node-dest u64-src)
1715        (! cbranch-true (aref *backend-labels* no-overflow) x86::x86-e-bits)
1716        (! setup-bignum-alloc-for-u64-overflow u64-src)
1717        (! %allocate-uvector node-dest)
1718        (! set-bigits-after-fixnum-overflow node-dest)
1719        (@ no-overflow))
1720      (let* ((arg_z ($ *x862-arg-z*))
1721             (imm0 ($ *x862-imm0* :mode :u64)))
1722        (x862-copy-register seg imm0 u64-src)
1723        (! call-subprim (subprim-name->offset '.SPmakeu64))
1724        (x862-copy-register seg node-dest arg_z)))))
1725
1726(defun x862-single->heap (seg dest src)
1727  (with-x86-local-vinsn-macros (seg)
1728    (! setup-single-float-allocation)
1729    (! %allocate-uvector dest)
1730    (! set-single-float-value dest src)))
1731
1732(defun x862-double->heap (seg dest src)
1733  (with-x86-local-vinsn-macros (seg)
1734    (! setup-double-float-allocation)
1735    (! %allocate-uvector dest)
1736    (! set-double-float-value dest src)))
1737
1738
1739(defun x862-vref1 (seg vreg xfer type-keyword src unscaled-idx index-known-fixnum) 
1740  (with-x86-local-vinsn-macros (seg vreg xfer)
1741    (when vreg
1742      (let* ((arch (backend-target-arch *target-backend*))
1743             (is-node (member type-keyword (arch::target-gvector-types arch)))
1744             (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
1745
1746             (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
1747             (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
1748             (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
1749             (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
1750             (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
1751             (vreg-class (and (not (eq vreg :push)) (hard-regspec-class vreg)))
1752             (vreg-mode
1753              (if (or (eql vreg-class hard-reg-class-gpr)
1754                      (eql vreg-class hard-reg-class-fpr))
1755                (get-regspec-mode vreg)
1756                hard-reg-class-gpr-mode-invalid)))
1757        (cond
1758          (is-node
1759           (if (eq vreg :push)
1760             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
1761               (! push-misc-ref-c-node  src index-known-fixnum)
1762               (! push-misc-ref-node src unscaled-idx))
1763             (ensuring-node-target (target vreg)
1764               (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
1765                 (! misc-ref-c-node target src index-known-fixnum)
1766                 (if unscaled-idx
1767                   (! misc-ref-node target src unscaled-idx)
1768                   (with-node-target (src) unscaled-idx
1769                     (x862-absolute-natural seg unscaled-idx  nil (ash index-known-fixnum *x862-target-fixnum-shift*))
1770                     (! misc-ref-node target src unscaled-idx)))))))
1771          (is-32-bit
1772           (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-32-bit-constant-index arch)))
1773             (cond ((eq type-keyword :single-float-vector)
1774                    (with-fp-target () (fp-val :single-float)
1775                      (if (and (eql vreg-class hard-reg-class-fpr)
1776                               (eql vreg-mode hard-reg-class-fpr-mode-single))
1777                        (setq fp-val vreg))
1778                      (! misc-ref-c-single-float fp-val src index-known-fixnum)
1779                      (if (eql vreg-class hard-reg-class-fpr)
1780                        (<- fp-val)
1781                        (ensuring-node-target (target vreg)
1782                          (target-arch-case
1783                           (:x8632 (x862-single->heap seg target fp-val))
1784                           (:x8664 (! single->node target fp-val)))))))
1785                   (t
1786                    (with-additional-imm-reg ()
1787                      (with-imm-target () temp
1788                        (if is-signed
1789                          (! misc-ref-c-s32 temp src index-known-fixnum)
1790                          (! misc-ref-c-u32 temp src index-known-fixnum))
1791                        (ensuring-node-target (target vreg)
1792                          (if (eq type-keyword :simple-string)
1793                            (! u32->char target temp)
1794                            (target-arch-case
1795                             (:x8632
1796                              (if is-signed
1797                                (x862-box-s32 seg target temp)
1798                                (x862-box-u32 seg target temp)))
1799                             (:x8664
1800                              (! box-fixnum target temp)))))))))
1801             (with-imm-target () idx-reg
1802               (if index-known-fixnum
1803                 (x862-absolute-natural seg idx-reg nil (ash index-known-fixnum 2))
1804                 (! scale-32bit-misc-index idx-reg unscaled-idx))
1805               (cond ((eq type-keyword :single-float-vector)
1806                      (with-fp-target () (fp-val :single-float)
1807                        (if (and (eql vreg-class hard-reg-class-fpr)
1808                                 (eql vreg-mode hard-reg-class-fpr-mode-single))
1809                          (setq fp-val vreg))
1810                        (! misc-ref-single-float fp-val src idx-reg)
1811                        (if (eq vreg-class hard-reg-class-fpr)
1812                          (<- fp-val)
1813                          (ensuring-node-target (target vreg)
1814                            (target-arch-case
1815                             (:x8632 (x862-single->heap seg target fp-val))
1816                             (:x8664 (! single->node target fp-val)))))))
1817                     (t
1818                      (with-imm-target () temp
1819                        (if is-signed
1820                          (! misc-ref-s32 temp src idx-reg)
1821                          (! misc-ref-u32 temp src idx-reg))
1822                        (ensuring-node-target (target vreg)
1823                          (if (eq type-keyword :simple-string)
1824                            (! u32->char target temp)
1825                            (target-arch-case
1826                             (:x8632 (if is-signed
1827                                       (x862-box-s32 seg target temp)
1828                                       (x862-box-u32 seg target temp)))
1829                             (:x8664 (! box-fixnum target temp)))))))))))
1830          (is-8-bit
1831           (with-imm-target () temp
1832             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-8-bit-constant-index arch)))
1833               (if is-signed
1834                 (! misc-ref-c-s8 temp src index-known-fixnum)
1835                 (! misc-ref-c-u8 temp src index-known-fixnum))
1836               (with-additional-imm-reg ()
1837                 (with-imm-target () idx-reg
1838                   (if index-known-fixnum
1839                     (x862-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) index-known-fixnum))
1840                     (! scale-8bit-misc-index idx-reg unscaled-idx))
1841                   (if is-signed
1842                     (! misc-ref-s8 temp src idx-reg)
1843                     (! misc-ref-u8 temp src idx-reg)))))
1844             (if (eq type-keyword :simple-string)
1845               (ensuring-node-target (target vreg)
1846                 (! u32->char target temp))
1847               (if (and (= vreg-mode hard-reg-class-gpr-mode-u8)
1848                        (eq type-keyword :unsigned-8-bit-vector))
1849                 (x862-copy-register seg vreg temp)
1850                 (ensuring-node-target (target vreg)
1851                   (! box-fixnum target temp))))))
1852          (is-16-bit
1853           (with-imm-target () temp
1854             (ensuring-node-target (target vreg)
1855               (if (and index-known-fixnum
1856                        (<= index-known-fixnum (arch::target-max-16-bit-constant-index arch)))
1857                 (if is-signed
1858                   (! misc-ref-c-s16 temp src index-known-fixnum)
1859                   (! misc-ref-c-u16 temp src index-known-fixnum))
1860                 (with-imm-target () idx-reg
1861                   (if index-known-fixnum
1862                     (x862-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 1)))
1863                     (! scale-16bit-misc-index idx-reg unscaled-idx))
1864                   (if is-signed
1865                     (! misc-ref-s16 temp src idx-reg)
1866                     (! misc-ref-u16 temp src idx-reg))))
1867               (! box-fixnum target temp))))
1868          ;; Down to the dregs.
1869          (is-64-bit
1870           (with-node-target (src) extra
1871             (unless unscaled-idx (setq unscaled-idx extra)))
1872           (case type-keyword
1873             (:double-float-vector
1874              (with-fp-target () (fp-val :double-float)
1875                (if (and (eql vreg-class hard-reg-class-fpr)
1876                         (eql vreg-mode hard-reg-class-fpr-mode-double))
1877                  (setq fp-val vreg))
1878                (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
1879                  (! misc-ref-c-double-float fp-val src index-known-fixnum)
1880                  (progn
1881                    (if index-known-fixnum
1882                      (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
1883                    (! misc-ref-double-float fp-val src unscaled-idx)))
1884                (if (eq vreg-class hard-reg-class-fpr)
1885                  (<- fp-val)
1886                  (ensuring-node-target (target vreg)
1887                    (x862-double->heap seg target fp-val)))))
1888             ((:signed-64-bit-vector :fixnum-vector)
1889              (ensuring-node-target (target vreg)
1890
1891                (with-imm-target () (s64-reg :s64)
1892                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
1893                    (! misc-ref-c-s64 s64-reg src index-known-fixnum)
1894                    (progn
1895                      (if index-known-fixnum
1896                        (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
1897                      (! misc-ref-s64 s64-reg src unscaled-idx)))
1898                  (if (eq type-keyword :fixnum-vector)
1899                    (! box-fixnum target s64-reg)
1900                    (x862-box-s64 seg target s64-reg)))))
1901             (t
1902                (with-imm-target () (u64-reg :u64)
1903                  (if (eql vreg-mode hard-reg-class-gpr-mode-u64)
1904                    (setq u64-reg vreg))
1905                  (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
1906                    (! misc-ref-c-u64 u64-reg src index-known-fixnum)
1907                    (progn
1908                      (if index-known-fixnum
1909                        (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
1910                      (! misc-ref-u64 u64-reg src unscaled-idx)))
1911                  (unless (eq u64-reg vreg)
1912                    (ensuring-node-target (target vreg)
1913                      (x862-box-u64 seg target u64-reg)))))))
1914          (t
1915           (unless is-1-bit
1916             (nx-error "~& unsupported vector type: ~s"
1917                       type-keyword))
1918           (ensuring-node-target (target vreg)
1919             (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-1-bit-constant-index arch)))
1920               (! misc-ref-c-bit-fixnum target src index-known-fixnum)
1921               (with-imm-target () bitnum
1922                 (if index-known-fixnum
1923                   (x862-lri seg bitnum index-known-fixnum)
1924                   (! scale-1bit-misc-index bitnum unscaled-idx))
1925                 (! nref-bit-vector-fixnum target bitnum src))))))))
1926    (^)))
1927
1928;;; safe = T means assume "vector" is miscobj, do bounds check.
1929;;; safe = fixnum means check that subtag of vector = "safe" and do
1930;;;        bounds check.
1931;;; safe = nil means crash&burn.
1932;;; This mostly knows how to reference the elements of an immediate miscobj.
1933(defun x862-vref (seg vreg xfer type-keyword vector index safe)
1934  (with-x86-local-vinsn-macros (seg vreg xfer)
1935    (when *x862-full-safety*
1936      (unless vreg (setq vreg *x862-arg-z*)))
1937    (if (null vreg)
1938      (progn
1939        (x862-form seg nil nil vector)
1940        (x862-form seg nil xfer index))
1941      (let* ((index-known-fixnum (acode-fixnum-form-p index))
1942             (unscaled-idx nil)
1943             (src nil))
1944        (if (or safe (not index-known-fixnum))
1945          (multiple-value-setq (src unscaled-idx)
1946            (x862-two-untargeted-reg-forms seg vector *x862-arg-y* index *x862-arg-z*))
1947          (setq src (x862-one-untargeted-reg-form seg vector *x862-arg-z*)))
1948        (when safe
1949          (if (typep safe 'fixnum)
1950            (! trap-unless-typecode= src safe))
1951          (unless index-known-fixnum
1952            (! trap-unless-fixnum unscaled-idx))
1953          (! check-misc-bound unscaled-idx src))
1954        (x862-vref1 seg vreg xfer type-keyword src unscaled-idx index-known-fixnum)))))
1955
1956
1957
1958(defun x862-aset2 (seg vreg xfer  array i j new safe type-keyword  dim0 dim1)
1959  (target-arch-case
1960   (:x8632 (error "not for x8632 yet")))
1961  (with-x86-local-vinsn-macros (seg target)
1962    (let* ((i-known-fixnum (acode-fixnum-form-p i))
1963           (j-known-fixnum (acode-fixnum-form-p j))
1964           (arch (backend-target-arch *target-backend*))
1965           (is-node (member type-keyword (arch::target-gvector-types arch)))
1966           (constval (x862-constant-value-ok-for-type-keyword type-keyword new))
1967           (needs-memoization (and is-node (x862-acode-needs-memoization new)))
1968           (src)
1969           (unscaled-i)
1970           (unscaled-j)
1971           (val-reg (x862-target-reg-for-aset vreg type-keyword))
1972           (constidx
1973            (and dim0 dim1 i-known-fixnum j-known-fixnum
1974                 (>= i-known-fixnum 0)
1975                 (>= j-known-fixnum 0)
1976                 (< i-known-fixnum dim0)
1977                 (< j-known-fixnum dim1)
1978                 (+ (* i-known-fixnum dim1) j-known-fixnum))))
1979      (progn
1980        (if constidx
1981          (multiple-value-setq (src val-reg)
1982            (x862-two-targeted-reg-forms seg array ($ *x862-temp0*) new val-reg))
1983          (multiple-value-setq (src unscaled-i unscaled-j val-reg)
1984            (if needs-memoization
1985              (progn
1986                (x862-four-targeted-reg-forms seg
1987                                              array ($ *x862-temp0*)
1988                                              i ($ x8664::arg_x)
1989                                              j ($ *x862-arg-y*)
1990                                              new val-reg)
1991                (values ($ *x862-temp0*) ($ x8664::arg_x) ($ *x862-arg-y*) ($ *x862-arg-z*)))
1992              (x862-four-untargeted-reg-forms seg
1993                                              array ($ *x862-temp0*)
1994                                              i ($ x8664::arg_x)
1995                                              j ($ *x862-arg-y*)
1996                                              new val-reg))))
1997        (let* ((*available-backend-imm-temps* *available-backend-imm-temps*))
1998          (when (and (= (hard-regspec-class val-reg) hard-reg-class-gpr)
1999                     (logbitp (hard-regspec-value val-reg)
2000                              *backend-imm-temps*))
2001            (use-imm-temp (hard-regspec-value val-reg)))
2002          (when safe     
2003            (when (typep safe 'fixnum)
2004              (! trap-unless-simple-array-2
2005                 src
2006                 (dpb safe target::arrayH.flags-cell-subtag-byte
2007                      (ash 1 $arh_simple_bit))
2008                 (nx-error-for-simple-2d-array-type type-keyword)))
2009            (unless i-known-fixnum
2010              (! trap-unless-fixnum unscaled-i))
2011            (unless j-known-fixnum
2012              (! trap-unless-fixnum unscaled-j)))
2013          (with-imm-target () dim1
2014            (let* ((idx-reg ($ *x862-arg-y*)))
2015              (if constidx
2016                (if needs-memoization
2017                  (x862-lri seg *x862-arg-y* (ash constidx *x862-target-fixnum-shift*)))
2018                (progn
2019                  (if safe                 
2020                    (! check-2d-bound dim1 unscaled-i unscaled-j src)
2021                    (! 2d-dim1 dim1 src))
2022                  (! 2d-unscaled-index idx-reg dim1 unscaled-i unscaled-j)))
2023              (let* ((v ($ x8664::arg_x)))
2024                (! array-data-vector-ref v src)
2025                (x862-vset1 seg vreg xfer type-keyword v idx-reg constidx val-reg (x862-unboxed-reg-for-aset seg type-keyword val-reg safe constval) constval needs-memoization)))))))))
2026
2027
2028(defun x862-aset3 (seg vreg xfer  array i j k new safe type-keyword  dim0 dim1 dim2)
2029  (target-arch-case
2030   (:x8632 (error "not for x8632 yet")))
2031  (with-x86-local-vinsn-macros (seg target)
2032    (let* ((i-known-fixnum (acode-fixnum-form-p i))
2033           (j-known-fixnum (acode-fixnum-form-p j))
2034           (k-known-fixnum (acode-fixnum-form-p k))
2035           (arch (backend-target-arch *target-backend*))
2036           (is-node (member type-keyword (arch::target-gvector-types arch)))
2037           (constval (x862-constant-value-ok-for-type-keyword type-keyword new))
2038           (needs-memoization (and is-node (x862-acode-needs-memoization new)))
2039           (src)
2040           (unscaled-i)
2041           (unscaled-j)
2042           (unscaled-k)
2043           (val-reg (x862-target-reg-for-aset vreg type-keyword))
2044           (constidx
2045            (and dim0 dim1 dim2 i-known-fixnum j-known-fixnum k-known-fixnum
2046                 (>= i-known-fixnum 0)
2047                 (>= j-known-fixnum 0)
2048                 (>= k-known-fixnum 0)
2049                 (< i-known-fixnum dim0)
2050                 (< j-known-fixnum dim1)
2051                 (< k-known-fixnum dim2)
2052                 (+ (* i-known-fixnum dim1 dim2)
2053                    (* j-known-fixnum dim2)
2054                    k-known-fixnum))))
2055      (progn
2056        (if constidx
2057          (multiple-value-setq (src val-reg)
2058            (x862-two-targeted-reg-forms seg array ($ *x862-temp0*) new val-reg))
2059          (progn
2060            (setq src ($ x8664::temp1)
2061                  unscaled-i ($ *x862-temp0*)
2062                  unscaled-j ($ x8664::arg_x)
2063                  unscaled-k ($ *x862-arg-y*))
2064            (x862-push-register
2065             seg
2066             (x862-one-untargeted-reg-form seg array ($ *x862-arg-z*)))
2067            (x862-four-targeted-reg-forms seg
2068                                          i ($ *x862-temp0*)
2069                                          j ($ x8664::arg_x)
2070                                          k ($ *x862-arg-y*)
2071                                          new val-reg)
2072            (x862-pop-register seg src)))
2073        (let* ((*available-backend-imm-temps* *available-backend-imm-temps*))
2074          (when (and (= (hard-regspec-class val-reg) hard-reg-class-gpr)
2075                     (logbitp (hard-regspec-value val-reg)
2076                              *backend-imm-temps*))
2077            (use-imm-temp (hard-regspec-value val-reg)))
2078       
2079          (when safe     
2080            (when (typep safe 'fixnum)
2081              (! trap-unless-simple-array-3
2082                 src
2083                 (dpb safe target::arrayH.flags-cell-subtag-byte
2084                      (ash 1 $arh_simple_bit))
2085                 (nx-error-for-simple-3d-array-type type-keyword)))
2086            (unless i-known-fixnum
2087              (! trap-unless-fixnum unscaled-i))
2088            (unless j-known-fixnum
2089              (! trap-unless-fixnum unscaled-j))
2090            (unless k-known-fixnum
2091              (! trap-unless-fixnum unscaled-k)))
2092          (with-imm-target () dim1
2093            (with-imm-target (dim1) dim2
2094              (let* ((idx-reg ($ *x862-arg-y*)))
2095                (if constidx
2096                  (when needs-memoization
2097                    (x862-lri seg idx-reg (ash constidx *x862-target-fixnum-shift*)))
2098                  (progn
2099                    (if safe                 
2100                      (! check-3d-bound dim1 dim2 unscaled-i unscaled-j unscaled-k src)
2101                      (! 3d-dims dim1 dim2 src))
2102                    (! 3d-unscaled-index idx-reg dim1 dim2 unscaled-i unscaled-j unscaled-k)))
2103                (let* ((v ($ x8664::arg_x)))
2104                  (! array-data-vector-ref v src)
2105                  (x862-vset1 seg vreg xfer type-keyword v idx-reg constidx val-reg (x862-unboxed-reg-for-aset seg type-keyword val-reg safe constval) constval needs-memoization))))))))))
2106
2107
2108(defun x862-aref2 (seg vreg xfer array i j safe typekeyword &optional dim0 dim1)
2109  (target-arch-case
2110   (:x8632 (error "not for x8632 yet")))
2111  (with-x86-local-vinsn-macros (seg vreg xfer)
2112    (let* ((i-known-fixnum (acode-fixnum-form-p i))
2113           (j-known-fixnum (acode-fixnum-form-p j))
2114           (src)
2115           (unscaled-i)
2116           (unscaled-j)
2117           (constidx
2118            (and dim0 dim1 i-known-fixnum j-known-fixnum
2119                 (>= i-known-fixnum 0)
2120                 (>= j-known-fixnum 0)
2121                 (< i-known-fixnum dim0)
2122                 (< j-known-fixnum dim1)
2123                 (+ (* i-known-fixnum dim1) j-known-fixnum))))
2124      (if constidx
2125        (setq src (x862-one-targeted-reg-form seg array ($ *x862-arg-z*)))
2126        (multiple-value-setq (src unscaled-i unscaled-j)
2127          (x862-three-untargeted-reg-forms seg
2128                                           array x8664::arg_x
2129                                           i *x862-arg-y*
2130                                           j *x862-arg-z*)))
2131      (when safe       
2132        (when (typep safe 'fixnum)
2133          (! trap-unless-simple-array-2
2134             src
2135             (dpb safe target::arrayH.flags-cell-subtag-byte
2136                  (ash 1 $arh_simple_bit))
2137             (nx-error-for-simple-2d-array-type typekeyword)))
2138        (unless i-known-fixnum
2139          (! trap-unless-fixnum unscaled-i))
2140        (unless j-known-fixnum
2141          (! trap-unless-fixnum unscaled-j)))
2142      (with-node-target (src) idx-reg
2143        (with-imm-target () dim1
2144          (unless constidx
2145            (if safe                   
2146              (! check-2d-bound dim1 unscaled-i unscaled-j src)
2147              (! 2d-dim1 dim1 src))
2148            (! 2d-unscaled-index idx-reg dim1 unscaled-i unscaled-j))
2149          (with-node-target (idx-reg) v
2150            (! array-data-vector-ref v src)
2151            (x862-vref1 seg vreg xfer typekeyword v idx-reg constidx)))))))
2152
2153(defun x862-aref3 (seg vreg xfer array i j k safe typekeyword &optional dim0 dim1 dim2)
2154  (target-arch-case
2155   (:x8632 (error "not for x8632 yet")))
2156  (with-x86-local-vinsn-macros (seg vreg xfer)
2157    (let* ((i-known-fixnum (acode-fixnum-form-p i))
2158           (j-known-fixnum (acode-fixnum-form-p j))
2159           (k-known-fixnum (acode-fixnum-form-p k))
2160           (src)
2161           (unscaled-i)
2162           (unscaled-j)
2163           (unscaled-k)
2164           (constidx
2165            (and dim0 dim1 i-known-fixnum j-known-fixnum k-known-fixnum
2166                 (>= i-known-fixnum 0)
2167                 (>= j-known-fixnum 0)
2168                 (>= k-known-fixnum 0)
2169                 (< i-known-fixnum dim0)
2170                 (< j-known-fixnum dim1)
2171                 (< k-known-fixnum dim2)
2172                 (+ (* i-known-fixnum dim1 dim2)
2173                    (* j-known-fixnum dim2)
2174                    k-known-fixnum))))
2175      (if constidx
2176        (setq src (x862-one-targeted-reg-form seg array ($ *x862-arg-z*)))
2177        (multiple-value-setq (src unscaled-i unscaled-j unscaled-k)
2178          (x862-four-untargeted-reg-forms seg
2179                                           array *x862-temp0*
2180                                           i x8664::arg_x
2181                                           j *x862-arg-y*
2182                                           k *x862-arg-z*)))
2183      (when safe       
2184        (when (typep safe 'fixnum)
2185          (! trap-unless-simple-array-3
2186             src
2187             (dpb safe target::arrayH.flags-cell-subtag-byte
2188                  (ash 1 $arh_simple_bit))
2189             (nx-error-for-simple-3d-array-type typekeyword)))
2190        (unless i-known-fixnum
2191          (! trap-unless-fixnum unscaled-i))
2192        (unless j-known-fixnum
2193          (! trap-unless-fixnum unscaled-j))
2194        (unless k-known-fixnum
2195          (! trap-unless-fixnum unscaled-k)))
2196      (with-node-target (src) idx-reg
2197        (with-imm-target () dim1
2198          (with-imm-target (dim1) dim2
2199            (unless constidx
2200              (if safe                   
2201                (! check-3d-bound dim1 dim2 unscaled-i unscaled-j unscaled-k src)
2202                (! 3d-dims dim1 dim2 src))
2203              (! 3d-unscaled-index idx-reg dim1 dim2 unscaled-i unscaled-j unscaled-k))))
2204        (with-node-target (idx-reg) v
2205          (! array-data-vector-ref v src)
2206          (x862-vref1 seg vreg xfer typekeyword v idx-reg constidx))))))
2207
2208
2209
2210(defun x862-natural-vset (seg vreg xfer vector index value safe)
2211  (with-x86-local-vinsn-macros (seg vreg xfer)
2212    (let* ((index-known-fixnum (acode-fixnum-form-p index))
2213           (arch (backend-target-arch *target-backend*))
2214           (src nil)
2215           (unscaled-idx nil))
2216      (with-imm-target () (target :natural)
2217        (if (or safe (not index-known-fixnum))
2218          (multiple-value-setq (src unscaled-idx target)
2219            (x862-three-untargeted-reg-forms seg vector *x862-arg-y* index *x862-arg-z* value (or vreg target)))
2220          (multiple-value-setq (src target)
2221            (x862-two-untargeted-reg-forms seg vector *x862-arg-y* value (or vreg target))))
2222        (when safe
2223          (with-imm-temps (target) ()   ; Don't use target in type/bounds check
2224            (if (typep safe 'fixnum)
2225              (! trap-unless-typecode= src safe))
2226            (unless index-known-fixnum
2227              (! trap-unless-fixnum unscaled-idx))
2228            (! check-misc-bound unscaled-idx src)))
2229        (target-arch-case
2230         
2231         (:x8664
2232          (if (and index-known-fixnum
2233                   (<= index-known-fixnum (arch::target-max-64-bit-constant-index arch)))
2234            (! misc-set-c-u64 target src index-known-fixnum)
2235            (progn
2236              (if index-known-fixnum
2237                (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3))))
2238              (! misc-set-u64 target src unscaled-idx)))))
2239        (<- target)                     ; should be a no-op in this case
2240        (^)))))
2241
2242
2243(defun x862-constant-value-ok-for-type-keyword (type-keyword form)
2244  (let* ((arch (backend-target-arch *target-backend*))
2245         (is-node  (member type-keyword (arch::target-gvector-types arch))))
2246    (if is-node
2247      (cond ((eq form *nx-nil*)
2248             (target-nil-value))
2249            ((eq form *nx-t*)
2250             (+ (target-nil-value) (arch::target-t-offset arch)))
2251            (t
2252             (let* ((fixval (acode-fixnum-form-p form)))
2253               (if fixval
2254                 (ash fixval (arch::target-fixnum-shift arch))))))
2255      (if (and (acode-p form)
2256               (or (eq (acode-operator form) (%nx1-operator immediate))
2257                   (eq (acode-operator form) (%nx1-operator fixnum))))
2258        (let* ((val (%cadr form))
2259
2260               (typep (cond ((eq type-keyword :signed-32-bit-vector)
2261                             (typep val '(signed-byte 32)))
2262                            ((eq type-keyword :single-float-vector)
2263                             (typep val 'short-float))
2264                            ((eq type-keyword :double-float-vector)
2265                             (typep val 'double-float))
2266                            ((eq type-keyword :simple-string)
2267                             (typep val 'base-char))
2268                            ((eq type-keyword :signed-8-bit-vector)
2269                             (typep val '(signed-byte 8)))
2270                            ((eq type-keyword :unsigned-8-bit-vector)
2271                             (typep val '(unsigned-byte 8)))
2272                            ((eq type-keyword :signed-16-bit-vector) 
2273                             (typep val '(signed-byte 16)))
2274                            ((eq type-keyword :unsigned-16-bit-vector)
2275                             (typep val '(unsigned-byte 16)))
2276                            ((eq type-keyword :bit-vector)
2277                             (typep val 'bit)))))
2278          (if typep val))))))
2279
2280(defun x862-target-reg-for-aset (vreg type-keyword)
2281  (let* ((arch (backend-target-arch *target-backend*))
2282         (is-node (member type-keyword (arch::target-gvector-types arch)))
2283         (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
2284         (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
2285         (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
2286         (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
2287         (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
2288         (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
2289         (vreg-class (if (and vreg (not (eq vreg :push))) (hard-regspec-class vreg)))
2290         (vreg-mode (if (or (eql vreg-class hard-reg-class-gpr)
2291                            (eql vreg-class hard-reg-class-fpr))
2292                      (get-regspec-mode vreg)))
2293         (next-imm-target (available-imm-temp  *available-backend-imm-temps*))
2294         (next-fp-target (available-fp-temp *available-backend-fp-temps*))
2295         (acc (make-wired-lreg *x862-arg-z*)))
2296    (cond ((or is-node
2297               (eq vreg :push)
2298               is-1-bit
2299               (eq type-keyword :simple-string)
2300               (eq type-keyword :fixnum-vector)
2301               (and (eql vreg-class hard-reg-class-gpr)
2302                    (eql vreg-mode hard-reg-class-gpr-mode-node)))
2303           acc)
2304          ;; If there's no vreg - if we're setting for effect only, and
2305          ;; not for value - we can target an unboxed register directly.
2306          ;; Usually.
2307          ((null vreg)
2308           (cond (is-64-bit
2309                  (if (eq type-keyword :double-float-vector)
2310                    (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-double)
2311                    (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s64 hard-reg-class-gpr-mode-u64))))
2312                 (is-32-bit
2313                  (if (eq type-keyword :single-float-vector)
2314                    (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-single)
2315                    (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s32 hard-reg-class-gpr-mode-u32))))
2316                 (is-16-bit
2317                  (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s16 hard-reg-class-gpr-mode-u16)))
2318                 (is-8-bit
2319                  (make-unwired-lreg next-imm-target :mode (if is-signed hard-reg-class-gpr-mode-s8 hard-reg-class-gpr-mode-u8)))
2320                 (t "Bug: can't determine operand size for ~s" type-keyword)))
2321          ;; Vreg is non-null.  We might be able to use it directly.
2322          (t
2323           (let* ((lreg (if vreg-mode
2324                          (make-unwired-lreg (lreg-value vreg)))))
2325             (if 
2326               (cond
2327                 (is-64-bit
2328                  (if (eq type-keyword :double-float-vector)
2329                    (and (eql vreg-class hard-reg-class-fpr)
2330                         (eql vreg-mode hard-reg-class-fpr-mode-double))
2331                      (if is-signed
2332                        (and (eql vreg-class hard-reg-class-gpr)
2333                                 (eql vreg-mode hard-reg-class-gpr-mode-s64))
2334                        (and (eql vreg-class hard-reg-class-gpr)
2335                                 (eql vreg-mode hard-reg-class-gpr-mode-u64)))))
2336                   (is-32-bit
2337                    (if (eq type-keyword :single-float-vector)
2338                      (and (eql vreg-class hard-reg-class-fpr)
2339                               (eql vreg-mode hard-reg-class-fpr-mode-single))
2340                      (if is-signed
2341                        (and (eql vreg-class hard-reg-class-gpr)
2342                                 (or (eql vreg-mode hard-reg-class-gpr-mode-s32)
2343                                     (eql vreg-mode hard-reg-class-gpr-mode-s64)))
2344                        (and (eql vreg-class hard-reg-class-gpr)
2345                                 (or (eql vreg-mode hard-reg-class-gpr-mode-u32)
2346                                     (eql vreg-mode hard-reg-class-gpr-mode-u64)
2347                                     (eql vreg-mode hard-reg-class-gpr-mode-s64))))))
2348                   (is-16-bit
2349                    (if is-signed
2350                      (and (eql vreg-class hard-reg-class-gpr)
2351                               (or (eql vreg-mode hard-reg-class-gpr-mode-s16)
2352                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
2353                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))
2354                      (and (eql vreg-class hard-reg-class-gpr)
2355                               (or (eql vreg-mode hard-reg-class-gpr-mode-u16)
2356                                   (eql vreg-mode hard-reg-class-gpr-mode-u32)
2357                                   (eql vreg-mode hard-reg-class-gpr-mode-u64)
2358                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
2359                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))))
2360                   (t
2361                    (if is-signed
2362                      (and (eql vreg-class hard-reg-class-gpr)
2363                               (or (eql vreg-mode hard-reg-class-gpr-mode-s8)
2364                                   (eql vreg-mode hard-reg-class-gpr-mode-s16)
2365                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
2366                                   (eql vreg-mode hard-reg-class-gpr-mode-s64)))
2367                      (and (eql vreg-class hard-reg-class-gpr)
2368                               (or (eql vreg-mode hard-reg-class-gpr-mode-u8)
2369                                   (eql vreg-mode hard-reg-class-gpr-mode-u16)
2370                                   (eql vreg-mode hard-reg-class-gpr-mode-u32)
2371                                   (eql vreg-mode hard-reg-class-gpr-mode-u64)
2372                                   (eql vreg-mode hard-reg-class-gpr-mode-s16)
2373                                   (eql vreg-mode hard-reg-class-gpr-mode-s32)
2374                                   (eql vreg-mode hard-reg-class-gpr-mode-s64))))))
2375               lreg
2376               acc))))))
2377
2378(defun x862-unboxed-reg-for-aset (seg type-keyword result-reg safe constval)
2379  (with-x86-local-vinsn-macros (seg)
2380    (let* ((arch (backend-target-arch *target-backend*))
2381           (is-node (member type-keyword (arch::target-gvector-types arch)))
2382           (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
2383           (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
2384           (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
2385           (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
2386           (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector)))
2387           (result-is-node-gpr (and (eql (hard-regspec-class result-reg)
2388                                         hard-reg-class-gpr)
2389                                    (eql (get-regspec-mode result-reg)
2390                                         hard-reg-class-gpr-mode-node)))
2391           (next-imm-target (available-imm-temp *available-backend-imm-temps*))
2392           (next-fp-target (available-fp-temp *available-backend-fp-temps*)))
2393      (if (or is-node (not result-is-node-gpr))
2394        result-reg
2395        (cond (is-64-bit
2396               (if (eq type-keyword :double-float-vector)
2397                 (let* ((reg (make-unwired-lreg next-fp-target :mode hard-reg-class-fpr-mode-double)))
2398                   (if safe
2399                     (! get-double? reg result-reg)
2400                     (! get-double reg result-reg))
2401                   reg)
2402                 (if is-signed
2403                   (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s64)))
2404                     (if (eq type-keyword :fixnum-vector)
2405                       (progn
2406                         (when safe
2407                           (! trap-unless-fixnum result-reg))
2408                         (! fixnum->signed-natural reg result-reg))
2409                       (! unbox-s64 reg result-reg))
2410                     reg)
2411                   (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u64)))
2412                     (! unbox-u64 reg result-reg)
2413                     reg))))
2414              (is-32-bit
2415               ;; Generally better to use a GPR for the :SINGLE-FLOAT-VECTOR
2416               ;; case here.
2417               (if is-signed             
2418                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s32)))
2419                   (if (eq type-keyword :fixnum-vector)
2420                     (progn
2421                       (when safe
2422                         (! trap-unless-fixnum result-reg))
2423                       (! fixnum->signed-natural reg result-reg))
2424                     (! unbox-s32 reg result-reg))
2425                   reg)
2426                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u32)))
2427                   (cond ((eq type-keyword :simple-string)
2428                          (if (characterp constval)
2429                            (x862-lri seg reg (char-code constval))
2430                            (! unbox-base-char reg result-reg)))
2431                         ((eq type-keyword :single-float-vector)
2432                          (if (typep constval 'single-float)
2433                            (x862-lri seg reg (single-float-bits constval))
2434                            (progn
2435                              (when safe
2436                                (! trap-unless-single-float result-reg))
2437                              (! single-float-bits reg result-reg))))
2438                         (t
2439                          (if (typep constval '(unsigned-byte 32))
2440                            (x862-lri seg reg constval)
2441                            (if *x862-reckless*
2442                              (target-arch-case
2443                               (:x8632 (! unbox-u32 reg result-reg))
2444                               (:x8664 (! %unbox-u32 reg result-reg)))
2445                              (! unbox-u32 reg result-reg)))))
2446                   reg)))
2447              (is-16-bit
2448               (if is-signed
2449                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s16)))
2450                   (if (typep constval '(signed-byte 16))
2451                     (x862-lri seg reg constval)
2452                     (if *x862-reckless*
2453                       (! %unbox-s16 reg result-reg)
2454                       (! unbox-s16 reg result-reg)))
2455                   reg)
2456                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u16)))
2457                   (if (typep constval '(unsigned-byte 16))
2458                     (x862-lri seg reg constval)
2459                     (if *x862-reckless*
2460                       (! %unbox-u16 reg result-reg)
2461                       (! unbox-u16 reg result-reg)))
2462                   reg)))
2463              (is-8-bit
2464               (if is-signed
2465                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-s8)))
2466                   (if (typep constval '(signed-byte 8))
2467                     (x862-lri seg reg constval)
2468                     (if *x862-reckless*
2469                       (! %unbox-s8 reg result-reg)
2470                       (! unbox-s8 reg result-reg)))
2471                   reg)
2472                 (let* ((reg (make-unwired-lreg next-imm-target :mode hard-reg-class-gpr-mode-u8)))
2473                   (if (typep constval '(unsigned-byte 8))
2474                     (x862-lri seg reg constval)
2475                     (if *x862-reckless*
2476                       (! %unbox-u8 reg result-reg)
2477                       (! unbox-u8 reg result-reg)))
2478                   reg)))
2479              (t
2480                 (let* ((reg result-reg))
2481                   (unless (typep constval 'bit)
2482                     (when safe
2483                       (! trap-unless-bit reg )))
2484                   reg)))))))
2485
2486
2487;;; xxx
2488(defun x862-vset1 (seg vreg xfer type-keyword src unscaled-idx index-known-fixnum val-reg unboxed-val-reg constval node-value-needs-memoization)
2489  (with-x86-local-vinsn-macros (seg vreg xfer)
2490    (let* ((arch (backend-target-arch *target-backend*))
2491           (is-node (member type-keyword (arch::target-gvector-types arch)))
2492           (is-1-bit (member type-keyword (arch::target-1-bit-ivector-types arch)))
2493           (is-8-bit (member type-keyword (arch::target-8-bit-ivector-types arch)))
2494           (is-16-bit (member type-keyword (arch::target-16-bit-ivector-types arch)))
2495           (is-32-bit (member type-keyword (arch::target-32-bit-ivector-types arch)))
2496           (is-64-bit (member type-keyword (arch::target-64-bit-ivector-types arch)))
2497           (is-signed (member type-keyword '(:signed-8-bit-vector :signed-16-bit-vector :signed-32-bit-vector :signed-64-bit-vector :fixnum-vector))))
2498      (cond ((and is-node node-value-needs-memoization)
2499             (unless (and (eql (hard-regspec-value src) (target-arch-case
2500                                                         (:x8632 x8632::temp0)
2501                                                         (:x8664 x8664::arg_x)))
2502                          (eql (hard-regspec-value unscaled-idx) *x862-arg-y*)
2503                          (eql (hard-regspec-value val-reg) *x862-arg-z*))
2504               (compiler-bug "Bug: invalid register targeting for gvset: ~s" (list src unscaled-idx val-reg)))
2505             (! call-subprim-3 val-reg (subprim-name->offset '.SPgvset) src unscaled-idx val-reg))
2506            (is-node
2507             (if (and index-known-fixnum (<= index-known-fixnum
2508                                             (target-word-size-case
2509                                              (32 (arch::target-max-32-bit-constant-index arch))
2510                                              (64 (arch::target-max-64-bit-constant-index arch)))))
2511               (if (typep constval '(signed-byte 32))
2512                 (! misc-set-immediate-c-node constval src index-known-fixnum)
2513                 (! misc-set-c-node val-reg src index-known-fixnum))
2514               (progn
2515                 (if index-known-fixnum
2516                   (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum *x862-target-node-shift*))))
2517                 (if (typep constval '(signed-byte 32))
2518                   (! misc-set-immediate-node constval src unscaled-idx)
2519                   (! misc-set-node val-reg src unscaled-idx)))))
2520            (t
2521             (with-additional-imm-reg (src unscaled-idx val-reg)
2522               (with-imm-target (unboxed-val-reg) scaled-idx
2523                 (cond
2524                   (is-64-bit
2525                    (if (and index-known-fixnum
2526                             (<= index-known-fixnum
2527                                 (arch::target-max-64-bit-constant-index arch)))
2528                      (if (eq type-keyword :double-float-vector)
2529                        (! misc-set-c-double-float unboxed-val-reg src index-known-fixnum)
2530                        (if is-signed
2531                          (! misc-set-c-s64 unboxed-val-reg src index-known-fixnum)
2532                          (! misc-set-c-u64 unboxed-val-reg src index-known-fixnum)))
2533                      (progn
2534                        (if index-known-fixnum
2535                          (x862-absolute-natural seg unscaled-idx nil (+ (arch::target-misc-dfloat-offset arch) (ash index-known-fixnum 3))))
2536                        (if (eq type-keyword :double-float-vector)
2537                          (! misc-set-double-float unboxed-val-reg src unscaled-idx)
2538                          (if is-signed
2539                            (! misc-set-s64 unboxed-val-reg src unscaled-idx)
2540                            (! misc-set-u64 unboxed-val-reg src unscaled-idx))))))
2541                   (is-32-bit
2542                    (if (and index-known-fixnum
2543                             (<= index-known-fixnum
2544                                 (arch::target-max-32-bit-constant-index arch)))
2545                      (if (eq type-keyword :single-float-vector)
2546                        (if (eq (hard-regspec-class unboxed-val-reg)
2547                                hard-reg-class-fpr)
2548                          (! misc-set-c-single-float unboxed-val-reg src index-known-fixnum)
2549                          (! misc-set-c-u32 unboxed-val-reg src index-known-fixnum))
2550                        (if is-signed
2551                          (! misc-set-c-s32 unboxed-val-reg src index-known-fixnum)
2552                          (! misc-set-c-u32 unboxed-val-reg src index-known-fixnum)))
2553                      (progn
2554                        (if index-known-fixnum
2555                          (x862-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 2)))
2556                          (! scale-32bit-misc-index scaled-idx unscaled-idx))
2557                        (if (and (eq type-keyword :single-float-vector)
2558                                 (eql (hard-regspec-class unboxed-val-reg)
2559                                      hard-reg-class-fpr))
2560                          (! misc-set-single-float unboxed-val-reg src scaled-idx)
2561                          (if is-signed
2562                            (! misc-set-s32 unboxed-val-reg src scaled-idx)
2563                            (! misc-set-u32 unboxed-val-reg src scaled-idx))))))
2564                   (is-16-bit
2565                    (if (and index-known-fixnum
2566                             (<= index-known-fixnum
2567                                 (arch::target-max-16-bit-constant-index arch)))
2568                      (if is-signed
2569                        (! misc-set-c-s16 unboxed-val-reg src index-known-fixnum)
2570                        (! misc-set-c-u16 unboxed-val-reg src index-known-fixnum))
2571                      (progn
2572                        (if index-known-fixnum
2573                          (x862-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 1)))
2574                          (! scale-16bit-misc-index scaled-idx unscaled-idx))
2575                        (if is-signed
2576                          (! misc-set-s16 unboxed-val-reg src scaled-idx)
2577                          (! misc-set-u16 unboxed-val-reg src scaled-idx)))))
2578                   (is-8-bit
2579                    (if (and index-known-fixnum
2580                             (<= index-known-fixnum
2581                                 (arch::target-max-8-bit-constant-index arch)))
2582                      (if is-signed
2583                        (! misc-set-c-s8 unboxed-val-reg src index-known-fixnum)
2584                        (! misc-set-c-u8  unboxed-val-reg src index-known-fixnum))
2585                      (progn
2586                        (if index-known-fixnum
2587                          (x862-absolute-natural seg scaled-idx nil (+ (arch::target-misc-data-offset arch) index-known-fixnum))
2588                          (! scale-8bit-misc-index scaled-idx unscaled-idx))
2589                        (if is-signed
2590                          (! misc-set-s8 unboxed-val-reg src scaled-idx)
2591                          (! misc-set-u8 unboxed-val-reg src scaled-idx)))))
2592                   (is-1-bit
2593                    (if (and index-known-fixnum (<= index-known-fixnum (arch::target-max-1-bit-constant-index arch)))
2594                      (if constval
2595                        (if (zerop constval)
2596                          (! set-constant-bit-to-zero src index-known-fixnum)
2597                          (! set-constant-bit-to-one src index-known-fixnum))
2598                        (progn
2599                          (! set-constant-bit-to-variable-value src index-known-fixnum val-reg)))
2600                      (progn
2601                        (if index-known-fixnum
2602                          (x862-lri seg scaled-idx index-known-fixnum)
2603                          (! scale-1bit-misc-index scaled-idx unscaled-idx))
2604                        (if constval
2605                          (if (zerop constval)
2606                            (! nset-variable-bit-to-zero src scaled-idx)
2607                            (! nset-variable-bit-to-one src scaled-idx))
2608                          (progn
2609                            (! nset-variable-bit-to-variable-value src scaled-idx val-reg)))))))))))
2610      (when (and vreg val-reg) (<- val-reg))
2611      (^))))
2612
2613
2614(defun x862-code-coverage-entry (seg note)
2615 (let* ((afunc *x862-cur-afunc*))
2616   (setf (afunc-bits afunc) (%ilogior (afunc-bits afunc) (ash 1 $fbitccoverage)))
2617   (with-x86-local-vinsn-macros (seg)
2618     (let* ((ccreg ($ x8664::arg_x)))
2619       (! vpush-register ccreg)
2620       (! ref-constant ccreg (x86-immediate-label note))
2621       (! misc-set-immediate-c-node 0 ccreg 1)
2622       (! vpop-register ccreg)))))
2623
2624(defun x862-vset (seg vreg xfer type-keyword vector index value safe)
2625  (with-x86-local-vinsn-macros (seg)
2626    (let* ((arch (backend-target-arch *target-backend*))
2627           (is-node (member type-keyword (arch::target-gvector-types arch)))
2628           (constval (x862-constant-value-ok-for-type-keyword type-keyword value))
2629           (needs-memoization (and is-node (x862-acode-needs-memoization value)))
2630           (index-known-fixnum (acode-fixnum-form-p index)))
2631      (let* ((src (target-arch-case
2632                   (:x8632 ($ x8632::temp0))
2633                   (:x8664 ($ x8664::arg_x))))
2634             (unscaled-idx ($ *x862-arg-y*))
2635             (result-reg ($ *x862-arg-z*)))
2636        (cond (needs-memoization
2637               (x862-three-targeted-reg-forms seg
2638                                              vector src
2639                                              index unscaled-idx
2640                                              value result-reg))
2641              (t
2642               (setq result-reg (x862-target-reg-for-aset vreg type-keyword))
2643               (target-arch-case
2644                (:x8632
2645                 (with-node-temps (src) ()
2646                   (x862-three-targeted-reg-forms seg
2647                                                  vector src
2648                                                  index unscaled-idx
2649                                                  value result-reg)))
2650                (:x8664
2651                 (multiple-value-setq (src unscaled-idx result-reg)
2652                   (x862-three-untargeted-reg-forms seg
2653                                                  vector src
2654                                                  index unscaled-idx
2655                                                  value result-reg))))))
2656        (when safe
2657          (let* ((*available-backend-imm-temps* *available-backend-imm-temps*)
2658                 (value (if (eql (hard-regspec-class result-reg)
2659                                 hard-reg-class-gpr)
2660                          (hard-regspec-value result-reg)))
2661                 (result-is-imm nil))
2662            (when (and value (logbitp value *available-backend-imm-temps*))
2663              (setq *available-backend-imm-temps* (bitclr value *available-backend-imm-temps*))
2664              (setq result-is-imm t))
2665            (if (typep safe 'fixnum)
2666              (if result-is-imm
2667                (with-additional-imm-reg (src safe)
2668                  (! trap-unless-typecode= src safe))
2669                (! trap-unless-typecode= src safe)))
2670            (unless index-known-fixnum
2671              (! trap-unless-fixnum unscaled-idx))
2672            (if result-is-imm
2673              (with-additional-imm-reg (unscaled-idx src)
2674                (! check-misc-bound unscaled-idx src))
2675              (! check-misc-bound unscaled-idx src))))
2676        (x862-vset1 seg vreg xfer type-keyword src unscaled-idx index-known-fixnum result-reg (x862-unboxed-reg-for-aset seg type-keyword result-reg safe constval) constval needs-memoization)))))
2677
2678
2679
2680(defun x862-tail-call-alias (immref sym &optional arglist)
2681  (let ((alias (cdr (assq sym *x862-tail-call-aliases*))))
2682    (if (and alias (or (null arglist) (eq (+ (length (car arglist)) (length (cadr arglist))) (cdr alias))))
2683      (make-acode (%nx1-operator immediate) (car alias))
2684      immref)))
2685
2686;;; If BODY is essentially an APPLY involving an &rest arg, try to avoid
2687;;; consing it.
2688(defun x862-eliminate-&rest (body rest key-p auxen rest-values)
2689  (when (and rest (not key-p) (not (cadr auxen)) rest-values)
2690    (when (eq (logand (the fixnum (nx-var-bits rest))
2691                      (logior $vsetqmask (ash -1 $vbitspecial)
2692                              (ash 1 $vbitclosed) (ash 1 $vbitsetq) (ash 1 $vbitcloseddownward)))
2693              0)               ; Nothing but simple references
2694      (do* ()
2695           ((not (acode-p body)))
2696        (let* ((op (acode-operator body)))
2697          (if (or (eq op (%nx1-operator lexical-function-call))
2698                  (eq op (%nx1-operator call)))
2699            (destructuring-bind (fn-form (stack-args reg-args) &optional spread-p) (%cdr body)
2700               (unless (and (eq spread-p t)
2701                           (eq (x862-lexical-reference-p (%car reg-args)) rest))
2702                (return nil))
2703              (flet ((independent-of-all-values (form)       
2704                       (setq form (acode-unwrapped-form-value form))
2705                       (or (x86-constant-form-p form)
2706                           (let* ((lexref (x862-lexical-reference-p form)))
2707                             (and lexref 
2708                                  (neq lexref rest)
2709                                  (dolist (val rest-values t)
2710                                    (unless (x862-var-not-set-by-form-p lexref val)
2711                                      (return))))))))
2712                (unless (or (eq op (%nx1-operator lexical-function-call))
2713                            (independent-of-all-values fn-form))
2714                  (return nil))
2715                (if (dolist (s stack-args t)
2716                          (unless (independent-of-all-values s)
2717                            (return nil)))
2718                  (let* ((arglist (append stack-args rest-values)))
2719                    (return
2720                     (make-acode op 
2721                                 fn-form 
2722                                 (if (<= (length arglist) *x862-target-num-arg-regs*)
2723                                   (list nil (reverse arglist))
2724                                   (list (butlast arglist *x862-target-num-arg-regs*)
2725                                         (reverse (last arglist *x862-target-num-arg-regs*))))
2726                                 nil)))
2727                  (return nil))))
2728            (if (eq op (%nx1-operator local-block))
2729              (setq body (%cadr body))
2730              (if (and (eq op (%nx1-operator if))
2731                       (eq (x862-lexical-reference-p (%cadr body)) rest))
2732                (setq body (%caddr body))
2733                (return nil)))))))))
2734
2735(defun x862-call-fn (seg vreg xfer fn arglist spread-p)
2736  (with-x86-local-vinsn-macros (seg vreg xfer)
2737    (when spread-p
2738      (destructuring-bind (stack-args reg-args) arglist
2739        (when (and (null (cdr reg-args))
2740                   (nx-null (acode-unwrapped-form-value (car reg-args))))
2741          (setq spread-p nil)
2742          (let* ((nargs (length stack-args)))
2743            (declare (fixnum nargs))
2744            (if (<= nargs *x862-target-num-arg-regs*)
2745              (setq arglist (list nil (reverse stack-args)))
2746              (setq arglist (list (butlast stack-args *x862-target-num-arg-regs*) (reverse (last stack-args *x862-target-num-arg-regs*)))))))))
2747    (let* ((lexref (x862-lexical-reference-p fn))
2748           (simple-case (or (fixnump fn)
2749                            (typep fn 'lreg)
2750                            (x862-immediate-function-p fn)
2751                            (and 
2752                             lexref
2753                             (not spread-p)
2754                             (flet ((all-simple (args)
2755                                      (dolist (arg args t)
2756                                        (when (and arg (not (x862-var-not-set-by-form-p lexref arg)))
2757                                          (return)))))
2758                               (and (all-simple (car arglist))
2759                                    (all-simple (cadr arglist))
2760                                    (setq fn (var-ea lexref)))))))
2761           (cstack *x862-cstack*)
2762           (top *x862-top-vstack-lcell*)
2763           (vstack *x862-vstack*))
2764      (setq xfer (or xfer 0))
2765      (when (and (eq xfer $backend-return)
2766                 (eq 0 *x862-undo-count*)
2767                 (acode-p fn)
2768                 (eq (acode-operator fn) (%nx1-operator immediate))
2769                 (symbolp (cadr fn)))
2770        (setq fn (x862-tail-call-alias fn (%cadr fn) arglist)))
2771     
2772      (if (and (eq xfer $backend-return) (not (x862-tailcallok xfer)))
2773        (progn
2774          (x862-call-fn seg vreg $backend-mvpass fn arglist spread-p)
2775          (x862-set-vstack (%i+ (if simple-case 0 *x862-target-node-size*) vstack))
2776          (setq  *x862-cstack* cstack)
2777          (let ((*x862-returning-values* t)) (x862-do-return seg)))
2778        (let* ((mv-p (x862-mv-p xfer))
2779               (mv-return-label (if (and mv-p
2780                                         (not (x862-tailcallok xfer)))
2781                                  (backend-get-next-label))))
2782          (unless simple-case
2783            (x862-vpush-register seg (x862-one-untargeted-reg-form seg fn *x862-arg-z*))
2784            (setq fn (x862-vloc-ea vstack)))
2785          (x862-invoke-fn seg fn (x862-arglist seg arglist mv-return-label) spread-p xfer mv-return-label)
2786          (if (and (logbitp $backend-mvpass-bit xfer)
2787                   (not simple-case))
2788            (progn
2789              (! save-values)
2790              (! vstack-discard 1)
2791              (x862-set-nargs seg 0)
2792              (! recover-values))
2793            (unless (or mv-p simple-case)
2794              (! vstack-discard 1)))
2795          (x862-set-vstack vstack)
2796          (setq *x862-top-vstack-lcell* top)
2797          (setq *x862-cstack* cstack)
2798          (when (or (logbitp $backend-mvpass-bit xfer) (not mv-p))
2799            (<- *x862-arg-z*)
2800            (x862-branch seg (logand (lognot $backend-mvpass-mask) xfer)))))
2801      nil)))
2802
2803(defun x862-restore-full-lisp-context (seg)
2804  (with-x86-local-vinsn-macros (seg)
2805    (! restore-full-lisp-context)))
2806
2807(defun x862-emit-aligned-label (seg labelnum)
2808  (with-x86-local-vinsn-macros (seg)
2809    (! emit-aligned-label (aref *backend-labels* labelnum))
2810    (@ labelnum)
2811    (target-arch-case
2812     (:x8632
2813      (! recover-fn))
2814     (:x8664
2815      (! recover-fn-from-rip)))))
2816
2817 
2818(defun x862-call-symbol (seg jump-p)
2819  (with-x86-local-vinsn-macros (seg)
2820    (if jump-p
2821      (! jump-known-symbol)
2822      (! call-known-symbol *x862-arg-z*))))
2823
2824;;; Nargs = nil -> multiple-value case.
2825(defun x862-invoke-fn (seg fn nargs spread-p xfer &optional mvpass-label)
2826  (with-x86-local-vinsn-macros (seg)
2827    (let* ((f-op (acode-unwrapped-form-value fn))
2828           (immp (and (consp f-op)
2829                      (eq (%car f-op) (%nx1-operator immediate))))
2830           (symp (and immp (symbolp (%cadr f-op))))
2831           (label-p (and (fixnump fn) 
2832                         (locally (declare (fixnum fn))
2833                           (and (= fn -2) (- fn)))))
2834           (tail-p (eq xfer $backend-return))
2835           (func (if (consp f-op) (%cadr f-op)))
2836           (a-reg nil)
2837           (lfunp (and (acode-p f-op) 
2838                       (eq (acode-operator f-op) (%nx1-operator simple-function))))
2839           (expression-p (or (typep fn 'lreg) (and (fixnump fn) (not label-p))))
2840           (callable (or symp lfunp label-p))
2841           (destreg (if symp ($ *x862-fname*) (unless label-p ($ *x862-temp0*))))
2842           (alternate-tail-call
2843            (and tail-p label-p *x862-tail-label* (eql nargs *x862-tail-nargs*) (not spread-p))))
2844      (when expression-p
2845        ;;Have to do this before spread args, since might be vsp-relative.
2846        (if nargs
2847          (x862-do-lexical-reference seg destreg fn)
2848          (x862-copy-register seg destreg fn)))
2849      (if (or symp lfunp)
2850        (setq func (if symp
2851                     (x862-symbol-entry-locative func)
2852                     (x862-afunc-lfun-ref func))
2853              a-reg (x862-register-constant-p func)))
2854      (when tail-p
2855        #-no-compiler-bugs
2856        (unless (or immp symp lfunp (typep fn 'lreg) (fixnump fn)) (compiler-bug "Well, well, well.  How could this have happened ?"))
2857        (when a-reg
2858          (x862-copy-register seg destreg a-reg))
2859        (unless spread-p
2860          (unless alternate-tail-call
2861            (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* (and nargs (<= nargs *x862-target-num-arg-regs*))))))
2862      (if spread-p
2863        (progn
2864          (x862-set-nargs seg (%i- nargs 1))
2865                                        ; .SPspread-lexpr-z & .SPspreadargz preserve temp1
2866          (target-arch-case
2867           (:x8632
2868            (! save-node-register-to-spill-area *x862-temp0*)))
2869          (if (eq spread-p 0)
2870            (! spread-lexpr)
2871            (! spread-list))
2872          (target-arch-case
2873           (:x8632
2874            (! load-node-register-from-spill-area *x862-temp0*)))
2875
2876          (when (and tail-p *x862-register-restore-count*)
2877            (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* nil)))
2878        (if nargs
2879          (unless alternate-tail-call (x862-set-nargs seg nargs))
2880          (! pop-argument-registers)))
2881      (if callable
2882        (if (not tail-p)
2883          (if (x862-mvpass-p xfer)
2884            (let* ((call-reg (if symp ($ *x862-fname*) ($ *x862-temp0*))))
2885              (unless mvpass-label (compiler-bug "no label for mvpass"))
2886              (if label-p
2887                (x862-copy-register seg call-reg ($ *x862-fn*))
2888                (if a-reg
2889                  (x862-copy-register seg call-reg  a-reg)
2890                  (x862-store-immediate seg func call-reg)))
2891              (if symp
2892                (! pass-multiple-values-symbol)
2893                (! pass-multiple-values))
2894              (when mvpass-label
2895                (@= mvpass-label)))
2896            (progn 
2897              (if label-p
2898                (progn
2899                  (! call-label (aref *backend-labels* 2)))
2900                (progn
2901                  (if a-reg
2902                    (x862-copy-register seg destreg a-reg)
2903                    (x862-store-immediate seg func destreg))
2904                  (if symp
2905                    (x862-call-symbol seg nil)
2906                    (! call-known-function))))))
2907          (if alternate-tail-call
2908            (progn
2909              (x862-unwind-stack seg xfer 0 0 *x862-tail-vsp*)
2910              (! jump (aref *backend-labels* *x862-tail-label*)))
2911            (progn
2912              (x862-unwind-stack seg xfer 0 0 #x7fffff)
2913              (if (and (not spread-p) nargs (%i<= nargs *x862-target-num-arg-regs*))
2914                (progn
2915                  (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
2916                  (x862-restore-full-lisp-context seg)
2917                  (if label-p
2918                    (! jump (aref *backend-labels* 1))
2919                    (progn
2920                      (if symp
2921                        (x862-call-symbol seg t)
2922                        (! jump-known-function)))))
2923                (progn
2924                  (unless (or label-p a-reg) (x862-store-immediate seg func destreg))
2925                  (when label-p
2926                    (x862-copy-register seg *x862-temp0* *x862-fn*))
2927
2928                  (cond ((or spread-p (null nargs))
2929                         (if symp
2930                           (! tail-call-sym-gen)
2931                           (! tail-call-fn-gen)))
2932                        ((%i> nargs *x862-target-num-arg-regs*)
2933                         (if symp
2934                           (! tail-call-sym-slide)
2935                           (! tail-call-fn-slide)))
2936                        (t
2937                         (if symp
2938                           (! tail-call-sym-vsp)
2939                           (! tail-call-fn-vsp)))))))))
2940        ;; The general (funcall) case: we don't know (at compile-time)
2941        ;; for sure whether we've got a symbol or a (local, constant)
2942        ;; function.
2943        (progn
2944          (unless (or (fixnump fn) (typep fn 'lreg))
2945            (x862-one-targeted-reg-form seg fn destreg))
2946          (if (not tail-p)
2947            (if (x862-mvpass-p xfer)
2948              (progn (! pass-multiple-values)
2949                     (when mvpass-label
2950                       (@= mvpass-label)))
2951              (! funcall))                 
2952            (cond ((or (null nargs) spread-p)
2953                   (! tail-funcall-gen))
2954                  ((%i> nargs *x862-target-num-arg-regs*)
2955                   (! tail-funcall-slide))
2956                  (t
2957                   (! restore-full-lisp-context)
2958                   (! tail-funcall)))))))
2959    nil))
2960
2961(defun x862-seq-fbind (seg vreg xfer vars afuncs body p2decls)
2962  (let* ((old-stack (x862-encode-stack))
2963         (copy afuncs)
2964         (func nil))
2965    (with-x86-p2-declarations p2decls 
2966      (dolist (var vars) 
2967        (when (neq 0 (afunc-fn-refcount (setq func (pop afuncs))))
2968          (x862-seq-bind-var seg var (nx1-afunc-ref func))))
2969      (x862-undo-body seg vreg xfer body old-stack)
2970      (dolist (var vars)
2971        (when (neq 0 (afunc-fn-refcount (setq func (pop copy))))
2972          (x862-close-var seg var))))))
2973
2974(defun x862-make-closure (seg afunc downward-p)
2975  (with-x86-local-vinsn-macros (seg)
2976    (flet ((var-to-reg (var target)
2977             (let* ((ea (var-ea (var-bits var))))
2978               (if ea
2979                 (x862-addrspec-to-reg seg (x862-ea-open ea) target)
2980                 (! load-nil target))
2981               target))
2982           (set-some-cells (dest cellno c0 c1 c2 c3)
2983             (declare (fixnum cellno))
2984             (! misc-set-c-node c0 dest cellno)
2985             (incf cellno)
2986             (when c1
2987               (! misc-set-c-node c1 dest cellno)
2988               (incf cellno)
2989               (when c2
2990                 (! misc-set-c-node c2 dest cellno)
2991                 (incf cellno)
2992                 (when c3
2993                   (! misc-set-c-node c3 dest cellno)
2994                   (incf cellno))))
2995             cellno))
2996      (let* ((inherited-vars (afunc-inherited-vars afunc))
2997             (arch (backend-target-arch *target-backend*))
2998             (dest ($ *x862-arg-z*))
2999             (vsize (+ (length inherited-vars)
3000                       (target-arch-case
3001                        (:x8632 7)
3002                        (:x8664 5))     ; %closure-code%, afunc
3003                       1)))             ; lfun-bits
3004        (declare (list inherited-vars))
3005        (let* ((cell (target-arch-case (:x8632 6)
3006                                       (:x8664 4))))
3007          (declare (fixnum cell))
3008          (if downward-p
3009            (progn
3010              (! make-fixed-stack-gvector
3011                 dest
3012                 (ash (logandc2 (+ vsize 2) 1) (arch::target-word-shift arch))
3013                 (arch::make-vheader vsize (nx-lookup-target-uvector-subtag :function)))
3014              (x862-open-undo $undostkblk))
3015            (progn
3016              (x862-lri seg
3017                        *x862-imm0*
3018                        (arch::make-vheader vsize (nx-lookup-target-uvector-subtag :function)))
3019              (target-arch-case
3020               (:x8632
3021                (! setup-uvector-allocation *x862-imm0*)
3022                (x862-lri seg *x862-imm0* (- (ash (logandc2 (+ vsize 2) 1) (arch::target-word-shift arch)) x8632::fulltag-misc)))
3023               (:x8664
3024                (x862-lri seg x8664::imm1 (- (ash (logandc2 (+ vsize 2) 1) (arch::target-word-shift arch)) x8664::fulltag-misc))))
3025              (! %allocate-uvector dest)))
3026          (! init-nclosure *x862-arg-z*)
3027          ;;; xxx --- x8632 likely to have register conflicts with *x862-ra0*
3028          (x862-store-immediate seg (x862-afunc-lfun-ref afunc) *x862-ra0*)
3029          (target-arch-case
3030           (:x8632
3031            (with-node-temps (*x862-arg-z*) (t0)
3032              (do* ((func *x862-ra0* nil))
3033                   ((null inherited-vars))
3034                (let* ((t0r (or func (if inherited-vars
3035                                       (var-to-reg (pop inherited-vars) t0)))))
3036                  (! misc-set-c-node t0r dest cell)
3037                  (incf cell)))))
3038           (:x8664
3039            (with-node-temps (*x862-arg-z*) (t0 t1 t2 t3)
3040              (do* ((func *x862-ra0* nil))
3041                   ((null inherited-vars))
3042                (let* ((t0r (or func (if inherited-vars (var-to-reg (pop inherited-vars) t0))))
3043                       (t1r (if inherited-vars (var-to-reg (pop inherited-vars) t1)))
3044                       (t2r (if inherited-vars (var-to-reg (pop inherited-vars) t2)))
3045                       (t3r (if inherited-vars (var-to-reg (pop inherited-vars) t3))))
3046                  (setq cell (set-some-cells dest cell t0r t1r t2r t3r)))))))
3047          (x862-lri seg *x862-arg-y* (ash (logior (ash -1 $lfbits-noname-bit) (ash 1 $lfbits-trampoline-bit)) *x862-target-fixnum-shift*))
3048          (! misc-set-c-node *x862-arg-y* dest cell))
3049        (! finalize-closure dest)
3050        dest))))
3051       
3052(defun x862-symbol-entry-locative (sym)
3053  (setq sym (require-type sym 'symbol))
3054  (when (eq sym '%call-next-method-with-args)
3055    (setf (afunc-bits *x862-cur-afunc*)
3056          (%ilogior (%ilsl $fbitnextmethargsp 1) (afunc-bits *x862-cur-afunc*))))
3057  (or (assq sym *x862-fcells*)
3058      (let ((new (list sym)))
3059        (push new *x862-fcells*)
3060        new)))
3061
3062(defun x862-symbol-value-cell (sym)
3063  (setq sym (require-type sym 'symbol))
3064  (or (assq sym *x862-vcells*)
3065      (let ((new (list sym)))
3066        (push new *x862-vcells*)
3067        (ensure-binding-index sym)
3068        new)))
3069
3070
3071(defun x862-symbol-locative-p (imm)
3072  (and (consp imm)
3073       (or (memq imm *x862-vcells*)
3074           (memq imm *x862-fcells*))))
3075
3076
3077
3078
3079(defun x862-immediate-function-p (f)
3080  (setq f (acode-unwrapped-form-value f))
3081  (and (acode-p f)
3082       (or (eq (%car f) (%nx1-operator immediate))
3083           (eq (%car f) (%nx1-operator simple-function)))))
3084
3085(defun x86-constant-form-p (form)
3086  (setq form (nx-untyped-form form))
3087  (if form
3088    (or (nx-null form)
3089        (nx-t form)
3090        (and (consp form)
3091             (or (eq (acode-operator form) (%nx1-operator immediate))
3092                 (eq (acode-operator form) (%nx1-operator fixnum))
3093                 (eq (acode-operator form) (%nx1-operator simple-function)))))))
3094
3095
3096 
3097(defun x862-integer-constant-p (form mode)
3098  (let* ((val 
3099         (or (acode-fixnum-form-p (setq form (acode-unwrapped-form form)))
3100             (and (acode-p form)
3101                  (eq (acode-operator form) (%nx1-operator immediate))
3102                  (setq form (%cadr form))
3103                  (if (typep form 'integer)
3104                    form)))))
3105    (when val
3106      (let* ((type (mode-specifier-type mode))
3107             (high (numeric-ctype-high type))
3108             (low (numeric-ctype-low type)))
3109        (if (and (>= val low)
3110                 (<= val high))
3111          val
3112          (if (<= (integer-length val) (integer-length (- high low)))
3113            (if (eql 0 low)             ; type is unsigned, value is negative
3114              (logand high val)
3115              (- val (1+ (- high low))))))))))
3116
3117         
3118
3119
3120(defun x86-side-effect-free-form-p (form)
3121  (when (consp (setq form (acode-unwrapped-form-value form)))
3122    (or (x86-constant-form-p form)
3123        ;(eq (acode-operator form) (%nx1-operator bound-special-ref))
3124        (if (eq (acode-operator form) (%nx1-operator lexical-reference))
3125          (not (%ilogbitp $vbitsetq (nx-var-bits (%cadr form))))))))
3126
3127(defun x862-formlist (seg stkargs &optional revregargs)
3128  (with-x86-local-vinsn-macros (seg) 
3129    (let* ((nregs (length revregargs))
3130           (n nregs))
3131      (declare (fixnum n))
3132      (dolist (arg stkargs)
3133        (let* ((pushform (x862-acode-operator-supports-push arg)))
3134          (if pushform
3135            (progn
3136              (x862-form seg :push nil pushform)
3137              (x862-new-vstack-lcell :outgoing-argument *x862-target-lcell-size* 0 nil)
3138              (x862-adjust-vstack *x862-target-node-size*))
3139             
3140            (let* ((reg (x862-one-untargeted-reg-form seg arg *x862-arg-z*)))
3141              (x862-vpush-register-arg seg reg)))
3142          (incf n)))
3143      (when revregargs
3144        (let* ((zform (%car revregargs))
3145               (yform (%cadr revregargs))
3146               (xform (%caddr revregargs)))
3147          (if (eq 3 nregs)
3148            (progn
3149              (target-arch-case (:x8632 (compiler-bug "3 reg args on x8632?")))
3150              (x862-three-targeted-reg-forms seg xform ($ x8664::arg_x)
3151                                             yform ($ *x862-arg-y*)
3152                                             zform ($ *x862-arg-z*)))
3153            (if (eq 2 nregs)
3154              (x862-two-targeted-reg-forms seg yform ($ *x862-arg-y*) zform ($ *x862-arg-z*))
3155              (x862-one-targeted-reg-form seg zform ($ *x862-arg-z*))))))
3156      n)))
3157
3158(defun x862-arglist (seg args &optional mv-label)
3159  (with-x86-local-vinsn-macros (seg)
3160    (when mv-label
3161      (x862-vpush-label seg (aref *backend-labels* mv-label)))
3162    (when (car args)
3163      (! reserve-outgoing-frame)
3164      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil)
3165      (x862-new-vstack-lcell :reserved *x862-target-lcell-size* 0 nil)
3166      (setq *x862-vstack* (+  *x862-vstack* (* 2 *x862-target-node-size*))))
3167    (x862-formlist seg (car args) (cadr args))))
3168
3169
3170(defun x862-unboxed-integer-arg-to-reg (seg form immreg &optional ffi-arg-type)
3171  (let* ((mode (ecase ffi-arg-type
3172                 ((nil) :natural)
3173                 (:signed-byte :s8)
3174                 (:unsigned-byte :u8)
3175                 (:signed-halfword :s16)
3176                 (:unsigned-halfword :u16)
3177                 (:signed-fullword :s32)
3178                 (:unsigned-fullword :u32)
3179                 (:unsigned-doubleword :u64)
3180                 (:signed-doubleword :s64)))
3181         (modeval (gpr-mode-name-value mode)))
3182    (with-x86-local-vinsn-macros (seg)
3183      (let* ((value (x862-integer-constant-p form mode)))
3184        (if value
3185          (progn
3186            (unless (typep immreg 'lreg)
3187              (setq immreg (make-unwired-lreg immreg :mode modeval)))
3188            (if (< value 0)
3189              (x862-lri seg immreg value)
3190              (x862-lriu seg immreg value))
3191            immreg)
3192          (progn 
3193            (x862-one-targeted-reg-form seg form (make-wired-lreg *x862-imm0* :mode modeval))))))))
3194
3195
3196(defun x862-macptr-arg-to-reg (seg form address-reg) 
3197  (x862-one-targeted-reg-form seg
3198                              form 
3199                              address-reg))
3200
3201
3202(defun x862-one-lreg-form (seg form lreg)
3203  (let ((is-float (= (hard-regspec-class lreg) hard-reg-class-fpr)))
3204    (if is-float
3205      (x862-form-float seg lreg nil form)
3206      (x862-form seg lreg nil form))
3207    lreg))
3208
3209(defun x862-one-targeted-reg-form (seg form reg)
3210  (x862-one-lreg-form seg form reg))
3211
3212(defun x862-one-untargeted-lreg-form (seg form reg)
3213  (x862-one-lreg-form seg form (if (typep reg 'lreg) reg (make-unwired-lreg reg))))
3214
3215(defun x862-one-untargeted-reg-form (seg form suggested)
3216  (with-x86-local-vinsn-macros (seg)
3217    (let* ((gpr-p (= (hard-regspec-class suggested) hard-reg-class-gpr))
3218           (node-p (if gpr-p (= (get-regspec-mode suggested) hard-reg-class-gpr-mode-node))))
3219      (if node-p
3220        (let* ((ref (x862-lexical-reference-ea form))
3221               (reg (backend-ea-physical-reg ref hard-reg-class-gpr)))
3222          (if reg
3223            ref
3224            (if (nx-null form)
3225              (progn
3226                (! load-nil suggested)
3227                suggested)
3228              (if (and (acode-p form) 
3229                       (eq (acode-operator form) (%nx1-operator immediate)) 
3230                       (setq reg (x862-register-constant-p (cadr form))))
3231                reg
3232                (x862-one-untargeted-lreg-form seg form suggested)))))
3233        (x862-one-untargeted-lreg-form seg form suggested)))))
3234             
3235
3236
3237
3238(defun x862-push-register (seg areg)
3239  (let* ((a-float (= (hard-regspec-class areg) hard-reg-class-fpr))
3240         (a-single (if a-float (= (get-regspec-mode areg) hard-reg-class-fpr-mode-single)))
3241         (a-node (unless a-float (= (get-regspec-mode areg) hard-reg-class-gpr-mode-node)))
3242         vinsn)
3243    (with-x86-local-vinsn-macros (seg)
3244      (if a-node
3245        (setq vinsn (x862-vpush-register seg areg :node-temp))
3246        (if a-single
3247          (target-arch-case
3248           (:x8632
3249            (setq vinsn (! temp-push-single-float areg))
3250            (x862-open-undo $undo-x86-c-frame))
3251           (:x8664
3252            (setq vinsn (! vpush-single-float areg))
3253            (x862-new-vstack-lcell :single-float *x862-target-lcell-size* 0 nil)
3254            (x862-adjust-vstack *x862-target-node-size*)))
3255          (target-arch-case
3256           (:x8632
3257            (if a-float
3258              (progn
3259                (setq vinsn (! temp-push-double-float areg))
3260                (x862-open-undo $undo-x86-c-frame))
3261              (progn
3262                (setq vinsn (! temp-push-unboxed-word areg))
3263                (x862-open-undo $undo-x86-c-frame))))
3264           (:x8664
3265            (setq vinsn
3266                  (if a-float
3267                    (! temp-push-double-float areg)
3268                    (! temp-push-unboxed-word areg)))
3269            (x862-open-undo $undo-x86-c-frame)))))
3270      vinsn)))
3271
3272
3273
3274(defun x862-pop-register (seg areg)
3275  (let* ((a-float (= (hard-regspec-class areg) hard-reg-class-fpr))
3276         (a-single (if a-float (= (get-regspec-mode areg) hard-reg-class-fpr-mode-single)))
3277         (a-node (unless a-float (= (get-regspec-mode areg) hard-reg-class-gpr-mode-node)))
3278         vinsn)
3279    (with-x86-local-vinsn-macros (seg)
3280      (if a-node
3281        (setq vinsn (x862-vpop-register seg areg))
3282        (if a-single
3283          (target-arch-case
3284           (:x8632
3285            (setq vinsn (! temp-pop-single-float areg))
3286            (x862-close-undo))
3287           (:x8664
3288            (setq vinsn (! vpop-single-float areg))
3289            (setq *x862-top-vstack-lcell* (lcell-parent *x862-top-vstack-lcell*))
3290            (x862-adjust-vstack (- *x862-target-node-size*))))
3291          (target-arch-case
3292           (:x8632
3293            (if a-float
3294              (progn
3295                (setq vinsn (! temp-pop-double-float areg))
3296                (x862-close-undo))
3297              (progn
3298                (setq vinsn (! temp-pop-unboxed-word areg))
3299                (x862-close-undo))))
3300           (:x8664
3301            (setq vinsn
3302                  (if a-float
3303                    (! temp-pop-double-float areg)
3304                    (! temp-pop-unboxed-word areg)))
3305            (x862-close-undo)))))
3306      vinsn)))
3307
3308;;; If reg is a GPR and of mode node, use arg_z, otherwise, just return
3309;;; reg.
3310(defun x862-acc-reg-for (reg)
3311  (with-x86-local-vinsn-macros (seg)
3312    (if (and (eql (hard-regspec-class reg) hard-reg-class-gpr)
3313           (eql (get-regspec-mode reg) hard-reg-class-gpr-mode-node))
3314      ($ *x862-arg-z*)
3315      reg)))
3316
3317;;; The compiler often generates superfluous pushes & pops.  Try to
3318;;; eliminate them.
3319(defun x862-elide-pushes (seg push-vinsn pop-vinsn)
3320  (with-x86-local-vinsn-macros (seg)
3321    (let* ((pushed-reg (svref (vinsn-variable-parts push-vinsn) 0))
3322           (popped-reg (svref (vinsn-variable-parts pop-vinsn) 0))
3323           (same-reg (eq (hard-regspec-value pushed-reg)
3324                         (hard-regspec-value popped-reg)))
3325           (csp-p (vinsn-attribute-p push-vinsn :csp)))
3326      (when csp-p                       ; vsp case is harder.
3327        (let* ((pushed-reg-is-set (vinsn-sequence-sets-reg-p
3328                                   push-vinsn pop-vinsn pushed-reg))
3329               (popped-reg-is-set (if same-reg
3330                                    pushed-reg-is-set
3331                                    (vinsn-sequence-sets-reg-p
3332                                     push-vinsn pop-vinsn popped-reg))))
3333          (unless (and pushed-reg-is-set popped-reg-is-set)
3334            (unless same-reg
3335              (let* ((copy (if (eq (hard-regspec-class pushed-reg)
3336                                   hard-reg-class-fpr)
3337                             (if (= (get-regspec-mode pushed-reg)
3338                                    hard-reg-class-fpr-mode-double)
3339                               (! copy-double-float popped-reg pushed-reg)
3340                               (! copy-single-float popped-reg pushed-reg))
3341                             (! copy-gpr popped-reg pushed-reg))))
3342                (remove-dll-node copy)
3343                (if pushed-reg-is-set
3344                  (insert-dll-node-after copy push-vinsn)
3345                  (insert-dll-node-before copy push-vinsn))))
3346            (elide-vinsn push-vinsn)
3347            (elide-vinsn pop-vinsn)))))))
3348               
3349       
3350;;; we never leave the first form pushed (the 68K compiler had some subprims that
3351;;; would vpop the first argument out of line.)
3352(defun x862-two-targeted-reg-forms (seg aform areg bform breg)
3353  (unless (typep areg 'lreg)
3354    (warn "~s is not an lreg (1/2)" areg))
3355  (unless (typep breg 'lreg)
3356    (warn "~s is not an lreg (2/2)" breg))
3357  (let* ((avar (x862-lexical-reference-p aform))
3358         (atriv (x862-trivial-p bform))
3359         (aconst (and (not atriv) (or (x86-side-effect-free-form-p aform)
3360                                      (if avar (x862-var-not-set-by-form-p avar bform)))))
3361         apushed)
3362    (progn
3363      (unless aconst
3364        (if atriv
3365          (x862-one-targeted-reg-form seg aform areg)
3366          (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
3367      (x862-one-targeted-reg-form seg bform breg)
3368      (if aconst
3369        (x862-one-targeted-reg-form seg aform areg)
3370        (if apushed
3371          (x862-elide-pushes seg apushed (x862-pop-register seg areg)))))
3372    (values areg breg)))
3373
3374
3375(defun x862-two-untargeted-reg-forms (seg aform areg bform breg)
3376  (with-x86-local-vinsn-macros (seg)
3377    (let* ((avar (x862-lexical-reference-p aform))
3378           (adest areg)
3379           (bdest breg)
3380           (atriv (x862-trivial-p bform))
3381           (aconst (and (not atriv) (or (x86-side-effect-free-form-p aform)
3382                                        (if avar (x862-var-not-set-by-form-p avar bform)))))
3383           (apushed (not (or atriv aconst))))
3384      (progn
3385        (unless aconst
3386          (if atriv
3387            (setq adest (x862-one-untargeted-reg-form seg aform areg))
3388            (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
3389        (setq bdest (x862-one-untargeted-reg-form seg bform breg))
3390        (if aconst
3391          (setq adest (x862-one-untargeted-reg-form seg aform areg))
3392          (if apushed
3393            (x862-elide-pushes seg apushed (x862-pop-register seg areg)))))
3394      (values adest bdest))))
3395
3396
3397(defun x862-three-targeted-reg-forms (seg aform areg bform breg cform creg)
3398  (unless (typep areg 'lreg)
3399    (warn "~s is not an lreg (1/3)" areg))
3400  (unless (typep breg 'lreg)
3401    (warn "~s is not an lreg (2/3)" breg))
3402  (unless (typep creg 'lreg)
3403    (warn "~s is not an lreg (3/3)" creg))
3404  (let* ((atriv (or (null aform) 
3405                    (and (x862-trivial-p bform)
3406                         (x862-trivial-p cform))))
3407         (btriv (or (null bform)
3408                    (x862-trivial-p cform)))
3409         (aconst (and (not atriv) 
3410                      (or (x86-side-effect-free-form-p aform)
3411                          (let ((avar (x862-lexical-reference-p aform)))
3412                            (and avar 
3413                                 (x862-var-not-set-by-form-p avar bform)
3414                                 (x862-var-not-set-by-form-p avar cform))))))
3415         (bconst (and (not btriv)
3416                      (or
3417                       (x86-side-effect-free-form-p bform)
3418                       (let ((bvar (x862-lexical-reference-p bform)))
3419                         (and bvar (x862-var-not-set-by-form-p bvar cform))))))
3420         (apushed nil)
3421         (bpushed nil))
3422    (if (and aform (not aconst))
3423      (if atriv
3424        (x862-one-targeted-reg-form seg aform areg)
3425        (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
3426    (if (and bform (not bconst))
3427      (if btriv
3428        (x862-one-targeted-reg-form seg bform breg)
3429        (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
3430    (x862-one-targeted-reg-form seg cform creg)
3431    (unless btriv 
3432      (if bconst
3433        (x862-one-targeted-reg-form seg bform breg)
3434        (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
3435    (unless atriv
3436      (if aconst
3437        (x862-one-targeted-reg-form seg aform areg)
3438        (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
3439    (values areg breg creg)))
3440
3441(defun x862-four-targeted-reg-forms (seg aform areg bform breg cform creg dform dreg)
3442  (unless (typep areg 'lreg)
3443    (warn "~s is not an lreg (1/4)" areg))
3444  (unless (typep breg 'lreg)
3445    (warn "~s is not an lreg (2/4)" breg))
3446  (unless (typep creg 'lreg)
3447    (warn "~s is not an lreg (3/4)" creg))
3448  (unless (typep dreg 'lreg)
3449    (warn "~s is not an lreg (4/4)" dreg))
3450  (let* ((atriv (or (null aform) 
3451                    (and (x862-trivial-p bform)
3452                         (x862-trivial-p cform)
3453                         (x862-trivial-p dform))))
3454         (btriv (or (null bform)
3455                    (and (x862-trivial-p cform)
3456                         (x862-trivial-p dform))))
3457         (ctriv (or (null cform)
3458                    (x862-trivial-p dform)))
3459         (aconst (and (not atriv) 
3460                      (or (x86-side-effect-free-form-p aform)
3461                          (let ((avar (x862-lexical-reference-p aform)))
3462                            (and avar 
3463                                 (x862-var-not-set-by-form-p avar bform)
3464                                 (x862-var-not-set-by-form-p avar cform)
3465                                 (x862-var-not-set-by-form-p avar dform))))))
3466         (bconst (and (not btriv)
3467                      (or
3468                       (x86-side-effect-free-form-p bform)
3469                       (let ((bvar (x862-lexical-reference-p bform)))
3470                         (and bvar
3471                              (x862-var-not-set-by-form-p bvar cform)
3472                              (x862-var-not-set-by-form-p bvar dform))))))
3473         (cconst (and (not ctriv)
3474                      (or
3475                       (x86-side-effect-free-form-p cform)
3476                       (let ((cvar (x862-lexical-reference-p cform)))
3477                         (and cvar (x862-var-not-set-by-form-p cvar dform))))))
3478         (apushed nil)
3479         (bpushed nil)
3480         (cpushed nil))
3481    (if (and aform (not aconst))
3482      (if atriv
3483        (x862-one-targeted-reg-form seg aform areg)
3484        (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
3485    (if (and bform (not bconst))
3486      (if btriv
3487        (x862-one-targeted-reg-form seg bform breg)
3488        (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
3489    (if (and cform (not cconst))
3490      (if ctriv
3491        (x862-one-targeted-reg-form seg cform creg)
3492        (setq cpushed (x862-push-register seg (x862-one-untargeted-reg-form seg cform (x862-acc-reg-for creg))))))
3493    (x862-one-targeted-reg-form seg dform dreg)
3494    (unless ctriv
3495      (if cconst
3496        (x862-one-targeted-reg-form seg cform creg)
3497        (x862-elide-pushes seg cpushed (x862-pop-register seg creg))))
3498    (unless btriv 
3499      (if bconst
3500        (x862-one-targeted-reg-form seg bform breg)
3501        (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
3502    (unless atriv
3503      (if aconst
3504        (x862-one-targeted-reg-form seg aform areg)
3505        (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
3506    (values areg breg creg)))
3507
3508(defun x862-three-untargeted-reg-forms (seg aform areg bform breg cform creg)
3509  (with-x86-local-vinsn-macros (seg)
3510    (let* ((atriv (or (null aform) 
3511                      (and (x862-trivial-p bform)
3512                           (x862-trivial-p cform))))
3513           (btriv (or (null bform)
3514                      (x862-trivial-p cform)))
3515           (aconst (and (not atriv) 
3516                        (or (x86-side-effect-free-form-p aform)
3517                            (let ((avar (x862-lexical-reference-p aform)))
3518                              (and avar 
3519                                   (x862-var-not-set-by-form-p avar bform)
3520                                   (x862-var-not-set-by-form-p avar cform))))))
3521           (bconst (and (not btriv)
3522                        (or
3523                         (x86-side-effect-free-form-p bform)
3524                         (let ((bvar (x862-lexical-reference-p bform)))
3525                           (and bvar (x862-var-not-set-by-form-p bvar cform))))))
3526           (adest areg)
3527           (bdest breg)
3528           (cdest creg)
3529           (apushed nil)
3530           (bpushed nil))
3531      (if (and aform (not aconst))
3532        (if atriv
3533          (setq adest (x862-one-untargeted-reg-form seg aform ($ areg)))
3534          (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
3535      (if (and bform (not bconst))
3536        (if btriv
3537          (setq bdest (x862-one-untargeted-reg-form seg bform ($ breg)))
3538          (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
3539      (setq cdest (x862-one-untargeted-reg-form seg cform creg))
3540      (unless btriv 
3541        (if bconst
3542          (setq bdest (x862-one-untargeted-reg-form seg bform breg))
3543          (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
3544      (unless atriv
3545        (if aconst
3546          (setq adest (x862-one-untargeted-reg-form seg aform areg))
3547          (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
3548      (values adest bdest cdest))))
3549
3550(defun x862-four-untargeted-reg-forms (seg aform areg bform breg cform creg dform dreg)
3551  (let* ((atriv (or (null aform) 
3552                    (and (x862-trivial-p bform)
3553                         (x862-trivial-p cform)
3554                         (x862-trivial-p dform))))
3555         (btriv (or (null bform)
3556                    (and (x862-trivial-p cform)
3557                         (x862-trivial-p dform))))
3558         (ctriv (or (null cform)
3559                    (x862-trivial-p dform)))
3560         (aconst (and (not atriv) 
3561                      (or (x86-side-effect-free-form-p aform)
3562                          (let ((avar (x862-lexical-reference-p aform)))
3563                            (and avar 
3564                                 (x862-var-not-set-by-form-p avar bform)
3565                                 (x862-var-not-set-by-form-p avar cform)
3566                                 (x862-var-not-set-by-form-p avar dform))))))
3567         (bconst (and (not btriv)
3568                      (or
3569                       (x86-side-effect-free-form-p bform)
3570                       (let ((bvar (x862-lexical-reference-p bform)))
3571                         (and bvar
3572                              (x862-var-not-set-by-form-p bvar cform)
3573                              (x862-var-not-set-by-form-p bvar dform))))))
3574         (cconst (and (not ctriv)
3575                      (or
3576                       (x86-side-effect-free-form-p cform)
3577                       (let ((cvar (x862-lexical-reference-p cform)))
3578                         (and cvar
3579                              (x862-var-not-set-by-form-p cvar dform))))))
3580         (adest areg)
3581         (bdest breg)
3582         (cdest creg)
3583         (ddest dreg)
3584         (apushed nil)
3585         (bpushed nil)
3586         (cpushed nil))
3587    (if (and aform (not aconst))
3588      (if atriv
3589        (setq adest (x862-one-targeted-reg-form seg aform areg))
3590        (setq apushed (x862-push-register seg (x862-one-untargeted-reg-form seg aform (x862-acc-reg-for areg))))))
3591    (if (and bform (not bconst))
3592      (if btriv
3593        (setq bdest (x862-one-untargeted-reg-form seg bform breg))
3594        (setq bpushed (x862-push-register seg (x862-one-untargeted-reg-form seg bform (x862-acc-reg-for breg))))))
3595    (if (and cform (not cconst))
3596      (if ctriv
3597        (setq cdest (x862-one-untargeted-reg-form seg cform creg))
3598        (setq cpushed (x862-push-register seg (x862-one-untargeted-reg-form seg cform (x862-acc-reg-for creg))))))
3599    (setq ddest (x862-one-untargeted-reg-form seg dform dreg))
3600    (unless ctriv 
3601      (if cconst
3602        (setq cdest (x862-one-untargeted-reg-form seg cform creg))
3603        (x862-elide-pushes seg cpushed (x862-pop-register seg creg))))
3604    (unless btriv 
3605      (if bconst
3606        (setq bdest (x862-one-untargeted-reg-form seg bform breg))
3607        (x862-elide-pushes seg bpushed (x862-pop-register seg breg))))
3608    (unless atriv
3609      (if aconst
3610        (setq adest (x862-one-untargeted-reg-form seg aform areg))
3611        (x862-elide-pushes seg apushed (x862-pop-register seg areg))))
3612    (values adest bdest cdest ddest)))
3613
3614(defun x862-lri (seg reg value)
3615  (with-x86-local-vinsn-macros (seg)
3616    (! lri reg value)))
3617
3618;;; unsigned variant
3619(defun x862-lriu (seg reg value)
3620  (with-x86-local-vinsn-macros (seg)
3621    (! lriu reg value)))
3622
3623(defun x862-multiple-value-body (seg form)
3624  (let* ((lab (backend-get-next-label))
3625         (*x862-vstack* *x862-vstack*)
3626         (*x862-top-vstack-lcell* *x862-top-vstack-lcell*)
3627         (old-stack (x862-encode-stack)))
3628    (with-x86-local-vinsn-macros (seg)
3629      (x862-open-undo $undomvexpect)
3630      (x862-undo-body seg nil (logior $backend-mvpass-mask lab) form old-stack)
3631      (@ lab))))
3632
3633(defun x862-afunc-lfun-ref (afunc)
3634  (or
3635   (afunc-lfun afunc)
3636   (progn (pushnew afunc (afunc-fwd-refs *x862-cur-afunc*) :test #'eq)
3637          afunc)))
3638
3639(defun x862-augment-arglist (afunc arglist &optional (maxregs *x862-target-num-arg-regs*))
3640  (let ((inherited-args (afunc-inherited-vars afunc)))
3641    (when inherited-args
3642      (let* ((current-afunc *x862-cur-afunc*)
3643             (stkargs (car arglist))
3644             (regargs (cadr arglist))
3645             (inhforms nil)
3646             (numregs (length regargs))
3647             (own-inhvars (afunc-inherited-vars current-afunc)))
3648        (dolist (var inherited-args)
3649          (let* ((root-var (nx-root-var var))
3650                 (other-guy 
3651                  (dolist (v own-inhvars #|(error "other guy not found")|# root-var)
3652                    (when (eq root-var (nx-root-var v)) (return v)))))
3653            (push (make-acode (%nx1-operator inherited-arg) other-guy) inhforms)))
3654        (dolist (form inhforms)
3655          (if (%i< numregs maxregs)
3656            (progn
3657              (setq regargs (nconc regargs (list form)))
3658              (setq numregs (%i+ numregs 1)))
3659            (push form stkargs)))
3660        (%rplaca (%cdr arglist) regargs) ; might have started out NIL.
3661        (%rplaca arglist stkargs)))) 
3662  arglist)
3663
3664(defun x862-acode-operator-supports-u8 (form)
3665  (setq form (acode-unwrapped-form-value form))
3666  (when (acode-p form)
3667    (let* ((operator (acode-operator form)))
3668      (if (member operator *x862-operator-supports-u8-target*)
3669        (values operator (acode-operand 1 form))))))
3670
3671(defun x862-acode-operator-supports-push (form)
3672  (let ((value (acode-unwrapped-form-value form)))
3673    (when (acode-p value)
3674      (if (or (eq value *nx-t*)
3675              (eq value *nx-nil*)
3676              (let* ((operator (acode-operator value)))
3677                (member operator *x862-operator-supports-push*)))
3678        value))))
3679
3680(defun x862-compare-u8 (seg vreg xfer form u8constant cr-bit true-p u8-operator)
3681  (with-x86-local-vinsn-macros (seg vreg xfer)
3682    (with-imm-target () (u8 :u8)
3683      (if (and (eql u8-operator (%nx1-operator lisptag))
3684               (eql 0 u8constant))
3685        (let* ((formreg (x862-one-untargeted-reg-form seg form *x862-arg-z*)))
3686         
3687          (! set-flags-from-lisptag formreg))
3688        (progn
3689          (x862-use-operator u8-operator seg u8 nil form)
3690          (if (zerop u8constant)
3691            (! compare-u8-reg-to-zero u8)
3692            (! compare-u8-constant u8 u8constant))))
3693      ;; Flags set.  Branch or return a boolean value ?
3694      (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
3695      (regspec-crf-gpr-case 
3696       (vreg dest)
3697       (^ cr-bit true-p)
3698       (progn
3699         (ensuring-node-target (target dest)
3700           (if (not true-p)
3701             (setq cr-bit (logxor 1 cr-bit)))
3702           (! cr-bit->boolean target cr-bit))
3703         (^))))))
3704
3705;;; There are other cases involving constants that are worth exploiting.
3706(defun x862-compare (seg vreg xfer i j cr-bit true-p)
3707  (with-x86-local-vinsn-macros (seg vreg xfer)
3708    (let* ((iu8 (let* ((i-fixnum (acode-fixnum-form-p i)))
3709                  (if (typep i-fixnum '(unsigned-byte 8))
3710                    i-fixnum)))
3711           (ju8 (let* ((j-fixnum (acode-fixnum-form-p j)))
3712                  (if (typep j-fixnum '(unsigned-byte 8))
3713                    j-fixnum)))
3714           (u8 (or iu8 ju8))
3715           (other-u8 (if iu8 j (if ju8 i)))
3716           (js32 (acode-s32-constant-p j))
3717           (is32 (acode-s32-constant-p i))
3718           (boolean (backend-crf-p vreg)))
3719      (multiple-value-bind (u8-operator u8-operand) (if other-u8 (x862-acode-operator-supports-u8 other-u8))
3720        (if u8-operator
3721          (x862-compare-u8 seg vreg xfer u8-operand u8 (if (and iu8 (not (eq cr-bit x86::x86-e-bits))) (logxor 1 cr-bit) cr-bit) true-p u8-operator)
3722          (if (and boolean (or js32 is32))
3723            (let* ((reg (x862-one-untargeted-reg-form seg (if js32 i j) *x862-arg-z*))
3724                   (constant (or js32 is32)))
3725              (if (zerop constant)
3726                (! compare-reg-to-zero reg)
3727                (! compare-s32-constant reg (or js32 is32)))
3728              (unless (or js32 (eq cr-bit x86::x86-e-bits))
3729                (setq cr-bit (x862-reverse-cr-bit cr-bit)))
3730              (^ cr-bit true-p))
3731            (if (and ;(eq cr-bit x86::x86-e-bits)
3732                     (or js32 is32))
3733              (progn
3734                (unless (or js32 (eq cr-bit x86::x86-e-bits))
3735                  (setq cr-bit (x862-reverse-cr-bit cr-bit)))
3736              (x862-test-reg-%izerop
3737               seg 
3738               vreg 
3739               xfer 
3740               (x862-one-untargeted-reg-form 
3741                seg 
3742                (if js32 i j) 
3743                *x862-arg-z*) 
3744               cr-bit 
3745               true-p 
3746               (or js32 is32)))
3747              (multiple-value-bind (ireg jreg) (x862-two-untargeted-reg-forms seg i *x862-arg-y* j *x862-arg-z*)
3748                (x862-compare-registers seg vreg xfer ireg jreg cr-bit true-p)))))))))
3749
3750(defun x862-natural-compare (seg vreg xfer i j cr-bit true-p)
3751  (with-x86-local-vinsn-macros (seg vreg xfer)
3752    (let* ((jconstant (acode-fixnum-form-p j))
3753           (ju31 (typep jconstant '(unsigned-byte 31)))
3754           (iconstant (acode-fixnum-form-p i))
3755           (iu31 (typep iconstant '(unsigned-byte 31)))
3756           (boolean (backend-crf-p vreg)))
3757      (if (and boolean (or ju31 iu31))
3758        (with-imm-target
3759            () (reg :natural)
3760            (x862-one-targeted-reg-form seg (if ju31 i j) reg)
3761            (! compare-u31-constant reg (if ju31 jconstant iconstant))
3762            (unless (or ju31 (eq cr-bit x86::x86-e-bits)) 
3763                (setq cr-bit (x862-reverse-cr-bit cr-bit)))
3764            (^ cr-bit true-p))
3765        (target-arch-case
3766         (:x8664
3767          (with-imm-target () (ireg :natural)
3768            (with-imm-target (ireg) (jreg :natural)
3769              (x862-two-targeted-reg-forms seg i ireg j jreg)
3770              (x862-compare-natural-registers seg vreg xfer ireg jreg cr-bit true-p))))
3771         (:x8632
3772          (with-imm-target () (jreg :natural) 
3773            (x862-one-targeted-reg-form seg i jreg)
3774            (x862-push-register seg jreg)
3775            (x862-one-targeted-reg-form seg j jreg)
3776            (! temp-pop-temp1-as-unboxed-word)
3777            (x862-close-undo)
3778            (x862-compare-natural-registers seg vreg xfer ($ x8632::temp1) jreg cr-bit true-p))))))))
3779
3780
3781
3782                 
3783(defun x862-compare-natural-registers (seg vreg xfer ireg jreg cr-bit true-p)
3784  (with-x86-local-vinsn-macros (seg vreg xfer)
3785    (if vreg
3786      (progn
3787        (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
3788        (! compare ireg jreg)
3789        (target-arch-case
3790         (:x8664)
3791         (:x8632 (! mark-temp1-as-node-preserving-flags)))
3792        (regspec-crf-gpr-case 
3793         (vreg dest)
3794         (^ cr-bit true-p)
3795         (progn
3796           (ensuring-node-target (target dest)
3797             (if (not true-p)
3798               (setq cr-bit (logxor 1 cr-bit)))
3799             (! cr-bit->boolean target cr-bit))
3800           (^))))
3801      (^))))
3802
3803
3804(defun x862-compare-registers (seg vreg xfer ireg jreg cr-bit true-p)
3805  (with-x86-local-vinsn-macros (seg vreg xfer)
3806    (if vreg
3807      (progn
3808        (! compare ireg jreg)
3809        (regspec-crf-gpr-case 
3810         (vreg dest)
3811         (^ cr-bit true-p)
3812         (progn
3813           (ensuring-node-target (target dest)
3814             (if (not true-p)
3815               (setq cr-bit (logxor 1 cr-bit)))
3816             (! cr-bit->boolean target cr-bit))
3817           (^))))
3818      (^))))
3819
3820(defun x862-compare-register-to-constant (seg vreg xfer ireg cr-bit true-p constant)
3821  (cond ((eq constant *nx-nil*)
3822         (x862-compare-register-to-nil seg vreg xfer ireg cr-bit true-p))
3823        (t
3824         (with-x86-local-vinsn-macros (seg vreg xfer)
3825           (when vreg
3826             (if (eq constant *nx-t*)
3827               (! compare-to-t ireg)
3828               (let* ((imm (x862-immediate-operand constant))
3829                      (reg (x862-register-constant-p imm))) 
3830                 (if reg
3831                   (! compare-registers reg ireg)
3832                   (! compare-constant-to-register (x86-immediate-label imm) ireg))))
3833             (regspec-crf-gpr-case 
3834              (vreg dest)
3835              (^ cr-bit true-p)
3836              (progn
3837                (ensuring-node-target (target dest)
3838                  (if (not true-p)
3839                    (setq cr-bit (logxor 1 cr-bit)))
3840                  (! cr-bit->boolean target cr-bit))
3841                (^))))))))
3842         
3843(defun x862-compare-register-to-nil (seg vreg xfer ireg cr-bit true-p)
3844  (with-x86-local-vinsn-macros (seg vreg xfer)
3845    (when vreg
3846      (! compare-to-nil ireg)
3847      (regspec-crf-gpr-case 
3848       (vreg dest)
3849       (^ cr-bit true-p)
3850       (progn
3851       (ensuring-node-target (target dest)
3852         (if (not true-p)
3853           (setq cr-bit (logxor 1 cr-bit)))
3854         (! cr-bit->boolean target cr-bit))
3855       (^))))))
3856
3857(defun x862-compare-ea-to-nil (seg vreg xfer ea cr-bit true-p)
3858  (with-x86-local-vinsn-macros (seg vreg xfer)
3859    (when vreg
3860      (if (addrspec-vcell-p ea)
3861        (with-node-target () temp
3862          (x862-stack-to-register seg ea temp)
3863          (! compare-value-cell-to-nil temp))
3864        (! compare-vframe-offset-to-nil (memspec-frame-address-offset ea) *x862-vstack*))
3865      (regspec-crf-gpr-case 
3866       (vreg dest)
3867       (^ cr-bit true-p)
3868       (progn
3869       (ensuring-node-target (target dest)
3870         (if (not true-p)
3871           (setq cr-bit (logxor 1 cr-bit)))
3872         (! cr-bit->boolean target cr-bit))
3873       (^))))))
3874
3875(defun x862-cr-bit-for-unsigned-comparison (cr-bit)
3876  (ecase cr-bit
3877    (#.x86::x86-e-bits #.x86::x86-e-bits)
3878    (#.x86::x86-ne-bits #.x86::x86-ne-bits)
3879    (#.x86::x86-l-bits #.x86::x86-b-bits)
3880    (#.x86::x86-le-bits #.x86::x86-be-bits)
3881    (#.x86::x86-ge-bits #.x86::x86-ae-bits)
3882    (#.x86::x86-g-bits #.x86::x86-a-bits)))
3883
3884
3885(defun x862-compare-double-float-registers (seg vreg xfer ireg jreg cr-bit true-p)
3886  (with-x86-local-vinsn-macros (seg vreg xfer)
3887    (if vreg
3888      (progn
3889        (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
3890        (regspec-crf-gpr-case 
3891         (vreg dest)
3892         (progn
3893           (! double-float-compare ireg jreg)
3894           (^ cr-bit true-p))
3895         (progn
3896           (! double-float-compare ireg jreg)
3897           (ensuring-node-target (target dest)
3898             (if (not true-p)
3899               (setq cr-bit (logxor 1 cr-bit)))
3900             (! cr-bit->boolean target cr-bit))
3901           (^))))
3902      (^))))
3903
3904(defun x862-compare-single-float-registers (seg vreg xfer ireg jreg cr-bit true-p)
3905  (with-x86-local-vinsn-macros (seg vreg xfer)
3906    (if vreg
3907      (progn
3908        (setq cr-bit (x862-cr-bit-for-unsigned-comparison cr-bit))
3909        (regspec-crf-gpr-case 
3910         (vreg dest)
3911         (progn
3912           (! single-float-compare ireg jreg)
3913           (^ cr-bit true-p))
3914         (progn
3915           (! single-float-compare ireg jreg)
3916           (ensuring-node-target (target dest)
3917             (if (not true-p)
3918               (setq cr-bit (logxor 1 cr-bit)))
3919             (! cr-bit->boolean target cr-bit))
3920         (^))))
3921      (^))))
3922
3923
3924(defun x862-immediate-form-p (form)
3925  (if (and (consp form)
3926           (or (eq (%car form) (%nx1-operator immediate))
3927               (eq (%car form) (%nx1-operator simple-function))))
3928    t))
3929
3930(defun x862-test-%izerop (seg vreg xfer form cr-bit true-p)
3931  (x862-test-reg-%izerop seg vreg xfer (x862-one-untargeted-reg-form seg form *x862-arg-z*) cr-bit true-p 0))
3932
3933(defun x862-test-reg-%izerop (seg vreg xfer reg cr-bit true-p  zero)
3934  (declare (fixnum reg zero))
3935  (with-x86-local-vinsn-macros (seg vreg xfer)
3936    (if (zerop zero)
3937      (! compare-reg-to-zero reg)
3938      (! compare-s32-constant reg zero))
3939    (regspec-crf-gpr-case 
3940     (vreg dest)
3941     (^ cr-bit true-p)
3942     (progn
3943       (ensuring-node-target (target dest)
3944         (if (not true-p)
3945           (setq cr-bit (logxor 1 cr-bit)))
3946         (! cr-bit->boolean target cr-bit))
3947       (^)))))
3948
3949(defun x862-lexical-reference-ea (form &optional (no-closed-p t))
3950  (when (acode-p (setq form (acode-unwrapped-form-value form)))
3951    (if (eq (acode-operator form) (%nx1-operator lexical-reference))
3952      (let* ((addr (var-ea (%cadr form))))
3953        (if (typep addr 'lreg)
3954          addr
3955          (unless (and no-closed-p (addrspec-vcell-p addr ))
3956            addr))))))
3957
3958
3959(defun x862-vpush-register (seg src &optional why info attr)
3960  (with-x86-local-vinsn-macros (seg)
3961    (prog1
3962      (! vpush-register src)
3963      (setq *x862-tos-reg* src)
3964      (x862-new-vstack-lcell (or why :node) *x862-target-lcell-size* (or attr 0) info)
3965      (x862-adjust-vstack *x862-target-node-size*))))
3966
3967
3968;;; Need to track stack usage when pushing label for mv-call.
3969(defun x862-vpush-label (seg label)
3970  (with-x86-local-vinsn-macros (seg)
3971    (prog1
3972      (! vpush-label label)
3973      (x862-new-vstack-lcell :label *x862-target-lcell-size* 0 nil)
3974      (x862-adjust-vstack *x862-target-node-size*))))
3975
3976(defun x862-temp-push-node (seg reg)
3977  (with-x86-local-vinsn-macros (seg)
3978    (! temp-push-node reg)
3979    (x862-open-undo $undostkblk)))
3980
3981(defun x862-temp-pop-node (seg reg)
3982  (with-x86-local-vinsn-macros (seg)
3983    (! temp-pop-node reg)
3984    (x862-close-undo)))
3985
3986(defun x862-vpush-register-arg (seg src)
3987  (x862-vpush-register seg src :outgoing-argument))
3988
3989
3990(defun x862-vpop-register (seg dest)
3991  (with-x86-local-vinsn-macros (seg)
3992    (prog1
3993      (! vpop-register dest)
3994      (setq *x862-top-vstack-lcell* (lcell-parent *x862-top-vstack-lcell*))
3995      (x862-adjust-vstack (- *x862-target-node-size*)))))
3996
3997(defun x862-macptr->heap (seg dest src)
3998  (with-x86-local-vinsn-macros (seg)
3999    (! setup-macptr-allocation src)
4000    (! %allocate-uvector dest)
4001    (! %set-new-macptr-value dest)))
4002
4003(defun x862-copy-register (seg dest src)
4004  (with-x86-local-vinsn-macros (seg)
4005    (when dest
4006      (let* ((dest-gpr (backend-ea-physical-reg dest hard-reg-class-gpr))
4007             (src-gpr (if src (backend-ea-physical-reg src hard-reg-class-gpr)))
4008             (dest-fpr (backend-ea-physical-reg dest hard-reg-class-fpr))
4009             (src-fpr (if src (backend-ea-physical-reg src hard-reg-class-fpr)))
4010             (src-mode (if src (get-regspec-mode src)))
4011             (dest-mode (get-regspec-mode dest))
4012             (dest-crf (backend-ea-physical-reg dest hard-reg-class-crf)))
4013        (if (null src)
4014          (if dest-gpr
4015            (! load-nil dest-gpr)
4016            (if dest-crf
4017              (! set-eq-bit)))
4018          (if (and dest-crf src-gpr)
4019            ;; "Copying" a GPR to a CR field means comparing it to rnil
4020            (! compare-to-nil src)
4021            (if (and dest-gpr src-gpr)
4022              (if (eq src-mode dest-mode)
4023                (unless (eq src-gpr dest-gpr)
4024                  (! copy-gpr dest src))
4025                ;; This is the "GPR <- GPR" case.  There are
4026                ;; word-size dependencies, but there's also
4027                ;; lots of redundancy here.
4028                (target-arch-case
4029                 (:x8632
4030                  (ecase dest-mode
4031                    (#.hard-reg-class-gpr-mode-node ; boxed result.
4032                     (case src-mode
4033                       (#.hard-reg-class-gpr-mode-node
4034                        (unless (eql  dest-gpr src-gpr)
4035                          (! copy-gpr dest src)))
4036                       (#.hard-reg-class-gpr-mode-u32
4037                        (x862-box-u32 seg dest src))
4038                       (#.hard-reg-class-gpr-mode-s32
4039                        (x862-box-s32 seg dest src))
4040                       (#.hard-reg-class-gpr-mode-u16
4041                        (! box-fixnum dest src))
4042                       (#.hard-reg-class-gpr-mode-s16
4043                        (! box-fixnum dest src))
4044                       (#.hard-reg-class-gpr-mode-u8
4045                        (! box-fixnum dest src))
4046                       (#.hard-reg-class-gpr-mode-s8
4047                        (! box-fixnum dest src))
4048                       (#.hard-reg-class-gpr-mode-address
4049                        (x862-macptr->heap seg dest src))))
4050                    ((#.hard-reg-class-gpr-mode-u32
4051                      #.hard-reg-class-gpr-mode-address)
4052                     (case src-mode
4053                       (#.hard-reg-class-gpr-mode-node
4054                        (let* ((src-type (get-node-regspec-type-modes src)))
4055                          (declare (fixnum src-type))
4056                          (case dest-mode
4057                            (#.hard-reg-class-gpr-mode-u32
4058                             (! unbox-u32 dest src))
4059                            (#.hard-reg-class-gpr-mode-address
4060                             (unless (or (logbitp #.hard-reg-class-gpr-mode-address src-type)
4061                                         *x862-reckless*)
4062                               (! trap-unless-macptr src))
4063                             (! deref-macptr dest src)))))
4064                       ((#.hard-reg-class-gpr-mode-u32
4065                         #.hard-reg-class-gpr-mode-s32
4066                         #.hard-reg-class-gpr-mode-address)
4067                        (unless (eql  dest-gpr src-gpr)
4068                          (! copy-gpr dest src)))
4069                       (#.hard-reg-class-gpr-mode-u16
4070                        (! u16->u32 dest src))                 
4071                       (#.hard-reg-class-gpr-mode-s16
4072                        (! s16->s32 dest src))
4073                       (#.hard-reg-class-gpr-mode-u8
4074                        (! u8->u32 dest src))
4075                       (#.hard-reg-class-gpr-mode-s8
4076                        (! s8->s32 dest src))))
4077                    (#.hard-reg-class-gpr-mode-s32
4078                     (case src-mode
4079                       (#.hard-reg-class-gpr-mode-node
4080                        (! unbox-s32 dest src))
4081                       ((#.hard-reg-class-gpr-mode-u32
4082                         #.hard-reg-class-gpr-mode-s32
4083                         #.hard-reg-class-gpr-mode-address)
4084                        (unless (eql  dest-gpr src-gpr)
4085                          (! copy-gpr dest src)))
4086                       (#.hard-reg-class-gpr-mode-u16
4087                        (! u16->u32 dest src))                 
4088                       (#.hard-reg-class-gpr-mode-s16
4089                        (! s16->s32 dest src))
4090                       (#.hard-reg-class-gpr-mode-u8
4091                        (! u8->u32 dest src))
4092                       (#.hard-reg-class-gpr-mode-s8
4093                        (! s8->s32 dest src))))
4094                    (#.hard-reg-class-gpr-mode-u16
4095                     (case src-mode
4096                       (#.hard-reg-class-gpr-mode-node
4097                        (! unbox-u16 dest src))
4098                       ((#.hard-reg-class-gpr-mode-u8
4099                         #.hard-reg-class-gpr-mode-s8)
4100                        (! u8->u32 dest src))
4101                       (t
4102                        (unless (eql dest-gpr src-gpr)
4103                          (! copy-gpr dest src)))))
4104                    (#.hard-reg-class-gpr-mode-s16
4105                     (case src-mode
4106                       (#.hard-reg-class-gpr-mode-node
4107                        (! unbox-s16 dest src))
4108                       (#.hard-reg-class-gpr-mode-s8
4109                        (! s8->s32 dest src))
4110                       (#.hard-reg-class-gpr-mode-u8
4111                        (! u8->u32 dest src))
4112                       (t
4113                        (unless (eql dest-gpr src-gpr)
4114                          (! copy-gpr dest src)))))
4115                    (#.hard-reg-class-gpr-mode-u8
4116                     (case src-mode
4117                       (#.hard-reg-class-gpr-mode-node
4118                        (if *x862-reckless*
4119                          (! %unbox-u8 dest src)
4120                          (! unbox-u8 dest src)))
4121                       (t
4122                        (unless (eql dest-gpr src-gpr)
4123                          (! copy-gpr dest src)))))
4124                    (#.hard-reg-class-gpr-mode-s8
4125                     (case src-mode
4126                       (#.hard-reg-class-gpr-mode-node
4127                        (! unbox-s8 dest src))
4128                       (t
4129                        (unless (eql dest-gpr src-gpr)
4130                          (! copy-gpr dest src)))))))
4131                 (:x8664
4132                  (ecase dest-mode
4133                    (#.hard-reg-class-gpr-mode-node ; boxed result.
4134                     (case src-mode
4135                       (#.hard-reg-class-gpr-mode-node
4136                        (unless (eql  dest-gpr src-gpr)
4137                          (! copy-gpr dest src)))
4138                       (#.hard-reg-class-gpr-mode-u64
4139                        (x862-box-u64 seg dest src))
4140                       (#.hard-reg-class-gpr-mode-s64
4141                        (x862-box-s64 seg dest src))
4142                       (#.hard-reg-class-gpr-mode-u32
4143                        (x862-box-u32 seg dest src))
4144                       (#.hard-reg-class-gpr-mode-s32
4145                        (x862-box-s32 seg dest src))
4146                       (#.hard-reg-class-gpr-mode-u16
4147                        (! box-fixnum dest src))
4148                       (#.hard-reg-class-gpr-mode-s16
4149                        (! box-fixnum dest src))
4150                       (#.hard-reg-class-gpr-mode-u8
4151                        (! box-fixnum dest src))
4152                       (#.hard-reg-class-gpr-mode-s8
4153                        (! box-fixnum dest src))
4154                       (#.hard-reg-class-gpr-mode-address
4155                        (x862-macptr->heap seg dest src))))
4156                    ((#.hard-reg-class-gpr-mode-u64
4157                      #.hard-reg-class-gpr-mode-address)
4158                     (case src-mode
4159                       (#.hard-reg-class-gpr-mode-node
4160                        (let* ((src-type (get-node-regspec-type-modes src)))
4161                          (declare (fixnum src-type))
4162                          (case dest-mode
4163                            (#.hard-reg-class-gpr-mode-u64
4164                             (! unbox-u64 dest src))
4165                            (#.hard-reg-class-gpr-mode-address
4166                             (unless (or (logbitp #.hard-reg-class-gpr-mode-address src-type)
4167                                         *x862-reckless*)
4168                               (! trap-unless-macptr src))
4169                             (! deref-macptr dest src)))))
4170                       ((#.hard-reg-class-gpr-mode-u64
4171                         #.hard-reg-class-gpr-mode-s64
4172                         #.hard-reg-class-gpr-mode-address)
4173                        (unless (eql  dest-gpr src-gpr)
4174                          (! copy-gpr dest src)))
4175                       ((#.hard-reg-class-gpr-mode-u16
4176                         #.hard-reg-class-gpr-mode-s16)
4177                        (! u16->u32 dest src))
4178                       ((#.hard-reg-class-gpr-mode-u8
4179                         #.hard-reg-class-gpr-mode-s8)
4180                        (! u8->u32 dest src))))
4181                    (#.hard-reg-class-gpr-mode-s64
4182                     (case src-mode
4183                       (#.hard-reg-class-gpr-mode-node
4184                        (! unbox-s64 dest src))
4185                       ((#.hard-reg-class-gpr-mode-u64
4186                         #.hard-reg-class-gpr-mode-s64
4187                         #.hard-reg-class-gpr-mode-address)
4188                        (unless (eql  dest-gpr src-gpr)
4189                          (! copy-gpr dest src)))
4190                       ((#.hard-reg-class-gpr-mode-u16
4191                         #.hard-reg-class-gpr-mode-s16)
4192                        (! s16->s32 dest src))
4193                       ((#.hard-reg-class-gpr-mode-u8
4194                         #.hard-reg-class-gpr-mode-s8)
4195                        (! s8->s32 dest src))))
4196                    (#.hard-reg-class-gpr-mode-s32
4197                     (case src-mode
4198                       (#.hard-reg-class-gpr-mode-node
4199                        (! unbox-s32 dest src))
4200                       ((#.hard-reg-class-gpr-mode-u32
4201                         #.hard-reg-class-gpr-mode-s32
4202                         #.hard-reg-class-gpr-mode-address)
4203                        (unless (eql  dest-gpr src-gpr)
4204                          (! copy-gpr dest src)))
4205                       (#.hard-reg-class-gpr-mode-u16
4206                        (! u16->u32 dest src))                 
4207                       (#.hard-reg-class-gpr-mode-s16
4208                        (! s16->s32 dest src))
4209                       (#.hard-reg-class-gpr-mode-u8
4210                        (! u8->u32 dest src))
4211                       (#.hard-reg-class-gpr-mode-s8
4212                        (! s8->s32 dest src))))
4213                    (#.hard-reg-class-gpr-mode-u32
4214                     (case src-mode
4215                       (#.hard-reg-class-gpr-mode-node
4216                        (if *x862-reckless*
4217                          (! %unbox-u32 dest src)
4218                          (! unbox-u32 dest src)))
4219                       ((#.hard-reg-class-gpr-mode-u32
4220                         #.hard-reg-class-gpr-mode-s32)
4221                        (unless (eql  dest-gpr src-gpr)
4222                          (! copy-gpr dest src)))
4223                       (#.hard-reg-class-gpr-mode-u16
4224                        (! u16->u32 dest src))