// Externe Routinen zu ARILEV1.D
// Prozessor: SPARC 64-bit
// Compiler: GNU-C oder ...
// Parameter-Übergabe: in Registern %o0-%o5.
// Parameter-Übergabe: in Registern %o0-%o5.
//   Argumente vom Typ uint8, uint16, uint32 sind bereits vom Aufrufer zu
//   uint64 umgewandelt worden (zero-extend, "srl reg,0,reg").
//   Argumente vom Typ sint8, sint16, sint32 sind bereits vom Aufrufer zu
//   sint64 umgewandelt worden (sign-extend, "sra reg,0,reg").
//   Ergebnisse vom Typ uint8, uint16, uint32 müssen vor Rückgabe zu uint64
//   umgewandelt werden (zero-extend, "srl reg,0,reg").
//   Ergebnisse vom Typ sint8, sint16, sint32 müssen vor Rückgabe zu sint64
//   umgewandelt werden (sign-extend, "sra reg,0,reg").
// Einstellungen: intCsize=32, intDsize=32.

#ifdef ASM_UNDERSCORE
  #define C(entrypoint) _##entrypoint
#else
  #define C(entrypoint) entrypoint
#endif

// When this file is compiled into a shared library, ELF linkers need to
// know which symbols are functions.
#if defined(__NetBSD__) || defined(__OpenBSD__)
  #define DECLARE_FUNCTION(name) .type C(name),@function
#elif defined(__svr4__) || defined(__ELF__)
  // Some preprocessors keep the backslash in place, some don't.
  // Some complain about the # being not in front of an ANSI C macro.
  // Therefore we use a dollar, which will be sed-converted to # later.
  #define DECLARE_FUNCTION(name) .type C(name),$function
#else
  #define DECLARE_FUNCTION(name)
#endif

  // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots
  // (diese werden VOR der vorigen Instruktion ausgeführt):
  #define _             // Instruktion, die stets ausgeführt wird
  #define __            // Instruktion, die nur im Sprung-Fall ausgeführt wird
  // Abkürzungen für Anweisungen:
  #define ret   jmp %i7+8    // return from subroutine
  #define retl  jmp %o7+8    // return from leaf subroutine (no save/restore)

        .seg "text"

        .global C(mulu16_),C(mulu32_),C(mulu32_unchecked),C(mulu64_)
        .global C(divu_6432_3232_),C(divu_3216_1616_)
        .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down)
        .global C(clear_loop_up),C(clear_loop_down)
        .global C(test_loop_up),C(test_loop_down)
        .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up)
#if CL_DS_BIG_ENDIAN_P
        .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up)
        .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up)
        .global C(not_loop_up)
        .global C(and_test_loop_up)
        .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down)
        .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down)
        .global C(neg_loop_down)
        .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down)
        .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up)
        .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down)
#else
        .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down)
        .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down)
        .global C(not_loop_down)
        .global C(and_test_loop_down),C(compare_loop_down)
        .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up)
        .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up)
        .global C(neg_loop_up)
        .global C(shift1left_loop_up),C(shiftleft_loop_up)
        .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down)
        .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up)
#endif

#define LOOP_TYPE  1    // 1: Standard-Schleifen
                        // 2: Schleifen ohne Pointer, nur mit Zähler
#define STANDARD_LOOPS  (LOOP_TYPE==1)
#define COUNTER_LOOPS  (LOOP_TYPE==2)

// extern uint32 mulu16_ (uint16 arg1, uint16 arg2);
// ergebnis := arg1*arg2.
        DECLARE_FUNCTION(mulu16_)
C(mulu16_:) // Input in %o0,%o1, Output in %o0
        umul %o0,%o1,%o2
        retl
       _ srl %o2,0,%o0

// extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
// 2^32*hi+lo := arg1*arg2.
        DECLARE_FUNCTION(mulu32_)
C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1
        umul %o0,%o1,%o2
        rd %y,%g1
        retl
       _ srl %o2,0,%o0

// extern uint32 mulu32_unchecked (uint32 x, uint32 y);
// ergebnis := arg1*arg2 < 2^32.
        DECLARE_FUNCTION(mulu32_unchecked)
C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0
        umul %o0,%o1,%o2
        retl
       _ srl %o2,0,%o0

// extern struct { uint64 lo; uint64 hi; } mulu64_ (uint64 arg1, uint64 arg2);
// 2^64*hi+lo := arg1*arg2.
        DECLARE_FUNCTION(mulu64_)
C(mulu64_:) // Input in %o0,%o1, Output in %o0,%g2
        srlx %o0,32,%o2         // %o2 = high32(arg1)
        srl %o0,0,%o0           // %o0 = low32(arg1)
        srlx %o1,32,%o3         // %o3 = high32(arg2)
        srl %o1,0,%o1           // %o1 = low32(arg2)
        mulx %o2,%o3,%g2        // high part
        mulx %o2,%o1,%o2        // first mid part
        mulx %o0,%o3,%o3        // second mid part
        addcc %o2,%o3,%o2       // sum of mid parts
        mov 0,%o3
        movcs %xcc,1,%o3        // carry from sum of mid parts
        sllx %o3,32,%o3
        add %g2,%o3,%g2         // add to high part
        srlx %o2,32,%o3
        add %g2,%o3,%g2         // add high32(midparts) to high part
        mulx %o0,%o1,%o0        // low part
        sllx %o2,32,%o2
        addcc %o0,%o2,%o0       // add low32(midparts)*2^32 to low part
        add %g2,1,%o3
        retl
       _ movcs %xcc,%o3,%g2     // add carry to high part

// extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
// x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y .
        DECLARE_FUNCTION(divu_6432_3232_)
C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1
        wr %o0,%g0,%y
        udiv %o1,%o2,%o0        // x durch y dividieren, %o0 := q
        umul %o0,%o2,%g1        // %g1 := (q*y) mod 2^32
        sub %o1,%g1,%g1         // %g1 := (xlo-q*y) mod 2^32 = r
        retl
       _ srl %o0,0,%o0

// extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y);
// x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y .
        DECLARE_FUNCTION(divu_3216_1616_)
C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient).
        wr %g0,%g0,%y
        udiv %o0,%o1,%o2        // dividieren, Quotient nach %o2
#if 0 // Who says that %y has some meaningful contents after `udiv' ??
        rd %y,%g1               // Rest aus %y
#else
        umul %o2,%o1,%g1        // %g1 := (q*y) mod 2^32
        sub %o0,%g1,%g1         // %g1 := (x-q*y) mod 2^32 = r
#endif
        sll %g1,16,%g1          // in die oberen 16 Bit schieben
        or %o2,%g1,%o0
        retl
       _ srl %o0,0,%o0

#if !defined(__GNUC__)
        .global C(_get_g1)
// extern uint32 _get_g1 (void);
        DECLARE_FUNCTION(_get_g1)
C(_get_g1:)
        retl
       _ srl %g1,0,%o0
#endif

#if !defined(__GNUC__)
        .global C(_get_g2)
// extern uint64 _get_g2 (void);
        DECLARE_FUNCTION(_get_g2)
C(_get_g2:)
        retl
       _ mov %g2,%o0
#endif

// extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
        DECLARE_FUNCTION(copy_loop_up)
C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ nop
1:        ldx [%o0],%o3
          add %o0,8,%o0
          stx %o3,[%o1]
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ add %o1,8,%o1
2:      retl
       _ mov %o1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,8,%o1
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
        sub %o1,%o2,%o1         // %o1 = &destptr[count-1]
