// Externe Routinen zu ARILEV1.D
// Prozessor: SPARC
// Compiler: GNU-C oder SUN-C
// Parameter-Übergabe: in Registern %o0-%o5.
// Einstellungen: intCsize=32, intDsize=32.

#if defined(sparc_v8) || defined(__sparc_v8) || defined(__sparc_v8__)
  #define sparcv8
#endif

#ifdef ASM_UNDERSCORE /* SunOS 4 */
  #if defined(__STDC__) || defined (__cplusplus)
    #define C(entrypoint) _##entrypoint
  #else
    #define C(entrypoint) _/**/entrypoint
  #endif
#else /* SunOS 5 = Solaris 2 */
  #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)
        .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)
        .global C(divu_loop_up),C(divucopy_loop_up)
#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)
        .global C(divu_loop_down),C(divucopy_loop_down)
#endif

#define LOOP_TYPE  1    // 1: Standard-Schleifen
                        // 2: Schleifen ohne Pointer, nur mit Zähler
                        // 3: entrollte Schleifen
#define SLOW_LOOPS  0
#define STANDARD_LOOPS  (LOOP_TYPE==1)
#define COUNTER_LOOPS  (LOOP_TYPE==2)
#define UNROLLED_LOOPS  (LOOP_TYPE==3)
#define MULU32_INLINE  1  // 1: mulu32-Aufrufe inline in die Schleifen

// extern uint32 mulu16_ (uint16 arg1, uint16 arg2);
// ergebnis := arg1*arg2.
        DECLARE_FUNCTION(mulu16_)
C(mulu16_:) // Input in %o0,%o1, Output in %o0
#ifdef sparcv8
        umul    %o0,%o1,%o0
        retl
       _ nop
#else
        mov     %o1,%y
        nop                     // Wartetakt, nötig z.B. für SUN SPARCstation IPC
        andcc   %g0,%g0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
        // ergeben das Resultat. (Die anderen Bits sind Null.)
        rd      %y,%o0
        srl     %o0,17,%o0
        sll     %o2,15,%o2
        retl
       _ or      %o2,%o0,%o0
#endif

// 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
#ifdef sparcv8
        umul    %o0,%o1,%o0
        retl
       _ rd      %y,%g1
#else
        mov     %o1,%y
        sra     %o0,31,%o3      // Wartetakt, nötig z.B. für SUN SPARCstation IPC
        andcc   %g0,%g0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%g0,%o2
        and     %o3,%o1,%o3     // %o3 = (0 falls %o0>=0, %o1 falls %o0<0)
        add     %o2,%o3,%g1     // hi
        retl
       _ rd      %y,%o0         // lo
#endif

// 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
#ifdef sparcv8
        umul    %o0,%o1,%o0
        retl
       _ nop
#else
        subcc   %o0,%o1,%g0
        bcc,a   1f
       __ mov     %o1,%y
        // arg1 < arg2, also kann man arg1 < 2^16 annehmen.
        mov     %o0,%y
        nop                     // Wartetakt, nötig z.B. für SUN SPARCstation IPC
        andcc   %g0,%g0,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        mulscc  %o2,%o1,%o2
        // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
        // ergeben das Resultat. (Die anderen Bits sind Null.)
        rd      %y,%o0
        srl     %o0,17,%o0
        sll     %o2,15,%o2
        retl
       _ or      %o2,%o0,%o0
1:      // arg1 >= arg2, also kann man arg2 < 2^16 annehmen.
        nop                     // Wartetakt, nötig z.B. für SUN SPARCstation IPC
        andcc   %g0,%g0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        mulscc  %o2,%o0,%o2
        // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
        // ergeben das Resultat.
        rd      %y,%o0
        srl     %o0,17,%o0
        sll     %o2,15,%o2
        retl
       _ or      %o2,%o0,%o0
#endif

// 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
#if defined(sparcv8)
        // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
        wr      %o0,%g0,%y
        nop                     // wait 1 | Necessary for certain sparcv8
        nop                     // wait 2 | processors such as Ross Hypersparc,
        nop                     // wait 3 | but not for most of the others.
        udiv    %o1,%o2,%o0     // x durch y dividieren, %o0 := q
        umul    %o0,%o2,%g1     // %g1 := (q*y) mod 2^32
        retl
       _ sub     %o1,%g1,%g1    // %g1 := (xlo-q*y) mod 2^32 = r
#else
        // %o0 = xhi, %o1 = xlo, %o2 = y
// Divisions-Einzelschritte:
// %o0|%o1  wird jeweils um 1 Bit nach links geschoben,
// dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben.
// Je nachdem wird mit %o3|%o1 statt %o0|%o1 weitergemacht (spart 1 'mov').
// Deswegen muß man den Code doppelt vorsehen: einmal mit %o0, einmal mit %o3.
#define SA0(label) /* Vergleichsschritt mit %o0  */\
        subcc   %o0,%o2,%o3; \
        bcc     label;       \
       _ addxcc  %o1,%o1,%o1
#define SA1(label) /* Vergleichsschritt mit %o3  */\
        subcc   %o3,%o2,%o0; \
        bcc     label;       \
       _ addxcc  %o1,%o1,%o1
#define SB0() /* Additionsschritt mit %o0  */\
        addx    %o0,%o0,%o0
#define SB1() /* Additionsschritt mit %o3  */\
        addx    %o3,%o3,%o3
// Los geht's:
        addcc   %o2,%o2,%g0     // y = %o2 < 2^31 ?
        bcc     Lsmalldiv       // ja -> "kleine" Division
       _ andcc   %o2,1,%g0      // y = %o2 gerade ?
        be      Levendiv        // ja -> Division durch gerade Zahl
       _ srl     %o2,1,%o2
        // Division durch ungerade Zahl:
        // floor(x / (2*y'-1)) = floor(floor(x/2) / y') + (0 oder 1 oder 2)
        // da  0 <= x/(2*y'-1) - x/(2*y') = x/(2*y'-1) / (2*y') = x/y / (2*y')
        //       < 2^32 / (2*y') < 2^32/y <= 2 .
        add     %o2,1,%o2       // %o2 = ceiling(y/2) = y'
        // Man spart im Vergleich zu Lsmalldiv
        // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0()
        // dafür am Schluß mehr zu tun...
        SA0(Lb01)               // Bit 31 des Quotienten bestimmen
La01:   SB0(); SA0(Lb02)        // Bit 30 des Quotienten bestimmen
La02:   SB0(); SA0(Lb03)        // Bit 29 des Quotienten bestimmen
La03:   SB0(); SA0(Lb04)        // Bit 28 des Quotienten bestimmen
La04:   SB0(); SA0(Lb05)        // Bit 27 des Quotienten bestimmen
La05:   SB0(); SA0(Lb06)        // Bit 26 des Quotienten bestimmen
La06:   SB0(); SA0(Lb07)        // Bit 25 des Quotienten bestimmen
La07:   SB0(); SA0(Lb08)        // Bit 24 des Quotienten bestimmen
La08:   SB0(); SA0(Lb09)        // Bit 23 des Quotienten bestimmen
La09:   SB0(); SA0(Lb10)        // Bit 22 des Quotienten bestimmen
La10:   SB0(); SA0(Lb11)        // Bit 21 des Quotienten bestimmen
La11:   SB0(); SA0(Lb12)        // Bit 20 des Quotienten bestimmen
La12:   SB0(); SA0(Lb13)        // Bit 19 des Quotienten bestimmen
La13:   SB0(); SA0(Lb14)        // Bit 18 des Quotienten bestimmen
La14:   SB0(); SA0(Lb15)        // Bit 17 des Quotienten bestimmen
La15:   SB0(); SA0(Lb16)        // Bit 16 des Quotienten bestimmen
La16:   SB0(); SA0(Lb17)        // Bit 15 des Quotienten bestimmen
La17:   SB0(); SA0(Lb18)        // Bit 14 des Quotienten bestimmen
La18:   SB0(); SA0(Lb19)        // Bit 13 des Quotienten bestimmen
La19:   SB0(); SA0(Lb20)        // Bit 12 des Quotienten bestimmen
La20:   SB0(); SA0(Lb21)        // Bit 11 des Quotienten bestimmen
La21:   SB0(); SA0(Lb22)        // Bit 10 des Quotienten bestimmen
La22:   SB0(); SA0(Lb23)        // Bit 9 des Quotienten bestimmen
La23:   SB0(); SA0(Lb24)        // Bit 8 des Quotienten bestimmen
La24:   SB0(); SA0(Lb25)        // Bit 7 des Quotienten bestimmen
La25:   SB0(); SA0(Lb26)        // Bit 6 des Quotienten bestimmen
La26:   SB0(); SA0(Lb27)        // Bit 5 des Quotienten bestimmen
La27:   SB0(); SA0(Lb28)        // Bit 4 des Quotienten bestimmen
La28:   SB0(); SA0(Lb29)        // Bit 3 des Quotienten bestimmen
La29:   SB0(); SA0(Lb30)        // Bit 2 des Quotienten bestimmen
La30:   SB0(); SA0(Lb31)        // Bit 1 des Quotienten bestimmen
La31:   SB0(); SA0(Lb32)        // Bit 0 des Quotienten bestimmen
La32:   SB0()                   // %o0 = x mod (2*y')
        xor     %o1,-1,%o1      // %o1 = floor( floor(x/2) / y') = floor(x/(2*y'))
        add     %o2,%o2,%o2
        sub     %o2,1,%o2       // wieder %o2 = 2*y'-1 = y
        // Quotient und Rest umrechnen:
        // x = %o1 * 2*y' + %o0 = %o1 * (2*y'-1) + (%o0+%o1)
        // Also Quotient = %o1, Rest = %o0+%o1.
        // Noch maximal 2 mal: Quotient += 1, Rest -= y.
        addcc   %o1,%o0,%o0     // Rest mod y bestimmen
        bcc     1f              // Additions-Überlauf -> Quotient erhöhen
       _ subcc   %o0,%o2,%o3
        subcc   %o3,%o2,%o0     // muß der Quotient nochmals erhöht werden?
        bcs     2f
       _ mov     %o3,%g1
        // Quotient 2 mal erhöhen, Rest %o0
        mov     %o0,%g1
        retl
       _ add     %o1,2,%o0
1:      // kein Additions-Überlauf.
        // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden:
        bcs     3f              // %o0 < %o2 -> Rest %o0 und Quotient %o1 OK
       _ mov     %o3,%g1
2:      // Quotient %o1 erhöhen, Rest = %o0-%o2 = %o3
        retl
       _ add     %o1,1,%o0
3:      // Quotient %o1 und Rest %o0 OK
        mov     %o0,%g1
        retl
       _ mov     %o1,%o0
// Parallelschiene zu La01..La32:
Lb01:   SB1(); SA1(La02)
Lb02:   SB1(); SA1(La03)
Lb03:   SB1(); SA1(La04)
Lb04:   SB1(); SA1(La05)
Lb05:   SB1(); SA1(La06)
Lb06:   SB1(); SA1(La07)
Lb07:   SB1(); SA1(La08)
Lb08:   SB1(); SA1(La09)
Lb09:   SB1(); SA1(La10)
Lb10:   SB1(); SA1(La11)
Lb11:   SB1(); SA1(La12)
Lb12:   SB1(); SA1(La13)
Lb13:   SB1(); SA1(La14)
Lb14:   SB1(); SA1(La15)
Lb15:   SB1(); SA1(La16)
Lb16:   SB1(); SA1(La17)
Lb17:   SB1(); SA1(La18)
Lb18:   SB1(); SA1(La19)
Lb19:   SB1(); SA1(La20)
Lb20:   SB1(); SA1(La21)
Lb21:   SB1(); SA1(La22)
Lb22:   SB1(); SA1(La23)
Lb23:   SB1(); SA1(La24)
Lb24:   SB1(); SA1(La25)
Lb25:   SB1(); SA1(La26)
Lb26:   SB1(); SA1(La27)
Lb27:   SB1(); SA1(La28)
Lb28:   SB1(); SA1(La29)
Lb29:   SB1(); SA1(La30)
Lb30:   SB1(); SA1(La31)
Lb31:   SB1(); SA1(La32)
Lb32:   SB1()                   // %o3 = x mod (2*y')
        xor     %o1,-1,%o1      // %o1 = floor( floor(x/2) / y') = floor(x/(2*y'))
        add     %o2,%o2,%o2
        sub     %o2,1,%o2       // wieder %o2 = 2*y'-1 = y
        // Quotient und Rest umrechnen:
        // x = %o1 * 2*y' + %o3 = %o1 * (2*y'-1) + (%o3+%o1)
        // Also Quotient = %o1, Rest = %o3+%o1.
        // Noch maximal 2 mal: Quotient += 1, Rest -= y.
        addcc   %o1,%o3,%o3     // Rest mod y bestimmen
        bcc     1f              // Additions-Überlauf -> Quotient erhöhen
       _ subcc   %o3,%o2,%o0
        subcc   %o0,%o2,%o3     // muß der Quotient nochmals erhöht werden?
        bcs     2f
       _ mov     %o0,%g1
        // Quotient 2 mal erhöhen, Rest %o3
        mov     %o3,%g1
        retl
       _ add     %o1,2,%o0
