1 // Externe Routinen zu ARILEV1.D
2 // Prozessor: SPARC 64-bit
3 // Compiler: GNU-C oder ...
4 // Parameter-Übergabe: in Registern %o0-%o5.
5 // Parameter-Übergabe: in Registern %o0-%o5.
6 // Argumente vom Typ uint8, uint16, uint32 sind bereits vom Aufrufer zu
7 // uint64 umgewandelt worden (zero-extend, "srl reg,0,reg").
8 // Argumente vom Typ sint8, sint16, sint32 sind bereits vom Aufrufer zu
9 // sint64 umgewandelt worden (sign-extend, "sra reg,0,reg").
10 // Ergebnisse vom Typ uint8, uint16, uint32 müssen vor Rückgabe zu uint64
11 // umgewandelt werden (zero-extend, "srl reg,0,reg").
12 // Ergebnisse vom Typ sint8, sint16, sint32 müssen vor Rückgabe zu sint64
13 // umgewandelt werden (sign-extend, "sra reg,0,reg").
14 // Einstellungen: intCsize=32, intDsize=32.
17 #define C(entrypoint) _##entrypoint
19 #define C(entrypoint) entrypoint
22 // When this file is compiled into a shared library, ELF linkers need to
23 // know which symbols are functions.
24 #if defined(__NetBSD__) || defined(__OpenBSD__)
25 #define DECLARE_FUNCTION(name) .type C(name),@function
26 #elif defined(__svr4__) || defined(__ELF__)
27 #define DECLARE_FUNCTION(name) .type C(name),#function
29 #define DECLARE_FUNCTION(name)
32 // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots
33 // (diese werden VOR der vorigen Instruktion ausgeführt):
34 #define _ // Instruktion, die stets ausgeführt wird
35 #define __ // Instruktion, die nur im Sprung-Fall ausgeführt wird
36 // Abkürzungen für Anweisungen:
37 #define ret jmp %i7+8 // return from subroutine
38 #define retl jmp %o7+8 // return from leaf subroutine (no save/restore)
42 .register %g2,#scratch
44 .global C(mulu16_),C(mulu32_),C(mulu32_unchecked),C(mulu64_)
45 .global C(divu_6432_3232_),C(divu_3216_1616_)
46 .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down)
47 .global C(clear_loop_up),C(clear_loop_down)
48 .global C(test_loop_up),C(test_loop_down)
49 .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up)
50 #if CL_DS_BIG_ENDIAN_P
51 .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up)
52 .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up)
53 .global C(not_loop_up)
54 .global C(and_test_loop_up)
55 .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down)
56 .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down)
57 .global C(neg_loop_down)
58 .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down)
59 .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up)
60 .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down)
62 .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down)
63 .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down)
64 .global C(not_loop_down)
65 .global C(and_test_loop_down),C(compare_loop_down)
66 .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up)
67 .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up)
68 .global C(neg_loop_up)
69 .global C(shift1left_loop_up),C(shiftleft_loop_up)
70 .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down)
71 .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up)
74 #define LOOP_TYPE 1 // 1: Standard-Schleifen
75 // 2: Schleifen ohne Pointer, nur mit Zähler
76 #define STANDARD_LOOPS (LOOP_TYPE==1)
77 #define COUNTER_LOOPS (LOOP_TYPE==2)
79 // extern uint32 mulu16_ (uint16 arg1, uint16 arg2);
80 // ergebnis := arg1*arg2.
81 DECLARE_FUNCTION(mulu16_)
82 C(mulu16_:) // Input in %o0,%o1, Output in %o0
87 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
88 // 2^32*hi+lo := arg1*arg2.
89 DECLARE_FUNCTION(mulu32_)
90 C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1
96 // extern uint32 mulu32_unchecked (uint32 x, uint32 y);
97 // ergebnis := arg1*arg2 < 2^32.
98 DECLARE_FUNCTION(mulu32_unchecked)
99 C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0
104 // extern struct { uint64 lo; uint64 hi; } mulu64_ (uint64 arg1, uint64 arg2);
105 // 2^64*hi+lo := arg1*arg2.
106 DECLARE_FUNCTION(mulu64_)
107 C(mulu64_:) // Input in %o0,%o1, Output in %o0,%g2
108 srlx %o0,32,%o2 // %o2 = high32(arg1)
109 srl %o0,0,%o0 // %o0 = low32(arg1)
110 srlx %o1,32,%o3 // %o3 = high32(arg2)
111 srl %o1,0,%o1 // %o1 = low32(arg2)
112 mulx %o2,%o3,%g2 // high part
113 mulx %o2,%o1,%o2 // first mid part
114 mulx %o0,%o3,%o3 // second mid part
115 addcc %o2,%o3,%o2 // sum of mid parts
117 movcs %xcc,1,%o3 // carry from sum of mid parts
119 add %g2,%o3,%g2 // add to high part
121 add %g2,%o3,%g2 // add high32(midparts) to high part
122 mulx %o0,%o1,%o0 // low part
124 addcc %o0,%o2,%o0 // add low32(midparts)*2^32 to low part
127 _ movcs %xcc,%o3,%g2 // add carry to high part
129 // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
130 // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y .
131 DECLARE_FUNCTION(divu_6432_3232_)
132 C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1
134 udiv %o1,%o2,%o0 // x durch y dividieren, %o0 := q
135 umul %o0,%o2,%g1 // %g1 := (q*y) mod 2^32
136 sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r
140 // extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y);
141 // x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y .
142 DECLARE_FUNCTION(divu_3216_1616_)
143 C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient).
145 udiv %o0,%o1,%o2 // dividieren, Quotient nach %o2
146 #if 0 // Who says that %y has some meaningful contents after `udiv' ??
147 rd %y,%g1 // Rest aus %y
149 umul %o2,%o1,%g1 // %g1 := (q*y) mod 2^32
150 sub %o0,%g1,%g1 // %g1 := (x-q*y) mod 2^32 = r
152 sll %g1,16,%g1 // in die oberen 16 Bit schieben
157 #if !defined(__GNUC__)
159 // extern uint32 _get_g1 (void);
160 DECLARE_FUNCTION(_get_g1)
166 #if !defined(__GNUC__)
168 // extern uint64 _get_g2 (void);
169 DECLARE_FUNCTION(_get_g2)
175 // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
176 DECLARE_FUNCTION(copy_loop_up)
177 C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
179 // srl %o2,0,%o2 // zero-extend %o2 = count
192 // srl %o2,0,%o2 // zero-extend %o2 = count
195 sub %g0,%o2,%o2 // %o2 = -count
196 sllx %o2,3,%o2 // %o2 = -8*count
197 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
198 sub %o1,%o2,%o1 // %o1 = &destptr[count-1]
199 1: ldx [%o0+%o2],%o3 // nächstes Digit holen
200 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
202 _ stx %o3,[%o1+%o2] // Digit ablegen
207 // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
208 DECLARE_FUNCTION(copy_loop_down)
209 C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
211 // srl %o2,0,%o2 // zero-extend %o2 = count
224 // srl %o2,0,%o2 // zero-extend %o2 = count
227 sllx %o2,3,%o2 // %o2 = 8*count
228 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
229 sub %o1,%o2,%o1 // %o1 = &destptr[-count]
230 1: ldx [%o0+%o2],%o3 // nächstes Digit holen
231 subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
233 _ stx %o3,[%o1+%o2] // Digit ablegen
238 // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
239 DECLARE_FUNCTION(fill_loop_up)
240 C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
242 // srl %o1,0,%o1 // zero-extend %o1 = count
253 // srl %o1,0,%o1 // zero-extend %o1 = count
256 sub %g0,%o1,%o1 // %o1 = -count
257 sllx %o1,3,%o1 // %o1 = -8*count
258 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
259 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
261 _ stx %o2,[%o0+%o1] // Digit ablegen
266 // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
267 DECLARE_FUNCTION(fill_loop_down)
268 C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
270 // srl %o1,0,%o1 // zero-extend %o1 = count
281 // srl %o1,0,%o1 // zero-extend %o1 = count
283 _ sllx %o1,3,%o1 // %o1 = 8*count
284 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
285 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
287 _ stx %o2,[%o0+%o1] // Digit ablegen
292 // extern uintD* clear_loop_up (uintD* destptr, uintC count);
293 DECLARE_FUNCTION(clear_loop_up)
294 C(clear_loop_up:) // Input in %o0,%o1, Output in %o0
296 // srl %o1,0,%o1 // zero-extend %o1 = count
307 // srl %o1,0,%o1 // zero-extend %o1 = count
310 sub %g0,%o1,%o1 // %o1 = -count
311 sllx %o1,3,%o1 // %o1 = -8*count
312 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
313 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
315 _ stx %g0,[%o0+%o1] // Digit 0 ablegen
320 // extern uintD* clear_loop_down (uintD* destptr, uintC count);
321 DECLARE_FUNCTION(clear_loop_down)
322 C(clear_loop_down:) // Input in %o0,%o1, Output in %o0
324 // srl %o1,0,%o1 // zero-extend %o1 = count
335 // srl %o1,0,%o1 // zero-extend %o1 = count
337 _ sllx %o1,3,%o1 // %o1 = 8*count
338 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
339 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
341 _ stx %g0,[%o0+%o1] // Digit 0 ablegen
346 // extern boolean test_loop_up (uintD* ptr, uintC count);
347 DECLARE_FUNCTION(test_loop_up)
348 C(test_loop_up:) // Input in %o0,%o1, Output in %o0
350 // srl %o1,0,%o1 // zero-extend %o1 = count
365 // srl %o1,0,%o1 // zero-extend %o1 = count
367 _ sub %g0,%o1,%o1 // %o1 = -count
368 sllx %o1,3,%o1 // %o1 = -8*count
369 sub %o0,%o1,%o0 // %o0 = &ptr[count]
370 ldx [%o0+%o1],%o2 // nächstes Digit holen
371 1: brnz,pn %o2,3f // testen
372 _ addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
374 __ ldx [%o0+%o1],%o2 // nächstes Digit holen
381 // extern boolean test_loop_down (uintD* ptr, uintC count);
382 DECLARE_FUNCTION(test_loop_down)
383 C(test_loop_down:) // Input in %o0,%o1, Output in %o0
385 // srl %o1,0,%o1 // zero-extend %o1 = count
400 // srl %o1,0,%o1 // zero-extend %o1 = count
402 _ sllx %o1,3,%o1 // %o1 = 8*count
403 sub %o0,%o1,%o0 // %o0 = &ptr[-count]
405 ldx [%o0+%o1],%o2 // nächstes Digit holen
406 1: brnz,pn %o2,3f // testen
407 _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
409 __ ldx [%o0+%o1],%o2 // nächstes Digit holen
416 #if CL_DS_BIG_ENDIAN_P
418 // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
419 DECLARE_FUNCTION(or_loop_up)
420 C(or_loop_up:) // Input in %o0,%o1,%o2
422 // srl %o2,0,%o2 // zero-extend %o2 = count
424 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
425 1: ldx [%o0],%o3 // *xptr
426 ldx [%o0+%o1],%o4 // *yptr
428 or %o3,%o4,%o3 // verknüpfen
429 stx %o3,[%o0] // =: *xptr
431 _ add %o0,8,%o0 // xptr++, yptr++
436 // srl %o2,0,%o2 // zero-extend %o2 = count
439 sub %g0,%o2,%o2 // %o2 = -count
440 sllx %o2,3,%o2 // %o2 = -8*count
441 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
442 sub %o1,%o2,%o1 // %o1 = &yptr[count]
443 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
444 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
445 ldx [%o0+%o2],%o4 // noch ein Digit holen
446 or %o4,%o3,%o3 // beide verknüpfen
448 _ stx %o3,[%o1+%o2] // Digit ablegen
455 // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
456 DECLARE_FUNCTION(xor_loop_up)
457 C(xor_loop_up:) // Input in %o0,%o1,%o2
459 // srl %o2,0,%o2 // zero-extend %o2 = count
461 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
462 1: ldx [%o0],%o3 // *xptr
463 ldx [%o0+%o1],%o4 // *yptr
465 xor %o3,%o4,%o3 // verknüpfen
466 stx %o3,[%o0] // =: *xptr
468 _ add %o0,8,%o0 // xptr++, yptr++
473 // srl %o2,0,%o2 // zero-extend %o2 = count
476 sub %g0,%o2,%o2 // %o2 = -count
477 sllx %o2,3,%o2 // %o2 = -8*count
478 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
479 sub %o1,%o2,%o1 // %o1 = &yptr[count]
480 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
481 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
482 ldx [%o0+%o2],%o4 // noch ein Digit holen
483 xor %o4,%o3,%o3 // beide verknüpfen
485 _ stx %o3,[%o1+%o2] // Digit ablegen
490 #if CL_DS_BIG_ENDIAN_P
492 // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
493 DECLARE_FUNCTION(and_loop_up)
494 C(and_loop_up:) // Input in %o0,%o1,%o2
496 // srl %o2,0,%o2 // zero-extend %o2 = count
498 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
499 1: ldx [%o0],%o3 // *xptr
500 ldx [%o0+%o1],%o4 // *yptr
502 and %o3,%o4,%o3 // verknüpfen
503 stx %o3,[%o0] // =: *xptr
505 _ add %o0,8,%o0 // xptr++, yptr++
510 // srl %o2,0,%o2 // zero-extend %o2 = count
513 sub %g0,%o2,%o2 // %o2 = -count
514 sllx %o2,3,%o2 // %o2 = -8*count
515 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
516 sub %o1,%o2,%o1 // %o1 = &yptr[count]
517 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
518 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
519 ldx [%o0+%o2],%o4 // noch ein Digit holen
520 and %o4,%o3,%o3 // beide verknüpfen
522 _ stx %o3,[%o1+%o2] // Digit ablegen
527 // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
528 DECLARE_FUNCTION(eqv_loop_up)
529 C(eqv_loop_up:) // Input in %o0,%o1,%o2
531 // srl %o2,0,%o2 // zero-extend %o2 = count
533 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
534 1: ldx [%o0],%o3 // *xptr
535 ldx [%o0+%o1],%o4 // *yptr
537 xnor %o3,%o4,%o3 // verknüpfen
538 stx %o3,[%o0] // =: *xptr
540 _ add %o0,8,%o0 // xptr++, yptr++
545 // srl %o2,0,%o2 // zero-extend %o2 = count
548 sub %g0,%o2,%o2 // %o2 = -count
549 sllx %o2,3,%o2 // %o2 = -8*count
550 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
551 sub %o1,%o2,%o1 // %o1 = &yptr[count]
552 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
553 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
554 ldx [%o0+%o2],%o4 // noch ein Digit holen
555 xnor %o4,%o3,%o3 // beide verknüpfen
557 _ stx %o3,[%o1+%o2] // Digit ablegen
562 // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
563 DECLARE_FUNCTION(nand_loop_up)
564 C(nand_loop_up:) // Input in %o0,%o1,%o2
566 // srl %o2,0,%o2 // zero-extend %o2 = count
568 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
569 1: ldx [%o0],%o3 // *xptr
570 ldx [%o0+%o1],%o4 // *yptr
572 and %o3,%o4,%o3 // verknüpfen
574 stx %o3,[%o0] // =: *xptr
576 _ add %o0,8,%o0 // xptr++, yptr++
581 // srl %o2,0,%o2 // zero-extend %o2 = count
584 sub %g0,%o2,%o2 // %o2 = -count
585 sllx %o2,3,%o2 // %o2 = -8*count
586 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
587 sub %o1,%o2,%o1 // %o1 = &yptr[count]
588 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
589 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
590 ldx [%o0+%o2],%o4 // noch ein Digit holen
591 and %o4,%o3,%o3 // beide verknüpfen
594 _ stx %o3,[%o1+%o2] // Digit ablegen
599 // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
600 DECLARE_FUNCTION(nor_loop_up)
601 C(nor_loop_up:) // Input in %o0,%o1,%o2
603 // srl %o2,0,%o2 // zero-extend %o2 = count
605 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
606 1: ldx [%o0],%o3 // *xptr
607 ldx [%o0+%o1],%o4 // *yptr
609 or %o3,%o4,%o3 // verknüpfen
611 stx %o3,[%o0] // =: *xptr
613 _ add %o0,8,%o0 // xptr++, yptr++
618 // srl %o2,0,%o2 // zero-extend %o2 = count
621 sub %g0,%o2,%o2 // %o2 = -count
622 sllx %o2,3,%o2 // %o2 = -8*count
623 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
624 sub %o1,%o2,%o1 // %o1 = &yptr[count]
625 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
626 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
627 ldx [%o0+%o2],%o4 // noch ein Digit holen
628 or %o4,%o3,%o3 // beide verknüpfen
631 _ stx %o3,[%o1+%o2] // Digit ablegen
636 // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
637 DECLARE_FUNCTION(andc2_loop_up)
638 C(andc2_loop_up:) // Input in %o0,%o1,%o2
640 // srl %o2,0,%o2 // zero-extend %o2 = count
642 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
643 1: ldx [%o0],%o3 // *xptr
644 ldx [%o0+%o1],%o4 // *yptr
646 andn %o3,%o4,%o3 // verknüpfen
647 stx %o3,[%o0] // =: *xptr
649 _ add %o0,8,%o0 // xptr++, yptr++
654 // srl %o2,0,%o2 // zero-extend %o2 = count
657 sub %g0,%o2,%o2 // %o2 = -count
658 sllx %o2,3,%o2 // %o2 = -8*count
659 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
660 sub %o1,%o2,%o1 // %o1 = &yptr[count]
661 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
662 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
663 ldx [%o0+%o2],%o4 // noch ein Digit holen
664 andn %o4,%o3,%o3 // beide verknüpfen
666 _ stx %o3,[%o1+%o2] // Digit ablegen
671 // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
672 DECLARE_FUNCTION(orc2_loop_up)
673 C(orc2_loop_up:) // Input in %o0,%o1,%o2
675 // srl %o2,0,%o2 // zero-extend %o2 = count
677 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
678 1: ldx [%o0],%o3 // *xptr
679 ldx [%o0+%o1],%o4 // *yptr
681 orn %o3,%o4,%o3 // verknüpfen
682 stx %o3,[%o0] // =: *xptr
684 _ add %o0,8,%o0 // xptr++, yptr++
689 // srl %o2,0,%o2 // zero-extend %o2 = count
692 sub %g0,%o2,%o2 // %o2 = -count
693 sllx %o2,3,%o2 // %o2 = -8*count
694 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
695 sub %o1,%o2,%o1 // %o1 = &yptr[count]
696 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
697 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
698 ldx [%o0+%o2],%o4 // noch ein Digit holen
699 orn %o4,%o3,%o3 // beide verknüpfen
701 _ stx %o3,[%o1+%o2] // Digit ablegen
706 // extern void not_loop_up (uintD* xptr, uintC count);
707 DECLARE_FUNCTION(not_loop_up)
708 C(not_loop_up:) // Input in %o0,%o1
710 // srl %o1,0,%o1 // zero-extend %o1 = count
723 // srl %o1,0,%o1 // zero-extend %o1 = count
726 sub %g0,%o1,%o1 // %o1 = -count
727 sllx %o1,3,%o1 // %o1 = -8*count
728 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
729 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
730 ldx [%o0+%o1],%o2 // nächstes Digit holen
733 _ stx %o2,[%o0+%o1] // Digit ablegen
738 // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
739 DECLARE_FUNCTION(and_test_loop_up)
740 C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
742 // srl %o2,0,%o2 // zero-extend %o2 = count
759 // srl %o2,0,%o2 // zero-extend %o2 = count
761 _ sub %g0,%o2,%o2 // %o2 = -count
762 sllx %o2,3,%o2 // %o2 = -8*count
763 sub %o0,%o2,%o0 // %o0 = &xptr[count]
764 sub %o1,%o2,%o1 // %o1 = &yptr[count]
765 ldx [%o0+%o2],%o3 // nächstes Digit holen
766 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
767 andcc %o3,%o4,%g0 // beide verknüpfen
769 _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
771 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
780 // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
781 DECLARE_FUNCTION(compare_loop_up)
782 C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
784 // srl %o2,0,%o2 // zero-extend %o2 = count
801 _ sra %o0,0,%o0 // sign-extend %o0
804 // srl %o2,0,%o2 // zero-extend %o2 = count
806 _ sub %g0,%o2,%o2 // %o2 = -count
807 sllx %o2,3,%o2 // %o2 = -8*count
808 sub %o0,%o2,%o0 // %o0 = &xptr[count]
809 sub %o1,%o2,%o1 // %o1 = &yptr[count]
810 ldx [%o0+%o2],%o3 // nächstes Digit holen
811 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
812 subcc %o3,%o4,%g0 // vergleichen
814 _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
816 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
819 3: subcc %o3,%o4,%g0 // nochmals vergleichen
823 _ sra %o0,0,%o0 // sign-extend %o0
826 #if CL_DS_BIG_ENDIAN_P
828 // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
829 DECLARE_FUNCTION(add_loop_down)
830 C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
832 // srl %o3,0,%o3 // zero-extend %o3 = count
834 _ mov %g0,%g1 // Carry := 0
836 1: ldx [%o0],%o4 // source1-digit
838 ldx [%o1],%o5 // source2-digit
840 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
842 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
844 stx %o4,[%o2] // Digit ablegen
852 // srl %o3,0,%o3 // zero-extend %o3 = count
854 _ mov %g0,%g1 // Carry := 0
857 sllx %o3,3,%o3 // %o3 = 8*count
858 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
859 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
860 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
861 1: ldx [%o0+%o3],%o4 // source1-digit
862 ldx [%o1+%o3],%o5 // source2-digit
864 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
866 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
869 _ stx %o4,[%o2+%o3] // Digit ablegen
874 // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
875 DECLARE_FUNCTION(addto_loop_down)
876 C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
878 // srl %o2,0,%o2 // zero-extend %o2 = count
880 _ mov %g0,%o5 // Carry := 0
882 1: ldx [%o0],%o3 // source-digit
884 ldx [%o1],%o4 // dest-digit
886 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
888 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
889 stx %o4,[%o1] // Digit ablegen
897 // srl %o2,0,%o2 // zero-extend %o2 = count
899 _ mov %g0,%o5 // Carry := 0
902 sllx %o2,3,%o2 // %o2 = 8*count
903 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
904 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
905 ldx [%o0+%o2],%o3 // source-digit
906 1: ldx [%o1+%o2],%o4 // dest-digit
908 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
910 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
911 stx %o4,[%o1+%o2] // Digit ablegen
914 __ ldx [%o0+%o2],%o3 // source-digit
919 // extern uintD inc_loop_down (uintD* ptr, uintC count);
920 DECLARE_FUNCTION(inc_loop_down)
921 C(inc_loop_down:) // Input in %o0,%o1, Output in %o0
923 // srl %o1,0,%o1 // zero-extend %o1 = count
939 // srl %o1,0,%o1 // zero-extend %o1 = count
942 sllx %o1,3,%o1 // %o1 = 8*count
943 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
944 ldx [%o0+%o1],%o2 // digit holen
945 1: addcc %o2,1,%o2 // incrementieren
947 _ stx %o2,[%o0+%o1] // ablegen
948 subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
957 // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
958 DECLARE_FUNCTION(sub_loop_down)
959 C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
961 // srl %o3,0,%o3 // zero-extend %o3 = count
963 _ mov %g0,%g1 // Carry := 0
965 1: ldx [%o1],%o5 // source2-digit
967 ldx [%o0],%o4 // source1-digit
969 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
971 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
973 stx %o4,[%o2] // Digit ablegen
981 // srl %o3,0,%o3 // zero-extend %o3 = count
983 _ mov %g0,%g1 // Carry := 0
986 sllx %o3,3,%o3 // %o3 = 8*count
987 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
988 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
989 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
990 1: ldx [%o0+%o3],%o4 // source1-digit
991 ldx [%o1+%o3],%o5 // source2-digit
993 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
995 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
998 _ stx %o4,[%o2+%o3] // Digit ablegen
1003 // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
1004 DECLARE_FUNCTION(subx_loop_down)
1005 C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
1007 // srl %o3,0,%o3 // zero-extend %o3 = count
1009 _ mov %o4,%g1 // Carry (0 oder -1)
1011 1: ldx [%o1],%o5 // source2-digit
1013 ldx [%o0],%o4 // source1-digit
1015 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
1017 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
1019 stx %o4,[%o2] // Digit ablegen
1027 // srl %o3,0,%o3 // zero-extend %o3 = count
1029 _ mov %o4,%g1 // Carry (0 oder -1)
1032 sllx %o3,3,%o3 // %o3 = 8*count
1033 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
1034 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
1035 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
1036 1: ldx [%o1+%o3],%o5 // source2-digit
1037 ldx [%o0+%o3],%o4 // source1-digit
1039 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
1041 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
1044 _ stx %o4,[%o2+%o3] // Digit ablegen
1049 // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
1050 DECLARE_FUNCTION(subfrom_loop_down)
1051 C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1053 // srl %o2,0,%o2 // zero-extend %o2 = count
1055 _ mov %g0,%o5 // Carry := 0
1057 1: ldx [%o0],%o3 // source-digit
1059 ldx [%o1],%o4 // dest-digit
1061 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1063 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
1064 stx %o4,[%o1] // Digit ablegen
1072 // srl %o2,0,%o2 // zero-extend %o2 = count
1074 _ mov %g0,%o5 // Carry := 0
1077 sllx %o2,3,%o2 // %o2 = 8*count
1078 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
1079 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
1080 ldx [%o0+%o2],%o3 // source-digit
1081 1: ldx [%o1+%o2],%o4 // dest-digit
1083 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1085 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
1086 stx %o4,[%o1+%o2] // Digit ablegen
1089 __ ldx [%o0+%o2],%o3 // source-digit
1094 // extern uintD dec_loop_down (uintD* ptr, uintC count);
1095 DECLARE_FUNCTION(dec_loop_down)
1096 C(dec_loop_down:) // Input in %o0,%o1, Output in %o0
1098 // srl %o1,0,%o1 // zero-extend %o1 = count
1114 // srl %o1,0,%o1 // zero-extend %o1 = count
1117 sllx %o1,3,%o1 // %o1 = 8*count
1118 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
1119 ldx [%o0+%o1],%o2 // digit holen
1120 1: subcc %o2,1,%o2 // decrementieren
1122 _ stx %o2,[%o0+%o1] // ablegen
1123 subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1125 __ ldx [%o0+%o1],%o2
1132 // extern uintD neg_loop_down (uintD* ptr, uintC count);
1133 DECLARE_FUNCTION(neg_loop_down)
1134 C(neg_loop_down:) // Input in %o0,%o1, Output in %o0
1136 // srl %o1,0,%o1 // zero-extend %o1 = count
1137 // erstes Digit /=0 suchen:
1148 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1149 stx %o2,[%o0] // 1 Digit negieren
1150 // alle anderen Digits invertieren:
1163 // srl %o1,0,%o1 // zero-extend %o1 = count
1164 // erstes Digit /=0 suchen:
1167 sllx %o1,3,%o1 // %o1 = 8*count
1168 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
1169 ldx [%o0+%o1],%o2 // digit holen
1170 1: subcc %g0,%o2,%o2 // negieren, testen
1172 _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1174 __ ldx [%o0+%o1],%o2
1177 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1178 // alle anderen Digits invertieren:
1180 stx %o2,[%o0+%o1] // ablegen
1189 __ ldx [%o0+%o1],%o2
1194 // extern uintD shift1left_loop_down (uintD* ptr, uintC count);
1195 DECLARE_FUNCTION(shift1left_loop_down)
1196 C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0
1197 // srl %o1,0,%o1 // zero-extend %o1 = count
1199 _ mov 0,%o3 // Carry := 0
1201 1: ldx [%o0],%o2 // Digit
1202 addcc %o2,%o2,%o4 // shiften
1203 add %o4,%o3,%o4 // und carry
1204 srlx %o2,63,%o3 // neues Carry
1205 stx %o4,[%o0] // Digit ablegen
1212 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
1213 DECLARE_FUNCTION(shiftleft_loop_down)
1214 C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1215 // srl %o1,0,%o1 // zero-extend %o1 = count
1217 _ sub %g0,%o2,%g1 // 64-i (mod 64)
1219 1: ldx [%o0],%o4 // Digit
1221 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits
1222 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
1223 stx %o5,[%o0] // Digit ablegen
1224 srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
1230 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
1231 DECLARE_FUNCTION(shiftleftcopy_loop_down)
1232 C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
1233 // srl %o2,0,%o2 // zero-extend %o2 = count
1235 _ mov 0,%o4 // Carry := 0
1236 sub %g0,%o3,%g1 // 64-i (mod 64)
1238 1: ldx [%o0],%o5 // Digit
1240 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
1241 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
1243 stx %g2,[%o1] // Digit ablegen
1244 srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
1250 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
1251 DECLARE_FUNCTION(shift1right_loop_up)
1252 C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1253 // srl %o1,0,%o1 // zero-extend %o1 = count
1255 _ sllx %o2,63,%o2 // Carry
1256 1: ldx [%o0],%o3 // Digit
1258 srlx %o3,1,%o4 // shiften
1259 or %o2,%o4,%o4 // und mit altem Carry kombinieren
1260 stx %o4,[%o0] // und ablegen
1261 sllx %o3,63,%o2 // neuer Carry
1267 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
1268 DECLARE_FUNCTION(shiftright_loop_up)
1269 C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
1270 // srl %o1,0,%o1 // zero-extend %o1 = count
1271 sub %g0,%o2,%g1 // 64-i (mod 64)
1273 _ or %g0,%g0,%o3 // Carry := 0
1274 1: ldx [%o0],%o4 // Digit
1276 srlx %o4,%o2,%o5 // shiften
1277 or %o3,%o5,%o5 // und mit altem Carry kombinieren
1278 stx %o5,[%o0] // und ablegen
1279 sllx %o4,%g1,%o3 // neuer Carry
1285 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
1286 DECLARE_FUNCTION(shiftrightsigned_loop_up)
1287 C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
1288 // srl %o1,0,%o1 // zero-extend %o1 = count
1289 ldx [%o0],%o4 // erstes Digit
1290 sub %g0,%o2,%g1 // 64-i (mod 64)
1291 srax %o4,%o2,%o5 // shiften
1292 stx %o5,[%o0] // und ablegen
1293 sllx %o4,%g1,%o3 // neuer Carry
1297 1: ldx [%o0],%o4 // Digit
1299 srlx %o4,%o2,%o5 // shiften
1300 or %o3,%o5,%o5 // und mit altem Carry kombinieren
1301 stx %o5,[%o0] // und ablegen
1302 sllx %o4,%g1,%o3 // neuer Carry
1308 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
1309 DECLARE_FUNCTION(shiftrightcopy_loop_up)
1310 C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
1311 // srl %o2,0,%o2 // zero-extend %o2 = count
1312 sub %g0,%o3,%g1 // 64-i (mod 64)
1314 _ sllx %o4,%g1,%g2 // erster Carry
1315 1: ldx [%o0],%o4 // Digit
1317 srlx %o4,%o3,%o5 // shiften
1318 or %g2,%o5,%o5 // und mit altem Carry kombinieren
1319 stx %o5,[%o1] // und ablegen
1320 sllx %o4,%g1,%g2 // neuer Carry
1327 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
1328 DECLARE_FUNCTION(mulusmall_loop_down)
1329 C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
1330 // srl %o2,0,%o2 // zero-extend %o2 = len
1333 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
1334 // und kleinen Carry %o3 dazu:
1337 srlx %o4,32,%o5 // high32(x)
1338 srl %o4,0,%o4 // low32(x)
1339 mulx %o4,%o0,%o4 // low32(x)*digit
1340 mulx %o5,%o0,%o5 // high32(x)*digit
1341 sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32
1342 add %g1,%o3,%g1 // plus carry
1343 addcc %o4,%g1,%o4 // plus low32(x)*digit
1344 srlx %o5,32,%o3 // high32(high32(x)*digit)
1346 movcs %xcc,%g1,%o3 // neuer Carry
1347 stx %o4,[%o1] // neues Digit ablegen
1353 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1354 DECLARE_FUNCTION(mulu_loop_down)
1355 C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
1358 srlx %i0,32,%l1 // %l1 = high32(digit)
1359 srl %i0,0,%l2 // %l2 = low32(digit)
1361 sllx %l3,32,%l3 // %l3 = 2^32
1362 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1364 ldx [%i1+%i2],%o0 // nächstes Digit
1366 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1369 mulx %l1,%o1,%o3 // high part
1370 mulx %l1,%o2,%o4 // first mid part
1371 mulx %l2,%o1,%o1 // second mid part
1372 mulx %l2,%o2,%o2 // low part
1373 srlx %o2,32,%o5 // low part's upper half
1374 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1375 addcc %o4,%o1,%o4 // add other mid part
1377 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1381 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1382 addcc %o0,%l0,%o0 // alten Carry addieren
1383 add %o3,%o5,%l0 // add high32(midparts) to high part
1385 movcs %xcc,%o5,%l0 // neuer Carry
1386 // Multiplikation fertig
1388 _ stx %o0,[%i2] // Low-Digit ablegen
1389 stx %l0,[%i2-8] // letzten Carry ablegen
1393 // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1394 DECLARE_FUNCTION(muluadd_loop_down)
1395 C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
1398 srlx %i0,32,%l1 // %l1 = high32(digit)
1399 srl %i0,0,%l2 // %l2 = low32(digit)
1401 sllx %l3,32,%l3 // %l3 = 2^32
1402 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1404 ldx [%i1+%i2],%o0 // nächstes Digit
1405 ldx [%i2],%i4 // *destptr
1407 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1410 mulx %l1,%o1,%o3 // high part
1411 mulx %l1,%o2,%o4 // first mid part
1412 mulx %l2,%o1,%o1 // second mid part
1413 mulx %l2,%o2,%o2 // low part
1414 srlx %o2,32,%o5 // low part's upper half
1415 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1416 addcc %o4,%o1,%o4 // add other mid part
1418 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1422 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1423 addcc %o0,%l0,%o0 // alten Carry addieren
1424 add %o3,%o5,%l0 // add high32(midparts) to high part
1426 movcs %xcc,%o5,%l0 // neuer Carry
1427 // Multiplikation fertig
1428 addcc %i4,%o0,%o0 // alten *destptr addieren
1430 movcs %xcc,%o2,%l0 // neuer Carry
1432 _ stx %o0,[%i2] // Low-Digit ablegen
1433 mov %l0,%i0 // letzter Carry
1437 // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1438 DECLARE_FUNCTION(mulusub_loop_down)
1439 C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
1442 srlx %i0,32,%l1 // %l1 = high32(digit)
1443 srl %i0,0,%l2 // %l2 = low32(digit)
1445 sllx %l3,32,%l3 // %l3 = 2^32
1446 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1448 ldx [%i1+%i2],%o0 // nächstes Digit
1449 ldx [%i2],%i4 // *destptr
1451 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1454 mulx %l1,%o1,%o3 // high part
1455 mulx %l1,%o2,%o4 // first mid part
1456 mulx %l2,%o1,%o1 // second mid part
1457 mulx %l2,%o2,%o2 // low part
1458 srlx %o2,32,%o5 // low part's upper half
1459 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1460 addcc %o4,%o1,%o4 // add other mid part
1462 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1466 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1467 addcc %o0,%l0,%o0 // alten Carry addieren
1468 add %o3,%o5,%l0 // add high32(midparts) to high part
1470 movcs %xcc,%o5,%l0 // neuer Carry
1471 // Multiplikation fertig
1472 subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren
1474 movcs %xcc,%o2,%l0 // neuer Carry
1476 _ stx %o0,[%i2] // Low-Digit ablegen
1477 mov %l0,%i0 // letzter Carry
1483 #if !CL_DS_BIG_ENDIAN_P
1485 // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
1486 DECLARE_FUNCTION(or_loop_down)
1487 C(or_loop_down:) // Input in %o0,%o1,%o2
1489 // srl %o2,0,%o2 // zero-extend %o2 = count
1491 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1493 1: ldx [%o0],%o3 // *xptr
1494 ldx [%o0+%o1],%o4 // *yptr
1496 or %o3,%o4,%o3 // verknüpfen
1497 stx %o3,[%o0] // =: *xptr
1499 _ sub %o0,8,%o0 // xptr++, yptr++
1504 // srl %o2,0,%o2 // zero-extend %o2 = count
1506 _ sllx %o2,3,%o2 // %o2 = 8*count
1507 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1508 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1509 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1510 ldx [%o1+%o2],%o3 // nächstes Digit holen
1511 ldx [%o0+%o2],%o4 // noch ein Digit holen
1512 or %o4,%o3,%o3 // beide verknüpfen
1514 _ stx %o3,[%o1+%o2] // Digit ablegen
1519 // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1520 DECLARE_FUNCTION(xor_loop_down)
1521 C(xor_loop_down:) // Input in %o0,%o1,%o2
1523 // srl %o2,0,%o2 // zero-extend %o2 = count
1525 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1527 1: ldx [%o0],%o3 // *xptr
1528 ldx [%o0+%o1],%o4 // *yptr
1530 xor %o3,%o4,%o3 // verknüpfen
1531 stx %o3,[%o0] // =: *xptr
1533 _ sub %o0,8,%o0 // xptr++, yptr++
1538 // srl %o2,0,%o2 // zero-extend %o2 = count
1540 _ sllx %o2,3,%o2 // %o2 = 8*count
1541 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1542 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1543 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1544 ldx [%o1+%o2],%o3 // nächstes Digit holen
1545 ldx [%o0+%o2],%o4 // noch ein Digit holen
1546 xor %o4,%o3,%o3 // beide verknüpfen
1548 _ stx %o3,[%o1+%o2] // Digit ablegen
1553 // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
1554 DECLARE_FUNCTION(and_loop_down)
1555 C(and_loop_down:) // Input in %o0,%o1,%o2
1557 // srl %o2,0,%o2 // zero-extend %o2 = count
1559 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1561 1: ldx [%o0],%o3 // *xptr
1562 ldx [%o0+%o1],%o4 // *yptr
1564 and %o3,%o4,%o3 // verknüpfen
1565 stx %o3,[%o0] // =: *xptr
1567 _ sub %o0,8,%o0 // xptr++, yptr++
1572 // srl %o2,0,%o2 // zero-extend %o2 = count
1574 _ sllx %o2,3,%o2 // %o2 = 8*count
1575 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1576 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1577 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1578 ldx [%o1+%o2],%o3 // nächstes Digit holen
1579 ldx [%o0+%o2],%o4 // noch ein Digit holen
1580 and %o4,%o3,%o3 // beide verknüpfen
1582 _ stx %o3,[%o1+%o2] // Digit ablegen
1587 // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
1588 DECLARE_FUNCTION(eqv_loop_down)
1589 C(eqv_loop_down:) // Input in %o0,%o1,%o2
1591 // srl %o2,0,%o2 // zero-extend %o2 = count
1593 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1595 1: ldx [%o0],%o3 // *xptr
1596 ldx [%o0+%o1],%o4 // *yptr
1598 xnor %o3,%o4,%o3 // verknüpfen
1599 stx %o3,[%o0] // =: *xptr
1601 _ sub %o0,8,%o0 // xptr++, yptr++
1606 // srl %o2,0,%o2 // zero-extend %o2 = count
1608 _ sllx %o2,3,%o2 // %o2 = 8*count
1609 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1610 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1611 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1612 ldx [%o1+%o2],%o3 // nächstes Digit holen
1613 ldx [%o0+%o2],%o4 // noch ein Digit holen
1614 xnor %o4,%o3,%o3 // beide verknüpfen
1616 _ stx %o3,[%o1+%o2] // Digit ablegen
1621 // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
1622 DECLARE_FUNCTION(nand_loop_down)
1623 C(nand_loop_down:) // Input in %o0,%o1,%o2
1625 // srl %o2,0,%o2 // zero-extend %o2 = count
1627 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1629 1: ldx [%o0],%o3 // *xptr
1630 ldx [%o0+%o1],%o4 // *yptr
1632 and %o3,%o4,%o3 // verknüpfen
1634 stx %o3,[%o0] // =: *xptr
1636 _ sub %o0,8,%o0 // xptr++, yptr++
1641 // srl %o2,0,%o2 // zero-extend %o2 = count
1643 _ sllx %o2,3,%o2 // %o2 = 8*count
1644 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1645 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1646 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1647 ldx [%o1+%o2],%o3 // nächstes Digit holen
1648 ldx [%o0+%o2],%o4 // noch ein Digit holen
1649 and %o4,%o3,%o3 // beide verknüpfen
1652 _ stx %o3,[%o1+%o2] // Digit ablegen
1657 // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1658 DECLARE_FUNCTION(nor_loop_down)
1659 C(nor_loop_down:) // Input in %o0,%o1,%o2
1661 // srl %o2,0,%o2 // zero-extend %o2 = count
1663 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1665 1: ldx [%o0],%o3 // *xptr
1666 ldx [%o0+%o1],%o4 // *yptr
1668 or %o3,%o4,%o3 // verknüpfen
1670 stx %o3,[%o0] // =: *xptr
1672 _ sub %o0,8,%o0 // xptr++, yptr++
1677 // srl %o2,0,%o2 // zero-extend %o2 = count
1679 _ sllx %o2,3,%o2 // %o2 = 8*count
1680 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1681 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1682 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1683 ldx [%o1+%o2],%o3 // nächstes Digit holen
1684 ldx [%o0+%o2],%o4 // noch ein Digit holen
1685 or %o4,%o3,%o3 // beide verknüpfen
1688 _ stx %o3,[%o1+%o2] // Digit ablegen
1693 // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1694 DECLARE_FUNCTION(andc2_loop_down)
1695 C(andc2_loop_down:) // Input in %o0,%o1,%o2
1697 // srl %o2,0,%o2 // zero-extend %o2 = count
1699 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1701 1: ldx [%o0],%o3 // *xptr
1702 ldx [%o0+%o1],%o4 // *yptr
1704 andn %o3,%o4,%o3 // verknüpfen
1705 stx %o3,[%o0] // =: *xptr
1707 _ sub %o0,8,%o0 // xptr++, yptr++
1712 // srl %o2,0,%o2 // zero-extend %o2 = count
1714 _ sllx %o2,3,%o2 // %o2 = 8*count
1715 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1716 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1717 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1718 ldx [%o1+%o2],%o3 // nächstes Digit holen
1719 ldx [%o0+%o2],%o4 // noch ein Digit holen
1720 andn %o4,%o3,%o3 // beide verknüpfen
1722 _ stx %o3,[%o1+%o2] // Digit ablegen
1727 // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1728 DECLARE_FUNCTION(orc2_loop_down)
1729 C(orc2_loop_down:) // Input in %o0,%o1,%o2
1731 // srl %o2,0,%o2 // zero-extend %o2 = count
1733 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1735 1: ldx [%o0],%o3 // *xptr
1736 ldx [%o0+%o1],%o4 // *yptr
1738 orn %o3,%o4,%o3 // verknüpfen
1739 stx %o3,[%o0] // =: *xptr
1741 _ sub %o0,8,%o0 // xptr++, yptr++
1746 // srl %o2,0,%o2 // zero-extend %o2 = count
1748 _ sllx %o2,3,%o2 // %o2 = 8*count
1749 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1750 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1751 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1752 ldx [%o1+%o2],%o3 // nächstes Digit holen
1753 ldx [%o0+%o2],%o4 // noch ein Digit holen
1754 orn %o4,%o3,%o3 // beide verknüpfen
1756 _ stx %o3,[%o1+%o2] // Digit ablegen
1761 // extern void not_loop_down (uintD* xptr, uintC count);
1762 DECLARE_FUNCTION(not_loop_down)
1763 C(not_loop_down:) // Input in %o0,%o1
1765 // srl %o1,0,%o1 // zero-extend %o1 = count
1778 // srl %o1,0,%o1 // zero-extend %o1 = count
1780 _ sllx %o1,3,%o1 // %o1 = 8*count
1781 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
1782 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1783 ldx [%o0+%o1],%o2 // nächstes Digit holen
1786 _ stx %o2,[%o0+%o1] // Digit ablegen
1791 // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
1792 DECLARE_FUNCTION(and_test_loop_down)
1793 C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1795 // srl %o2,0,%o2 // zero-extend %o2 = count
1814 // srl %o2,0,%o2 // zero-extend %o2 = count
1815 sllx %o2,3,%o2 // %o2 = 8*count
1816 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1817 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1821 ldx [%o0+%o2],%o3 // nächstes Digit holen
1822 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
1823 andcc %o3,%o4,%g0 // beide verknüpfen
1825 _ subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1827 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
1834 // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
1835 DECLARE_FUNCTION(compare_loop_down)
1836 C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1838 // srl %o2,0,%o2 // zero-extend %o2 = count
1854 _ sra %o0,0,%o0 // sign-extend %o0
1857 // srl %o2,0,%o2 // zero-extend %o2 = count
1858 sllx %o2,3,%o2 // %o2 = 8*count
1859 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1860 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1864 ldx [%o0+%o2],%o3 // nächstes Digit holen
1865 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
1866 subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1868 _ subcc %o3,%o4,%g0 // vergleichen
1870 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
1874 _ sra %o0,0,%o0 // sign-extend %o0
1881 // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1882 DECLARE_FUNCTION(add_loop_up)
1883 C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1885 // srl %o3,0,%o3 // zero-extend %o3 = count
1887 _ mov %g0,%g1 // Carry := 0
1888 1: ldx [%o0],%o4 // source1-digit
1890 ldx [%o1],%o5 // source2-digit
1893 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
1895 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
1896 stx %o4,[%o2] // Digit ablegen
1904 // srl %o3,0,%o3 // zero-extend %o3 = count
1906 _ mov %g0,%g1 // Carry := 0
1907 sub %g0,%o3,%o3 // %o3 = -count
1908 sllx %o3,3,%o3 // %o3 = -8*count
1910 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
1911 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
1912 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
1913 1: ldx [%o0+%o3],%o4 // source1-digit
1914 ldx [%o1+%o3],%o5 // source2-digit
1916 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
1918 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
1919 addcc %o3,8,%o3 // Zähler erniedrigen, Pointer erhöhen
1921 _ stx %o4,[%o2+%o3] // Digit ablegen
1926 // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
1927 DECLARE_FUNCTION(addto_loop_up)
1928 C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1930 // srl %o2,0,%o2 // zero-extend %o2 = count
1932 _ mov %g0,%o5 // Carry := 0
1933 1: ldx [%o0],%o3 // source-digit
1935 ldx [%o1],%o4 // dest-digit
1937 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1939 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
1940 stx %o4,[%o1] // Digit ablegen
1948 // srl %o2,0,%o2 // zero-extend %o2 = count
1950 _ mov %g0,%o5 // Carry := 0
1951 sub %g0,%o2,%o2 // %o2 = -count
1952 sllx %o2,3,%o2 // %o2 = -8*count
1953 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
1954 sub %o1,%o2,%o1 // %o1 = &destptr[count]
1955 ldx [%o0+%o2],%o3 // source-digit
1956 1: ldx [%o1+%o2],%o4 // dest-digit
1958 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1960 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
1961 stx %o4,[%o1+%o2] // Digit ablegen
1962 addcc %o2,8,%o2 // Zähler erniedrigen, Pointer erhöhen
1964 __ ldx [%o0+%o2],%o3 // source-digit
1969 // extern uintD inc_loop_up (uintD* ptr, uintC count);
1970 DECLARE_FUNCTION(inc_loop_up)
1971 C(inc_loop_up:) // Input in %o0,%o1, Output in %o0
1973 // srl %o1,0,%o1 // zero-extend %o1 = count
1990 // srl %o1,0,%o1 // zero-extend %o1 = count
1992 _ sub %g0,%o1,%o1 // %o1 = -count
1993 sllx %o1,3,%o1 // %o1 = -8*count
1994 sub %o0,%o1,%o0 // %o0 = &ptr[count]
1995 ldx [%o0+%o1],%o2 // digit holen
1996 1: addcc %o2,1,%o2 // incrementieren
1998 _ stx %o2,[%o0+%o1] // ablegen
1999 addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2001 __ ldx [%o0+%o1],%o2
2008 // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
2009 DECLARE_FUNCTION(sub_loop_up)
2010 C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2012 // srl %o3,0,%o3 // zero-extend %o3 = count
2014 _ mov %g0,%g1 // Carry := 0
2015 1: ldx [%o0],%o4 // source1-digit
2017 ldx [%o1],%o5 // source2-digit
2020 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
2022 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
2023 stx %o4,[%o2] // Digit ablegen
2031 // srl %o3,0,%o3 // zero-extend %o3 = count
2033 _ mov %g0,%g1 // Carry := 0
2034 sub %g0,%o3,%o3 // %o3 = -count
2035 sllx %o3,3,%o3 // %o3 = -8*count
2037 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
2038 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
2039 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
2040 1: ldx [%o1+%o3],%o5 // source2-digit
2041 ldx [%o0+%o3],%o4 // source1-digit
2043 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
2045 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
2048 _ stx %o4,[%o2+%o3] // Digit ablegen
2053 // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
2054 DECLARE_FUNCTION(subx_loop_up)
2055 C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
2057 // srl %o3,0,%o3 // zero-extend %o3 = count
2059 _ mov %o4,%g1 // Carry (0 oder -1)
2060 1: ldx [%o0],%o4 // source1-digit
2062 ldx [%o1],%o5 // source2-digit
2065 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
2067 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
2068 stx %o4,[%o2] // Digit ablegen
2076 // srl %o3,0,%o3 // zero-extend %o3 = count
2078 _ mov %o4,%g1 // Carry (0 oder -1)
2079 sub %g0,%o3,%o3 // %o3 = -count
2080 sllx %o3,3,%o3 // %o3 = -8*count
2082 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
2083 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
2084 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
2085 1: ldx [%o1+%o3],%o5 // source2-digit
2086 ldx [%o0+%o3],%o4 // source1-digit
2088 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
2090 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
2093 _ stx %o4,[%o2+%o3] // Digit ablegen
2098 // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
2099 DECLARE_FUNCTION(subfrom_loop_up)
2100 C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
2102 // srl %o2,0,%o2 // zero-extend %o2 = count
2104 _ mov %g0,%o5 // Carry := 0
2105 1: ldx [%o0],%o3 // source-digit
2107 ldx [%o1],%o4 // dest-digit
2109 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
2111 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
2112 stx %o4,[%o1] // Digit ablegen
2120 // srl %o2,0,%o2 // zero-extend %o2 = count
2122 _ mov %g0,%o5 // Carry := 0
2123 sub %g0,%o2,%o2 // %o2 = -count
2124 sllx %o2,3,%o2 // %o2 = -8*count
2125 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
2126 sub %o1,%o2,%o1 // %o1 = &destptr[count]
2127 ldx [%o0+%o2],%o3 // source-digit
2128 1: ldx [%o1+%o2],%o4 // dest-digit
2130 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
2132 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
2133 stx %o4,[%o1+%o2] // Digit ablegen
2136 __ ldx [%o0+%o2],%o3 // source-digit
2141 // extern uintD dec_loop_up (uintD* ptr, uintC count);
2142 DECLARE_FUNCTION(dec_loop_up)
2143 C(dec_loop_up:) // Input in %o0,%o1, Output in %o0
2145 // srl %o1,0,%o1 // zero-extend %o1 = count
2162 // srl %o1,0,%o1 // zero-extend %o1 = count
2164 _ sub %g0,%o1,%o1 // %o1 = -count
2165 sllx %o1,3,%o1 // %o1 = -8*count
2166 sub %o0,%o1,%o0 // %o0 = &ptr[count]
2167 ldx [%o0+%o1],%o2 // digit holen
2168 1: subcc %o2,1,%o2 // decrementieren
2170 _ stx %o2,[%o0+%o1] // ablegen
2171 addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2173 __ ldx [%o0+%o1],%o2
2180 // extern uintD neg_loop_up (uintD* ptr, uintC count);
2181 DECLARE_FUNCTION(neg_loop_up)
2182 C(neg_loop_up:) // Input in %o0,%o1, Output in %o0
2184 // srl %o1,0,%o1 // zero-extend %o1 = count
2185 // erstes Digit /=0 suchen:
2196 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2197 // 1 Digit negieren, alle anderen Digits invertieren:
2210 // srl %o1,0,%o1 // zero-extend %o1 = count
2211 // erstes Digit /=0 suchen:
2213 _ sub %g0,%o1,%o1 // %o1 = -count
2214 sllx %o1,3,%o1 // %o1 = -8*count
2215 sub %o0,%o1,%o0 // %o0 = &ptr[count]
2216 ldx [%o0+%o1],%o2 // digit holen
2217 1: subcc %g0,%o2,%o2 // negieren, testen
2219 _ addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2221 __ ldx [%o0+%o1],%o2
2224 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2225 // alle anderen Digits invertieren:
2227 stx %o2,[%o0+%o1] // ablegen
2236 __ ldx [%o0+%o1],%o2
2241 // extern uintD shift1left_loop_up (uintD* ptr, uintC count);
2242 DECLARE_FUNCTION(shift1left_loop_up)
2243 C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0
2244 // srl %o1,0,%o1 // zero-extend %o1 = count
2246 _ mov 0,%o3 // Carry := 0
2247 1: ldx [%o0],%o2 // Digit
2248 addcc %o2,%o2,%o4 // shiften
2249 add %o4,%o3,%o4 // und carry
2250 srlx %o2,63,%o3 // neues Carry
2251 stx %o4,[%o0] // Digit ablegen
2258 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
2259 DECLARE_FUNCTION(shiftleft_loop_up)
2260 C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2261 // srl %o1,0,%o1 // zero-extend %o1 = count
2263 _ sub %g0,%o2,%g1 // 64-i (mod 64)
2264 1: ldx [%o0],%o4 // Digit
2266 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits
2267 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
2268 stx %o5,[%o0] // Digit ablegen
2269 srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
2277 // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
2278 DECLARE_FUNCTION(shiftleftcopy_loop_up)
2279 C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
2280 // srl %o2,0,%o2 // zero-extend %o2 = count
2282 _ mov 0,%o4 // Carry := 0
2283 sub %g0,%o3,%g1 // 64-i (mod 64)
2284 1: ldx [%o0],%o5 // Digit
2286 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
2287 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
2288 stx %g2,[%o1] // Digit ablegen
2290 srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
2296 #if !CL_DS_BIG_ENDIAN_P
2298 // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
2299 DECLARE_FUNCTION(shift1right_loop_down)
2300 C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
2301 // srl %o1,0,%o1 // zero-extend %o1 = count
2303 _ sllx %o2,63,%o2 // Carry
2305 1: ldx [%o0],%o3 // Digit
2307 srlx %o3,1,%o4 // shiften
2308 or %o2,%o4,%o4 // und mit altem Carry kombinieren
2309 stx %o4,[%o0] // und ablegen
2310 sllx %o3,63,%o2 // neuer Carry
2316 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
2317 DECLARE_FUNCTION(shiftright_loop_down)
2318 C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2319 // srl %o1,0,%o1 // zero-extend %o1 = count
2320 sub %g0,%o2,%g1 // 64-i (mod 64)
2322 _ or %g0,%g0,%o3 // Carry := 0
2324 1: ldx [%o0],%o4 // Digit
2326 srlx %o4,%o2,%o5 // shiften
2327 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2328 stx %o5,[%o0] // und ablegen
2329 sllx %o4,%g1,%o3 // neuer Carry
2335 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
2336 DECLARE_FUNCTION(shiftrightsigned_loop_down)
2337 C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2338 // srl %o1,0,%o1 // zero-extend %o1 = count
2339 ldx [%o0-8],%o4 // erstes Digit
2340 sub %g0,%o2,%g1 // 64-i (mod 64)
2341 srax %o4,%o2,%o5 // shiften
2342 stx %o5,[%o0-8] // und ablegen
2343 sllx %o4,%g1,%o3 // neuer Carry
2347 1: ldx [%o0],%o4 // Digit
2349 srlx %o4,%o2,%o5 // shiften
2350 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2351 stx %o5,[%o0] // und ablegen
2352 sllx %o4,%g1,%o3 // neuer Carry
2358 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
2359 DECLARE_FUNCTION(shiftrightcopy_loop_down)
2360 C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
2361 // srl %o2,0,%o2 // zero-extend %o2 = count
2362 sub %g0,%o3,%g1 // 64-i (mod 64)
2364 _ sllx %o4,%g1,%g2 // erster Carry
2366 1: ldx [%o0],%o4 // Digit
2368 srlx %o4,%o3,%o5 // shiften
2369 or %g2,%o5,%o5 // und mit altem Carry kombinieren
2370 stx %o5,[%o1] // und ablegen
2371 sllx %o4,%g1,%g2 // neuer Carry
2378 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
2379 DECLARE_FUNCTION(mulusmall_loop_up)
2380 C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
2381 // srl %o2,0,%o2 // zero-extend %o2 = len
2384 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
2385 // und kleinen Carry %o3 dazu:
2388 srlx %o4,32,%o5 // high32(x)
2389 srl %o4,0,%o4 // low32(x)
2390 mulx %o4,%o0,%o4 // low32(x)*digit
2391 mulx %o5,%o0,%o5 // high32(x)*digit
2392 sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32
2393 add %g1,%o3,%g1 // plus carry
2394 addcc %o4,%g1,%o4 // plus low32(x)*digit
2395 srlx %o5,32,%o3 // high32(high32(x)*digit)
2397 movcs %xcc,%g1,%o3 // neuer Carry
2398 stx %o4,[%o1] // neues Digit ablegen
2404 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2405 DECLARE_FUNCTION(mulu_loop_up)
2406 C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
2409 srlx %i0,32,%l1 // %l1 = high32(digit)
2410 srl %i0,0,%l2 // %l2 = low32(digit)
2412 sllx %l3,32,%l3 // %l3 = 2^32
2413 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2414 1: ldx [%i1+%i2],%o0 // nächstes Digit
2416 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2419 mulx %l1,%o1,%o3 // high part
2420 mulx %l1,%o2,%o4 // first mid part
2421 mulx %l2,%o1,%o1 // second mid part
2422 mulx %l2,%o2,%o2 // low part
2423 srlx %o2,32,%o5 // low part's upper half
2424 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2425 addcc %o4,%o1,%o4 // add other mid part
2427 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2431 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2432 addcc %o0,%l0,%o0 // alten Carry addieren
2433 add %o3,%o5,%l0 // add high32(midparts) to high part
2435 movcs %xcc,%o5,%l0 // neuer Carry
2436 // Multiplikation fertig
2437 stx %o0,[%i2] // Low-Digit ablegen
2440 stx %l0,[%i2] // letzten Carry ablegen
2444 // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2445 DECLARE_FUNCTION(muluadd_loop_up)
2446 C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2449 srlx %i0,32,%l1 // %l1 = high32(digit)
2450 srl %i0,0,%l2 // %l2 = low32(digit)
2452 sllx %l3,32,%l3 // %l3 = 2^32
2453 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2454 1: ldx [%i1+%i2],%o0 // nächstes Digit
2455 ldx [%i2],%i4 // *destptr
2457 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2460 mulx %l1,%o1,%o3 // high part
2461 mulx %l1,%o2,%o4 // first mid part
2462 mulx %l2,%o1,%o1 // second mid part
2463 mulx %l2,%o2,%o2 // low part
2464 srlx %o2,32,%o5 // low part's upper half
2465 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2466 addcc %o4,%o1,%o4 // add other mid part
2468 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2472 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2473 addcc %o0,%l0,%o0 // alten Carry addieren
2474 add %o3,%o5,%l0 // add high32(midparts) to high part
2476 movcs %xcc,%o5,%l0 // neuer Carry
2477 // Multiplikation fertig
2478 addcc %i4,%o0,%o0 // alten *destptr addieren
2480 movcs %xcc,%o2,%l0 // neuer Carry
2481 stx %o0,[%i2] // Low-Digit ablegen
2484 mov %l0,%i0 // letzter Carry
2488 // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2489 DECLARE_FUNCTION(mulusub_loop_up)
2490 C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2493 srlx %i0,32,%l1 // %l1 = high32(digit)
2494 srl %i0,0,%l2 // %l2 = low32(digit)
2496 sllx %l3,32,%l3 // %l3 = 2^32
2497 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2498 1: ldx [%i1+%i2],%o0 // nächstes Digit
2499 ldx [%i2],%i4 // *destptr
2501 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2504 mulx %l1,%o1,%o3 // high part
2505 mulx %l1,%o2,%o4 // first mid part
2506 mulx %l2,%o1,%o1 // second mid part
2507 mulx %l2,%o2,%o2 // low part
2508 srlx %o2,32,%o5 // low part's upper half
2509 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2510 addcc %o4,%o1,%o4 // add other mid part
2512 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2516 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2517 addcc %o0,%l0,%o0 // alten Carry addieren
2518 add %o3,%o5,%l0 // add high32(midparts) to high part
2520 movcs %xcc,%o5,%l0 // neuer Carry
2521 // Multiplikation fertig
2522 subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren
2524 movcs %xcc,%o2,%l0 // neuer Carry
2525 stx %o0,[%i2] // Low-Digit ablegen
2528 mov %l0,%i0 // letzter Carry
2534 // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
2535 DECLARE_FUNCTION(shiftxor_loop_up)
2536 C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2
2537 // srl %o2,0,%o2 // zero-extend %o2 = count
2539 _ sub %g0,%o3,%g1 // 64-i (mod 64)
2541 ldx [%o0],%o4 // *xptr holen
2542 1: ldx [%o0+%o1],%o5 // *yptr holen
2544 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
2545 xor %o4,%g2,%o4 // mit dem modifizierten *xptr kombinieren
2546 stx %o4,[%o0] // und ablegen
2548 srlx %o5,%g1,%g2 // höchste i Bits von *yptr
2549 ldx [%o0],%o4 // schon mal mit dem nächsten *xptr
2551 _ xor %o4,%g2,%o4 // verknüpfen
2552 stx %o4,[%o0] // und ablegen