1 ;;;; 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.
14 ;;;; addition, subtraction, and multiplication
16 (macrolet ((define-generic-arith-routine ((fun cost) &body body)
17 `(define-assembly-routine (,(symbolicate "GENERIC-" fun)
19 (:return-style :full-call)
23 ((:arg x (descriptor-reg any-reg) rdx-offset)
24 (:arg y (descriptor-reg any-reg)
25 ;; this seems wrong esi-offset -- FIXME: What's it mean?
28 (:res res (descriptor-reg any-reg) rdx-offset)
30 (:temp rax unsigned-reg rax-offset)
31 (:temp rbx unsigned-reg rbx-offset)
32 (:temp rcx unsigned-reg rcx-offset))
34 (declare (ignorable rbx))
36 (inst test x 7) ; fixnum?
37 (inst jmp :nz DO-STATIC-FUN) ; no - do generic
38 (inst test y 7) ; fixnum?
39 (inst jmp :z DO-BODY) ; yes - doit here
46 (make-ea :qword :base rsp-tn :disp n-word-bytes))
47 (inst sub rsp-tn (fixnumize 2))
48 (inst push rax) ; callers return addr
49 (inst mov rcx (fixnumize 2)) ; arg count
54 ',(symbolicate "TWO-ARG-" fun)))))
59 (define-generic-arith-routine (+ 10)
63 (inst rcr res 1) ; carry has correct sign
64 (inst sar res 2) ; remove type bits
68 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
69 (storew rcx res bignum-digits-offset other-pointer-lowtag))
73 (define-generic-arith-routine (- 10)
77 (inst cmc) ; carry has correct sign now
79 (inst sar res 2) ; remove type bits
83 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
84 (storew rcx res bignum-digits-offset other-pointer-lowtag))
87 (define-generic-arith-routine (* 30)
88 (move rax x) ; must use eax for 64-bit result
89 (inst sar rax 3) ; remove *4 fixnum bias
90 (inst imul y) ; result in edx:eax
91 (inst jmp :no OKAY) ; still fixnum
93 ;; zzz jrd changed edx to ebx in here, as edx isn't listed as a temp, above
94 ;; pfw says that loses big -- edx is target for arg x and result res
95 ;; note that 'edx' is not defined -- using x
96 (inst shrd rax x 3) ; high bits from edx
97 (inst sar x 3) ; now shift edx too
99 (move rcx x) ; save high bits from cqo
100 (inst cqo) ; edx:eax <- sign-extend of eax
102 (inst jmp :e SINGLE-WORD-BIGNUM)
104 (with-fixed-allocation (res bignum-widetag (+ bignum-digits-offset 2))
105 (storew rax res bignum-digits-offset other-pointer-lowtag)
106 (storew rcx res (1+ bignum-digits-offset) other-pointer-lowtag))
111 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
112 (storew rax res bignum-digits-offset other-pointer-lowtag))
121 (define-assembly-routine (generic-negate
123 (:return-style :full-call)
127 ((:arg x (descriptor-reg any-reg) rdx-offset)
128 (:res res (descriptor-reg any-reg) rdx-offset)
130 (:temp rax unsigned-reg rax-offset)
131 (:temp rcx unsigned-reg rcx-offset))
137 (inst lea rbp-tn (make-ea :qword :base rsp-tn :disp n-word-bytes))
138 (inst sub rsp-tn (fixnumize 2))
140 (inst mov rcx (fixnumize 1)) ; arg count
141 (inst jmp (make-ea :qword
142 :disp (+ nil-value (static-fun-offset '%negate))))
146 (inst neg res) ; (- most-negative-fixnum) is BIGNUM
148 (inst shr res 3) ; sign bit is data - remove type bits
151 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
152 (storew rcx res bignum-digits-offset other-pointer-lowtag))
158 (macrolet ((define-cond-assem-rtn (name translate static-fn test)
159 `(define-assembly-routine (,name
161 (:return-style :full-call)
163 (:translate ,translate)
165 ((:arg x (descriptor-reg any-reg) rdx-offset)
166 (:arg y (descriptor-reg any-reg) rdi-offset)
168 (:res res descriptor-reg rdx-offset)
170 (:temp eax unsigned-reg rax-offset)
171 (:temp ecx unsigned-reg rcx-offset))
173 ;; KLUDGE: The "3" here is a mask for the bits which will be
174 ;; zero in a fixnum. It should have a symbolic name. (Actually,
175 ;; it might already have a symbolic name which the coder
176 ;; couldn't be bothered to use..) -- WHN 19990917
178 (inst jmp :nz TAIL-CALL-TO-STATIC-FN)
180 (inst jmp :z INLINE-FIXNUM-COMPARE)
182 TAIL-CALL-TO-STATIC-FN
185 (inst lea rbp-tn (make-ea :qword
188 (inst sub rsp-tn (fixnumize 2)) ; FIXME: Push 2 words on stack,
191 (inst mov ecx (fixnumize 2)) ; FIXME: FIXNUMIZE and
192 ; SINGLE-FLOAT-BITS are parallel,
193 ; should be named parallelly.
194 (inst jmp (make-ea :qword
196 (static-fun-offset ',static-fn))))
198 INLINE-FIXNUM-COMPARE
200 (inst mov res nil-value)
201 (inst jmp ,test RETURN-FALSE)
207 (define-cond-assem-rtn generic-< < two-arg-< :ge)
208 (define-cond-assem-rtn generic-> > two-arg-> :le))
210 (define-assembly-routine (generic-eql
212 (:return-style :full-call)
216 ((:arg x (descriptor-reg any-reg) rdx-offset)
217 (:arg y (descriptor-reg any-reg) rdi-offset)
219 (:res res descriptor-reg rdx-offset)
221 (:temp eax unsigned-reg rax-offset)
222 (:temp ecx unsigned-reg rcx-offset))
224 (inst jmp :e RETURN-T)
226 (inst jmp :z RETURN-NIL)
228 (inst jmp :nz DO-STATIC-FN)
231 (inst mov res nil-value)
237 (inst lea rbp-tn (make-ea :qword :base rsp-tn :disp n-word-bytes))
238 (inst sub rsp-tn (fixnumize 2))
240 (inst mov ecx (fixnumize 2))
241 (inst jmp (make-ea :qword
242 :disp (+ nil-value (static-fun-offset 'eql))))
248 (define-assembly-routine (generic-=
250 (:return-style :full-call)
254 ((:arg x (descriptor-reg any-reg) rdx-offset)
255 (:arg y (descriptor-reg any-reg) rdi-offset)
257 (:res res descriptor-reg rdx-offset)
259 (:temp eax unsigned-reg rax-offset)
260 (:temp ecx unsigned-reg rcx-offset)
262 (inst test x 7) ; descriptor?
263 (inst jmp :nz DO-STATIC-FN) ; yes, do it here
264 (inst test y 7) ; descriptor?
265 (inst jmp :nz DO-STATIC-FN)
267 (inst jmp :e RETURN-T) ; ok
269 (inst mov res nil-value)
275 (inst lea rbp-tn (make-ea :qword :base rsp-tn :disp n-word-bytes))
276 (inst sub rsp-tn (fixnumize 2))
278 (inst mov ecx (fixnumize 2))
279 (inst jmp (make-ea :qword
280 :disp (+ nil-value (static-fun-offset 'two-arg-=))))