1:      // kein Additions-Überlauf.
        // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden:
        bcs     3f              // %o3 < %o2 -> Rest %o3 und Quotient %o1 OK
       _ mov     %o0,%g1
2:      // Quotient %o1 erhöhen, Rest = %o3-%o2 = %o0
        retl
       _ add     %o1,1,%o0
3:      // Quotient %o1 und Rest %o3 OK
        mov     %o3,%g1
        retl
       _ mov     %o1,%o0
Lsmalldiv: // Division durch y < 2^31
        addcc   %o1,%o1,%o1
Lc00:   SB0(); SA0(Ld01)        // Bit 31 des Quotienten bestimmen
Lc01:   SB0(); SA0(Ld02)        // Bit 30 des Quotienten bestimmen
Lc02:   SB0(); SA0(Ld03)        // Bit 29 des Quotienten bestimmen
Lc03:   SB0(); SA0(Ld04)        // Bit 28 des Quotienten bestimmen
Lc04:   SB0(); SA0(Ld05)        // Bit 27 des Quotienten bestimmen
Lc05:   SB0(); SA0(Ld06)        // Bit 26 des Quotienten bestimmen
Lc06:   SB0(); SA0(Ld07)        // Bit 25 des Quotienten bestimmen
Lc07:   SB0(); SA0(Ld08)        // Bit 24 des Quotienten bestimmen
Lc08:   SB0(); SA0(Ld09)        // Bit 23 des Quotienten bestimmen
Lc09:   SB0(); SA0(Ld10)        // Bit 22 des Quotienten bestimmen
Lc10:   SB0(); SA0(Ld11)        // Bit 21 des Quotienten bestimmen
Lc11:   SB0(); SA0(Ld12)        // Bit 20 des Quotienten bestimmen
Lc12:   SB0(); SA0(Ld13)        // Bit 19 des Quotienten bestimmen
Lc13:   SB0(); SA0(Ld14)        // Bit 18 des Quotienten bestimmen
Lc14:   SB0(); SA0(Ld15)        // Bit 17 des Quotienten bestimmen
Lc15:   SB0(); SA0(Ld16)        // Bit 16 des Quotienten bestimmen
Lc16:   SB0(); SA0(Ld17)        // Bit 15 des Quotienten bestimmen
Lc17:   SB0(); SA0(Ld18)        // Bit 14 des Quotienten bestimmen
Lc18:   SB0(); SA0(Ld19)        // Bit 13 des Quotienten bestimmen
Lc19:   SB0(); SA0(Ld20)        // Bit 12 des Quotienten bestimmen
Lc20:   SB0(); SA0(Ld21)        // Bit 11 des Quotienten bestimmen
Lc21:   SB0(); SA0(Ld22)        // Bit 10 des Quotienten bestimmen
Lc22:   SB0(); SA0(Ld23)        // Bit 9 des Quotienten bestimmen
Lc23:   SB0(); SA0(Ld24)        // Bit 8 des Quotienten bestimmen
Lc24:   SB0(); SA0(Ld25)        // Bit 7 des Quotienten bestimmen
Lc25:   SB0(); SA0(Ld26)        // Bit 6 des Quotienten bestimmen
Lc26:   SB0(); SA0(Ld27)        // Bit 5 des Quotienten bestimmen
Lc27:   SB0(); SA0(Ld28)        // Bit 4 des Quotienten bestimmen
Lc28:   SB0(); SA0(Ld29)        // Bit 3 des Quotienten bestimmen
Lc29:   SB0(); SA0(Ld30)        // Bit 2 des Quotienten bestimmen
Lc30:   SB0(); SA0(Ld31)        // Bit 1 des Quotienten bestimmen
Lc31:   SB0(); SA0(Ld32)        // Bit 0 des Quotienten bestimmen
Lc32:   mov     %o0,%g1         // Rest aus %o0 in %g1 abspeichern
        retl
       _ xor     %o1,-1,%o0     // Quotient nach %o0
// Parallelschiene zu Lc01..Lc32:
Ld01:   SB1(); SA1(Lc02)
Ld02:   SB1(); SA1(Lc03)
Ld03:   SB1(); SA1(Lc04)
Ld04:   SB1(); SA1(Lc05)
Ld05:   SB1(); SA1(Lc06)
Ld06:   SB1(); SA1(Lc07)
Ld07:   SB1(); SA1(Lc08)
Ld08:   SB1(); SA1(Lc09)
Ld09:   SB1(); SA1(Lc10)
Ld10:   SB1(); SA1(Lc11)
Ld11:   SB1(); SA1(Lc12)
Ld12:   SB1(); SA1(Lc13)
Ld13:   SB1(); SA1(Lc14)
Ld14:   SB1(); SA1(Lc15)
Ld15:   SB1(); SA1(Lc16)
Ld16:   SB1(); SA1(Lc17)
Ld17:   SB1(); SA1(Lc18)
Ld18:   SB1(); SA1(Lc19)
Ld19:   SB1(); SA1(Lc20)
Ld20:   SB1(); SA1(Lc21)
Ld21:   SB1(); SA1(Lc22)
Ld22:   SB1(); SA1(Lc23)
Ld23:   SB1(); SA1(Lc24)
Ld24:   SB1(); SA1(Lc25)
Ld25:   SB1(); SA1(Lc26)
Ld26:   SB1(); SA1(Lc27)
Ld27:   SB1(); SA1(Lc28)
Ld28:   SB1(); SA1(Lc29)
Ld29:   SB1(); SA1(Lc30)
Ld30:   SB1(); SA1(Lc31)
Ld31:   SB1(); SA1(Lc32)
Ld32:   mov     %o3,%g1         // Rest aus %o3 in %g1 abspeichern
        retl
       _ xor     %o1,-1,%o0     // Quotient nach %o0
Levendiv: // Division durch gerades y.
        // x/2 durch y/2 dividieren, Quotient OK, Rest evtl. mit 2 multiplizieren.
        // Es ist schon %o2 = y/2.
        // Man spart im Vergleich zu Lsmalldiv
        // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0()
        // dafür am Schluß Bit 0 von x zum Rest dazuschieben.
        SA0(Lf01)               // Bit 31 des Quotienten bestimmen
Le01:   SB0(); SA0(Lf02)        // Bit 30 des Quotienten bestimmen
Le02:   SB0(); SA0(Lf03)        // Bit 29 des Quotienten bestimmen
Le03:   SB0(); SA0(Lf04)        // Bit 28 des Quotienten bestimmen
Le04:   SB0(); SA0(Lf05)        // Bit 27 des Quotienten bestimmen
Le05:   SB0(); SA0(Lf06)        // Bit 26 des Quotienten bestimmen
Le06:   SB0(); SA0(Lf07)        // Bit 25 des Quotienten bestimmen
Le07:   SB0(); SA0(Lf08)        // Bit 24 des Quotienten bestimmen
Le08:   SB0(); SA0(Lf09)        // Bit 23 des Quotienten bestimmen
Le09:   SB0(); SA0(Lf10)        // Bit 22 des Quotienten bestimmen
Le10:   SB0(); SA0(Lf11)        // Bit 21 des Quotienten bestimmen
Le11:   SB0(); SA0(Lf12)        // Bit 20 des Quotienten bestimmen
Le12:   SB0(); SA0(Lf13)        // Bit 19 des Quotienten bestimmen
Le13:   SB0(); SA0(Lf14)        // Bit 18 des Quotienten bestimmen
Le14:   SB0(); SA0(Lf15)        // Bit 17 des Quotienten bestimmen
Le15:   SB0(); SA0(Lf16)        // Bit 16 des Quotienten bestimmen
Le16:   SB0(); SA0(Lf17)        // Bit 15 des Quotienten bestimmen
Le17:   SB0(); SA0(Lf18)        // Bit 14 des Quotienten bestimmen
Le18:   SB0(); SA0(Lf19)        // Bit 13 des Quotienten bestimmen
Le19:   SB0(); SA0(Lf20)        // Bit 12 des Quotienten bestimmen
Le20:   SB0(); SA0(Lf21)        // Bit 11 des Quotienten bestimmen
Le21:   SB0(); SA0(Lf22)        // Bit 10 des Quotienten bestimmen
Le22:   SB0(); SA0(Lf23)        // Bit 9 des Quotienten bestimmen
Le23:   SB0(); SA0(Lf24)        // Bit 8 des Quotienten bestimmen
Le24:   SB0(); SA0(Lf25)        // Bit 7 des Quotienten bestimmen
Le25:   SB0(); SA0(Lf26)        // Bit 6 des Quotienten bestimmen
Le26:   SB0(); SA0(Lf27)        // Bit 5 des Quotienten bestimmen
Le27:   SB0(); SA0(Lf28)        // Bit 4 des Quotienten bestimmen
Le28:   SB0(); SA0(Lf29)        // Bit 3 des Quotienten bestimmen
Le29:   SB0(); SA0(Lf30)        // Bit 2 des Quotienten bestimmen
Le30:   SB0(); SA0(Lf31)        // Bit 1 des Quotienten bestimmen
Le31:   SB0(); SA0(Lf32)        // Bit 0 des Quotienten bestimmen
Le32:   SB0()                   // Bit 0 des Restes bestimmen
        mov     %o0,%g1         // Rest aus %o0 in %g1 abspeichern
        retl
       _ xor     %o1,-1,%o0     // Quotient nach %o0
// Parallelschiene zu Le01..Le32:
Lf01:   SB1(); SA1(Le02)
Lf02:   SB1(); SA1(Le03)
Lf03:   SB1(); SA1(Le04)
Lf04:   SB1(); SA1(Le05)
Lf05:   SB1(); SA1(Le06)
Lf06:   SB1(); SA1(Le07)
Lf07:   SB1(); SA1(Le08)
Lf08:   SB1(); SA1(Le09)
Lf09:   SB1(); SA1(Le10)
Lf10:   SB1(); SA1(Le11)
Lf11:   SB1(); SA1(Le12)
Lf12:   SB1(); SA1(Le13)
Lf13:   SB1(); SA1(Le14)
Lf14:   SB1(); SA1(Le15)
Lf15:   SB1(); SA1(Le16)
Lf16:   SB1(); SA1(Le17)
Lf17:   SB1(); SA1(Le18)
Lf18:   SB1(); SA1(Le19)
Lf19:   SB1(); SA1(Le20)
Lf20:   SB1(); SA1(Le21)
Lf21:   SB1(); SA1(Le22)
Lf22:   SB1(); SA1(Le23)
Lf23:   SB1(); SA1(Le24)
Lf24:   SB1(); SA1(Le25)
Lf25:   SB1(); SA1(Le26)
Lf26:   SB1(); SA1(Le27)
Lf27:   SB1(); SA1(Le28)
Lf28:   SB1(); SA1(Le29)
Lf29:   SB1(); SA1(Le30)
Lf30:   SB1(); SA1(Le31)
Lf31:   SB1(); SA1(Le32)
Lf32:   SB1()
        mov     %o3,%g1         // Rest aus %o0 in %g1 abspeichern
        retl
       _ xor     %o1,-1,%o0     // Quotient nach %o0
