Tweaks to get sb-simd 1.3 to compile
[sbcl/simd.git] / src / compiler / sparc / type-vops.lisp
blob960ce711b573010f3a210f736e5f836466539e0f
1 ;;;; type testing and checking VOPs for the Sparc VM
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!VM")
15 (defun %test-fixnum (value target not-p &key temp)
16 (declare (ignore temp))
17 (assemble ()
18 (inst andcc zero-tn value fixnum-tag-mask)
19 (if (member :sparc-v9 *backend-subfeatures*)
20 (inst b (if not-p :ne :eq) target (if not-p :pn :pt))
21 (inst b (if not-p :ne :eq) target))
22 (inst nop)))
24 (defun %test-fixnum-and-headers (value target not-p headers
25 &key temp)
26 (let ((drop-through (gen-label)))
27 (assemble ()
28 (inst andcc zero-tn value fixnum-tag-mask)
29 (inst b :eq (if not-p drop-through target)))
30 (%test-headers value target not-p nil headers
31 :drop-through drop-through
32 :temp temp)))
34 (defun %test-immediate (value target not-p immediate &key temp)
35 (assemble ()
36 (inst and temp value widetag-mask)
37 (inst cmp temp immediate)
38 ;; FIXME: include SPARC-V9 magic
39 (inst b (if not-p :ne :eq) target)
40 (inst nop)))
42 (defun %test-lowtag (value target not-p lowtag
43 &key temp skip-nop)
44 (assemble ()
45 (inst and temp value lowtag-mask)
46 (inst cmp temp lowtag)
47 ;; FIXME: include SPARC-V9 magic
48 (inst b (if not-p :ne :eq) target)
49 (unless skip-nop
50 (inst nop))))
52 (defun %test-headers (value target not-p function-p headers
53 &key temp (drop-through (gen-label)))
54 (let ((lowtag (if function-p fun-pointer-lowtag other-pointer-lowtag)))
55 (multiple-value-bind (when-true when-false)
56 (if not-p
57 (values drop-through target)
58 (values target drop-through))
59 (assemble ()
60 (%test-lowtag value when-false t lowtag :temp temp)
61 (load-type temp value (- lowtag))
62 (do ((remaining headers (cdr remaining)))
63 ((null remaining))
64 (let ((header (car remaining))
65 (last (null (cdr remaining))))
66 (cond
67 ((atom header)
68 (cond
69 ((and (not last) (null (cddr remaining))
70 (atom (cadr remaining))
71 (= (logcount (logxor header (cadr remaining))) 1))
72 (inst and temp temp (ldb (byte 8 0) (logeqv header (cadr remaining))))
73 (inst cmp temp (ldb (byte 8 0) (logand header (cadr remaining))))
74 (inst b (if not-p :ne :eq) target)
75 (return))
77 (inst cmp temp header)
78 (if last
79 ;; FIXME: Some SPARC-V9 magic might not go amiss
80 ;; here, too, if I can figure out what it should
81 ;; be.
82 (inst b (if not-p :ne :eq) target)
83 (inst b :eq when-true)))))
85 (let ((start (car header))
86 (end (cdr header)))
87 ;; FIXME: BIGNUM-WIDETAG here actually means (MIN
88 ;; <widetags>).
89 (cond
90 ;; FIXME: this doesn't catch the {0x2 0x6 0xA 0xE}
91 ;; group
93 ;; also FIXME: exuberant cut'n'paste between
94 ;; backends
95 ((and last (not (= start bignum-widetag))
96 (= (+ start 4) end)
97 (= (logcount (logxor start end)) 1))
98 (inst and temp temp (ldb (byte 8 0) (logeqv start end)))
99 (inst cmp temp (ldb (byte 8 0) (logand start end)))
100 (inst b (if not-p :ne :eq) target))
101 ((and (not last) (null (cddr remaining))
102 (= (+ start 4) end) (= (logcount (logxor start end)) 1)
103 (listp (cadr remaining))
104 (= (+ (caadr remaining) 4) (cdadr remaining))
105 (= (logcount (logxor (caadr remaining) (cdadr remaining))) 1)
106 (= (logcount (logxor (caadr remaining) start)) 1))
107 (inst and temp temp (ldb (byte 8 0) (logeqv start (cdadr remaining))))
108 (inst cmp temp (ldb (byte 8 0) (logand start (cdadr remaining))))
109 (inst b (if not-p :ne :eq) target)
110 (return))
112 (unless (= start bignum-widetag)
113 (inst cmp temp start)
114 (if (= end complex-array-widetag)
115 (progn
116 (aver last)
117 (inst b (if not-p :lt :ge) target))
118 (inst b :lt when-false)))
119 (unless (= end complex-array-widetag)
120 (inst cmp temp end)
121 (if last
122 (inst b (if not-p :gt :le) target)
123 (inst b :le when-true))))))))))
124 (inst nop)
125 (emit-label drop-through)))))
127 ;;;; Simple type checking and testing:
129 ;;; These types are represented by a single type code, so are easily
130 ;;; open-coded as a mask and compare.
131 (define-vop (check-type)
132 (:args (value :target result :scs (any-reg descriptor-reg)))
133 (:results (result :scs (any-reg descriptor-reg)))
134 (:temporary (:scs (non-descriptor-reg)) temp)
135 (:vop-var vop)
136 (:save-p :compute-only))
138 (define-vop (type-predicate)
139 (:args (value :scs (any-reg descriptor-reg)))
140 (:conditional)
141 (:info target not-p)
142 (:policy :fast-safe)
143 (:temporary (:scs (non-descriptor-reg)) temp))
145 (defun cost-to-test-types (type-codes)
146 (+ (* 2 (length type-codes))
147 (if (> (apply #'max type-codes) lowtag-limit) 7 2)))
149 (defmacro !define-type-vops (pred-name check-name ptype error-code
150 (&rest type-codes)
151 &key &allow-other-keys)
152 (let ((cost (cost-to-test-types (mapcar #'eval type-codes))))
153 `(progn
154 ,@(when pred-name
155 `((define-vop (,pred-name type-predicate)
156 (:translate ,pred-name)
157 (:generator ,cost
158 (test-type value target not-p (,@type-codes)
159 :temp temp)))))
160 ,@(when check-name
161 `((define-vop (,check-name check-type)
162 (:generator ,cost
163 (let ((err-lab
164 (generate-error-code vop ,error-code value)))
165 (test-type value err-lab t (,@type-codes)
166 :temp temp)
167 (move result value))))))
168 ,@(when ptype
169 `((primitive-type-vop ,check-name (:check) ,ptype))))))
172 ;;;; Other integer ranges.
174 ;; A (signed-byte 32) can be represented with either fixnum or a
175 ;; bignum with exactly one digit.
177 (define-vop (signed-byte-32-p type-predicate)
178 (:translate signed-byte-32-p)
179 (:generator 45
180 (let ((not-target (gen-label)))
181 (multiple-value-bind
182 (yep nope)
183 (if not-p
184 (values not-target target)
185 (values target not-target))
186 (inst andcc zero-tn value #x3)
187 (inst b :eq yep)
188 (test-type value nope t (other-pointer-lowtag) :temp temp)
189 (loadw temp value 0 other-pointer-lowtag)
190 (inst cmp temp (+ (ash 1 n-widetag-bits)
191 bignum-widetag))
192 (inst b (if not-p :ne :eq) target)
193 (inst nop)
194 (emit-label not-target)))))
196 (define-vop (check-signed-byte-32 check-type)
197 (:generator 45
198 (let ((nope (generate-error-code vop object-not-signed-byte-32-error value))
199 (yep (gen-label)))
200 (inst andcc temp value #x3)
201 (inst b :eq yep)
202 (test-type value nope t (other-pointer-lowtag) :temp temp)
203 (loadw temp value 0 other-pointer-lowtag)
204 (inst cmp temp (+ (ash 1 n-widetag-bits) bignum-widetag))
205 (inst b :ne nope)
206 (inst nop)
207 (emit-label yep)
208 (move result value))))
211 ;; An (unsigned-byte 32) can be represented with either a
212 ;; positive fixnum, a bignum with exactly one positive digit, or
213 ;; a bignum with exactly two digits and the second digit all
214 ;; zeros.
216 (define-vop (unsigned-byte-32-p type-predicate)
217 (:translate unsigned-byte-32-p)
218 (:generator 45
219 (let ((not-target (gen-label))
220 (single-word (gen-label))
221 (fixnum (gen-label)))
222 (multiple-value-bind
223 (yep nope)
224 (if not-p
225 (values not-target target)
226 (values target not-target))
227 ;; Is it a fixnum?
228 (inst andcc temp value #x3)
229 (inst b :eq fixnum)
230 (inst cmp value)
232 ;; If not, is it an other pointer?
233 (test-type value nope t (other-pointer-lowtag) :temp temp)
234 ;; Get the header.
235 (loadw temp value 0 other-pointer-lowtag)
236 ;; Is it one?
237 (inst cmp temp (+ (ash 1 n-widetag-bits) bignum-widetag))
238 (inst b :eq single-word)
239 ;; If it's other than two, we can't be an
240 ;; (unsigned-byte 32)
241 (inst cmp temp (+ (ash 2 n-widetag-bits) bignum-widetag))
242 (inst b :ne nope)
243 ;; Get the second digit.
244 (loadw temp value (1+ bignum-digits-offset) other-pointer-lowtag)
245 ;; All zeros, its an (unsigned-byte 32).
246 (inst cmp temp)
247 (inst b :eq yep)
248 (inst nop)
249 ;; Otherwise, it isn't.
250 (inst b nope)
251 (inst nop)
253 (emit-label single-word)
254 ;; Get the single digit.
255 (loadw temp value bignum-digits-offset other-pointer-lowtag)
256 (inst cmp temp)
258 ;; positive implies (unsigned-byte 32).
259 (emit-label fixnum)
260 (inst b (if not-p :lt :ge) target)
261 (inst nop)
263 (emit-label not-target)))))
265 (define-vop (check-unsigned-byte-32 check-type)
266 (:generator 45
267 (let ((nope
268 (generate-error-code vop object-not-unsigned-byte-32-error value))
269 (yep (gen-label))
270 (fixnum (gen-label))
271 (single-word (gen-label)))
272 ;; Is it a fixnum?
273 (inst andcc temp value #x3)
274 (inst b :eq fixnum)
275 (inst cmp value)
277 ;; If not, is it an other pointer?
278 (test-type value nope t (other-pointer-lowtag) :temp temp)
279 ;; Get the number of digits.
280 (loadw temp value 0 other-pointer-lowtag)
281 ;; Is it one?
282 (inst cmp temp (+ (ash 1 n-widetag-bits) bignum-widetag))
283 (inst b :eq single-word)
284 ;; If it's other than two, we can't be an (unsigned-byte 32)
285 (inst cmp temp (+ (ash 2 n-widetag-bits) bignum-widetag))
286 (inst b :ne nope)
287 ;; Get the second digit.
288 (loadw temp value (1+ bignum-digits-offset) other-pointer-lowtag)
289 ;; All zeros, its an (unsigned-byte 32).
290 (inst cmp temp)
291 (inst b :eq yep)
292 ;; Otherwise, it isn't.
293 (inst b :ne nope)
294 (inst nop)
296 (emit-label single-word)
297 ;; Get the single digit.
298 (loadw temp value bignum-digits-offset other-pointer-lowtag)
299 ;; positive implies (unsigned-byte 32).
300 (inst cmp temp)
302 (emit-label fixnum)
303 (inst b :lt nope)
304 (inst nop)
306 (emit-label yep)
307 (move result value))))
311 ;;;; List/symbol types:
313 ;; symbolp (or symbol (eq nil))
314 ;; consp (and list (not (eq nil)))
316 (define-vop (symbolp type-predicate)
317 (:translate symbolp)
318 (:generator 12
319 (let* ((drop-thru (gen-label))
320 (is-symbol-label (if not-p drop-thru target)))
321 (inst cmp value null-tn)
322 (inst b :eq is-symbol-label)
323 (test-type value target not-p (symbol-header-widetag) :temp temp)
324 (emit-label drop-thru))))
326 (define-vop (check-symbol check-type)
327 (:generator 12
328 (let ((drop-thru (gen-label))
329 (error (generate-error-code vop object-not-symbol-error value)))
330 (inst cmp value null-tn)
331 (inst b :eq drop-thru)
332 (test-type value error t (symbol-header-widetag) :temp temp)
333 (emit-label drop-thru)
334 (move result value))))
336 (define-vop (consp type-predicate)
337 (:translate consp)
338 (:generator 8
339 (let* ((drop-thru (gen-label))
340 (is-not-cons-label (if not-p target drop-thru)))
341 (inst cmp value null-tn)
342 (inst b :eq is-not-cons-label)
343 (test-type value target not-p (list-pointer-lowtag) :temp temp)
344 (emit-label drop-thru))))
346 (define-vop (check-cons check-type)
347 (:generator 8
348 (let ((error (generate-error-code vop object-not-cons-error value)))
349 (inst cmp value null-tn)
350 (inst b :eq error)
351 (test-type value error t (list-pointer-lowtag) :temp temp)
352 (move result value))))