Remove "-HEADER-" from SYMBOL and VALUE-CELL widetag names
[sbcl.git] / src / compiler / arm64 / type-vops.lisp
blob4084ba1a8382f3120b64c5004739a2d681e6dd21
1 ;;;; type testing and checking VOPs for the ARM 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")
14 (defun %test-fixnum (value target not-p &key temp)
15 (declare (ignore temp))
16 (assemble ()
17 (inst tst value fixnum-tag-mask)
18 (inst b (if not-p :ne :eq) target)))
20 (defun %test-fixnum-immediate-and-headers (value target not-p immediate
21 headers &key temp)
22 (let ((drop-through (gen-label)))
23 (inst tst value fixnum-tag-mask)
24 (inst b :eq (if not-p drop-through target))
25 (%test-immediate-and-headers value target not-p immediate headers
26 :drop-through drop-through :temp temp)))
28 (defun %test-immediate-and-headers (value target not-p immediate headers
29 &key (drop-through (gen-label)) temp)
31 (inst mov temp immediate)
32 (inst cmp temp (extend value :uxtb))
33 (inst b :eq (if not-p drop-through target))
34 (%test-headers value target not-p nil headers :drop-through drop-through
35 :temp temp))
37 (defun %test-fixnum-and-headers (value target not-p headers &key temp)
38 (let ((drop-through (gen-label)))
39 (assemble ()
40 (inst ands temp value fixnum-tag-mask)
41 (inst b :eq (if not-p drop-through target)))
42 (%test-headers value target not-p nil headers
43 :drop-through drop-through :temp temp)))
45 (defun %test-immediate (value target not-p immediate &key temp)
46 (assemble ()
47 (inst and temp value widetag-mask)
48 (inst cmp temp immediate)
49 (inst b (if not-p :ne :eq) target)))
51 (defun %test-lowtag (value target not-p lowtag &key temp)
52 (assemble ()
53 (inst and temp value lowtag-mask)
54 (inst cmp temp lowtag)
55 (inst b (if not-p :ne :eq) target)))
57 (defun %test-headers (value target not-p function-p headers
58 &key temp (drop-through (gen-label)))
59 (let ((lowtag (if function-p fun-pointer-lowtag other-pointer-lowtag)))
60 (multiple-value-bind (when-true when-false)
61 (if not-p
62 (values drop-through target)
63 (values target drop-through))
64 (assemble ()
65 (%test-lowtag value when-false t lowtag :temp temp)
66 (load-type temp value (- lowtag))
67 (do ((remaining headers (cdr remaining)))
68 ((null remaining))
69 (let ((header (car remaining))
70 (last (null (cdr remaining))))
71 (cond
72 ((atom header)
73 (cond
74 ((and (not last) (null (cddr remaining))
75 (atom (cadr remaining))
76 (= (logcount (logxor header (cadr remaining))) 1))
77 (inst and temp temp (logical-mask
78 (ldb (byte 8 0) (logeqv header (cadr remaining)))))
79 (inst cmp temp (ldb (byte 8 0) (logand header (cadr remaining))))
80 (inst b (if not-p :ne :eq) target)
81 (return))
83 (inst cmp temp header)
84 (if last
85 (inst b (if not-p :ne :eq) target)
86 (inst b :eq when-true)))))
88 (let ((start (car header))
89 (end (cdr header)))
90 (cond
91 ((and last (not (= start bignum-widetag))
92 (= (+ start 4) end)
93 (= (logcount (logxor start end)) 1))
94 (inst and temp temp (logical-mask
95 (ldb (byte 8 0) (logeqv start end))))
96 (inst cmp temp (ldb (byte 8 0) (logand start end)))
97 (inst b (if not-p :ne :eq) target))
98 ((and (not last) (null (cddr remaining))
99 (= (+ start 4) end) (= (logcount (logxor start end)) 1)
100 (listp (cadr remaining))
101 (= (+ (caadr remaining) 4) (cdadr remaining))
102 (= (logcount (logxor (caadr remaining) (cdadr remaining))) 1)
103 (= (logcount (logxor (caadr remaining) start)) 1))
104 (inst and temp temp (ldb (byte 8 0) (logeqv start (cdadr remaining))))
105 (inst cmp temp (ldb (byte 8 0) (logand start (cdadr remaining))))
106 (inst b (if not-p :ne :eq) target)
107 (return))
109 (unless (= start bignum-widetag)
110 (inst cmp temp start)
111 (if (= end complex-array-widetag)
112 (progn
113 (aver last)
114 (inst b (if not-p :lt :ge) target))
115 (inst b :lt when-false)))
116 (unless (= end complex-array-widetag)
117 (inst cmp temp end)
118 (if last
119 (inst b (if not-p :gt :le) target)
120 (inst b :le when-true))))))))))
121 (emit-label drop-through)))))
123 ;;;; Other integer ranges.
125 ;;; A (signed-byte 64) can be represented with either fixnum or a bignum with
126 ;;; exactly one digit.
127 (define-vop (signed-byte-64-p type-predicate)
128 (:translate signed-byte-64-p)
129 (:generator 45
130 (multiple-value-bind (yep nope)
131 (if not-p
132 (values not-target target)
133 (values target not-target))
134 (assemble ()
135 (inst ands temp value fixnum-tag-mask)
136 (inst b :eq yep)
137 (test-type value nope t (other-pointer-lowtag) :temp temp)
138 (loadw temp value 0 other-pointer-lowtag)
139 (inst cmp temp (+ (ash 1 n-widetag-bits) bignum-widetag))
140 (inst b (if not-p :ne :eq) target)))
141 not-target))
143 ;;; An (UNSIGNED-BYTE 64) can be represented with either a positive
144 ;;; fixnum, a bignum with exactly one positive digit, or a bignum with
145 ;;; exactly two digits and the second digit all zeros.
146 (define-vop (unsigned-byte-64-p type-predicate)
147 (:translate unsigned-byte-64-p)
148 (:generator 45
149 (let ((single-word (gen-label))
150 (fixnum (gen-label)))
151 (multiple-value-bind (yep nope)
152 (if not-p
153 (values not-target target)
154 (values target not-target))
155 (assemble ()
156 ;; Is it a fixnum?
157 (move temp value)
158 (%test-fixnum temp fixnum nil)
160 ;; If not, is it an other pointer?
161 (test-type value nope t (other-pointer-lowtag) :temp temp)
162 ;; Get the header.
163 (loadw temp value 0 other-pointer-lowtag)
164 ;; Is it one?
165 (inst cmp temp (+ (ash 1 n-widetag-bits) bignum-widetag))
166 (inst b :eq single-word)
167 ;; If it's other than two, it can't be an (unsigned-byte 64)
168 (inst cmp temp (+ (ash 2 n-widetag-bits) bignum-widetag))
169 (inst b :ne nope)
170 ;; Get the second digit.
171 (loadw temp value (1+ bignum-digits-offset) other-pointer-lowtag)
172 ;; All zeros, it's an (unsigned-byte 64).
173 (inst cbz temp yep)
174 (inst b nope)
176 (emit-label single-word)
177 ;; Get the single digit.
178 (loadw temp value bignum-digits-offset other-pointer-lowtag)
180 ;; positive implies (unsigned-byte 64).
181 (emit-label fixnum)
182 (inst cmp temp 0)
183 (if not-p
184 (inst b :lt target)
185 (inst b :ge target))))
186 (values))
187 NOT-TARGET))
189 (define-vop (fixnump/unsigned-byte-64)
190 (:policy :fast-safe)
191 (:args (value :scs (unsigned-reg)))
192 (:arg-types unsigned-num)
193 (:translate fixnump)
194 (:conditional :eq)
195 (:generator 5
196 (inst tst value (ash (1- (ash 1 (- n-word-bits
197 n-positive-fixnum-bits)))
198 n-positive-fixnum-bits))))
200 (define-vop (fixnump/signed-byte-64 type-predicate)
201 (:args (value :scs (signed-reg)))
202 (:conditional :vc)
203 (:info)
204 (:arg-types signed-num)
205 (:translate fixnump)
206 (:generator 5
207 (inst adds temp value value)))
209 ;;; MOD type checks
210 (defun power-of-two-limit-p (x)
211 (and (fixnump x)
212 (= (logcount (1+ x)) 1)))
214 (define-vop (test-fixnum-mod-power-of-two)
215 (:args (value :scs (any-reg descriptor-reg
216 unsigned-reg signed-reg
217 immediate)))
218 (:arg-types *
219 (:constant (satisfies power-of-two-limit-p)))
220 (:translate fixnum-mod-p)
221 (:conditional :eq)
222 (:info hi)
223 (:save-p :compute-only)
224 (:policy :fast-safe)
225 (:generator 2
226 (aver (not (sc-is value immediate)))
227 (let* ((fixnum-hi (if (sc-is value unsigned-reg signed-reg)
229 (fixnumize hi))))
230 (inst tst value (lognot fixnum-hi)))))
232 (define-vop (test-fixnum-mod-tagged-unsigned-imm)
233 (:args (value :scs (any-reg descriptor-reg
234 unsigned-reg signed-reg
235 immediate)))
236 (:arg-types (:or tagged-num unsigned-num signed-num)
237 (:constant (satisfies add-sub-immediate-p)))
238 (:translate fixnum-mod-p)
239 (:conditional :ls)
240 (:info hi)
241 (:save-p :compute-only)
242 (:policy :fast-safe)
243 (:generator 3
244 (aver (not (sc-is value immediate)))
245 (let ((fixnum-hi (if (sc-is value unsigned-reg signed-reg)
247 (fixnumize hi))))
248 (inst cmp value fixnum-hi))))
250 (defun add-sub-immediate+1-p (x)
251 (add-sub-immediate-p (1+ (fixnumize x))))
253 ;;; Adding 1 and changing the codntions from <= to < allows to encode
254 ;;; more immediates.
255 (define-vop (test-fixnum-mod-tagged-unsigned-imm+1)
256 (:args (value :scs (any-reg descriptor-reg
257 unsigned-reg signed-reg
258 immediate)))
259 (:arg-types (:or tagged-num unsigned-num signed-num)
260 (:constant (satisfies add-sub-immediate+1-p)))
261 (:translate fixnum-mod-p)
262 (:conditional :cc)
263 (:info hi)
264 (:save-p :compute-only)
265 (:policy :fast-safe)
266 (:generator 3
267 (aver (not (sc-is value immediate)))
268 (let ((fixnum-hi (if (sc-is value unsigned-reg signed-reg)
269 (1+ hi)
270 (fixnumize (1+ hi)))))
271 (inst cmp value fixnum-hi))))
273 (define-vop (test-fixnum-mod-tagged-unsigned)
274 (:args (value :scs (any-reg descriptor-reg
275 unsigned-reg signed-reg
276 immediate)))
277 (:arg-types (:or tagged-num unsigned-num signed-num)
278 (:constant fixnum))
279 (:temporary (:scs (non-descriptor-reg)) temp)
280 (:translate fixnum-mod-p)
281 (:conditional :ls)
282 (:info hi)
283 (:save-p :compute-only)
284 (:policy :fast-safe)
285 (:generator 4
286 (aver (not (sc-is value immediate)))
287 (let ((fixnum-hi (if (sc-is value unsigned-reg signed-reg)
289 (fixnumize hi))))
290 (load-immediate-word temp fixnum-hi)
291 (inst cmp value temp))))
293 (defun add-sub-immediate/+1-p (x)
294 (let ((x (fixnumize x)))
295 (or (add-sub-immediate-p x)
296 (add-sub-immediate-p (1+ x)))))
298 (define-vop (test-fixnum-mod-*-imm)
299 (:args (value :scs (any-reg descriptor-reg)))
300 (:arg-types * (:constant (satisfies add-sub-immediate/+1-p)))
301 (:translate fixnum-mod-p)
302 (:conditional)
303 (:info target not-p hi)
304 (:save-p :compute-only)
305 (:policy :fast-safe)
306 (:generator 5
307 (let* ((1+ (not (add-sub-immediate-p (fixnumize hi))))
308 (fixnum-hi (fixnumize (if 1+
309 (1+ hi)
310 hi))))
311 #.(assert (= fixnum-tag-mask 1))
312 (cond (not-p
313 (inst tst value fixnum-tag-mask)
314 ;; TBNZ can't jump as far as B.
315 (inst b :ne target))
317 (inst tbnz value 0 skip)))
318 (inst cmp value fixnum-hi)
319 (inst b (if not-p
320 (if 1+ :cs :hi)
321 (if 1+ :cc :ls))
322 target))
323 skip))
325 (define-vop (test-fixnum-mod-*)
326 (:args (value :scs (any-reg descriptor-reg)))
327 (:arg-types * (:constant fixnum))
328 (:translate fixnum-mod-p)
329 (:temporary (:scs (any-reg)) temp)
330 (:conditional)
331 (:info target not-p hi)
332 (:save-p :compute-only)
333 (:policy :fast-safe)
334 (:generator 6
335 #.(assert (= fixnum-tag-mask 1))
336 (cond (not-p
337 (inst tst value fixnum-tag-mask)
338 ;; TBNZ can't jump as far as B.
339 (inst b :ne target))
341 (inst tbnz value 0 skip)))
342 (let ((condition (if not-p :hi :ls)))
343 (load-immediate-word temp (fixnumize hi))
344 (inst cmp value temp)
345 (inst b condition target))
346 SKIP))
348 ;;;; List/symbol types:
350 ;;; symbolp (or symbol (eq nil))
351 ;;; consp (and list (not (eq nil)))
353 (define-vop (symbolp type-predicate)
354 (:translate symbolp)
355 (:generator 12
356 (let* ((drop-thru (gen-label))
357 (is-symbol-label (if not-p drop-thru target)))
358 (inst cmp value null-tn)
359 (inst b :eq is-symbol-label)
360 (test-type value target not-p (symbol-widetag) :temp temp)
361 (emit-label drop-thru))))
363 (define-vop (consp type-predicate)
364 (:translate consp)
365 (:generator 8
366 (let* ((drop-thru (gen-label))
367 (is-not-cons-label (if not-p target drop-thru)))
368 (inst cmp value null-tn)
369 (inst b :eq is-not-cons-label)
370 (test-type value target not-p (list-pointer-lowtag) :temp temp)
371 (emit-label drop-thru))))