#endif

// 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).
#if defined(sparcv8)
        // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
        wr      %g0,%g0,%y
        nop                     // wait 1
        nop                     // wait 2
        nop                     // wait 3
        udiv    %o0,%o1,%o0     // dividieren, Quotient nach %o0
        rd      %y,%o1          // Rest aus %y
        sll     %o1,16,%o1      // in die oberen 16 Bit schieben
        retl
       _ or      %o0,%o1,%o0
#else
        // %o0 = x, %o1 = y
// Divisions-Einzelschritte:
// %o0  wird jeweils um 1 Bit nach links geschoben,
// dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben.
// Dann wird auf >= 2^15*y verglichen (nicht auf >= 2^16*y, weil man dann das
// links herausgeschobene Bit mit vergleichen müßte!)
        sll %o1,16,%o1
        srl %o1,1,%o1           // 2^15*y
        sub %g0,%o1,%o2         // zum Addieren statt Subtrahieren: -2^15*y
        // SC0(label) subtrahiert y, schiebt Carry-Bit rechts in %o0 rein
        // (1 falls Subtraktion aufging, 0 sonst).
        // Ging die Subtraktion nicht auf, so müßte man noch 2*y addieren.
        // Das faßt man mit der nächsten Operation zusammen, indem man - statt
        // y zu subtrahieren - y addiert:
        // SC1(label) addiert y, schiebt Carry-Bit rechts in %o0 rein
        // (1 falls Subtraktion aufgegangen wäre, man also wieder im
        // "positiven Bereich" landet, 0 sonst).
#define SC0(label) \
        addcc   %o0,%o2,%o0; \
        bcc     label;       \
       _ addx    %o0,%o0,%o0
#define SC1(label) \
        addcc   %o0,%o1,%o0; \
        bcs     label;       \
       _ addx    %o0,%o0,%o0
        SC0(Lh01)               // Bit 15 des Quotienten bestimmen
Lg01:   SC0(Lh02)               // Bit 14 des Quotienten bestimmen
Lg02:   SC0(Lh03)               // Bit 13 des Quotienten bestimmen
Lg03:   SC0(Lh04)               // Bit 12 des Quotienten bestimmen
Lg04:   SC0(Lh05)               // Bit 11 des Quotienten bestimmen
Lg05:   SC0(Lh06)               // Bit 10 des Quotienten bestimmen
Lg06:   SC0(Lh07)               // Bit 9 des Quotienten bestimmen
Lg07:   SC0(Lh08)               // Bit 8 des Quotienten bestimmen
Lg08:   SC0(Lh09)               // Bit 7 des Quotienten bestimmen
Lg09:   SC0(Lh10)               // Bit 6 des Quotienten bestimmen
Lg10:   SC0(Lh11)               // Bit 5 des Quotienten bestimmen
Lg11:   SC0(Lh12)               // Bit 4 des Quotienten bestimmen
Lg12:   SC0(Lh13)               // Bit 3 des Quotienten bestimmen
Lg13:   SC0(Lh14)               // Bit 2 des Quotienten bestimmen
Lg14:   SC0(Lh15)               // Bit 1 des Quotienten bestimmen
Lg15:   SC0(Lh16)               // Bit 0 des Quotienten bestimmen
Lg16:   // Die oberen 16 Bit von %o0 sind der Rest,
        // die unteren 16 Bit von %o0 sind der Quotient.
        retl
       _ nop
Lh01:   SC1(Lg02)               // Bit 14 des Quotienten bestimmen
Lh02:   SC1(Lg03)               // Bit 13 des Quotienten bestimmen
Lh03:   SC1(Lg04)               // Bit 12 des Quotienten bestimmen
Lh04:   SC1(Lg05)               // Bit 11 des Quotienten bestimmen
Lh05:   SC1(Lg06)               // Bit 10 des Quotienten bestimmen
Lh06:   SC1(Lg07)               // Bit 9 des Quotienten bestimmen
Lh07:   SC1(Lg08)               // Bit 8 des Quotienten bestimmen
Lh08:   SC1(Lg09)               // Bit 7 des Quotienten bestimmen
Lh09:   SC1(Lg10)               // Bit 6 des Quotienten bestimmen
Lh10:   SC1(Lg11)               // Bit 5 des Quotienten bestimmen
Lh11:   SC1(Lg12)               // Bit 4 des Quotienten bestimmen
Lh12:   SC1(Lg13)               // Bit 3 des Quotienten bestimmen
Lh13:   SC1(Lg14)               // Bit 2 des Quotienten bestimmen
Lh14:   SC1(Lg15)               // Bit 1 des Quotienten bestimmen
Lh15:   SC1(Lg16)               // Bit 0 des Quotienten bestimmen
Lh16:   // Noch 2*y addieren:
        add %o0,%o1,%o0
        retl
       _ add %o0,%o1,%o0
#endif

#if !defined(__GNUC__)
        .global C(_get_g1)
// extern uint32 _get_g1 (void);
        DECLARE_FUNCTION(_get_g1)
C(_get_g1:)
        retl
       _ mov %g1,%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
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          add %o0,4,%o0
          st %o3,[%o1]
          subcc %o2,1,%o2
          bne 1b
         _ add %o1,4,%o1
2:      retl
       _ mov %o1,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o1,4,%o1
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
        sub %o1,%o2,%o1         // %o1 = &destptr[count-1]
1:        ld [%o0+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          bne 1b
         _ st %o3,[%o1+%o2]     // Digit ablegen
2:      retl
       _ add %o1,4,%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
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          st %o3,[%o1]
          subcc %o2,1,%o2
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov %o1,%o0
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
        sub %o1,%o2,%o1         // %o1 = &destptr[-count]
1:        ld [%o0+%o2],%o3      // nächstes Digit holen
          subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          bne 1b
         _ st %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
        andcc %o1,%o1,%g0
        be 2f
       _ nop
1:        st %o2,[%o0]
          subcc %o1,1,%o1
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o1,%o1       // %o1 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o1,2,%o1           // %o1 = -4*count
        sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
1:        addcc %o1,4,%o1       // Zähler "erniedrigen", Pointer erhöhen
          bne 1b
         _ st %o2,[%o0+%o1]     // Digit ablegen
2:      retl
       _ add %o0,4,%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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
1:        st %o2,[%o0]
          subcc %o1,1,%o1
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ add %o0,4,%o0
#endif
#if COUNTER_LOOPS
        andcc %o1,%o1,%g0
        be 2f
       _ sll %o1,2,%o1          // %o1 = 4*count
        sub %o0,%o1,%o0         // %o0 = &destptr[-count]
1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne 1b
         _ st %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
        andcc %o1,%o1,%g0
        be 2f
       _ nop
1:        st %g0,[%o0]
          subcc %o1,1,%o1
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o1,%o1       // %o1 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o1,2,%o1           // %o1 = -4*count
        sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
1:        addcc %o1,4,%o1       // Zähler "erniedrigen", Pointer erhöhen
          bne 1b
         _ st %g0,[%o0+%o1]     // Digit 0 ablegen
2:      retl
       _ add %o0,4,%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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
1:        st %g0,[%o0]
          subcc %o1,1,%o1
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ add %o0,4,%o0
#endif
#if COUNTER_LOOPS
        andcc %o1,%o1,%g0
        be 2f
       _ sll %o1,2,%o1          // %o1 = 4*count
        sub %o0,%o1,%o0         // %o0 = &destptr[-count]
1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne 1b
         _ st %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
        andcc %o1,%o1,%g0
        be 2f
       _ nop
          ld [%o0],%o2
1:        add %o0,4,%o0
          andcc %o2,%o2,%g0
          bne 3f
         _ subcc %o1,1,%o1
          bne,a 1b
         __ ld [%o0],%o2
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o1,%o1       // %o1 = -count
        be 2f
       _ sll %o1,2,%o1          // %o1 = -4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ld [%o0+%o1],%o2      // nächstes Digit holen
1:        andcc %o2,%o2,%g0     // testen
          bne 3f
         _ addcc %o1,4,%o1      // Zähler "erniedrigen", Pointer erhöhen
          bne,a 1b
         __ ld [%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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
          ld [%o0],%o2
1:        sub %o0,4,%o0
          andcc %o2,%o2,%g0
          bne 3f
         _ subcc %o1,1,%o1
          bne,a 1b
         __ ld [%o0],%o2
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif
#if COUNTER_LOOPS
        sll %o1,2,%o1           // %o1 = 4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count]
        subcc %o1,4,%o1
        bcs 4f
       _ nop
          ld [%o0+%o1],%o2      // nächstes Digit holen
1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bcs 3f
         _ andcc %o2,%o2,%g0    // testen
          be,a 1b
         __ ld [%o0+%o1],%o2    // nächstes Digit holen
2:      retl
       _ mov 1,%o0
3:      bne 2b
       _ nop
4:      retl
       _ mov 0,%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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          or %o3,%o4,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          xor %o3,%o4,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          xor %o3,%o4,%o3       // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          xor %o4,%o3,%o3       // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          and %o3,%o4,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          xnor %o3,%o4,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          xnor %o3,%o4,%o3      // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          xnor %o4,%o3,%o3      // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          and %o3,%o4,%o3
          xor %o3,-1,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          xor %o3,-1,%o3
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          xor %o3,-1,%o3
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          or %o3,%o4,%o3
          xor %o3,-1,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          xor %o3,-1,%o3
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          xor %o3,-1,%o3
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          andn %o3,%o4,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          andn %o3,%o4,%o3      // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          andn %o4,%o3,%o3      // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o1,4,%o1
          orn %o3,%o4,%o3
          st %o3,[%o0]
          subcc %o2,1,%o2
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          orn %o3,%o4,%o3       // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ add %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
1:        ld [%o1+%o2],%o3      // nächstes Digit holen
          addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          orn %o4,%o3,%o3       // beide verknüpfen
          bne 1b
         _ st %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
        andcc %o1,%o1,%g0
        be 2f
       _ nop
1:        ld [%o0],%o2
          subcc %o1,1,%o1
          xor %o2,-1,%o2
          st %o2,[%o0]
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        subcc %g0,%o1,%o1       // %o1 = -count
        be 2f
       _ sub %o0,4,%o0
        sll %o1,2,%o1           // %o1 = -4*count
        sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
1:        addcc %o1,4,%o1       // Zähler "erniedrigen", Pointer erhöhen
          ld [%o0+%o1],%o2      // nächstes Digit holen
          xor %o2,-1,%o2
          bne 1b
         _ st %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
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0],%o3
          ld [%o1],%o4
          add %o0,4,%o0
          andcc %o3,%o4,%g0
          bne 3f
         _ subcc %o2,1,%o2
          bne 1b
         _ add %o1,4,%o1
2:      retl
       _ mov 0,%o0
3:      retl
       _ mov 1,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sll %o2,2,%o2          // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
          ld [%o0+%o2],%o3      // nächstes Digit holen
1:        ld [%o1+%o2],%o4      // noch ein Digit holen
          andcc %o3,%o4,%g0     // beide verknüpfen
          bne 3f
         _ addcc %o2,4,%o2      // Zähler "erniedrigen", Pointer erhöhen
          bne,a 1b
         __ ld [%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
        andcc %o2,%o2,%g0
        be 2f
       _ nop
          ld [%o0],%o3
1:        ld [%o1],%o4
          add %o0,4,%o0
          subcc %o3,%o4,%g0
          bne 3f
         _ add %o1,4,%o1
          subcc %o2,1,%o2
          bne,a 1b
         __ ld [%o0],%o3
2:      retl
       _ mov 0,%o0
3:      blu 4f
       _ nop
        retl
       _ mov 1,%o0
4:      retl
       _ mov -1,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ sll %o2,2,%o2          // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[count]
        sub %o1,%o2,%o1         // %o1 = &yptr[count]
          ld [%o0+%o2],%o3      // nächstes Digit holen
1:        ld [%o1+%o2],%o4      // noch ein Digit holen
          subcc %o3,%o4,%g0     // vergleichen
          bne 3f
         _ addcc %o2,4,%o2      // Zähler "erniedrigen", Pointer erhöhen
          bne,a 1b
         __ ld [%o0+%o2],%o3    // nächstes Digit holen
2:      retl
       _ mov 0,%o0
3:      subcc %o3,%o4,%g0       // nochmals vergleichen
        blu 4f
       _ nop
        retl
       _ mov 1,%o0
4:      retl
       _ mov -1,%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
        andcc %o3,%o3,%g0
        be 2f
       _ mov %g0,%g1            // Carry := 0
        sub %o0,4,%o0
1:        ld [%o0],%o4          // source1-digit
          sub %o1,4,%o1
          ld [%o1],%o5          // source2-digit
          subcc %g0,%g1,%g0     // carry
          addxcc %o4,%o5,%o4    // addieren
          addx %g0,%g0,%g1      // neuer Carry
          sub %o2,4,%o2
          st %o4,[%o2]          // Digit ablegen
          subcc %o3,1,%o3
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
        andcc %o3,%o3,%g0
        be 2f
       _ mov %g0,%g1            // Carry := 0
        sub %o0,4,%o0
        sub %o1,4,%o1
        sll %o3,2,%o3           // %o3 = 4*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:        ld [%o0+%o3],%o4      // source1-digit
          ld [%o1+%o3],%o5      // source2-digit
          subcc %g0,%g1,%g0     // carry
          addxcc %o4,%o5,%o4    // addieren
          addx %g0,%g0,%g1      // neuer Carry
          subcc %o3,4,%o3
          bne 1b
         _ st %o4,[%o2+%o3]     // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif
#if UNROLLED_LOOPS
        and %o3,7,%o4           // count mod 8
        sll %o4,2,%o5
        sub %o0,%o5,%o0         // %o0 = &sourceptr1[-(count mod 8)]
        sub %o1,%o5,%o1         // %o1 = &sourceptr2[-(count mod 8)]
        sub %o2,%o5,%o2         // %o2 = &destptr[-(count mod 8)]
        sll %o4,4,%o4
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o5
0:
#else
        set _add_loop_down+176,%o5
#endif
        sub %o5,%o4,%o5
        jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%g1,%g0     // carry
          ld [%o0+28],%o4       // source1-digit
          ld [%o1+28],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2+28]       // Digit ablegen
          ld [%o0+24],%o4       // source1-digit
          ld [%o1+24],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2+24]       // Digit ablegen
          ld [%o0+20],%o4       // source1-digit
          ld [%o1+20],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2+20]       // Digit ablegen
          ld [%o0+16],%o4       // source1-digit
          ld [%o1+16],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2+16]       // Digit ablegen
          ld [%o0+12],%o4       // source1-digit
          ld [%o1+12],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2+12]       // Digit ablegen
          ld [%o0+8],%o4        // source1-digit
          ld [%o1+8],%o5        // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2+8]        // Digit ablegen
          ld [%o0+4],%o4        // source1-digit
          ld [%o1+4],%o5        // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2+4]        // Digit ablegen
          ld [%o0],%o4          // source1-digit
          ld [%o1],%o5          // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2]          // Digit ablegen
          addx %g0,%g0,%g1      // neuer Carry
          sub %o0,32,%o0
          sub %o1,32,%o1
          subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ sub %o2,32,%o2
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o2,%o2,%g0
        be 2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,4,%o0
