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 // Some preprocessors keep the backslash in place, some don't.
28 // Some complain about the # being not in front of an ANSI C macro.
29 // Therefore we use a dollar, which will be sed-converted to # later.
30 #define DECLARE_FUNCTION(name) .type C(name),$function
32 #define DECLARE_FUNCTION(name)
35 // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots
36 // (diese werden VOR der vorigen Instruktion ausgeführt):
37 #define _ // Instruktion, die stets ausgeführt wird
38 #define __ // Instruktion, die nur im Sprung-Fall ausgeführt wird
39 // Abkürzungen für Anweisungen:
40 #define ret jmp %i7+8 // return from subroutine
41 #define retl jmp %o7+8 // return from leaf subroutine (no save/restore)
45 .register %g2,#scratch
47 .global C(mulu16_),C(mulu32_),C(mulu32_unchecked),C(mulu64_)
48 .global C(divu_6432_3232_),C(divu_3216_1616_)
49 .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down)
50 .global C(clear_loop_up),C(clear_loop_down)
51 .global C(test_loop_up),C(test_loop_down)
52 .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up)
53 #if CL_DS_BIG_ENDIAN_P
54 .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up)
55 .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up)
56 .global C(not_loop_up)
57 .global C(and_test_loop_up)
58 .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down)
59 .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down)
60 .global C(neg_loop_down)
61 .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down)
62 .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up)
63 .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down)
65 .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down)
66 .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down)
67 .global C(not_loop_down)
68 .global C(and_test_loop_down),C(compare_loop_down)
69 .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up)
70 .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up)
71 .global C(neg_loop_up)
72 .global C(shift1left_loop_up),C(shiftleft_loop_up)
73 .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down)
74 .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up)
77 #define LOOP_TYPE 1 // 1: Standard-Schleifen
78 // 2: Schleifen ohne Pointer, nur mit Zähler
79 #define STANDARD_LOOPS (LOOP_TYPE==1)
80 #define COUNTER_LOOPS (LOOP_TYPE==2)
82 // extern uint32 mulu16_ (uint16 arg1, uint16 arg2);
83 // ergebnis := arg1*arg2.
84 DECLARE_FUNCTION(mulu16_)
85 C(mulu16_:) // Input in %o0,%o1, Output in %o0
90 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
91 // 2^32*hi+lo := arg1*arg2.
92 DECLARE_FUNCTION(mulu32_)
93 C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1
99 // extern uint32 mulu32_unchecked (uint32 x, uint32 y);
100 // ergebnis := arg1*arg2 < 2^32.
101 DECLARE_FUNCTION(mulu32_unchecked)
102 C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0
107 // extern struct { uint64 lo; uint64 hi; } mulu64_ (uint64 arg1, uint64 arg2);
108 // 2^64*hi+lo := arg1*arg2.
109 DECLARE_FUNCTION(mulu64_)
110 C(mulu64_:) // Input in %o0,%o1, Output in %o0,%g2
111 srlx %o0,32,%o2 // %o2 = high32(arg1)
112 srl %o0,0,%o0 // %o0 = low32(arg1)
113 srlx %o1,32,%o3 // %o3 = high32(arg2)
114 srl %o1,0,%o1 // %o1 = low32(arg2)
115 mulx %o2,%o3,%g2 // high part
116 mulx %o2,%o1,%o2 // first mid part
117 mulx %o0,%o3,%o3 // second mid part
118 addcc %o2,%o3,%o2 // sum of mid parts
120 movcs %xcc,1,%o3 // carry from sum of mid parts
122 add %g2,%o3,%g2 // add to high part
124 add %g2,%o3,%g2 // add high32(midparts) to high part
125 mulx %o0,%o1,%o0 // low part
127 addcc %o0,%o2,%o0 // add low32(midparts)*2^32 to low part
130 _ movcs %xcc,%o3,%g2 // add carry to high part
132 // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
133 // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y .
134 DECLARE_FUNCTION(divu_6432_3232_)
135 C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1
137 udiv %o1,%o2,%o0 // x durch y dividieren, %o0 := q
138 umul %o0,%o2,%g1 // %g1 := (q*y) mod 2^32
139 sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r
143 // extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y);
144 // x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y .
145 DECLARE_FUNCTION(divu_3216_1616_)
146 C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient).
148 udiv %o0,%o1,%o2 // dividieren, Quotient nach %o2
149 #if 0 // Who says that %y has some meaningful contents after `udiv' ??
150 rd %y,%g1 // Rest aus %y
152 umul %o2,%o1,%g1 // %g1 := (q*y) mod 2^32
153 sub %o0,%g1,%g1 // %g1 := (x-q*y) mod 2^32 = r
155 sll %g1,16,%g1 // in die oberen 16 Bit schieben
160 #if !defined(__GNUC__)
162 // extern uint32 _get_g1 (void);
163 DECLARE_FUNCTION(_get_g1)
169 #if !defined(__GNUC__)
171 // extern uint64 _get_g2 (void);
172 DECLARE_FUNCTION(_get_g2)
178 // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
179 DECLARE_FUNCTION(copy_loop_up)
180 C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
182 // srl %o2,0,%o2 // zero-extend %o2 = count
195 // srl %o2,0,%o2 // zero-extend %o2 = count
198 sub %g0,%o2,%o2 // %o2 = -count
199 sllx %o2,3,%o2 // %o2 = -8*count
200 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
201 sub %o1,%o2,%o1 // %o1 = &destptr[count-1]
202 1: ldx [%o0+%o2],%o3 // nächstes Digit holen
203 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
205 _ stx %o3,[%o1+%o2] // Digit ablegen
210 // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
211 DECLARE_FUNCTION(copy_loop_down)
212 C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
214 // srl %o2,0,%o2 // zero-extend %o2 = count
227 // srl %o2,0,%o2 // zero-extend %o2 = count
230 sllx %o2,3,%o2 // %o2 = 8*count
231 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
232 sub %o1,%o2,%o1 // %o1 = &destptr[-count]
233 1: ldx [%o0+%o2],%o3 // nächstes Digit holen
234 subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
236 _ stx %o3,[%o1+%o2] // Digit ablegen
241 // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
242 DECLARE_FUNCTION(fill_loop_up)
243 C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
245 // srl %o1,0,%o1 // zero-extend %o1 = count
256 // srl %o1,0,%o1 // zero-extend %o1 = count
259 sub %g0,%o1,%o1 // %o1 = -count
260 sllx %o1,3,%o1 // %o1 = -8*count
261 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
262 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
264 _ stx %o2,[%o0+%o1] // Digit ablegen
269 // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
270 DECLARE_FUNCTION(fill_loop_down)
271 C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
273 // srl %o1,0,%o1 // zero-extend %o1 = count
284 // srl %o1,0,%o1 // zero-extend %o1 = count
286 _ sllx %o1,3,%o1 // %o1 = 8*count
287 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
288 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
290 _ stx %o2,[%o0+%o1] // Digit ablegen
295 // extern uintD* clear_loop_up (uintD* destptr, uintC count);
296 DECLARE_FUNCTION(clear_loop_up)
297 C(clear_loop_up:) // Input in %o0,%o1, Output in %o0
299 // srl %o1,0,%o1 // zero-extend %o1 = count
310 // srl %o1,0,%o1 // zero-extend %o1 = count
313 sub %g0,%o1,%o1 // %o1 = -count
314 sllx %o1,3,%o1 // %o1 = -8*count
315 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
316 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
318 _ stx %g0,[%o0+%o1] // Digit 0 ablegen
323 // extern uintD* clear_loop_down (uintD* destptr, uintC count);
324 DECLARE_FUNCTION(clear_loop_down)
325 C(clear_loop_down:) // Input in %o0,%o1, Output in %o0
327 // srl %o1,0,%o1 // zero-extend %o1 = count
338 // srl %o1,0,%o1 // zero-extend %o1 = count
340 _ sllx %o1,3,%o1 // %o1 = 8*count
341 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
342 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
344 _ stx %g0,[%o0+%o1] // Digit 0 ablegen
349 // extern boolean test_loop_up (uintD* ptr, uintC count);
350 DECLARE_FUNCTION(test_loop_up)
351 C(test_loop_up:) // Input in %o0,%o1, Output in %o0
353 // srl %o1,0,%o1 // zero-extend %o1 = count
368 // srl %o1,0,%o1 // zero-extend %o1 = count
370 _ sub %g0,%o1,%o1 // %o1 = -count
371 sllx %o1,3,%o1 // %o1 = -8*count
372 sub %o0,%o1,%o0 // %o0 = &ptr[count]
373 ldx [%o0+%o1],%o2 // nächstes Digit holen
374 1: brnz,pn %o2,3f // testen
375 _ addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
377 __ ldx [%o0+%o1],%o2 // nächstes Digit holen
384 // extern boolean test_loop_down (uintD* ptr, uintC count);
385 DECLARE_FUNCTION(test_loop_down)
386 C(test_loop_down:) // Input in %o0,%o1, Output in %o0
388 // srl %o1,0,%o1 // zero-extend %o1 = count
403 // srl %o1,0,%o1 // zero-extend %o1 = count
405 _ sllx %o1,3,%o1 // %o1 = 8*count
406 sub %o0,%o1,%o0 // %o0 = &ptr[-count]
408 ldx [%o0+%o1],%o2 // nächstes Digit holen
409 1: brnz,pn %o2,3f // testen
410 _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
412 __ ldx [%o0+%o1],%o2 // nächstes Digit holen
419 #if CL_DS_BIG_ENDIAN_P
421 // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
422 DECLARE_FUNCTION(or_loop_up)
423 C(or_loop_up:) // Input in %o0,%o1,%o2
425 // srl %o2,0,%o2 // zero-extend %o2 = count
427 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
428 1: ldx [%o0],%o3 // *xptr
429 ldx [%o0+%o1],%o4 // *yptr
431 or %o3,%o4,%o3 // verknüpfen
432 stx %o3,[%o0] // =: *xptr
434 _ add %o0,8,%o0 // xptr++, yptr++
439 // srl %o2,0,%o2 // zero-extend %o2 = count
442 sub %g0,%o2,%o2 // %o2 = -count
443 sllx %o2,3,%o2 // %o2 = -8*count
444 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
445 sub %o1,%o2,%o1 // %o1 = &yptr[count]
446 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
447 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
448 ldx [%o0+%o2],%o4 // noch ein Digit holen
449 or %o4,%o3,%o3 // beide verknüpfen
451 _ stx %o3,[%o1+%o2] // Digit ablegen
458 // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
459 DECLARE_FUNCTION(xor_loop_up)
460 C(xor_loop_up:) // Input in %o0,%o1,%o2
462 // srl %o2,0,%o2 // zero-extend %o2 = count
464 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
465 1: ldx [%o0],%o3 // *xptr
466 ldx [%o0+%o1],%o4 // *yptr
468 xor %o3,%o4,%o3 // verknüpfen
469 stx %o3,[%o0] // =: *xptr
471 _ add %o0,8,%o0 // xptr++, yptr++
476 // srl %o2,0,%o2 // zero-extend %o2 = count
479 sub %g0,%o2,%o2 // %o2 = -count
480 sllx %o2,3,%o2 // %o2 = -8*count
481 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
482 sub %o1,%o2,%o1 // %o1 = &yptr[count]
483 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
484 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
485 ldx [%o0+%o2],%o4 // noch ein Digit holen
486 xor %o4,%o3,%o3 // beide verknüpfen
488 _ stx %o3,[%o1+%o2] // Digit ablegen
493 #if CL_DS_BIG_ENDIAN_P
495 // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
496 DECLARE_FUNCTION(and_loop_up)
497 C(and_loop_up:) // Input in %o0,%o1,%o2
499 // srl %o2,0,%o2 // zero-extend %o2 = count
501 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
502 1: ldx [%o0],%o3 // *xptr
503 ldx [%o0+%o1],%o4 // *yptr
505 and %o3,%o4,%o3 // verknüpfen
506 stx %o3,[%o0] // =: *xptr
508 _ add %o0,8,%o0 // xptr++, yptr++
513 // srl %o2,0,%o2 // zero-extend %o2 = count
516 sub %g0,%o2,%o2 // %o2 = -count
517 sllx %o2,3,%o2 // %o2 = -8*count
518 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
519 sub %o1,%o2,%o1 // %o1 = &yptr[count]
520 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
521 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
522 ldx [%o0+%o2],%o4 // noch ein Digit holen
523 and %o4,%o3,%o3 // beide verknüpfen
525 _ stx %o3,[%o1+%o2] // Digit ablegen
530 // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
531 DECLARE_FUNCTION(eqv_loop_up)
532 C(eqv_loop_up:) // Input in %o0,%o1,%o2
534 // srl %o2,0,%o2 // zero-extend %o2 = count
536 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
537 1: ldx [%o0],%o3 // *xptr
538 ldx [%o0+%o1],%o4 // *yptr
540 xnor %o3,%o4,%o3 // verknüpfen
541 stx %o3,[%o0] // =: *xptr
543 _ add %o0,8,%o0 // xptr++, yptr++
548 // srl %o2,0,%o2 // zero-extend %o2 = count
551 sub %g0,%o2,%o2 // %o2 = -count
552 sllx %o2,3,%o2 // %o2 = -8*count
553 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
554 sub %o1,%o2,%o1 // %o1 = &yptr[count]
555 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
556 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
557 ldx [%o0+%o2],%o4 // noch ein Digit holen
558 xnor %o4,%o3,%o3 // beide verknüpfen
560 _ stx %o3,[%o1+%o2] // Digit ablegen
565 // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
566 DECLARE_FUNCTION(nand_loop_up)
567 C(nand_loop_up:) // Input in %o0,%o1,%o2
569 // srl %o2,0,%o2 // zero-extend %o2 = count
571 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
572 1: ldx [%o0],%o3 // *xptr
573 ldx [%o0+%o1],%o4 // *yptr
575 and %o3,%o4,%o3 // verknüpfen
577 stx %o3,[%o0] // =: *xptr
579 _ add %o0,8,%o0 // xptr++, yptr++
584 // srl %o2,0,%o2 // zero-extend %o2 = count
587 sub %g0,%o2,%o2 // %o2 = -count
588 sllx %o2,3,%o2 // %o2 = -8*count
589 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
590 sub %o1,%o2,%o1 // %o1 = &yptr[count]
591 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
592 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
593 ldx [%o0+%o2],%o4 // noch ein Digit holen
594 and %o4,%o3,%o3 // beide verknüpfen
597 _ stx %o3,[%o1+%o2] // Digit ablegen
602 // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
603 DECLARE_FUNCTION(nor_loop_up)
604 C(nor_loop_up:) // Input in %o0,%o1,%o2
606 // srl %o2,0,%o2 // zero-extend %o2 = count
608 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
609 1: ldx [%o0],%o3 // *xptr
610 ldx [%o0+%o1],%o4 // *yptr
612 or %o3,%o4,%o3 // verknüpfen
614 stx %o3,[%o0] // =: *xptr
616 _ add %o0,8,%o0 // xptr++, yptr++
621 // srl %o2,0,%o2 // zero-extend %o2 = count
624 sub %g0,%o2,%o2 // %o2 = -count
625 sllx %o2,3,%o2 // %o2 = -8*count
626 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
627 sub %o1,%o2,%o1 // %o1 = &yptr[count]
628 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
629 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
630 ldx [%o0+%o2],%o4 // noch ein Digit holen
631 or %o4,%o3,%o3 // beide verknüpfen
634 _ stx %o3,[%o1+%o2] // Digit ablegen
639 // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
640 DECLARE_FUNCTION(andc2_loop_up)
641 C(andc2_loop_up:) // Input in %o0,%o1,%o2
643 // srl %o2,0,%o2 // zero-extend %o2 = count
645 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
646 1: ldx [%o0],%o3 // *xptr
647 ldx [%o0+%o1],%o4 // *yptr
649 andn %o3,%o4,%o3 // verknüpfen
650 stx %o3,[%o0] // =: *xptr
652 _ add %o0,8,%o0 // xptr++, yptr++
657 // srl %o2,0,%o2 // zero-extend %o2 = count
660 sub %g0,%o2,%o2 // %o2 = -count
661 sllx %o2,3,%o2 // %o2 = -8*count
662 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
663 sub %o1,%o2,%o1 // %o1 = &yptr[count]
664 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
665 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
666 ldx [%o0+%o2],%o4 // noch ein Digit holen
667 andn %o4,%o3,%o3 // beide verknüpfen
669 _ stx %o3,[%o1+%o2] // Digit ablegen
674 // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
675 DECLARE_FUNCTION(orc2_loop_up)
676 C(orc2_loop_up:) // Input in %o0,%o1,%o2
678 // srl %o2,0,%o2 // zero-extend %o2 = count
680 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
681 1: ldx [%o0],%o3 // *xptr
682 ldx [%o0+%o1],%o4 // *yptr
684 orn %o3,%o4,%o3 // verknüpfen
685 stx %o3,[%o0] // =: *xptr
687 _ add %o0,8,%o0 // xptr++, yptr++
692 // srl %o2,0,%o2 // zero-extend %o2 = count
695 sub %g0,%o2,%o2 // %o2 = -count
696 sllx %o2,3,%o2 // %o2 = -8*count
697 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
698 sub %o1,%o2,%o1 // %o1 = &yptr[count]
699 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
700 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
701 ldx [%o0+%o2],%o4 // noch ein Digit holen
702 orn %o4,%o3,%o3 // beide verknüpfen
704 _ stx %o3,[%o1+%o2] // Digit ablegen
709 // extern void not_loop_up (uintD* xptr, uintC count);
710 DECLARE_FUNCTION(not_loop_up)
711 C(not_loop_up:) // Input in %o0,%o1
713 // srl %o1,0,%o1 // zero-extend %o1 = count
726 // srl %o1,0,%o1 // zero-extend %o1 = count
729 sub %g0,%o1,%o1 // %o1 = -count
730 sllx %o1,3,%o1 // %o1 = -8*count
731 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
732 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
733 ldx [%o0+%o1],%o2 // nächstes Digit holen
736 _ stx %o2,[%o0+%o1] // Digit ablegen
741 // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
742 DECLARE_FUNCTION(and_test_loop_up)
743 C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
745 // srl %o2,0,%o2 // zero-extend %o2 = count
762 // srl %o2,0,%o2 // zero-extend %o2 = count
764 _ sub %g0,%o2,%o2 // %o2 = -count
765 sllx %o2,3,%o2 // %o2 = -8*count
766 sub %o0,%o2,%o0 // %o0 = &xptr[count]
767 sub %o1,%o2,%o1 // %o1 = &yptr[count]
768 ldx [%o0+%o2],%o3 // nächstes Digit holen
769 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
770 andcc %o3,%o4,%g0 // beide verknüpfen
772 _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
774 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
783 // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
784 DECLARE_FUNCTION(compare_loop_up)
785 C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
787 // srl %o2,0,%o2 // zero-extend %o2 = count
804 _ sra %o0,0,%o0 // sign-extend %o0
807 // srl %o2,0,%o2 // zero-extend %o2 = count
809 _ sub %g0,%o2,%o2 // %o2 = -count
810 sllx %o2,3,%o2 // %o2 = -8*count
811 sub %o0,%o2,%o0 // %o0 = &xptr[count]
812 sub %o1,%o2,%o1 // %o1 = &yptr[count]
813 ldx [%o0+%o2],%o3 // nächstes Digit holen
814 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
815 subcc %o3,%o4,%g0 // vergleichen
817 _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
819 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
822 3: subcc %o3,%o4,%g0 // nochmals vergleichen
826 _ sra %o0,0,%o0 // sign-extend %o0
829 #if CL_DS_BIG_ENDIAN_P
831 // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
832 DECLARE_FUNCTION(add_loop_down)
833 C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
835 // srl %o3,0,%o3 // zero-extend %o3 = count
837 _ mov %g0,%g1 // Carry := 0
839 1: ldx [%o0],%o4 // source1-digit
841 ldx [%o1],%o5 // source2-digit
843 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
845 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
847 stx %o4,[%o2] // Digit ablegen
855 // srl %o3,0,%o3 // zero-extend %o3 = count
857 _ mov %g0,%g1 // Carry := 0
860 sllx %o3,3,%o3 // %o3 = 8*count
861 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
862 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
863 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
864 1: ldx [%o0+%o3],%o4 // source1-digit
865 ldx [%o1+%o3],%o5 // source2-digit
867 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
869 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
872 _ stx %o4,[%o2+%o3] // Digit ablegen
877 // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
878 DECLARE_FUNCTION(addto_loop_down)
879 C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
881 // srl %o2,0,%o2 // zero-extend %o2 = count
883 _ mov %g0,%o5 // Carry := 0
885 1: ldx [%o0],%o3 // source-digit
887 ldx [%o1],%o4 // dest-digit
889 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
891 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
892 stx %o4,[%o1] // Digit ablegen
900 // srl %o2,0,%o2 // zero-extend %o2 = count
902 _ mov %g0,%o5 // Carry := 0
905 sllx %o2,3,%o2 // %o2 = 8*count
906 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
907 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
908 ldx [%o0+%o2],%o3 // source-digit
909 1: ldx [%o1+%o2],%o4 // dest-digit
911 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
913 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
914 stx %o4,[%o1+%o2] // Digit ablegen
917 __ ldx [%o0+%o2],%o3 // source-digit
922 // extern uintD inc_loop_down (uintD* ptr, uintC count);
923 DECLARE_FUNCTION(inc_loop_down)
924 C(inc_loop_down:) // Input in %o0,%o1, Output in %o0
926 // srl %o1,0,%o1 // zero-extend %o1 = count
942 // srl %o1,0,%o1 // zero-extend %o1 = count
945 sllx %o1,3,%o1 // %o1 = 8*count
946 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
947 ldx [%o0+%o1],%o2 // digit holen
948 1: addcc %o2,1,%o2 // incrementieren
950 _ stx %o2,[%o0+%o1] // ablegen
951 subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
960 // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
961 DECLARE_FUNCTION(sub_loop_down)
962 C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
964 // srl %o3,0,%o3 // zero-extend %o3 = count
966 _ mov %g0,%g1 // Carry := 0
968 1: ldx [%o1],%o5 // source2-digit
970 ldx [%o0],%o4 // source1-digit
972 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
974 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
976 stx %o4,[%o2] // Digit ablegen
984 // srl %o3,0,%o3 // zero-extend %o3 = count
986 _ mov %g0,%g1 // Carry := 0
989 sllx %o3,3,%o3 // %o3 = 8*count
990 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
991 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
992 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
993 1: ldx [%o0+%o3],%o4 // source1-digit
994 ldx [%o1+%o3],%o5 // source2-digit
996 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
998 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
1001 _ stx %o4,[%o2+%o3] // Digit ablegen
1006 // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
1007 DECLARE_FUNCTION(subx_loop_down)
1008 C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
1010 // srl %o3,0,%o3 // zero-extend %o3 = count
1012 _ mov %o4,%g1 // Carry (0 oder -1)
1014 1: ldx [%o1],%o5 // source2-digit
1016 ldx [%o0],%o4 // source1-digit
1018 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
1020 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
1022 stx %o4,[%o2] // Digit ablegen
1030 // srl %o3,0,%o3 // zero-extend %o3 = count
1032 _ mov %o4,%g1 // Carry (0 oder -1)
1035 sllx %o3,3,%o3 // %o3 = 8*count
1036 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
1037 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
1038 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
1039 1: ldx [%o1+%o3],%o5 // source2-digit
1040 ldx [%o0+%o3],%o4 // source1-digit
1042 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
1044 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
1047 _ stx %o4,[%o2+%o3] // Digit ablegen
1052 // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
1053 DECLARE_FUNCTION(subfrom_loop_down)
1054 C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1056 // srl %o2,0,%o2 // zero-extend %o2 = count
1058 _ mov %g0,%o5 // Carry := 0
1060 1: ldx [%o0],%o3 // source-digit
1062 ldx [%o1],%o4 // dest-digit
1064 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1066 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
1067 stx %o4,[%o1] // Digit ablegen
1075 // srl %o2,0,%o2 // zero-extend %o2 = count
1077 _ mov %g0,%o5 // Carry := 0
1080 sllx %o2,3,%o2 // %o2 = 8*count
1081 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
1082 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
1083 ldx [%o0+%o2],%o3 // source-digit
1084 1: ldx [%o1+%o2],%o4 // dest-digit
1086 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1088 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
1089 stx %o4,[%o1+%o2] // Digit ablegen
1092 __ ldx [%o0+%o2],%o3 // source-digit
1097 // extern uintD dec_loop_down (uintD* ptr, uintC count);
1098 DECLARE_FUNCTION(dec_loop_down)
1099 C(dec_loop_down:) // Input in %o0,%o1, Output in %o0
1101 // srl %o1,0,%o1 // zero-extend %o1 = count
1117 // srl %o1,0,%o1 // zero-extend %o1 = count
1120 sllx %o1,3,%o1 // %o1 = 8*count
1121 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
1122 ldx [%o0+%o1],%o2 // digit holen
1123 1: subcc %o2,1,%o2 // decrementieren
1125 _ stx %o2,[%o0+%o1] // ablegen
1126 subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1128 __ ldx [%o0+%o1],%o2
1135 // extern uintD neg_loop_down (uintD* ptr, uintC count);
1136 DECLARE_FUNCTION(neg_loop_down)
1137 C(neg_loop_down:) // Input in %o0,%o1, Output in %o0
1139 // srl %o1,0,%o1 // zero-extend %o1 = count
1140 // erstes Digit /=0 suchen:
1151 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1152 stx %o2,[%o0] // 1 Digit negieren
1153 // alle anderen Digits invertieren:
1166 // srl %o1,0,%o1 // zero-extend %o1 = count
1167 // erstes Digit /=0 suchen:
1170 sllx %o1,3,%o1 // %o1 = 8*count
1171 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
1172 ldx [%o0+%o1],%o2 // digit holen
1173 1: subcc %g0,%o2,%o2 // negieren, testen
1175 _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1177 __ ldx [%o0+%o1],%o2
1180 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1181 // alle anderen Digits invertieren:
1183 stx %o2,[%o0+%o1] // ablegen
1192 __ ldx [%o0+%o1],%o2
1197 // extern uintD shift1left_loop_down (uintD* ptr, uintC count);
1198 DECLARE_FUNCTION(shift1left_loop_down)
1199 C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0
1200 // srl %o1,0,%o1 // zero-extend %o1 = count
1202 _ mov 0,%o3 // Carry := 0
1204 1: ldx [%o0],%o2 // Digit
1205 addcc %o2,%o2,%o4 // shiften
1206 add %o4,%o3,%o4 // und carry
1207 srlx %o2,63,%o3 // neues Carry
1208 stx %o4,[%o0] // Digit ablegen
1215 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
1216 DECLARE_FUNCTION(shiftleft_loop_down)
1217 C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1218 // srl %o1,0,%o1 // zero-extend %o1 = count
1220 _ sub %g0,%o2,%g1 // 64-i (mod 64)
1222 1: ldx [%o0],%o4 // Digit
1224 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits
1225 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
1226 stx %o5,[%o0] // Digit ablegen
1227 srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
1233 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
1234 DECLARE_FUNCTION(shiftleftcopy_loop_down)
1235 C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
1236 // srl %o2,0,%o2 // zero-extend %o2 = count
1238 _ mov 0,%o4 // Carry := 0
1239 sub %g0,%o3,%g1 // 64-i (mod 64)
1241 1: ldx [%o0],%o5 // Digit
1243 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
1244 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
1246 stx %g2,[%o1] // Digit ablegen
1247 srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
1253 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
1254 DECLARE_FUNCTION(shift1right_loop_up)
1255 C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1256 // srl %o1,0,%o1 // zero-extend %o1 = count
1258 _ sllx %o2,63,%o2 // Carry
1259 1: ldx [%o0],%o3 // Digit
1261 srlx %o3,1,%o4 // shiften
1262 or %o2,%o4,%o4 // und mit altem Carry kombinieren
1263 stx %o4,[%o0] // und ablegen
1264 sllx %o3,63,%o2 // neuer Carry
1270 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
1271 DECLARE_FUNCTION(shiftright_loop_up)
1272 C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
1273 // srl %o1,0,%o1 // zero-extend %o1 = count
1274 sub %g0,%o2,%g1 // 64-i (mod 64)
1276 _ or %g0,%g0,%o3 // Carry := 0
1277 1: ldx [%o0],%o4 // Digit
1279 srlx %o4,%o2,%o5 // shiften
1280 or %o3,%o5,%o5 // und mit altem Carry kombinieren
1281 stx %o5,[%o0] // und ablegen
1282 sllx %o4,%g1,%o3 // neuer Carry
1288 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
1289 DECLARE_FUNCTION(shiftrightsigned_loop_up)
1290 C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
1291 // srl %o1,0,%o1 // zero-extend %o1 = count
1292 ldx [%o0],%o4 // erstes Digit
1293 sub %g0,%o2,%g1 // 64-i (mod 64)
1294 srax %o4,%o2,%o5 // shiften
1295 stx %o5,[%o0] // und ablegen
1296 sllx %o4,%g1,%o3 // neuer Carry
1300 1: ldx [%o0],%o4 // Digit
1302 srlx %o4,%o2,%o5 // shiften
1303 or %o3,%o5,%o5 // und mit altem Carry kombinieren
1304 stx %o5,[%o0] // und ablegen
1305 sllx %o4,%g1,%o3 // neuer Carry
1311 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
1312 DECLARE_FUNCTION(shiftrightcopy_loop_up)
1313 C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
1314 // srl %o2,0,%o2 // zero-extend %o2 = count
1315 sub %g0,%o3,%g1 // 64-i (mod 64)
1317 _ sllx %o4,%g1,%g2 // erster Carry
1318 1: ldx [%o0],%o4 // Digit
1320 srlx %o4,%o3,%o5 // shiften
1321 or %g2,%o5,%o5 // und mit altem Carry kombinieren
1322 stx %o5,[%o1] // und ablegen
1323 sllx %o4,%g1,%g2 // neuer Carry
1330 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
1331 DECLARE_FUNCTION(mulusmall_loop_down)
1332 C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
1333 // srl %o2,0,%o2 // zero-extend %o2 = len
1336 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
1337 // und kleinen Carry %o3 dazu:
1340 srlx %o4,32,%o5 // high32(x)
1341 srl %o4,0,%o4 // low32(x)
1342 mulx %o4,%o0,%o4 // low32(x)*digit
1343 mulx %o5,%o0,%o5 // high32(x)*digit
1344 sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32
1345 add %g1,%o3,%g1 // plus carry
1346 addcc %o4,%g1,%o4 // plus low32(x)*digit
1347 srlx %o5,32,%o3 // high32(high32(x)*digit)
1349 movcs %xcc,%g1,%o3 // neuer Carry
1350 stx %o4,[%o1] // neues Digit ablegen
1356 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1357 DECLARE_FUNCTION(mulu_loop_down)
1358 C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
1361 srlx %i0,32,%l1 // %l1 = high32(digit)
1362 srl %i0,0,%l2 // %l2 = low32(digit)
1364 sllx %l3,32,%l3 // %l3 = 2^32
1365 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1367 ldx [%i1+%i2],%o0 // nächstes Digit
1369 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1372 mulx %l1,%o1,%o3 // high part
1373 mulx %l1,%o2,%o4 // first mid part
1374 mulx %l2,%o1,%o1 // second mid part
1375 mulx %l2,%o2,%o2 // low part
1376 srlx %o2,32,%o5 // low part's upper half
1377 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1378 addcc %o4,%o1,%o4 // add other mid part
1380 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1384 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1385 addcc %o0,%l0,%o0 // alten Carry addieren
1386 add %o3,%o5,%l0 // add high32(midparts) to high part
1388 movcs %xcc,%o5,%l0 // neuer Carry
1389 // Multiplikation fertig
1391 _ stx %o0,[%i2] // Low-Digit ablegen
1392 stx %l0,[%i2-8] // letzten Carry ablegen
1396 // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1397 DECLARE_FUNCTION(muluadd_loop_down)
1398 C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
1401 srlx %i0,32,%l1 // %l1 = high32(digit)
1402 srl %i0,0,%l2 // %l2 = low32(digit)
1404 sllx %l3,32,%l3 // %l3 = 2^32
1405 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1407 ldx [%i1+%i2],%o0 // nächstes Digit
1408 ldx [%i2],%i4 // *destptr
1410 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1413 mulx %l1,%o1,%o3 // high part
1414 mulx %l1,%o2,%o4 // first mid part
1415 mulx %l2,%o1,%o1 // second mid part
1416 mulx %l2,%o2,%o2 // low part
1417 srlx %o2,32,%o5 // low part's upper half
1418 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1419 addcc %o4,%o1,%o4 // add other mid part
1421 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1425 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1426 addcc %o0,%l0,%o0 // alten Carry addieren
1427 add %o3,%o5,%l0 // add high32(midparts) to high part
1429 movcs %xcc,%o5,%l0 // neuer Carry
1430 // Multiplikation fertig
1431 addcc %i4,%o0,%o0 // alten *destptr addieren
1433 movcs %xcc,%o2,%l0 // neuer Carry
1435 _ stx %o0,[%i2] // Low-Digit ablegen
1436 mov %l0,%i0 // letzter Carry
1440 // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1441 DECLARE_FUNCTION(mulusub_loop_down)
1442 C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
1445 srlx %i0,32,%l1 // %l1 = high32(digit)
1446 srl %i0,0,%l2 // %l2 = low32(digit)
1448 sllx %l3,32,%l3 // %l3 = 2^32
1449 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1451 ldx [%i1+%i2],%o0 // nächstes Digit
1452 ldx [%i2],%i4 // *destptr
1454 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1457 mulx %l1,%o1,%o3 // high part
1458 mulx %l1,%o2,%o4 // first mid part
1459 mulx %l2,%o1,%o1 // second mid part
1460 mulx %l2,%o2,%o2 // low part
1461 srlx %o2,32,%o5 // low part's upper half
1462 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1463 addcc %o4,%o1,%o4 // add other mid part
1465 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1469 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1470 addcc %o0,%l0,%o0 // alten Carry addieren
1471 add %o3,%o5,%l0 // add high32(midparts) to high part
1473 movcs %xcc,%o5,%l0 // neuer Carry
1474 // Multiplikation fertig
1475 subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren
1477 movcs %xcc,%o2,%l0 // neuer Carry
1479 _ stx %o0,[%i2] // Low-Digit ablegen
1480 mov %l0,%i0 // letzter Carry
1486 #if !CL_DS_BIG_ENDIAN_P
1488 // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
1489 DECLARE_FUNCTION(or_loop_down)
1490 C(or_loop_down:) // Input in %o0,%o1,%o2
1492 // srl %o2,0,%o2 // zero-extend %o2 = count
1494 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1496 1: ldx [%o0],%o3 // *xptr
1497 ldx [%o0+%o1],%o4 // *yptr
1499 or %o3,%o4,%o3 // verknüpfen
1500 stx %o3,[%o0] // =: *xptr
1502 _ sub %o0,8,%o0 // xptr++, yptr++
1507 // srl %o2,0,%o2 // zero-extend %o2 = count
1509 _ sllx %o2,3,%o2 // %o2 = 8*count
1510 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1511 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1512 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1513 ldx [%o1+%o2],%o3 // nächstes Digit holen
1514 ldx [%o0+%o2],%o4 // noch ein Digit holen
1515 or %o4,%o3,%o3 // beide verknüpfen
1517 _ stx %o3,[%o1+%o2] // Digit ablegen
1522 // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1523 DECLARE_FUNCTION(xor_loop_down)
1524 C(xor_loop_down:) // Input in %o0,%o1,%o2
1526 // srl %o2,0,%o2 // zero-extend %o2 = count
1528 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1530 1: ldx [%o0],%o3 // *xptr
1531 ldx [%o0+%o1],%o4 // *yptr
1533 xor %o3,%o4,%o3 // verknüpfen
1534 stx %o3,[%o0] // =: *xptr
1536 _ sub %o0,8,%o0 // xptr++, yptr++
1541 // srl %o2,0,%o2 // zero-extend %o2 = count
1543 _ sllx %o2,3,%o2 // %o2 = 8*count
1544 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1545 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1546 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1547 ldx [%o1+%o2],%o3 // nächstes Digit holen
1548 ldx [%o0+%o2],%o4 // noch ein Digit holen
1549 xor %o4,%o3,%o3 // beide verknüpfen
1551 _ stx %o3,[%o1+%o2] // Digit ablegen
1556 // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
1557 DECLARE_FUNCTION(and_loop_down)
1558 C(and_loop_down:) // Input in %o0,%o1,%o2
1560 // srl %o2,0,%o2 // zero-extend %o2 = count
1562 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1564 1: ldx [%o0],%o3 // *xptr
1565 ldx [%o0+%o1],%o4 // *yptr
1567 and %o3,%o4,%o3 // verknüpfen
1568 stx %o3,[%o0] // =: *xptr
1570 _ sub %o0,8,%o0 // xptr++, yptr++
1575 // srl %o2,0,%o2 // zero-extend %o2 = count
1577 _ sllx %o2,3,%o2 // %o2 = 8*count
1578 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1579 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1580 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1581 ldx [%o1+%o2],%o3 // nächstes Digit holen
1582 ldx [%o0+%o2],%o4 // noch ein Digit holen
1583 and %o4,%o3,%o3 // beide verknüpfen
1585 _ stx %o3,[%o1+%o2] // Digit ablegen
1590 // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
1591 DECLARE_FUNCTION(eqv_loop_down)
1592 C(eqv_loop_down:) // Input in %o0,%o1,%o2
1594 // srl %o2,0,%o2 // zero-extend %o2 = count
1596 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1598 1: ldx [%o0],%o3 // *xptr
1599 ldx [%o0+%o1],%o4 // *yptr
1601 xnor %o3,%o4,%o3 // verknüpfen
1602 stx %o3,[%o0] // =: *xptr
1604 _ sub %o0,8,%o0 // xptr++, yptr++
1609 // srl %o2,0,%o2 // zero-extend %o2 = count
1611 _ sllx %o2,3,%o2 // %o2 = 8*count
1612 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1613 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1614 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1615 ldx [%o1+%o2],%o3 // nächstes Digit holen
1616 ldx [%o0+%o2],%o4 // noch ein Digit holen
1617 xnor %o4,%o3,%o3 // beide verknüpfen
1619 _ stx %o3,[%o1+%o2] // Digit ablegen
1624 // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
1625 DECLARE_FUNCTION(nand_loop_down)
1626 C(nand_loop_down:) // Input in %o0,%o1,%o2
1628 // srl %o2,0,%o2 // zero-extend %o2 = count
1630 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1632 1: ldx [%o0],%o3 // *xptr
1633 ldx [%o0+%o1],%o4 // *yptr
1635 and %o3,%o4,%o3 // verknüpfen
1637 stx %o3,[%o0] // =: *xptr
1639 _ sub %o0,8,%o0 // xptr++, yptr++
1644 // srl %o2,0,%o2 // zero-extend %o2 = count
1646 _ sllx %o2,3,%o2 // %o2 = 8*count
1647 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1648 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1649 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1650 ldx [%o1+%o2],%o3 // nächstes Digit holen
1651 ldx [%o0+%o2],%o4 // noch ein Digit holen
1652 and %o4,%o3,%o3 // beide verknüpfen
1655 _ stx %o3,[%o1+%o2] // Digit ablegen
1660 // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1661 DECLARE_FUNCTION(nor_loop_down)
1662 C(nor_loop_down:) // Input in %o0,%o1,%o2
1664 // srl %o2,0,%o2 // zero-extend %o2 = count
1666 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1668 1: ldx [%o0],%o3 // *xptr
1669 ldx [%o0+%o1],%o4 // *yptr
1671 or %o3,%o4,%o3 // verknüpfen
1673 stx %o3,[%o0] // =: *xptr
1675 _ sub %o0,8,%o0 // xptr++, yptr++
1680 // srl %o2,0,%o2 // zero-extend %o2 = count
1682 _ sllx %o2,3,%o2 // %o2 = 8*count
1683 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1684 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1685 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1686 ldx [%o1+%o2],%o3 // nächstes Digit holen
1687 ldx [%o0+%o2],%o4 // noch ein Digit holen
1688 or %o4,%o3,%o3 // beide verknüpfen
1691 _ stx %o3,[%o1+%o2] // Digit ablegen
1696 // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1697 DECLARE_FUNCTION(andc2_loop_down)
1698 C(andc2_loop_down:) // Input in %o0,%o1,%o2
1700 // srl %o2,0,%o2 // zero-extend %o2 = count
1702 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1704 1: ldx [%o0],%o3 // *xptr
1705 ldx [%o0+%o1],%o4 // *yptr
1707 andn %o3,%o4,%o3 // verknüpfen
1708 stx %o3,[%o0] // =: *xptr
1710 _ sub %o0,8,%o0 // xptr++, yptr++
1715 // srl %o2,0,%o2 // zero-extend %o2 = count
1717 _ sllx %o2,3,%o2 // %o2 = 8*count
1718 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1719 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1720 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1721 ldx [%o1+%o2],%o3 // nächstes Digit holen
1722 ldx [%o0+%o2],%o4 // noch ein Digit holen
1723 andn %o4,%o3,%o3 // beide verknüpfen
1725 _ stx %o3,[%o1+%o2] // Digit ablegen
1730 // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1731 DECLARE_FUNCTION(orc2_loop_down)
1732 C(orc2_loop_down:) // Input in %o0,%o1,%o2
1734 // srl %o2,0,%o2 // zero-extend %o2 = count
1736 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1738 1: ldx [%o0],%o3 // *xptr
1739 ldx [%o0+%o1],%o4 // *yptr
1741 orn %o3,%o4,%o3 // verknüpfen
1742 stx %o3,[%o0] // =: *xptr
1744 _ sub %o0,8,%o0 // xptr++, yptr++
1749 // srl %o2,0,%o2 // zero-extend %o2 = count
1751 _ sllx %o2,3,%o2 // %o2 = 8*count
1752 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1753 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1754 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1755 ldx [%o1+%o2],%o3 // nächstes Digit holen
1756 ldx [%o0+%o2],%o4 // noch ein Digit holen
1757 orn %o4,%o3,%o3 // beide verknüpfen
1759 _ stx %o3,[%o1+%o2] // Digit ablegen
1764 // extern void not_loop_down (uintD* xptr, uintC count);
1765 DECLARE_FUNCTION(not_loop_down)
1766 C(not_loop_down:) // Input in %o0,%o1
1768 // srl %o1,0,%o1 // zero-extend %o1 = count
1781 // srl %o1,0,%o1 // zero-extend %o1 = count
1783 _ sllx %o1,3,%o1 // %o1 = 8*count
1784 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
1785 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1786 ldx [%o0+%o1],%o2 // nächstes Digit holen
1789 _ stx %o2,[%o0+%o1] // Digit ablegen
1794 // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
1795 DECLARE_FUNCTION(and_test_loop_down)
1796 C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1798 // srl %o2,0,%o2 // zero-extend %o2 = count
1817 // srl %o2,0,%o2 // zero-extend %o2 = count
1818 sllx %o2,3,%o2 // %o2 = 8*count
1819 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1820 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1824 ldx [%o0+%o2],%o3 // nächstes Digit holen
1825 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
1826 andcc %o3,%o4,%g0 // beide verknüpfen
1828 _ subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1830 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
1837 // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
1838 DECLARE_FUNCTION(compare_loop_down)
1839 C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1841 // srl %o2,0,%o2 // zero-extend %o2 = count
1857 _ sra %o0,0,%o0 // sign-extend %o0
1860 // srl %o2,0,%o2 // zero-extend %o2 = count
1861 sllx %o2,3,%o2 // %o2 = 8*count
1862 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1863 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1867 ldx [%o0+%o2],%o3 // nächstes Digit holen
1868 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
1869 subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1871 _ subcc %o3,%o4,%g0 // vergleichen
1873 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
1877 _ sra %o0,0,%o0 // sign-extend %o0
1884 // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1885 DECLARE_FUNCTION(add_loop_up)
1886 C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1888 // srl %o3,0,%o3 // zero-extend %o3 = count
1890 _ mov %g0,%g1 // Carry := 0
1891 1: ldx [%o0],%o4 // source1-digit
1893 ldx [%o1],%o5 // source2-digit
1896 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
1898 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
1899 stx %o4,[%o2] // Digit ablegen
1907 // srl %o3,0,%o3 // zero-extend %o3 = count
1909 _ mov %g0,%g1 // Carry := 0
1910 sub %g0,%o3,%o3 // %o3 = -count
1911 sllx %o3,3,%o3 // %o3 = -8*count
1913 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
1914 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
1915 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
1916 1: ldx [%o0+%o3],%o4 // source1-digit
1917 ldx [%o1+%o3],%o5 // source2-digit
1919 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
1921 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
1922 addcc %o3,8,%o3 // Zähler erniedrigen, Pointer erhöhen
1924 _ stx %o4,[%o2+%o3] // Digit ablegen
1929 // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
1930 DECLARE_FUNCTION(addto_loop_up)
1931 C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1933 // srl %o2,0,%o2 // zero-extend %o2 = count
1935 _ mov %g0,%o5 // Carry := 0
1936 1: ldx [%o0],%o3 // source-digit
1938 ldx [%o1],%o4 // dest-digit
1940 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1942 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
1943 stx %o4,[%o1] // Digit ablegen
1951 // srl %o2,0,%o2 // zero-extend %o2 = count
1953 _ mov %g0,%o5 // Carry := 0
1954 sub %g0,%o2,%o2 // %o2 = -count
1955 sllx %o2,3,%o2 // %o2 = -8*count
1956 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
1957 sub %o1,%o2,%o1 // %o1 = &destptr[count]
1958 ldx [%o0+%o2],%o3 // source-digit
1959 1: ldx [%o1+%o2],%o4 // dest-digit
1961 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1963 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
1964 stx %o4,[%o1+%o2] // Digit ablegen
1965 addcc %o2,8,%o2 // Zähler erniedrigen, Pointer erhöhen
1967 __ ldx [%o0+%o2],%o3 // source-digit
1972 // extern uintD inc_loop_up (uintD* ptr, uintC count);
1973 DECLARE_FUNCTION(inc_loop_up)
1974 C(inc_loop_up:) // Input in %o0,%o1, Output in %o0
1976 // srl %o1,0,%o1 // zero-extend %o1 = count
1993 // srl %o1,0,%o1 // zero-extend %o1 = count
1995 _ sub %g0,%o1,%o1 // %o1 = -count
1996 sllx %o1,3,%o1 // %o1 = -8*count
1997 sub %o0,%o1,%o0 // %o0 = &ptr[count]
1998 ldx [%o0+%o1],%o2 // digit holen
1999 1: addcc %o2,1,%o2 // incrementieren
2001 _ stx %o2,[%o0+%o1] // ablegen
2002 addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2004 __ ldx [%o0+%o1],%o2
2011 // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
2012 DECLARE_FUNCTION(sub_loop_up)
2013 C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2015 // srl %o3,0,%o3 // zero-extend %o3 = count
2017 _ mov %g0,%g1 // Carry := 0
2018 1: ldx [%o0],%o4 // source1-digit
2020 ldx [%o1],%o5 // source2-digit
2023 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
2025 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
2026 stx %o4,[%o2] // Digit ablegen
2034 // srl %o3,0,%o3 // zero-extend %o3 = count
2036 _ mov %g0,%g1 // Carry := 0
2037 sub %g0,%o3,%o3 // %o3 = -count
2038 sllx %o3,3,%o3 // %o3 = -8*count
2040 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
2041 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
2042 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
2043 1: ldx [%o1+%o3],%o5 // source2-digit
2044 ldx [%o0+%o3],%o4 // source1-digit
2046 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
2048 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
2051 _ stx %o4,[%o2+%o3] // Digit ablegen
2056 // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
2057 DECLARE_FUNCTION(subx_loop_up)
2058 C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
2060 // srl %o3,0,%o3 // zero-extend %o3 = count
2062 _ mov %o4,%g1 // Carry (0 oder -1)
2063 1: ldx [%o0],%o4 // source1-digit
2065 ldx [%o1],%o5 // source2-digit
2068 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
2070 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
2071 stx %o4,[%o2] // Digit ablegen
2079 // srl %o3,0,%o3 // zero-extend %o3 = count
2081 _ mov %o4,%g1 // Carry (0 oder -1)
2082 sub %g0,%o3,%o3 // %o3 = -count
2083 sllx %o3,3,%o3 // %o3 = -8*count
2085 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
2086 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
2087 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
2088 1: ldx [%o1+%o3],%o5 // source2-digit
2089 ldx [%o0+%o3],%o4 // source1-digit
2091 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
2093 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
2096 _ stx %o4,[%o2+%o3] // Digit ablegen
2101 // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
2102 DECLARE_FUNCTION(subfrom_loop_up)
2103 C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
2105 // srl %o2,0,%o2 // zero-extend %o2 = count
2107 _ mov %g0,%o5 // Carry := 0
2108 1: ldx [%o0],%o3 // source-digit
2110 ldx [%o1],%o4 // dest-digit
2112 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
2114 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
2115 stx %o4,[%o1] // Digit ablegen
2123 // srl %o2,0,%o2 // zero-extend %o2 = count
2125 _ mov %g0,%o5 // Carry := 0
2126 sub %g0,%o2,%o2 // %o2 = -count
2127 sllx %o2,3,%o2 // %o2 = -8*count
2128 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
2129 sub %o1,%o2,%o1 // %o1 = &destptr[count]
2130 ldx [%o0+%o2],%o3 // source-digit
2131 1: ldx [%o1+%o2],%o4 // dest-digit
2133 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
2135 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
2136 stx %o4,[%o1+%o2] // Digit ablegen
2139 __ ldx [%o0+%o2],%o3 // source-digit
2144 // extern uintD dec_loop_up (uintD* ptr, uintC count);
2145 DECLARE_FUNCTION(dec_loop_up)
2146 C(dec_loop_up:) // Input in %o0,%o1, Output in %o0
2148 // srl %o1,0,%o1 // zero-extend %o1 = count
2165 // srl %o1,0,%o1 // zero-extend %o1 = count
2167 _ sub %g0,%o1,%o1 // %o1 = -count
2168 sllx %o1,3,%o1 // %o1 = -8*count
2169 sub %o0,%o1,%o0 // %o0 = &ptr[count]
2170 ldx [%o0+%o1],%o2 // digit holen
2171 1: subcc %o2,1,%o2 // decrementieren
2173 _ stx %o2,[%o0+%o1] // ablegen
2174 addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2176 __ ldx [%o0+%o1],%o2
2183 // extern uintD neg_loop_up (uintD* ptr, uintC count);
2184 DECLARE_FUNCTION(neg_loop_up)
2185 C(neg_loop_up:) // Input in %o0,%o1, Output in %o0
2187 // srl %o1,0,%o1 // zero-extend %o1 = count
2188 // erstes Digit /=0 suchen:
2199 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2200 // 1 Digit negieren, alle anderen Digits invertieren:
2213 // srl %o1,0,%o1 // zero-extend %o1 = count
2214 // erstes Digit /=0 suchen:
2216 _ sub %g0,%o1,%o1 // %o1 = -count
2217 sllx %o1,3,%o1 // %o1 = -8*count
2218 sub %o0,%o1,%o0 // %o0 = &ptr[count]
2219 ldx [%o0+%o1],%o2 // digit holen
2220 1: subcc %g0,%o2,%o2 // negieren, testen
2222 _ addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2224 __ ldx [%o0+%o1],%o2
2227 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2228 // alle anderen Digits invertieren:
2230 stx %o2,[%o0+%o1] // ablegen
2239 __ ldx [%o0+%o1],%o2
2244 // extern uintD shift1left_loop_up (uintD* ptr, uintC count);
2245 DECLARE_FUNCTION(shift1left_loop_up)
2246 C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0
2247 // srl %o1,0,%o1 // zero-extend %o1 = count
2249 _ mov 0,%o3 // Carry := 0
2250 1: ldx [%o0],%o2 // Digit
2251 addcc %o2,%o2,%o4 // shiften
2252 add %o4,%o3,%o4 // und carry
2253 srlx %o2,63,%o3 // neues Carry
2254 stx %o4,[%o0] // Digit ablegen
2261 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
2262 DECLARE_FUNCTION(shiftleft_loop_up)
2263 C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2264 // srl %o1,0,%o1 // zero-extend %o1 = count
2266 _ sub %g0,%o2,%g1 // 64-i (mod 64)
2267 1: ldx [%o0],%o4 // Digit
2269 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits
2270 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
2271 stx %o5,[%o0] // Digit ablegen
2272 srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
2280 // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
2281 DECLARE_FUNCTION(shiftleftcopy_loop_up)
2282 C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
2283 // srl %o2,0,%o2 // zero-extend %o2 = count
2285 _ mov 0,%o4 // Carry := 0
2286 sub %g0,%o3,%g1 // 64-i (mod 64)
2287 1: ldx [%o0],%o5 // Digit
2289 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
2290 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
2291 stx %g2,[%o1] // Digit ablegen
2293 srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
2299 #if !CL_DS_BIG_ENDIAN_P
2301 // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
2302 DECLARE_FUNCTION(shift1right_loop_down)
2303 C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
2304 // srl %o1,0,%o1 // zero-extend %o1 = count
2306 _ sllx %o2,63,%o2 // Carry
2308 1: ldx [%o0],%o3 // Digit
2310 srlx %o3,1,%o4 // shiften
2311 or %o2,%o4,%o4 // und mit altem Carry kombinieren
2312 stx %o4,[%o0] // und ablegen
2313 sllx %o3,63,%o2 // neuer Carry
2319 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
2320 DECLARE_FUNCTION(shiftright_loop_down)
2321 C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2322 // srl %o1,0,%o1 // zero-extend %o1 = count
2323 sub %g0,%o2,%g1 // 64-i (mod 64)
2325 _ or %g0,%g0,%o3 // Carry := 0
2327 1: ldx [%o0],%o4 // Digit
2329 srlx %o4,%o2,%o5 // shiften
2330 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2331 stx %o5,[%o0] // und ablegen
2332 sllx %o4,%g1,%o3 // neuer Carry
2338 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
2339 DECLARE_FUNCTION(shiftrightsigned_loop_down)
2340 C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2341 // srl %o1,0,%o1 // zero-extend %o1 = count
2342 ldx [%o0-8],%o4 // erstes Digit
2343 sub %g0,%o2,%g1 // 64-i (mod 64)
2344 srax %o4,%o2,%o5 // shiften
2345 stx %o5,[%o0-8] // und ablegen
2346 sllx %o4,%g1,%o3 // neuer Carry
2350 1: ldx [%o0],%o4 // Digit
2352 srlx %o4,%o2,%o5 // shiften
2353 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2354 stx %o5,[%o0] // und ablegen
2355 sllx %o4,%g1,%o3 // neuer Carry
2361 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
2362 DECLARE_FUNCTION(shiftrightcopy_loop_down)
2363 C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
2364 // srl %o2,0,%o2 // zero-extend %o2 = count
2365 sub %g0,%o3,%g1 // 64-i (mod 64)
2367 _ sllx %o4,%g1,%g2 // erster Carry
2369 1: ldx [%o0],%o4 // Digit
2371 srlx %o4,%o3,%o5 // shiften
2372 or %g2,%o5,%o5 // und mit altem Carry kombinieren
2373 stx %o5,[%o1] // und ablegen
2374 sllx %o4,%g1,%g2 // neuer Carry
2381 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
2382 DECLARE_FUNCTION(mulusmall_loop_up)
2383 C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
2384 // srl %o2,0,%o2 // zero-extend %o2 = len
2387 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
2388 // und kleinen Carry %o3 dazu:
2391 srlx %o4,32,%o5 // high32(x)
2392 srl %o4,0,%o4 // low32(x)
2393 mulx %o4,%o0,%o4 // low32(x)*digit
2394 mulx %o5,%o0,%o5 // high32(x)*digit
2395 sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32
2396 add %g1,%o3,%g1 // plus carry
2397 addcc %o4,%g1,%o4 // plus low32(x)*digit
2398 srlx %o5,32,%o3 // high32(high32(x)*digit)
2400 movcs %xcc,%g1,%o3 // neuer Carry
2401 stx %o4,[%o1] // neues Digit ablegen
2407 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2408 DECLARE_FUNCTION(mulu_loop_up)
2409 C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
2412 srlx %i0,32,%l1 // %l1 = high32(digit)
2413 srl %i0,0,%l2 // %l2 = low32(digit)
2415 sllx %l3,32,%l3 // %l3 = 2^32
2416 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2417 1: ldx [%i1+%i2],%o0 // nächstes Digit
2419 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2422 mulx %l1,%o1,%o3 // high part
2423 mulx %l1,%o2,%o4 // first mid part
2424 mulx %l2,%o1,%o1 // second mid part
2425 mulx %l2,%o2,%o2 // low part
2426 srlx %o2,32,%o5 // low part's upper half
2427 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2428 addcc %o4,%o1,%o4 // add other mid part
2430 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2434 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2435 addcc %o0,%l0,%o0 // alten Carry addieren
2436 add %o3,%o5,%l0 // add high32(midparts) to high part
2438 movcs %xcc,%o5,%l0 // neuer Carry
2439 // Multiplikation fertig
2440 stx %o0,[%i2] // Low-Digit ablegen
2443 stx %l0,[%i2] // letzten Carry ablegen
2447 // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2448 DECLARE_FUNCTION(muluadd_loop_up)
2449 C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2452 srlx %i0,32,%l1 // %l1 = high32(digit)
2453 srl %i0,0,%l2 // %l2 = low32(digit)
2455 sllx %l3,32,%l3 // %l3 = 2^32
2456 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2457 1: ldx [%i1+%i2],%o0 // nächstes Digit
2458 ldx [%i2],%i4 // *destptr
2460 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2463 mulx %l1,%o1,%o3 // high part
2464 mulx %l1,%o2,%o4 // first mid part
2465 mulx %l2,%o1,%o1 // second mid part
2466 mulx %l2,%o2,%o2 // low part
2467 srlx %o2,32,%o5 // low part's upper half
2468 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2469 addcc %o4,%o1,%o4 // add other mid part
2471 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2475 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2476 addcc %o0,%l0,%o0 // alten Carry addieren
2477 add %o3,%o5,%l0 // add high32(midparts) to high part
2479 movcs %xcc,%o5,%l0 // neuer Carry
2480 // Multiplikation fertig
2481 addcc %i4,%o0,%o0 // alten *destptr addieren
2483 movcs %xcc,%o2,%l0 // neuer Carry
2484 stx %o0,[%i2] // Low-Digit ablegen
2487 mov %l0,%i0 // letzter Carry
2491 // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2492 DECLARE_FUNCTION(mulusub_loop_up)
2493 C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2496 srlx %i0,32,%l1 // %l1 = high32(digit)
2497 srl %i0,0,%l2 // %l2 = low32(digit)
2499 sllx %l3,32,%l3 // %l3 = 2^32
2500 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2501 1: ldx [%i1+%i2],%o0 // nächstes Digit
2502 ldx [%i2],%i4 // *destptr
2504 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2507 mulx %l1,%o1,%o3 // high part
2508 mulx %l1,%o2,%o4 // first mid part
2509 mulx %l2,%o1,%o1 // second mid part
2510 mulx %l2,%o2,%o2 // low part
2511 srlx %o2,32,%o5 // low part's upper half
2512 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2513 addcc %o4,%o1,%o4 // add other mid part
2515 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2519 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2520 addcc %o0,%l0,%o0 // alten Carry addieren
2521 add %o3,%o5,%l0 // add high32(midparts) to high part
2523 movcs %xcc,%o5,%l0 // neuer Carry
2524 // Multiplikation fertig
2525 subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren
2527 movcs %xcc,%o2,%l0 // neuer Carry
2528 stx %o0,[%i2] // Low-Digit ablegen
2531 mov %l0,%i0 // letzter Carry
2537 // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
2538 DECLARE_FUNCTION(shiftxor_loop_up)
2539 C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2
2540 // srl %o2,0,%o2 // zero-extend %o2 = count
2542 _ sub %g0,%o3,%g1 // 64-i (mod 64)
2544 ldx [%o0],%o4 // *xptr holen
2545 1: ldx [%o0+%o1],%o5 // *yptr holen
2547 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
2548 xor %o4,%g2,%o4 // mit dem modifizierten *xptr kombinieren
2549 stx %o4,[%o0] // und ablegen
2551 srlx %o5,%g1,%g2 // höchste i Bits von *yptr
2552 ldx [%o0],%o4 // schon mal mit dem nächsten *xptr
2554 _ xor %o4,%g2,%o4 // verknüpfen
2555 stx %o4,[%o0] // und ablegen