1 ;;;; VOPs and other machine-specific support routines for call-out to C
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 (defun my-make-wired-tn (prim-type-name sc-name offset
)
15 (make-wired-tn (primitive-type-or-lose prim-type-name
)
16 (sc-number-or-lose sc-name
)
22 (define-alien-type-method (integer :arg-tn
) (type state
)
23 (let ((stack-frame-size (arg-state-stack-frame-size state
)))
24 (setf (arg-state-stack-frame-size state
) (1+ stack-frame-size
))
26 (ptype reg-sc stack-sc
)
27 (if (alien-integer-type-signed type
)
28 (values 'signed-byte-64
'signed-reg
'signed-stack
)
29 (values 'unsigned-byte-64
'unsigned-reg
'unsigned-stack
))
30 (if (< stack-frame-size
4)
31 (my-make-wired-tn ptype reg-sc
(+ stack-frame-size nl0-offset
))
32 (my-make-wired-tn ptype stack-sc
(* 2 (- stack-frame-size
4)))))))
34 (define-alien-type-method (system-area-pointer :arg-tn
) (type state
)
35 (declare (ignore type
))
36 (let ((stack-frame-size (arg-state-stack-frame-size state
)))
37 (setf (arg-state-stack-frame-size state
) (1+ stack-frame-size
))
38 (if (< stack-frame-size
4)
39 (my-make-wired-tn 'system-area-pointer
41 (+ stack-frame-size nl0-offset
))
42 (my-make-wired-tn 'system-area-pointer
44 (* 2 (- stack-frame-size
4))))))
46 (define-alien-type-method (double-float :arg-tn
) (type state
)
47 (declare (ignore type
))
48 (let ((stack-frame-size (arg-state-stack-frame-size state
)))
49 (setf (arg-state-stack-frame-size state
) (1+ stack-frame-size
))
50 (if (< stack-frame-size
6)
51 (my-make-wired-tn 'double-float
53 (+ stack-frame-size nl0-offset
))
54 (my-make-wired-tn 'double-float
56 (* 2 (- stack-frame-size
4))))))
58 (define-alien-type-method (single-float :arg-tn
) (type state
)
59 (declare (ignore type
))
60 (let ((stack-frame-size (arg-state-stack-frame-size state
)))
61 (setf (arg-state-stack-frame-size state
) (1+ stack-frame-size
))
62 (if (< stack-frame-size
6)
63 (my-make-wired-tn 'single-float
65 (+ stack-frame-size nl0-offset
))
66 (my-make-wired-tn 'single-float
68 (* 2 (- stack-frame-size
4))))))
70 (define-alien-type-method (integer :result-tn
) (type state
)
71 (declare (ignore state
))
74 (if (alien-integer-type-signed type
)
75 (values 'signed-byte-64
'signed-reg
)
76 (values 'unsigned-byte-64
'unsigned-reg
))
77 (my-make-wired-tn ptype reg-sc lip-offset
)))
79 (define-alien-type-method (integer :naturalize-gen
) (type alien
)
80 (if (<= (alien-type-bits type
) 32)
81 (if (alien-integer-type-signed type
)
82 `(sign-extend ,alien
,(alien-type-bits type
))
83 `(logand ,alien
,(1- (ash 1 (alien-type-bits type
)))))
86 (define-alien-type-method (system-area-pointer :result-tn
) (type state
)
87 (declare (ignore type state
))
88 (my-make-wired-tn 'system-area-pointer
'sap-reg lip-offset
))
90 (define-alien-type-method (double-float :result-tn
) (type state
)
91 (declare (ignore type state
))
92 (my-make-wired-tn 'double-float
'double-reg lip-offset
))
94 (define-alien-type-method (single-float :result-tn
) (type state
)
95 (declare (ignore type state
))
96 (my-make-wired-tn 'single-float
'single-reg lip-offset
))
98 (define-alien-type-method (values :result-tn
) (type state
)
99 (let ((values (alien-values-type-values type
)))
101 (error "Too many result values from c-call."))
103 (invoke-alien-type-method :result-tn
(car values
) state
))))
105 (defun make-call-out-tns (type)
106 (let ((arg-state (make-arg-state)))
108 (dolist (arg-type (alien-fun-type-arg-types type
))
109 (arg-tns (invoke-alien-type-method :arg-tn arg-type arg-state
)))
110 (values (my-make-wired-tn 'positive-fixnum
'any-reg nsp-offset
)
111 (* (max (- (logandc2 (1+ (arg-state-stack-frame-size arg-state
)) 1) 4) 2)
113 #.
(floor n-machine-word-bits n-word-bits
))
115 (invoke-alien-type-method :result-tn
116 (alien-fun-type-result-type type
)
119 (defknown sign-extend
((signed-byte 64) t
) fixnum
120 (foldable flushable movable
))
122 (define-vop (sign-extend)
123 (:translate sign-extend
)
125 (:args
(val :scs
(signed-reg) :target res
))
126 (:arg-types signed-num
(:constant fixnum
))
128 (:results
(res :scs
(signed-reg)))
129 (:result-types fixnum
)
133 ;;(inst sextb val res) ;; Under what circumstances can we use this?
134 (inst sll val
56 res
)
135 (inst sra res
56 res
))
137 ;;(inst sextw val res) ;; Under what circumstances can we use this?
138 (inst sll val
48 res
)
139 (inst sra res
48 res
))
141 (inst sll val
32 res
)
142 (inst sra res
32 res
)))))
145 (defun sign-extend (x size
)
146 (declare (type (signed-byte 64) x
))
148 (8 (sign-extend x size
))
149 (16 (sign-extend x size
))
150 (32 (sign-extend x size
))))
153 (defun sign-extend (x size
)
154 (if (logbitp (1- size
) x
)
155 (dpb x
(byte size
0) -
1)
158 (define-vop (foreign-symbol-sap)
159 (:translate foreign-symbol-sap
)
162 (:arg-types
(:constant simple-string
))
163 (:info foreign-symbol
)
164 (:results
(res :scs
(sap-reg)))
165 (:result-types system-area-pointer
)
167 (inst li
(make-fixup foreign-symbol
:foreign
) res
)))
169 (define-vop (call-out)
170 (:args
(function :scs
(sap-reg) :target cfunc
)
172 (:results
(results :more t
))
173 (:ignore args results
)
175 (:temporary
(:sc any-reg
:offset cfunc-offset
176 :from
(:argument
0) :to
(:result
0)) cfunc
)
177 (:temporary
(:sc control-stack
:offset nfp-save-offset
) nfp-save
)
178 (:temporary
(:scs
(non-descriptor-reg)) temp
)
181 (let ((cur-nfp (sb!c
::current-nfp-tn vop
)))
183 (store-stack-tn nfp-save cur-nfp
))
184 (move function cfunc
)
185 (inst li
(make-fixup "call_into_c" :foreign
) temp
)
186 (inst jsr lip-tn temp
(make-fixup "call_into_c" :foreign
))
188 (maybe-load-stack-nfp-tn cur-nfp nfp-save temp
)))))
190 (define-vop (alloc-number-stack-space)
192 (:results
(result :scs
(sap-reg any-reg
)))
193 (:result-types system-area-pointer
)
194 (:temporary
(:scs
(unsigned-reg) :to
(:result
0)) temp
)
196 (unless (zerop amount
)
197 (let ((delta (logandc2 (+ amount
7) 7)))
198 (cond ((< delta
(ash 1 15))
199 (inst lda nsp-tn
(- delta
) nsp-tn
))
202 (inst subq nsp-tn temp nsp-tn
)))))
203 (move nsp-tn result
)))
205 (define-vop (dealloc-number-stack-space)
208 (:temporary
(:scs
(unsigned-reg) :to
(:result
0)) temp
)
210 (unless (zerop amount
)
211 (let ((delta (logandc2 (+ amount
7) 7)))
212 (cond ((< delta
(ash 1 15))
213 (inst lda nsp-tn delta nsp-tn
))
216 (inst addq nsp-tn temp nsp-tn
)))))))