1:        ld [%o0],%o3          // source-digit
          sub %o1,4,%o1
          ld [%o1],%o4          // dest-digit
          subcc %g0,%o5,%g0     // carry
          addxcc %o4,%o3,%o4    // addieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1]          // Digit ablegen
          subcc %o2,1,%o2
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,4,%o0
        sub %o1,4,%o1
        sll %o2,2,%o2           // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
        sub %o1,%o2,%o1         // %o1 = &destptr[-count-1]
          ld [%o0+%o2],%o3      // source-digit
1:        ld [%o1+%o2],%o4      // dest-digit
          subcc %g0,%o5,%g0     // carry
          addxcc %o4,%o3,%o4    // addieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1+%o2]      // Digit ablegen
          subcc %o2,4,%o2
          bne,a 1b
         __ ld [%o0+%o2],%o3    // source-digit
2:      retl
       _ mov %o5,%o0
#endif
#if UNROLLED_LOOPS
        and %o2,7,%o3           // count mod 8
        sll %o3,2,%o4
        sub %o0,%o4,%o0         // %o0 = &sourceptr[-(count mod 8)]
        sub %o1,%o4,%o1         // %o1 = &destptr[-(count mod 8)]
        sll %o3,4,%o3
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o4
0:
#else
        set _addto_loop_down+172,%o4
#endif
        sub %o4,%o3,%o4
        jmp %o4                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%o5,%g0     // carry
          ld [%o0+28],%o3       // source-digit
          ld [%o1+28],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1+28]       // Digit ablegen
          ld [%o0+24],%o3       // source-digit
          ld [%o1+24],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1+24]       // Digit ablegen
          ld [%o0+20],%o3       // source-digit
          ld [%o1+20],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1+20]       // Digit ablegen
          ld [%o0+16],%o3       // source-digit
          ld [%o1+16],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1+16]       // Digit ablegen
          ld [%o0+12],%o3       // source-digit
          ld [%o1+12],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1+12]       // Digit ablegen
          ld [%o0+8],%o3        // source-digit
          ld [%o1+8],%o4        // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1+8]        // Digit ablegen
          ld [%o0+4],%o3        // source-digit
          ld [%o1+4],%o4        // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1+4]        // Digit ablegen
          ld [%o0],%o3          // source-digit
          ld [%o1],%o4          // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1]          // Digit ablegen
          addx %g0,%g0,%o5      // neuer Carry
          sub %o0,32,%o0
          subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ sub %o1,32,%o1
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o2
          addcc %o2,1,%o2
          bne 3f
         _ st %o2,[%o0]
          subcc %o1,1,%o1
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov 1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
        sll %o1,2,%o1           // %o1 = 4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
          ld [%o0+%o1],%o2      // digit holen
1:        addcc %o2,1,%o2       // incrementieren
          bne 3f
         _ st %o2,[%o0+%o1]     // ablegen
          subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne,a 1b
         __ ld [%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
        andcc %o3,%o3,%g0
        be 2f
       _ mov %g0,%g1            // Carry := 0
        sub %o0,4,%o0
1:        ld [%o0],%o4          // source1-digit
          sub %o1,4,%o1
          ld [%o1],%o5          // source2-digit
          subcc %g0,%g1,%g0     // carry
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          sub %o2,4,%o2
          st %o4,[%o2]          // Digit ablegen
          subcc %o3,1,%o3
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
        andcc %o3,%o3,%g0
        be 2f
       _ mov %g0,%g1            // Carry := 0
        sub %o0,4,%o0
        sub %o1,4,%o1
        sll %o3,2,%o3           // %o3 = 4*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:        ld [%o0+%o3],%o4      // source1-digit
          ld [%o1+%o3],%o5      // source2-digit
          subcc %g0,%g1,%g0     // carry
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          subcc %o3,4,%o3
          bne 1b
         _ st %o4,[%o2+%o3]     // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif
#if UNROLLED_LOOPS
        and %o3,7,%o4           // count mod 8
        sll %o4,2,%o5
        sub %o0,%o5,%o0         // %o0 = &sourceptr1[-(count mod 8)]
        sub %o1,%o5,%o1         // %o1 = &sourceptr2[-(count mod 8)]
        sub %o2,%o5,%o2         // %o2 = &destptr[-(count mod 8)]
        sll %o4,4,%o4
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o5
0:
#else
        set _sub_loop_down+176,%o5
#endif
        sub %o5,%o4,%o5
        jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%g1,%g0     // carry
          ld [%o0+28],%o4       // source1-digit
          ld [%o1+28],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+28]       // Digit ablegen
          ld [%o0+24],%o4       // source1-digit
          ld [%o1+24],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+24]       // Digit ablegen
          ld [%o0+20],%o4       // source1-digit
          ld [%o1+20],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+20]       // Digit ablegen
          ld [%o0+16],%o4       // source1-digit
          ld [%o1+16],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+16]       // Digit ablegen
          ld [%o0+12],%o4       // source1-digit
          ld [%o1+12],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+12]       // Digit ablegen
          ld [%o0+8],%o4        // source1-digit
          ld [%o1+8],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+8]        // Digit ablegen
          ld [%o0+4],%o4        // source1-digit
          ld [%o1+4],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+4]        // Digit ablegen
          ld [%o0],%o4          // source1-digit
          ld [%o1],%o5          // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2]          // Digit ablegen
          addx %g0,%g0,%g1      // neuer Carry
          sub %o0,32,%o0
          sub %o1,32,%o1
          subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ sub %o2,32,%o2
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o3,%o3,%g0
        be 2f
       _ mov %o4,%g1            // Carry
        sub %o0,4,%o0
1:        ld [%o0],%o4          // source1-digit
          sub %o1,4,%o1
          ld [%o1],%o5          // source2-digit
          subcc %g0,%g1,%g0     // carry
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          sub %o2,4,%o2
          st %o4,[%o2]          // Digit ablegen
          subcc %o3,1,%o3
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov %g1,%o0
#endif
#if COUNTER_LOOPS
        andcc %o3,%o3,%g0
        be 2f
       _ mov %o4,%g1            // Carry
        sub %o0,4,%o0
        sub %o1,4,%o1
        sll %o3,2,%o3           // %o3 = 4*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:        ld [%o0+%o3],%o4      // source1-digit
          ld [%o1+%o3],%o5      // source2-digit
          subcc %g0,%g1,%g0     // carry
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          subcc %o3,4,%o3
          bne 1b
         _ st %o4,[%o2+%o3]     // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif
#if UNROLLED_LOOPS
        and %o3,7,%o5           // count mod 8
        sll %o5,2,%g1
        sub %o0,%g1,%o0         // %o0 = &sourceptr1[-(count mod 8)]
        sub %o1,%g1,%o1         // %o1 = &sourceptr2[-(count mod 8)]
        sub %o2,%g1,%o2         // %o2 = &destptr[-(count mod 8)]
        sll %o5,4,%o5
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%g1
0:
#else
        set _subx_loop_down+176,%g1
#endif
        sub %g1,%o5,%g1
        jmp %g1                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%o4,%g0      // carry initialisieren
1:        subcc %g0,%g1,%g0     // carry
          ld [%o0+28],%o4       // source1-digit
          ld [%o1+28],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+28]       // Digit ablegen
          ld [%o0+24],%o4       // source1-digit
          ld [%o1+24],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+24]       // Digit ablegen
          ld [%o0+20],%o4       // source1-digit
          ld [%o1+20],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+20]       // Digit ablegen
          ld [%o0+16],%o4       // source1-digit
          ld [%o1+16],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+16]       // Digit ablegen
          ld [%o0+12],%o4       // source1-digit
          ld [%o1+12],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+12]       // Digit ablegen
          ld [%o0+8],%o4        // source1-digit
          ld [%o1+8],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+8]        // Digit ablegen
          ld [%o0+4],%o4        // source1-digit
          ld [%o1+4],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2+4]        // Digit ablegen
          ld [%o0],%o4          // source1-digit
          ld [%o1],%o5          // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2]          // Digit ablegen
          addx %g0,%g0,%g1      // neuer Carry
          sub %o0,32,%o0
          sub %o1,32,%o1
          subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ sub %o2,32,%o2
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o2,%o2,%g0
        be 2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,4,%o0
1:        ld [%o0],%o3          // source-digit
          sub %o1,4,%o1
          ld [%o1],%o4          // dest-digit
          subcc %g0,%o5,%g0     // carry
          subxcc %o4,%o3,%o4    // subtrahieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1]          // Digit ablegen
          subcc %o2,1,%o2
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ mov %g0,%o5            // Carry := 0
        sub %o0,4,%o0
        sub %o1,4,%o1
        sll %o2,2,%o2           // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
        sub %o1,%o2,%o1         // %o1 = &destptr[-count-1]
          ld [%o0+%o2],%o3      // source-digit
