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-no-return
)
23 ((:arg x
(descriptor-reg any-reg
) edx-offset
)
24 (:arg y
(descriptor-reg any-reg
) edi-offset
)
26 (:res res
(descriptor-reg any-reg
) edx-offset
)
29 '((:temp eax unsigned-reg eax-offset
)))
30 (:temp ecx unsigned-reg ecx-offset
))
32 ,@(multiple-value-bind (reg byte
)
33 (if (eq fun
'*) (values 'eax
'al-tn
) (values 'ecx
'cl-tn
))
36 (inst test
,byte fixnum-tag-mask
))) ; both fixnums?
38 (inst jmp
:nz DO-STATIC-FUN
) ; no - do generic
41 (inst clc
) ; single-value return
45 ;; Same as: (inst enter (fixnumize 1))
47 (inst mov ebp-tn esp-tn
)
48 (inst sub esp-tn
(fixnumize 1))
49 (inst push
(make-ea :dword
:base ebp-tn
50 :disp
(frame-byte-offset return-pc-save-offset
)))
51 (inst mov ecx
(fixnumize 2)) ; arg count
56 ',(symbolicate "TWO-ARG-" fun
))))))))
58 (define-generic-arith-routine (+ 10)
62 (inst rcr res
1) ; carry has correct sign
63 (inst sar res
1) ; remove type bits
67 (alloc-other res bignum-widetag
(1+ bignum-digits-offset
) nil
)
68 (storew ecx res bignum-digits-offset other-pointer-lowtag
)
72 (define-generic-arith-routine (- 10)
76 (inst cmc
) ; carry has correct sign now
78 (inst sar res
1) ; remove type bits
82 (alloc-other res bignum-widetag
(1+ bignum-digits-offset
) nil
)
83 (storew ecx res bignum-digits-offset other-pointer-lowtag
)
86 (define-generic-arith-routine (* 30)
87 (move eax x
) ; must use eax for 64-bit result
88 (inst sar eax n-fixnum-tag-bits
) ; remove *4 fixnum bias
89 (inst imul y
) ; result in edx:eax
90 (inst jmp
:no OKAY
) ; still fixnum
92 ;; zzz jrd changed edx to ebx in here, as edx isn't listed as a temp, above
93 ;; pfw says that loses big -- edx is target for arg x and result res
94 ;; note that 'edx' is not defined -- using x
95 (inst shrd eax x n-fixnum-tag-bits
) ; high bits from edx
96 (inst sar x n-fixnum-tag-bits
) ; now shift edx too
98 (move ecx x
) ; save high bits from cdq
99 (inst cdq
) ; edx:eax <- sign-extend of eax
101 (inst jmp
:e SINGLE-WORD-BIGNUM
)
103 (alloc-other res bignum-widetag
(+ bignum-digits-offset
2) nil
)
104 (storew eax res bignum-digits-offset other-pointer-lowtag
)
105 (storew ecx res
(1+ bignum-digits-offset
) other-pointer-lowtag
)
110 (alloc-other res bignum-widetag
(1+ bignum-digits-offset
) nil
)
111 (storew eax res bignum-digits-offset other-pointer-lowtag
)
120 (define-assembly-routine (generic-negate
122 (:return-style
:full-call
)
126 ((:arg x
(descriptor-reg any-reg
) edx-offset
)
127 (:res res
(descriptor-reg any-reg
) edx-offset
)
128 (:temp ecx unsigned-reg ecx-offset
))
129 (inst test x fixnum-tag-mask
)
133 (inst mov ebp-tn esp-tn
)
134 (inst sub esp-tn
(fixnumize 1))
135 (inst push
(make-ea :dword
:base ebp-tn
136 :disp
(frame-byte-offset return-pc-save-offset
)))
137 (inst mov ecx
(fixnumize 1)) ; arg count
138 (inst jmp
(make-ea :dword
139 :disp
(+ nil-value
(static-fun-offset '%negate
))))
143 (inst neg res
) ; (- most-negative-fixnum) is BIGNUM
145 (inst shr res n-fixnum-tag-bits
) ; sign bit is data - remove type bits
148 (alloc-other res bignum-widetag
(1+ bignum-digits-offset
) nil
)
149 (storew ecx res bignum-digits-offset other-pointer-lowtag
)
155 (macrolet ((define-cond-assem-rtn (name translate static-fn test
)
156 `(define-assembly-routine (,name
157 (:translate
,translate
)
162 ((:arg x
(descriptor-reg any-reg
) edx-offset
)
163 (:arg y
(descriptor-reg any-reg
) edi-offset
)
165 (:temp ecx unsigned-reg ecx-offset
))
169 (inst test ecx fixnum-tag-mask
)
170 (inst jmp
:nz DO-STATIC-FUN
) ; are both fixnums?
177 (inst mov ebp-tn esp-tn
)
178 (inst sub esp-tn
(fixnumize 3))
179 (inst mov
(make-ea :dword
:base esp-tn
180 :disp
(frame-byte-offset
185 (inst lea ebp-tn
(make-ea :dword
:base esp-tn
186 :disp
(frame-byte-offset
190 (inst mov ecx
(fixnumize 2))
191 (inst call
(make-ea :dword
193 (static-fun-offset ',static-fn
))))
194 ;; HACK: We depend on NIL having the lowest address of all
195 ;; static symbols (including T)
197 (:l
`((inst mov y
(1+ nil-value
))
199 (:g
`((inst cmp x
(1+ nil-value
)))))
201 (define-cond-assem-rtn generic-
< < two-arg-
< :l
)
202 (define-cond-assem-rtn generic-
> > two-arg-
> :g
))
204 (define-assembly-routine (generic-eql
210 ((:arg x
(descriptor-reg any-reg
) edx-offset
)
211 (:arg y
(descriptor-reg any-reg
) edi-offset
)
213 (:temp ecx unsigned-reg ecx-offset
))
216 (inst and ecx lowtag-mask
)
217 (inst cmp ecx other-pointer-lowtag
)
218 (inst jmp
:e DO-STATIC-FUN
)
220 ;; At least one fixnum
226 ;; Might as well fast path that...
231 (inst mov ebp-tn esp-tn
)
232 (inst sub esp-tn
(fixnumize 3))
233 (inst mov
(make-ea :dword
:base esp-tn
234 :disp
(frame-byte-offset
239 (inst lea ebp-tn
(make-ea :dword
:base esp-tn
240 :disp
(frame-byte-offset
244 (inst mov ecx
(fixnumize 2))
245 (inst call
(make-ea :dword
246 :disp
(+ nil-value
(static-fun-offset 'eql
))))
251 (define-assembly-routine (generic-=
257 ((:arg x
(descriptor-reg any-reg
) edx-offset
)
258 (:arg y
(descriptor-reg any-reg
) edi-offset
)
260 (:temp ecx unsigned-reg ecx-offset
))
263 (inst test ecx fixnum-tag-mask
)
264 (inst jmp
:nz DO-STATIC-FUN
)
272 (inst mov ebp-tn esp-tn
)
273 (inst sub esp-tn
(fixnumize 3))
274 (inst mov
(make-ea :dword
:base esp-tn
275 :disp
(frame-byte-offset
280 (inst lea ebp-tn
(make-ea :dword
:base esp-tn
281 :disp
(frame-byte-offset
285 (inst mov ecx
(fixnumize 2))
286 (inst call
(make-ea :dword
287 :disp
(+ nil-value
(static-fun-offset 'two-arg-
=))))
293 ;;; Support for the Mersenne Twister, MT19937, random number generator
294 ;;; due to Matsumoto and Nishimura.
296 ;;; Makoto Matsumoto and T. Nishimura, "Mersenne twister: A
297 ;;; 623-dimensionally equidistributed uniform pseudorandom number
298 ;;; generator.", ACM Transactions on Modeling and Computer Simulation,
302 ;;; 0-1: Constant matrix A. [0, #x9908b0df] (not used here)
303 ;;; 2: Index; init. to 1.
306 ;;; This assembly routine is called from the inline VOP and updates
307 ;;; the state vector with new random numbers. The state vector is
308 ;;; passed in the EAX register.
309 #+sb-assembling
; We don't want a vop for this one.
310 (define-assembly-routine
311 (random-mt19937-update)
312 ((:temp state unsigned-reg eax-offset
)
313 (:temp k unsigned-reg ebx-offset
)
314 (:temp y unsigned-reg ecx-offset
)
315 (:temp tmp unsigned-reg edx-offset
))
317 ;; Save the temporary registers.
322 ;; Generate a new set of results.
325 (inst mov y
(make-ea-for-vector-data state
:index k
:offset
3))
326 (inst mov tmp
(make-ea-for-vector-data state
:index k
:offset
(+ 1 3)))
327 (inst and y
#x80000000
)
328 (inst and tmp
#x7fffffff
)
332 (inst xor y
#x9908b0df
)
334 (inst xor y
(make-ea-for-vector-data state
:index k
:offset
(+ 397 3)))
335 (inst mov
(make-ea-for-vector-data state
:index k
:offset
3) y
)
337 (inst cmp k
(- 624 397))
340 (inst mov y
(make-ea-for-vector-data state
:index k
:offset
3))
341 (inst mov tmp
(make-ea-for-vector-data state
:index k
:offset
(+ 1 3)))
342 (inst and y
#x80000000
)
343 (inst and tmp
#x7fffffff
)
347 (inst xor y
#x9908b0df
)
349 (inst xor y
(make-ea-for-vector-data state
:index k
:offset
(+ (- 397 624) 3)))
350 (inst mov
(make-ea-for-vector-data state
:index k
:offset
3) y
)
352 (inst cmp k
(- 624 1))
355 (inst mov y
(make-ea-for-vector-data state
:offset
(+ (- 624 1) 3)))
356 (inst mov tmp
(make-ea-for-vector-data state
:offset
(+ 0 3)))
357 (inst and y
#x80000000
)
358 (inst and tmp
#x7fffffff
)
362 (inst xor y
#x9908b0df
)
364 (inst xor y
(make-ea-for-vector-data state
:offset
(+ (- 397 1) 3)))
365 (inst mov
(make-ea-for-vector-data state
:offset
(+ (- 624 1) 3)) y
)
367 ;; Restore the temporary registers and return.