source: release/1.3/source/level-0/X86/X8632/x8632-def.lisp

Last change on this file was 12084, checked in by R. Matthew Emerson, 16 years ago

Merge 12074 (%ff-call/%do-ff-call and 64-bit return values).

File size: 22.4 KB
RevLine 
[7361]1;;; -*- Mode: Lisp; Package: CCL -*-
2;;;
3;;; Copyright (C) 2006, Clozure Associates and contributors
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
[8857]19;;; Use the offsets in a function's self-reference table to replace
20;;; the :self in (movl ($ :self) (% fn)) wih the function's actual
21;;; address.
22(defx8632lapfunction %update-self-references ((fun arg_z))
23 (movzwl (@ x8632::misc-data-offset (% fun)) (% imm0)) ;imm word count
24 (subl ($ 2) (% imm0))
25 (box-fixnum imm0 temp0) ;byte offset of first self-ref offset
[8906]26 (jmp @load-offset)
[8857]27 @loop
28 (movl (% fun) (@ x8632::misc-header-offset (% fun) (% imm0)))
29 (subl ($ '1) (% temp0))
[8906]30 @load-offset
[8857]31 (movl (@ x8632::misc-data-offset (% fun) (% temp0)) (% imm0))
32 (test (% imm0) (% imm0))
33 (jne @loop)
34 (single-value-return))
35
[7963]36(defx8632lapfunction %function-code-words ((fun arg_z))
[7361]37 (trap-unless-typecode= fun x8632::subtag-function)
[7430]38 (movzwl (@ x8632::misc-data-offset (% fun)) (% imm0))
[7361]39 (box-fixnum imm0 arg_z)
40 (single-value-return))
41
[7963]42(defx8632lapfunction %nth-immediate ((fun arg_y) (n arg_z))
[7361]43 (trap-unless-typecode= fun x8632::subtag-function)
[7430]44 (movzwl (@ x8632::misc-data-offset (% fun)) (% imm0))
[7361]45 (lea (@ (% n) (% imm0) 4) (% imm0))
46 (movl (@ x8632::misc-data-offset (% fun) (% imm0)) (% arg_z))
47 (single-value-return))
48
[7963]49(defx8632lapfunction %set-nth-immediate ((fun 4) #|(ra 0)|# (n arg_y) (new arg_z))
50 (popl (@ 8 (% esp)))
51 (popl (% temp0))
52 (addl ($ 4) (% esp))
[7361]53 (trap-unless-typecode= temp0 x8632::subtag-function)
[7963]54 (movzwl (@ x8632::misc-data-offset (% temp0)) (% imm0))
[7361]55 (lea (@ (% n) (% imm0) 4) (% arg_y))
56 ;; expects gvector in temp0
57 (jmp-subprim .SPgvset))
58
[7963]59(defx8632lapfunction %function-code-byte ((fun arg_y) (pc arg_z))
[7361]60 (unbox-fixnum pc imm0)
61 (movzbl (@ (% fun) (% imm0)) (% imm0))
62 (box-fixnum imm0 arg_z)
63 (single-value-return))
64
[9461]65(defx8632lapfunction %function-register-usage ((f arg_z))
66 (check-nargs 1)
67 (trap-unless-typecode= f x8632::subtag-function)
68 (movl (% esp) (% temp0))
69 (pushl ($ nil))
70 (pushl ($ nil))
71 (jmp-subprim .SPvalues))
72
[9127]73;;; XXX probably should unify these next two with the x8664 versions.
74
75;;; Make a new function, with PROTO's code and the specified immediates.
76;;; IMMEDIATES should contain lfun-bits as the last element.
77(defun %clone-x86-function (proto &rest immediates)
78 (declare (dynamic-extent immediates))
[9192]79 (let* ((protov (function-to-function-vector proto))
[9127]80 (code-words (%function-code-words proto))
81 (numimms (length immediates))
82 (newv (allocate-typed-vector :function (the fixnum (+ code-words numimms)))))
83 (declare (fixnum code-words numimms))
84 (%copy-ivector-to-ivector protov 0 newv 0 (the fixnum (ash code-words target::word-shift)))
85 (%update-self-references newv)
86 (do* ((k code-words (1+ k))
87 (imms immediates (cdr imms)))
[9192]88 ((null imms) (function-vector-to-function newv))
[9127]89 (declare (fixnum k) (list imms))
90 (setf (%svref newv k) (car imms)))))
91
[10267]92(defun %copy-function (proto &optional target)
93 (let* ((protov (function-to-function-vector proto))
94 (code-words (%function-code-words proto))
95 (total-words (uvsize protov))
96 (newv (if target
97 (function-to-function-vector target)
98 (allocate-typed-vector :function total-words))))
99 (declare (fixnum code-words total-words))
100 (when target
101 (unless (and (eql code-words (%function-code-words target))
102 (eql total-words (uvsize newv)))
103 (error "Wrong size target ~s" target)))
104 (%copy-ivector-to-ivector protov 0 newv 0 (the fixnum (ash code-words target::word-shift)))
105 (loop for k fixnum from code-words below total-words
106 do (setf (%svref newv k) (%svref protov k)))
[11348]107 (%update-self-references (function-vector-to-function newv))))
[10267]108
[9127]109(defun replace-function-code (target proto)
110 (let* ((target-words (%function-code-words target))
111 (proto-words (%function-code-words proto)))
112 (declare (fixnum target-words proto-words))
113 (if (= target-words proto-words)
114 (progn
[9192]115 (%copy-ivector-to-ivector (function-to-function-vector proto)
[9127]116 0
[9192]117 (function-to-function-vector target)
[9127]118 0
119 (the fixnum (ash target-words
120 target::word-shift)))
121 (%update-self-references target)
122 target)
123 (error "Code size mismatch: target = ~s, proto = ~s"
124 target-words proto-words))))
125
[7963]126(defx8632lapfunction %get-kernel-global-from-offset ((offset arg_z))
[7361]127 (check-nargs 1)
128 (unbox-fixnum offset imm0)
[10959]129 (movl (@ (target-nil-value) (% imm0)) (% arg_z))
[7361]130 (single-value-return))
131
[7963]132(defx8632lapfunction %set-kernel-global-from-offset ((offset arg_y)
133 (new-value arg_z))
[7361]134 (check-nargs 2)
135 (unbox-fixnum offset imm0)
[10959]136 (movl (% arg_z) (@ (target-nil-value) (% imm0)))
[7361]137 (single-value-return))
138
[7963]139(defx8632lapfunction %get-kernel-global-ptr-from-offset ((offset arg_y)
140 (ptr arg_z))
[7361]141 (check-nargs 2)
142 (unbox-fixnum offset imm0)
[10959]143 (movl (@ (target-nil-value) (% imm0)) (% imm0))
[7963]144 (movl (% imm0) (@ x8632::macptr.address (% ptr)))
[7361]145 (single-value-return))
146
[7963]147(defx8632lapfunction %fixnum-ref ((fixnum arg_y) #| &optional |# (offset arg_z))
[7361]148 (:arglist (fixnum &optional offset))
149 (check-nargs 1 2)
[8374]150 (cmpl ($ x8632::fixnumone) (% nargs))
[7361]151 (jne @2-args)
[7963]152 (movl (% offset) (% fixnum))
[7361]153 (xorl (%l offset) (%l offset))
154 @2-args
155 (unbox-fixnum offset imm0)
[7963]156 (movl (@ (% fixnum) (% imm0)) (% arg_z))
[7361]157 (single-value-return))
158
[7963]159(defx8632lapfunction %fixnum-ref-natural ((fixnum arg_y) #| &optional |# (offset arg_z))
[7361]160 (:arglist (fixnum &optional offset))
161 (check-nargs 1 2)
[8374]162 (cmpl ($ x8632::fixnumone) (% nargs))
[7361]163 (jne @2-args)
[7963]164 (movl (% offset) (% fixnum))
[7361]165 (xorl (%l offset) (%l offset))
166 @2-args
167 (unbox-fixnum offset imm0)
[7963]168 (movl (@ (% fixnum) (% imm0)) (% imm0))
169 (jmp-subprim .SPmakeu32))
[7361]170
[7963]171(defx8632lapfunction %fixnum-set ((fixnum 4) #|(ra 0)|# (offset arg_y) #| &optional |# (new-value arg_z))
[7361]172 (:arglist (fixnum offset &optional newval))
173 (check-nargs 2 3)
[8374]174 (cmpl ($ '2) (% nargs))
[7361]175 (jne @3-args)
[11152]176 (movl (% new-value) (% offset))
177 (single-value-return)
[7361]178 @3-args
[11152]179 (movl (@ fixnum (% esp)) (% temp0))
[7361]180 (unbox-fixnum offset imm0)
[7963]181 (movl (% new-value) (@ (% temp0) (% imm0)))
182 (single-value-return 3))
[7361]183
184
[7963]185(defx8632lapfunction %fixnum-set-natural ((fixnum 4) #|(ra 0)|# (offset arg_y) #| &optional |# (new-value arg_z))
[11152]186 (:arglist (fixnum offsnet &optional newval))
[7361]187 (check-nargs 2 3)
[8374]188 (cmpl ($ '2) (% nargs))
[7361]189 (jne @3-args)
[11152]190 (save-simple-frame)
[7963]191 (movl (% offset) (% temp0))
[11152]192 (xorl (% offset) (% offset))
193 (jmp @common)
[7361]194 @3-args
[11152]195 (movl (% ebp) (@ 8 (% esp)))
196 (lea (@ 8 (% esp)) (% ebp))
197 (popl (@ 4 (% ebp)))
198 (popl (% temp0))
199 @common
[7963]200 (call-subprim .SPgetu32) ;puts u32 in imm0
201 (mark-as-imm temp1)
202 (unbox-fixnum offset temp1)
203 (movl (% imm0) (@ (% temp0) (% temp1)))
204 (mark-as-node temp1)
[7361]205 (restore-simple-frame)
[11152]206 (single-value-return))
[7361]207
208
[7963]209(defx8632lapfunction %current-frame-ptr ()
[7361]210 (check-nargs 0)
[7963]211 (movl (% ebp) (% arg_z))
[7361]212 (single-value-return))
213
214
[7963]215(defx8632lapfunction %current-tsp ()
[7361]216 (check-nargs 0)
[10575]217 (movl (:rcontext x8632::tcr.save-tsp) (% arg_z))
[7361]218 (single-value-return))
219
220
[7963]221(defx8632lapfunction %%frame-backlink ((p arg_z))
[7361]222 (check-nargs 1)
[7963]223 (movl (@ (% arg_z)) (% arg_z))
[7361]224 (single-value-return))
225
[7963]226;;; Look for "movl $imm32,%fn at the tra; if present, then $imm32 is
227;;; the address of the function.
228;;;
229;;; That is: #b10111111 <imm32>
230;;; ^^^^
231;;; operand size || register number (%fn/%edi)
232
233(defx8632lapfunction %return-address-function ((r arg_z))
[9642]234 (extract-fulltag r imm0)
[7963]235 (cmpb ($ x8632::fulltag-tra) (% imm0.b))
[7361]236 (jne @fail)
[7963]237 (cmpb ($ x8632::recover-fn-opcode-byte) (@ (% r)))
[7361]238 (jne @fail)
[7963]239 (movl (@ x8632::recover-fn-address-offset (% r)) (% arg_z))
[7361]240 (single-value-return)
241 @fail
[10959]242 (movl ($ (target-nil-value)) (% arg_z))
[7361]243 (single-value-return))
244
[7963]245(defx8632lapfunction %return-address-offset ((r arg_z))
[9642]246 (extract-fulltag r imm0)
[7963]247 (cmpb ($ x8632::fulltag-tra) (% imm0.b))
[7361]248 (jne @fail)
[7963]249 (cmpb ($ x8632::recover-fn-opcode-byte) (@ (% r)))
[7361]250 (jne @fail)
[7963]251 (movl (@ x8632::recover-fn-address-offset (% r)) (% imm0))
[9643]252 (subl (% arg_z) (% imm0))
253 (negl (% imm0))
[7963]254 (box-fixnum imm0 arg_z)
[9643]255 (single-value-return)
[7361]256 @fail
[10959]257 (movl ($ (target-nil-value)) (% arg_z))
[7361]258 (single-value-return))
259
260;;; It's always been the case that the function associated with a
261;;; frame pointer is the caller of the function that "uses" that frame.
262(defun %cfp-lfun (p)
[7963]263 (let* ((ra (%fixnum-ref p x8632::lisp-frame.return-address)))
[7361]264 (if (eq ra (%get-kernel-global ret1valaddr))
[7963]265 (setq ra (%fixnum-ref p x8632::lisp-frame.xtra)))
[7361]266 (values (%return-address-function ra) (%return-address-offset ra))))
267
[7963]268(defx8632lapfunction %uvector-data-fixnum ((uv arg_z))
[7361]269 (check-nargs 1)
[7963]270 (trap-unless-fulltag= arg_z x8632::fulltag-misc)
271 (addl ($ x8632::misc-data-offset) (% arg_z))
[7361]272 (single-value-return))
273
[7963]274(defx8632lapfunction %catch-top ((tcr arg_z))
[7361]275 (check-nargs 1)
[10959]276 (movl ($ (target-nil-value)) (% arg_y))
[10575]277 (movl (:rcontext x8632::tcr.catch-top) (% arg_z))
[7361]278 (testb (%b arg_z) (%b arg_z))
[7963]279 (cmovel (% arg_y) (% arg_z))
[7361]280 (single-value-return))
281
[7963]282(defx8632lapfunction %catch-tsp ((catch arg_z))
[7361]283 (check-nargs 1)
[7963]284 (lea (@ (- (+ x8632::fulltag-misc
285 (ash 1 (1+ x8632::word-shift)))) (% arg_z))
[7361]286 (% arg_z))
287 (single-value-return))
288
289;;; Same as %address-of, but doesn't cons any bignums
290;;; It also left shift fixnums just like everything else.
[7963]291(defx8632lapfunction %fixnum-address-of ((x arg_z))
[7361]292 (check-nargs 1)
293 (box-fixnum x arg_z)
294 (single-value-return))
295
[7963]296(defx8632lapfunction %save-standard-binding-list ((bindings arg_z))
297 (mark-as-imm temp0)
[10575]298 (movl (:rcontext x8632::tcr.vs-area) (% imm0))
[7963]299 (movl (@ x8632::area.high (% imm0)) (% temp0))
300 (subl ($ x8632::node-size) (% temp0))
301 (movl (% bindings) (@ (% temp0)))
302 (mark-as-node temp0)
[7361]303 (single-value-return))
304
[7963]305(defx8632lapfunction %saved-bindings-address ()
306 (mark-as-imm temp0)
[10575]307 (movl (:rcontext x8632::tcr.vs-area) (% imm0))
[7963]308 (movl (@ x8632::area.high (% imm0)) (% temp0))
309 (leal (@ (- x8632::node-size) (% temp0)) (% arg_z))
310 (mark-as-node temp0)
[7361]311 (single-value-return))
312
[7963]313(defx8632lapfunction %get-object ((macptr arg_y) (offset arg_z))
[7361]314 (check-nargs 2)
[7963]315 (trap-unless-typecode= macptr x8632::subtag-macptr)
316 (trap-unless-lisptag= offset x8632::tag-fixnum)
[7361]317 (macptr-ptr macptr imm0)
[7963]318 (mark-as-imm temp0)
319 (unbox-fixnum offset temp0)
320 (movl (@ (% imm0) (% temp0)) (% arg_z))
321 (mark-as-node temp0)
[7361]322 (single-value-return))
323
[7963]324(defx8632lapfunction %set-object ((macptr 4) #|(ra 0)|# (offset arg_y) (value arg_z))
[7361]325 (check-nargs 3)
[7963]326 (movl (@ macptr (% esp)) (% temp1))
327 (trap-unless-typecode= temp1 x8632::subtag-macptr)
328 (trap-unless-lisptag= offset x8632::tag-fixnum)
329 (macptr-ptr temp1 imm0)
330 (mark-as-imm temp0)
331 (unbox-fixnum offset temp0)
332 (movl (% arg_z) (@ (% imm0) (% temp0)))
333 (mark-as-node temp0)
[8691]334 (single-value-return 3))
[7361]335
[7963]336(defx8632lapfunction %apply-lexpr-with-method-context ((magic 4)
337 #|(ra 0)|#
338 (function arg_y)
339 (args arg_z))
[7361]340 ;; Somebody's called (or tail-called) us.
[9136]341 ;; * Put magic arg in %rcontext:tcr.next-method-context
342 ;; * Put function somewhere safe until we're ready to jump to it
343 ;; * Set nargs to 0, then spread "args" on stack (clobbers regs)
344 ;; * Jump to function (saved previously)
[10575]345 (popl (:rcontext x8632::tcr.save0)) ;return address
346 (popl (:rcontext x8632::tcr.next-method-context)) ;magic arg
[9146]347 (discard-reserved-frame)
[10575]348 (movl (% function) (:rcontext x8632::tcr.save1))
[8656]349 (set-nargs 0)
350 (movl (@ (% args)) (% temp0)) ;lexpr-count
351 (movl (% temp0) (% nargs))
352 (leal (@ x8632::node-size (% arg_z) (% temp0)) (% imm0))
[9136]353 (subl ($ '2) (% temp0))
[7361]354 (jbe @reg-only)
[7963]355 ;; Some args will be pushed; reserve a frame.
356 (pushl ($ x8632::reserved-frame-marker))
357 (pushl ($ x8632::reserved-frame-marker))
[7361]358 @pushloop
[8656]359 (pushl (@ (- x8632::node-size) (% imm0)))
360 (subl ($ x8632::node-size) (% imm0))
[7963]361 (subl ($ x8632::node-size) (% temp0))
[7361]362 (jne @pushloop)
363 @two
[7963]364 (movl (@ (* x8632::node-size 2) (% arg_z)) (% arg_y))
[7361]365 @one
[7963]366 (movl (@ (* x8632::node-size 1) (% arg_z)) (% arg_z))
[7361]367 (jmp @go)
368 @reg-only
[9136]369 (rcmp (% nargs) ($ '1))
[7963]370 (je @one)
371 (jb @go)
372 (jmp @two)
[7361]373 @go
[10575]374 (pushl (:rcontext x8632::tcr.save0)) ;return address
375 (movl (:rcontext x8632::tcr.save1) (% temp0)) ;function
376 (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear spill area
[9136]377 (jmp (% temp0)))
[7361]378
[7963]379(defx8632lapfunction %apply-with-method-context ((magic 4)
380 #|(ra 0)|#
381 (function arg_y)
382 (args arg_z))
383 ;; Similar to above.
[10575]384 (popl (:rcontext x8632::tcr.save0)) ;save return address
385 (popl (:rcontext x8632::tcr.next-method-context)) ;
[9146]386 (discard-reserved-frame)
[10575]387 (movl (% args) (:rcontext x8632::tcr.save2)) ;in case of error
[10489]388 (set-nargs 0)
389 (pushl ($ target::reserved-frame-marker)) ;reserve frame (might discard it
390 (pushl ($ target::reserved-frame-marker)) ;if nothing is passed on stack)
[7361]391 (cmp-reg-to-nil arg_z)
392 (je @done)
393 @loop
[10489]394 (extract-fulltag arg_z imm0)
395 (cmpb ($ x8632::fulltag-cons) (% imm0.b)) ;nil is a cons on x8632, but we
[7963]396 (jne @bad) ; checked for it already.
[10490]397 (add ($ '1) (% nargs)) ;shorter than lea (imm0 is eax)
398 (pushl (@ target::cons.car (% arg_z)))
[7361]399 (%cdr arg_z arg_z)
400 (cmp-reg-to-nil arg_z)
401 (jne @loop)
402 @done
[10490]403 ;; arg_y about to get clobbered; put function into temp0
404 (movl (% function) (% temp0))
[10489]405 ;; temp1 (aka nargs) contains number of args just pushed
406 (test (% nargs) (% nargs))
[7361]407 (jne @pop)
408 @discard-and-go
409 (discard-reserved-frame)
410 (jmp @go)
411 @pop
[7963]412 (cmpl ($ '1) (% nargs))
[7361]413 (pop (% arg_z))
414 (je @discard-and-go)
[7963]415 (cmpl ($ '2) (% nargs))
[7361]416 (pop (% arg_y))
417 (je @discard-and-go)
418 @go
[10575]419 (pushl (:rcontext x8632::tcr.save0)) ;return address
420 (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
[10490]421 (jmp (% temp0))
[7361]422 @bad
[10489]423 (addl (% nargs) (% esp))
[10575]424 (movl (:rcontext x8632::tcr.save1) (% arg_z)) ;saved args
425 (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
[7963]426 (movl ($ '#.$XNOSPREAD) (% arg_y))
[7361]427 (set-nargs 2)
428 (jmp-subprim .SPksignalerr))
429
430;;; The idea here is to call METHOD in the same stack frame in
431;;; which the lexpr was originally called. The lexpr can't
432;;; have had any required arguments, %APPLY-LEXPR-TAIL-WISE
433;;; must have been tail-called, and the frame built on lexpr
434;;; entry must be in %rbp.
[7963]435(defx8632lapfunction %apply-lexpr-tail-wise ((method arg_y) (args arg_z))
436 (addl ($ x8632::node-size) (% esp)) ; discard extra return address
437 (movl (% method) (% xfn)) ;temp1
438 (movl (% args) (% esp))
439 (popl (% imm0)) ;nargs
440 (movl (@ x8632::lisp-frame.return-address (% ebp)) (% temp0))
441 (movl (@ 0 (% ebp)) (% ebp))
[9127]442 (rcmpl (% imm0) ($ '2))
[7361]443 (jbe @pop-regs)
[7963]444 ;; More than 2 args; some must have been pushed by caller,
[7361]445 ;; so retain the reserved frame.
446 (pop (% arg_z))
447 (pop (% arg_y))
448 (jmp @popped)
449 @pop-regs
[9127]450 (rcmpl (% imm0) ($ '1))
[7361]451 (jb @discard)
452 (ja @pop2)
453 (pop (% arg_z))
454 (jmp @discard)
455 @pop2
456 (pop (% arg_z))
457 (pop (% arg_y))
458 @discard
459 (discard-reserved-frame)
460 @popped
[7963]461 (push (% temp0)) ;return address
[9127]462 (movl (% xfn) (% temp0)) ;temp1 is also nargs
463 (movl (% imm0) (% nargs))
464 (jmp (% temp0)))
[7361]465
[7963]466(defun closure-function (fun)
467 (while (and (functionp fun) (not (compiled-function-p fun)))
468 (setq fun (%nth-immediate fun 0))
469 (when (vectorp fun)
470 (setq fun (svref fun 0))))
471 fun)
[7361]472
473;;; For use by (setf (apply ...) ...)
474;;; (apply+ f butlast last) = (apply f (append butlast (list last)))
475
476(defun apply+ (&lap function arg1 arg2 &rest other-args)
477 (x86-lap-function apply+ ()
478 (:arglist (function arg1 arg2 &rest other-args))
479 (check-nargs 3 nil)
[10575]480 (popl (:rcontext x8632::tcr.save0)) ;save return address
[7963]481 ;; only two arg regs on x8632, so the caller will always push a frame
482 (movl (% arg_z) (% temp0)) ; last
483 (movl (% arg_y) (% arg_z)) ; butlast
[8374]484 (subl ($ '2) (% nargs)) ; remove count for butlast & last
[8656]485 (movd (% temp1) (% mm0)) ;save nargs (aka temp1) for later
[7361]486 ;; Do .SPspreadargz inline here
[8656]487 (xorl (%l temp1) (%l temp1))
[10575]488 (movl (% arg_z) (:rcontext x8632::tcr.save1)) ; save in case of error
[7361]489 (cmp-reg-to-nil arg_z)
490 (je @done)
[8656]491 ;;(mark-as-imm temp1)
[7361]492 @loop
[8656]493 (extract-fulltag arg_z imm0)
494 (cmpb ($ x8632::fulltag-cons) (%b imm0))
[7361]495 (jne @bad)
[7963]496 (%car arg_z arg_y)
[7361]497 (%cdr arg_z arg_z)
[8656]498 (addl ($ '1) (%l temp1))
[7361]499 (cmp-reg-to-nil arg_z)
[7963]500 (push (% arg_y))
[7361]501 (jne @loop)
502 @done
503 ;; nargs was at least 1 when we started spreading, and can't have gotten
504 ;; any smaller.
[7963]505 (movd (% mm0) (% arg_y)) ;nargs from before loop
[8656]506 (addl (% arg_y) (% temp1)) ;did I mention nargs is temp1?
[7963]507 (movl (% temp0) (% arg_z))
[7361]508 (pop (% arg_y))
[8374]509 (addl ($ '1) (% nargs))
[7361]510 (load-constant funcall temp0)
[10575]511 (pushl (:rcontext x8632::tcr.save0)) ;return address
512 (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
[7361]513 (jmp-subprim .SPfuncall)
[8656]514 @bad ;error spreading list.
515 (add (% temp1) (% esp)) ;discard whatever's been pushed
[10575]516 (movl (:rcontext x8632::tcr.save1) (% arg_z))
517 (movapd (% fpzero) (:rcontext x8632::tcr.save0)) ;clear out spill area
[7963]518 (movl ($ '#.$XNOSPREAD) (% arg_y))
[7361]519 (set-nargs 2)
520 (jmp-subprim .SPksignalerr) ))
521
522
523
524;;; This needs to:
[12084]525;;; (a) call the .SPffcall subprimitive, which will discard the foreign
526;;; stack frame allocated by WITH-VARIABLE-C-FRAME in %FF-CALL
527;;; (b) re-establish the same foreign stack frame and store the results
528;;; there.
529;;;
530;;; The flags argument tells us what/where the result is:
531;;;
532;;;; flags meaning
533;;; 0 32-bit value in EAX
534;;; 1 single-float value on x87 stack
535;;; 2 double-float value on x87 stack
536;;; 3 64-bit value with low half in EAX, high half in tcr.unboxed1
[8906]537
[9679]538(defx8632lapfunction %do-ff-call ((flags 4) #|(ra 0)|# (frame arg_y) (entry arg_z))
[12084]539 (save-stackargs-frame 1)
[9679]540 (push (% arg_y))
541 (push (% arg_z))
[7361]542 (call-subprim .SPffcall)
[9679]543 ;; there might be an fp result on x87 stack, so don't use
544 ;; any mmx instructions until the result has been read.
[10575]545 (movd (:rcontext x8632::tcr.foreign-sp) (% xmm0))
[9679]546 (movd (% xmm0) (@ (% frame)))
[10575]547 (movl (% frame) (:rcontext x8632::tcr.foreign-sp))
[12084]548 (cmpl ($ 0) (@ -4 (% ebp)))
549 (jne @fp-or-doubleword)
[8656]550 (movl (% eax) (@ 4 (% frame)))
[12084]551 @done
552 (movl ($ nil) (% arg_z))
553 (restore-simple-frame)
554 (single-value-return)
555 @fp-or-doubleword
556 (cmpl ($ '2) (@ -4 (% ebp)))
557 (jl @single)
558 (je @double)
559 ;; high 32 bits in tcr.unboxed1 (see .SPffcall)
560 (movl (% eax) (@ 4 (% frame)))
561 (movl (:rcontext x8632::tcr.unboxed1) (% eax))
562 (movl (% eax) (@ 8 (% frame)))
[9679]563 (jmp @done)
564 @single
565 (fstps (@ 4 (% frame)))
566 (jmp @done)
567 @double
568 (fstpl (@ 4 (% frame)))
[12084]569 (jmp @done))
570
[7361]571(defun %ff-call (entry &rest specs-and-vals)
572 (declare (dynamic-extent specs-and-vals))
573 (let* ((len (length specs-and-vals))
574 (total-words 0))
575 (declare (fixnum len total-words))
576 (let* ((result-spec (or (car (last specs-and-vals)) :void))
[8656]577 (nargs (ash (the fixnum (1- len)) -1)))
578 (declare (fixnum nargs))
[7361]579 (ecase result-spec
[8656]580 ((:address :unsigned-doubleword :signed-doubleword
581 :single-float :double-float
582 :signed-fullword :unsigned-fullword
583 :signed-halfword :unsigned-halfword
584 :signed-byte :unsigned-byte
585 :void)
586 (do* ((i 0 (1+ i))
587 (specs specs-and-vals (cddr specs))
588 (spec (car specs) (car specs)))
589 ((= i nargs))
590 (declare (fixnum i))
591 (case spec
[8906]592 (:registers
593 (error "don't know what to do with argspec ~s" spec))
[8656]594 ((:double-float :unsigned-doubleword :signed-doubleword)
595 (incf total-words 2))
596 ((:address :single-float
597 :signed-fullword :unsigned-fullword
598 :signed-halfword :unsigned-halfword
599 :signed-byte :unsigned-byte)
[7361]600 (incf total-words))
[8656]601 (t (if (typep spec 'unsigned-byte)
602 (incf total-words spec)
603 (error "Invalid argument spec ~s" spec)))))
604 ;; It's necessary to ensure that the C frame is the youngest thing on
605 ;; the foreign stack here.
606 (with-macptrs ((argptr))
607 (with-variable-c-frame
608 total-words frame
609 (%setf-macptr-to-object argptr frame)
[10560]610 (let* ((offset 8))
[8656]611 (do* ((i 0 (1+ i))
612 (specs specs-and-vals (cddr specs))
613 (spec (car specs) (car specs))
614 (val (cadr specs) (cadr specs)))
615 ((= i nargs))
616 (declare (fixnum i))
617 (case spec
618 (:double-float
619 (setf (%get-double-float argptr offset) val)
620 (incf offset 8))
621 (:single-float
622 (setf (%get-single-float argptr offset) val)
623 (incf offset 4))
624 (:signed-doubleword
625 (setf (%%get-signed-longlong argptr offset) val)
626 (incf offset 8))
627 (:unsigned-doubleword
628 (setf (%%get-unsigned-longlong argptr offset) val)
629 (incf offset 8))
630 (:address
631 (setf (%get-ptr argptr offset) val)
632 (incf offset 4))
633 ((:signed-fullword :signed-halfword :signed-byte)
634 (setf (%get-signed-natural argptr offset) val)
635 (incf offset 4))
636 ((:unsigned-fullword :unsigned-halfword :unsigned-byte)
637 (setf (%get-natural argptr offset) val)
638 (incf offset 4))
639 (t
640 (let* ((p 0))
641 (declare (fixnum p))
642 (dotimes (i (the fixnum spec))
643 (setf (%get-ptr argptr offset) (%get-ptr val p))
644 (incf p 4)
645 (incf offset 4))))))
[9679]646 (let ((flags (case result-spec
647 (:single-float 1)
648 (:double-float 2)
[12084]649 ((:signed-doubleword :unsigned-doubleword) 3)
[9679]650 (t 0))))
651 (%do-ff-call flags frame entry))
[8656]652 (ecase result-spec
653 (:void nil)
654 (:address (%get-ptr argptr 4))
655 (:unsigned-byte (%get-unsigned-byte argptr 4))
656 (:signed-byte (%get-signed-byte argptr 4))
657 (:unsigned-halfword (%get-unsigned-word argptr 4))
658 (:signed-halfword (%get-signed-word argptr 4))
659 (:unsigned-fullword (%get-natural argptr 4))
660 (:signed-fullword (%get-signed-natural argptr 4))
661 (:unsigned-doubleword (%%get-unsigned-longlong argptr 4))
662 (:signed-doubleword (%%get-signed-longlong argptr 4))
[9679]663 (:single-float (%get-single-float argptr 4))
664 (:double-float (%get-double-float argptr 4)))))))))))
[7361]665
666;;; end of x86-def.lisp
Note: See TracBrowser for help on using the repository browser.