1:        ld [%o1+%o2],%o4      // dest-digit
          subcc %g0,%o5,%g0     // carry
          subxcc %o4,%o3,%o4    // subtrahieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1+%o2]      // Digit ablegen
          subcc %o2,4,%o2
          bne,a 1b
         __ ld [%o0+%o2],%o3    // source-digit
2:      retl
       _ mov %o5,%o0
#endif
#if UNROLLED_LOOPS
        and %o2,7,%o3           // count mod 8
        sll %o3,2,%o4
        sub %o0,%o4,%o0         // %o0 = &sourceptr[-(count mod 8)]
        sub %o1,%o4,%o1         // %o1 = &destptr[-(count mod 8)]
        sll %o3,4,%o3
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o4
0:
#else
        set _subfrom_loop_down+172,%o4
#endif
        sub %o4,%o3,%o4
        jmp %o4                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%o5,%g0     // carry
          ld [%o0+28],%o3       // source-digit
          ld [%o1+28],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1+28]       // Digit ablegen
          ld [%o0+24],%o3       // source-digit
          ld [%o1+24],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1+24]       // Digit ablegen
          ld [%o0+20],%o3       // source-digit
          ld [%o1+20],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1+20]       // Digit ablegen
          ld [%o0+16],%o3       // source-digit
          ld [%o1+16],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1+16]       // Digit ablegen
          ld [%o0+12],%o3       // source-digit
          ld [%o1+12],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1+12]       // Digit ablegen
          ld [%o0+8],%o3        // source-digit
          ld [%o1+8],%o4        // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1+8]        // Digit ablegen
          ld [%o0+4],%o3        // source-digit
          ld [%o1+4],%o4        // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1+4]        // Digit ablegen
          ld [%o0],%o3          // source-digit
          ld [%o1],%o4          // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1]          // Digit ablegen
          addx %g0,%g0,%o5      // neuer Carry
          sub %o0,32,%o0
          subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ sub %o1,32,%o1
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o2
          subcc %o2,1,%o2
          bcc 3f
         _ st %o2,[%o0]
          subcc %o1,1,%o1
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov -1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
        sll %o1,2,%o1           // %o1 = 4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
          ld [%o0+%o1],%o2      // digit holen
1:        subcc %o2,1,%o2       // decrementieren
          bcc 3f
         _ st %o2,[%o0+%o1]     // ablegen
          subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
          bne,a 1b
         __ ld [%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
        // erstes Digit /=0 suchen:
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o2
          subcc %g0,%o2,%o2
          bne 3f
         _ subcc %o1,1,%o1
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        st %o2,[%o0]            // 1 Digit negieren
        // alle anderen Digits invertieren:
        be 5f
       _ sub %o0,4,%o0
4:        ld [%o0],%o2
          subcc %o1,1,%o1
          xor %o2,-1,%o2
          st %o2,[%o0]
          bne 4b
         _ sub %o0,4,%o0
5:      retl
       _ mov -1,%o0
#endif
#if COUNTER_LOOPS
        // erstes Digit /=0 suchen:
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
        sll %o1,2,%o1           // %o1 = 4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
          ld [%o0+%o1],%o2      // digit holen
1:        subcc %g0,%o2,%o2     // negieren, testen
          bne 3f
         _ subcc %o1,4,%o1      // Zähler erniedrigen, Pointer erniedrigen
          bne,a 1b
         __ ld [%o0+%o1],%o2
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // alle anderen Digits invertieren:
        add %o1,4,%o1
        st %o2,[%o0+%o1]        // ablegen
        subcc %o1,4,%o1
        be 5f
       _ nop
          ld [%o0+%o1],%o2
4:        xor %o2,-1,%o2
          st %o2,[%o0+%o1]
          subcc %o1,4,%o1
          bne,a 4b
         __ ld [%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
        andcc %o1,%o1,%g0
        be 2f
       _ mov 0,%o3              // Carry := 0
        sub %o0,4,%o0
1:        ld [%o0],%o2          // Digit
          subcc %g0,%o3,%g0     // carry
          addxcc %o2,%o2,%o2    // shiften
          addx %g0,%g0,%o3      // neues Carry
          st %o2,[%o0]          // Digit ablegen
          subcc %o1,1,%o1
          bne 1b
         _ sub %o0,4,%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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %g0,%o2,%g1        // 32-i (mod 32)
        sub %o0,4,%o0
1:        ld [%o0],%o4          // Digit
          subcc %o1,1,%o1
          sll %o4,%o2,%o5       // dessen niedere (32-i) Bits
          or %o3,%o5,%o5        // mit dem alten Carry kombinieren
          st %o5,[%o0]          // Digit ablegen
          srl %o4,%g1,%o3       // dessen höchste i Bits liefern den neuen Carry
          bne 1b
         _ sub %o0,4,%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
        andcc %o2,%o2,%g0
        be 2f
       _ mov 0,%o4              // Carry := 0
        sub %g0,%o3,%g1         // 32-i (mod 32)
        sub %o0,4,%o0
1:        ld [%o0],%o5          // Digit
          subcc %o2,1,%o2
          sll %o5,%o3,%g2       // dessen niedere (32-i) Bits
          or %o4,%g2,%g2        // mit dem alten Carry kombinieren
          sub %o1,4,%o1
          st %g2,[%o1]          // Digit ablegen
          srl %o5,%g1,%o4       // dessen höchste i Bits liefern den neuen Carry
          bne 1b
         _ sub %o0,4,%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
        andcc %o1,%o1,%g0
        be 2f
       _ sll %o2,31,%o2         // Carry
1:        ld [%o0],%o3          // Digit
          subcc %o1,1,%o1
          srl %o3,1,%o4         // shiften
          or %o2,%o4,%o4        // und mit altem Carry kombinieren
          st %o4,[%o0]          // und ablegen
          sll %o3,31,%o2        // neuer Carry
          bne 1b
         _ add %o0,4,%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
        sub %g0,%o2,%g1         // 32-i (mod 32)
        andcc %o1,%o1,%g0
        be 2f
       _ or %g0,%g0,%o3         // Carry := 0
1:        ld [%o0],%o4          // Digit
          subcc %o1,1,%o1
          srl %o4,%o2,%o5       // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          st %o5,[%o0]          // und ablegen
          sll %o4,%g1,%o3       // neuer Carry
          bne 1b
         _ add %o0,4,%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
        ld [%o0],%o4            // erstes Digit
        sub %g0,%o2,%g1         // 32-i (mod 32)
        sra %o4,%o2,%o5         // shiften
        st %o5,[%o0]            // und ablegen
        sll %o4,%g1,%o3         // neuer Carry
        subcc %o1,1,%o1
        be 2f
       _ add %o0,4,%o0
1:        ld [%o0],%o4          // Digit
          subcc %o1,1,%o1
          srl %o4,%o2,%o5       // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          st %o5,[%o0]          // und ablegen
          sll %o4,%g1,%o3       // neuer Carry
          bne 1b
         _ add %o0,4,%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
        sub %g0,%o3,%g1         // 32-i (mod 32)
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o4,%g1,%g2        // erster Carry
1:        ld [%o0],%o4          // Digit
          add %o0,4,%o0
          srl %o4,%o3,%o5       // shiften
          or %g2,%o5,%o5        // und mit altem Carry kombinieren
          st %o5,[%o1]          // und ablegen
          sll %o4,%g1,%g2       // neuer Carry
          subcc %o2,1,%o2
          bne 1b
         _ add %o1,4,%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
        andcc %o2,%o2,%g0
        be 3f
       _ sub %o1,4,%o1
1:        // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
          // und kleinen Carry %o3 dazu:
          mov %o0,%y
          ld [%o1],%o4          // Wartetakt!
          addcc %o3,%o3,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%g0,%o5
          // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y
          // ergeben das Resultat. (Die anderen Bits sind Null.)
          tst %o4               // Korrektur, falls %o4 negativ war
          bge 2f
         _ sra %o5,26,%o3       // 6 obere Bits von %o5 -> neuer Carry
          add %o3,%o0,%o3       // (falls %o4 negativ war, noch + %o0)
2:        rd %y,%o4
          srl %o4,26,%o4        // 6 obere Bits von %y
          sll %o5,6,%o5         // 26 untere Bits von %o5
          or %o5,%o4,%o4        // neues Digit
          st %o4,[%o1]          // ablegen
          subcc %o2,1,%o2
          bne 1b
         _ sub %o1,4,%o1
3:      retl
       _ mov %o3,%o0

// extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
#if !MULU32_INLINE
        DECLARE_FUNCTION(mulu_loop_down)
C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
        save %sp,-96,%sp
        mov 0,%l0               // Carry
1:        sub %i1,4,%i1
          ld [%i1],%o1          // nächstes Digit
          call _mulu32_         // mit digit multiplizieren
         _ mov %i0,%o0
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
          sub %i2,4,%i2
          subcc %i3,1,%i3
          bne 1b
         _ st %o0,[%i2]         // Low-Digit ablegen
        st %l0,[%i2-4]          // letzten Carry ablegen
        ret
       _ restore
#else
        DECLARE_FUNCTION(mulu_loop_down)
C(mulu_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1
        mov 0,%o4               // Carry
1:        ld [%o1-4],%g1        // nächstes Digit
          // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
#ifdef sparcv8
          sub     %o1,4,%o1
          umul    %g1,%o0,%g1
          rd      %y,%o5
#else
          mov     %g1,%y
          sub     %o1,4,%o1     // Wartetakt!
          andcc   %g0,%g0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%g0,%o5
          tst     %o0
          bl,a    2f
         __ add     %o5,%g1,%o5
2:        rd      %y,%g1
#endif
          addcc %o4,%g1,%g1     // und bisherigen Carry addieren
          addx %g0,%o5,%o4      // High-Digit gibt neuen Carry
          sub %o2,4,%o2
          subcc %o3,1,%o3
          bne 1b
         _ st %g1,[%o2]         // Low-Digit ablegen
        retl
       _ st %o4,[%o2-4]         // letzten Carry ablegen
#endif

// 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
#if !MULU32_INLINE
        save %sp,-96,%sp
        mov 0,%l0               // Carry
1:        sub %i1,4,%i1
          ld [%i1],%o1          // nächstes source-Digit
          call _mulu32_         // mit digit multiplizieren
         _ mov %i0,%o0
          sub %i2,4,%i2
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
          addcc %o1,%o0,%o0     // addieren
          addx %g0,%l0,%l0
          subcc %i3,1,%i3
          bne 1b
         _ st %o0,[%i2]         // Low-Digit ablegen
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#else
        save %sp,-96,%sp
        mov 0,%l0               // Carry
#ifndef sparcv8
        sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
#endif
1:        ld [%i1-4],%o1        // nächstes source-Digit
          sub %i1,4,%i1
          // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
#ifdef sparcv8
          umul    %i0,%o1,%o0
          rd      %y,%o2
#else
          mov     %o1,%y
          and     %o1,%l1,%o3   // Wartetakt!
          andcc   %g0,%g0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%g0,%o2
          add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
          rd      %y,%o0
#endif
          sub %i2,4,%i2
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
          addcc %o1,%o0,%o0     // addieren
          addx %g0,%l0,%l0
          subcc %i3,1,%i3
          bne 1b
         _ st %o0,[%i2]         // Low-Digit ablegen
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#endif

// 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
#if !MULU32_INLINE
        save %sp,-96,%sp
        mov 0,%l0               // Carry
1:        sub %i1,4,%i1
          ld [%i1],%o1          // nächstes source-Digit
          call _mulu32_         // mit digit multiplizieren
         _ mov %i0,%o0
          sub %i2,4,%i2
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
          subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
          addx %g0,%l0,%l0
          subcc %i3,1,%i3
          bne 1b
         _ st %o1,[%i2]         // dest-Digit ablegen
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#else
        save %sp,-96,%sp
        mov 0,%l0               // Carry
#ifndef sparcv8
        sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
#endif
1:        ld [%i1-4],%o1        // nächstes source-Digit
          sub %i1,4,%i1
          // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
#ifdef sparcv8
          umul    %i0,%o1,%o0
          rd      %y,%o2
#else
          mov     %o1,%y
          and     %o1,%l1,%o3   // Wartetakt!
          andcc   %g0,%g0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%g0,%o2
          add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
          rd      %y,%o0
#endif
          sub %i2,4,%i2
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
          subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
          addx %g0,%l0,%l0
          subcc %i3,1,%i3
          bne 1b
         _ st %o1,[%i2]         // dest-Digit ablegen
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#endif

// extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
        DECLARE_FUNCTION(divu_loop_up)
C(divu_loop_up:) // Input in %i0,%i1,%i2, Output in %i0
        save %sp,-96,%sp
        andcc %i2,%i2,%g0
        be 2f
       _ mov 0,%g1                 // Rest
1:        mov %g1,%o0              // Rest als High-Digit
          ld [%i1],%o1             // nächstes Digit als Low-Digit
          call C(divu_6432_3232_)  // zusammen durch digit dividieren
         _ mov %i0,%o2
          st %o0,[%i1]             // Quotient ablegen, Rest in %g1
          subcc %i2,1,%i2
          bne 1b
         _ add %i1,4,%i1
2:      mov %g1,%i0                // Rest als Ergebnis
        ret
       _ restore

// extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(divucopy_loop_up)
C(divucopy_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
        save %sp,-96,%sp
        andcc %i3,%i3,%g0
        be 2f
       _ mov 0,%g1                 // Rest
1:        mov %g1,%o0              // Rest als High-Digit
          ld [%i1],%o1             // nächstes Digit als Low-Digit
          call C(divu_6432_3232_)  // zusammen durch digit dividieren
         _ mov %i0,%o2
          st %o0,[%i2]             // Quotient ablegen, Rest in %g1
          add %i1,4,%i1
          subcc %i3,1,%i3
          bne 1b
         _ add %i2,4,%i2
2:      mov %g1,%i0                // Rest als Ergebnis
        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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          or %o3,%o4,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          xor %o3,%o4,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          xor %o3,%o4,%o3       // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          xor %o4,%o3,%o3       // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          and %o3,%o4,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          xnor %o3,%o4,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          xnor %o3,%o4,%o3      // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          xnor %o4,%o3,%o3      // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          and %o3,%o4,%o3
          xor %o3,-1,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          and %o3,%o4,%o3       // verknüpfen
          xor %o3,-1,%o3
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          and %o4,%o3,%o3       // beide verknüpfen
          xor %o3,-1,%o3
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          or %o3,%o4,%o3
          xor %o3,-1,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          or %o3,%o4,%o3        // verknüpfen
          xor %o3,-1,%o3
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          or %o4,%o3,%o3        // beide verknüpfen
          xor %o3,-1,%o3
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          andn %o3,%o4,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          andn %o3,%o4,%o3      // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          andn %o4,%o3,%o3      // beide verknüpfen
          bne 1b
         _ st %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 SLOW_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          orn %o3,%o4,%o3
          st %o3,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if STANDARD_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
        sub %o0,4,%o0
1:        ld [%o0],%o3          // *xptr
          ld [%o0+%o1],%o4      // *yptr
          subcc %o2,1,%o2
          orn %o3,%o4,%o3       // verknüpfen
          st %o3,[%o0]          // =: *xptr
          bne 1b
         _ sub %o0,4,%o0        // xptr++, yptr++
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o2,2,%o2          // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o1+%o2],%o3      // nächstes Digit holen
          ld [%o0+%o2],%o4      // noch ein Digit holen
          orn %o4,%o3,%o3       // beide verknüpfen
          bne 1b
         _ st %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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %o0,4,%o0
1:        ld [%o0],%o2
          subcc %o1,1,%o1
          xor %o2,-1,%o2
          st %o2,[%o0]
          bne 1b
         _ sub %o0,4,%o0
2:      retl
       _ nop
#endif
#if COUNTER_LOOPS
        andcc %o1,%o1,%g0
        be 2f
       _ sll %o1,2,%o1          // %o1 = 4*count
        sub %o0,%o1,%o0         // %o0 = &destptr[-count]
1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
          ld [%o0+%o1],%o2      // nächstes Digit holen
          xor %o2,-1,%o2
          bne 1b
         _ st %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
        andcc %o2,%o2,%g0
        be 4f
       _ sub %o0,4,%o0
1:        ld [%o0],%o3
          sub %o1,4,%o1
          ld [%o1],%o4
          subcc %o2,1,%o2
          be 3f
         _ andcc %o3,%o4,%g0
          be 1b
         _ sub %o0,4,%o0
2:      retl
       _ mov 1,%o0
3:      bne 2b
       _ nop
4:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
        sll %o2,2,%o2           // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
        subcc %o2,4,%o2
        bcs 2f
       _ nop
          ld [%o0+%o2],%o3      // nächstes Digit holen
1:        ld [%o1+%o2],%o4      // noch ein Digit holen
          andcc %o3,%o4,%g0     // beide verknüpfen
          bne 3f
         _ subcc %o2,4,%o2      // Zähler erniedrigen, Pointer erniedrigen
          bcc,a 1b
         __ ld [%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
        andcc %o2,%o2,%g0
        be 2f
       _ nop
1:        ld [%o0-4],%o3
          ld [%o1-4],%o4
          subcc %o3,%o4,%g0
          bne 3f
         _ sub %o0,4,%o0
          subcc %o2,1,%o2
          bne 1b
         _ sub %o1,4,%o1
2:      retl
       _ mov 0,%o0
3:      blu 4f
       _ nop
        retl
       _ mov 1,%o0
4:      retl
       _ mov -1,%o0
#endif
#if COUNTER_LOOPS
        sll %o2,2,%o2           // %o2 = 4*count
        sub %o0,%o2,%o0         // %o0 = &xptr[-count]
        sub %o1,%o2,%o1         // %o1 = &yptr[-count]
        subcc %o2,4,%o2
        bcs 5f
       _ nop
          ld [%o0+%o2],%o3      // nächstes Digit holen
1:        ld [%o1+%o2],%o4      // noch ein Digit holen
          subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
          bcs 4f
         _ subcc %o3,%o4,%g0    // vergleichen
          be,a 1b
         __ ld [%o0+%o2],%o3    // nächstes Digit holen
2:      blu 3f
       _ nop
        retl
       _ mov 1,%o0
3:      retl
       _ mov -1,%o0
4:      bne 2b
       _ nop
5:      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
        andcc %o3,%o3,%g0
        be 2f
       _ subcc %g0,%g0,%g0      // Carry := 0
1:        ld [%o0],%o4          // source1-digit
          add %o0,4,%o0
          ld [%o1],%o5          // source2-digit
          add %o1,4,%o1
          addxcc %o4,%o5,%o4    // addieren
          addx %g0,%g0,%g1      // neuer Carry
          st %o4,[%o2]          // Digit ablegen
          add %o2,4,%o2
          subcc %o3,1,%o3
          bne 1b
         _ subcc %g0,%g1,%g0    // carry
2:      retl
       _ addx %g0,%g0,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o3,%o3       // %o3 = -count
        be 2f
       _ mov %g0,%g1            // Carry := 0
        sll %o3,2,%o3           // %o3 = -4*count
        sub %o2,4,%o2
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
        sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
1:        ld [%o0+%o3],%o4      // source1-digit
          ld [%o1+%o3],%o5      // source2-digit
          subcc %g0,%g1,%g0     // carry
          addxcc %o4,%o5,%o4    // addieren
          addx %g0,%g0,%g1      // neuer Carry
          addcc %o3,4,%o3       // Zähler erniedrigen, Pointer erhöhen
          bne 1b
         _ st %o4,[%o2+%o3]     // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif
#if UNROLLED_LOOPS
        and %o3,7,%o4           // count mod 8
        sll %o4,2,%o5
        add %o0,%o5,%o0         // %o0 = &sourceptr1[count mod 8]
        add %o1,%o5,%o1         // %o1 = &sourceptr2[count mod 8]
        add %o2,%o5,%o2         // %o2 = &destptr[count mod 8]
        sll %o4,4,%o4
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o5
0:
#else
        set _add_loop_up+176,%o5
#endif
        sub %o5,%o4,%o5
        jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%g1,%g0     // carry
          ld [%o0-32],%o4       // source1-digit
          ld [%o1-32],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-32]       // Digit ablegen
          ld [%o0-28],%o4       // source1-digit
          ld [%o1-28],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-28]       // Digit ablegen
          ld [%o0-24],%o4       // source1-digit
          ld [%o1-24],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-24]       // Digit ablegen
          ld [%o0-20],%o4       // source1-digit
          ld [%o1-20],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-20]       // Digit ablegen
          ld [%o0-16],%o4       // source1-digit
          ld [%o1-16],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-16]       // Digit ablegen
          ld [%o0-12],%o4       // source1-digit
          ld [%o1-12],%o5       // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-12]       // Digit ablegen
          ld [%o0-8],%o4        // source1-digit
          ld [%o1-8],%o5        // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-8]        // Digit ablegen
          ld [%o0-4],%o4        // source1-digit
          ld [%o1-4],%o5        // source2-digit
          addxcc %o5,%o4,%o5    // addieren
          st %o5,[%o2-4]        // Digit ablegen
          addx %g0,%g0,%g1      // neuer Carry
          add %o0,32,%o0
          add %o1,32,%o1
          subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ add %o2,32,%o2
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o2,%o2,%g0
        be 2f
       _ mov %g0,%o5            // Carry := 0
