// Externe Routinen zu ARILEV1.D
// Prozessor: 80386 im native mode
// Assembler-Syntax: GNU oder SUN, Moves von links nach rechts
// Compiler: GNU-C oder SUN-C
// Parameter-Übergabe: auf dem Stack 4(%esp),8(%esp),...
// Register: %eax,%edx,%ecx dürfen stets verändert werden, alles andere retten.
// Ergebnis-Übergabe: in %eax
// Einstellungen: intCsize=32, intDsize=32.

// Bruno Haible 14.8.1992
// Zum Teil abgeschrieben von Bernhard Degels "v-i386.s"

  #ifdef UNDERSCORE
    #if defined(__STDC__) || defined (__cplusplus)
      #define C(entrypoint) _##entrypoint
    #else
      #define C(entrypoint) _/**/entrypoint
    #endif
  #else
    #define C(entrypoint) entrypoint
  #endif
  #if defined(UNDERSCORE) || defined(COHERENT) /* defined(__EMX__) || defined(__GO32__) || defined(linux) || defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(COHERENT) || ... */
    // GNU-Assembler oder MWC-Assembler
    #define repz     repe
    #define shcl     %cl,
  #else /* defined(sun) || ... */
    // SUN-Assembler oder Consensys-Assembler
    #define jecxz    orl %ecx,%ecx ; jz
    #define shcl
  #endif
  #if defined(__EMX__)
    // Direction-Flag ist defaultmäßig gelöscht
    #define dir0start
    #define dir0end
    #define dir1start  std
    #define dir1end    cld
  #elif 1
    // Wir gehen auf Nummer sicher.
    #define dir0start  cld
    #define dir0end
    #define dir1start  std
    #define dir1end    cld
  #else
    // Direction-Flag darf nach Belieben modifiziert werden
    #define dir0start  cld
    #define dir0end
    #define dir1start  std
    #define dir1end
  #endif
  // Alignment. Note that some assemblers need ".align 3,0x90" whereas other
  // assemblers don't like this syntax. So we put in the "nop"s by hand.
  #ifdef UNDERSCORE
    // BSD syntax assembler
    #define ALIGN  .align 3
  #else
    // ELF syntax assembler
    #define ALIGN  .align 8
  #endif

        .text

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

#ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */

// extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
// 2^32*hi+lo := arg1*arg2.
        ALIGN
        .globl C(mulu32_)
C(mulu32_:)
        movl    4(%esp),%eax    // arg1
        mull    8(%esp)         // %edx|%eax := arg1 * arg2
        movl    %edx,C(mulu32_high) // %edx = hi abspeichern
        ret                     // %eax = lo als Ergebnis

#endif

#ifndef __GNUC__ /* mit GNU-C machen wir divu_6432_3232() als Macro, der inline multipliziert */

// 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 .
        ALIGN
        .globl C(divu_6432_3232_)
C(divu_6432_3232_:)
        movl    4(%esp),%edx
        movl    8(%esp),%eax
        divl    12(%esp)       // x = %edx|%eax durch dividieren
        movl    %edx,C(divu_32_rest) // Rest %edx = r abspeichern
        ret                    // Quotient %eax = q als Ergebnis

#endif

// extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
        ALIGN
C(copy_loop_up:)
        movl    %edi,%edx       // %edi retten
        movl    %esi,%eax       // %esi retten
        movl    4(%esp),%esi    // %esi = sourceptr
        movl    8(%esp),%edi    // %edi = destptr
        movl    12(%esp),%ecx   // %ecx = count
        dir0start
        rep
          movsl                 // %ecx mal aufwärts (%edi) := (%esi)
        dir0end
        movl    %eax,%esi       // %esi zurück
        movl    %edi,%eax       // %edi als Ergebnis
        movl    %edx,%edi       // %edi zurück
        ret

// extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
        ALIGN
C(copy_loop_down:)
        movl    %edi,%edx       // %edi retten
        movl    %esi,%eax       // %esi retten
        movl    4(%esp),%esi    // %esi = sourceptr
        movl    8(%esp),%edi    // %edi = destptr
        movl    12(%esp),%ecx   // %ecx = count
        leal    -4(%esi),%esi
        leal    -4(%edi),%edi
        dir1start
        rep
          movsl                 // %ecx mal abwärts (%edi) := (%esi)
        dir1end
        movl    %eax,%esi       // %esi zurück
        leal    4(%edi),%eax    // %edi als Ergebnis
        movl    %edx,%edi       // %edi zurück
        ret

// extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
        ALIGN
C(fill_loop_up:)
        movl    %edi,%edx       // %edi retten
        movl    4(%esp),%edi    // %edi = destptr
        movl    8(%esp),%ecx    // %ecx = count
        movl    12(%esp),%eax   // %eax = filler
        dir0start
        rep
          stosl                 // %ecx mal aufwärts (%edi) := %eax
        dir0end
        movl    %edi,%eax       // %edi als Ergebnis
        movl    %edx,%edi       // %edi zurück
        ret

// extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
        ALIGN
C(fill_loop_down:)
        movl    %edi,%edx       // %edi retten
        movl    4(%esp),%edi    // %edi = destptr
        movl    8(%esp),%ecx    // %ecx = count
        movl    12(%esp),%eax   // %eax = filler
        leal    -4(%edi),%edi
        dir1start
        rep
          stosl                 // %ecx mal abwärts (%edi) := %eax
        dir1end
        leal    4(%edi),%eax    // %edi als Ergebnis
        movl    %edx,%edi       // %edi zurück
        ret

// extern uintD* clear_loop_up (uintD* destptr, uintC count);
        ALIGN
C(clear_loop_up:)
        movl    %edi,%edx       // %edi retten
        movl    4(%esp),%edi    // %edi = destptr
        movl    8(%esp),%ecx    // %ecx = count
        xorl    %eax,%eax       // %eax = 0
        dir0start
        rep
          stosl                 // %ecx mal aufwärts (%edi) := %eax
        dir0end
        movl    %edi,%eax       // %edi als Ergebnis
        movl    %edx,%edi       // %edi zurück
        ret

// extern uintD* clear_loop_down (uintD* destptr, uintC count);
        ALIGN
C(clear_loop_down:)
        movl    %edi,%edx       // %edi retten
        movl    4(%esp),%edi    // %edi = destptr
        movl    8(%esp),%ecx    // %ecx = count
        leal    -4(%edi),%edi
        xorl    %eax,%eax       // %eax = 0
        dir1start
        rep
          stosl                 // %ecx mal abwärts (%edi) := %eax
        dir1end
        leal    4(%edi),%eax    // %edi als Ergebnis
        movl    %edx,%edi       // %edi zurück
        ret

// extern boolean test_loop_up (uintD* ptr, uintC count);
        ALIGN
