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 .global C(mulu16_),C(mulu32_),C(mulu32_unchecked),C(mulu64_)
46 .global C(divu_6432_3232_),C(divu_3216_1616_)
47 .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down)
48 .global C(clear_loop_up),C(clear_loop_down)
49 .global C(test_loop_up),C(test_loop_down)
50 .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up)
51 #if CL_DS_BIG_ENDIAN_P
52 .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up)
53 .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up)
54 .global C(not_loop_up)
55 .global C(and_test_loop_up)
56 .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down)
57 .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down)
58 .global C(neg_loop_down)
59 .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down)
60 .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up)
61 .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down)
63 .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down)
64 .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down)
65 .global C(not_loop_down)
66 .global C(and_test_loop_down),C(compare_loop_down)
67 .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up)
68 .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up)
69 .global C(neg_loop_up)
70 .global C(shift1left_loop_up),C(shiftleft_loop_up)
71 .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down)
72 .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up)
75 #define LOOP_TYPE 1 // 1: Standard-Schleifen
76 // 2: Schleifen ohne Pointer, nur mit Zähler
77 #define STANDARD_LOOPS (LOOP_TYPE==1)
78 #define COUNTER_LOOPS (LOOP_TYPE==2)
80 // extern uint32 mulu16_ (uint16 arg1, uint16 arg2);
81 // ergebnis := arg1*arg2.
82 DECLARE_FUNCTION(mulu16_)
83 C(mulu16_:) // Input in %o0,%o1, Output in %o0
88 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
89 // 2^32*hi+lo := arg1*arg2.
90 DECLARE_FUNCTION(mulu32_)
91 C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1
97 // extern uint32 mulu32_unchecked (uint32 x, uint32 y);
98 // ergebnis := arg1*arg2 < 2^32.
99 DECLARE_FUNCTION(mulu32_unchecked)
100 C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0
105 // extern struct { uint64 lo; uint64 hi; } mulu64_ (uint64 arg1, uint64 arg2);
106 // 2^64*hi+lo := arg1*arg2.
107 DECLARE_FUNCTION(mulu64_)
108 C(mulu64_:) // Input in %o0,%o1, Output in %o0,%g2
109 srlx %o0,32,%o2 // %o2 = high32(arg1)
110 srl %o0,0,%o0 // %o0 = low32(arg1)
111 srlx %o1,32,%o3 // %o3 = high32(arg2)
112 srl %o1,0,%o1 // %o1 = low32(arg2)
113 mulx %o2,%o3,%g2 // high part
114 mulx %o2,%o1,%o2 // first mid part
115 mulx %o0,%o3,%o3 // second mid part
116 addcc %o2,%o3,%o2 // sum of mid parts
118 movcs %xcc,1,%o3 // carry from sum of mid parts
120 add %g2,%o3,%g2 // add to high part
122 add %g2,%o3,%g2 // add high32(midparts) to high part
123 mulx %o0,%o1,%o0 // low part
125 addcc %o0,%o2,%o0 // add low32(midparts)*2^32 to low part
128 _ movcs %xcc,%o3,%g2 // add carry to high part
130 // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
131 // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y .
132 DECLARE_FUNCTION(divu_6432_3232_)
133 C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1
135 udiv %o1,%o2,%o0 // x durch y dividieren, %o0 := q
136 umul %o0,%o2,%g1 // %g1 := (q*y) mod 2^32
137 sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r
141 // extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y);
142 // x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y .
143 DECLARE_FUNCTION(divu_3216_1616_)
144 C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient).
146 udiv %o0,%o1,%o2 // dividieren, Quotient nach %o2
147 #if 0 // Who says that %y has some meaningful contents after `udiv' ??
148 rd %y,%g1 // Rest aus %y
150 umul %o2,%o1,%g1 // %g1 := (q*y) mod 2^32
151 sub %o0,%g1,%g1 // %g1 := (x-q*y) mod 2^32 = r
153 sll %g1,16,%g1 // in die oberen 16 Bit schieben
158 #if !defined(__GNUC__)
160 // extern uint32 _get_g1 (void);
161 DECLARE_FUNCTION(_get_g1)
167 #if !defined(__GNUC__)
169 // extern uint64 _get_g2 (void);
170 DECLARE_FUNCTION(_get_g2)
176 // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
177 DECLARE_FUNCTION(copy_loop_up)
178 C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
180 // srl %o2,0,%o2 // zero-extend %o2 = count
193 // srl %o2,0,%o2 // zero-extend %o2 = count
196 sub %g0,%o2,%o2 // %o2 = -count
197 sllx %o2,3,%o2 // %o2 = -8*count
198 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
199 sub %o1,%o2,%o1 // %o1 = &destptr[count-1]
200 1: ldx [%o0+%o2],%o3 // nächstes Digit holen
201 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
203 _ stx %o3,[%o1+%o2] // Digit ablegen
208 // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
209 DECLARE_FUNCTION(copy_loop_down)
210 C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
212 // srl %o2,0,%o2 // zero-extend %o2 = count
225 // srl %o2,0,%o2 // zero-extend %o2 = count
228 sllx %o2,3,%o2 // %o2 = 8*count
229 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
230 sub %o1,%o2,%o1 // %o1 = &destptr[-count]
231 1: ldx [%o0+%o2],%o3 // nächstes Digit holen
232 subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
234 _ stx %o3,[%o1+%o2] // Digit ablegen
239 // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
240 DECLARE_FUNCTION(fill_loop_up)
241 C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
243 // srl %o1,0,%o1 // zero-extend %o1 = count
254 // srl %o1,0,%o1 // zero-extend %o1 = count
257 sub %g0,%o1,%o1 // %o1 = -count
258 sllx %o1,3,%o1 // %o1 = -8*count
259 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
260 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
262 _ stx %o2,[%o0+%o1] // Digit ablegen
267 // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
268 DECLARE_FUNCTION(fill_loop_down)
269 C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
271 // srl %o1,0,%o1 // zero-extend %o1 = count
282 // srl %o1,0,%o1 // zero-extend %o1 = count
284 _ sllx %o1,3,%o1 // %o1 = 8*count
285 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
286 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
288 _ stx %o2,[%o0+%o1] // Digit ablegen
293 // extern uintD* clear_loop_up (uintD* destptr, uintC count);
294 DECLARE_FUNCTION(clear_loop_up)
295 C(clear_loop_up:) // Input in %o0,%o1, Output in %o0
297 // srl %o1,0,%o1 // zero-extend %o1 = count
308 // srl %o1,0,%o1 // zero-extend %o1 = count
311 sub %g0,%o1,%o1 // %o1 = -count
312 sllx %o1,3,%o1 // %o1 = -8*count
313 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
314 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
316 _ stx %g0,[%o0+%o1] // Digit 0 ablegen
321 // extern uintD* clear_loop_down (uintD* destptr, uintC count);
322 DECLARE_FUNCTION(clear_loop_down)
323 C(clear_loop_down:) // Input in %o0,%o1, Output in %o0
325 // srl %o1,0,%o1 // zero-extend %o1 = count
336 // srl %o1,0,%o1 // zero-extend %o1 = count
338 _ sllx %o1,3,%o1 // %o1 = 8*count
339 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
340 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
342 _ stx %g0,[%o0+%o1] // Digit 0 ablegen
347 // extern boolean test_loop_up (uintD* ptr, uintC count);
348 DECLARE_FUNCTION(test_loop_up)
349 C(test_loop_up:) // Input in %o0,%o1, Output in %o0
351 // srl %o1,0,%o1 // zero-extend %o1 = count
366 // srl %o1,0,%o1 // zero-extend %o1 = count
368 _ sub %g0,%o1,%o1 // %o1 = -count
369 sllx %o1,3,%o1 // %o1 = -8*count
370 sub %o0,%o1,%o0 // %o0 = &ptr[count]
371 ldx [%o0+%o1],%o2 // nächstes Digit holen
372 1: brnz,pn %o2,3f // testen
373 _ addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
375 __ ldx [%o0+%o1],%o2 // nächstes Digit holen
382 // extern boolean test_loop_down (uintD* ptr, uintC count);
383 DECLARE_FUNCTION(test_loop_down)
384 C(test_loop_down:) // Input in %o0,%o1, Output in %o0
386 // srl %o1,0,%o1 // zero-extend %o1 = count
401 // srl %o1,0,%o1 // zero-extend %o1 = count
403 _ sllx %o1,3,%o1 // %o1 = 8*count
404 sub %o0,%o1,%o0 // %o0 = &ptr[-count]
406 ldx [%o0+%o1],%o2 // nächstes Digit holen
407 1: brnz,pn %o2,3f // testen
408 _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
410 __ ldx [%o0+%o1],%o2 // nächstes Digit holen
417 #if CL_DS_BIG_ENDIAN_P
419 // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
420 DECLARE_FUNCTION(or_loop_up)
421 C(or_loop_up:) // Input in %o0,%o1,%o2
423 // srl %o2,0,%o2 // zero-extend %o2 = count
425 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
426 1: ldx [%o0],%o3 // *xptr
427 ldx [%o0+%o1],%o4 // *yptr
429 or %o3,%o4,%o3 // verknüpfen
430 stx %o3,[%o0] // =: *xptr
432 _ add %o0,8,%o0 // xptr++, yptr++
437 // srl %o2,0,%o2 // zero-extend %o2 = count
440 sub %g0,%o2,%o2 // %o2 = -count
441 sllx %o2,3,%o2 // %o2 = -8*count
442 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
443 sub %o1,%o2,%o1 // %o1 = &yptr[count]
444 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
445 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
446 ldx [%o0+%o2],%o4 // noch ein Digit holen
447 or %o4,%o3,%o3 // beide verknüpfen
449 _ stx %o3,[%o1+%o2] // Digit ablegen
456 // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
457 DECLARE_FUNCTION(xor_loop_up)
458 C(xor_loop_up:) // Input in %o0,%o1,%o2
460 // srl %o2,0,%o2 // zero-extend %o2 = count
462 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
463 1: ldx [%o0],%o3 // *xptr
464 ldx [%o0+%o1],%o4 // *yptr
466 xor %o3,%o4,%o3 // verknüpfen
467 stx %o3,[%o0] // =: *xptr
469 _ add %o0,8,%o0 // xptr++, yptr++
474 // srl %o2,0,%o2 // zero-extend %o2 = count
477 sub %g0,%o2,%o2 // %o2 = -count
478 sllx %o2,3,%o2 // %o2 = -8*count
479 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
480 sub %o1,%o2,%o1 // %o1 = &yptr[count]
481 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
482 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
483 ldx [%o0+%o2],%o4 // noch ein Digit holen
484 xor %o4,%o3,%o3 // beide verknüpfen
486 _ stx %o3,[%o1+%o2] // Digit ablegen
491 #if CL_DS_BIG_ENDIAN_P
493 // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
494 DECLARE_FUNCTION(and_loop_up)
495 C(and_loop_up:) // Input in %o0,%o1,%o2
497 // srl %o2,0,%o2 // zero-extend %o2 = count
499 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
500 1: ldx [%o0],%o3 // *xptr
501 ldx [%o0+%o1],%o4 // *yptr
503 and %o3,%o4,%o3 // verknüpfen
504 stx %o3,[%o0] // =: *xptr
506 _ add %o0,8,%o0 // xptr++, yptr++
511 // srl %o2,0,%o2 // zero-extend %o2 = count
514 sub %g0,%o2,%o2 // %o2 = -count
515 sllx %o2,3,%o2 // %o2 = -8*count
516 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
517 sub %o1,%o2,%o1 // %o1 = &yptr[count]
518 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
519 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
520 ldx [%o0+%o2],%o4 // noch ein Digit holen
521 and %o4,%o3,%o3 // beide verknüpfen
523 _ stx %o3,[%o1+%o2] // Digit ablegen
528 // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
529 DECLARE_FUNCTION(eqv_loop_up)
530 C(eqv_loop_up:) // Input in %o0,%o1,%o2
532 // srl %o2,0,%o2 // zero-extend %o2 = count
534 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
535 1: ldx [%o0],%o3 // *xptr
536 ldx [%o0+%o1],%o4 // *yptr
538 xnor %o3,%o4,%o3 // verknüpfen
539 stx %o3,[%o0] // =: *xptr
541 _ add %o0,8,%o0 // xptr++, yptr++
546 // srl %o2,0,%o2 // zero-extend %o2 = count
549 sub %g0,%o2,%o2 // %o2 = -count
550 sllx %o2,3,%o2 // %o2 = -8*count
551 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
552 sub %o1,%o2,%o1 // %o1 = &yptr[count]
553 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
554 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
555 ldx [%o0+%o2],%o4 // noch ein Digit holen
556 xnor %o4,%o3,%o3 // beide verknüpfen
558 _ stx %o3,[%o1+%o2] // Digit ablegen
563 // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
564 DECLARE_FUNCTION(nand_loop_up)
565 C(nand_loop_up:) // Input in %o0,%o1,%o2
567 // srl %o2,0,%o2 // zero-extend %o2 = count
569 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
570 1: ldx [%o0],%o3 // *xptr
571 ldx [%o0+%o1],%o4 // *yptr
573 and %o3,%o4,%o3 // verknüpfen
575 stx %o3,[%o0] // =: *xptr
577 _ add %o0,8,%o0 // xptr++, yptr++
582 // srl %o2,0,%o2 // zero-extend %o2 = count
585 sub %g0,%o2,%o2 // %o2 = -count
586 sllx %o2,3,%o2 // %o2 = -8*count
587 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
588 sub %o1,%o2,%o1 // %o1 = &yptr[count]
589 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
590 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
591 ldx [%o0+%o2],%o4 // noch ein Digit holen
592 and %o4,%o3,%o3 // beide verknüpfen
595 _ stx %o3,[%o1+%o2] // Digit ablegen
600 // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
601 DECLARE_FUNCTION(nor_loop_up)
602 C(nor_loop_up:) // Input in %o0,%o1,%o2
604 // srl %o2,0,%o2 // zero-extend %o2 = count
606 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
607 1: ldx [%o0],%o3 // *xptr
608 ldx [%o0+%o1],%o4 // *yptr
610 or %o3,%o4,%o3 // verknüpfen
612 stx %o3,[%o0] // =: *xptr
614 _ add %o0,8,%o0 // xptr++, yptr++
619 // srl %o2,0,%o2 // zero-extend %o2 = count
622 sub %g0,%o2,%o2 // %o2 = -count
623 sllx %o2,3,%o2 // %o2 = -8*count
624 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
625 sub %o1,%o2,%o1 // %o1 = &yptr[count]
626 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
627 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
628 ldx [%o0+%o2],%o4 // noch ein Digit holen
629 or %o4,%o3,%o3 // beide verknüpfen
632 _ stx %o3,[%o1+%o2] // Digit ablegen
637 // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
638 DECLARE_FUNCTION(andc2_loop_up)
639 C(andc2_loop_up:) // Input in %o0,%o1,%o2
641 // srl %o2,0,%o2 // zero-extend %o2 = count
643 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
644 1: ldx [%o0],%o3 // *xptr
645 ldx [%o0+%o1],%o4 // *yptr
647 andn %o3,%o4,%o3 // verknüpfen
648 stx %o3,[%o0] // =: *xptr
650 _ add %o0,8,%o0 // xptr++, yptr++
655 // srl %o2,0,%o2 // zero-extend %o2 = count
658 sub %g0,%o2,%o2 // %o2 = -count
659 sllx %o2,3,%o2 // %o2 = -8*count
660 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
661 sub %o1,%o2,%o1 // %o1 = &yptr[count]
662 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
663 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
664 ldx [%o0+%o2],%o4 // noch ein Digit holen
665 andn %o4,%o3,%o3 // beide verknüpfen
667 _ stx %o3,[%o1+%o2] // Digit ablegen
672 // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
673 DECLARE_FUNCTION(orc2_loop_up)
674 C(orc2_loop_up:) // Input in %o0,%o1,%o2
676 // srl %o2,0,%o2 // zero-extend %o2 = count
678 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
679 1: ldx [%o0],%o3 // *xptr
680 ldx [%o0+%o1],%o4 // *yptr
682 orn %o3,%o4,%o3 // verknüpfen
683 stx %o3,[%o0] // =: *xptr
685 _ add %o0,8,%o0 // xptr++, yptr++
690 // srl %o2,0,%o2 // zero-extend %o2 = count
693 sub %g0,%o2,%o2 // %o2 = -count
694 sllx %o2,3,%o2 // %o2 = -8*count
695 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
696 sub %o1,%o2,%o1 // %o1 = &yptr[count]
697 1: ldx [%o1+%o2],%o3 // nächstes Digit holen
698 addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
699 ldx [%o0+%o2],%o4 // noch ein Digit holen
700 orn %o4,%o3,%o3 // beide verknüpfen
702 _ stx %o3,[%o1+%o2] // Digit ablegen
707 // extern void not_loop_up (uintD* xptr, uintC count);
708 DECLARE_FUNCTION(not_loop_up)
709 C(not_loop_up:) // Input in %o0,%o1
711 // srl %o1,0,%o1 // zero-extend %o1 = count
724 // srl %o1,0,%o1 // zero-extend %o1 = count
727 sub %g0,%o1,%o1 // %o1 = -count
728 sllx %o1,3,%o1 // %o1 = -8*count
729 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
730 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen
731 ldx [%o0+%o1],%o2 // nächstes Digit holen
734 _ stx %o2,[%o0+%o1] // Digit ablegen
739 // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
740 DECLARE_FUNCTION(and_test_loop_up)
741 C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
743 // srl %o2,0,%o2 // zero-extend %o2 = count
760 // srl %o2,0,%o2 // zero-extend %o2 = count
762 _ sub %g0,%o2,%o2 // %o2 = -count
763 sllx %o2,3,%o2 // %o2 = -8*count
764 sub %o0,%o2,%o0 // %o0 = &xptr[count]
765 sub %o1,%o2,%o1 // %o1 = &yptr[count]
766 ldx [%o0+%o2],%o3 // nächstes Digit holen
767 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
768 andcc %o3,%o4,%g0 // beide verknüpfen
770 _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
772 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
781 // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
782 DECLARE_FUNCTION(compare_loop_up)
783 C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
785 // srl %o2,0,%o2 // zero-extend %o2 = count
802 _ sra %o0,0,%o0 // sign-extend %o0
805 // srl %o2,0,%o2 // zero-extend %o2 = count
807 _ sub %g0,%o2,%o2 // %o2 = -count
808 sllx %o2,3,%o2 // %o2 = -8*count
809 sub %o0,%o2,%o0 // %o0 = &xptr[count]
810 sub %o1,%o2,%o1 // %o1 = &yptr[count]
811 ldx [%o0+%o2],%o3 // nächstes Digit holen
812 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
813 subcc %o3,%o4,%g0 // vergleichen
815 _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen
817 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
820 3: subcc %o3,%o4,%g0 // nochmals vergleichen
824 _ sra %o0,0,%o0 // sign-extend %o0
827 #if CL_DS_BIG_ENDIAN_P
829 // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
830 DECLARE_FUNCTION(add_loop_down)
831 C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
833 // srl %o3,0,%o3 // zero-extend %o3 = count
835 _ mov %g0,%g1 // Carry := 0
837 1: ldx [%o0],%o4 // source1-digit
839 ldx [%o1],%o5 // source2-digit
841 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
843 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
845 stx %o4,[%o2] // Digit ablegen
853 // srl %o3,0,%o3 // zero-extend %o3 = count
855 _ mov %g0,%g1 // Carry := 0
858 sllx %o3,3,%o3 // %o3 = 8*count
859 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
860 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
861 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
862 1: ldx [%o0+%o3],%o4 // source1-digit
863 ldx [%o1+%o3],%o5 // source2-digit
865 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
867 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
870 _ stx %o4,[%o2+%o3] // Digit ablegen
875 // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
876 DECLARE_FUNCTION(addto_loop_down)
877 C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
879 // srl %o2,0,%o2 // zero-extend %o2 = count
881 _ mov %g0,%o5 // Carry := 0
883 1: ldx [%o0],%o3 // source-digit
885 ldx [%o1],%o4 // dest-digit
887 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
889 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
890 stx %o4,[%o1] // Digit ablegen
898 // srl %o2,0,%o2 // zero-extend %o2 = count
900 _ mov %g0,%o5 // Carry := 0
903 sllx %o2,3,%o2 // %o2 = 8*count
904 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
905 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
906 ldx [%o0+%o2],%o3 // source-digit
907 1: ldx [%o1+%o2],%o4 // dest-digit
909 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
911 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
912 stx %o4,[%o1+%o2] // Digit ablegen
915 __ ldx [%o0+%o2],%o3 // source-digit
920 // extern uintD inc_loop_down (uintD* ptr, uintC count);
921 DECLARE_FUNCTION(inc_loop_down)
922 C(inc_loop_down:) // Input in %o0,%o1, Output in %o0
924 // srl %o1,0,%o1 // zero-extend %o1 = count
940 // srl %o1,0,%o1 // zero-extend %o1 = count
943 sllx %o1,3,%o1 // %o1 = 8*count
944 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
945 ldx [%o0+%o1],%o2 // digit holen
946 1: addcc %o2,1,%o2 // incrementieren
948 _ stx %o2,[%o0+%o1] // ablegen
949 subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
958 // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
959 DECLARE_FUNCTION(sub_loop_down)
960 C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
962 // srl %o3,0,%o3 // zero-extend %o3 = count
964 _ mov %g0,%g1 // Carry := 0
966 1: ldx [%o1],%o5 // source2-digit
968 ldx [%o0],%o4 // source1-digit
970 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
972 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
974 stx %o4,[%o2] // Digit ablegen
982 // srl %o3,0,%o3 // zero-extend %o3 = count
984 _ mov %g0,%g1 // Carry := 0
987 sllx %o3,3,%o3 // %o3 = 8*count
988 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
989 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
990 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
991 1: ldx [%o0+%o3],%o4 // source1-digit
992 ldx [%o1+%o3],%o5 // source2-digit
994 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
996 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
999 _ stx %o4,[%o2+%o3] // Digit ablegen
1004 // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
1005 DECLARE_FUNCTION(subx_loop_down)
1006 C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
1008 // srl %o3,0,%o3 // zero-extend %o3 = count
1010 _ mov %o4,%g1 // Carry (0 oder -1)
1012 1: ldx [%o1],%o5 // source2-digit
1014 ldx [%o0],%o4 // source1-digit
1016 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
1018 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
1020 stx %o4,[%o2] // Digit ablegen
1028 // srl %o3,0,%o3 // zero-extend %o3 = count
1030 _ mov %o4,%g1 // Carry (0 oder -1)
1033 sllx %o3,3,%o3 // %o3 = 8*count
1034 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
1035 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
1036 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
1037 1: ldx [%o1+%o3],%o5 // source2-digit
1038 ldx [%o0+%o3],%o4 // source1-digit
1040 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
1042 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
1045 _ stx %o4,[%o2+%o3] // Digit ablegen
1050 // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
1051 DECLARE_FUNCTION(subfrom_loop_down)
1052 C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1054 // srl %o2,0,%o2 // zero-extend %o2 = count
1056 _ mov %g0,%o5 // Carry := 0
1058 1: ldx [%o0],%o3 // source-digit
1060 ldx [%o1],%o4 // dest-digit
1062 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1064 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
1065 stx %o4,[%o1] // Digit ablegen
1073 // srl %o2,0,%o2 // zero-extend %o2 = count
1075 _ mov %g0,%o5 // Carry := 0
1078 sllx %o2,3,%o2 // %o2 = 8*count
1079 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
1080 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
1081 ldx [%o0+%o2],%o3 // source-digit
1082 1: ldx [%o1+%o2],%o4 // dest-digit
1084 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1086 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
1087 stx %o4,[%o1+%o2] // Digit ablegen
1090 __ ldx [%o0+%o2],%o3 // source-digit
1095 // extern uintD dec_loop_down (uintD* ptr, uintC count);
1096 DECLARE_FUNCTION(dec_loop_down)
1097 C(dec_loop_down:) // Input in %o0,%o1, Output in %o0
1099 // srl %o1,0,%o1 // zero-extend %o1 = count
1115 // srl %o1,0,%o1 // zero-extend %o1 = count
1118 sllx %o1,3,%o1 // %o1 = 8*count
1119 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
1120 ldx [%o0+%o1],%o2 // digit holen
1121 1: subcc %o2,1,%o2 // decrementieren
1123 _ stx %o2,[%o0+%o1] // ablegen
1124 subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1126 __ ldx [%o0+%o1],%o2
1133 // extern uintD neg_loop_down (uintD* ptr, uintC count);
1134 DECLARE_FUNCTION(neg_loop_down)
1135 C(neg_loop_down:) // Input in %o0,%o1, Output in %o0
1137 // srl %o1,0,%o1 // zero-extend %o1 = count
1138 // erstes Digit /=0 suchen:
1149 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1150 stx %o2,[%o0] // 1 Digit negieren
1151 // alle anderen Digits invertieren:
1164 // srl %o1,0,%o1 // zero-extend %o1 = count
1165 // erstes Digit /=0 suchen:
1168 sllx %o1,3,%o1 // %o1 = 8*count
1169 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
1170 ldx [%o0+%o1],%o2 // digit holen
1171 1: subcc %g0,%o2,%o2 // negieren, testen
1173 _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1175 __ ldx [%o0+%o1],%o2
1178 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1179 // alle anderen Digits invertieren:
1181 stx %o2,[%o0+%o1] // ablegen
1190 __ ldx [%o0+%o1],%o2
1195 // extern uintD shift1left_loop_down (uintD* ptr, uintC count);
1196 DECLARE_FUNCTION(shift1left_loop_down)
1197 C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0
1198 // srl %o1,0,%o1 // zero-extend %o1 = count
1200 _ mov 0,%o3 // Carry := 0
1202 1: ldx [%o0],%o2 // Digit
1203 addcc %o2,%o2,%o4 // shiften
1204 add %o4,%o3,%o4 // und carry
1205 srlx %o2,63,%o3 // neues Carry
1206 stx %o4,[%o0] // Digit ablegen
1213 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
1214 DECLARE_FUNCTION(shiftleft_loop_down)
1215 C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1216 // srl %o1,0,%o1 // zero-extend %o1 = count
1218 _ sub %g0,%o2,%g1 // 64-i (mod 64)
1220 1: ldx [%o0],%o4 // Digit
1222 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits
1223 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
1224 stx %o5,[%o0] // Digit ablegen
1225 srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
1231 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
1232 DECLARE_FUNCTION(shiftleftcopy_loop_down)
1233 C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
1234 // srl %o2,0,%o2 // zero-extend %o2 = count
1236 _ mov 0,%o4 // Carry := 0
1237 sub %g0,%o3,%g1 // 64-i (mod 64)
1239 1: ldx [%o0],%o5 // Digit
1241 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
1242 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
1244 stx %g2,[%o1] // Digit ablegen
1245 srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
1251 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
1252 DECLARE_FUNCTION(shift1right_loop_up)
1253 C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1254 // srl %o1,0,%o1 // zero-extend %o1 = count
1256 _ sllx %o2,63,%o2 // Carry
1257 1: ldx [%o0],%o3 // Digit
1259 srlx %o3,1,%o4 // shiften
1260 or %o2,%o4,%o4 // und mit altem Carry kombinieren
1261 stx %o4,[%o0] // und ablegen
1262 sllx %o3,63,%o2 // neuer Carry
1268 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
1269 DECLARE_FUNCTION(shiftright_loop_up)
1270 C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
1271 // srl %o1,0,%o1 // zero-extend %o1 = count
1272 sub %g0,%o2,%g1 // 64-i (mod 64)
1274 _ or %g0,%g0,%o3 // Carry := 0
1275 1: ldx [%o0],%o4 // Digit
1277 srlx %o4,%o2,%o5 // shiften
1278 or %o3,%o5,%o5 // und mit altem Carry kombinieren
1279 stx %o5,[%o0] // und ablegen
1280 sllx %o4,%g1,%o3 // neuer Carry
1286 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
1287 DECLARE_FUNCTION(shiftrightsigned_loop_up)
1288 C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
1289 // srl %o1,0,%o1 // zero-extend %o1 = count
1290 ldx [%o0],%o4 // erstes Digit
1291 sub %g0,%o2,%g1 // 64-i (mod 64)
1292 srax %o4,%o2,%o5 // shiften
1293 stx %o5,[%o0] // und ablegen
1294 sllx %o4,%g1,%o3 // neuer Carry
1298 1: ldx [%o0],%o4 // Digit
1300 srlx %o4,%o2,%o5 // shiften
1301 or %o3,%o5,%o5 // und mit altem Carry kombinieren
1302 stx %o5,[%o0] // und ablegen
1303 sllx %o4,%g1,%o3 // neuer Carry
1309 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
1310 DECLARE_FUNCTION(shiftrightcopy_loop_up)
1311 C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
1312 // srl %o2,0,%o2 // zero-extend %o2 = count
1313 sub %g0,%o3,%g1 // 64-i (mod 64)
1315 _ sllx %o4,%g1,%g2 // erster Carry
1316 1: ldx [%o0],%o4 // Digit
1318 srlx %o4,%o3,%o5 // shiften
1319 or %g2,%o5,%o5 // und mit altem Carry kombinieren
1320 stx %o5,[%o1] // und ablegen
1321 sllx %o4,%g1,%g2 // neuer Carry
1328 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
1329 DECLARE_FUNCTION(mulusmall_loop_down)
1330 C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
1331 // srl %o2,0,%o2 // zero-extend %o2 = len
1334 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
1335 // und kleinen Carry %o3 dazu:
1338 srlx %o4,32,%o5 // high32(x)
1339 srl %o4,0,%o4 // low32(x)
1340 mulx %o4,%o0,%o4 // low32(x)*digit
1341 mulx %o5,%o0,%o5 // high32(x)*digit
1342 sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32
1343 add %g1,%o3,%g1 // plus carry
1344 addcc %o4,%g1,%o4 // plus low32(x)*digit
1345 srlx %o5,32,%o3 // high32(high32(x)*digit)
1347 movcs %xcc,%g1,%o3 // neuer Carry
1348 stx %o4,[%o1] // neues Digit ablegen
1354 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1355 DECLARE_FUNCTION(mulu_loop_down)
1356 C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
1359 srlx %i0,32,%l1 // %l1 = high32(digit)
1360 srl %i0,0,%l2 // %l2 = low32(digit)
1362 sllx %l3,32,%l3 // %l3 = 2^32
1363 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1365 ldx [%i1+%i2],%o0 // nächstes Digit
1367 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1370 mulx %l1,%o1,%o3 // high part
1371 mulx %l1,%o2,%o4 // first mid part
1372 mulx %l2,%o1,%o1 // second mid part
1373 mulx %l2,%o2,%o2 // low part
1374 srlx %o2,32,%o5 // low part's upper half
1375 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1376 addcc %o4,%o1,%o4 // add other mid part
1378 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1382 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1383 addcc %o0,%l0,%o0 // alten Carry addieren
1384 add %o3,%o5,%l0 // add high32(midparts) to high part
1386 movcs %xcc,%o5,%l0 // neuer Carry
1387 // Multiplikation fertig
1389 _ stx %o0,[%i2] // Low-Digit ablegen
1390 stx %l0,[%i2-8] // letzten Carry ablegen
1394 // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1395 DECLARE_FUNCTION(muluadd_loop_down)
1396 C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
1399 srlx %i0,32,%l1 // %l1 = high32(digit)
1400 srl %i0,0,%l2 // %l2 = low32(digit)
1402 sllx %l3,32,%l3 // %l3 = 2^32
1403 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1405 ldx [%i1+%i2],%o0 // nächstes Digit
1406 ldx [%i2],%i4 // *destptr
1408 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1411 mulx %l1,%o1,%o3 // high part
1412 mulx %l1,%o2,%o4 // first mid part
1413 mulx %l2,%o1,%o1 // second mid part
1414 mulx %l2,%o2,%o2 // low part
1415 srlx %o2,32,%o5 // low part's upper half
1416 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1417 addcc %o4,%o1,%o4 // add other mid part
1419 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1423 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1424 addcc %o0,%l0,%o0 // alten Carry addieren
1425 add %o3,%o5,%l0 // add high32(midparts) to high part
1427 movcs %xcc,%o5,%l0 // neuer Carry
1428 // Multiplikation fertig
1429 addcc %i4,%o0,%o0 // alten *destptr addieren
1431 movcs %xcc,%o2,%l0 // neuer Carry
1433 _ stx %o0,[%i2] // Low-Digit ablegen
1434 mov %l0,%i0 // letzter Carry
1438 // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1439 DECLARE_FUNCTION(mulusub_loop_down)
1440 C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
1443 srlx %i0,32,%l1 // %l1 = high32(digit)
1444 srl %i0,0,%l2 // %l2 = low32(digit)
1446 sllx %l3,32,%l3 // %l3 = 2^32
1447 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
1449 ldx [%i1+%i2],%o0 // nächstes Digit
1450 ldx [%i2],%i4 // *destptr
1452 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
1455 mulx %l1,%o1,%o3 // high part
1456 mulx %l1,%o2,%o4 // first mid part
1457 mulx %l2,%o1,%o1 // second mid part
1458 mulx %l2,%o2,%o2 // low part
1459 srlx %o2,32,%o5 // low part's upper half
1460 add %o4,%o5,%o4 // add to one of the mid parts, no carry
1461 addcc %o4,%o1,%o4 // add other mid part
1463 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
1467 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
1468 addcc %o0,%l0,%o0 // alten Carry addieren
1469 add %o3,%o5,%l0 // add high32(midparts) to high part
1471 movcs %xcc,%o5,%l0 // neuer Carry
1472 // Multiplikation fertig
1473 subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren
1475 movcs %xcc,%o2,%l0 // neuer Carry
1477 _ stx %o0,[%i2] // Low-Digit ablegen
1478 mov %l0,%i0 // letzter Carry
1484 #if !CL_DS_BIG_ENDIAN_P
1486 // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
1487 DECLARE_FUNCTION(or_loop_down)
1488 C(or_loop_down:) // Input in %o0,%o1,%o2
1490 // srl %o2,0,%o2 // zero-extend %o2 = count
1492 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1494 1: ldx [%o0],%o3 // *xptr
1495 ldx [%o0+%o1],%o4 // *yptr
1497 or %o3,%o4,%o3 // verknüpfen
1498 stx %o3,[%o0] // =: *xptr
1500 _ sub %o0,8,%o0 // xptr++, yptr++
1505 // srl %o2,0,%o2 // zero-extend %o2 = count
1507 _ sllx %o2,3,%o2 // %o2 = 8*count
1508 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1509 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1510 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1511 ldx [%o1+%o2],%o3 // nächstes Digit holen
1512 ldx [%o0+%o2],%o4 // noch ein Digit holen
1513 or %o4,%o3,%o3 // beide verknüpfen
1515 _ stx %o3,[%o1+%o2] // Digit ablegen
1520 // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1521 DECLARE_FUNCTION(xor_loop_down)
1522 C(xor_loop_down:) // Input in %o0,%o1,%o2
1524 // srl %o2,0,%o2 // zero-extend %o2 = count
1526 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1528 1: ldx [%o0],%o3 // *xptr
1529 ldx [%o0+%o1],%o4 // *yptr
1531 xor %o3,%o4,%o3 // verknüpfen
1532 stx %o3,[%o0] // =: *xptr
1534 _ sub %o0,8,%o0 // xptr++, yptr++
1539 // srl %o2,0,%o2 // zero-extend %o2 = count
1541 _ sllx %o2,3,%o2 // %o2 = 8*count
1542 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1543 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1544 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1545 ldx [%o1+%o2],%o3 // nächstes Digit holen
1546 ldx [%o0+%o2],%o4 // noch ein Digit holen
1547 xor %o4,%o3,%o3 // beide verknüpfen
1549 _ stx %o3,[%o1+%o2] // Digit ablegen
1554 // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
1555 DECLARE_FUNCTION(and_loop_down)
1556 C(and_loop_down:) // Input in %o0,%o1,%o2
1558 // srl %o2,0,%o2 // zero-extend %o2 = count
1560 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1562 1: ldx [%o0],%o3 // *xptr
1563 ldx [%o0+%o1],%o4 // *yptr
1565 and %o3,%o4,%o3 // verknüpfen
1566 stx %o3,[%o0] // =: *xptr
1568 _ sub %o0,8,%o0 // xptr++, yptr++
1573 // srl %o2,0,%o2 // zero-extend %o2 = count
1575 _ sllx %o2,3,%o2 // %o2 = 8*count
1576 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1577 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1578 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1579 ldx [%o1+%o2],%o3 // nächstes Digit holen
1580 ldx [%o0+%o2],%o4 // noch ein Digit holen
1581 and %o4,%o3,%o3 // beide verknüpfen
1583 _ stx %o3,[%o1+%o2] // Digit ablegen
1588 // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
1589 DECLARE_FUNCTION(eqv_loop_down)
1590 C(eqv_loop_down:) // Input in %o0,%o1,%o2
1592 // srl %o2,0,%o2 // zero-extend %o2 = count
1594 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1596 1: ldx [%o0],%o3 // *xptr
1597 ldx [%o0+%o1],%o4 // *yptr
1599 xnor %o3,%o4,%o3 // verknüpfen
1600 stx %o3,[%o0] // =: *xptr
1602 _ sub %o0,8,%o0 // xptr++, yptr++
1607 // srl %o2,0,%o2 // zero-extend %o2 = count
1609 _ sllx %o2,3,%o2 // %o2 = 8*count
1610 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1611 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1612 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1613 ldx [%o1+%o2],%o3 // nächstes Digit holen
1614 ldx [%o0+%o2],%o4 // noch ein Digit holen
1615 xnor %o4,%o3,%o3 // beide verknüpfen
1617 _ stx %o3,[%o1+%o2] // Digit ablegen
1622 // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
1623 DECLARE_FUNCTION(nand_loop_down)
1624 C(nand_loop_down:) // Input in %o0,%o1,%o2
1626 // srl %o2,0,%o2 // zero-extend %o2 = count
1628 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1630 1: ldx [%o0],%o3 // *xptr
1631 ldx [%o0+%o1],%o4 // *yptr
1633 and %o3,%o4,%o3 // verknüpfen
1635 stx %o3,[%o0] // =: *xptr
1637 _ sub %o0,8,%o0 // xptr++, yptr++
1642 // srl %o2,0,%o2 // zero-extend %o2 = count
1644 _ sllx %o2,3,%o2 // %o2 = 8*count
1645 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1646 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1647 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1648 ldx [%o1+%o2],%o3 // nächstes Digit holen
1649 ldx [%o0+%o2],%o4 // noch ein Digit holen
1650 and %o4,%o3,%o3 // beide verknüpfen
1653 _ stx %o3,[%o1+%o2] // Digit ablegen
1658 // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1659 DECLARE_FUNCTION(nor_loop_down)
1660 C(nor_loop_down:) // Input in %o0,%o1,%o2
1662 // srl %o2,0,%o2 // zero-extend %o2 = count
1664 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1666 1: ldx [%o0],%o3 // *xptr
1667 ldx [%o0+%o1],%o4 // *yptr
1669 or %o3,%o4,%o3 // verknüpfen
1671 stx %o3,[%o0] // =: *xptr
1673 _ sub %o0,8,%o0 // xptr++, yptr++
1678 // srl %o2,0,%o2 // zero-extend %o2 = count
1680 _ sllx %o2,3,%o2 // %o2 = 8*count
1681 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1682 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1683 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1684 ldx [%o1+%o2],%o3 // nächstes Digit holen
1685 ldx [%o0+%o2],%o4 // noch ein Digit holen
1686 or %o4,%o3,%o3 // beide verknüpfen
1689 _ stx %o3,[%o1+%o2] // Digit ablegen
1694 // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1695 DECLARE_FUNCTION(andc2_loop_down)
1696 C(andc2_loop_down:) // Input in %o0,%o1,%o2
1698 // srl %o2,0,%o2 // zero-extend %o2 = count
1700 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1702 1: ldx [%o0],%o3 // *xptr
1703 ldx [%o0+%o1],%o4 // *yptr
1705 andn %o3,%o4,%o3 // verknüpfen
1706 stx %o3,[%o0] // =: *xptr
1708 _ sub %o0,8,%o0 // xptr++, yptr++
1713 // srl %o2,0,%o2 // zero-extend %o2 = count
1715 _ sllx %o2,3,%o2 // %o2 = 8*count
1716 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1717 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1718 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1719 ldx [%o1+%o2],%o3 // nächstes Digit holen
1720 ldx [%o0+%o2],%o4 // noch ein Digit holen
1721 andn %o4,%o3,%o3 // beide verknüpfen
1723 _ stx %o3,[%o1+%o2] // Digit ablegen
1728 // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1729 DECLARE_FUNCTION(orc2_loop_down)
1730 C(orc2_loop_down:) // Input in %o0,%o1,%o2
1732 // srl %o2,0,%o2 // zero-extend %o2 = count
1734 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1736 1: ldx [%o0],%o3 // *xptr
1737 ldx [%o0+%o1],%o4 // *yptr
1739 orn %o3,%o4,%o3 // verknüpfen
1740 stx %o3,[%o0] // =: *xptr
1742 _ sub %o0,8,%o0 // xptr++, yptr++
1747 // srl %o2,0,%o2 // zero-extend %o2 = count
1749 _ sllx %o2,3,%o2 // %o2 = 8*count
1750 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1751 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1752 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1753 ldx [%o1+%o2],%o3 // nächstes Digit holen
1754 ldx [%o0+%o2],%o4 // noch ein Digit holen
1755 orn %o4,%o3,%o3 // beide verknüpfen
1757 _ stx %o3,[%o1+%o2] // Digit ablegen
1762 // extern void not_loop_down (uintD* xptr, uintC count);
1763 DECLARE_FUNCTION(not_loop_down)
1764 C(not_loop_down:) // Input in %o0,%o1
1766 // srl %o1,0,%o1 // zero-extend %o1 = count
1779 // srl %o1,0,%o1 // zero-extend %o1 = count
1781 _ sllx %o1,3,%o1 // %o1 = 8*count
1782 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
1783 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen
1784 ldx [%o0+%o1],%o2 // nächstes Digit holen
1787 _ stx %o2,[%o0+%o1] // Digit ablegen
1792 // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
1793 DECLARE_FUNCTION(and_test_loop_down)
1794 C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1796 // srl %o2,0,%o2 // zero-extend %o2 = count
1815 // srl %o2,0,%o2 // zero-extend %o2 = count
1816 sllx %o2,3,%o2 // %o2 = 8*count
1817 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1818 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1822 ldx [%o0+%o2],%o3 // nächstes Digit holen
1823 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
1824 andcc %o3,%o4,%g0 // beide verknüpfen
1826 _ subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1828 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
1835 // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
1836 DECLARE_FUNCTION(compare_loop_down)
1837 C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1839 // srl %o2,0,%o2 // zero-extend %o2 = count
1855 _ sra %o0,0,%o0 // sign-extend %o0
1858 // srl %o2,0,%o2 // zero-extend %o2 = count
1859 sllx %o2,3,%o2 // %o2 = 8*count
1860 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
1861 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
1865 ldx [%o0+%o2],%o3 // nächstes Digit holen
1866 1: ldx [%o1+%o2],%o4 // noch ein Digit holen
1867 subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen
1869 _ subcc %o3,%o4,%g0 // vergleichen
1871 __ ldx [%o0+%o2],%o3 // nächstes Digit holen
1875 _ sra %o0,0,%o0 // sign-extend %o0
1882 // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1883 DECLARE_FUNCTION(add_loop_up)
1884 C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1886 // srl %o3,0,%o3 // zero-extend %o3 = count
1888 _ mov %g0,%g1 // Carry := 0
1889 1: ldx [%o0],%o4 // source1-digit
1891 ldx [%o1],%o5 // source2-digit
1894 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
1896 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
1897 stx %o4,[%o2] // Digit ablegen
1905 // srl %o3,0,%o3 // zero-extend %o3 = count
1907 _ mov %g0,%g1 // Carry := 0
1908 sub %g0,%o3,%o3 // %o3 = -count
1909 sllx %o3,3,%o3 // %o3 = -8*count
1911 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
1912 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
1913 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
1914 1: ldx [%o0+%o3],%o4 // source1-digit
1915 ldx [%o1+%o3],%o5 // source2-digit
1917 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1
1919 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5
1920 addcc %o3,8,%o3 // Zähler erniedrigen, Pointer erhöhen
1922 _ stx %o4,[%o2+%o3] // Digit ablegen
1927 // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
1928 DECLARE_FUNCTION(addto_loop_up)
1929 C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1931 // srl %o2,0,%o2 // zero-extend %o2 = count
1933 _ mov %g0,%o5 // Carry := 0
1934 1: ldx [%o0],%o3 // source-digit
1936 ldx [%o1],%o4 // dest-digit
1938 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1940 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
1941 stx %o4,[%o1] // Digit ablegen
1949 // srl %o2,0,%o2 // zero-extend %o2 = count
1951 _ mov %g0,%o5 // Carry := 0
1952 sub %g0,%o2,%o2 // %o2 = -count
1953 sllx %o2,3,%o2 // %o2 = -8*count
1954 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
1955 sub %o1,%o2,%o1 // %o1 = &destptr[count]
1956 ldx [%o0+%o2],%o3 // source-digit
1957 1: ldx [%o1+%o2],%o4 // dest-digit
1959 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
1961 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4
1962 stx %o4,[%o1+%o2] // Digit ablegen
1963 addcc %o2,8,%o2 // Zähler erniedrigen, Pointer erhöhen
1965 __ ldx [%o0+%o2],%o3 // source-digit
1970 // extern uintD inc_loop_up (uintD* ptr, uintC count);
1971 DECLARE_FUNCTION(inc_loop_up)
1972 C(inc_loop_up:) // Input in %o0,%o1, Output in %o0
1974 // srl %o1,0,%o1 // zero-extend %o1 = count
1991 // srl %o1,0,%o1 // zero-extend %o1 = count
1993 _ sub %g0,%o1,%o1 // %o1 = -count
1994 sllx %o1,3,%o1 // %o1 = -8*count
1995 sub %o0,%o1,%o0 // %o0 = &ptr[count]
1996 ldx [%o0+%o1],%o2 // digit holen
1997 1: addcc %o2,1,%o2 // incrementieren
1999 _ stx %o2,[%o0+%o1] // ablegen
2000 addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2002 __ ldx [%o0+%o1],%o2
2009 // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
2010 DECLARE_FUNCTION(sub_loop_up)
2011 C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2013 // srl %o3,0,%o3 // zero-extend %o3 = count
2015 _ mov %g0,%g1 // Carry := 0
2016 1: ldx [%o0],%o4 // source1-digit
2018 ldx [%o1],%o5 // source2-digit
2021 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
2023 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
2024 stx %o4,[%o2] // Digit ablegen
2032 // srl %o3,0,%o3 // zero-extend %o3 = count
2034 _ mov %g0,%g1 // Carry := 0
2035 sub %g0,%o3,%o3 // %o3 = -count
2036 sllx %o3,3,%o3 // %o3 = -8*count
2038 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
2039 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
2040 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
2041 1: ldx [%o1+%o3],%o5 // source2-digit
2042 ldx [%o0+%o3],%o4 // source1-digit
2044 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1
2046 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
2049 _ stx %o4,[%o2+%o3] // Digit ablegen
2054 // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
2055 DECLARE_FUNCTION(subx_loop_up)
2056 C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
2058 // srl %o3,0,%o3 // zero-extend %o3 = count
2060 _ mov %o4,%g1 // Carry (0 oder -1)
2061 1: ldx [%o0],%o4 // source1-digit
2063 ldx [%o1],%o5 // source2-digit
2066 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
2068 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
2069 stx %o4,[%o2] // Digit ablegen
2077 // srl %o3,0,%o3 // zero-extend %o3 = count
2079 _ mov %o4,%g1 // Carry (0 oder -1)
2080 sub %g0,%o3,%o3 // %o3 = -count
2081 sllx %o3,3,%o3 // %o3 = -8*count
2083 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
2084 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
2085 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
2086 1: ldx [%o1+%o3],%o5 // source2-digit
2087 ldx [%o0+%o3],%o4 // source1-digit
2089 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1
2091 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
2094 _ stx %o4,[%o2+%o3] // Digit ablegen
2099 // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
2100 DECLARE_FUNCTION(subfrom_loop_up)
2101 C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
2103 // srl %o2,0,%o2 // zero-extend %o2 = count
2105 _ mov %g0,%o5 // Carry := 0
2106 1: ldx [%o0],%o3 // source-digit
2108 ldx [%o1],%o4 // dest-digit
2110 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
2112 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
2113 stx %o4,[%o1] // Digit ablegen
2121 // srl %o2,0,%o2 // zero-extend %o2 = count
2123 _ mov %g0,%o5 // Carry := 0
2124 sub %g0,%o2,%o2 // %o2 = -count
2125 sllx %o2,3,%o2 // %o2 = -8*count
2126 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
2127 sub %o1,%o2,%o1 // %o1 = &destptr[count]
2128 ldx [%o0+%o2],%o3 // source-digit
2129 1: ldx [%o1+%o2],%o4 // dest-digit
2131 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5
2133 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
2134 stx %o4,[%o1+%o2] // Digit ablegen
2137 __ ldx [%o0+%o2],%o3 // source-digit
2142 // extern uintD dec_loop_up (uintD* ptr, uintC count);
2143 DECLARE_FUNCTION(dec_loop_up)
2144 C(dec_loop_up:) // Input in %o0,%o1, Output in %o0
2146 // srl %o1,0,%o1 // zero-extend %o1 = count
2163 // srl %o1,0,%o1 // zero-extend %o1 = count
2165 _ sub %g0,%o1,%o1 // %o1 = -count
2166 sllx %o1,3,%o1 // %o1 = -8*count
2167 sub %o0,%o1,%o0 // %o0 = &ptr[count]
2168 ldx [%o0+%o1],%o2 // digit holen
2169 1: subcc %o2,1,%o2 // decrementieren
2171 _ stx %o2,[%o0+%o1] // ablegen
2172 addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2174 __ ldx [%o0+%o1],%o2
2181 // extern uintD neg_loop_up (uintD* ptr, uintC count);
2182 DECLARE_FUNCTION(neg_loop_up)
2183 C(neg_loop_up:) // Input in %o0,%o1, Output in %o0
2185 // srl %o1,0,%o1 // zero-extend %o1 = count
2186 // erstes Digit /=0 suchen:
2197 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2198 // 1 Digit negieren, alle anderen Digits invertieren:
2211 // srl %o1,0,%o1 // zero-extend %o1 = count
2212 // erstes Digit /=0 suchen:
2214 _ sub %g0,%o1,%o1 // %o1 = -count
2215 sllx %o1,3,%o1 // %o1 = -8*count
2216 sub %o0,%o1,%o0 // %o0 = &ptr[count]
2217 ldx [%o0+%o1],%o2 // digit holen
2218 1: subcc %g0,%o2,%o2 // negieren, testen
2220 _ addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen
2222 __ ldx [%o0+%o1],%o2
2225 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2226 // alle anderen Digits invertieren:
2228 stx %o2,[%o0+%o1] // ablegen
2237 __ ldx [%o0+%o1],%o2
2242 // extern uintD shift1left_loop_up (uintD* ptr, uintC count);
2243 DECLARE_FUNCTION(shift1left_loop_up)
2244 C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0
2245 // srl %o1,0,%o1 // zero-extend %o1 = count
2247 _ mov 0,%o3 // Carry := 0
2248 1: ldx [%o0],%o2 // Digit
2249 addcc %o2,%o2,%o4 // shiften
2250 add %o4,%o3,%o4 // und carry
2251 srlx %o2,63,%o3 // neues Carry
2252 stx %o4,[%o0] // Digit ablegen
2259 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
2260 DECLARE_FUNCTION(shiftleft_loop_up)
2261 C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2262 // srl %o1,0,%o1 // zero-extend %o1 = count
2264 _ sub %g0,%o2,%g1 // 64-i (mod 64)
2265 1: ldx [%o0],%o4 // Digit
2267 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits
2268 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
2269 stx %o5,[%o0] // Digit ablegen
2270 srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
2278 // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
2279 DECLARE_FUNCTION(shiftleftcopy_loop_up)
2280 C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
2281 // srl %o2,0,%o2 // zero-extend %o2 = count
2283 _ mov 0,%o4 // Carry := 0
2284 sub %g0,%o3,%g1 // 64-i (mod 64)
2285 1: ldx [%o0],%o5 // Digit
2287 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
2288 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
2289 stx %g2,[%o1] // Digit ablegen
2291 srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
2297 #if !CL_DS_BIG_ENDIAN_P
2299 // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
2300 DECLARE_FUNCTION(shift1right_loop_down)
2301 C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
2302 // srl %o1,0,%o1 // zero-extend %o1 = count
2304 _ sllx %o2,63,%o2 // Carry
2306 1: ldx [%o0],%o3 // Digit
2308 srlx %o3,1,%o4 // shiften
2309 or %o2,%o4,%o4 // und mit altem Carry kombinieren
2310 stx %o4,[%o0] // und ablegen
2311 sllx %o3,63,%o2 // neuer Carry
2317 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
2318 DECLARE_FUNCTION(shiftright_loop_down)
2319 C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2320 // srl %o1,0,%o1 // zero-extend %o1 = count
2321 sub %g0,%o2,%g1 // 64-i (mod 64)
2323 _ or %g0,%g0,%o3 // Carry := 0
2325 1: ldx [%o0],%o4 // Digit
2327 srlx %o4,%o2,%o5 // shiften
2328 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2329 stx %o5,[%o0] // und ablegen
2330 sllx %o4,%g1,%o3 // neuer Carry
2336 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
2337 DECLARE_FUNCTION(shiftrightsigned_loop_down)
2338 C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2339 // srl %o1,0,%o1 // zero-extend %o1 = count
2340 ldx [%o0-8],%o4 // erstes Digit
2341 sub %g0,%o2,%g1 // 64-i (mod 64)
2342 srax %o4,%o2,%o5 // shiften
2343 stx %o5,[%o0-8] // und ablegen
2344 sllx %o4,%g1,%o3 // neuer Carry
2348 1: ldx [%o0],%o4 // Digit
2350 srlx %o4,%o2,%o5 // shiften
2351 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2352 stx %o5,[%o0] // und ablegen
2353 sllx %o4,%g1,%o3 // neuer Carry
2359 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
2360 DECLARE_FUNCTION(shiftrightcopy_loop_down)
2361 C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
2362 // srl %o2,0,%o2 // zero-extend %o2 = count
2363 sub %g0,%o3,%g1 // 64-i (mod 64)
2365 _ sllx %o4,%g1,%g2 // erster Carry
2367 1: ldx [%o0],%o4 // Digit
2369 srlx %o4,%o3,%o5 // shiften
2370 or %g2,%o5,%o5 // und mit altem Carry kombinieren
2371 stx %o5,[%o1] // und ablegen
2372 sllx %o4,%g1,%g2 // neuer Carry
2379 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
2380 DECLARE_FUNCTION(mulusmall_loop_up)
2381 C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
2382 // srl %o2,0,%o2 // zero-extend %o2 = len
2385 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
2386 // und kleinen Carry %o3 dazu:
2389 srlx %o4,32,%o5 // high32(x)
2390 srl %o4,0,%o4 // low32(x)
2391 mulx %o4,%o0,%o4 // low32(x)*digit
2392 mulx %o5,%o0,%o5 // high32(x)*digit
2393 sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32
2394 add %g1,%o3,%g1 // plus carry
2395 addcc %o4,%g1,%o4 // plus low32(x)*digit
2396 srlx %o5,32,%o3 // high32(high32(x)*digit)
2398 movcs %xcc,%g1,%o3 // neuer Carry
2399 stx %o4,[%o1] // neues Digit ablegen
2405 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2406 DECLARE_FUNCTION(mulu_loop_up)
2407 C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
2410 srlx %i0,32,%l1 // %l1 = high32(digit)
2411 srl %i0,0,%l2 // %l2 = low32(digit)
2413 sllx %l3,32,%l3 // %l3 = 2^32
2414 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2415 1: ldx [%i1+%i2],%o0 // nächstes Digit
2417 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2420 mulx %l1,%o1,%o3 // high part
2421 mulx %l1,%o2,%o4 // first mid part
2422 mulx %l2,%o1,%o1 // second mid part
2423 mulx %l2,%o2,%o2 // low part
2424 srlx %o2,32,%o5 // low part's upper half
2425 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2426 addcc %o4,%o1,%o4 // add other mid part
2428 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2432 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2433 addcc %o0,%l0,%o0 // alten Carry addieren
2434 add %o3,%o5,%l0 // add high32(midparts) to high part
2436 movcs %xcc,%o5,%l0 // neuer Carry
2437 // Multiplikation fertig
2438 stx %o0,[%i2] // Low-Digit ablegen
2441 stx %l0,[%i2] // letzten Carry ablegen
2445 // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2446 DECLARE_FUNCTION(muluadd_loop_up)
2447 C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2450 srlx %i0,32,%l1 // %l1 = high32(digit)
2451 srl %i0,0,%l2 // %l2 = low32(digit)
2453 sllx %l3,32,%l3 // %l3 = 2^32
2454 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2455 1: ldx [%i1+%i2],%o0 // nächstes Digit
2456 ldx [%i2],%i4 // *destptr
2458 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2461 mulx %l1,%o1,%o3 // high part
2462 mulx %l1,%o2,%o4 // first mid part
2463 mulx %l2,%o1,%o1 // second mid part
2464 mulx %l2,%o2,%o2 // low part
2465 srlx %o2,32,%o5 // low part's upper half
2466 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2467 addcc %o4,%o1,%o4 // add other mid part
2469 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2473 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2474 addcc %o0,%l0,%o0 // alten Carry addieren
2475 add %o3,%o5,%l0 // add high32(midparts) to high part
2477 movcs %xcc,%o5,%l0 // neuer Carry
2478 // Multiplikation fertig
2479 addcc %i4,%o0,%o0 // alten *destptr addieren
2481 movcs %xcc,%o2,%l0 // neuer Carry
2482 stx %o0,[%i2] // Low-Digit ablegen
2485 mov %l0,%i0 // letzter Carry
2489 // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2490 DECLARE_FUNCTION(mulusub_loop_up)
2491 C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2494 srlx %i0,32,%l1 // %l1 = high32(digit)
2495 srl %i0,0,%l2 // %l2 = low32(digit)
2497 sllx %l3,32,%l3 // %l3 = 2^32
2498 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr
2499 1: ldx [%i1+%i2],%o0 // nächstes Digit
2500 ldx [%i2],%i4 // *destptr
2502 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
2505 mulx %l1,%o1,%o3 // high part
2506 mulx %l1,%o2,%o4 // first mid part
2507 mulx %l2,%o1,%o1 // second mid part
2508 mulx %l2,%o2,%o2 // low part
2509 srlx %o2,32,%o5 // low part's upper half
2510 add %o4,%o5,%o4 // add to one of the mid parts, no carry
2511 addcc %o4,%o1,%o4 // add other mid part
2513 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part
2517 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart)
2518 addcc %o0,%l0,%o0 // alten Carry addieren
2519 add %o3,%o5,%l0 // add high32(midparts) to high part
2521 movcs %xcc,%o5,%l0 // neuer Carry
2522 // Multiplikation fertig
2523 subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren
2525 movcs %xcc,%o2,%l0 // neuer Carry
2526 stx %o0,[%i2] // Low-Digit ablegen
2529 mov %l0,%i0 // letzter Carry
2535 // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
2536 DECLARE_FUNCTION(shiftxor_loop_up)
2537 C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2
2538 // srl %o2,0,%o2 // zero-extend %o2 = count
2540 _ sub %g0,%o3,%g1 // 64-i (mod 64)
2542 ldx [%o0],%o4 // *xptr holen
2543 1: ldx [%o0+%o1],%o5 // *yptr holen
2545 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits
2546 xor %o4,%g2,%o4 // mit dem modifizierten *xptr kombinieren
2547 stx %o4,[%o0] // und ablegen
2549 srlx %o5,%g1,%g2 // höchste i Bits von *yptr
2550 ldx [%o0],%o4 // schon mal mit dem nächsten *xptr
2552 _ xor %o4,%g2,%o4 // verknüpfen
2553 stx %o4,[%o0] // und ablegen