1:        ld [%o0],%o3          // source-digit
          add %o0,4,%o0
          ld [%o1],%o4          // dest-digit
          subcc %g0,%o5,%g0     // carry
          addxcc %o4,%o3,%o4    // addieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1]          // Digit ablegen
          subcc %o2,1,%o2
          bne 1b
         _ add %o1,4,%o1
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ mov %g0,%o5            // Carry := 0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
        sub %o1,%o2,%o1         // %o1 = &destptr[count]
          ld [%o0+%o2],%o3      // source-digit
1:        ld [%o1+%o2],%o4      // dest-digit
          subcc %g0,%o5,%g0     // carry
          addxcc %o4,%o3,%o4    // addieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1+%o2]      // Digit ablegen
          addcc %o2,4,%o2       // Zähler erniedrigen, Pointer erhöhen
          bne,a 1b
         __ ld [%o0+%o2],%o3    // source-digit
2:      retl
       _ mov %o5,%o0
#endif
#if UNROLLED_LOOPS
        and %o2,7,%o3           // count mod 8
        sll %o3,2,%o4
        add %o0,%o4,%o0         // %o0 = &sourceptr[count mod 8]
        add %o1,%o4,%o1         // %o1 = &destptr[count mod 8]
        sll %o3,4,%o3
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o4
0:
#else
        set _addto_loop_up+172,%o4
#endif
        sub %o4,%o3,%o4
        jmp %o4                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%o5,%g0     // carry
          ld [%o0-32],%o3       // source-digit
          ld [%o1-32],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-32]       // Digit ablegen
          ld [%o0-28],%o3       // source-digit
          ld [%o1-28],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-28]       // Digit ablegen
          ld [%o0-24],%o3       // source-digit
          ld [%o1-24],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-24]       // Digit ablegen
          ld [%o0-20],%o3       // source-digit
          ld [%o1-20],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-20]       // Digit ablegen
          ld [%o0-16],%o3       // source-digit
          ld [%o1-16],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-16]       // Digit ablegen
          ld [%o0-12],%o3       // source-digit
          ld [%o1-12],%o4       // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-12]       // Digit ablegen
          ld [%o0-8],%o3        // source-digit
          ld [%o1-8],%o4        // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-8]        // Digit ablegen
          ld [%o0-4],%o3        // source-digit
          ld [%o1-4],%o4        // dest-digit
          addxcc %o4,%o3,%o4    // addieren
          st %o4,[%o1-4]        // Digit ablegen
          addx %g0,%g0,%o5      // neuer Carry
          add %o0,32,%o0
          subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ add %o1,32,%o1
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o1,%o1,%g0
        be 2f
       _ nop
          ld [%o0],%o2