1:        ldx [%o0+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ add %o1,8,%o0
#endif

// extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
        DECLARE_FUNCTION(copy_loop_down)
C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
1:        ldx [%o0],%o3
          sub %o1,8,%o1
          stx %o3,[%o1]
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sllx %o2,3,%o2          // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
        sub %o1,%o2,%o1         // %o1 = &destptr[-count]
1:        ldx [%o0+%o2],%o3     // nächstes Digit holen
          subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ mov %o1,%o0
#endif

// extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
        DECLARE_FUNCTION(fill_loop_up)
C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ nop
1:        stx %o2,[%o0]
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
        sub %g0,%o1,%o1         // %o1 = -count
        sllx %o1,3,%o1          // %o1 = -8*count
        sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
1:        addcc %o1,8,%o1       // Zähler "erniedrigen", Pointer erhöhen
          bne,pt %xcc,1b
         _ stx %o2,[%o0+%o1]    // Digit ablegen
2:      retl
       _ add %o0,8,%o0
#endif

// extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
        DECLARE_FUNCTION(fill_loop_down)
C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
1:        stx %o2,[%o0]
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ add %o0,8,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sllx %o1,3,%o1         // %o1 = 8*count
        sub %o0,%o1,%o0         // %o0 = &destptr[-count]
1:        subcc %o1,8,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne,pt %xcc,1b
         _ stx %o2,[%o0+%o1]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern uintD* clear_loop_up (uintD* destptr, uintC count);
        DECLARE_FUNCTION(clear_loop_up)
C(clear_loop_up:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ nop
1:        stx %g0,[%o0]
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
        sub %g0,%o1,%o1         // %o1 = -count
        sllx %o1,3,%o1          // %o1 = -8*count
        sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
1:        addcc %o1,8,%o1       // Zähler "erniedrigen", Pointer erhöhen
          bne,pt %xcc,1b
         _ stx %g0,[%o0+%o1]    // Digit 0 ablegen
2:      retl
       _ add %o0,8,%o0
#endif

// extern uintD* clear_loop_down (uintD* destptr, uintC count);
        DECLARE_FUNCTION(clear_loop_down)
C(clear_loop_down:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
1:        stx %g0,[%o0]
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ add %o0,8,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sllx %o1,3,%o1         // %o1 = 8*count
        sub %o0,%o1,%o0         // %o0 = &destptr[-count]
1:        subcc %o1,8,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne,pt %xcc,1b
         _ stx %g0,[%o0+%o1]    // Digit 0 ablegen
2:      retl
       _ nop
#endif

// extern boolean test_loop_up (uintD* ptr, uintC count);
        DECLARE_FUNCTION(test_loop_up)
C(test_loop_up:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ nop
          ldx [%o0],%o2
1:        add %o0,8,%o0
          brnz,pn %o2,3f
         _ subcc %o1,1,%o1
          bne,a,pt %xcc,1b
         __ ldx [%o0],%o2
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %g0,%o1,%o1        // %o1 = -count
        sllx %o1,3,%o1          // %o1 = -8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ldx [%o0+%o1],%o2     // nächstes Digit holen
1:        brnz,pn %o2,3f        // testen
         _ addcc %o1,8,%o1      // Zähler "erniedrigen", Pointer erhöhen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2   // nächstes Digit holen
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif

// extern boolean test_loop_down (uintD* ptr, uintC count);
        DECLARE_FUNCTION(test_loop_down)
C(test_loop_down:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
          ldx [%o0],%o2
1:        sub %o0,8,%o0
          brnz,pn %o2,3f
         _ subcc %o1,1,%o1
          bne,a,pt %xcc,1b
         __ ldx [%o0],%o2
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sllx %o1,3,%o1         // %o1 = 8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count]
        sub %o1,8,%o1
          ldx [%o0+%o1],%o2     // nächstes Digit holen
1:        brnz,pn %o2,3f        // testen
         _ subcc %o1,8,%o1      // Zähler erniedrigen, Pointer erniedrigen
          bcc,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2   // nächstes Digit holen
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif

#if CL_DS_BIG_ENDIAN_P

// extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(or_loop_up)
C(or_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

#endif

// extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(xor_loop_up)
C(xor_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          xor %o3,%o4,%o3       // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          xor %o4,%o3,%o3       // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

#if CL_DS_BIG_ENDIAN_P

// extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(and_loop_up)
C(and_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(eqv_loop_up)
C(eqv_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          xnor %o3,%o4,%o3      // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          xnor %o4,%o3,%o3      // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(nand_loop_up)
C(nand_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          xnor %g0,%o3,%o3
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          xnor %g0,%o3,%o3
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(nor_loop_up)
C(nor_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          xnor %g0,%o3,%o3
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          xnor %g0,%o3,%o3
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(andc2_loop_up)
C(andc2_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          andn %o3,%o4,%o3      // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          andn %o4,%o3,%o3      // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(orc2_loop_up)
C(orc2_loop_up:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          orn %o3,%o4,%o3       // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ add %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o0,8,%o0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ldx [%o1+%o2],%o3     // nächstes Digit holen
          addcc %o2,8,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          orn %o4,%o3,%o3       // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void not_loop_up (uintD* xptr, uintC count);
        DECLARE_FUNCTION(not_loop_up)
C(not_loop_up:) // Input in %o0,%o1
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ nop
1:        ldx [%o0],%o2
          subcc %o1,1,%o1
          xnor %g0,%o2,%o2
          stx %o2,[%o0]
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
        sub %g0,%o1,%o1         // %o1 = -count
        sllx %o1,3,%o1          // %o1 = -8*count
        sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
1:        addcc %o1,8,%o1       // Zähler "erniedrigen", Pointer erhöhen
          ldx [%o0+%o1],%o2     // nächstes Digit holen
          xnor %g0,%o2,%o2
          bne,pt %xcc,1b
         _ stx %o2,[%o0+%o1]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(and_test_loop_up)
C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ nop
1:        ldx [%o0],%o3
          ldx [%o1],%o4
          add %o0,8,%o0
          andcc %o3,%o4,%g0
          bne,pn %xcc,3f
         _ subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ add %o1,8,%o1
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %g0,%o2,%o2        // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
          ldx [%o0+%o2],%o3     // nächstes Digit holen
1:        ldx [%o1+%o2],%o4     // noch ein Digit holen
          andcc %o3,%o4,%g0     // beide verknüpfen
          bne,pn %xcc,3f
         _ addcc %o2,8,%o2      // Zähler "erniedrigen", Pointer erhöhen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // nächstes Digit holen
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif

#endif

// extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(compare_loop_up)
C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ nop
          ldx [%o0],%o3
1:        ldx [%o1],%o4
          add %o0,8,%o0
          subcc %o3,%o4,%g0
          bne,pn %xcc,3f
         _ add %o1,8,%o1
          subcc %o2,1,%o2
          bne,a,pt %xcc,1b
         __ ldx [%o0],%o3
2:      retl
       _ mov 0,%o0
3:      mov 1,%o0
        movlu %xcc,-1,%o0
        retl
       _ sra %o0,0,%o0          // sign-extend %o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %g0,%o2,%o2        // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
          ldx [%o0+%o2],%o3     // nächstes Digit holen
1:        ldx [%o1+%o2],%o4     // noch ein Digit holen
          subcc %o3,%o4,%g0     // vergleichen
          bne,pn %xcc,3f
         _ addcc %o2,8,%o2      // Zähler "erniedrigen", Pointer erhöhen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // nächstes Digit holen
2:      retl
       _ mov 0,%o0
3:      subcc %o3,%o4,%g0       // nochmals vergleichen
        mov 1,%o0
        movlu %xcc,-1,%o0
        retl
       _ sra %o0,0,%o0          // sign-extend %o0
#endif

#if CL_DS_BIG_ENDIAN_P

// extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        DECLARE_FUNCTION(add_loop_down)
C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
#if STANDARD_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
        sub %o0,8,%o0
1:        ldx [%o0],%o4         // source1-digit
          sub %o1,8,%o1
          ldx [%o1],%o5         // source2-digit
          addcc %o4,%g1,%o4
          movcc %xcc,0,%g1      // %g1|%o4 := %o4 + alter Carry %g1
          addcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %g1|%o4 := %o4 + alter Carry %g1 + %o5
          sub %o2,8,%o2
          stx %o4,[%o2]         // Digit ablegen
          subcc %o3,1,%o3
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
        sub %o0,8,%o0
        sub %o1,8,%o1
        sllx %o3,3,%o3          // %o3 = 8*count
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[-count-1]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[-count-1]
        sub %o2,%o3,%o2         // %o2 = &destptr[-count]
1:        ldx [%o0+%o3],%o4     // source1-digit
          ldx [%o1+%o3],%o5     // source2-digit
          addcc %o4,%g1,%o4
          movcc %xcc,0,%g1      // %g1|%o4 := %o4 + alter Carry %g1
          addcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %g1|%o4 := %o4 + alter Carry %g1 + %o5
          subcc %o3,8,%o3
          bne,pt %xcc,1b
         _ stx %o4,[%o2+%o3]    // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif

// extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
        DECLARE_FUNCTION(addto_loop_down)
C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // source-digit
          sub %o1,8,%o1
          ldx [%o1],%o4         // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          addcc %o3,%o4,%o4
          movcs %xcc,1,%o5      // %o5|%o4 := %o3 + alter Carry %o5 + %o4
          stx %o4,[%o1]         // Digit ablegen
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,8,%o0
        sub %o1,8,%o1
        sllx %o2,3,%o2          // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
        sub %o1,%o2,%o1         // %o1 = &destptr[-count-1]
          ldx [%o0+%o2],%o3     // source-digit
1:        ldx [%o1+%o2],%o4     // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          addcc %o3,%o4,%o4
          movcs %xcc,1,%o5      // %o5|%o4 := %o3 + alter Carry %o5 + %o4
          stx %o4,[%o1+%o2]     // Digit ablegen
          subcc %o2,8,%o2
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // source-digit
2:      retl
       _ mov %o5,%o0
#endif

// extern uintD inc_loop_down (uintD* ptr, uintC count);
        DECLARE_FUNCTION(inc_loop_down)
C(inc_loop_down:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
1:        ldx [%o0],%o2
          addcc %o2,1,%o2
          bne,pn %xcc,3f
         _ stx %o2,[%o0]
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov 1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
        sllx %o1,3,%o1          // %o1 = 8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
          ldx [%o0+%o1],%o2     // digit holen
1:        addcc %o2,1,%o2       // incrementieren
          bne,pn %xcc,3f
         _ stx %o2,[%o0+%o1]    // ablegen
          subcc %o1,8,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2
2:      retl
       _ mov 1,%o0
3:      retl
       _ mov 0,%o0
#endif

// extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        DECLARE_FUNCTION(sub_loop_down)
C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
#if STANDARD_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
        sub %o1,8,%o1
1:        ldx [%o1],%o5         // source2-digit
          sub %o0,8,%o0
          ldx [%o0],%o4         // source1-digit
          addcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %g1|%o5 := %o5 + alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
          sub %o2,8,%o2
          stx %o4,[%o2]         // Digit ablegen
          subcc %o3,1,%o3
          bne,pt %xcc,1b
         _ sub %o1,8,%o1
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
        sub %o0,8,%o0
        sub %o1,8,%o1
        sllx %o3,3,%o3          // %o3 = 8*count
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[-count-1]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[-count-1]
        sub %o2,%o3,%o2         // %o2 = &destptr[-count]
1:        ldx [%o0+%o3],%o4     // source1-digit
          ldx [%o1+%o3],%o5     // source2-digit
          addcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %g1|%o5 := %o5 + alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
          subcc %o3,8,%o3
          bne,pt %xcc,1b
         _ stx %o4,[%o2+%o3]    // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif

// extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
        DECLARE_FUNCTION(subx_loop_down)
C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
#if STANDARD_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %o4,%g1            // Carry (0 oder -1)
        sub %o1,8,%o1
1:        ldx [%o1],%o5         // source2-digit
          sub %o0,8,%o0
          ldx [%o0],%o4         // source1-digit
          subcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %o5-2^64*%g1 := %o5 - alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,-1,%g1     // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
          sub %o2,8,%o2
          stx %o4,[%o2]         // Digit ablegen
          subcc %o3,1,%o3
          bne,pt %xcc,1b
         _ sub %o1,8,%o1
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %o4,%g1            // Carry (0 oder -1)
        sub %o0,8,%o0
        sub %o1,8,%o1
        sllx %o3,3,%o3          // %o3 = 8*count
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[-count-1]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[-count-1]
        sub %o2,%o3,%o2         // %o2 = &destptr[-count]
1:        ldx [%o1+%o3],%o5     // source2-digit
          ldx [%o0+%o3],%o4     // source1-digit
          subcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %o5-2^64*%g1 := %o5 - alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,-1,%g1     // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
          subcc %o3,8,%o3
          bne,pt %xcc,1b
         _ stx %o4,[%o2+%o3]    // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif

// extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
        DECLARE_FUNCTION(subfrom_loop_down)
C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // source-digit
          sub %o1,8,%o1
          ldx [%o1],%o4         // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          subcc %o4,%o3,%o4
          movcs %xcc,1,%o5      // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
          stx %o4,[%o1]         // Digit ablegen
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,8,%o0
        sub %o1,8,%o1
        sllx %o2,3,%o2          // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
        sub %o1,%o2,%o1         // %o1 = &destptr[-count-1]
          ldx [%o0+%o2],%o3     // source-digit
1:        ldx [%o1+%o2],%o4     // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          subcc %o4,%o3,%o4
          movcs %xcc,1,%o5      // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
          stx %o4,[%o1+%o2]     // Digit ablegen
          subcc %o2,8,%o2
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // source-digit
2:      retl
       _ mov %o5,%o0
#endif

// extern uintD dec_loop_down (uintD* ptr, uintC count);
        DECLARE_FUNCTION(dec_loop_down)
C(dec_loop_down:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
1:        ldx [%o0],%o2
          subcc %o2,1,%o2
          bcc,pn %xcc,3f
         _ stx %o2,[%o0]
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov -1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
        sllx %o1,3,%o1          // %o1 = 8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
          ldx [%o0+%o1],%o2     // digit holen
1:        subcc %o2,1,%o2       // decrementieren
          bcc,pn %xcc,3f
         _ stx %o2,[%o0+%o1]    // ablegen
          subcc %o1,8,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2
2:      retl
       _ mov -1,%o0
3:      retl
       _ mov 0,%o0
#endif

// extern uintD neg_loop_down (uintD* ptr, uintC count);
        DECLARE_FUNCTION(neg_loop_down)
C(neg_loop_down:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        // erstes Digit /=0 suchen:
        brz,pn %o1,2f
       _ sub %o0,8,%o0
1:        ldx [%o0],%o2
          subcc %g0,%o2,%o2
          bne,pn %xcc,3f
         _ subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        stx %o2,[%o0]           // 1 Digit negieren
        // alle anderen Digits invertieren:
        be,pn %xcc,5f
       _ sub %o0,8,%o0
4:        ldx [%o0],%o2
          subcc %o1,1,%o1
          xnor %g0,%o2,%o2
          stx %o2,[%o0]
          bne,pt %xcc,4b
         _ sub %o0,8,%o0
5:      retl
       _ mov -1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        // erstes Digit /=0 suchen:
        brz,pn %o1,2f
       _ sub %o0,8,%o0
        sllx %o1,3,%o1          // %o1 = 8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
          ldx [%o0+%o1],%o2     // digit holen
1:        subcc %g0,%o2,%o2     // negieren, testen
          bne,pn %xcc,3f
         _ subcc %o1,8,%o1      // Zähler erniedrigen, Pointer erniedrigen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // alle anderen Digits invertieren:
        add %o1,8,%o1
        stx %o2,[%o0+%o1]       // ablegen
        subcc %o1,8,%o1
        be,pn %xcc,5f
       _ nop
          ldx [%o0+%o1],%o2
4:        xnor %g0,%o2,%o2
          stx %o2,[%o0+%o1]
          subcc %o1,8,%o1
          bne,a,pt %xcc,4b
         __ ldx [%o0+%o1],%o2
5:      retl
       _ mov -1,%o0
#endif

// extern uintD shift1left_loop_down (uintD* ptr, uintC count);
        DECLARE_FUNCTION(shift1left_loop_down)
C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ mov 0,%o3              // Carry := 0
        sub %o0,8,%o0
1:        ldx [%o0],%o2         // Digit
          addcc %o2,%o2,%o4     // shiften
          add %o4,%o3,%o4       // und carry
          srlx %o2,63,%o3       // neues Carry
          stx %o4,[%o0]         // Digit ablegen
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o3,%o0

// extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
        DECLARE_FUNCTION(shiftleft_loop_down)
C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %g0,%o2,%g1        // 64-i (mod 64)
        sub %o0,8,%o0
1:        ldx [%o0],%o4         // Digit
          subcc %o1,1,%o1
          sllx %o4,%o2,%o5      // dessen niedere (64-i) Bits
          or %o3,%o5,%o5        // mit dem alten Carry kombinieren
          stx %o5,[%o0]         // Digit ablegen
          srlx %o4,%g1,%o3      // dessen höchste i Bits liefern den neuen Carry
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o3,%o0

// extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
        DECLARE_FUNCTION(shiftleftcopy_loop_down)
C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov 0,%o4              // Carry := 0
        sub %g0,%o3,%g1         // 64-i (mod 64)
        sub %o0,8,%o0
1:        ldx [%o0],%o5         // Digit
          subcc %o2,1,%o2
          sllx %o5,%o3,%g2      // dessen niedere (64-i) Bits
          or %o4,%g2,%g2        // mit dem alten Carry kombinieren
          sub %o1,8,%o1
          stx %g2,[%o1]         // Digit ablegen
          srlx %o5,%g1,%o4      // dessen höchste i Bits liefern den neuen Carry
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o4,%o0

// extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
        DECLARE_FUNCTION(shift1right_loop_up)
C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sllx %o2,63,%o2        // Carry
1:        ldx [%o0],%o3         // Digit
          subcc %o1,1,%o1
          srlx %o3,1,%o4        // shiften
          or %o2,%o4,%o4        // und mit altem Carry kombinieren
          stx %o4,[%o0]         // und ablegen
          sllx %o3,63,%o2       // neuer Carry
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ mov %o2,%o0

// extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
        DECLARE_FUNCTION(shiftright_loop_up)
C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        sub %g0,%o2,%g1         // 64-i (mod 64)
        brz,pn %o1,2f
       _ or %g0,%g0,%o3         // Carry := 0
1:        ldx [%o0],%o4         // Digit
          subcc %o1,1,%o1
          srlx %o4,%o2,%o5      // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          stx %o5,[%o0]         // und ablegen
          sllx %o4,%g1,%o3      // neuer Carry
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ mov %o3,%o0

// extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
        DECLARE_FUNCTION(shiftrightsigned_loop_up)
C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        ldx [%o0],%o4           // erstes Digit
        sub %g0,%o2,%g1         // 64-i (mod 64)
        srax %o4,%o2,%o5        // shiften
        stx %o5,[%o0]           // und ablegen
        sllx %o4,%g1,%o3        // neuer Carry
        subcc %o1,1,%o1
        be,pn %xcc,2f
       _ add %o0,8,%o0
1:        ldx [%o0],%o4         // Digit
          subcc %o1,1,%o1
          srlx %o4,%o2,%o5      // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          stx %o5,[%o0]         // und ablegen
          sllx %o4,%g1,%o3      // neuer Carry
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ mov %o3,%o0

// extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
        DECLARE_FUNCTION(shiftrightcopy_loop_up)
C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
//      srl %o2,0,%o2           // zero-extend %o2 = count
        sub %g0,%o3,%g1         // 64-i (mod 64)
        brz,pn %o2,2f
       _ sllx %o4,%g1,%g2       // erster Carry
1:        ldx [%o0],%o4         // Digit
          add %o0,8,%o0
          srlx %o4,%o3,%o5      // shiften
          or %g2,%o5,%o5        // und mit altem Carry kombinieren
          stx %o5,[%o1]         // und ablegen
          sllx %o4,%g1,%g2      // neuer Carry
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ add %o1,8,%o1
2:      retl
       _ mov %g2,%o0

// extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
        DECLARE_FUNCTION(mulusmall_loop_down)
C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
//      srl %o2,0,%o2           // zero-extend %o2 = len
        brz,pn %o2,2f
       _ sub %o1,8,%o1
1:        // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
          // und kleinen Carry %o3 dazu:
          ldx [%o1],%o4
          sub %o2,1,%o2
          srlx %o4,32,%o5       // high32(x)
          srl %o4,0,%o4         // low32(x)
          mulx %o4,%o0,%o4      // low32(x)*digit
          mulx %o5,%o0,%o5      // high32(x)*digit
          sllx %o5,32,%g1       // low32(high32(x)*digit)*2^32
          add %g1,%o3,%g1       // plus carry
          addcc %o4,%g1,%o4     // plus low32(x)*digit
          srlx %o5,32,%o3       // high32(high32(x)*digit)
          add %o3,1,%g1
          movcs %xcc,%g1,%o3    // neuer Carry
          stx %o4,[%o1]         // neues Digit ablegen
          brnz,pt %o2,1b
         _ sub %o1,8,%o1
2:      retl
       _ mov %o3,%o0

// extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(mulu_loop_down)
C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
        save %sp,-192,%sp
        mov 0,%l0               // Carry
        srlx %i0,32,%l1         // %l1 = high32(digit)
        srl %i0,0,%l2           // %l2 = low32(digit)
        mov 1,%l3
        sllx %l3,32,%l3         // %l3 = 2^32
        sub %i1,%i2,%i1         // %i1 = sourceptr - destptr
1:        sub %i2,8,%i2
          ldx [%i1+%i2],%o0     // nächstes Digit
          subcc %i3,1,%i3
          // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
          srlx %o0,32,%o1
          srl %o0,0,%o2
          mulx %l1,%o1,%o3      // high part
          mulx %l1,%o2,%o4      // first mid part
          mulx %l2,%o1,%o1      // second mid part
          mulx %l2,%o2,%o2      // low part
          srlx %o2,32,%o5       // low part's upper half
          add %o4,%o5,%o4       // add to one of the mid parts, no carry
          addcc %o4,%o1,%o4     // add other mid part
          add %o3,%l3,%o5
          movcs %xcc,%o5,%o3    // if carry, add 2^32 to the high part
          srlx %o4,32,%o5
          sllx %o4,32,%o4
          srl %o2,0,%o2
          add %o2,%o4,%o0       // combine low32(midparts) and low32(lowpart)
          addcc %o0,%l0,%o0     // alten Carry addieren
          add %o3,%o5,%l0       // add high32(midparts) to high part
          add %l0,1,%o5
          movcs %xcc,%o5,%l0    // neuer Carry
          // Multiplikation fertig
          brnz,pt %i3,1b
         _ stx %o0,[%i2]        // Low-Digit ablegen
        stx %l0,[%i2-8]         // letzten Carry ablegen
        ret
       _ restore

// extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(muluadd_loop_down)
C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
        save %sp,-192,%sp
        mov 0,%l0               // Carry
        srlx %i0,32,%l1         // %l1 = high32(digit)
        srl %i0,0,%l2           // %l2 = low32(digit)
        mov 1,%l3
        sllx %l3,32,%l3         // %l3 = 2^32
        sub %i1,%i2,%i1         // %i1 = sourceptr - destptr
1:        sub %i2,8,%i2
          ldx [%i1+%i2],%o0     // nächstes Digit
          ldx [%i2],%i4         // *destptr
          subcc %i3,1,%i3
          // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
          srlx %o0,32,%o1
          srl %o0,0,%o2
          mulx %l1,%o1,%o3      // high part
          mulx %l1,%o2,%o4      // first mid part
          mulx %l2,%o1,%o1      // second mid part
          mulx %l2,%o2,%o2      // low part
          srlx %o2,32,%o5       // low part's upper half
          add %o4,%o5,%o4       // add to one of the mid parts, no carry
          addcc %o4,%o1,%o4     // add other mid part
          add %o3,%l3,%o5
          movcs %xcc,%o5,%o3    // if carry, add 2^32 to the high part
          srlx %o4,32,%o5
          sllx %o4,32,%o4
          srl %o2,0,%o2
          add %o2,%o4,%o0       // combine low32(midparts) and low32(lowpart)
          addcc %o0,%l0,%o0     // alten Carry addieren
          add %o3,%o5,%l0       // add high32(midparts) to high part
          add %l0,1,%o5
          movcs %xcc,%o5,%l0    // neuer Carry
          // Multiplikation fertig
          addcc %i4,%o0,%o0     // alten *destptr addieren
          add %l0,1,%o2
          movcs %xcc,%o2,%l0    // neuer Carry
          brnz,pt %i3,1b
         _ stx %o0,[%i2]        // Low-Digit ablegen
        mov %l0,%i0             // letzter Carry
        ret
       _ restore

// extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(mulusub_loop_down)
C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
        save %sp,-192,%sp
        mov 0,%l0               // Carry
        srlx %i0,32,%l1         // %l1 = high32(digit)
        srl %i0,0,%l2           // %l2 = low32(digit)
        mov 1,%l3
        sllx %l3,32,%l3         // %l3 = 2^32
        sub %i1,%i2,%i1         // %i1 = sourceptr - destptr
1:        sub %i2,8,%i2
          ldx [%i1+%i2],%o0     // nächstes Digit
          ldx [%i2],%i4         // *destptr
          subcc %i3,1,%i3
          // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
          srlx %o0,32,%o1
          srl %o0,0,%o2
          mulx %l1,%o1,%o3      // high part
          mulx %l1,%o2,%o4      // first mid part
          mulx %l2,%o1,%o1      // second mid part
          mulx %l2,%o2,%o2      // low part
          srlx %o2,32,%o5       // low part's upper half
          add %o4,%o5,%o4       // add to one of the mid parts, no carry
          addcc %o4,%o1,%o4     // add other mid part
          add %o3,%l3,%o5
          movcs %xcc,%o5,%o3    // if carry, add 2^32 to the high part
          srlx %o4,32,%o5
          sllx %o4,32,%o4
          srl %o2,0,%o2
          add %o2,%o4,%o0       // combine low32(midparts) and low32(lowpart)
          addcc %o0,%l0,%o0     // alten Carry addieren
          add %o3,%o5,%l0       // add high32(midparts) to high part
          add %l0,1,%o5
          movcs %xcc,%o5,%l0    // neuer Carry
          // Multiplikation fertig
          subcc %i4,%o0,%o0     // vom alten *destptr subtrahieren
          add %l0,1,%o2
          movcs %xcc,%o2,%l0    // neuer Carry
          brnz,pt %i3,1b
         _ stx %o0,[%i2]        // Low-Digit ablegen
        mov %l0,%i0             // letzter Carry
        ret
       _ restore

#endif

#if !CL_DS_BIG_ENDIAN_P

// extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(or_loop_down)
C(or_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(xor_loop_down)
C(xor_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          xor %o3,%o4,%o3       // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          xor %o4,%o3,%o3       // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(and_loop_down)
C(and_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(eqv_loop_down)
C(eqv_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          xnor %o3,%o4,%o3      // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          xnor %o4,%o3,%o3      // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(nand_loop_down)
C(nand_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          xnor %g0,%o3,%o3
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          xnor %g0,%o3,%o3
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(nor_loop_down)
C(nor_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          xnor %g0,%o3,%o3
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          xnor %g0,%o3,%o3
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(andc2_loop_down)
C(andc2_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          andn %o3,%o4,%o3      // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          andn %o4,%o3,%o3      // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(orc2_loop_down)
C(orc2_loop_down:) // Input in %o0,%o1,%o2
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // *xptr
          ldx [%o0+%o1],%o4     // *yptr
          subcc %o2,1,%o2
          orn %o3,%o4,%o3       // verknüpfen
          stx %o3,[%o0]         // =: *xptr
          bne,pt %xcc,1b
         _ sub %o0,8,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sllx %o2,3,%o2         // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o1+%o2],%o3     // nächstes Digit holen
          ldx [%o0+%o2],%o4     // noch ein Digit holen
          orn %o4,%o3,%o3       // beide verknüpfen
          bne,pt %xcc,1b
         _ stx %o3,[%o1+%o2]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern void not_loop_down (uintD* xptr, uintC count);
        DECLARE_FUNCTION(not_loop_down)
C(not_loop_down:) // Input in %o0,%o1
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %o0,8,%o0
1:        ldx [%o0],%o2
          subcc %o1,1,%o1
          xnor %g0,%o2,%o2
          stx %o2,[%o0]
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sllx %o1,3,%o1         // %o1 = 8*count
        sub %o0,%o1,%o0         // %o0 = &destptr[-count]
1:        subcc %o1,8,%o1       // Zähler erniedrigen, Pointer erniedrigen
          ldx [%o0+%o1],%o2     // nächstes Digit holen
          xnor %g0,%o2,%o2
          bne,pt %xcc,1b
         _ stx %o2,[%o0+%o1]    // Digit ablegen
2:      retl
       _ nop
#endif

// extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(and_test_loop_down)
C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,4f
       _ sub %o0,8,%o0
1:        ldx [%o0],%o3
          sub %o1,8,%o1
          ldx [%o1],%o4
          subcc %o2,1,%o2
          be,pn %xcc,3f
         _ andcc %o3,%o4,%g0
          be,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov 1,%o0
3:      bne 2b
       _ nop
4:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        sllx %o2,3,%o2          // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
        subcc %o2,8,%o2
        bcs,pn %xcc,2f
       _ nop
          ldx [%o0+%o2],%o3     // nächstes Digit holen
1:        ldx [%o1+%o2],%o4     // noch ein Digit holen
          andcc %o3,%o4,%g0     // beide verknüpfen
          bne,pn %xcc,3f
         _ subcc %o2,8,%o2      // Zähler erniedrigen, Pointer erniedrigen
          bcc,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // nächstes Digit holen
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif

// extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
        DECLARE_FUNCTION(compare_loop_down)
C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ nop
1:        ldx [%o0-8],%o3
          ldx [%o1-8],%o4
          subcc %o3,%o4,%g0
          bne,pn %xcc,3f
         _ sub %o0,8,%o0
          subcc %o2,1,%o2
          bne,pn %xcc,1b
         _ sub %o1,8,%o1
2:      retl
       _ mov 0,%o0
3:      mov 1,%o0
        movlu %xcc,-1,%o0
        retl
       _ sra %o0,0,%o0          // sign-extend %o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        sllx %o2,3,%o2          // %o2 = 8*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
        subcc %o2,8,%o2
        bcs,pn %xcc,4f
       _ nop
          ldx [%o0+%o2],%o3     // nächstes Digit holen
1:        ldx [%o1+%o2],%o4     // noch ein Digit holen
          subcc %o2,8,%o2       // Zähler erniedrigen, Pointer erniedrigen
          bcs,pn %xcc,3f
         _ subcc %o3,%o4,%g0    // vergleichen
          be,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // nächstes Digit holen
2:      mov 1,%o0
        movlu %xcc,-1,%o0
        retl
       _ sra %o0,0,%o0          // sign-extend %o0
3:      bne 2b
       _ nop
4:      retl
       _ mov 0,%o0
#endif

// extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        DECLARE_FUNCTION(add_loop_up)
C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
#if STANDARD_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
1:        ldx [%o0],%o4         // source1-digit
          add %o0,8,%o0
          ldx [%o1],%o5         // source2-digit
          add %o1,8,%o1
          addcc %o4,%g1,%o4
          movcc %xcc,0,%g1      // %g1|%o4 := %o4 + alter Carry %g1
          addcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %g1|%o4 := %o4 + alter Carry %g1 + %o5
          stx %o4,[%o2]         // Digit ablegen
          subcc %o3,1,%o3
          bne,pt %xcc,1b
         _ add %o2,8,%o2
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
        sub %g0,%o3,%o3         // %o3 = -count
        sllx %o3,3,%o3          // %o3 = -8*count
        sub %o2,8,%o2
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
        sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
1:        ldx [%o0+%o3],%o4     // source1-digit
          ldx [%o1+%o3],%o5     // source2-digit
          addcc %o4,%g1,%o4
          movcc %xcc,0,%g1      // %g1|%o4 := %o4 + alter Carry %g1
          addcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %g1|%o4 := %o4 + alter Carry %g1 + %o5
          addcc %o3,8,%o3       // Zähler erniedrigen, Pointer erhöhen
          bne,pt %xcc,1b
         _ stx %o4,[%o2+%o3]    // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif

// extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
        DECLARE_FUNCTION(addto_loop_up)
C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
1:        ldx [%o0],%o3         // source-digit
          add %o0,8,%o0
          ldx [%o1],%o4         // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          addcc %o3,%o4,%o4
          movcs %xcc,1,%o5      // %o5|%o4 := %o3 + alter Carry %o5 + %o4
          stx %o4,[%o1]         // Digit ablegen
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ add %o1,8,%o1
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
        sub %o1,%o2,%o1         // %o1 = &destptr[count]
          ldx [%o0+%o2],%o3     // source-digit
1:        ldx [%o1+%o2],%o4     // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          addcc %o3,%o4,%o4
          movcs %xcc,1,%o5      // %o5|%o4 := %o3 + alter Carry %o5 + %o4
          stx %o4,[%o1+%o2]     // Digit ablegen
          addcc %o2,8,%o2       // Zähler erniedrigen, Pointer erhöhen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // source-digit
2:      retl
       _ mov %o5,%o0
#endif

// extern uintD inc_loop_up (uintD* ptr, uintC count);
        DECLARE_FUNCTION(inc_loop_up)
C(inc_loop_up:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ nop
          ldx [%o0],%o2
1:        add %o0,8,%o0
          addcc %o2,1,%o2
          bne,pn %xcc,3f
         _ stx %o2,[%o0-8]
          subcc %o1,1,%o1
          bne,a,pt %xcc,1b
         __ ldx [%o0],%o2
2:      retl
       _ mov 1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %g0,%o1,%o1        // %o1 = -count
        sllx %o1,3,%o1          // %o1 = -8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ldx [%o0+%o1],%o2     // digit holen
1:        addcc %o2,1,%o2       // incrementieren
          bne,pn %xcc,3f
         _ stx %o2,[%o0+%o1]    // ablegen
          addcc %o1,8,%o1       // Zähler erniedrigen, Pointer erhöhen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2
2:      retl
       _ mov 1,%o0
3:      retl
       _ mov 0,%o0
#endif

// extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        DECLARE_FUNCTION(sub_loop_up)
C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
#if STANDARD_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
1:        ldx [%o0],%o4         // source1-digit
          add %o0,8,%o0
          ldx [%o1],%o5         // source2-digit
          add %o1,8,%o1
          addcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %g1|%o5 := %o5 + alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
          stx %o4,[%o2]         // Digit ablegen
          subcc %o3,1,%o3
          bne,pt %xcc,1b
         _ add %o2,8,%o2
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %g0,%g1            // Carry := 0
        sub %g0,%o3,%o3         // %o3 = -count
        sllx %o3,3,%o3          // %o3 = -8*count
        sub %o2,8,%o2
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
        sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
1:        ldx [%o1+%o3],%o5     // source2-digit
          ldx [%o0+%o3],%o4     // source1-digit
          addcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %g1|%o5 := %o5 + alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,1,%g1      // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1
          addcc %o3,8,%o3
          bne,pt %xcc,1b
         _ stx %o4,[%o2+%o3]    // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif

// extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
        DECLARE_FUNCTION(subx_loop_up)
C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
#if STANDARD_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %o4,%g1            // Carry (0 oder -1)
1:        ldx [%o0],%o4         // source1-digit
          add %o0,8,%o0
          ldx [%o1],%o5         // source2-digit
          add %o1,8,%o1
          subcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %o5-2^64*%g1 := %o5 - alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,-1,%g1     // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
          stx %o4,[%o2]         // Digit ablegen
          subcc %o3,1,%o3
          bne,pt %xcc,1b
         _ add %o2,8,%o2
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o3,0,%o3           // zero-extend %o3 = count
        brz,pn %o3,2f
       _ mov %o4,%g1            // Carry (0 oder -1)
        sub %g0,%o3,%o3         // %o3 = -count
        sllx %o3,3,%o3          // %o3 = -8*count
        sub %o2,8,%o2
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
        sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
1:        ldx [%o1+%o3],%o5     // source2-digit
          ldx [%o0+%o3],%o4     // source1-digit
          subcc %o5,%g1,%o5
          movcc %xcc,0,%g1      // %o5-2^64*%g1 := %o5 - alter Carry %g1
          subcc %o4,%o5,%o4
          movcs %xcc,-1,%g1     // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1
          addcc %o3,8,%o3
          bne,pt %xcc,1b
         _ stx %o4,[%o2+%o3]    // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif

// extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
        DECLARE_FUNCTION(subfrom_loop_up)
C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
#if STANDARD_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
1:        ldx [%o0],%o3         // source-digit
          add %o0,8,%o0
          ldx [%o1],%o4         // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          subcc %o4,%o3,%o4
          movcs %xcc,1,%o5      // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
          stx %o4,[%o1]         // Digit ablegen
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ add %o1,8,%o1
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov %g0,%o5            // Carry := 0
        sub %g0,%o2,%o2         // %o2 = -count
        sllx %o2,3,%o2          // %o2 = -8*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
        sub %o1,%o2,%o1         // %o1 = &destptr[count]
          ldx [%o0+%o2],%o3     // source-digit
1:        ldx [%o1+%o2],%o4     // dest-digit
          addcc %o3,%o5,%o3
          movcc %xcc,0,%o5      // %o5|%o3 := %o3 + alter Carry %o5
          subcc %o4,%o3,%o4
          movcs %xcc,1,%o5      // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5
          stx %o4,[%o1+%o2]     // Digit ablegen
          addcc %o2,8,%o2
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o2],%o3   // source-digit
2:      retl
       _ mov %o5,%o0
#endif

// extern uintD dec_loop_up (uintD* ptr, uintC count);
        DECLARE_FUNCTION(dec_loop_up)
C(dec_loop_up:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ nop
          ldx [%o0],%o2
1:        add %o0,8,%o0
          subcc %o2,1,%o2
          bcc,pn %xcc,3f
         _ stx %o2,[%o0-8]
          subcc %o1,1,%o1
          bne,a,pt %xcc,1b
         __ ldx [%o0],%o2
2:      retl
       _ mov -1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %g0,%o1,%o1        // %o1 = -count
        sllx %o1,3,%o1          // %o1 = -8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ldx [%o0+%o1],%o2     // digit holen
1:        subcc %o2,1,%o2       // decrementieren
          bcc,pn %xcc,3f
         _ stx %o2,[%o0+%o1]    // ablegen
          addcc %o1,8,%o1       // Zähler erniedrigen, Pointer erhöhen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2
2:      retl
       _ mov -1,%o0
3:      retl
       _ mov 0,%o0
#endif

// extern uintD neg_loop_up (uintD* ptr, uintC count);
        DECLARE_FUNCTION(neg_loop_up)
C(neg_loop_up:) // Input in %o0,%o1, Output in %o0
#if STANDARD_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        // erstes Digit /=0 suchen:
        brz,pn %o1,2f
       _ add %o0,8,%o0
1:        ldx [%o0-8],%o2
          subcc %g0,%o2,%o2
          bne,pn %xcc,3f
         _ subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // 1 Digit negieren, alle anderen Digits invertieren:
        be,pn %xcc,5f
       _ stx %o2,[%o0-8]
4:        ldx [%o0],%o2
          subcc %o1,1,%o1
          xnor %g0,%o2,%o2
          stx %o2,[%o0]
          bne,pt %xcc,4b
         _ add %o0,8,%o0
5:      retl
       _ mov -1,%o0
#endif
#if COUNTER_LOOPS
//      srl %o1,0,%o1           // zero-extend %o1 = count
        // erstes Digit /=0 suchen:
        brz,pn %o1,2f
       _ sub %g0,%o1,%o1        // %o1 = -count
        sllx %o1,3,%o1          // %o1 = -8*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ldx [%o0+%o1],%o2     // digit holen
1:        subcc %g0,%o2,%o2     // negieren, testen
          bne,pn %xcc,3f
         _ addcc %o1,8,%o1      // Zähler erniedrigen, Pointer erhöhen
          bne,a,pt %xcc,1b
         __ ldx [%o0+%o1],%o2
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // alle anderen Digits invertieren:
        sub %o1,8,%o1
        stx %o2,[%o0+%o1]       // ablegen
        addcc %o1,8,%o1
        be,pn %xcc,5f
       _ nop
          ldx [%o0+%o1],%o2
4:        xnor %g0,%o2,%o2
          stx %o2,[%o0+%o1]
          addcc %o1,8,%o1
          bne,a,pt %xcc,4b
         __ ldx [%o0+%o1],%o2
5:      retl
       _ mov -1,%o0
#endif

// extern uintD shift1left_loop_up (uintD* ptr, uintC count);
        DECLARE_FUNCTION(shift1left_loop_up)
C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ mov 0,%o3              // Carry := 0
1:        ldx [%o0],%o2         // Digit
          addcc %o2,%o2,%o4     // shiften
          add %o4,%o3,%o4       // und carry
          srlx %o2,63,%o3       // neues Carry
          stx %o4,[%o0]         // Digit ablegen
          subcc %o1,1,%o1
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ mov %o3,%o0

// extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
        DECLARE_FUNCTION(shiftleft_loop_up)
C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sub %g0,%o2,%g1        // 64-i (mod 64)
1:        ldx [%o0],%o4         // Digit
          subcc %o1,1,%o1
          sllx %o4,%o2,%o5      // dessen niedere (64-i) Bits
          or %o3,%o5,%o5        // mit dem alten Carry kombinieren
          stx %o5,[%o0]         // Digit ablegen
          srlx %o4,%g1,%o3      // dessen höchste i Bits liefern den neuen Carry
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ mov %o3,%o0

#endif

// extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
        DECLARE_FUNCTION(shiftleftcopy_loop_up)
C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ mov 0,%o4              // Carry := 0
        sub %g0,%o3,%g1         // 64-i (mod 64)
1:        ldx [%o0],%o5         // Digit
          subcc %o2,1,%o2
          sllx %o5,%o3,%g2      // dessen niedere (64-i) Bits
          or %o4,%g2,%g2        // mit dem alten Carry kombinieren
          stx %g2,[%o1]         // Digit ablegen
          add %o1,8,%o1
          srlx %o5,%g1,%o4      // dessen höchste i Bits liefern den neuen Carry
          bne,pt %xcc,1b
         _ add %o0,8,%o0
2:      retl
       _ mov %o4,%o0

#if !CL_DS_BIG_ENDIAN_P

// extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
        DECLARE_FUNCTION(shift1right_loop_down)
C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        brz,pn %o1,2f
       _ sllx %o2,63,%o2        // Carry
        sub %o0,8,%o0
1:        ldx [%o0],%o3         // Digit
          subcc %o1,1,%o1
          srlx %o3,1,%o4        // shiften
          or %o2,%o4,%o4        // und mit altem Carry kombinieren
          stx %o4,[%o0]         // und ablegen
          sllx %o3,63,%o2       // neuer Carry
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o2,%o0

// extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
        DECLARE_FUNCTION(shiftright_loop_down)
C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        sub %g0,%o2,%g1         // 64-i (mod 64)
        brz,pn %o1,2f
       _ or %g0,%g0,%o3         // Carry := 0
        sub %o0,8,%o0
1:        ldx [%o0],%o4         // Digit
          subcc %o1,1,%o1
          srlx %o4,%o2,%o5      // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          stx %o5,[%o0]         // und ablegen
          sllx %o4,%g1,%o3      // neuer Carry
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o3,%o0

// extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
        DECLARE_FUNCTION(shiftrightsigned_loop_down)
C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
//      srl %o1,0,%o1           // zero-extend %o1 = count
        ldx [%o0-8],%o4         // erstes Digit
        sub %g0,%o2,%g1         // 64-i (mod 64)
        srax %o4,%o2,%o5        // shiften
        stx %o5,[%o0-8]         // und ablegen
        sllx %o4,%g1,%o3        // neuer Carry
        subcc %o1,1,%o1
        be,pn %xcc,2f
       _ sub %o0,16,%o0
1:        ldx [%o0],%o4         // Digit
          subcc %o1,1,%o1
          srlx %o4,%o2,%o5      // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          stx %o5,[%o0]         // und ablegen
          sllx %o4,%g1,%o3      // neuer Carry
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %o3,%o0

// extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
        DECLARE_FUNCTION(shiftrightcopy_loop_down)
C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
//      srl %o2,0,%o2           // zero-extend %o2 = count
        sub %g0,%o3,%g1         // 64-i (mod 64)
        brz,pn %o2,2f
       _ sllx %o4,%g1,%g2       // erster Carry
          sub %o0,8,%o0
1:        ldx [%o0],%o4         // Digit
          sub %o1,8,%o1
          srlx %o4,%o3,%o5      // shiften
          or %g2,%o5,%o5        // und mit altem Carry kombinieren
          stx %o5,[%o1]         // und ablegen
          sllx %o4,%g1,%g2      // neuer Carry
          subcc %o2,1,%o2
          bne,pt %xcc,1b
         _ sub %o0,8,%o0
2:      retl
       _ mov %g2,%o0

// extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
        DECLARE_FUNCTION(mulusmall_loop_up)
C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1
//      srl %o2,0,%o2           // zero-extend %o2 = len
        brz,pn %o2,2f
       _ nop
1:        // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
          // und kleinen Carry %o3 dazu:
          ldx [%o1],%o4
          sub %o2,1,%o2
          srlx %o4,32,%o5       // high32(x)
          srl %o4,0,%o4         // low32(x)
          mulx %o4,%o0,%o4      // low32(x)*digit
          mulx %o5,%o0,%o5      // high32(x)*digit
          sllx %o5,32,%g1       // low32(high32(x)*digit)*2^32
          add %g1,%o3,%g1       // plus carry
          addcc %o4,%g1,%o4     // plus low32(x)*digit
          srlx %o5,32,%o3       // high32(high32(x)*digit)
          add %o3,1,%g1
          movcs %xcc,%g1,%o3    // neuer Carry
          stx %o4,[%o1]         // neues Digit ablegen
          brnz,pt %o2,1b
         _ add %o1,8,%o1
2:      retl
       _ mov %o3,%o0

// extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(mulu_loop_up)
C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
        save %sp,-192,%sp
        mov 0,%l0               // Carry
        srlx %i0,32,%l1         // %l1 = high32(digit)
        srl %i0,0,%l2           // %l2 = low32(digit)
        mov 1,%l3
        sllx %l3,32,%l3         // %l3 = 2^32
        sub %i1,%i2,%i1         // %i1 = sourceptr - destptr
1:        ldx [%i1+%i2],%o0     // nächstes Digit
          subcc %i3,1,%i3
          // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
          srlx %o0,32,%o1
          srl %o0,0,%o2
          mulx %l1,%o1,%o3      // high part
          mulx %l1,%o2,%o4      // first mid part
          mulx %l2,%o1,%o1      // second mid part
          mulx %l2,%o2,%o2      // low part
          srlx %o2,32,%o5       // low part's upper half
          add %o4,%o5,%o4       // add to one of the mid parts, no carry
          addcc %o4,%o1,%o4     // add other mid part
          add %o3,%l3,%o5
          movcs %xcc,%o5,%o3    // if carry, add 2^32 to the high part
          srlx %o4,32,%o5
          sllx %o4,32,%o4
          srl %o2,0,%o2
          add %o2,%o4,%o0       // combine low32(midparts) and low32(lowpart)
          addcc %o0,%l0,%o0     // alten Carry addieren
          add %o3,%o5,%l0       // add high32(midparts) to high part
          add %l0,1,%o5
          movcs %xcc,%o5,%l0    // neuer Carry
          // Multiplikation fertig
          stx %o0,[%i2]         // Low-Digit ablegen
          brnz,pt %i3,1b
         _ add %i2,8,%i2
        stx %l0,[%i2]           // letzten Carry ablegen
        ret
       _ restore

// extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(muluadd_loop_up)
C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
        save %sp,-192,%sp
        mov 0,%l0               // Carry
        srlx %i0,32,%l1         // %l1 = high32(digit)
        srl %i0,0,%l2           // %l2 = low32(digit)
        mov 1,%l3
        sllx %l3,32,%l3         // %l3 = 2^32
        sub %i1,%i2,%i1         // %i1 = sourceptr - destptr
1:        ldx [%i1+%i2],%o0     // nächstes Digit
          ldx [%i2],%i4         // *destptr
          subcc %i3,1,%i3
          // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
          srlx %o0,32,%o1
          srl %o0,0,%o2
          mulx %l1,%o1,%o3      // high part
          mulx %l1,%o2,%o4      // first mid part
          mulx %l2,%o1,%o1      // second mid part
          mulx %l2,%o2,%o2      // low part
          srlx %o2,32,%o5       // low part's upper half
          add %o4,%o5,%o4       // add to one of the mid parts, no carry
          addcc %o4,%o1,%o4     // add other mid part
          add %o3,%l3,%o5
          movcs %xcc,%o5,%o3    // if carry, add 2^32 to the high part
          srlx %o4,32,%o5
          sllx %o4,32,%o4
          srl %o2,0,%o2
          add %o2,%o4,%o0       // combine low32(midparts) and low32(lowpart)
          addcc %o0,%l0,%o0     // alten Carry addieren
          add %o3,%o5,%l0       // add high32(midparts) to high part
          add %l0,1,%o5
          movcs %xcc,%o5,%l0    // neuer Carry
          // Multiplikation fertig
          addcc %i4,%o0,%o0     // alten *destptr addieren
          add %l0,1,%o2
          movcs %xcc,%o2,%l0    // neuer Carry
          stx %o0,[%i2]         // Low-Digit ablegen
          brnz,pt %i3,1b
         _ add %i2,8,%i2
        mov %l0,%i0             // letzter Carry
        ret
       _ restore

// extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(mulusub_loop_up)
C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
        save %sp,-192,%sp
        mov 0,%l0               // Carry
        srlx %i0,32,%l1         // %l1 = high32(digit)
        srl %i0,0,%l2           // %l2 = low32(digit)
        mov 1,%l3
        sllx %l3,32,%l3         // %l3 = 2^32
        sub %i1,%i2,%i1         // %i1 = sourceptr - destptr
1:        ldx [%i1+%i2],%o0     // nächstes Digit
          ldx [%i2],%i4         // *destptr
          subcc %i3,1,%i3
          // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0
          srlx %o0,32,%o1
          srl %o0,0,%o2
          mulx %l1,%o1,%o3      // high part
          mulx %l1,%o2,%o4      // first mid part
          mulx %l2,%o1,%o1      // second mid part
          mulx %l2,%o2,%o2      // low part
          srlx %o2,32,%o5       // low part's upper half
          add %o4,%o5,%o4       // add to one of the mid parts, no carry
          addcc %o4,%o1,%o4     // add other mid part
          add %o3,%l3,%o5
          movcs %xcc,%o5,%o3    // if carry, add 2^32 to the high part
          srlx %o4,32,%o5
          sllx %o4,32,%o4
          srl %o2,0,%o2
          add %o2,%o4,%o0       // combine low32(midparts) and low32(lowpart)
          addcc %o0,%l0,%o0     // alten Carry addieren
          add %o3,%o5,%l0       // add high32(midparts) to high part
          add %l0,1,%o5
          movcs %xcc,%o5,%l0    // neuer Carry
          // Multiplikation fertig
          subcc %i4,%o0,%o0     // vom alten *destptr subtrahieren
          add %l0,1,%o2
          movcs %xcc,%o2,%l0    // neuer Carry
          stx %o0,[%i2]         // Low-Digit ablegen
          brnz,pt %i3,1b
         _ add %i2,8,%i2
        mov %l0,%i0             // letzter Carry
        ret
       _ restore

#endif

// extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
        DECLARE_FUNCTION(shiftxor_loop_up)
C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2
//      srl %o2,0,%o2           // zero-extend %o2 = count
        brz,pn %o2,2f
       _ sub %g0,%o3,%g1        // 64-i (mod 64)
        sub %o1,%o0,%o1
        ldx [%o0],%o4           // *xptr holen
1:        ldx [%o0+%o1],%o5     // *yptr holen
          subcc %o2,1,%o2
          sllx %o5,%o3,%g2      // dessen niedere (64-i) Bits
          xor %o4,%g2,%o4       // mit dem modifizierten *xptr kombinieren
          stx %o4,[%o0]         // und ablegen
          add %o0,8,%o0
          srlx %o5,%g1,%g2      // höchste i Bits von *yptr
          ldx [%o0],%o4         // schon mal mit dem nächsten *xptr
          bne,pt %xcc,1b
         _ xor %o4,%g2,%o4      // verknüpfen
        stx %o4,[%o0]           // und ablegen
2:      retl
       _ nop

