# Externe Routinen zu ARILEV1.D
# Compiler: CC oder GNU-C auf SUN3 oder AMIGA
# Parameter-Übergabe:
#   auf dem Stack: sp@(4), sp@(8), ... (.W-Größen belegen 4 Byte!),
#   Rückgabewert in d0.
# Register a0-a1,d0-d1 frei verwendbar,
# Register a2-a4,d2-d7 müssen gerettet werden.
# Einstellungen: intCsize=16, intDsize=16.

#ifdef INCLUDED_FROM_C

  #define COPY_LOOPS
  #define FILL_LOOPS
  #define CLEAR_LOOPS
  #define LOG_LOOPS
  #define TEST_LOOPS
  #define ADDSUB_LOOPS
  #define SHIFT_LOOPS
  #define MUL_LOOPS
  #define DIV_LOOPS

#else

           .text

           .globl _copy_loop_up,_copy_loop_down,_fill_loop_up,_fill_loop_down
           .globl _clear_loop_up,_clear_loop_down
           .globl _or_loop_up,_xor_loop_up,_and_loop_up,_eqv_loop_up
           .globl _nand_loop_up,_nor_loop_up,_andc2_loop_up,_orc2_loop_up
           .globl _not_loop_up
           .globl _and_test_loop_up,_test_loop_up,_compare_loop_up
           .globl _add_loop_down,_addto_loop_down,_inc_loop_down
           .globl _sub_loop_down,_subx_loop_down,_subfrom_loop_down,_dec_loop_down
           .globl _neg_loop_down
           .globl _shift1left_loop_down,_shiftleft_loop_down,_shiftleftcopy_loop_down
           .globl _shift1right_loop_up,_shiftright_loop_up,_shiftrightsigned_loop_up,_shiftrightcopy_loop_up
           .globl _mulusmall_loop_down,_mulu_loop_down,_muluadd_loop_down,_mulusub_loop_down
           .globl _divu_loop_up,_divucopy_loop_up

#ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */
           .globl _mulu32_
! extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
! 2^32*hi+lo := arg1*arg2.
mulu32_:   ! Input in d0,d1, Output in d0,mulu32_high
           movel sp@(4),d0
           movel sp@(8),d1
           movel d2,a0
           movel d3,a1
           movel d4,sp@-
           ! d0.L = 2^16*a+b, d1.L = 2^16*c+d -> Produkt
           ! (2^16*a+b)*(2^16*c+d) = 2^32*a*c + 2^16*(a*d+b*c) + b*d
           movel d0,d2
           swap d2      ! d2.W = a
           movel d1,d3
           swap d1      ! d1.W = c
           movel d1,d4
           mulu d2,d1   ! d1.L = a*c
           mulu d3,d2   ! d2.L = a*d
           mulu d0,d4   ! d4.L = b*c
           mulu d3,d0   ! d0.L = b*d
           clrl d3      ! Hilfsregister für Zero-Extend
           swap d2
           movew d2,d3
           addl d3,d1   ! high16(a*d) zu d1.L addieren
           swap d4
           movew d4,d3
           addl d3,d1   ! high16(b*c) zu d1.L addieren
           clrw d2
           addl d2,d0   ! 2^16*low16(a*d) zu d0.L addieren
           bccs 1f
           addql #1,d1
    1:     clrw d4
           addl d4,d0   ! 2^16*low16(b*c) zu d0.L addieren
           bccs 2f
           addql #1,d1
    2:     ! d0.L = lo, d1.L = hi fertig.
           movel d1,(_mulu32_high) ! Adressierung?? Deklaration??
           movel sp@+,d4
           movel a1,d3
           movel a0,d2
           rts
#endif

| extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
_copy_loop_up: | Input in a0,a1,d0.W, Output in d0
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a0@+,a1@+
    2:       dbra d0,1b
           movel a1,d0
           rts

| extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
_copy_loop_down: | Input in a0,a1,d0.W, Output in d0
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a0@-,a1@-
    2:       dbra d0,1b
           movel a1,d0
           rts

| extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
_fill_loop_up: | Input in a0,d0.W,d1.W, Output in d0
           movel sp@(4),a0
           movew sp@(8+2),d0
           movew sp@(12+2),d1
           bras 2f
    1:       movew d1,a0@+
    2:       dbra d0,1b
           movel a0,d0
           rts

| extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
_fill_loop_down: | Input in a0,d0.W,d1.W, Output in d0
           movel sp@(4),a0
           movew sp@(8+2),d0
           movew sp@(12+2),d1
           bras 2f
    1:       movew d1,a0@-
    2:       dbra d0,1b
           movel a0,d0
           rts

| extern uintD* clear_loop_up (uintD* destptr, uintC count);
_clear_loop_up: | Input in a0,d0.W, verändert d1, Output in d0
           movel sp@(4),a0
           movew sp@(8+2),d0
           moveq #0,d1
           bras 2f
    1:       movew d1,a0@+
    2:       dbra d0,1b
           movel a0,d0
           rts

| extern uintD* clear_loop_down (uintD* destptr, uintC count);
_clear_loop_down: | Input in a0,d0.W, verändert d1, Output in d0
           movel sp@(4),a0
           movew sp@(8+2),d0
           moveq #0,d1
           bras 2f
    1:       movew d1,a0@-
    2:       dbra d0,1b
           movel a0,d0
           rts

| extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
_or_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             orw d1,a0@+
    2:       dbra d0,1b
           rts

| extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
_xor_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             eorw d1,a0@+
    2:       dbra d0,1b
           rts

| extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
_and_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             andw d1,a0@+
    2:       dbra d0,1b
           rts

| extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
_eqv_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             eorw d1,a0@
             notw a0@+
    2:       dbra d0,1b
           rts

| extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
_nand_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             andw d1,a0@
             notw a0@+
    2:       dbra d0,1b
           rts

| extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
_nor_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             orw d1,a0@
             notw a0@+
    2:       dbra d0,1b
           rts

| extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
_andc2_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             notw d1
             andw d1,a0@+
    2:       dbra d0,1b
           rts

| extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
_orc2_loop_up: | Input in a0,a1,d0.W, verändert d1
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a1@+,d1
             notw d1
             orw d1,a0@+
    2:       dbra d0,1b
           rts

| extern void not_loop_up (uintD* xptr, uintC count);
_not_loop_up: | Input in a0,d0.W
           movel sp@(4),a0
           movew sp@(8+2),d0
           bras 2f
    1:       notw a0@+
    2:       dbra d0,1b
           rts

| extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
_and_test_loop_up: | Input in a0,a1,d0.W, verändert d1, Output in d0.W=d0.L
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       movew a0@+,d1
             andw a1@+,d1
             bnes 3f
    2:       dbra d0,1b
           clrl d0
           rts
    3:     moveq #1,d0
           rts

| extern boolean test_loop_up (uintD* ptr, uintC count);
_test_loop_up: | Input in a0,d0.W, Output in d0.W=d0.L
           movel sp@(4),a0
           movew sp@(8+2),d0
           bras 2f
    1:       tstw a0@+
             bnes 3f
    2:       dbra d0,1b
           clrl d0
           rts
    3:     moveq #1,d0
           rts

| extern signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
_compare_loop_up: | Input in a0,a1,d0.W, Output in d0.W=d0.L
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           bras 2f
    1:       cmpmw a1@+,a0@+
             bnes 3f
    2:       dbra d0,1b
           clrl d0
           rts
    3:     bcss 4f
           moveq #1,d0
           rts
    4:     moveq #-1,d0
           rts

| extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
_add_loop_down: | Input in a0,a1,a2,d0.W, verändert d1,d2, Output in d0.W
           moveml a2/d2,sp@-
           movel sp@(8+4),a0
           movel sp@(8+8),a1
           movel sp@(8+12),a2
           movew sp@(8+16+2),d0
           andb #0x0e,ccr   | X-Bit löschen
           bras 2f
    1:       movew a0@-,d1
             movew a1@-,d2
             addxw d2,d1
             movew d1,a2@-
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           moveml sp@+,a2/d2
           rts

| extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
_addto_loop_down: | Input in a0,a1,d0.W, Output in d0.W
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           andb #0x0e,ccr   | X-Bit löschen
           bras 2f
    1:       addxw a0@-,a1@-
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           rts

| extern uintD inc_loop_down (uintD* ptr, uintC count);
_inc_loop_down: | Input in a0,d0.W, Output in d0.W
           movel sp@(4),a0
           movew sp@(8+2),d0
           dbra d0,1f          | simuliere gesetzten Carry
                              | d0.W=-1 für Übertrag
           rts
    1:       addqw #1,a0@-
             dbcc d0,1b       | kein Carry -> Schleife abbrechen
           subxw d0,d0       | kein Carry -> d0.W=0, sonst d0.W=-1 für Übertrag
           rts

| extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
_sub_loop_down: | Input in a0,a1,a2,d0.W, verändert d1,d2, Output in d0.W
           moveml a2/d2,sp@-
           movel sp@(8+4),a0
           movel sp@(8+8),a1
           movel sp@(8+12),a2
           movew sp@(8+16+2),d0
           andb #0x0e,ccr   | X-Bit löschen
           bras 2f
    1:       movew a0@-,d1
             movew a1@-,d2
             subxw d2,d1
             movew d1,a2@-
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           moveml sp@+,a2/d2
           rts

| extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
_subx_loop_down: | Input in a0,a1,a2,d0.W,d1.W, verändert d2, Output in d0.W
           moveml a2/d2,sp@-
           movel sp@(8+4),a0
           movel sp@(8+8),a1
           movel sp@(8+12),a2
           movew sp@(8+16+2),d0
           movew sp@(8+20+2),d1
           roxrw #1,d1      | X-Bit initialisieren
           bras 2f
    1:       movew a0@-,d1
             movew a1@-,d2
             subxw d2,d1
             movew d1,a2@-
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           moveml sp@+,a2/d2
           rts

| extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
_subfrom_loop_down: | Input in a0,a1,d0.W, Output in d0.W
           movel sp@(4),a0
           movel sp@(8),a1
           movew sp@(12+2),d0
           andb #0x0e,ccr   | X-Bit löschen
           bras 2f
    1:       subxw a0@-,a1@-
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           rts

| extern uintD dec_loop_down (uintD* ptr, uintC count);
_dec_loop_down: | Input in a0,d0.W, Output in d0.W
           movel sp@(4),a0
           movew sp@(8+2),d0
           dbra d0,1f          | simuliere gesetzten Carry
                              | d0.W=-1 als Übertrag
           rts
    1:       subqw #1,a0@-
             dbcc d0,1b       | kein Carry -> Schleife abbrechen
           subxw d0,d0       | kein Carry -> d0.W=0, sonst d0.W=-1 als Übertrag
           rts

| extern uintD neg_loop_down (uintD* ptr, uintC count);
_neg_loop_down: | Input in a0,d0.W, Output in d0.W
           movel sp@(4),a0
           movew sp@(8+2),d0
           andb #0x0e,ccr   | X-Bit löschen
           bras 2f
    1:       negxw a0@-
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           rts

| extern uintD shift1left_loop_down (uintD* ptr, uintC count);
_shift1left_loop_down: | Input in a0,d0.W, Output in d0.W
           movel sp@(4),a0
           movew sp@(8+2),d0
           andb #0x0e,ccr   | X-Bit löschen
           bras 2f
    1:       roxlw a0@-     | Digit a0@- um 1 Bit links schieben, X-Bit als Buffer
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           rts

| extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
_shiftleft_loop_down: | Input in a0,d0.W,d1.W,d2.W, Output in d0.W
           moveml d2-d3,sp@-
           movel sp@(8+4),a0
           movew sp@(8+8+2),d0
           movew sp@(8+12+2),d1
           movew sp@(8+16+2),d2
           | a0 = ptr, d0.W = count, d1.W = i,
           | d2.W = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku
           bras 2f
    1:       clrl d3
             movew a0@-,d3  | d3.L = d3.W = neues Digit
             lsll d1,d3      | um i Bits nach links schieben
             orw d2,d3       | d3 enthält die letzten 16+i Bits
             movew d3,a0@   | 16 Bits ablegen
             swap d3
             movew d3,d2     | neuen Übertrag bilden
    2:       dbra d0,1b        | Schleife d0.W mal durchlaufen
           movew d2,d0
           moveml sp@+,d2-d3
           rts

| extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
_shiftleftcopy_loop_down: | Input in a0,a1,d0.W,d1.W, Output in d0.W
           moveml d2-d3,sp@-
           movel sp@(8+4),a0
           movel sp@(8+8),a1
           movew sp@(8+12+2),d0
           movew sp@(8+16+2),d1
           clrw d2
           | a0 = sourceptr, a1 = destptr, d0.W = count, d1.W = i,
           | d2.W = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku
           bras 2f
    1:       clrl d3
             movew a0@-,d3  | d3.L = d3.W = neues Digit
             lsll d1,d3      | um i Bits nach links schieben
             orw d2,d3       | d3 enthält die letzten 16+i Bits
             movew d3,a1@-  | 16 Bits ablegen
             swap d3
             movew d3,d2     | neuen Übertrag bilden
    2:       dbra d0,1b        | Schleife d0.W mal durchlaufen
           movew d2,d0
           moveml sp@+,d2-d3
           rts

| extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
_shift1right_loop_up: | Input in a0,d0.W,d1.W, Output in d0.W
           movel sp@(4),a0
           movew sp@(8+2),d0
           movew sp@(12+2),d1
           roxrw #1,d1       | X-Bit löschen oder setzen, je nach d1.W
           bras 2f
    1:       roxrw a0@+     | Digit a0@+ um 1 Bit rechts schieben, X-Bit als Buffer
    2:       dbra d0,1b
           subxw d0,d0       | -1 falls X gesetzt, 0 falls X gelöscht
           rts

| extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
_shiftright_loop_up: | Input in a0,d0.W,d1.W, Output in d0.W
           moveml d2-d3,sp@-
           movel sp@(8+4),a0
           movew sp@(8+8+2),d0
           movew sp@(8+12+2),d1
           | a0 = ptr, d0.W = count, d1.W = i,
           | d2.L = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku
           clrl d2           | Übertrag = 0
           bras 2f
    1:       | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i,
             | d2.L = Schiebe-Übertrag (obere i Bits, restliche 32-i Bits sind 0)
             | d3.L = Schiebe-Akku
             clrl d3
             movew a0@,d3   | neue Daten
             swap d3          | nach Bit 31..16(d3), d3.W = 0
             lsrl d1,d3      | Bits 31-i..16-i(d3) sind die neuen Daten
             orl d3,d2       | Bits 31..16-i(d3) sind die bisherigen Daten
             swap d2          | untere 16 Bit ergeben neuen Übertrag,
             movew d2,a0@+  | obere 16 Bit werden abgespeichert
             clrw d2         | d2.L = neuer Übertrag
    2:       dbra d0,1b        | Schleife d0.W mal durchlaufen
           swap d2
           movew d2,d0
           moveml sp@+,d2-d3
           rts

| extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
_shiftrightsigned_loop_up: | Input in a0,d0.W,d1.W, Output in d0.W
           moveml d2-d3,sp@-
           movel sp@(8+4),a0
           movew sp@(8+8+2),d0
           movew sp@(8+12+2),d1
           | a0 = ptr, d0.W = count, d1.W = i,
           | d2.L = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku
           movew a0@,d2     | erstes Digit
           extl d2           | Vorzeichenbit nach Bit 31..16(d2)
           clrw d2           | Rest von d2.L löschen
           lsrl d1,d2        | d2.W enthält in seinen oberen i Bits das Vorzeichen
           swap d2            | Übertrag mit i Vorzeichenbits initialisiert
           bras 2f
    1:       | a0 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i,
             | d2.L = Schiebe-Übertrag (obere i Bits, restliche 32-i Bits sind 0)
             | d3.L = Schiebe-Akku
             clrl d3
             movew a0@,d3   | neue Daten
             swap d3          | nach Bit 31..16(d3), d3.W = 0
             lsrl d1,d3      | Bits 31-i..16-i(d3) sind die neuen Daten
             orl d3,d2       | Bits 31..16-i(d3) sind die bisherigen Daten
             swap d2          | untere 16 Bit ergeben neuen Übertrag,
             movew d2,a0@+  | obere 16 Bit werden abgespeichert
    2:       clrw d2         | d2.L = neuer Übertrag
             dbra d0,1b        | Schleife d0.W mal durchlaufen
           swap d2
           movew d2,d0
           moveml sp@+,d2-d3
           rts

| extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
_shiftrightcopy_loop_up: | Input in a0,a1,d0.W,d1.W,d2.W, Output in d0.W
           moveml d2-d3,sp@-
           movel sp@(8+4),a0
           movel sp@(8+8),a1
           movew sp@(8+12+2),d0
           movew sp@(8+16+2),d1
           movew sp@(8+20+2),d2
           | a0 = ptr, d0.W = count, d1.W = i,
           | d2.L = Schiebe-Übertrag (i Bits), d3.L = Schiebe-Akku
           swap d2            | carry nach d2.HW
           clrw d2           | Rest von d2.L löschen
           lsrl d1,d2        | d2.W enthält in seinen oberen i Bits das Vorzeichen
           swap d2            | Übertrag mit i Vorzeichenbits initialisiert
           bras 2f
    1:       | a0,a1 = Aufwärtszähler Adresse, d0.W = Herabzähler, d1.W = i,
             | d2.L = Schiebe-Übertrag (obere i Bits, restliche 32-i Bits sind 0)
             | d3.L = Schiebe-Akku
             clrl d3
             movew a0@+,d3  | neue Daten
             swap d3          | nach Bit 31..16(d3), d3.W = 0
             lsrl d1,d3      | Bits 31-i..16-i(d3) sind die neuen Daten
             orl d3,d2       | Bits 31..16-i(d3) sind die bisherigen Daten
             swap d2          | untere 16 Bit ergeben neuen Übertrag,
             movew d2,a1@+  | obere 16 Bit werden abgespeichert
    2:       clrw d2         | d2.L = neuer Übertrag
             dbra d0,1b        | Schleife d0.W mal durchlaufen
           swap d2
           movew d2,d0
           moveml sp@+,d2-d3
           rts

| extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
_mulusmall_loop_down: # Input in d0.W,a0,d1.W,d2.W, Output in d0.W
           moveml d2-d3,sp@-
           movew sp@(8+4+2),d0
           movel sp@(8+8),a0
           movew sp@(8+12+2),d1
           movew sp@(8+16+2),d2
           extl d2           | carry
           bras 2f
    1:       movew a0@-,d3  | nächstes Digit
             mulu d0,d3       | mit digit multiplizieren
             addl d3,d2      | und zum bisherigen Carry addieren. Kein Überlauf!
             movew d2,a0@   | Low-Digit ablegen
             clrw d2
             swap d2          | High-Digit gibt neuen Carry
    2:       dbra d1,1b
           movew d2,d0       | letzter Carry
           moveml sp@+,d2-d3
           rts

| extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
_mulu_loop_down: | Input in d0.W,a0,a1,d1.W
           moveml d2-d3,sp@-
           movew sp@(8+4+2),d0
           movel sp@(8+8),a0
           movel sp@(8+12),a1
           movew sp@(8+16+2),d1
           clrl d2           | carry
           bras 2f
    1:       movew a0@-,d3  | nächstes Digit
             mulu d0,d3       | mit digit multiplizieren
             addl d3,d2      | und zum bisherigen Carry addieren
             movew d2,a1@-  | Low-Digit ablegen
             clrw d2
             swap d2          | High-Digit gibt neuen Carry
    2:       dbra d1,1b
           movew d2,a1@-    | letzten Carry ablegen
           moveml sp@+,d2-d3
           rts

| extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
_muluadd_loop_down: | Input in d0.W,a0,a1,d1.W, benutzt d2,d3,d4, Output in d0.W
#if 1
           moveml d2-d3,sp@-
           movew sp@(8+4+2),d0
           movel sp@(8+8),a0
           movel sp@(8+12),a1
           movew sp@(8+16+2),d1
           subl d2,d2        | carry := 0, X-Bit löschen, d2.HW stets =0
           bras 2f
    1:       movew a0@-,d3  | nächstes Digit
             mulu d0,d3       | mit digit multiplizieren
             addxl d2,d3     | und bisherigen Carry und X-Bit addieren
             addw d3,a1@-   | Low-Digit zum dest-Digit addieren, X als Übertrag
             swap d3
             movew d3,d2     | High-Digit gibt neuen Carry
    2:       dbra d1,1b
           movew d2,d0       | letzten Carry und
           swap d2            | 0.W und
           addxw d2,d0       | letztes X-Bit addieren
           moveml sp@+,d2-d3
           rts
#else
           moveml d2-d4,sp@-
           movew sp@(12+4+2),d0
           movel sp@(12+8),a0
           movel sp@(12+12),a1
           movew sp@(12+16+2),d1
           clrl d2           | carry
           clrl d4           | d4.HW stets =0
           bras 2f
    1:       movew a0@-,d3  | nächstes Digit
             mulu d0,d3       | mit digit multiplizieren
             addl d3,d2      | und zum bisherigen Carry addieren
             movew a1@-,d4  | nächstes dest-Digit
             addl d4,d2      | dazuaddieren
             movew d2,a1@   | Low-Digit ablegen
             clrw d2
             swap d2          | High-Digit gibt neuen Carry
    2:       dbra d1,1b
           movew d2,d0       | letzten Carry als Ergebnis
           moveml sp@+,d2-d4
           rts
#endif

| extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
_mulusub_loop_down: | Input in d0.W,a0,a1,d1.W, benutzt d2,d3,d4, Output in d0.W
           moveml d2-d3,sp@-
           movew sp@(8+4+2),d0
           movel sp@(8+8),a0
           movel sp@(8+12),a1
           movew sp@(8+16+2),d1
           subl d2,d2        | carry := 0, X-Bit löschen, d2.HW stets =0
           bras 2f
    1:       movew a0@-,d3  | nächstes Digit
             mulu d0,d3       | mit digit multiplizieren
             addxl d2,d3     | und bisherigen Carry und X-Bit addieren
             subw d3,a1@-   | Low-Digit vom dest-Digit subtrahieren, X als Übertrag
             swap d3
             movew d3,d2     | High-Digit gibt neuen Carry
    2:       dbra d1,1b
           clrw d0
           addxw d2,d0       | letzter Carry und letztes X-Bit
           moveml sp@+,d2-d3
           rts

| extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
_divu_loop_up: # Input in d0.W,a0,d1.W, Output in d0.W
           movel d2,sp@-
           movew sp@(4+4+2),d0
           movel sp@(4+8),a0
           movew sp@(4+12+2),d1
           clrl d2           | Rest d2.HW := 0
           bras 2f
    1:       movew a0@,d2   | nächst-niedriges Digit mit Rest kombinieren
             divu d0,d2       | und durch digit dividieren
             movew d2,a0@+  | Quotient ablegen, Rest in d2.HW
    2:       dbra d1,1b
           swap d2
           movew d2,d0       | Rest
           movel sp@+,d2
           rts

| extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
_divucopy_loop_up: # Input in d0.W,a0,a1,d1.W, Output in d0.W
           movel d2,sp@-
           movew sp@(4+4+2),d0
           movel sp@(4+8),a0
           movel sp@(4+12),a1
           movew sp@(4+16+2),d1
           clrl d2           | Rest d2.HW := 0
           bras 2f
    1:       movew a0@+,d2  | nächst-niedriges Digit mit Rest kombinieren
             divu d0,d2       | und durch digit dividieren
             movew d2,a1@+  | Quotient ablegen, Rest in d2.HW
    2:       dbra d1,1b
           swap d2
           movew d2,d0       | Rest
           movel sp@+,d2
           rts

#endif