1:        add %o0,4,%o0
          addcc %o2,1,%o2
          bne 3f
         _ st %o2,[%o0-4]
          subcc %o1,1,%o1
          bne,a 1b
         __ ld [%o0],%o2
2:      retl
       _ mov 1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o1,%o1       // %o1 = -count
        be 2f
       _ sll %o1,2,%o1          // %o1 = -4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ld [%o0+%o1],%o2      // digit holen
1:        addcc %o2,1,%o2       // incrementieren
          bne 3f
         _ st %o2,[%o0+%o1]     // ablegen
          addcc %o1,4,%o1       // Zähler erniedrigen, Pointer erhöhen
          bne,a 1b
         __ ld [%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
        andcc %o3,%o3,%g0
        be 2f
       _ subcc %g0,%g0,%g0      // Carry := 0
1:        ld [%o0],%o4          // source1-digit
          add %o0,4,%o0
          ld [%o1],%o5          // source2-digit
          add %o1,4,%o1
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          st %o4,[%o2]          // Digit ablegen
          add %o2,4,%o2
          subcc %o3,1,%o3
          bne 1b
         _ subcc %g0,%g1,%g0    // carry
2:      retl
       _ addx %g0,%g0,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o3,%o3       // %o3 = -count
        be 2f
       _ mov %g0,%g1            // Carry := 0
        sll %o3,2,%o3           // %o3 = -4*count
        sub %o2,4,%o2
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
        sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
1:        ld [%o0+%o3],%o4      // source1-digit
          ld [%o1+%o3],%o5      // source2-digit
          subcc %g0,%g1,%g0     // carry
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          addcc %o3,4,%o3
          bne 1b
         _ st %o4,[%o2+%o3]     // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif
#if UNROLLED_LOOPS
        and %o3,7,%o4           // count mod 8
        sll %o4,2,%o5
        add %o0,%o5,%o0         // %o0 = &sourceptr1[count mod 8]
        add %o1,%o5,%o1         // %o1 = &sourceptr2[count mod 8]
        add %o2,%o5,%o2         // %o2 = &destptr[count mod 8]
        sll %o4,4,%o4
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o5
0:
#else
        set _sub_loop_up+176,%o5
#endif
        sub %o5,%o4,%o5
        jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%g1,%g0     // carry
          ld [%o0-32],%o4       // source1-digit
          ld [%o1-32],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-32]       // Digit ablegen
          ld [%o0-28],%o4       // source1-digit
          ld [%o1-28],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-28]       // Digit ablegen
          ld [%o0-24],%o4       // source1-digit
          ld [%o1-24],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-24]       // Digit ablegen
          ld [%o0-20],%o4       // source1-digit
          ld [%o1-20],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-20]       // Digit ablegen
          ld [%o0-16],%o4       // source1-digit
          ld [%o1-16],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-16]       // Digit ablegen
          ld [%o0-12],%o4       // source1-digit
          ld [%o1-12],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-12]       // Digit ablegen
          ld [%o0-8],%o4        // source1-digit
          ld [%o1-8],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-8]        // Digit ablegen
          ld [%o0-4],%o4        // source1-digit
          ld [%o1-4],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-4]        // Digit ablegen
          addx %g0,%g0,%g1      // neuer Carry
          add %o0,32,%o0
          add %o1,32,%o1
          subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ add %o2,32,%o2
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o3,%o3,%g0
        be 2f
       _ subcc %g0,%o4,%g0      // Carry
1:        ld [%o0],%o4          // source1-digit
          add %o0,4,%o0
          ld [%o1],%o5          // source2-digit
          add %o1,4,%o1
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          st %o4,[%o2]          // Digit ablegen
          add %o2,4,%o2
          subcc %o3,1,%o3
          bne 1b
         _ subcc %g0,%g1,%g0    // carry
2:      retl
       _ addx %g0,%g0,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o3,%o3       // %o3 = -count
        be 2f
       _ mov %o4,%g1            // Carry
        sll %o3,2,%o3           // %o3 = -4*count
        sub %o2,4,%o2
        sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
        sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
        sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
1:        ld [%o0+%o3],%o4      // source1-digit
          ld [%o1+%o3],%o5      // source2-digit
          subcc %g0,%g1,%g0     // carry
          subxcc %o4,%o5,%o4    // subtrahieren
          addx %g0,%g0,%g1      // neuer Carry
          addcc %o3,4,%o3
          bne 1b
         _ st %o4,[%o2+%o3]     // Digit ablegen
2:      retl
       _ mov %g1,%o0
#endif
#if UNROLLED_LOOPS
        and %o3,7,%o5           // count mod 8
        sll %o5,2,%g1
        add %o0,%g1,%o0         // %o0 = &sourceptr1[count mod 8]
        add %o1,%g1,%o1         // %o1 = &sourceptr2[count mod 8]
        add %o2,%g1,%o2         // %o2 = &destptr[count mod 8]
        sll %o5,4,%o5
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%g1
0:
#else
        set _subx_loop_up+176,%g1
#endif
        sub %g1,%o5,%g1
        jmp %g1                 // Sprung nach _subx_loop_up+4*(12+4*8-4*(count mod 8))
       _ subcc %g0,%o4,%g0      // carry initialisieren
1:        subcc %g0,%g1,%g0     // carry
          ld [%o0-32],%o4       // source1-digit
          ld [%o1-32],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-32]       // Digit ablegen
          ld [%o0-28],%o4       // source1-digit
          ld [%o1-28],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-28]       // Digit ablegen
          ld [%o0-24],%o4       // source1-digit
          ld [%o1-24],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-24]       // Digit ablegen
          ld [%o0-20],%o4       // source1-digit
          ld [%o1-20],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-20]       // Digit ablegen
          ld [%o0-16],%o4       // source1-digit
          ld [%o1-16],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-16]       // Digit ablegen
          ld [%o0-12],%o4       // source1-digit
          ld [%o1-12],%o5       // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-12]       // Digit ablegen
          ld [%o0-8],%o4        // source1-digit
          ld [%o1-8],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-8]        // Digit ablegen
          ld [%o0-4],%o4        // source1-digit
          ld [%o1-4],%o5        // source2-digit
          subxcc %o4,%o5,%o4    // subtrahieren
          st %o4,[%o2-4]        // Digit ablegen
          addx %g0,%g0,%g1      // neuer Carry
          add %o0,32,%o0
          add %o1,32,%o1
          subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ add %o2,32,%o2
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o2,%o2,%g0
        be 2f
       _ mov %g0,%o5            // Carry := 0
1:        ld [%o0],%o3          // source-digit
          add %o0,4,%o0
          ld [%o1],%o4          // dest-digit
          subcc %g0,%o5,%g0     // carry
          subxcc %o4,%o3,%o4    // subtrahieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1]          // Digit ablegen
          subcc %o2,1,%o2
          bne 1b
         _ add %o1,4,%o1
2:      retl
       _ mov %o5,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o2,%o2       // %o2 = -count
        be 2f
       _ mov %g0,%o5            // Carry := 0
        sll %o2,2,%o2           // %o2 = -4*count
        sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
        sub %o1,%o2,%o1         // %o1 = &destptr[count]
          ld [%o0+%o2],%o3      // source-digit
1:        ld [%o1+%o2],%o4      // dest-digit
          subcc %g0,%o5,%g0     // carry
          subxcc %o4,%o3,%o4    // subtrahieren
          addx %g0,%g0,%o5      // neuer Carry
          st %o4,[%o1+%o2]      // Digit ablegen
          addcc %o2,4,%o2
          bne,a 1b
         __ ld [%o0+%o2],%o3    // source-digit
2:      retl
       _ mov %o5,%o0
#endif
#if UNROLLED_LOOPS
        and %o2,7,%o3           // count mod 8
        sll %o3,2,%o4
        add %o0,%o4,%o0         // %o0 = &sourceptr[count mod 8]
        add %o1,%o4,%o1         // %o1 = &destptr[count mod 8]
        sll %o3,4,%o3
#ifdef PIC
        mov %o7,%g2             // save return address
        call 0f                 // put address of label 0 into %o7
       _ add %o7,144,%o4
0:
#else
        set _subfrom_loop_up+172,%o4
#endif
        sub %o4,%o3,%o4
        jmp %o4                 // Sprung nach _subfrom_loop_up+4*(11+4*8-4*(count mod 8))
       _ subcc %g0,%g0,%g0      // carry löschen
1:        subcc %g0,%o5,%g0     // carry
          ld [%o0-32],%o3       // source-digit
          ld [%o1-32],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-32]       // Digit ablegen
          ld [%o0-28],%o3       // source-digit
          ld [%o1-28],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-28]       // Digit ablegen
          ld [%o0-24],%o3       // source-digit
          ld [%o1-24],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-24]       // Digit ablegen
          ld [%o0-20],%o3       // source-digit
          ld [%o1-20],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-20]       // Digit ablegen
          ld [%o0-16],%o3       // source-digit
          ld [%o1-16],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-16]       // Digit ablegen
          ld [%o0-12],%o3       // source-digit
          ld [%o1-12],%o4       // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-12]       // Digit ablegen
          ld [%o0-8],%o3        // source-digit
          ld [%o1-8],%o4        // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-8]        // Digit ablegen
          ld [%o0-4],%o3        // source-digit
          ld [%o1-4],%o4        // dest-digit
          subxcc %o4,%o3,%o4    // subtrahieren
          st %o4,[%o1-4]        // Digit ablegen
          addx %g0,%g0,%o5      // neuer Carry
          add %o0,32,%o0
          subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
          bcc 1b
         _ add %o1,32,%o1
#ifdef PIC
        jmp %g2+8
#else
        retl
#endif
       _ 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
        andcc %o1,%o1,%g0
        be 2f
       _ nop
          ld [%o0],%o2
1:        add %o0,4,%o0
          subcc %o2,1,%o2
          bcc 3f
         _ st %o2,[%o0-4]
          subcc %o1,1,%o1
          bne,a 1b
         __ ld [%o0],%o2
2:      retl
       _ mov -1,%o0
3:      retl
       _ mov 0,%o0
#endif
#if COUNTER_LOOPS
        subcc %g0,%o1,%o1       // %o1 = -count
        be 2f
       _ sll %o1,2,%o1          // %o1 = -4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ld [%o0+%o1],%o2      // digit holen
