1 ;;;; stuff to handle simple cases for generic arithmetic
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.
16 ;;;; Addition and subtraction.
18 ;;; static-fun-offset returns the address of the raw_addr slot of
19 ;;; a static function's fdefn.
21 ;;; Note that there is only one use of static-fun-offset outside this
22 ;;; file (in genesis.lisp)
24 (define-assembly-routine (generic-+
26 (:return-style :full-call)
30 ((:arg x (descriptor-reg any-reg) a0-offset)
31 (:arg y (descriptor-reg any-reg) a1-offset)
33 (:res res (descriptor-reg any-reg) a0-offset)
35 (:temp temp non-descriptor-reg nl0-offset)
36 (:temp temp1 non-descriptor-reg nl1-offset)
37 (:temp temp2 non-descriptor-reg nl2-offset)
38 (:temp pa-flag non-descriptor-reg nl4-offset)
39 (:temp lra descriptor-reg lra-offset)
40 (:temp lip interior-reg lip-offset)
41 (:temp nargs any-reg nargs-offset)
42 (:temp ocfp any-reg ocfp-offset))
44 (inst and temp fixnum-tag-mask)
45 (inst bne temp DO-STATIC-FUN)
48 (inst xor temp1 temp x)
49 (inst xor temp2 temp y)
50 (inst and temp1 temp2)
51 (inst bltz temp1 DO-OVERFLOW)
52 (inst sra temp1 x n-fixnum-tag-bits)
54 (lisp-return lra lip :offset 2)
57 ;; We did overflow, so do the bignum version
58 (inst sra temp2 y n-fixnum-tag-bits)
59 (inst addu temp temp1 temp2)
60 (with-fixed-allocation (res pa-flag temp2 bignum-widetag
61 (1+ bignum-digits-offset) nil)
62 (storew temp res bignum-digits-offset other-pointer-lowtag))
63 (lisp-return lra lip :offset 2)
66 (inst lw lip null-tn (static-fun-offset 'two-arg-+))
67 (inst li nargs (fixnumize 2))
70 (move cfp-tn csp-tn t))
73 (define-assembly-routine (generic--
75 (:return-style :full-call)
79 ((:arg x (descriptor-reg any-reg) a0-offset)
80 (:arg y (descriptor-reg any-reg) a1-offset)
82 (:res res (descriptor-reg any-reg) a0-offset)
84 (:temp temp non-descriptor-reg nl0-offset)
85 (:temp temp1 non-descriptor-reg nl1-offset)
86 (:temp temp2 non-descriptor-reg nl2-offset)
87 (:temp pa-flag non-descriptor-reg nl4-offset)
88 (:temp lra descriptor-reg lra-offset)
89 (:temp lip interior-reg lip-offset)
90 (:temp nargs any-reg nargs-offset)
91 (:temp ocfp any-reg ocfp-offset))
93 (inst and temp fixnum-tag-mask)
94 (inst bne temp DO-STATIC-FUN)
98 (inst xor temp2 x temp)
99 (inst and temp1 temp2)
100 (inst bltz temp1 DO-OVERFLOW)
101 (inst sra temp1 x n-fixnum-tag-bits)
103 (lisp-return lra lip :offset 2)
106 ;; We did overflow, so do the bignum version
107 (inst sra temp2 y n-fixnum-tag-bits)
108 (inst subu temp temp1 temp2)
109 (with-fixed-allocation (res pa-flag temp2 bignum-widetag
110 (1+ bignum-digits-offset) nil)
111 (storew temp res bignum-digits-offset other-pointer-lowtag))
112 (lisp-return lra lip :offset 2)
115 (inst lw lip null-tn (static-fun-offset 'two-arg--))
116 (inst li nargs (fixnumize 2))
119 (move cfp-tn csp-tn t))
126 (define-assembly-routine (generic-*
128 (:return-style :full-call)
132 ((:arg x (descriptor-reg any-reg) a0-offset)
133 (:arg y (descriptor-reg any-reg) a1-offset)
135 (:res res (descriptor-reg any-reg) a0-offset)
137 (:temp temp non-descriptor-reg nl0-offset)
138 (:temp lo non-descriptor-reg nl1-offset)
139 (:temp hi non-descriptor-reg nl2-offset)
140 (:temp pa-flag non-descriptor-reg nl4-offset)
141 (:temp lra descriptor-reg lra-offset)
142 (:temp lip interior-reg lip-offset)
143 (:temp nargs any-reg nargs-offset)
144 (:temp ocfp any-reg ocfp-offset))
145 ;; If either arg is not a fixnum, call the static function.
147 (inst and temp fixnum-tag-mask)
148 (inst bne temp DO-STATIC-FUN)
149 ;; Remove the tag from one arg so that the result will have the correct
151 (inst sra temp x n-fixnum-tag-bits)
155 ;; Check to see if the result will fit in a fixnum. (I.e. the high word
156 ;; is just 32 copies of the sign bit of the low word).
157 (inst sra temp res 31)
158 (inst bne temp hi DO-BIGNUM)
159 (inst srl lo res n-fixnum-tag-bits)
160 (lisp-return lra lip :offset 2)
163 ;; Shift the double word hi:res down two bits into hi:low to get rid of the
165 (inst sll temp hi (- n-word-bits n-fixnum-tag-bits))
167 (inst sra hi n-fixnum-tag-bits)
169 ;; Do we need one word or two? Assume two.
170 (inst sra temp lo 31)
171 (inst bne temp hi TWO-WORDS)
172 ;; Assume a two word header.
173 (inst li temp (logior (ash 2 n-widetag-bits) bignum-widetag))
175 ;; Only need one word, fix the header.
176 (inst li temp (logior (ash 1 n-widetag-bits) bignum-widetag))
178 (pseudo-atomic (pa-flag :extra (pad-data-block (+ 1 bignum-digits-offset)))
179 (inst or res alloc-tn other-pointer-lowtag)
180 (storew temp res 0 other-pointer-lowtag))
181 (storew lo res bignum-digits-offset other-pointer-lowtag)
182 (lisp-return lra lip :offset 2)
185 (pseudo-atomic (pa-flag :extra (pad-data-block (+ 2 bignum-digits-offset)))
186 (inst or res alloc-tn other-pointer-lowtag)
187 (storew temp res 0 other-pointer-lowtag))
189 (storew lo res bignum-digits-offset other-pointer-lowtag)
190 (storew hi res (1+ bignum-digits-offset) other-pointer-lowtag)
191 (lisp-return lra lip :offset 2)
194 (inst lw lip null-tn (static-fun-offset 'two-arg-*))
195 (inst li nargs (fixnumize 2))
198 (move cfp-tn csp-tn t))
202 ((frob (name note cost type sc signed-p)
203 `(define-assembly-routine (,name
208 (:arg-types ,type ,type)
209 (:result-types ,type))
210 ((:arg x ,sc nl0-offset)
211 (:arg y ,sc nl1-offset)
212 (:res res ,sc nl0-offset))
213 ,@(when (eq type 'tagged-num)
215 (inst ,(if signed-p 'mult 'multu) x y)
217 (frob unsigned-* "unsigned *" 40 unsigned-num unsigned-reg nil)
218 (frob signed-* "signed *" 41 signed-num signed-reg t)
219 (frob fixnum-* "fixnum *" 30 tagged-num any-reg t))
226 (define-assembly-routine (positive-fixnum-truncate
227 (:note "unsigned fixnum truncate")
229 (:translate truncate)
231 (:arg-types positive-fixnum positive-fixnum)
232 (:result-types positive-fixnum positive-fixnum))
233 ((:arg dividend any-reg nl0-offset)
234 (:arg divisor any-reg nl1-offset)
236 (:res quo any-reg nl2-offset)
237 (:res rem any-reg nl3-offset))
238 (let ((error (generate-error-code nil division-by-zero-error
240 (inst beq divisor error)
243 (inst divu dividend divisor)
249 (define-assembly-routine (fixnum-truncate
250 (:note "fixnum truncate")
253 (:translate truncate)
254 (:arg-types tagged-num tagged-num)
255 (:result-types tagged-num tagged-num))
256 ((:arg dividend any-reg nl0-offset)
257 (:arg divisor any-reg nl1-offset)
259 (:res quo any-reg nl2-offset)
260 (:res rem any-reg nl3-offset))
261 (let ((error (generate-error-code nil division-by-zero-error
263 (inst beq divisor error)
266 (inst div dividend divisor)
272 (define-assembly-routine (signed-truncate
273 (:note "(signed-byte 32) truncate")
276 (:translate truncate)
277 (:arg-types signed-num signed-num)
278 (:result-types signed-num signed-num))
280 ((:arg dividend signed-reg nl0-offset)
281 (:arg divisor signed-reg nl1-offset)
283 (:res quo signed-reg nl2-offset)
284 (:res rem signed-reg nl3-offset))
285 (let ((error (generate-error-code nil division-by-zero-error
287 (inst beq divisor error)
290 (inst div dividend divisor)
296 ;;;; Comparison routines.
299 ((define-cond-assem-rtn (name translate static-fn cmp not-p)
300 `(define-assembly-routine (,name
302 (:return-style :full-call)
304 (:translate ,translate)
306 ((:arg x (descriptor-reg any-reg) a0-offset)
307 (:arg y (descriptor-reg any-reg) a1-offset)
309 (:res res descriptor-reg a0-offset)
311 (:temp temp non-descriptor-reg nl0-offset)
312 (:temp lra descriptor-reg lra-offset)
313 (:temp lip interior-reg lip-offset)
314 (:temp nargs any-reg nargs-offset)
315 (:temp ocfp any-reg ocfp-offset))
317 (inst and temp fixnum-tag-mask)
318 (inst bne temp DO-STATIC-FUN)
321 (inst ,(if not-p 'beq 'bne) temp DONE)
326 (lisp-return lra lip :offset 2)
329 (inst lw lip null-tn (static-fun-offset ',static-fn))
330 (inst li nargs (fixnumize 2))
333 (move cfp-tn csp-tn t))))
335 (define-cond-assem-rtn generic-< < two-arg-< (inst slt temp x y) t)
336 (define-cond-assem-rtn generic-<= <= two-arg-<= (inst slt temp x y) nil)
337 (define-cond-assem-rtn generic-> > two-arg-> (inst slt temp y x) t)
338 (define-cond-assem-rtn generic->= >= two-arg->= (inst slt temp y x) nil))
341 (define-assembly-routine (generic-eql
343 (:return-style :full-call)
347 ((:arg x (descriptor-reg any-reg) a0-offset)
348 (:arg y (descriptor-reg any-reg) a1-offset)
350 (:res res descriptor-reg a0-offset)
352 (:temp temp non-descriptor-reg nl0-offset)
353 (:temp lra descriptor-reg lra-offset)
354 (:temp lip interior-reg lip-offset)
355 (:temp nargs any-reg nargs-offset)
356 (:temp ocfp any-reg ocfp-offset))
357 (inst beq x y RETURN-T)
359 (inst and temp fixnum-tag-mask)
360 (inst bne temp DO-STATIC-FUN)
370 (lisp-return lra lip :offset 2)
373 (inst lw lip null-tn (static-fun-offset 'eql))
374 (inst li nargs (fixnumize 2))
377 (move cfp-tn csp-tn t))
380 (define-assembly-routine (generic-=
382 (:return-style :full-call)
386 ((:arg x (descriptor-reg any-reg) a0-offset)
387 (:arg y (descriptor-reg any-reg) a1-offset)
389 (:res res descriptor-reg a0-offset)
391 (:temp temp non-descriptor-reg nl0-offset)
392 (:temp lra descriptor-reg lra-offset)
393 (:temp lip interior-reg lip-offset)
394 (:temp nargs any-reg nargs-offset)
395 (:temp ocfp any-reg ocfp-offset))
397 (inst and temp fixnum-tag-mask)
398 (inst bne temp DO-STATIC-FUN)
406 (lisp-return lra lip :offset 2)
409 (inst lw lip null-tn (static-fun-offset 'two-arg-=))
410 (inst li nargs (fixnumize 2))
413 (move cfp-tn csp-tn t))
416 (define-assembly-routine (generic-/=
418 (:return-style :full-call)
422 ((:arg x (descriptor-reg any-reg) a0-offset)
423 (:arg y (descriptor-reg any-reg) a1-offset)
425 (:res res descriptor-reg a0-offset)
427 (:temp temp non-descriptor-reg nl0-offset)
428 (:temp lra descriptor-reg lra-offset)
429 (:temp lip interior-reg lip-offset)
430 (:temp nargs any-reg nargs-offset)
431 (:temp ocfp any-reg ocfp-offset))
433 (inst and temp fixnum-tag-mask)
434 (inst bne temp DO-STATIC-FUN)
442 (lisp-return lra lip :offset 2)
445 (inst lw lip null-tn (static-fun-offset 'two-arg-/=))
446 (inst li nargs (fixnumize 2))
449 (move cfp-tn csp-tn t))