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) edx-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) edx-offset)
30 (:temp eax unsigned-reg eax-offset)
31 (:temp ecx unsigned-reg ecx-offset))
35 (inst test ecx 3) ; both fixnums?
36 (inst jmp :nz DO-STATIC-FUN) ; no - do generic
39 (inst clc) ; single-value return
47 (make-ea :dword :base esp-tn :disp n-word-bytes))
48 (inst sub esp-tn (fixnumize 2))
49 (inst push eax) ; callers return addr
50 (inst mov ecx (fixnumize 2)) ; arg count
55 ',(symbolicate "TWO-ARG-" fun))))))))
57 (define-generic-arith-routine (+ 10)
61 (inst rcr res 1) ; carry has correct sign
62 (inst sar res 1) ; remove type bits
66 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
67 (storew ecx res bignum-digits-offset other-pointer-lowtag))
71 (define-generic-arith-routine (- 10)
75 (inst cmc) ; carry has correct sign now
77 (inst sar res 1) ; remove type bits
81 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
82 (storew ecx res bignum-digits-offset other-pointer-lowtag))
85 (define-generic-arith-routine (* 30)
86 (move eax x) ; must use eax for 64-bit result
87 (inst sar eax 2) ; remove *4 fixnum bias
88 (inst imul y) ; result in edx:eax
89 (inst jmp :no okay) ; still fixnum
91 ;; zzz jrd changed edx to ebx in here, as edx isn't listed as a temp, above
92 ;; pfw says that loses big -- edx is target for arg x and result res
93 ;; note that 'edx' is not defined -- using x
94 (inst shrd eax x 2) ; high bits from edx
95 (inst sar x 2) ; now shift edx too
97 (move ecx x) ; save high bits from cdq
98 (inst cdq) ; edx:eax <- sign-extend of eax
100 (inst jmp :e SINGLE-WORD-BIGNUM)
102 (with-fixed-allocation (res bignum-widetag (+ bignum-digits-offset 2))
103 (storew eax res bignum-digits-offset other-pointer-lowtag)
104 (storew ecx res (1+ bignum-digits-offset) other-pointer-lowtag))
109 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
110 (storew eax res bignum-digits-offset other-pointer-lowtag))
119 (define-assembly-routine (generic-negate
121 (:return-style :full-call)
125 ((:arg x (descriptor-reg any-reg) edx-offset)
126 (:res res (descriptor-reg any-reg) edx-offset)
128 (:temp eax unsigned-reg eax-offset)
129 (:temp ecx unsigned-reg ecx-offset))
135 (inst lea ebp-tn (make-ea :dword :base esp-tn :disp n-word-bytes))
136 (inst sub esp-tn (fixnumize 2))
138 (inst mov ecx (fixnumize 1)) ; arg count
139 (inst jmp (make-ea :dword
140 :disp (+ nil-value (static-fun-offset '%negate))))
144 (inst neg res) ; (- most-negative-fixnum) is BIGNUM
146 (inst shr res 2) ; sign bit is data - remove type bits
149 (with-fixed-allocation (res bignum-widetag (1+ bignum-digits-offset))
150 (storew ecx res bignum-digits-offset other-pointer-lowtag))
156 (macrolet ((define-cond-assem-rtn (name translate static-fn test)
157 `(define-assembly-routine (,name
159 (:return-style :full-call)
161 (:translate ,translate)
163 ((:arg x (descriptor-reg any-reg) edx-offset)
164 (:arg y (descriptor-reg any-reg) edi-offset)
166 (:res res descriptor-reg edx-offset)
168 (:temp eax unsigned-reg eax-offset)
169 (:temp ecx unsigned-reg ecx-offset))
171 ;; KLUDGE: The "3" here is a mask for the bits which will be
172 ;; zero in a fixnum. It should have a symbolic name. (Actually,
173 ;; it might already have a symbolic name which the coder
174 ;; couldn't be bothered to use..) -- WHN 19990917
176 (inst jmp :nz TAIL-CALL-TO-STATIC-FN)
178 (inst jmp :z INLINE-FIXNUM-COMPARE)
180 TAIL-CALL-TO-STATIC-FN
183 (inst lea ebp-tn (make-ea :dword
186 (inst sub esp-tn (fixnumize 2)) ; FIXME: Push 2 words on stack,
189 (inst mov ecx (fixnumize 2)) ; FIXME: FIXNUMIZE and
190 ; SINGLE-FLOAT-BITS are parallel,
191 ; should be named parallelly.
192 (inst jmp (make-ea :dword
194 (static-fun-offset ',static-fn))))
196 INLINE-FIXNUM-COMPARE
198 (inst mov res nil-value)
199 (inst jmp ,test RETURN-FALSE)
206 (define-cond-assem-rtn generic-< < two-arg-< :ge)
207 (define-cond-assem-rtn generic-> > two-arg-> :le))
209 (define-assembly-routine (generic-eql
211 (:return-style :full-call)
215 ((:arg x (descriptor-reg any-reg) edx-offset)
216 (:arg y (descriptor-reg any-reg) edi-offset)
218 (:res res descriptor-reg edx-offset)
220 (:temp eax unsigned-reg eax-offset)
221 (:temp ecx unsigned-reg ecx-offset))
223 (inst jmp :e RETURN-T)
225 (inst jmp :z RETURN-NIL)
227 (inst jmp :nz DO-STATIC-FN)
230 (inst mov res nil-value)
236 (inst lea ebp-tn (make-ea :dword :base esp-tn :disp n-word-bytes))
237 (inst sub esp-tn (fixnumize 2))
239 (inst mov ecx (fixnumize 2))
240 (inst jmp (make-ea :dword
241 :disp (+ nil-value (static-fun-offset 'eql))))
248 (define-assembly-routine (generic-=
250 (:return-style :full-call)
254 ((:arg x (descriptor-reg any-reg) edx-offset)
255 (:arg y (descriptor-reg any-reg) edi-offset)
257 (:res res descriptor-reg edx-offset)
259 (:temp eax unsigned-reg eax-offset)
260 (:temp ecx unsigned-reg ecx-offset)
262 (inst test x 3) ; descriptor?
263 (inst jmp :nz DO-STATIC-FN) ; yes, do it here
264 (inst test y 3) ; descriptor?
265 (inst jmp :nz DO-STATIC-FN)
267 (inst jmp :e RETURN-T) ; ok
269 (inst mov res nil-value)
275 (inst lea ebp-tn (make-ea :dword :base esp-tn :disp n-word-bytes))
276 (inst sub esp-tn (fixnumize 2))
278 (inst mov ecx (fixnumize 2))
279 (inst jmp (make-ea :dword
280 :disp (+ nil-value (static-fun-offset 'two-arg-=))))
288 ;;; Support for the Mersenne Twister, MT19937, random number generator
289 ;;; due to Matsumoto and Nishimura.
291 ;;; Makoto Matsumoto and T. Nishimura, "Mersenne twister: A
292 ;;; 623-dimensionally equidistributed uniform pseudorandom number
293 ;;; generator.", ACM Transactions on Modeling and Computer Simulation,
297 ;;; 0-1: Constant matrix A. [0, #x9908b0df] (not used here)
298 ;;; 2: Index; init. to 1.
301 ;;; This assembly routine is called from the inline VOP and updates
302 ;;; the state vector with new random numbers. The state vector is
303 ;;; passed in the EAX register.
304 #+sb-assembling ; We don't want a vop for this one.
305 (define-assembly-routine
306 (random-mt19937-update)
307 ((:temp state unsigned-reg eax-offset)
308 (:temp k unsigned-reg ebx-offset)
309 (:temp y unsigned-reg ecx-offset)
310 (:temp tmp unsigned-reg edx-offset))
312 ;; Save the temporary registers.
317 ;; Generate a new set of results.
320 (inst mov y (make-ea-for-vector-data state :index k :offset 3))
321 (inst mov tmp (make-ea-for-vector-data state :index k :offset (+ 1 3)))
322 (inst and y #x80000000)
323 (inst and tmp #x7fffffff)
327 (inst xor y #x9908b0df)
329 (inst xor y (make-ea-for-vector-data state :index k :offset (+ 397 3)))
330 (inst mov (make-ea-for-vector-data state :index k :offset 3) y)
332 (inst cmp k (- 624 397))
335 (inst mov y (make-ea-for-vector-data state :index k :offset 3))
336 (inst mov tmp (make-ea-for-vector-data state :index k :offset (+ 1 3)))
337 (inst and y #x80000000)
338 (inst and tmp #x7fffffff)
342 (inst xor y #x9908b0df)
344 (inst xor y (make-ea-for-vector-data state :index k :offset (+ (- 397 624) 3)))
345 (inst mov (make-ea-for-vector-data state :index k :offset 3) y)
347 (inst cmp k (- 624 1))
350 (inst mov y (make-ea-for-vector-data state :offset (+ (- 624 1) 3)))
351 (inst mov tmp (make-ea-for-vector-data state :offset (+ 0 3)))
352 (inst and y #x80000000)
353 (inst and tmp #x7fffffff)
357 (inst xor y #x9908b0df)
359 (inst xor y (make-ea-for-vector-data state :offset (+ (- 397 1) 3)))
360 (inst mov (make-ea-for-vector-data state :offset (+ (- 624 1) 3)) y)
362 ;; Restore the temporary registers and return.