1:        subcc %o2,1,%o2       // decrementieren
          bcc 3f
         _ st %o2,[%o0+%o1]     // ablegen
          addcc %o1,4,%o1       // Zähler erniedrigen, Pointer erhöhen
          bne,a 1b
         __ ld [%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
        // erstes Digit /=0 suchen:
        andcc %o1,%o1,%g0
        be 2f
       _ add %o0,4,%o0
1:        ld [%o0-4],%o2
          subcc %g0,%o2,%o2
          bne 3f
         _ subcc %o1,1,%o1
          bne 1b
         _ add %o0,4,%o0
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // 1 Digit negieren, alle anderen Digits invertieren:
        be 5f
       _ st %o2,[%o0-4]
4:        ld [%o0],%o2
          subcc %o1,1,%o1
          xor %o2,-1,%o2
          st %o2,[%o0]
          bne 4b
         _ add %o0,4,%o0
5:      retl
       _ mov -1,%o0
#endif
#if COUNTER_LOOPS
        // erstes Digit /=0 suchen:
        subcc %g0,%o1,%o1       // %o1 = -count
        be 2f
       _ sll %o1,2,%o1          // %o1 = -4*count
        sub %o0,%o1,%o0         // %o0 = &ptr[count]
          ld [%o0+%o1],%o2      // digit holen
1:        subcc %g0,%o2,%o2     // negieren, testen
          bne 3f
         _ addcc %o1,4,%o1      // Zähler erniedrigen, Pointer erhöhen
          bne,a 1b
         __ ld [%o0+%o1],%o2
2:      retl
       _ mov 0,%o0
3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // alle anderen Digits invertieren:
        sub %o1,4,%o1
        st %o2,[%o0+%o1]        // ablegen
        addcc %o1,4,%o1
        be 5f
       _ nop
          ld [%o0+%o1],%o2
4:        xor %o2,-1,%o2
          st %o2,[%o0+%o1]
          addcc %o1,4,%o1
          bne,a 4b
         __ ld [%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
        andcc %o1,%o1,%g0
        be 2f
       _ mov 0,%o3              // Carry := 0
1:        ld [%o0],%o2          // Digit
          subcc %g0,%o3,%g0     // carry
          addxcc %o2,%o2,%o2    // shiften
          addx %g0,%g0,%o3      // neues Carry
          st %o2,[%o0]          // Digit ablegen
          subcc %o1,1,%o1
          bne 1b
         _ add %o0,4,%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
        andcc %o1,%o1,%g0
        be 2f
       _ sub %g0,%o2,%g1        // 32-i (mod 32)
1:        ld [%o0],%o4          // Digit
          subcc %o1,1,%o1
          sll %o4,%o2,%o5       // dessen niedere (32-i) Bits
          or %o3,%o5,%o5        // mit dem alten Carry kombinieren
          st %o5,[%o0]          // Digit ablegen
          srl %o4,%g1,%o3       // dessen höchste i Bits liefern den neuen Carry
          bne 1b
         _ add %o0,4,%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
        andcc %o2,%o2,%g0
        be 2f
       _ mov 0,%o4              // Carry := 0
        sub %g0,%o3,%g1         // 32-i (mod 32)
1:        ld [%o0],%o5          // Digit
          subcc %o2,1,%o2
          sll %o5,%o3,%g2       // dessen niedere (32-i) Bits
          or %o4,%g2,%g2        // mit dem alten Carry kombinieren
          st %g2,[%o1]          // Digit ablegen
          add %o1,4,%o1
          srl %o5,%g1,%o4       // dessen höchste i Bits liefern den neuen Carry
          bne 1b
         _ add %o0,4,%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
        andcc %o1,%o1,%g0
        be 2f
       _ sll %o2,31,%o2         // Carry
        sub %o0,4,%o0
1:        ld [%o0],%o3          // Digit
          subcc %o1,1,%o1
          srl %o3,1,%o4         // shiften
          or %o2,%o4,%o4        // und mit altem Carry kombinieren
          st %o4,[%o0]          // und ablegen
          sll %o3,31,%o2        // neuer Carry
          bne 1b
         _ sub %o0,4,%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
        sub %g0,%o2,%g1         // 32-i (mod 32)
        andcc %o1,%o1,%g0
        be 2f
       _ or %g0,%g0,%o3         // Carry := 0
        sub %o0,4,%o0
1:        ld [%o0],%o4          // Digit
          subcc %o1,1,%o1
          srl %o4,%o2,%o5       // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          st %o5,[%o0]          // und ablegen
          sll %o4,%g1,%o3       // neuer Carry
          bne 1b
         _ sub %o0,4,%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
        ld [%o0-4],%o4          // erstes Digit
        sub %g0,%o2,%g1         // 32-i (mod 32)
        sra %o4,%o2,%o5         // shiften
        st %o5,[%o0-4]          // und ablegen
        sll %o4,%g1,%o3         // neuer Carry
        subcc %o1,1,%o1
        be 2f
       _ sub %o0,8,%o0
1:        ld [%o0],%o4          // Digit
          subcc %o1,1,%o1
          srl %o4,%o2,%o5       // shiften
          or %o3,%o5,%o5        // und mit altem Carry kombinieren
          st %o5,[%o0]          // und ablegen
          sll %o4,%g1,%o3       // neuer Carry
          bne 1b
         _ sub %o0,4,%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
        sub %g0,%o3,%g1         // 32-i (mod 32)
        andcc %o2,%o2,%g0
        be 2f
       _ sll %o4,%g1,%g2        // erster Carry
          sub %o0,4,%o0
1:        ld [%o0],%o4          // Digit
          sub %o1,4,%o1
          srl %o4,%o3,%o5       // shiften
          or %g2,%o5,%o5        // und mit altem Carry kombinieren
          st %o5,[%o1]          // und ablegen
          sll %o4,%g1,%g2       // neuer Carry
          subcc %o2,1,%o2
          bne 1b
         _ sub %o0,4,%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
        andcc %o2,%o2,%g0
        be 3f
       _ nop
1:        // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
          // und kleinen Carry %o3 dazu:
          mov %o0,%y
          ld [%o1],%o4          // Wartetakt!
          addcc %o3,%o3,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%o4,%o5
          mulscc %o5,%g0,%o5
          // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y
          // ergeben das Resultat. (Die anderen Bits sind Null.)
          tst %o4               // Korrektur, falls %o4 negativ war
          bge 2f
         _ sra %o5,26,%o3       // 6 obere Bits von %o5 -> neuer Carry
          add %o3,%o0,%o3       // (falls %o4 negativ war, noch + %o0)
2:        rd %y,%o4
          srl %o4,26,%o4        // 6 obere Bits von %y
          sll %o5,6,%o5         // 26 untere Bits von %o5
          or %o5,%o4,%o4        // neues Digit
          st %o4,[%o1]          // ablegen
          subcc %o2,1,%o2
          bne 1b
         _ add %o1,4,%o1
3:      retl
       _ mov %o3,%o0

// extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
#if !MULU32_INLINE
        DECLARE_FUNCTION(mulu_loop_up)
C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
        save %sp,-96,%sp
        mov 0,%l0               // Carry
1:        ld [%i1],%o1          // nächstes Digit
          add %i1,4,%i1
          call _mulu32_         // mit digit multiplizieren
         _ mov %i0,%o0
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
          st %o0,[%i2]         // Low-Digit ablegen
          subcc %i3,1,%i3
          bne 1b
         _ add %i2,4,%i2
        st %l0,[%i2]            // letzten Carry ablegen
        ret
       _ restore
#else
        DECLARE_FUNCTION(mulu_loop_up)
C(mulu_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1
        mov 0,%o4               // Carry
1:        ld [%o1],%g1          // nächstes Digit
          // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
#ifdef sparcv8
          add     %o1,4,%o1
          umul    %g1,%o0,%g1
          rd      %y,%o5
#else
          mov     %g1,%y
          add     %o1,4,%o1     // Wartetakt!
          andcc   %g0,%g0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%o0,%o5
          mulscc  %o5,%g0,%o5
          tst     %o0
          bl,a    2f
         __ add     %o5,%g1,%o5
2:        rd      %y,%g1
#endif
          addcc %o4,%g1,%g1     // und bisherigen Carry addieren
          addx %g0,%o5,%o4      // High-Digit gibt neuen Carry
          st %g1,[%o2]          // Low-Digit ablegen
          subcc %o3,1,%o3
          bne 1b
         _ add %o2,4,%o2
        retl
       _ st %o4,[%o2]           // letzten Carry ablegen
#endif

// 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
#if !MULU32_INLINE
        save %sp,-96,%sp
        mov 0,%l0               // Carry
1:        ld [%i1],%o1          // nächstes source-Digit
          add %i1,4,%i1
          call _mulu32_         // mit digit multiplizieren
         _ mov %i0,%o0
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
          addcc %o1,%o0,%o0     // addieren
          addx %g0,%l0,%l0
          st %o0,[%i2]          // Low-Digit ablegen
          subcc %i3,1,%i3
          bne 1b
         _ add %i2,4,%i2
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#else
        save %sp,-96,%sp
        mov 0,%l0               // Carry
#ifndef sparcv8
        sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
#endif
1:        ld [%i1],%o1          // nächstes source-Digit
          add %i1,4,%i1
          // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
#ifdef sparcv8
          umul    %i0,%o1,%o0
          rd      %y,%o2
#else
          mov     %o1,%y
          and     %o1,%l1,%o3   // Wartetakt!
          andcc   %g0,%g0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%g0,%o2
          add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
          rd      %y,%o0
#endif
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
          addcc %o1,%o0,%o0     // addieren
          addx %g0,%l0,%l0
          st %o0,[%i2]          // Low-Digit ablegen
          subcc %i3,1,%i3
          bne 1b
         _ add %i2,4,%i2
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#endif

// 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
#if !MULU32_INLINE
        save %sp,-96,%sp
        mov 0,%l0               // Carry
1:        ld [%i1],%o1          // nächstes source-Digit
          add %i1,4,%i1
          call _mulu32_         // mit digit multiplizieren
         _ mov %i0,%o0
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
          subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
          addx %g0,%l0,%l0
          st %o1,[%i2]         // dest-Digit ablegen
          subcc %i3,1,%i3
          bne 1b
         _ add %i2,4,%i2
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#else
        save %sp,-96,%sp
        mov 0,%l0               // Carry
#ifndef sparcv8
        sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
#endif
1:        ld [%i1],%o1          // nächstes source-Digit
          add %i1,4,%i1
          // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
#ifdef sparcv8
          umul    %i0,%o1,%o0
          rd      %y,%o2
#else
          mov     %o1,%y
          and     %o1,%l1,%o3   // Wartetakt!
          andcc   %g0,%g0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%i0,%o2
          mulscc  %o2,%g0,%o2
          add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
          rd      %y,%o0
#endif
          ld [%i2],%o1          // nächstes dest-digit
          addcc %l0,%o0,%o0     // und bisherigen Carry addieren
          addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
          subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
          addx %g0,%l0,%l0
          st %o1,[%i2]          // dest-Digit ablegen
          subcc %i3,1,%i3
          bne 1b
         _ add %i2,4,%i2
        mov %l0,%i0             // letzter Carry
        ret
       _ restore
#endif

// extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len);
        DECLARE_FUNCTION(divu_loop_down)
C(divu_loop_down:) // Input in %i0,%i1,%i2, Output in %i0
        save %sp,-96,%sp
        andcc %i2,%i2,%g0
        be 2f
       _ mov 0,%g1                 // Rest
1:        mov %g1,%o0              // Rest als High-Digit
          ld [%i1-4],%o1           // nächstes Digit als Low-Digit
          call C(divu_6432_3232_)  // zusammen durch digit dividieren
         _ mov %i0,%o2
          st %o0,[%i1-4]           // Quotient ablegen, Rest in %g1
          subcc %i2,1,%i2
          bne 1b
         _ sub %i1,4,%i1
2:      mov %g1,%i0                // Rest als Ergebnis
        ret
       _ restore

// extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        DECLARE_FUNCTION(divucopy_loop_down)
C(divucopy_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
        save %sp,-96,%sp
        andcc %i3,%i3,%g0
        be 2f
       _ mov 0,%g1                 // Rest
1:        mov %g1,%o0              // Rest als High-Digit
          ld [%i1-4],%o1           // nächstes Digit als Low-Digit
          call C(divu_6432_3232_)  // zusammen durch digit dividieren
         _ mov %i0,%o2
          sub %i2,4,%i2
          st %o0,[%i2]             // Quotient ablegen, Rest in %g1
          subcc %i3,1,%i3
          bne 1b
         _ sub %i1,4,%i1
2:      mov %g1,%i0                // Rest als Ergebnis
        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
        andcc %o2,%o2,%g0
        be 2f
       _ sub %g0,%o3,%g1        // 32-i (mod 32)
        sub %o1,%o0,%o1
        ld [%o0],%o4            // *xptr holen
1:        ld [%o0+%o1],%o5      // *yptr holen
          subcc %o2,1,%o2
          sll %o5,%o3,%g2       // dessen niedere (32-i) Bits
          xor %o4,%g2,%o4       // mit dem modifizierten *xptr kombinieren
          st %o4,[%o0]          // und ablegen
          add %o0,4,%o0
          srl %o5,%g1,%g2       // höchste i Bits von *yptr
          ld [%o0],%o4          // schon mal mit dem nächsten *xptr
          bne 1b
         _ xor %o4,%g2,%o4      // verknüpfen
        st %o4,[%o0]            // und ablegen
2:      retl
       _ nop



syntax highlighted by Code2HTML, v. 0.9.1