close Warning: Can't use blame annotator:
No changeset 1633 in the repository

source: release/1.11/source/level-0/PPC/PPC64/ppc64-bignum.lisp

Last change on this file was 16688, checked in by R. Matthew Emerson, 9 years ago

Merge copyright/license header changes to 1.11 release branch.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 KB
RevLine 
1;;-*- Mode: Lisp; Package: CCL -*-
2;;;
3;;; Copyright 1994-2009 Clozure Associates
4;;;
5;;; Licensed under the Apache License, Version 2.0 (the "License");
6;;; you may not use this file except in compliance with the License.
7;;; You may obtain a copy of the License at
8;;;
9;;; http://www.apache.org/licenses/LICENSE-2.0
10;;;
11;;; Unless required by applicable law or agreed to in writing, software
12;;; distributed under the License is distributed on an "AS IS" BASIS,
13;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14;;; See the License for the specific language governing permissions and
15;;; limitations under the License.
16
17
18(in-package "CCL")
19
20;;; The caller has allocated a two-digit bignum (quite likely on the stack).
21;;; If we can fit in a single digit (if the high word is just a sign
22;;; extension of the low word), truncate the bignum in place (the
23;;; trailing words should already be zeroed.
24(defppclapfunction %fixnum-to-bignum-set ((bignum arg_y) (fixnum arg_z))
25 (unbox-fixnum imm0 fixnum)
26 (srdi imm1 imm0 32)
27 (srawi imm2 imm0 31)
28 (cmpw imm2 imm1)
29 (stw imm0 ppc64::misc-data-offset bignum)
30 (li imm2 ppc64::one-digit-bignum-header)
31 (beq @chop)
32 (stw imm1 (+ ppc64::misc-data-offset 4) bignum)
33 (blr)
34 @chop
35 (std imm2 ppc64::misc-header-offset bignum)
36 (blr))
37
38
39(defppclapfunction %multiply-and-add-loop64
40 ((x 8) (y 0) (r arg_x) (idx arg_y) (ylen arg_z))
41 (let ((i imm0)
42 (j imm1)
43 (xx imm2)
44 (yy imm3)
45 (rr imm4)
46 (dd imm5)
47 (cc nargs))
48 (ld temp0 x vsp)
49 (la i ppc64::misc-data-offset idx)
50 (ldx xx temp0 i) ;x[i]
51 (rotldi xx xx 32)
52 (ld temp0 y vsp)
53 (li cc 0)
54 (li j ppc64::misc-data-offset)
55 @loop
56 (ldx yy temp0 j) ;y[j]
57 (rotldi yy yy 32)
58 (mulld dd xx yy) ;low
59 (ldx rr r i) ;r[i]
60 (rotldi rr rr 32)
61 (addc rr rr dd) ;r[i] = r[i] + low
62 (mulhdu dd xx yy) ;high
63 (addze dd dd) ;carry from addding in low
64 (addc rr rr cc) ;add in carry digit
65 (addze cc dd)
66 (rotldi rr rr 32)
67 (stdx rr r i) ;update r[i]
68 (cmpdi ylen '1)
69 (la i 8 i)
70 (la j 8 j)
71 (subi ylen ylen '1)
72 (bne @loop)
73 (rotldi cc cc 32)
74 (stdx cc r i)
75 (set-nargs 0)
76 (la vsp 16 vsp)
77 (blr)))
78
79;;; Multiply the (32-bit) digits X and Y, producing a 64-bit result.
80;;; Add the 32-bit "prev" digit and the 32-bit carry-in digit to that 64-bit
81;;; result; return the halves as (VALUES high low).
82(defppclapfunction %multiply-and-add4 ((x 0) (y arg_x) (prev arg_y) (carry-in arg_z))
83 (let ((unboxed-x imm0)
84 (unboxed-y imm1)
85 (unboxed-prev imm2)
86 (unboxed-carry-in imm3)
87 (result64 imm4)
88 (high arg_y)
89 (low arg_z))
90 (ld temp0 x vsp)
91 (unbox-fixnum unboxed-x temp0)
92 (unbox-fixnum unboxed-y y)
93 (unbox-fixnum unboxed-prev prev)
94 (unbox-fixnum unboxed-carry-in carry-in)
95 (mulld result64 unboxed-x unboxed-y)
96 (add result64 result64 unboxed-prev)
97 (add result64 result64 unboxed-carry-in)
98 (clrlsldi low result64 32 ppc64::fixnumshift)
99 (clrrdi high result64 32)
100 (srdi high high (- 32 ppc64::fixnumshift))
101 (std high 0 vsp)
102 (set-nargs 2)
103 (vpush low)
104 (la temp0 '2 vsp)
105 (ba .SPvalues)))
106
107(defppclapfunction %multiply-and-add3 ((x arg_x) (y arg_y) (carry-in arg_z))
108 (let ((unboxed-x imm0)
109 (unboxed-y imm1)
110 (unboxed-carry-in imm2)
111 (result64 imm3)
112 (high arg_y)
113 (low arg_z))
114 (unbox-fixnum unboxed-x arg_x)
115 (unbox-fixnum unboxed-y y)
116 (unbox-fixnum unboxed-carry-in carry-in)
117 (mulld result64 unboxed-x unboxed-y)
118 (add result64 result64 unboxed-carry-in)
119 (clrlsldi low result64 32 ppc64::fixnumshift)
120 (clrrdi high result64 32)
121 (srdi high high (- 32 ppc64::fixnumshift))
122 (vpush high)
123 (set-nargs 2)
124 (vpush low)
125 (la temp0 '2 vsp)
126 (ba .SPvalues)))
127
128(defppclapfunction %multiply-and-add-fixnum-loop ((len64 0) (x arg_x) (y arg_y) (result arg_z))
129 (let ((carry imm4)
130 (iidx imm3)
131 (unboxed-y imm0)
132 (i temp0)
133 (hi imm2)
134 (rlen temp1))
135 (vpop rlen)
136 (li carry 0)
137 (li iidx ppc64::misc-data-offset)
138 (li i 0)
139 (b @test)
140 @loop
141 (unbox-fixnum unboxed-y y)
142 (ldx imm1 x iidx)
143 (rotldi imm1 imm1 32)
144 (mulhdu hi imm1 unboxed-y)
145 (mulld imm0 imm1 unboxed-y)
146 (addc imm0 imm0 carry)
147 (addze carry hi)
148 (rotldi imm0 imm0 32)
149 (stdx imm0 result iidx)
150 (la iidx 8 iidx)
151 (la i '1 i)
152 @test
153 (cmpd i rlen)
154 (blt @loop)
155 (rotldi carry carry 32)
156 (stdx carry result iidx)
157 (blr)))
158
159
160
161;;; Return the (possibly truncated) 32-bit quotient and remainder
162;;; resulting from dividing hi:low by divisor.
163(defppclapfunction %floor ((num-high arg_x) (num-low arg_y) (divisor arg_z))
164 (let ((unboxed-num imm0)
165 (unboxed-low imm1)
166 (unboxed-divisor imm2)
167 (unboxed-quo imm3)
168 (unboxed-rem imm4))
169 (sldi unboxed-num num-high (- 32 ppc64::fixnumshift))
170 (unbox-fixnum unboxed-low num-low)
171 (unbox-fixnum unboxed-divisor divisor)
172 (or unboxed-num unboxed-low unboxed-num)
173 (divdu unboxed-quo unboxed-num unboxed-divisor)
174 (mulld unboxed-rem unboxed-quo unboxed-divisor)
175 (sub unboxed-rem unboxed-num unboxed-rem)
176 (clrlsldi arg_y unboxed-quo 32 ppc64::fixnumshift)
177 (clrlsldi arg_z unboxed-rem 32 ppc64::fixnumshift)
178 (mr temp0 vsp)
179 (vpush arg_y)
180 (vpush arg_z)
181 (set-nargs 2)
182 (ba .SPvalues)))
183
184;;; Multiply two (UNSIGNED-BYTE 32) arguments, return the high and
185;;; low halves of the 64-bit result
186(defppclapfunction %multiply ((x arg_y) (y arg_z))
187 (let ((unboxed-x imm0)
188 (unboxed-y imm1)
189 (unboxed-high imm2)
190 (unboxed-low imm3))
191 (unbox-fixnum unboxed-x x)
192 (unbox-fixnum unboxed-y y)
193 (mulld imm2 unboxed-x unboxed-y)
194 (clrlsldi arg_y imm2 32 ppc64::fixnumshift) ; arg_y = low32
195 (srdi imm2 imm2 32)
196 (box-fixnum arg_z imm2) ; arg_z = high32
197 (mr temp0 vsp)
198 (vpush arg_z)
199 (set-nargs 2)
200 (vpush arg_y)
201 (ba .SPvalues)))
202
203;;; Any words in the "tail" of the bignum should have been
204;;; zeroed by the caller.
205(defppclapfunction %set-bignum-length ((newlen arg_y) (bignum arg_z))
206 (sldi imm0 newlen (- ppc64::num-subtag-bits ppc64::fixnumshift))
207 (ori imm0 imm0 ppc64::subtag-bignum)
208 (std imm0 ppc64::misc-header-offset bignum)
209 (blr))
210
211;;; Count the sign bits in the most significant digit of bignum;
212;;; return fixnum count.
213(defppclapfunction %bignum-sign-bits ((bignum arg_z))
214 (vector-size imm0 bignum imm0)
215 (sldi imm0 imm0 2)
216 (la imm0 (- ppc64::misc-data-offset 4) imm0) ; Reference last (most significant) digit
217 (lwzx imm0 bignum imm0)
218 (cmpwi imm0 0)
219 (not imm0 imm0)
220 (blt @wasneg)
221 (not imm0 imm0)
222 @wasneg
223 (cntlzw imm0 imm0)
224 (box-fixnum arg_z imm0)
225 (blr))
226
227(defppclapfunction %signed-bignum-ref ((bignum arg_y) (index arg_z))
228 (srdi imm0 index 1)
229 (la imm0 ppc64::misc-data-offset imm0)
230 (lwax imm0 bignum imm0)
231 (box-fixnum arg_z imm0)
232 (blr))
233
234
235;;; If the bignum is a one-digit bignum, return the value of the
236;;; single digit as a fixnum. Otherwise, if it's a two-digit-bignum
237;;; and the two words of the bignum can be represented in a fixnum,
238;;; return that fixnum; else return nil.
239(defppclapfunction %maybe-fixnum-from-one-or-two-digit-bignum ((bignum arg_z))
240 (ld imm1 ppc64::misc-header-offset bignum)
241 (cmpdi cr1 imm1 ppc64::one-digit-bignum-header)
242 (cmpdi cr2 imm1 ppc64::two-digit-bignum-header)
243 (beq cr1 @one)
244 (bne cr2 @no)
245 (ld imm0 ppc64::misc-data-offset bignum)
246 (rotldi imm0 imm0 32)
247 (box-fixnum arg_z imm0)
248 (unbox-fixnum imm1 arg_z)
249 (cmpd imm0 imm1)
250 (beqlr)
251 @no
252 (li arg_z nil)
253 (blr)
254 @one
255 (lwa imm0 ppc64::misc-data-offset bignum)
256 (box-fixnum arg_z imm0)
257 (blr))
258
259
260(defppclapfunction %digit-logical-shift-right ((digit arg_y) (count arg_z))
261 (unbox-fixnum imm0 digit)
262 (unbox-fixnum imm1 count)
263 (srw imm0 imm0 imm1)
264 (box-fixnum arg_z imm0)
265 (blr))
266
267(defppclapfunction %ashr ((digit arg_y) (count arg_z))
268 (unbox-fixnum imm0 digit)
269 (unbox-fixnum imm1 count)
270 (sraw imm0 imm0 imm1)
271 (box-fixnum arg_z imm0)
272 (blr))
273
274(defppclapfunction %ashl ((digit arg_y) (count arg_z))
275 (unbox-fixnum imm0 digit)
276 (unbox-fixnum imm1 count)
277 (slw imm0 imm0 imm1)
278 (clrlsldi arg_z imm0 32 ppc64::fixnumshift)
279 (blr))
280
281(defppclapfunction macptr->fixnum ((ptr arg_z))
282 (macptr-ptr imm0 ptr)
283 (andi. imm1 imm0 7)
284 (li arg_z nil)
285 (bne @done)
286 (mr arg_z imm0)
287 @done
288 (blr))
289
290(defppclapfunction fix-digit-logand ((fix arg_x) (big arg_y) (dest arg_z)) ; index 0
291 (let ((w1 imm0)
292 (w2 imm1))
293 (ld w2 ppc64::misc-data-offset big)
294 (unbox-fixnum w1 fix)
295 (rotldi w2 w2 32)
296 (cmpdi dest nil)
297 (and w1 w1 w2)
298 (bne @store)
299 (box-fixnum arg_z w1)
300 (blr)
301 @store
302 (rotldi w1 w1 32)
303 (std w1 ppc64::misc-data-offset dest)
304 (blr)))
305
306
307
308(defppclapfunction fix-digit-logandc2 ((fix arg_x) (big arg_y) (dest arg_z))
309 (cmpdi dest nil)
310 (ld imm1 ppc64::misc-data-offset big)
311 (unbox-fixnum imm0 fix)
312 (rotldi imm1 imm1 32)
313 (andc imm1 imm0 imm1)
314 (bne @store)
315 (box-fixnum arg_z imm1)
316 (blr)
317 @store
318 (rotldi imm1 imm1 32)
319 (std imm1 ppc64::misc-data-offset dest)
320 (blr))
321
322(defppclapfunction fix-digit-logandc1 ((fix arg_x) (big arg_y) (dest arg_z))
323 (cmpdi dest nil)
324 (ld imm1 ppc64::misc-data-offset big)
325 (unbox-fixnum imm0 fix)
326 (rotldi imm1 imm1 32)
327 (andc imm1 imm1 imm0)
328 (bne @store)
329 (box-fixnum arg_z imm1)
330 (blr)
331 @store
332 (rotldi imm1 imm1 32)
333 (std imm1 ppc64::misc-data-offset dest)
334 (blr))
335
336
337;;; Do LOGIOR on the N 32-bit words in A and B, storing the result in
338;;; C. (It's legal and desirable to do this more than 32 bits at a time.)
339
340(defppclapfunction %bignum-logior ((n 0) (a arg_x) (b arg_y) (c arg_z))
341 (vpop imm0)
342 (srdi imm0 imm0 1)
343 (andi. imm1 imm0 4)
344 (la imm3 ppc64::misc-data-offset imm0)
345 (beq @loop)
346 (cmpdi imm0 4)
347 (subi imm0 imm0 4)
348 (subi imm3 imm3 4)
349 (lwzx imm1 a imm3)
350 (lwzx imm2 b imm3)
351 (or imm1 imm1 imm2)
352 (stwx imm1 c imm3)
353 (beqlr)
354 @loop
355 (subi imm0 imm0 8)
356 (subi imm3 imm3 8)
357 (cmpdi imm0 0) ;can't happen on 1st iteration
358 (ldx imm1 a imm3)
359 (ldx imm2 b imm3)
360 (or imm1 imm1 imm2)
361 (stdx imm1 c imm3)
362 (bne @loop)
363 (blr))
364
365
366
367;;; Do LOGAND on the N 32-bit words in A and B, storing the result in
368;;; C. (It's legal and desirable to do this more than 32 bits at a time.)
369
370(defppclapfunction %bignum-logand ((n 0) (a arg_x) (b arg_y) (c arg_z))
371 (vpop imm0)
372 (srdi imm0 imm0 1)
373 (andi. imm1 imm0 4)
374 (la imm3 ppc64::misc-data-offset imm0)
375 (beq @loop)
376 (cmpdi imm0 4)
377 (subi imm0 imm0 4)
378 (subi imm3 imm3 4)
379 (lwzx imm1 a imm3)
380 (lwzx imm2 b imm3)
381 (and imm1 imm1 imm2)
382 (stwx imm1 c imm3)
383 (beqlr)
384 @loop
385 (subi imm0 imm0 8)
386 (subi imm3 imm3 8)
387 (cmpdi imm0 0) ;can't happen on 1st iteration
388 (ldx imm1 a imm3)
389 (ldx imm2 b imm3)
390 (and imm1 imm1 imm2)
391 (stdx imm1 c imm3)
392 (bne @loop)
393 (blr))
Note: See TracBrowser for help on using the repository browser.