source: branches/ia32/level-0/X86/X8632/x8632-bignum.lisp @ 7987

Last change on this file since 7987 was 7987, checked in by rme, 13 years ago

Try to set up for .SPvalues correctly.

File size: 23.5 KB
Line 
1(in-package "CCL")
2
3;;; %BIGNUM-REF needs to access bignums as obviously as possible, and it needs
4;;; to be able to return 32 bits somewhere no one looks for real objects.
5;;;
6;;; The easiest thing to do is to store the 32 raw bits in two fixnums
7;;; and return multiple values.
8;;;
9(defx8632lapfunction %bignum-ref ((bignum arg_y) (i arg_z))
10  (movl (% esp) (% temp0))              ;.SPvalues wants return addr in temp0
11  (movzwl (@ (+ 2 x8632::misc-data-offset) (% bignum) (% i)) (% imm0))
12  (box-fixnum imm0 temp1)
13  (push (% temp1))                      ;high
14  (movzwl (@ x8632::misc-data-offset (% bignum) (% i)) (% imm0))
15  (box-fixnum imm0 temp1)
16  (push (% temp1))                      ;low
17  (set-nargs 2)
18  (jmp-subprim .SPvalues))
19
20;;; BIGNUM[I] := DIGIT[0]
21(defx8632lapfunction %set-digit ((bignum 4) #|(ra 0)|# (i arg_y) (digit arg_z))
22  (movl (@ bignum (% esp)) (% temp0))
23  (svref digit 0 imm0)
24  (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% i)))
25  (single-value-return 3))
26
27;;; Return the sign of bignum (0 or -1) as a fixnum
28(defx8632lapfunction %bignum-sign ((bignum arg_z))
29  (vector-length bignum imm0)
30  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
31  (sarl ($ 31) (% imm0))                ;propagate sign bit
32  (box-fixnum imm0 arg_z)
33  (single-value-return))
34
35;;; Count the sign bits in the most significant digit of bignum;
36;;; return fixnum count.
37(defx8632lapfunction %bignum-sign-bits ((bignum arg_z))
38  (vector-length bignum imm0)
39  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
40  (mark-as-imm temp0)
41  (movl (% imm0) (% temp0))
42  (notl (% imm0))
43  (testl (% temp0) (% temp0))
44  (js @wasneg)
45  (notl (% imm0))
46  @wasneg
47  (bsrl (% imm0) (% imm0))
48  (sete (% temp0.b))
49  (xorl ($ 31) (% imm0))
50  (addb (% temp0.b) (% imm0.b))
51  (box-fixnum imm0 arg_z)
52  (mark-as-node temp0)
53  (single-value-return))
54
55(defx8632lapfunction %digit-0-or-plusp ((bignum arg_y) (idx arg_z))
56  (movl (@ x8632::misc-data-offset (% bignum) (% idx)) (% imm0))
57  (movl ($ x8632::nil-value) (% temp0))
58  (leal (@ x8632::t-offset (% temp0)) (% arg_z))
59  (testl (% imm0) (% imm0))
60  (cmovll (% temp0) (% arg_z))
61  (single-value-return))
62
63;;; For oddp, evenp
64(defx8632lapfunction %bignum-oddp ((bignum arg_z))
65  (movl (@ x8632::misc-data-offset (% bignum)) (% imm0))
66  (movl ($ x8632::nil-value) (% temp0))
67  (leal (@ x8632::t-offset (% temp0)) (% arg_z))
68  (testb ($ 1) (% imm0.b))
69  (cmovzl (% temp0) (% arg_z))
70  (single-value-return))
71
72(defx8632lapfunction bignum-plusp ((bignum arg_z))
73  (vector-length bignum imm0)
74  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
75  (movl ($ x8632::nil-value) (% temp0))
76  (lea (@ x8632::t-offset (% temp0)) (% arg_z))
77  (testl (% imm0) (% imm0))
78  (cmovlel (% temp0) (% arg_z))
79  (single-value-return))
80
81(defx8632lapfunction bignum-minusp ((bignum arg_z))
82  (vector-length bignum imm0)
83  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
84  (movl ($ x8632::nil-value) (% temp0))
85  (lea (@ x8632::t-offset (% temp0)) (% arg_z))
86  (testl (% imm0) (% imm0))
87  (cmovgl (% temp0) (% arg_z))
88  (single-value-return))
89
90;;; Add the digits A[I] and B[J], and the incoming carry C (a fixnum,
91;;; either 0 or 1).  Store the result in R[K], and return the outgoing
92;;; carry.  If I is NIL, A is a fixnum.  If J is NIL, B is a fixnum.
93(defx8632lapfunction %add-with-carry ((r 20) (k 16) (c 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
94  (mark-as-imm temp0)
95  (unbox-fixnum b imm0)
96  (cmpl ($ x8632::nil-value) (% j))
97  ;; if j not nil, get b[j]
98  (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
99  (movl (@ a (% esp)) (% arg_y))
100  (unbox-fixnum arg_y temp0)
101  (movl (@ i (% esp)) (% arg_z))
102  (cmpl ($ x8632::nil-value) (% arg_z))
103  ;; if i not nil, get a[i]
104  (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% temp0))
105  (movl ($ '1) (% arg_z))               ;for outgoing carry
106  (xorl (% arg_y) (% arg_y))
107  ;; I can't think of a better way to set CF at the moment.
108  ;; NEG would be ideal, but we don't have a free imm reg.
109  (btl ($ x8632::fixnumshift) (@ c (% esp))) ;CF = lsb of carry fixnum
110  (adc (% temp0) (% imm0))
111  (mark-as-node temp0)
112  (movl (@ r (% esp)) (% temp0))
113  (movl (@ k (% esp)) (% temp1))
114  (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
115  (cmovnc (% arg_y) (% arg_z))          ;zero outgoing carry if CF = 0
116  (single-value-return 7))
117
118;;; Add the digits A[I] and B[J], and the incoming carry C (a fixnum).
119;;; Store the result in R[K], and return the outgoing carry.  If I is
120;;; NIL, A is a fixnum.  If J is NIL, B is a fixnum.
121#+sse2
122(defx8632lapfunction %add-with-carry ((r 20) (k 16) (c 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
123  (let ((aa mm2)
124        (bb mm3)
125        (cc mm4))
126    (unbox-fixnum b imm0)               ;assume j will be nil
127    (cmpl ($ x8632::nil-value) (% j))
128    ;; if j not nil, get b[j]
129    (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
130    (movd (% imm0) (% bb))
131    (movl (@ a (% esp)) (% arg_y))
132    (movl (@ i (% esp)) (% arg_z))
133    (movl (@ c (% esp)) (% temp0))
134    (unbox-fixnum arg_y imm0)           ;assume i will be nil
135    (cmpl ($ x8632::nil-value) (% arg_z))
136    ;; if i not nil, get a[i]
137    (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% imm0))
138    (movd (% imm0) (% aa))
139    (unbox-fixnum temp0 imm0)
140    (movd (% imm0) (% cc))
141    (paddq (% xx) (% yy))
142    (paddq (% cc) (% yy))
143    (movl (@ r (% esp)) (% temp0))
144    (movl (@ k (% esp)) (% temp1))
145    (movd (% yy) (@ x8632::misc-data-offset (% temp0) (% temp1)))
146    (psrlq ($ 32) (% yy))               ;carry bit
147    (movd (% yy) (% imm0))
148    (box-fixnum imm0 arg_z)
149    (single-value-return 7)))
150
151;;; Store the result of A[I] - B[J] - borrow into R[K], returning the borrow.
152;;; If I is NIL, A is a fixnum; likewise for J and B.
153;;;
154;;; (a - b) - (1 - borrow), or equivalently, (a - b) + borrow - 1
155;;;
156;;; Note: borrow is 1 for no borrow and 0 for a borrow.
157(defx8632lapfunction %subtract-with-borrow ((r 20) (k 16) (borrow 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
158  (mark-as-imm temp0)
159  (unbox-fixnum b imm0)
160  (cmpl ($ x8632::nil-value) (% j))
161  (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
162  (movl (@ a (% esp)) (% arg_y))
163  (unbox-fixnum arg_y temp0)
164  (movl (@ i (% esp)) (% arg_z))
165  (cmpl ($ x8632::nil-value) (% arg_z))
166  (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% temp0))
167  ;; unboxed a or a[i] in temp0, unboxed b or b[j] in imm0
168  (cmpl ($ '1) (@ borrow (% esp)))      ;CF = 1 if borrow is 0 else CF = 0
169  (sbb (% imm0) (% temp0))
170  (movl ($ 1) (% imm0))
171  (sbb ($ 0) (% imm0))
172  (box-fixnum imm0 arg_z)
173  (movl (% temp0) (% imm0))
174  (mark-as-node temp0)
175  (movl (@ r (% esp)) (% temp0))
176  (movl (@ k (% esp)) (% temp1))
177  (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
178  (single-value-return 7))
179
180#+sse2
181(defx8632lapfunction %subtract-with-borrow ((r 20) (k 16) (borrow 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
182  (let ((aa mm2)
183        (bb mm3)
184        (ww mm4))
185    (unbox-fixnum b imm0)
186    (cmpl ($ x8632::nil-value) (% j))
187    ;; if j not nil, get b[j]
188    (cmovnel (@ x8632::misc-data-offset (% b) (% j)) (% imm0))
189    (movd (% imm0) (% bb))
190    (movl (@ a (% esp)) (% arg_y))
191    (movl (@ i (% esp)) (% arg_z))
192    (movl (@ borrow (% esp)) (% temp0))
193    (unbox-fixnum arg_y imm0)
194    (cmpl ($ x8632::nil-value) (% arg_z))
195    ;; if i not nil, get a[i]
196    (cmovnel (@ x8632::misc-data-offset (% arg_y) (% arg_z)) (% imm0))
197    (movd (% imm0) (% aa))
198    (unbox-fixnum temp0 imm0)
199    (subl ($ 1) (% imm0))
200    (movd (% imm0) (% ww))
201    (psubq (% bb) (% aa))
202    (paddq (% ww) (% aa))
203    (movl (@ r (% esp)) (% temp0))
204    (movl (@ k (% esp)) (% temp1))
205    (movd (% aa) (@ x8632::misc-data-offset (% temp0) (% temp1)))
206    (psrlq ($ 32) (% aa))               ;carry digit
207    (movd (% aa) (% imm0))
208    (xorl (% arg_z) (% arg_z))
209    (test ($ 1) (% imm0))
210    (cmovzl ($ '1) (% arg_z))
211    (single-value-return 7)))
212
213(defx8632lapfunction %subtract-one ((high arg_y) (low arg_z))
214  (mark-as-imm temp0)
215  (unbox-fixnum low imm0)
216  (movl (% high) (% temp0))
217  (shll ($ (- 16 x8632::fixnumshift)) (% temp0))
218  (orl (% imm0) (% temp0))
219  (subl ($ 1) (% temp0))
220  (movzwl (% temp0.w) (% imm0))
221  (box-fixnum imm0 low)
222  (sarl ($ 16) (% temp0))
223  (box-fixnum temp0 high)
224  (mark-as-node temp0)
225  (movl (% esp) (% temp0))
226  (push (% high))
227  (push (% low))
228  (jmp-subprim .SPvalues))
229
230;;; %SUBTRACT-WITH-BORROW -- Internal.
231;;;
232;;; This should be in assembler, and should not cons intermediate results.  It
233;;; returns a 32bit digit and a borrow resulting from subtracting b from a, and
234;;; subtracting a possible incoming borrow.
235;;;
236;;; We really do:  a - b - 1 + borrow, where borrow is either 0 or 1.
237;;;
238
239(defx8632lapfunction %subtract-with-borrow-1 ((a-h 12) (a-l 8) (b-h 4) #|(ra 0)|# (b-l arg_y) (borrow arg_z))
240  (mark-as-imm temp0)
241  (mark-as-imm temp1)
242  (unbox-fixnum b-l temp0)
243  (movl (@ b-h (% esp)) (% imm0))
244  (unbox-fixnum imm0 imm0)
245  (shll ($ 16) (% imm0))
246  (orl (% imm0) (% temp0))
247  (movl (@ a-l (% esp)) (% temp1))
248  (unbox-fixnum temp1 temp1)
249  (movl (@ a-h (% esp)) (% imm0))
250  (unbox-fixnum imm0 imm0)
251  (shll ($ 16) (% imm0))
252  (orl (% imm0) (% temp1))
253  (cmpl ($ '1) (% borrow))          ;CF = 1 if borrow is 0 else CF = 0
254  (sbbl (% temp0) (% temp1))
255  (movl ($ 1) (% imm0))
256  (subb ($ 0) (% imm0))
257  (box-fixnum imm0 arg_z)
258  (movzwl (% temp1.w) (% imm0))
259  (box-fixnum imm0 imm0)
260  (popl (% arg_y))                      ;return address
261  (addl ($ '5) (% esp))                 ;discard reserved frame & stack args
262  (pushl (% arg_y))
263  (push (% imm0))                       ;high
264  (sarl ($ 16) (% temp1))
265  (box-fixnum temp1 imm0)
266  (mark-as-node temp0)
267  (mark-as-node temp1)
268  (push (% imm0))                       ;low
269  (push (% arg_z))                      ;borrow
270  (set-nargs 3)
271  (leal (@ '3 (% esp)) (% temp0))
272  (jmp-subprim .SPvalues))
273 
274
275;;; To normalize a bignum is to drop "trailing" digits which are
276;;; redundant sign information.  When return-fixnum-p is non-nil, make
277;;; the resultant bignum into a fixnum if it fits.
278(defx8632lapfunction %normalize-bignum-2 ((return-fixnum-p arg_y) (bignum arg_z))
279  (push (% return-fixnum-p))
280  (mark-as-imm temp0)
281  (mark-as-imm temp1)
282  (let ((len arg_y)
283        (sign temp0)
284        (next temp1))
285    (vector-length bignum len)
286    (cmpl ($ '1) (% len))
287    (jle @maybe-return-fixnum)
288    ;; Zero trailing sign digits.
289    (push (% len))
290    ;; next-to-last digit
291    (movl (@ (- x8632::misc-data-offset 8) (% bignum) (% len)) (% next))
292    ;; last digit
293    (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% len)) (% sign))
294    (jmp @test)
295    @loop
296    (subl ($ '1) (% len))
297    (movl ($ 0) (@ x8632::misc-data-offset (% bignum) (% len)))
298    (cmpl ($ '1) (% len))               ;any more digits?
299    (je @adjust-length)
300    (movl (% next) (% sign))
301    ;; (bignum-ref bignum (- len 2))
302    (movl (@ (- x8632::misc-data-offset 8) (% bignum) (% len)) (% next))
303    @test
304    (movl (% next) (% imm0))
305    (sarl ($ 31) (% imm0))              ;propagate sign bit
306    (xorl (% sign) (% imm0))            ;whole digit only sign?
307    (jz @loop)
308    ;; New length now in len.
309    @adjust-length
310    (pop (% imm0))                      ;original length
311    (cmpl (% len) (% imm0))
312    ;; If the new length is the same as the original length, we know
313    ;; that the bignum is at least two digits long (because if it was
314    ;; shorter, we would have branched directly to
315    ;; @maybe-return-fixnum), and thus won't fit in a fixnum.
316    ;; Therefore, there's no need to do either of the tests at
317    ;; @maybe-return-fixnum.
318    (je @done)
319    (movl (% len) (% imm0))
320    (shll ($ (- x8632::num-subtag-bits x8632::fixnumshift)) (% imm0))
321    (movb ($ x8632::subtag-bignum) (% imm0.b))
322    (movl (% imm0) (@ x8632::misc-header-offset (% bignum)))
323    @maybe-return-fixnum
324    ;; could use SETcc here to avoid one branch
325    (cmpl ($ x8632::nil-value) (@ 0 (% esp))) ;return-fixnum-p
326    (je @done)
327    (cmpl ($ x8632::one-digit-bignum-header) (% bignum))
328    (jne @done)
329    ;; Bignum has one digit.  If it fits in a fixnum, return a fixnum.
330    (movl (@ x8632::misc-data-offset (% bignum)) (% imm0))
331    (box-fixnum imm0 arg_y)
332    (unbox-fixnum arg_y temp0)
333    (cmpl (% temp0) (% imm0))
334    (cmovel (% arg_y) (% arg_z))
335    @done
336    (pop (% imm0))                      ;discard saved return-fixnum-p
337    (mark-as-node temp0)
338    (mark-as-node temp1)
339    (single-value-return)))
340
341;;; Multiply X[I] by the unboxed value of the (non-negative) fixnum Y;
342;;; add the incoming carry from CARRY[0] to the 64-bit product.  Store
343;;; the low word of the 64-bit sum in R[0] and the high word in
344;;; CARRY[0].
345(defx8632lapfunction %multiply-and-add ((r 12) (carry 8) (x 4) #|(ra 0)|# (i arg_y) (y arg_z))
346  (let ((xx mm2)
347        (yy mm3)
348        (cc mm4))
349    (movl (@ x (% esp)) (% imm0))
350    (movd (@ x8632::misc-data-offset (% imm0) (% i)) (% xx))
351    (unbox-fixnum y imm0)
352    (movd (% imm0) (% yy))
353    (pmuludq (% xx) (% yy))             ;64 bit product
354    (movl (@ carry (% esp)) (% arg_y))
355    (movd (@ x8632::misc-data-offset (% arg_y)) (% cc))
356    (paddq (% cc) (% yy))               ;add in 32 bit carry digit
357    (movl (@ r (% esp)) (% arg_z))
358    (movd (% yy) (@ x8632::misc-data-offset (% arg_z)))
359    (psrlq ($ 32) (% yy))
360    (movd (% yy) (@ x8632::misc-data-offset (% arg_y)))
361    (single-value-return 5)))
362
363;; multiply x[i] by y and add to result starting at digit i
364(defx8632lapfunction %multiply-and-add-harder-loop-2
365    ((x 12) (y 8) (r 4) #|(ra 0)|# (i arg_y) (ylen arg_z))
366  (let ((cc mm2)
367        (xx mm3)
368        (yy mm4)
369        (j imm0))
370    (movl (@ x (% esp)) (% temp0))
371    (movd (@ x8632::misc-data-offset (% temp0) (% i)) (% xx)) ;x[i]
372    (movl (@ y (% esp)) (% temp0))
373    (movl (@ r (% esp)) (% temp1))
374    (pxor (% cc) (% cc))
375    (xorl (% j) (% j))
376    @loop
377    (movd (@ x8632::misc-data-offset (% temp0) (% j)) (% yy)) ;y[j]
378    (pmuludq (% xx) (% yy))
379    (paddq (% cc) (% yy))
380    (movd (% yy) (@ x8632::misc-data-offset (% temp1) (% i))) ;store r[i]
381    (movq (% yy) (% cc))
382    (psrlq ($ 32) (% cc))               ;carry high digit
383    (addl ($ '1) (% i))
384    (addl ($ '1) (% j))
385    (subl ($ '1) (% ylen))
386    (jg @loop)
387    (movd (% cc) (@ x8632::misc-data-offset (% temp1) (% i)))
388    (single-value-return 5)))
389
390;; this is silly 
391(defx8632lapfunction %add-the-carry ((high 4) #|(ra 0)|# (low arg_y) (c arg_z))
392  (mark-as-imm temp0)
393  (let ((imm1 temp0)
394        (imm1.w temp0.w))
395    (pop (% temp1))
396    (popl (% imm1))                     ;high
397    (discard-reserved-frame)
398    (push (% temp1))
399    (shll ($ (- 16 x8632::fixnumshift)) (% temp0))
400    (unbox-fixnum low imm0)
401    (orl (% imm0) (% imm1))
402    (unbox-fixnum c imm0)
403    (addl (% imm0) (% imm1))
404    (movzwl (% imm1.w) (% imm0))
405    (box-fixnum imm0 temp1)
406    (sarl ($ 16) (% imm1))
407    (shll ($ x8632::fixnumshift) (% imm1))
408    (push (% imm1))                     ;high
409    (push (% temp1)))                   ;low
410  (mark-as-node temp0)
411  (set-nargs 2)
412  (leal (@ '2 (% esp)) (% temp0))
413  (jmp-subprim .SPvalues))
414
415(defx8632lapfunction %bignum-count-trailing-zero-bits ((bignum arg_z))
416  (let ((i arg_y)
417        (len temp0)
418        (zeros temp1))
419    (vector-length bignum temp0)
420    (xorl (% i) (% i))
421    (movl ($ '32) (% zeros))
422    @loop
423    (movl (@ x8632::misc-data-offset (% bignum) (% i)) (% imm0))
424    (addl ($ '1) (% i))
425    (addl ($ '32) (% zeros))
426    (testl (% imm0) (% imm0))
427    (jz @loop)
428    ;; now count zero bits in digit
429    (bsrl (% imm0) (% imm0))
430    (box-fixnum imm0 imm0)
431    (addl (% imm0) (% zeros))
432    (movl (% zeros) (% arg_z))
433    (single-value-return)))
434
435;;; dest[i] = (logand x[i] y[i])
436(defx8632lapfunction %bignum-logand ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
437  (let ((i temp0)
438        (xx temp1)
439        (yy arg_y))
440    (movl (@ idx (% esp)) (% i))
441    (movl (@ x (% esp)) (% xx))
442    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
443    (andl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
444    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
445    (single-value-return 4)))
446
447;;; dest[i] = (logandc1 x[i] y[i])
448(defx8632lapfunction %bignum-logandc1 ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
449  (let ((i temp0)
450        (xx temp1)
451        (yy arg_y))
452    (movl (@ idx (% esp)) (% i))
453    (movl (@ x (% esp)) (% xx))
454    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
455    (not (% imm0))
456    (andl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
457    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
458    (single-value-return 4)))
459
460;;; dest[i] = (logandc2 x[i] y[i])
461(defx8632lapfunction %bignum-logandc2 ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
462  (let ((i temp0)
463        (xx temp1)
464        (yy arg_y))
465    (movl (@ idx (% esp)) (% i))
466    (movl (@ x (% esp)) (% xx))
467    (movl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
468    (not (% imm0))
469    (andl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
470    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
471    (single-value-return 4)))
472
473;;; dest[i] = (logior x[i] y[i])
474(defx8632lapfunction %bignum-logior ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
475  (let ((i temp0)
476        (xx temp1)
477        (yy arg_y))
478    (movl (@ idx (% esp)) (% i))
479    (movl (@ x (% esp)) (% xx))
480    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
481    (orl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
482    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
483    (single-value-return 4)))
484
485;;; dest[i] = (lognot x[i])
486(defx8632lapfunction %bignum-logior ((idx 4) #|(ra 0)|# (x arg_y) (dest arg_z))
487  (let ((i temp0))
488    (movl (@ idx (% esp)) (% i))
489    (movl (@ x8632::misc-data-offset (% x) (% i)) (% imm0))
490    (not (% imm0))
491    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
492    (single-value-return 3)))
493
494;;; dest[i] = (logxor x[i] y[i])
495(defx8632lapfunction %bignum-logxor ((idx 8) (x 4) #|(ra 0)|# (y arg_y) (dest arg_z))
496  (let ((i temp0)
497        (xx temp1)
498        (yy arg_y))
499    (movl (@ idx (% esp)) (% i))
500    (movl (@ x (% esp)) (% xx))
501    (movl (@ x8632::misc-data-offset (% xx) (% i)) (% imm0))
502    (xorl (@ x8632::misc-data-offset (% yy) (% i)) (% imm0))
503    (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% i)))
504    (single-value-return 4)))
505
506(defx8632lapfunction %compare-digits ((a 4) #|(ra 0)|# (b arg_y) (i arg_z))
507  (movl (@ a (% esp)) (% temp0))
508  (movl (@ x8632::misc-data-offset (% temp0) (% i)) (% imm0))
509  (xorl (% temp0) (% temp0))
510  (movl ($ '1) (% temp1))
511  (movl ($ '-1) (% arg_y))
512  (cmpl (@ x8632::misc-data-offset (% b) (% i)) (% imm0))
513  (cmovzl (% temp0) (% arg_z))
514  (cmovgl (% temp1) (% arg_z))
515  (cmovll (% arg_y) (% arg_z))
516  (single-value-return 3))
517
518;; returns number of bits in digit-hi,digit-lo that are sign bits
519;; 32 - digits-sign-bits is integer-length
520(defx8632lapfunction %digits-sign-bits ((hi arg_y) (lo arg_z))
521  (mark-as-imm temp0)
522  (shll ($ (- 16 x8632::fixnumshift)) (% hi))
523  (unbox-fixnum lo imm0)
524  (orl (% hi) (% imm0))
525  (movl (% imm0) (% temp0))
526  (not (% imm0))
527  (testl (% temp0) (% temp0))
528  (js @wasneg)
529  (not (% imm0))
530  @wasneg
531  (bsrl (% imm0) (% imm0))
532  (sete (% temp0.b))
533  (xorl ($ 31) (% imm0))
534  (addb (% temp0.b) (% imm0.b))
535  (box-fixnum imm0 arg_z)
536  (mark-as-node temp0)
537  (single-value-return))
538
539; if dest not nil store unboxed result in dest(0), else return a fixnum
540(defx8632lapfunction fix-digit-logandc2 ((fix 4) #|(ra 0)|# (big arg_y) (dest arg_z)) ; index 0
541  (mark-as-imm temp0)
542  (movl (@ fix (% esp)) (% temp0))
543  (unbox-fixnum temp0 temp0)
544  (movl (@ x8632::misc-data-offset (% big)) (% imm0))
545  (not (% imm0))
546  (andl (% temp0) (% imm0))
547  (mark-as-node temp0)
548  (cmpl ($ x8632::nil-value) (% dest))
549  (jne @store)
550  (box-fixnum imm0 arg_z)
551  (single-value-return 3)
552  @store
553  (movl (% imm0) (@ x8632::misc-data-offset (% dest)))
554  (single-value-return 3))
555
556(defx8632lapfunction digit-lognot-move ((index 4) #|(ra 0)|# (source arg_y) (dest arg_z))
557  (movl (@ index (% esp)) (% temp0))
558  (movl (@ x8632::misc-data-offset (% source) (% temp0)) (% imm0))
559  (not (% imm0))
560  (movl (% imm0) (@ x8632::misc-data-offset (% dest) (% temp0)))
561  (single-value-return 3))
562
563;; Add b to a starting at a[i]
564;; might want not to use SSE2 for this.  use lea to update loop counter
565;; variables so that the flags don't get set.
566(defx8632lapfunction bignum-add-loop-+ ((i 8) (a 4) #|(ra 0)|# (b arg_y) (blen arg_z))
567  (let ((aa mm2)
568        (bb mm3)
569        (cc mm4))
570    (movl (@ a (% esp)) (% temp0))
571    (movl (@ i (% esp)) (% temp1))
572    (xorl (% imm0) (% imm0))
573    (pxor (% cc) (% cc))
574    @loop
575    (movd (@ x8632::misc-data-offset (% temp0) (% temp1)) (% aa))
576    (movd (@ x8632::misc-data-offset (% b) (% imm0)) (% bb))
577    (paddq (% bb) (% aa))
578    (paddq (% cc) (% aa))
579    (movd (% aa) (@ x8632::misc-data-offset (% temp0) (% temp1)))
580    (psrlq ($ 32) (% aa))
581    (movq (% aa) (% cc))
582    (addl ($ '1) (% temp1))
583    (addl ($ '1) (% imm0))
584    (subl ($ '1) (% blen))
585    (jg @loop)
586    ;; add in final carry
587    (movd (% cc) (% imm0))
588    (addl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
589    (single-value-return 4)))
590
591(defx8632lapfunction bignum-logtest-loop ((count 4) #|(ra 0)|# (s1 arg_y) (s2 arg_z))
592  (let ((i temp1)
593        (c temp0))
594    (movl (@ count (% esp)) (% c))
595    (xorl (% i) (% i))
596    @loop
597    (movl (@ x8632::misc-data-offset (% s1) (% i)) (% imm0))
598    (test (@ x8632::misc-data-offset (% s2) (% i)) (% imm0))
599    (jnz @true)
600    (addl ($ '1) (% i))
601    (cmpl (% i) (% c))
602    (jg @loop)
603    (movl ($ x8632::nil-value) (% arg_z))
604    (single-value-return 3)
605    @true
606    (movl ($ x8632::t-value) (% arg_z))
607    (single-value-return 3)))
608
609;;; called from bignum-ashift-left-unaligned
610(defx8632lapfunction bignum-shift-left-loop ((nbits 12) (result 8) (bignum 4) #|(ra 0)|# (res-len-1 arg_y) (j arg_z))
611  (let ((r temp0)
612        (b temp1)
613        (bb mm2)
614        (bits mm3)
615        (tt mm4)
616        (remaining-bits mm5))
617    (movl (% j) (% imm0))
618    (subl ($ '1) (% imm0))
619    (pushl (% imm0))                    ;digits
620    (movl (@ nbits (% esp)) (% imm0))
621    (unbox-fixnum imm0 imm0)
622    (movd (% imm0) (% bits))            ;shift count
623    (negl (% imm0))
624    (addl ($ 32) (% imm0))
625    (movd (% imm0) (% remaining-bits))
626    (movl (@ result (% esp)) (% r))
627    (movl (@ bignum (% esp)) (% b))
628    (xorl (% imm0) (% imm0))
629    @loop
630    ;; bignum[i]
631    (movd (@ x8632::misc-data-offset (% b) (% imm0)) (% bb))
632    (psrlq (% remaining-bits) (% bb))
633    ;; bignum[i+1]
634    (movd (@ (+ x8632::misc-data-offset 4) (% b) (% imm0)) (% tt))
635    (psllq (% bits) (% tt))
636    (por (% tt) (% bb))
637    (movd (% bb) (@ x8632::misc-data-offset (% r) (% j)))
638    (addl ($ '1) (% imm0))
639    (addl ($ '1) (% j))
640    (cmpl (% j) (% res-len-1))
641    (jne @loop)
642    (movd (@ x8632::misc-data-offset (% bignum)) (% bb)) ;bignum[0]
643    (psllq (% bits) (% bb))
644    (popl (% arg_y))                    ;digits
645    (movd (% bb) (@ x8632::misc-data-offset (% r) (% arg_y)))
646    (movd (@ x8632::misc-data-offset (% bignum) (% imm0)) (% bb)) ;bignum[i]
647    (psrlq (% remaining-bits) (% bb))
648    (movd (% bb) (@ x8632::misc-data-offset (% r) (% j)))
649    (single-value-return 5)))
650
651(defx8632lapfunction %logcount-complement ((bignum arg_y) (i arg_z))
652  (mark-as-imm temp0)
653  (let ((rshift imm0)
654        (temp temp0))
655    (movl (@ x8632::misc-data-offset (% bignum) (% i)) (% rshift))
656    (notl (% rshift))
657    (xorl (% arg_z) (% arg_z))
658    (testl (% rshift) (% rshift))
659    (jmp @test)
660    @next
661    (lea (@ -1 (% rshift)) (% temp))
662    (and (% temp) (% rshift))           ;sets flags
663    (lea (@ '1 (% arg_z)) (% arg_z))    ;doesn't set flags
664    @test
665    (jne @next)
666    (mark-as-node temp0)
667    (single-value-return)))
668
669(defx8632lapfunction %logcount ((bignum arg_y) (i arg_z))
670  (mark-as-imm temp0)
671  (let ((rshift imm0)
672        (temp temp0))
673    (movl (@ x8632::misc-data-offset (% bignum) (% i)) (% rshift))
674    (xorl (% arg_z) (% arg_z))
675    (testl (% rshift) (% rshift))
676    (jmp @test)
677    @next
678    (lea (@ -1 (% rshift)) (% temp))
679    (and (% temp) (% rshift))           ;sets flags
680    (lea (@ '1 (% arg_z)) (% arg_z))    ;doesn't set flags
681    @test
682    (jne @next)
683    (mark-as-node temp0)
684    (single-value-return)))
685
686
687;;; floor: given x and y, producing q and r, q * y + r = x.
688
689;;; Divide bignum x by single digit y (passed as two halves).
690;;; The quotient in stored in q, and the remainder is returned
691;;; in two halves.
692(defx8632lapfunction %floor-loop-quo ((x 8) (q 4) #|(ra 0)|# (yhi arg_y) (ylo arg_z))
693  )
694
695
696
Note: See TracBrowser for help on using the repository browser.