C(test_loop_up:)
        movl    %edi,%edx       // %edi retten
        movl    4(%esp),%edi    // %edi = ptr
        movl    8(%esp),%ecx    // %ecx = count
        xorl    %eax,%eax       // %eax = 0
        dir0start
        repz                    // Falls %ecx > 0:
          scasl                 // %ecx mal aufwärts (%edi) testen
                                // und weiterschleifen, falls Z, d.h. (%edi)=0.
        dir0end
        // Noch ist %eax = 0.
        jz      tlu1            // alles =0 -> Ergebnis 0
        incl    %eax            // Ergebnis 1
tlu1:   movl    %edx,%edi       // %edi zurück
        ret

// extern boolean test_loop_down (uintD* ptr, uintC count);
        ALIGN
C(test_loop_down:)
        movl    %edi,%edx       // %edi retten
        movl    4(%esp),%edi    // %edi = ptr
        movl    8(%esp),%ecx    // %ecx = count
        xorl    %eax,%eax       // %eax = 0
        leal    -4(%edi),%edi
        dir1start
        repz                    // Falls %ecx > 0:
          scasl                 // %ecx mal aufwärts (%edi) testen
                                // und weiterschleifen, falls Z, d.h. (%edi)=0.
        dir1end
        // Noch ist %eax = 0.
        jz      tld1            // alles =0 -> Ergebnis 0
        incl    %eax            // Ergebnis 1
tld1:   movl    %edx,%edi       // %edi zurück
        ret

#if CL_DS_BIG_ENDIAN_P

// extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(or_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   olu2            // %ecx = 0 ?
olu1:     movl    (%edx,%esi),%eax // *yptr
          orl     %eax,(%edx)      // *xptr |= ...
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     olu1
olu2:   popl    %esi            // %esi zurück
        ret

// extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(xor_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   xlu2            // %ecx = 0 ?
xlu1:     movl    (%edx,%esi),%eax // *yptr
          xorl    %eax,(%edx)      // *xptr ^= ...
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     xlu1
xlu2:   popl    %esi            // %esi zurück
        ret

// extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(and_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   alu2            // %ecx = 0 ?
alu1:     movl    (%edx,%esi),%eax // *yptr
          andl    %eax,(%edx)      // *xptr &= ...
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     alu1
alu2:   popl    %esi            // %esi zurück
        ret

// extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(eqv_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   elu2            // %ecx = 0 ?
elu1:     movl    (%edx),%eax      // *xptr
          xorl    (%edx,%esi),%eax // ^ *yptr
          notl    %eax             // ~(...)
          movl    %eax,(%edx)      // =: *xptr
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     elu1
elu2:   popl    %esi            // %esi zurück
        ret

// extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(nand_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   nalu2           // %ecx = 0 ?
nalu1:    movl    (%edx),%eax      // *xptr
          andl    (%edx,%esi),%eax // & *yptr
          notl    %eax             // ~(...)
          movl    %eax,(%edx)      // =: *xptr
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     nalu1
nalu2:  popl    %esi            // %esi zurück
        ret

// extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(nor_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   nolu2           // %ecx = 0 ?
nolu1:    movl    (%edx),%eax      // *xptr
          orl     (%edx,%esi),%eax // | *yptr
          notl    %eax             // ~(...)
          movl    %eax,(%edx)      // =: *xptr
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     nolu1
nolu2:  popl    %esi            // %esi zurück
        ret

// extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(andc2_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   aclu2           // %ecx = 0 ?
aclu1:    movl    (%edx,%esi),%eax // *yptr
          notl    %eax             // ~ *yptr
          andl    %eax,(%edx)      // *xptr &= ...
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     aclu1
aclu2:  popl    %esi            // %esi zurück
        ret

// extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(orc2_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   oclu2           // %ecx = 0 ?
oclu1:    movl    (%edx,%esi),%eax // *yptr
          notl    %eax             // ~ *yptr
          orl     %eax,(%edx)      // *xptr |= ...
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     oclu1
oclu2:  popl    %esi            // %esi zurück
        ret

// extern void not_loop_up (uintD* xptr, uintC count);
        ALIGN
C(not_loop_up:)
        movl    4(%esp),%edx    // %edx = xptr
        movl    8(%esp),%ecx    // %ecx = count
        jecxz   nlu2            // %ecx = 0 ?
        nop ; nop ; nop ; nop ; nop ; nop
nlu1:     notl    (%edx)           // ~= *xptr
          leal    4(%edx),%edx     // xptr++
          decl    %ecx
          jnz     nlu1
nlu2:   ret

// extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(and_test_loop_up:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        jecxz   atlu2           // %ecx = 0 ?
        subl    %edx,%esi
atlu1:    movl    (%edx,%esi),%eax // *yptr
          andl    (%edx),%eax      // *xptr & ...
          jnz     atlu3
          leal    4(%edx),%edx     // xptr++, yptr++
          decl    %ecx
          jnz     atlu1
atlu2:  xorl    %eax,%eax       // Ergebnis 0
        popl    %esi            // %esi zurück
        ret
atlu3:  movl    $1,%eax         // Ergebnis 1 (nicht irgendwas /=0 !)
        popl    %esi            // %esi zurück
        ret

// extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(compare_loop_up:)
        movl    %esi,%edx       // %esi retten
        movl    %edi,%eax       // %edi retten
        movl    4(%esp),%esi    // %esi = xptr
        movl    8(%esp),%edi    // %edi = yptr
        movl    12(%esp),%ecx   // %ecx = count
        dir0start
        repz                    // Falls %ecx > 0:
          cmpsl                 // %ecx mal aufwärts (%edi) und (%esi) vergleichen
                                // und weiterschleifen, falls Z, d.h. (%edi)=(%esi).
        dir0end
        // Flags -> Ergebnis:
        // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0
        // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x<y -> Ergebnis -1
        // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1
        movl    %eax,%edi       // %edi zurück
        movl    %edx,%esi       // %esi zurück
        jbe     cmlu1           // "be" = Z oder C
        movl    $1,%eax         // Ergebnis +1
        ret
cmlu1:  sbbl    %eax,%eax       // Ergebnis -1 (falls C) oder 0 (falls NC)
        ret

// extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        ALIGN
C(add_loop_down:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        movl    12(%esp),%edx   // %edx = sourceptr1
        movl    16(%esp),%esi   // %esi = sourceptr2
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        subl    %edi,%esi
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      ald2
ald1:     leal    -4(%edi),%edi   // sourceptr1--, sourceptr2--, destptr--
          movl    (%edx,%edi),%eax // *sourceptr1
          adcl    (%esi,%edi),%eax // + *sourceptr2 + carry
          movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
          decl    %ecx
          jnz     ald1
ald2:   sbbl    %eax,%eax      // Ergebnis := - Carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret

// extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
        ALIGN
C(addto_loop_down:)
        pushl   %edi            // %edi retten
        movl    8(%esp),%edx    // %edx = sourceptr
        movl    12(%esp),%edi   // %edi = destptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      atld2
atld1:    leal    -4(%edi),%edi   // sourceptr--, destptr--
          movl    (%edx,%edi),%eax // *sourceptr
          adcl    %eax,(%edi)     // + *destptr + carry =: *destptr, neuer Carry
          decl    %ecx
          jnz     atld1
atld2:  sbbl    %eax,%eax       // Ergebnis := - Carry
        popl    %edi            // %edi zurück
        ret

// extern uintD inc_loop_down (uintD* ptr, uintC count);
        ALIGN
C(inc_loop_down:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        jecxz   ild2            // %ecx = 0 ?
ild1:     leal    -4(%edx),%edx
          addl    $1,(%edx)       // (*ptr)++
          jnc     ild3            // kein Carry -> fertig
          decl    %ecx
          jnz     ild1
ild2:   movl    $1,%eax         // Ergebnis := 1
        ret
ild3:   xorl    %eax,%eax       // Ergebnis := 0
        ret

// extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        ALIGN
C(sub_loop_down:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        movl    12(%esp),%edx   // %edx = sourceptr1
        movl    16(%esp),%esi   // %esi = sourceptr2
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        subl    %edi,%esi
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      sld2
sld1:     leal    -4(%edi),%edi   // sourceptr1--, sourceptr2--, destptr--
          movl    (%edx,%edi),%eax // *sourceptr1
          sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
          movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
          decl    %ecx
          jnz     sld1
sld2:   sbbl    %eax,%eax      // Ergebnis := - Carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret

// extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
        ALIGN
C(subx_loop_down:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        movl    12(%esp),%edx   // %edx = sourceptr1
        movl    16(%esp),%esi   // %esi = sourceptr2
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%ecx   // %ecx = count
        jecxz   sxld2           // %ecx = 0 ?
        subl    %edi,%edx
        subl    %edi,%esi
        movl    28(%esp),%eax   // carry, 0 oder -1
        addl    %eax,%eax       // Bit 31 davon in den Carry
        nop ; nop
sxld1:    leal    -4(%edi),%edi   // sourceptr1--, sourceptr2--, destptr--
          movl    (%edx,%edi),%eax // *sourceptr1
          sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
          movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
          decl    %ecx
          jnz     sxld1
        sbbl    %eax,%eax      // Ergebnis := - Carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret
sxld2:  movl    28(%esp),%eax  // Ergebnis := carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret

// extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
        ALIGN
C(subfrom_loop_down:)
        pushl   %edi            // %edi retten
        movl    8(%esp),%edx    // %edx = sourceptr
        movl    12(%esp),%edi   // %edi = destptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      sfld2
sfld1:    leal    -4(%edi),%edi   // sourceptr--, destptr--
          movl    (%edx,%edi),%eax // *sourceptr
          sbbl    %eax,(%edi)     // *destptr - *sourceptr - carry =: *destptr, neuer Carry
          decl    %ecx
          jnz     sfld1
sfld2:  sbbl    %eax,%eax       // Ergebnis := - Carry
        popl    %edi            // %edi zurück
        ret

// extern uintD dec_loop_down (uintD* ptr, uintC count);
        ALIGN
C(dec_loop_down:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        jecxz   dld2            // %ecx = 0 ?
dld1:     leal    -4(%edx),%edx
          subl    $1,(%edx)       // (*ptr)--
          jnc     dld3            // kein Carry -> fertig
          decl    %ecx
          jnz     dld1
dld2:   movl    $-1,%eax        // Ergebnis := -1
        ret
dld3:   xorl    %eax,%eax       // Ergebnis := 0
        ret

// extern uintD neg_loop_down (uintD* ptr, uintC count);
        ALIGN
C(neg_loop_down:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        // erstes Digit /=0 suchen:
        jecxz   nld2            // %ecx = 0 ?
nld1:     leal    -4(%edx),%edx
          negl    (%edx)
          jnz     nld3
          decl    %ecx
          jnz     nld1
nld2:   xorl    %eax,%eax       // Ergebnis := 0
        ret
        nop ; nop ; nop ; nop ; nop ; nop
nld3:   // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // alle anderen Digits invertieren:
        decl    %ecx
        jz      nld5
nld4:     leal    -4(%edx),%edx
          notl    (%edx)
          decl    %ecx
          jnz     nld4
nld5:   movl    $-1,%eax        // Ergebnis := -1
        ret

// extern uintD shift1left_loop_down (uintD* ptr, uintC count);
        ALIGN
C(shift1left_loop_down:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      s1lld2
        nop ; nop ; nop ; nop
s1lld1:   leal    -4(%edx),%edx   // ptr--
          rcll    $1,(%edx)       // *ptr und Carry um 1 Bit links rotieren
          decl    %ecx
          jnz     s1lld1
s1lld2: sbbl    %eax,%eax       // Ergebnis := - Carry
        ret

// extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
        ALIGN
C(shiftleft_loop_down:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%edi   // %edi = ptr
        movl    16(%esp),%edx   // %edx = count
        movb    20(%esp),%cl    // %cl = i
        orl     %edx,%edx       // count = 0 ?
        jz      slld4
        // erstes Digit shiften:
        leal    -4(%edi),%edi
        movl    (%edi),%eax     // Digit in %eax halten
        movl    %eax,%ebx       // und in %ebx rechnen:
        shll    %cl,%ebx        // um i Bits links shiften
        orl     24(%esp),%ebx   // und die unteren i Bits eintragen
        movl    %ebx,(%edi)     // und wieder ablegen
        // Letztes Digit in %eax.
        decl    %edx
        jz      slld2
        nop ; nop ; nop ; nop
slld1:    // weiteres Digit shiften:
          leal    -4(%edi),%edi
          movl    (%edi),%ebx
          shldl   shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften
          // Letztes Digit in %ebx.
          decl    %edx
          jz      slld3
          // weiteres Digit shiften:
          leal    -4(%edi),%edi
          movl    (%edi),%eax
          shldl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften
          // Letztes Digit in %eax.
          decl    %edx
          jnz     slld1
slld2:  movl    %eax,%ebx
slld3:  xorl    %eax,%eax       // %eax := 0
        shldl   shcl %ebx,%eax  // %eax := höchste %cl=i Bits von %ebx
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret
slld4:  movl    24(%esp),%eax   // %eax := carry
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
        ALIGN
C(shiftleftcopy_loop_down:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%esi   // %esi = sourceptr
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%edx   // count
        movb    28(%esp),%cl    // i
        orl     %edx,%edx       // count = 0 ?
        jz      slcld4
        subl    %edi,%esi
        // erstes Digit shiften:
        leal    -4(%edi),%edi   // sourceptr--, destptr--
        movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
        movl    %ebx,%eax       // und in %eax rechnen:
        shll    %cl,%eax        // um i Bits links shiften, rechts Nullen rein
        movl    %eax,(%edi)     // und als *destptr ablegen
        // Letztes Digit in %ebx.
        negb    %cl             // 32-i
        decl    %edx
        jz      slcld2
slcld1:   // weiteres Digit shiften:
          leal    -4(%edi),%edi   // sourceptr--, destptr--
          movl    (%edi,%esi),%eax // nächstes Digit nach %eax
          shrdl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften
          movl    %ebx,(%edi)     // %ebx als *destptr ablegen
          // Letztes Digit in %eax.
          decl    %edx
          jz      slcld3
          // weiteres Digit shiften:
          leal    -4(%edi),%edi   // sourceptr--, destptr--
          movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
          shrdl   shcl %ebx,%eax  // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften
          movl    %eax,(%edi)     // %eax als *destptr ablegen
          // Letztes Digit in %ebx.
          decl    %edx
          jnz     slcld1
slcld2: movl    %ebx,%eax
slcld3: shrl    %cl,%eax        // %eax um 32-i Bits nach rechts shiften
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %esi            // %esi zurück
        ret
slcld4: xorl    %eax,%eax       // %eax := 0
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %esi            // %esi zurück
        ret

// extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
        ALIGN
C(shift1right_loop_up:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        movl    12(%esp),%eax   // %eax = carry (0 oder -1)
        jecxz   s1rld3          // %ecx = 0 ?
        addl    %eax,%eax       // Carry := Bit 31 von carry
s1rld1:   rcrl    $1,(%edx)       // *ptr und Carry um 1 Bit rechts rotieren
          leal    4(%edx),%edx    // ptr++
          decl    %ecx
          jnz     s1rld1
s1rld2: sbbl    %eax,%eax       // Ergebnis := - Carry
s1rld3: ret

// extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
        ALIGN
C(shiftright_loop_up:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%edi   // %edi = ptr
        movl    16(%esp),%edx   // %edx = count
        movb    20(%esp),%cl    // %cl = i
        orl     %edx,%edx       // count = 0 ?
        jz      srlu4
        // erstes Digit shiften:
        movl    (%edi),%eax     // Digit in %eax halten
        movl    %eax,%ebx       // und in %ebx rechnen:
        shrl    %cl,%ebx        // um i Bits rechts shiften
        movl    %ebx,(%edi)     // und wieder ablegen
        // Letztes Digit in %eax.
        decl    %edx
        jz      srlu2
        nop ; nop ; nop
srlu1:    // weiteres Digit shiften:
          leal    4(%edi),%edi
          movl    (%edi),%ebx
          shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
          // Letztes Digit in %ebx.
          decl    %edx
          jz      srlu3
          // weiteres Digit shiften:
          leal    4(%edi),%edi
          movl    (%edi),%eax
          shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
          // Letztes Digit in %eax.
          decl    %edx
          jnz     srlu1
srlu2:  movl    %eax,%ebx
srlu3:  xorl    %eax,%eax       // %eax := 0
        shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret
srlu4:  xorl    %eax,%eax       // %eax := 0
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
        ALIGN
C(shiftrightsigned_loop_up:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%edi   // %edi = ptr
        movl    16(%esp),%edx   // %edx = count
        movb    20(%esp),%cl    // %cl = i
        // erstes Digit shiften:
        movl    (%edi),%eax     // Digit in %eax halten
        movl    %eax,%ebx       // und in %ebx rechnen:
        sarl    %cl,%ebx        // um i Bits rechts shiften, Vorzeichen vervielfachen
        movl    %ebx,(%edi)     // und wieder ablegen
        // Letztes Digit in %eax.
        decl    %edx
        jz      srslu2
srslu1:   // weiteres Digit shiften:
          leal    4(%edi),%edi
          movl    (%edi),%ebx
          shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
          // Letztes Digit in %ebx.
          decl    %edx
          jz      srslu3
          // weiteres Digit shiften:
          leal    4(%edi),%edi
          movl    (%edi),%eax
          shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
          // Letztes Digit in %eax.
          decl    %edx
          jnz     srslu1
srslu2: movl    %eax,%ebx
srslu3: xorl    %eax,%eax       // %eax := 0
        shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
        ALIGN
C(shiftrightcopy_loop_up:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%esi   // %esi = sourceptr
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%edx   // count
        movb    28(%esp),%cl    // i
        negb    %cl             // 32-i
        movl    32(%esp),%eax   // %eax = carry
        orl     %edx,%edx       // count = 0 ?
        jz      srcld3
        subl    %edi,%esi
        // erstes Digit shiften:
        movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
        shldl   shcl %ebx,%eax  // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein
        movl    %eax,(%edi)     // und als *destptr ablegen
        // Letztes Digit in %ebx.
        decl    %edx
        jz      srcld2
srcld1:   // weiteres Digit shiften:
          leal    4(%edi),%edi    // sourceptr++, destptr++
          movl    (%edi,%esi),%eax // nächstes Digit nach %eax
          shldl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften
          movl    %ebx,(%edi)     // %ebx als *destptr ablegen
          // Letztes Digit in %eax.
          decl    %edx
          jz      srcld3
          // weiteres Digit shiften:
          leal    4(%edi),%edi    // sourceptr++, destptr++
          movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
          shldl   shcl %ebx,%eax  // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften
          movl    %eax,(%edi)     // %eax als *destptr ablegen
          // Letztes Digit in %ebx.
          decl    %edx
          jnz     srcld1
srcld2: movl    %ebx,%eax
srcld3: shll    %cl,%eax        // %eax um 32-i Bits nach links shiften
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %esi            // %esi zurück
        ret

// extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
        ALIGN
C(mulusmall_loop_down:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%ebx   // %ebx = digit
        movl    20(%esp),%edi   // %edi = ptr
        movl    24(%esp),%ecx   // %ecx = len
        movl    28(%esp),%ebp   // %ebp = carry := newdigit
        movl    %ecx,%eax
        negl    %eax            // %eax = -len
        jz      msld2
        leal    -4(%edi,%eax,4),%edi // %edi = &ptr[-1-len]
        nop ; nop ; nop
msld1:    movl    (%edi,%ecx,4),%eax // *ptr
          mull    %ebx               // %edx|%eax := digit * *ptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
          movl    %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen
          decl    %ecx               // count--, ptr--
          jnz     msld1
msld2:  movl    %ebp,%eax       // Ergebnis := letzter Übertrag
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(mulu_loop_down:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    20(%esp),%ebx   // %ebx = digit
        movl    24(%esp),%esi   // %esi = sourceptr
        movl    28(%esp),%edi   // %edi = destptr
        movl    32(%esp),%ecx   // %ecx = len
        movl    %ecx,%eax
        notl    %eax            // %eax = -1-len
        leal    (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len]
        leal    (%edi,%eax,4),%edi // %edi = &destptr[-1-len]
        xorl    %ebp,%ebp       // %epb = carry := 0
muld1:    movl    (%esi,%ecx,4),%eax // *sourceptr
          mull    %ebx               // %edx|%eax := digit * *sourceptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
          movl    %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen
          decl    %ecx               // count--, sourceptr--, destptr--
          jnz     muld1
        movl    %ebp,(%edi)     // letzten Übertrag ablegen
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(muluadd_loop_down:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    20(%esp),%ebx   // %ebx = digit
        movl    24(%esp),%esi   // %esi = sourceptr
        movl    28(%esp),%edi   // %edi = destptr
        movl    32(%esp),%ecx   // %ecx = len
        movl    %ecx,%eax
        notl    %eax            // %eax = -1-len
        leal    (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len]
        leal    (%edi,%eax,4),%edi // %edi = &destptr[-1-len]
        xorl    %ebp,%ebp       // %epb = carry := 0
muald1:   movl    (%esi,%ecx,4),%eax // *sourceptr
          mull    %ebx               // %edx|%eax := digit * *sourceptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
          addl    %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren
          adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
          decl    %ecx               // count--, sourceptr--, destptr--
          jnz     muald1
        movl    %ebp,%eax       // Ergebnis := letzter Übertrag
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(mulusub_loop_down:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    20(%esp),%ebx   // %ebx = digit
        movl    24(%esp),%esi   // %esi = sourceptr
        movl    28(%esp),%edi   // %edi = destptr
        movl    32(%esp),%ecx   // %ecx = len
        movl    %ecx,%eax
        notl    %eax            // %eax = -1-len
        leal    (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len]
        leal    (%edi,%eax,4),%edi // %edi = &destptr[-1-len]
        xorl    %ebp,%ebp       // %epb = carry := 0
musld1:   movl    (%esi,%ecx,4),%eax // *sourceptr
          mull    %ebx               // %edx|%eax := digit * *sourceptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
          subl    %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren
          adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
          decl    %ecx               // count--, sourceptr--, destptr--
          jnz     musld1
        movl    %ebp,%eax       // Ergebnis := letzter Übertrag
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
        ALIGN
C(divu_loop_up:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%ebx   // %ebx = digit
        movl    16(%esp),%edi   // %edi = ptr
        movl    20(%esp),%ecx   // %ecx = len
        xorl    %edx,%edx       // %edx = Rest := 0
        jecxz   dlu2            // %ecx = 0 ?
dlu1:     movl    (%edi),%eax     // nächstes Digit *ptr
          divl    %ebx            // Division von %edx|%eax durch %ebx
          movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
          leal    4(%edi),%edi    // ptr++
          decl    %ecx
          jnz     dlu1
dlu2:   movl    %edx,%eax       // Ergebnis := letzter Rest
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(divucopy_loop_up:)
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%ebx   // %ebx = digit
        movl    20(%esp),%esi   // %esi = sourceptr
        movl    24(%esp),%edi   // %edi = destptr
        movl    28(%esp),%ecx   // %ecx = len
        xorl    %edx,%edx       // %edx = Rest := 0
        jecxz   dclu2           // %ecx = 0 ?
        subl    %edi,%esi
dclu1:    movl    (%esi,%edi),%eax // nächstes Digit *ptr
          divl    %ebx            // Division von %edx|%eax durch %ebx
          movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
          leal    4(%edi),%edi    // sourceptr++, destptr++
          decl    %ecx
          jnz     dclu1
dclu2:  movl    %edx,%eax       // Ergebnis := letzter Rest
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        ret

#else // !CL_DS_BIG_ENDIAN_P

// extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(or_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   old2            // %ecx = 0 ?
old1:     leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx,%esi),%eax // *yptr
          orl     %eax,(%edx)      // *xptr |= ...
          decl    %ecx
          jnz     old1
old2:   popl    %esi            // %esi zurück
        ret

// extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(xor_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   xld2            // %ecx = 0 ?
xld1:     leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx,%esi),%eax // *yptr
          xorl    %eax,(%edx)      // *xptr ^= ...
          decl    %ecx
          jnz     xld1
xld2:   popl    %esi            // %esi zurück
        ret

// extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(and_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   ald2            // %ecx = 0 ?
ald1:     leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx,%esi),%eax // *yptr
          andl    %eax,(%edx)      // *xptr &= ...
          decl    %ecx
          jnz     ald1
ald2:   popl    %esi            // %esi zurück
        ret

// extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(eqv_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   eld2            // %ecx = 0 ?
eld1:     leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx),%eax      // *xptr
          xorl    (%edx,%esi),%eax // ^ *yptr
          notl    %eax             // ~(...)
          movl    %eax,(%edx)      // =: *xptr
          decl    %ecx
          jnz     eld1
eld2:   popl    %esi            // %esi zurück
        ret

// extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(nand_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   nald2           // %ecx = 0 ?
nald1:    leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx),%eax      // *xptr
          andl    (%edx,%esi),%eax // & *yptr
          notl    %eax             // ~(...)
          movl    %eax,(%edx)      // =: *xptr
          decl    %ecx
          jnz     nald1
nald2:  popl    %esi            // %esi zurück
        ret

// extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(nor_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   nold2           // %ecx = 0 ?
nold1:    leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx),%eax      // *xptr
          orl     (%edx,%esi),%eax // | *yptr
          notl    %eax             // ~(...)
          movl    %eax,(%edx)      // =: *xptr
          decl    %ecx
          jnz     nold1
nold2:  popl    %esi            // %esi zurück
        ret

// extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(andc2_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   acld2           // %ecx = 0 ?
acld1:    leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx,%esi),%eax // *yptr
          notl    %eax             // ~ *yptr
          andl    %eax,(%edx)      // *xptr &= ...
          decl    %ecx
          jnz     acld1
acld2:  popl    %esi            // %esi zurück
        ret

// extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(orc2_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edx,%esi
        jecxz   ocld2           // %ecx = 0 ?
ocld1:    leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx,%esi),%eax // *yptr
          notl    %eax             // ~ *yptr
          orl     %eax,(%edx)      // *xptr |= ...
          decl    %ecx
          jnz     ocld1
ocld2:  popl    %esi            // %esi zurück
        ret

// extern void not_loop_down (uintD* xptr, uintC count);
        ALIGN
C(not_loop_down:)
        movl    4(%esp),%edx    // %edx = xptr
        movl    8(%esp),%ecx    // %ecx = count
        jecxz   nld2            // %ecx = 0 ?
        nop ; nop ; nop ; nop ; nop ; nop
nld1:     leal    -4(%edx),%edx    // xptr--
          notl    (%edx)           // ~= *xptr
          decl    %ecx
          jnz     nld1
nld2:   ret

// extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(and_test_loop_down:)
        pushl   %esi            // %esi retten
        movl    8(%esp),%edx    // %edx = xptr
        movl    12(%esp),%esi   // %esi = yptr
        movl    16(%esp),%ecx   // %ecx = count
        jecxz   atld2           // %ecx = 0 ?
        subl    %edx,%esi
atld1:    leal    -4(%edx),%edx    // xptr--, yptr--
          movl    (%edx,%esi),%eax // *yptr
          andl    (%edx),%eax      // *xptr & ...
          jnz     atld3
          decl    %ecx
          jnz     atld1
atld2:  xorl    %eax,%eax       // Ergebnis 0
        popl    %esi            // %esi zurück
        ret
atld3:  movl    $1,%eax         // Ergebnis 1 (nicht irgendwas /=0 !)
        popl    %esi            // %esi zurück
        ret

// extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
        ALIGN
C(compare_loop_down:)
        movl    %esi,%edx       // %esi retten
        movl    %edi,%eax       // %edi retten
        movl    4(%esp),%esi    // %esi = xptr
        movl    8(%esp),%edi    // %edi = yptr
        movl    12(%esp),%ecx   // %ecx = count
        leal    -4(%esi),%esi
        leal    -4(%edi),%edi
        dir1start
        repz                    // Falls %ecx > 0:
          cmpsl                 // %ecx mal aufwärts (%edi) und (%esi) vergleichen
                                // und weiterschleifen, falls Z, d.h. (%edi)=(%esi).
        dir1end
        // Flags -> Ergebnis:
        // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0
        // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x<y -> Ergebnis -1
        // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1
        movl    %eax,%edi       // %edi zurück
        movl    %edx,%esi       // %esi zurück
        jbe     cmld1           // "be" = Z oder C
        movl    $1,%eax         // Ergebnis +1
        ret
cmld1:  sbbl    %eax,%eax       // Ergebnis -1 (falls C) oder 0 (falls NC)
        ret

// extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        ALIGN
C(add_loop_up:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        movl    12(%esp),%edx   // %edx = sourceptr1
        movl    16(%esp),%esi   // %esi = sourceptr2
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        subl    %edi,%esi
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      alu2
alu1:     movl    (%edx,%edi),%eax // *sourceptr1
          adcl    (%esi,%edi),%eax // + *sourceptr2 + carry
          movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
          leal    4(%edi),%edi    // sourceptr1++, sourceptr2++, destptr++
          decl    %ecx
          jnz     alu1
alu2:   sbbl    %eax,%eax      // Ergebnis := - Carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret

// extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
        ALIGN
C(addto_loop_up:)
        pushl   %edi            // %edi retten
        movl    8(%esp),%edx    // %edx = sourceptr
        movl    12(%esp),%edi   // %edi = destptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      atlu2
atlu1:    movl    (%edx,%edi),%eax // *sourceptr
          adcl    %eax,(%edi)     // + *destptr + carry =: *destptr, neuer Carry
          leal    4(%edi),%edi    // sourceptr++, destptr++
          decl    %ecx
          jnz     atlu1
atlu2:  sbbl    %eax,%eax       // Ergebnis := - Carry
        popl    %edi            // %edi zurück
        ret

// extern uintD inc_loop_up (uintD* ptr, uintC count);
        ALIGN
C(inc_loop_up:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        jecxz   ilu2            // %ecx = 0 ?
ilu1:     addl    $1,(%edx)       // (*ptr)++
          jnc     ilu3            // kein Carry -> fertig
          leal    4(%edx),%edx
          decl    %ecx
          jnz     ilu1
ilu2:   movl    $1,%eax         // Ergebnis := 1
        ret
ilu3:   xorl    %eax,%eax       // Ergebnis := 0
        ret

// extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
        ALIGN
C(sub_loop_up:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        movl    12(%esp),%edx   // %edx = sourceptr1
        movl    16(%esp),%esi   // %esi = sourceptr2
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        subl    %edi,%esi
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      slu2
slu1:     movl    (%edx,%edi),%eax // *sourceptr1
          sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
          movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
          leal    4(%edi),%edi    // sourceptr1++, sourceptr2++, destptr++
          decl    %ecx
          jnz     slu1
slu2:   sbbl    %eax,%eax      // Ergebnis := - Carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret

// extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
        ALIGN
C(subx_loop_up:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        movl    12(%esp),%edx   // %edx = sourceptr1
        movl    16(%esp),%esi   // %esi = sourceptr2
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%ecx   // %ecx = count
        jecxz   sxlu2           // %ecx = 0 ?
        subl    %edi,%edx
        subl    %edi,%esi
        movl    28(%esp),%eax   // carry, 0 oder -1
        addl    %eax,%eax       // Bit 31 davon in den Carry
        nop ; nop
sxlu1:    movl    (%edx,%edi),%eax // *sourceptr1
          sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
          movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
          leal    4(%edi),%edi    // sourceptr1++, sourceptr2++, destptr++
          decl    %ecx
          jnz     sxlu1
        sbbl    %eax,%eax      // Ergebnis := - Carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret
sxlu2:  movl    28(%esp),%eax  // Ergebnis := carry
        popl    %edi           // %edi zurück
        popl    %esi           // %esi zurück
        ret

// extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
        ALIGN
C(subfrom_loop_up:)
        pushl   %edi            // %edi retten
        movl    8(%esp),%edx    // %edx = sourceptr
        movl    12(%esp),%edi   // %edi = destptr
        movl    16(%esp),%ecx   // %ecx = count
        subl    %edi,%edx
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      sflu2
sflu1:    movl    (%edx,%edi),%eax // *sourceptr
          sbbl    %eax,(%edi)     // *destptr - *sourceptr - carry =: *destptr, neuer Carry
          leal    4(%edi),%edi    // sourceptr++, destptr++
          decl    %ecx
          jnz     sflu1
sflu2:  sbbl    %eax,%eax       // Ergebnis := - Carry
        popl    %edi            // %edi zurück
        ret

// extern uintD dec_loop_up (uintD* ptr, uintC count);
        ALIGN
C(dec_loop_up:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        jecxz   dlu2            // %ecx = 0 ?
dlu1:     subl    $1,(%edx)       // (*ptr)--
          jnc     dlu3            // kein Carry -> fertig
          leal    4(%edx),%edx
          decl    %ecx
          jnz     dlu1
dlu2:   movl    $-1,%eax        // Ergebnis := -1
        ret
dlu3:   xorl    %eax,%eax       // Ergebnis := 0
        ret

// extern uintD neg_loop_up (uintD* ptr, uintC count);
        ALIGN
C(neg_loop_up:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        // erstes Digit /=0 suchen:
        jecxz   nlu2            // %ecx = 0 ?
nlu1:     negl    (%edx)
          jnz     nlu3
          leal    4(%edx),%edx
          decl    %ecx
          jnz     nlu1
nlu2:   xorl    %eax,%eax       // Ergebnis := 0
        ret
        nop ; nop ; nop ; nop ; nop ; nop
nlu3:   // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
        // alle anderen Digits invertieren:
        decl    %ecx
        jz      nlu5
nlu4:     leal    4(%edx),%edx
          notl    (%edx)
          decl    %ecx
          jnz     nlu4
nlu5:   movl    $-1,%eax        // Ergebnis := -1
        ret

// extern uintD shift1left_loop_up (uintD* ptr, uintC count);
        ALIGN
C(shift1left_loop_up:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
        jz      s1llu2
        nop ; nop ; nop ; nop
s1llu1:   rcll    $1,(%edx)       // *ptr und Carry um 1 Bit links rotieren
          leal    4(%edx),%edx    // ptr++
          decl    %ecx
          jnz     s1llu1
s1llu2: sbbl    %eax,%eax       // Ergebnis := - Carry
        ret

// extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
        ALIGN
C(shiftleft_loop_up:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%edi   // %edi = ptr
        movl    16(%esp),%edx   // %edx = count
        movb    20(%esp),%cl    // %cl = i
        orl     %edx,%edx       // count = 0 ?
        jz      sllu4
        // erstes Digit shiften:
        movl    (%edi),%eax     // Digit in %eax halten
        movl    %eax,%ebx       // und in %ebx rechnen:
        shll    %cl,%ebx        // um i Bits links shiften
        orl     24(%esp),%ebx   // und die unteren i Bits eintragen
        movl    %ebx,(%edi)     // und wieder ablegen
        leal    4(%edi),%edi
        // Letztes Digit in %eax.
        decl    %edx
        jz      sllu2
        nop ; nop ; nop ; nop
sllu1:    // weiteres Digit shiften:
          movl    (%edi),%ebx
          shldl   shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften
          leal    4(%edi),%edi
          // Letztes Digit in %ebx.
          decl    %edx
          jz      sllu3
          // weiteres Digit shiften:
          movl    (%edi),%eax
          shldl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften
          leal    4(%edi),%edi
          // Letztes Digit in %eax.
          decl    %edx
          jnz     sllu1
sllu2:  movl    %eax,%ebx
sllu3:  xorl    %eax,%eax       // %eax := 0
        shldl   shcl %ebx,%eax  // %eax := höchste %cl=i Bits von %ebx
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret
sllu4:  movl    24(%esp),%eax   // %eax := carry
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
        ALIGN
C(shiftleftcopy_loop_up:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%esi   // %esi = sourceptr
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%edx   // count
        movb    28(%esp),%cl    // i
        orl     %edx,%edx       // count = 0 ?
        jz      slclu4
        subl    %edi,%esi
        // erstes Digit shiften:
        movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
        movl    %ebx,%eax       // und in %eax rechnen:
        shll    %cl,%eax        // um i Bits links shiften, rechts Nullen rein
        movl    %eax,(%edi)     // und als *destptr ablegen
        leal    4(%edi),%edi    // sourceptr++, destptr++
        // Letztes Digit in %ebx.
        negb    %cl             // 32-i
        decl    %edx
        jz      slclu2
slclu1:   // weiteres Digit shiften:
          movl    (%edi,%esi),%eax // nächstes Digit nach %eax
          shrdl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften
          movl    %ebx,(%edi)     // %ebx als *destptr ablegen
          leal    4(%edi),%edi    // sourceptr++, destptr++
          // Letztes Digit in %eax.
          decl    %edx
          jz      slclu3
          // weiteres Digit shiften:
          movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
          shrdl   shcl %ebx,%eax  // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften
          movl    %eax,(%edi)     // %eax als *destptr ablegen
          leal    4(%edi),%edi    // sourceptr++, destptr++
          // Letztes Digit in %ebx.
          decl    %edx
          jnz     slclu1
slclu2: movl    %ebx,%eax
slclu3: shrl    %cl,%eax        // %eax um 32-i Bits nach rechts shiften
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %esi            // %esi zurück
        ret
slclu4: xorl    %eax,%eax       // %eax := 0
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %esi            // %esi zurück
        ret

// extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
        ALIGN
C(shift1right_loop_down:)
        movl    4(%esp),%edx    // %edx = ptr
        movl    8(%esp),%ecx    // %ecx = count
        movl    12(%esp),%eax   // %eax = carry (0 oder -1)
        jecxz   s1rlu3          // %ecx = 0 ?
        addl    %eax,%eax       // Carry := Bit 31 von carry
s1rlu1:   leal    -4(%edx),%edx   // ptr--
          rcrl    $1,(%edx)       // *ptr und Carry um 1 Bit rechts rotieren
          decl    %ecx
          jnz     s1rlu1
s1rlu2: sbbl    %eax,%eax       // Ergebnis := - Carry
s1rlu3: ret

// extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
        ALIGN
C(shiftright_loop_down:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%edi   // %edi = ptr
        movl    16(%esp),%edx   // %edx = count
        movb    20(%esp),%cl    // %cl = i
        orl     %edx,%edx       // count = 0 ?
        jz      srld4
        // erstes Digit shiften:
        leal    -4(%edi),%edi
        movl    (%edi),%eax     // Digit in %eax halten
        movl    %eax,%ebx       // und in %ebx rechnen:
        shrl    %cl,%ebx        // um i Bits rechts shiften
        movl    %ebx,(%edi)     // und wieder ablegen
        // Letztes Digit in %eax.
        decl    %edx
        jz      srld2
srld1:    // weiteres Digit shiften:
          leal    -4(%edi),%edi
          movl    (%edi),%ebx
          shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
          // Letztes Digit in %ebx.
          decl    %edx
          jz      srld3
          // weiteres Digit shiften:
          leal    -4(%edi),%edi
          movl    (%edi),%eax
          shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
          // Letztes Digit in %eax.
          decl    %edx
          jnz     srld1
srld2:  movl    %eax,%ebx
srld3:  xorl    %eax,%eax       // %eax := 0
        shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret
srld4:  xorl    %eax,%eax       // %eax := 0
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
        ALIGN
C(shiftrightsigned_loop_down:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%edi   // %edi = ptr
        movl    16(%esp),%edx   // %edx = count
        movb    20(%esp),%cl    // %cl = i
        // erstes Digit shiften:
        leal    -4(%edi),%edi
        movl    (%edi),%eax     // Digit in %eax halten
        movl    %eax,%ebx       // und in %ebx rechnen:
        sarl    %cl,%ebx        // um i Bits rechts shiften, Vorzeichen vervielfachen
        movl    %ebx,(%edi)     // und wieder ablegen
        // Letztes Digit in %eax.
        decl    %edx
        jz      srsld2
        nop ; nop ; nop ; nop
srsld1:   // weiteres Digit shiften:
          leal    -4(%edi),%edi
          movl    (%edi),%ebx
          shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
          // Letztes Digit in %ebx.
          decl    %edx
          jz      srsld3
          // weiteres Digit shiften:
          leal    -4(%edi),%edi
          movl    (%edi),%eax
          shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
          // Letztes Digit in %eax.
          decl    %edx
          jnz     srsld1
srsld2: movl    %eax,%ebx
srsld3: xorl    %eax,%eax       // %eax := 0
        shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
        ALIGN
C(shiftrightcopy_loop_down:)
        pushl   %esi            // %esi retten
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%esi   // %esi = sourceptr
        movl    20(%esp),%edi   // %edi = destptr
        movl    24(%esp),%edx   // count
        movb    28(%esp),%cl    // i
        negb    %cl             // 32-i
        movl    32(%esp),%eax   // %eax = carry
        orl     %edx,%edx       // count = 0 ?
        jz      srclu3
        subl    %edi,%esi
        // erstes Digit shiften:
        leal    -4(%edi),%edi   // sourceptr--, destptr--
        movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
        shldl   shcl %ebx,%eax  // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein
        movl    %eax,(%edi)     // und als *destptr ablegen
        // Letztes Digit in %ebx.
        decl    %edx
        jz      srclu2
        nop ; nop ; nop
srclu1:   // weiteres Digit shiften:
          leal    -4(%edi),%edi   // sourceptr--, destptr--
          movl    (%edi,%esi),%eax // nächstes Digit nach %eax
          shldl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften
          movl    %ebx,(%edi)     // %ebx als *destptr ablegen
          // Letztes Digit in %eax.
          decl    %edx
          jz      srclu3
          // weiteres Digit shiften:
          leal    -4(%edi),%edi   // sourceptr--, destptr--
          movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
          shldl   shcl %ebx,%eax  // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften
          movl    %eax,(%edi)     // %eax als *destptr ablegen
          // Letztes Digit in %ebx.
          decl    %edx
          jnz     srclu1
srclu2: movl    %ebx,%eax
srclu3: shll    %cl,%eax        // %eax um 32-i Bits nach links shiften
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %esi            // %esi zurück
        ret

// extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
        ALIGN
C(mulusmall_loop_up:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%ebx   // %ebx = digit
        movl    20(%esp),%edi   // %edi = ptr
        movl    24(%esp),%ecx   // %ecx = len
        movl    28(%esp),%ebp   // %ebp = carry := newdigit
        leal    (%edi,%ecx,4),%edi // %edi = &ptr[len]
        negl    %ecx            // %ecx = -count
        jz      mslu2
mslu1:    movl    (%edi,%ecx,4),%eax // *ptr
          mull    %ebx               // %edx|%eax := digit * *ptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
          movl    %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen
          incl    %ecx               // count--, ptr++
          jnz     mslu1
mslu2:  movl    %ebp,%eax       // Ergebnis := letzter Übertrag
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(mulu_loop_up:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    20(%esp),%ebx   // %ebx = digit
        movl    24(%esp),%esi   // %esi = sourceptr
        movl    28(%esp),%edi   // %edi = destptr
        movl    32(%esp),%ecx   // %ecx = len
        leal    (%esi,%ecx,4),%esi // %esi = &sourceptr[len]
        leal    (%edi,%ecx,4),%edi // %edi = &destptr[len]
        negl    %ecx            // %ecx = -count
        xorl    %ebp,%ebp       // %epb = carry := 0
        nop ; nop
mulu1:    movl    (%esi,%ecx,4),%eax // *sourceptr
          mull    %ebx               // %edx|%eax := digit * *sourceptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
          movl    %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen
          incl    %ecx               // count--, sourceptr++, destptr++
          jnz     mulu1
        movl    %ebp,(%edi)     // letzten Übertrag ablegen
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(muluadd_loop_up:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    20(%esp),%ebx   // %ebx = digit
        movl    24(%esp),%esi   // %esi = sourceptr
        movl    28(%esp),%edi   // %edi = destptr
        movl    32(%esp),%ecx   // %ecx = len
        leal    (%esi,%ecx,4),%esi // %esi = &sourceptr[len]
        leal    (%edi,%ecx,4),%edi // %edi = &destptr[len]
        negl    %ecx            // %ecx = -count
        xorl    %ebp,%ebp       // %epb = carry := 0
        nop ; nop
mualu1:   movl    (%esi,%ecx,4),%eax // *sourceptr
          mull    %ebx               // %edx|%eax := digit * *sourceptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
          addl    %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren
          adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
          incl    %ecx               // count--, sourceptr++, destptr++
          jnz     mualu1
        movl    %ebp,%eax       // Ergebnis := letzter Übertrag
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(mulusub_loop_up:)
        pushl   %ebp            // %ebp retten
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    20(%esp),%ebx   // %ebx = digit
        movl    24(%esp),%esi   // %esi = sourceptr
        movl    28(%esp),%edi   // %edi = destptr
        movl    32(%esp),%ecx   // %ecx = len
        leal    (%esi,%ecx,4),%esi // %esi = &sourceptr[len]
        leal    (%edi,%ecx,4),%edi // %edi = &destptr[len]
        negl    %ecx            // %ecx = -count
        xorl    %ebp,%ebp       // %epb = carry := 0
        nop ; nop
muslu1:   movl    (%esi,%ecx,4),%eax // *sourceptr
          mull    %ebx               // %edx|%eax := digit * *sourceptr
          addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
          movl    $0,%ebp
          adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
          subl    %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren
          adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
          incl    %ecx               // count--, sourceptr++, destptr++
          jnz     muslu1
        movl    %ebp,%eax       // Ergebnis := letzter Übertrag
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        popl    %ebp            // %ebp zurück
        ret

// extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len);
        ALIGN
C(divu_loop_down:)
        pushl   %edi            // %edi retten
        pushl   %ebx            // %ebx retten
        movl    12(%esp),%ebx   // %ebx = digit
        movl    16(%esp),%edi   // %edi = ptr
        movl    20(%esp),%ecx   // %ecx = len
        xorl    %edx,%edx       // %edx = Rest := 0
        jecxz   dld2            // %ecx = 0 ?
dld1:     leal    -4(%edi),%edi   // ptr--
          movl    (%edi),%eax     // nächstes Digit *ptr
          divl    %ebx            // Division von %edx|%eax durch %ebx
          movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
          decl    %ecx
          jnz     dld1
dld2:   movl    %edx,%eax       // Ergebnis := letzter Rest
        popl    %ebx            // %ebx zurück
        popl    %edi            // %edi zurück
        ret

// extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
        ALIGN
C(divucopy_loop_down:)
        pushl   %edi            // %edi retten
        pushl   %esi            // %esi retten
        pushl   %ebx            // %ebx retten
        movl    16(%esp),%ebx   // %ebx = digit
        movl    20(%esp),%esi   // %esi = sourceptr
        movl    24(%esp),%edi   // %edi = destptr
        movl    28(%esp),%ecx   // %ecx = len
        xorl    %edx,%edx       // %edx = Rest := 0
        jecxz   dcld2           // %ecx = 0 ?
        subl    %edi,%esi
dcld1:    leal    -4(%edi),%edi   // sourceptr--, destptr--
          movl    (%esi,%edi),%eax // nächstes Digit *ptr
          divl    %ebx            // Division von %edx|%eax durch %ebx
          movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
          decl    %ecx
          jnz     dcld1
dcld2:  movl    %edx,%eax       // Ergebnis := letzter Rest
        popl    %ebx            // %ebx zurück
        popl    %esi            // %esi zurück
        popl    %edi            // %edi zurück
        ret

#endif

