home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / CLISP / CLISPSRC.TAR / clisp-1995-01-01 / src / ari80386.d < prev    next >
Encoding:
Text File  |  1993-08-26  |  39.1 KB  |  1,005 lines

  1. # Externe Routinen zu ARILEV1.D
  2. # Prozessor: 80386 im native mode
  3. # Assembler-Syntax: GNU oder SUN, Moves von links nach rechts
  4. # Compiler: GNU-C oder SUN-C
  5. # Parameter-▄bergabe: auf dem Stack 4(%esp),8(%esp),...
  6. # Register: %eax,%edx,%ecx dⁿrfen stets verΣndert werden, alles andere retten.
  7. # Ergebnis-▄bergabe: in %eax
  8. # Einstellungen: intCsize=32, intDsize=32.
  9.  
  10. # Bruno Haible 14.8.1992
  11. # Zum Teil abgeschrieben von Bernhard Degels "v-i386.s"
  12.  
  13. #ifdef INCLUDED_FROM_C
  14.  
  15.   #define COPY_LOOPS
  16.   #define FILL_LOOPS
  17.   #define CLEAR_LOOPS
  18.   #define LOG_LOOPS
  19.   #define TEST_LOOPS
  20.   #define ADDSUB_LOOPS
  21.   #define SHIFT_LOOPS
  22.   #define MUL_LOOPS
  23.   #define DIV_LOOPS
  24.  
  25. #else
  26.  
  27.   #ifdef UNDERSCORE
  28.     #ifdef __STDC__
  29.       #define C(entrypoint) _##entrypoint
  30.     #else
  31.       #define C(entrypoint) _/**/entrypoint
  32.     #endif
  33.   #else
  34.     #define C(entrypoint) entrypoint
  35.   #endif
  36.   #if defined(UNDERSCORE) || defined(COHERENT) /* defined(__EMX__) || defined(__GO32__) || defined(linux) || defined(__386BSD__) || defined(__NetBSD__) || defined(COHERENT) || ... */
  37.     # GNU-Assembler oder MWC-Assembler
  38.     #define repz     repe
  39.     #define shcl     %cl,
  40.   #else /* defined(sun) || ... */
  41.     # SUN-Assembler oder Consensys-Assembler
  42.     #define jecxz    orl %ecx,%ecx ; jz
  43.     #define shcl
  44.   #endif
  45.   #if defined(__EMX__)
  46.     # Direction-Flag ist defaultmΣ▀ig gel÷scht
  47.     #define dir0start
  48.     #define dir0end
  49.     #define dir1start  std
  50.     #define dir1end    cld
  51.   #elif 1
  52.     # Wir gehen auf Nummer sicher.
  53.     #define dir0start  cld
  54.     #define dir0end
  55.     #define dir1start  std
  56.     #define dir1end    cld
  57.   #else
  58.     # Direction-Flag darf nach Belieben modifiziert werden
  59.     #define dir0start  cld
  60.     #define dir0end
  61.     #define dir1start  std
  62.     #define dir1end
  63.   #endif
  64.  
  65.         .text
  66.         .align 2
  67.  
  68.         .globl C(copy_loop_up)
  69.         .globl C(copy_loop_down)
  70.         .globl C(fill_loop_up)
  71.         .globl C(fill_loop_down)
  72.         .globl C(clear_loop_up)
  73.         .globl C(clear_loop_down)
  74.         .globl C(or_loop_up)
  75.         .globl C(xor_loop_up)
  76.         .globl C(and_loop_up)
  77.         .globl C(eqv_loop_up)
  78.         .globl C(nand_loop_up)
  79.         .globl C(nor_loop_up)
  80.         .globl C(andc2_loop_up)
  81.         .globl C(orc2_loop_up)
  82.         .globl C(not_loop_up)
  83.         .globl C(and_test_loop_up)
  84.         .globl C(test_loop_up)
  85.         .globl C(compare_loop_up)
  86.         .globl C(add_loop_down)
  87.         .globl C(addto_loop_down)
  88.         .globl C(inc_loop_down)
  89.         .globl C(sub_loop_down)
  90.         .globl C(subx_loop_down)
  91.         .globl C(subfrom_loop_down)
  92.         .globl C(dec_loop_down)
  93.         .globl C(neg_loop_down)
  94.         .globl C(shift1left_loop_down)
  95.         .globl C(shiftleft_loop_down)
  96.         .globl C(shiftleftcopy_loop_down)
  97.         .globl C(shift1right_loop_up)
  98.         .globl C(shiftright_loop_up)
  99.         .globl C(shiftrightsigned_loop_up)
  100.         .globl C(shiftrightcopy_loop_up)
  101.         .globl C(mulusmall_loop_down)
  102.         .globl C(mulu_loop_down)
  103.         .globl C(muluadd_loop_down)
  104.         .globl C(mulusub_loop_down)
  105.         .globl C(divu_loop_up)
  106.         .globl C(divucopy_loop_up)
  107.  
  108. #ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */
  109.  
  110. # extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
  111. # 2^32*hi+lo := arg1*arg2.
  112.         .globl C(mulu32_)
  113. C(mulu32_:)
  114.         movl    4(%esp),%eax    # arg1
  115.         mull    8(%esp)         # %edx|%eax := arg1 * arg2
  116.         movl    %edx,C(mulu32_high) # %edx = hi abspeichern
  117.         ret                     # %eax = lo als Ergebnis
  118.  
  119. #endif
  120.  
  121. #ifndef __GNUC__ /* mit GNU-C machen wir divu_6432_3232() als Macro, der inline multipliziert */
  122.  
  123. # extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
  124. # x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, da▀ 0 <= x < 2^32*y .
  125.         .globl C(divu_6432_3232_)
  126. C(divu_6432_3232_:)
  127.         movl    4(%esp),%edx
  128.         movl    8(%esp),%eax
  129.         divl    12(%esp)       # x = %edx|%eax durch dividieren
  130.         movl    %edx,C(divu_32_rest) # Rest %edx = r abspeichern
  131.         ret                    # Quotient %eax = q als Ergebnis
  132.  
  133. #endif
  134.  
  135. # extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
  136. C(copy_loop_up:)
  137.         movl    %edi,%edx       # %edi retten
  138.         movl    %esi,%eax       # %esi retten
  139.         movl    4(%esp),%esi    # %esi = sourceptr
  140.         movl    8(%esp),%edi    # %edi = destptr
  141.         movl    12(%esp),%ecx   # %ecx = count
  142.         dir0start
  143.         rep
  144.           movsl                 # %ecx mal aufwΣrts (%edi) := (%esi)
  145.         dir0end
  146.         movl    %eax,%esi       # %esi zurⁿck
  147.         movl    %edi,%eax       # %edi als Ergebnis
  148.         movl    %edx,%edi       # %edi zurⁿck
  149.         ret
  150.  
  151. # extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
  152. C(copy_loop_down:)
  153.         movl    %edi,%edx       # %edi retten
  154.         movl    %esi,%eax       # %esi retten
  155.         movl    4(%esp),%esi    # %esi = sourceptr
  156.         movl    8(%esp),%edi    # %edi = destptr
  157.         movl    12(%esp),%ecx   # %ecx = count
  158.         leal    -4(%esi),%esi
  159.         leal    -4(%edi),%edi
  160.         dir1start
  161.         rep
  162.           movsl                 # %ecx mal abwΣrts (%edi) := (%esi)
  163.         dir1end
  164.         movl    %eax,%esi       # %esi zurⁿck
  165.         leal    4(%edi),%eax    # %edi als Ergebnis
  166.         movl    %edx,%edi       # %edi zurⁿck
  167.         ret
  168.  
  169. # extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
  170. C(fill_loop_up:)
  171.         movl    %edi,%edx       # %edi retten
  172.         movl    4(%esp),%edi    # %edi = destptr
  173.         movl    8(%esp),%ecx    # %ecx = count
  174.         movl    12(%esp),%eax   # %eax = filler
  175.         dir0start
  176.         rep
  177.           stosl                 # %ecx mal aufwΣrts (%edi) := %eax
  178.         dir0end
  179.         movl    %edi,%eax       # %edi als Ergebnis
  180.         movl    %edx,%edi       # %edi zurⁿck
  181.         ret
  182.  
  183. # extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
  184. C(fill_loop_down:)
  185.         movl    %edi,%edx       # %edi retten
  186.         movl    4(%esp),%edi    # %edi = destptr
  187.         movl    8(%esp),%ecx    # %ecx = count
  188.         movl    12(%esp),%eax   # %eax = filler
  189.         leal    -4(%edi),%edi
  190.         dir1start
  191.         rep
  192.           stosl                 # %ecx mal abwΣrts (%edi) := %eax
  193.         dir1end
  194.         leal    4(%edi),%eax    # %edi als Ergebnis
  195.         movl    %edx,%edi       # %edi zurⁿck
  196.         ret
  197.  
  198. # extern uintD* clear_loop_up (uintD* destptr, uintC count);
  199. C(clear_loop_up:)
  200.         movl    %edi,%edx       # %edi retten
  201.         movl    4(%esp),%edi    # %edi = destptr
  202.         movl    8(%esp),%ecx    # %ecx = count
  203.         xorl    %eax,%eax       # %eax = 0
  204.         dir0start
  205.         rep
  206.           stosl                 # %ecx mal aufwΣrts (%edi) := %eax
  207.         dir0end
  208.         movl    %edi,%eax       # %edi als Ergebnis
  209.         movl    %edx,%edi       # %edi zurⁿck
  210.         ret
  211.  
  212. # extern uintD* clear_loop_down (uintD* destptr, uintC count);
  213. C(clear_loop_down:)
  214.         movl    %edi,%edx       # %edi retten
  215.         movl    4(%esp),%edi    # %edi = destptr
  216.         movl    8(%esp),%ecx    # %ecx = count
  217.         leal    -4(%edi),%edi
  218.         xorl    %eax,%eax       # %eax = 0
  219.         dir1start
  220.         rep
  221.           stosl                 # %ecx mal abwΣrts (%edi) := %eax
  222.         dir1end
  223.         leal    4(%edi),%eax    # %edi als Ergebnis
  224.         movl    %edx,%edi       # %edi zurⁿck
  225.         ret
  226.  
  227. # extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
  228. C(or_loop_up:)
  229.         pushl   %esi            # %esi retten
  230.         movl    8(%esp),%edx    # %edx = xptr
  231.         movl    12(%esp),%esi   # %esi = yptr
  232.         movl    16(%esp),%ecx   # %ecx = count
  233.         subl    %edx,%esi
  234.         jecxz   olu2            # %ecx = 0 ?
  235. olu1:     movl    (%edx,%esi),%eax # *yptr
  236.           orl     %eax,(%edx)      # *xptr |= ...
  237.           leal    4(%edx),%edx     # xptr++, yptr++
  238.           decl    %ecx
  239.           jnz     olu1
  240. olu2:   popl    %esi            # %esi zurⁿck
  241.         ret
  242.  
  243. # extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
  244. C(xor_loop_up:)
  245.         pushl   %esi            # %esi retten
  246.         movl    8(%esp),%edx    # %edx = xptr
  247.         movl    12(%esp),%esi   # %esi = yptr
  248.         movl    16(%esp),%ecx   # %ecx = count
  249.         subl    %edx,%esi
  250.         jecxz   xlu2            # %ecx = 0 ?
  251. xlu1:     movl    (%edx,%esi),%eax # *yptr
  252.           xorl    %eax,(%edx)      # *xptr ^= ...
  253.           leal    4(%edx),%edx     # xptr++, yptr++
  254.           decl    %ecx
  255.           jnz     xlu1
  256. xlu2:   popl    %esi            # %esi zurⁿck
  257.         ret
  258.  
  259. # extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
  260. C(and_loop_up:)
  261.         pushl   %esi            # %esi retten
  262.         movl    8(%esp),%edx    # %edx = xptr
  263.         movl    12(%esp),%esi   # %esi = yptr
  264.         movl    16(%esp),%ecx   # %ecx = count
  265.         subl    %edx,%esi
  266.         jecxz   alu2            # %ecx = 0 ?
  267. alu1:     movl    (%edx,%esi),%eax # *yptr
  268.           andl    %eax,(%edx)      # *xptr &= ...
  269.           leal    4(%edx),%edx     # xptr++, yptr++
  270.           decl    %ecx
  271.           jnz     alu1
  272. alu2:   popl    %esi            # %esi zurⁿck
  273.         ret
  274.  
  275. # extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
  276. C(eqv_loop_up:)
  277.         pushl   %esi            # %esi retten
  278.         movl    8(%esp),%edx    # %edx = xptr
  279.         movl    12(%esp),%esi   # %esi = yptr
  280.         movl    16(%esp),%ecx   # %ecx = count
  281.         subl    %edx,%esi
  282.         jecxz   elu2            # %ecx = 0 ?
  283. elu1:     movl    (%edx),%eax      # *xptr
  284.           xorl    (%edx,%esi),%eax # ^ *yptr
  285.           notl    %eax             # ~(...)
  286.           movl    %eax,(%edx)      # =: *xptr
  287.           leal    4(%edx),%edx     # xptr++, yptr++
  288.           decl    %ecx
  289.           jnz     elu1
  290. elu2:   popl    %esi            # %esi zurⁿck
  291.         ret
  292.  
  293. # extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
  294. C(nand_loop_up:)
  295.         pushl   %esi            # %esi retten
  296.         movl    8(%esp),%edx    # %edx = xptr
  297.         movl    12(%esp),%esi   # %esi = yptr
  298.         movl    16(%esp),%ecx   # %ecx = count
  299.         subl    %edx,%esi
  300.         jecxz   nalu2           # %ecx = 0 ?
  301. nalu1:    movl    (%edx),%eax      # *xptr
  302.           andl    (%edx,%esi),%eax # & *yptr
  303.           notl    %eax             # ~(...)
  304.           movl    %eax,(%edx)      # =: *xptr
  305.           leal    4(%edx),%edx     # xptr++, yptr++
  306.           decl    %ecx
  307.           jnz     nalu1
  308. nalu2:  popl    %esi            # %esi zurⁿck
  309.         ret
  310.  
  311. # extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
  312. C(nor_loop_up:)
  313.         pushl   %esi            # %esi retten
  314.         movl    8(%esp),%edx    # %edx = xptr
  315.         movl    12(%esp),%esi   # %esi = yptr
  316.         movl    16(%esp),%ecx   # %ecx = count
  317.         subl    %edx,%esi
  318.         jecxz   nolu2           # %ecx = 0 ?
  319. nolu1:    movl    (%edx),%eax      # *xptr
  320.           orl     (%edx,%esi),%eax # | *yptr
  321.           notl    %eax             # ~(...)
  322.           movl    %eax,(%edx)      # =: *xptr
  323.           leal    4(%edx),%edx     # xptr++, yptr++
  324.           decl    %ecx
  325.           jnz     nolu1
  326. nolu2:  popl    %esi            # %esi zurⁿck
  327.         ret
  328.  
  329. # extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
  330. C(andc2_loop_up:)
  331.         pushl   %esi            # %esi retten
  332.         movl    8(%esp),%edx    # %edx = xptr
  333.         movl    12(%esp),%esi   # %esi = yptr
  334.         movl    16(%esp),%ecx   # %ecx = count
  335.         subl    %edx,%esi
  336.         jecxz   aclu2           # %ecx = 0 ?
  337. aclu1:    movl    (%edx,%esi),%eax # *yptr
  338.           notl    %eax             # ~ *yptr
  339.           andl    %eax,(%edx)      # *xptr &= ...
  340.           leal    4(%edx),%edx     # xptr++, yptr++
  341.           decl    %ecx
  342.           jnz     aclu1
  343. aclu2:  popl    %esi            # %esi zurⁿck
  344.         ret
  345.  
  346. # extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
  347. C(orc2_loop_up:)
  348.         pushl   %esi            # %esi retten
  349.         movl    8(%esp),%edx    # %edx = xptr
  350.         movl    12(%esp),%esi   # %esi = yptr
  351.         movl    16(%esp),%ecx   # %ecx = count
  352.         subl    %edx,%esi
  353.         jecxz   oclu2           # %ecx = 0 ?
  354. oclu1:    movl    (%edx,%esi),%eax # *yptr
  355.           notl    %eax             # ~ *yptr
  356.           orl     %eax,(%edx)      # *xptr |= ...
  357.           leal    4(%edx),%edx     # xptr++, yptr++
  358.           decl    %ecx
  359.           jnz     oclu1
  360. oclu2:  popl    %esi            # %esi zurⁿck
  361.         ret
  362.  
  363. # extern void not_loop_up (uintD* xptr, uintC count);
  364. C(not_loop_up:)
  365.         movl    4(%esp),%edx    # %edx = xptr
  366.         movl    8(%esp),%ecx    # %ecx = count
  367.         jecxz   nlu2            # %ecx = 0 ?
  368. nlu1:     notl    (%edx)           # ~= *xptr
  369.           leal    4(%edx),%edx     # xptr++, yptr++
  370.           decl    %ecx
  371.           jnz     nlu1
  372. nlu2:   ret
  373.  
  374. # extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
  375. C(and_test_loop_up:)
  376.         pushl   %esi            # %esi retten
  377.         movl    8(%esp),%edx    # %edx = xptr
  378.         movl    12(%esp),%esi   # %esi = yptr
  379.         movl    16(%esp),%ecx   # %ecx = count
  380.         jecxz   atlu2           # %ecx = 0 ?
  381.         subl    %edx,%esi
  382. atlu1:    movl    (%edx,%esi),%eax # *yptr
  383.           andl    (%edx),%eax      # *xptr & ...
  384.           jnz     atlu3
  385.           leal    4(%edx),%edx     # xptr++, yptr++
  386.           decl    %ecx
  387.           jnz     atlu1
  388. atlu2:  xorl    %eax,%eax       # Ergebnis 0
  389. atlu3:  popl    %esi            # %esi zurⁿck
  390.         ret
  391.  
  392. # extern boolean test_loop_up (uintD* ptr, uintC count);
  393. C(test_loop_up:)
  394.         movl    %edi,%edx       # %edi retten
  395.         movl    4(%esp),%edi    # %edi = ptr
  396.         movl    8(%esp),%ecx    # %ecx = count
  397.         xorl    %eax,%eax       # %eax = 0
  398.         dir0start
  399.         repz                    # Falls %ecx > 0:
  400.           scasl                 # %ecx mal aufwΣrts (%edi) testen
  401.                                 # und weiterschleifen, falls Z, d.h. (%edi)=0.
  402.         dir0end
  403.         # Noch ist %eax = 0.
  404.         jz      tlu1            # alles =0 -> Ergebnis 0
  405.         incl    %eax            # Ergebnis 1
  406. tlu1:   movl    %edx,%edi       # %edi zurⁿck
  407.         ret
  408.  
  409. # extern signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
  410. C(compare_loop_up:)
  411.         movl    %esi,%edx       # %esi retten
  412.         movl    %edi,%eax       # %edi retten
  413.         movl    4(%esp),%esi    # %esi = xptr
  414.         movl    8(%esp),%edi    # %edi = yptr
  415.         movl    12(%esp),%ecx   # %ecx = count
  416.         dir0start
  417.         repz                    # Falls %ecx > 0:
  418.           cmpsl                 # %ecx mal aufwΣrts (%edi) und (%esi) vergleichen
  419.                                 # und weiterschleifen, falls Z, d.h. (%edi)=(%esi).
  420.         dir0end
  421.         # Flags -> Ergebnis:
  422.         # Z,NC -> bis zum Schlu▀ (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0
  423.         # NZ,C -> schlie▀lich (%esi)-(%edi) < 0 -> x<y -> Ergebnis -1
  424.         # NZ,NC -> schlie▀lich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1
  425.         movl    %eax,%edi       # %edi zurⁿck
  426.         movl    %edx,%esi       # %esi zurⁿck
  427.         jbe     cmlu1           # "be" = Z oder C
  428.         movl    $1,%eax         # Ergebnis +1
  429.         ret
  430. cmlu1:  sbbl    %eax,%eax       # Ergebnis -1 (falls C) oder 0 (falls NC)
  431.         ret
  432.  
  433. # extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
  434. C(add_loop_down:)
  435.         pushl   %esi            # %esi retten
  436.         pushl   %edi            # %edi retten
  437.         movl    12(%esp),%edx   # %edx = sourceptr1
  438.         movl    16(%esp),%esi   # %esi = sourceptr2
  439.         movl    20(%esp),%edi   # %edi = destptr
  440.         movl    24(%esp),%ecx   # %ecx = count
  441.         subl    %edi,%edx
  442.         subl    %edi,%esi
  443.         orl     %ecx,%ecx       # %ecx = 0 ?, Carry l÷schen
  444.         jz      ald2
  445. ald1:     leal    -4(%edi),%edi   # sourceptr1--, sourceptr2--, destptr--
  446.           movl    (%edx,%edi),%eax # *sourceptr1
  447.           adcl    (%esi,%edi),%eax # + *sourceptr2 + carry
  448.           movl    %eax,(%edi)     # =: *destptr, neuen Carry behalten
  449.           decl    %ecx
  450.           jnz     ald1
  451. ald2:   sbbl    %eax,%eax      # Ergebnis := - Carry
  452.         popl    %edi           # %edi zurⁿck
  453.         popl    %esi           # %esi zurⁿck
  454.         ret
  455.  
  456. # extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
  457. C(addto_loop_down:)
  458.         pushl   %edi            # %edi retten
  459.         movl    8(%esp),%edx    # %edx = sourceptr
  460.         movl    12(%esp),%edi   # %edi = destptr
  461.         movl    16(%esp),%ecx   # %ecx = count
  462.         subl    %edi,%edx
  463.         orl     %ecx,%ecx       # %ecx = 0 ?, Carry l÷schen
  464.         jz      atld2
  465. atld1:    leal    -4(%edi),%edi   # sourceptr--, destptr--
  466.           movl    (%edx,%edi),%eax # *sourceptr
  467.           adcl    %eax,(%edi)     # + *destptr + carry =: *destptr, neuer Carry
  468.           decl    %ecx
  469.           jnz     atld1
  470. atld2:  sbbl    %eax,%eax       # Ergebnis := - Carry
  471.         popl    %edi            # %edi zurⁿck
  472.         ret
  473.  
  474. # extern uintD inc_loop_down (uintD* ptr, uintC count);
  475. C(inc_loop_down:)
  476.         movl    4(%esp),%edx    # %edx = ptr
  477.         movl    8(%esp),%ecx    # %ecx = count
  478.         jecxz   ild2            # %ecx = 0 ?
  479. ild1:     leal    -4(%edx),%edx
  480.           addl    $1,(%edx)       # (*ptr)++
  481.           jnc     ild3            # kein Carry -> fertig
  482.           decl    %ecx
  483.           jnz     ild1
  484. ild2:   movl    $1,%eax         # Ergebnis := 1
  485.         ret
  486. ild3:   xorl    %eax,%eax       # Ergebnis := 0
  487.         ret
  488.  
  489. # extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
  490. C(sub_loop_down:)
  491.         pushl   %esi            # %esi retten
  492.         pushl   %edi            # %edi retten
  493.         movl    12(%esp),%edx   # %edx = sourceptr1
  494.         movl    16(%esp),%esi   # %esi = sourceptr2
  495.         movl    20(%esp),%edi   # %edi = destptr
  496.         movl    24(%esp),%ecx   # %ecx = count
  497.         subl    %edi,%edx
  498.         subl    %edi,%esi
  499.         orl     %ecx,%ecx       # %ecx = 0 ?, Carry l÷schen
  500.         jz      sld2
  501. sld1:     leal    -4(%edi),%edi   # sourceptr1--, sourceptr2--, destptr--
  502.           movl    (%edx,%edi),%eax # *sourceptr1
  503.           sbbl    (%esi,%edi),%eax # - *sourceptr2 - carry
  504.           movl    %eax,(%edi)     # =: *destptr, neuen Carry behalten
  505.           decl    %ecx
  506.           jnz     sld1
  507. sld2:   sbbl    %eax,%eax      # Ergebnis := - Carry
  508.         popl    %edi           # %edi zurⁿck
  509.         popl    %esi           # %esi zurⁿck
  510.         ret
  511.  
  512. # extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
  513. C(subx_loop_down:)
  514.         pushl   %esi            # %esi retten
  515.         pushl   %edi            # %edi retten
  516.         movl    12(%esp),%edx   # %edx = sourceptr1
  517.         movl    16(%esp),%esi   # %esi = sourceptr2
  518.         movl    20(%esp),%edi   # %edi = destptr
  519.         movl    24(%esp),%ecx   # %ecx = count
  520.         jecxz   sxld2           # %ecx = 0 ?
  521.         subl    %edi,%edx
  522.         subl    %edi,%esi
  523.         movl    28(%esp),%eax   # carry, 0 oder -1
  524.         addl    %eax,%eax       # Bit 31 davon in den Carry
  525. sxld1:    leal    -4(%edi),%edi   # sourceptr1--, sourceptr2--, destptr--
  526.           movl    (%edx,%edi),%eax # *sourceptr1
  527.           sbbl    (%esi,%edi),%eax # - *sourceptr2 - carry
  528.           movl    %eax,(%edi)     # =: *destptr, neuen Carry behalten
  529.           decl    %ecx
  530.           jnz     sxld1
  531.         sbbl    %eax,%eax      # Ergebnis := - Carry
  532.         popl    %edi           # %edi zurⁿck
  533.         popl    %esi           # %esi zurⁿck
  534.         ret
  535. sxld2:  movl    28(%esp),%eax  # Ergebnis := carry
  536.         popl    %edi           # %edi zurⁿck
  537.         popl    %esi           # %esi zurⁿck
  538.         ret
  539.  
  540. # extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
  541. C(subfrom_loop_down:)
  542.         pushl   %edi            # %edi retten
  543.         movl    8(%esp),%edx    # %edx = sourceptr
  544.         movl    12(%esp),%edi   # %edi = destptr
  545.         movl    16(%esp),%ecx   # %ecx = count
  546.         subl    %edi,%edx
  547.         orl     %ecx,%ecx       # %ecx = 0 ?, Carry l÷schen
  548.         jz      sfld2
  549. sfld1:    leal    -4(%edi),%edi   # sourceptr--, destptr--
  550.           movl    (%edx,%edi),%eax # *sourceptr
  551.           sbbl    %eax,(%edi)     # *destptr - *sourceptr - carry =: *destptr, neuer Carry
  552.           decl    %ecx
  553.           jnz     sfld1
  554. sfld2:  sbbl    %eax,%eax       # Ergebnis := - Carry
  555.         popl    %edi            # %edi zurⁿck
  556.         ret
  557.  
  558. # extern uintD dec_loop_down (uintD* ptr, uintC count);
  559. C(dec_loop_down:)
  560.         movl    4(%esp),%edx    # %edx = ptr
  561.         movl    8(%esp),%ecx    # %ecx = count
  562.         jecxz   dld2            # %ecx = 0 ?
  563. dld1:     leal    -4(%edx),%edx
  564.           subl    $1,(%edx)       # (*ptr)--
  565.           jnc     dld3            # kein Carry -> fertig
  566.           decl    %ecx
  567.           jnz     dld1
  568. dld2:   movl    $-1,%eax        # Ergebnis := -1
  569.         ret
  570. dld3:   xorl    %eax,%eax       # Ergebnis := 0
  571.         ret
  572.  
  573. # extern uintD neg_loop_down (uintD* ptr, uintC count);
  574. C(neg_loop_down:)
  575.         movl    4(%esp),%edx    # %edx = ptr
  576.         movl    8(%esp),%ecx    # %ecx = count
  577.         # erstes Digit /=0 suchen:
  578.         jecxz   nld2            # %ecx = 0 ?
  579. nld1:     leal    -4(%edx),%edx
  580.           negl    (%edx)
  581.           jnz     nld3
  582.           decl    %ecx
  583.           jnz     nld1
  584. nld2:   xorl    %eax,%eax       # Ergebnis := 0
  585.         ret
  586. nld3:   # erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
  587.         # alle anderen Digits invertieren:
  588.         decl    %ecx
  589.         jz      nld5
  590. nld4:     leal    -4(%edx),%edx
  591.           notl    (%edx)
  592.           decl    %ecx
  593.           jnz     nld4
  594. nld5:   movl    $-1,%eax        # Ergebnis := -1
  595.         ret
  596.  
  597. # extern uintD shift1left_loop_down (uintD* ptr, uintC count);
  598. C(shift1left_loop_down:)
  599.         movl    4(%esp),%edx    # %edx = ptr
  600.         movl    8(%esp),%ecx    # %ecx = count
  601.         orl     %ecx,%ecx       # %ecx = 0 ?, Carry l÷schen
  602.         jz      s1lld2
  603. s1lld1:   leal    -4(%edx),%edx   # ptr--
  604.           rcll    $1,(%edx)       # *ptr und Carry um 1 Bit links rotieren
  605.           decl    %ecx
  606.           jnz     s1lld1
  607. s1lld2: sbbl    %eax,%eax       # Ergebnis := - Carry
  608.         ret
  609.  
  610. # extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
  611. C(shiftleft_loop_down:)
  612.         pushl   %edi            # %edi retten
  613.         pushl   %ebx            # %ebx retten
  614.         movl    12(%esp),%edi   # %edi = ptr
  615.         movl    16(%esp),%edx   # %edx = count
  616.         movb    20(%esp),%cl    # %cl = i
  617.         orl     %edx,%edx       # count = 0 ?
  618.         jz      slld4
  619.         # erstes Digit shiften:
  620.         leal    -4(%edi),%edi
  621.         movl    (%edi),%eax     # Digit in %eax halten
  622.         movl    %eax,%ebx       # und in %ebx rechnen:
  623.         shll    %cl,%ebx        # um i Bits links shiften
  624.         orl     24(%esp),%ebx   # und die unteren i Bits eintragen
  625.         movl    %ebx,(%edi)     # und wieder ablegen
  626.         # Letztes Digit in %eax.
  627.         decl    %edx
  628.         jz      slld2
  629. slld1:    # weiteres Digit shiften:
  630.           leal    -4(%edi),%edi
  631.           movl    (%edi),%ebx
  632.           shldl   shcl %eax,(%edi) # (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften
  633.           # Letztes Digit in %ebx.
  634.           decl    %edx
  635.           jz      slld3
  636.           # weiteres Digit shiften:
  637.           leal    -4(%edi),%edi
  638.           movl    (%edi),%eax
  639.           shldl   shcl %ebx,(%edi) # (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften
  640.           # Letztes Digit in %eax.
  641.           decl    %edx
  642.           jnz     slld1
  643. slld2:  movl    %eax,%ebx
  644. slld3:  xorl    %eax,%eax       # %eax := 0
  645.         shldl   shcl %ebx,%eax  # %eax := h÷chste %cl=i Bits von %ebx
  646.         popl    %ebx            # %ebx zurⁿck
  647.         popl    %edi            # %edi zurⁿck
  648.         ret
  649. slld4:  movl    24(%esp),%eax   # %eax := carry
  650.         popl    %ebx            # %ebx zurⁿck
  651.         popl    %edi            # %edi zurⁿck
  652.         ret
  653.  
  654. # extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
  655. C(shiftleftcopy_loop_down:)
  656.         pushl   %esi            # %esi retten
  657.         pushl   %edi            # %edi retten
  658.         pushl   %ebx            # %ebx retten
  659.         movl    16(%esp),%esi   # %esi = sourceptr
  660.         movl    20(%esp),%edi   # %edi = destptr
  661.         movl    24(%esp),%edx   # count
  662.         movb    28(%esp),%cl    # i
  663.         orl     %edx,%edx       # count = 0 ?
  664.         jz      slcld4
  665.         subl    %edi,%esi
  666.         # erstes Digit shiften:
  667.         leal    -4(%edi),%edi   # sourceptr--, destptr--
  668.         movl    (%edi,%esi),%ebx # *sourceptr in %ebx halten
  669.         movl    %ebx,%eax       # und in %eax rechnen:
  670.         shll    %cl,%eax        # um i Bits links shiften, rechts Nullen rein
  671.         movl    %eax,(%edi)     # und als *destptr ablegen
  672.         # Letztes Digit in %ebx.
  673.         negb    %cl             # 32-i
  674.         decl    %edx
  675.         jz      slcld2
  676. slcld1:   # weiteres Digit shiften:
  677.           leal    -4(%edi),%edi   # sourceptr--, destptr--
  678.           movl    (%edi,%esi),%eax # nΣchstes Digit nach %eax
  679.           shrdl   shcl %eax,%ebx  # %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften
  680.           movl    %ebx,(%edi)     # %ebx als *destptr ablegen
  681.           # Letztes Digit in %eax.
  682.           decl    %edx
  683.           jz      slcld3
  684.           # weiteres Digit shiften:
  685.           leal    -4(%edi),%edi   # sourceptr--, destptr--
  686.           movl    (%edi,%esi),%ebx # nΣchstes Digit nach %ebx
  687.           shrdl   shcl %ebx,%eax  # %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften
  688.           movl    %eax,(%edi)     # %eax als *destptr ablegen
  689.           # Letztes Digit in %ebx.
  690.           decl    %edx
  691.           jnz     slcld1
  692. slcld2: movl    %ebx,%eax
  693. slcld3: shrl    %cl,%eax        # %eax um 32-i Bits nach rechts shiften
  694.         popl    %ebx            # %ebx zurⁿck
  695.         popl    %edi            # %edi zurⁿck
  696.         popl    %esi            # %esi zurⁿck
  697.         ret
  698. slcld4: xorl    %eax,%eax       # %eax := 0
  699.         popl    %ebx            # %ebx zurⁿck
  700.         popl    %edi            # %edi zurⁿck
  701.         popl    %esi            # %esi zurⁿck
  702.         ret
  703.  
  704. # extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
  705. C(shift1right_loop_up:)
  706.         movl    4(%esp),%edx    # %edx = ptr
  707.         movl    8(%esp),%ecx    # %ecx = count
  708.         movl    12(%esp),%eax   # %eax = carry (0 oder -1)
  709.         jecxz   s1rld3          # %ecx = 0 ?
  710.         addl    %eax,%eax       # Carry := Bit 31 von carry
  711. s1rld1:   rcrl    $1,(%edx)       # *ptr und Carry um 1 Bit rechts rotieren
  712.           leal    4(%edx),%edx    # ptr++
  713.           decl    %ecx
  714.           jnz     s1rld1
  715. s1rld2: sbbl    %eax,%eax       # Ergebnis := - Carry
  716. s1rld3: ret
  717.  
  718. # extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
  719. C(shiftright_loop_up:)
  720.         pushl   %edi            # %edi retten
  721.         pushl   %ebx            # %ebx retten
  722.         movl    12(%esp),%edi   # %edi = ptr
  723.         movl    16(%esp),%edx   # %edx = count
  724.         movb    20(%esp),%cl    # %cl = i
  725.         orl     %edx,%edx       # count = 0 ?
  726.         jz      srlu4
  727.         # erstes Digit shiften:
  728.         movl    (%edi),%eax     # Digit in %eax halten
  729.         movl    %eax,%ebx       # und in %ebx rechnen:
  730.         shrl    %cl,%ebx        # um i Bits rechts shiften
  731.         movl    %ebx,(%edi)     # und wieder ablegen
  732.         # Letztes Digit in %eax.
  733.         decl    %edx
  734.         jz      srlu2
  735. srlu1:    # weiteres Digit shiften:
  736.           leal    4(%edi),%edi
  737.           movl    (%edi),%ebx
  738.           shrdl   shcl %eax,(%edi) # (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
  739.           # Letztes Digit in %ebx.
  740.           decl    %edx
  741.           jz      srlu3
  742.           # weiteres Digit shiften:
  743.           leal    4(%edi),%edi
  744.           movl    (%edi),%eax
  745.           shrdl   shcl %ebx,(%edi) # (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
  746.           # Letztes Digit in %eax.
  747.           decl    %edx
  748.           jnz     srlu1
  749. srlu2:  movl    %eax,%ebx
  750. srlu3:  xorl    %eax,%eax       # %eax := 0
  751.         shrdl   shcl %ebx,%eax  # %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
  752.         popl    %ebx            # %ebx zurⁿck
  753.         popl    %edi            # %edi zurⁿck
  754.         ret
  755. srlu4:  xorl    %eax,%eax       # %eax := 0
  756.         popl    %ebx            # %ebx zurⁿck
  757.         popl    %edi            # %edi zurⁿck
  758.         ret
  759.  
  760. # extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
  761. C(shiftrightsigned_loop_up:)
  762.         pushl   %edi            # %edi retten
  763.         pushl   %ebx            # %ebx retten
  764.         movl    12(%esp),%edi   # %edi = ptr
  765.         movl    16(%esp),%edx   # %edx = count
  766.         movb    20(%esp),%cl    # %cl = i
  767.         # erstes Digit shiften:
  768.         movl    (%edi),%eax     # Digit in %eax halten
  769.         movl    %eax,%ebx       # und in %ebx rechnen:
  770.         sarl    %cl,%ebx        # um i Bits rechts shiften, Vorzeichen vervielfachen
  771.         movl    %ebx,(%edi)     # und wieder ablegen
  772.         # Letztes Digit in %eax.
  773.         decl    %edx
  774.         jz      srslu2
  775. srslu1:   # weiteres Digit shiften:
  776.           leal    4(%edi),%edi
  777.           movl    (%edi),%ebx
  778.           shrdl   shcl %eax,(%edi) # (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
  779.           # Letztes Digit in %ebx.
  780.           decl    %edx
  781.           jz      srslu3
  782.           # weiteres Digit shiften:
  783.           leal    4(%edi),%edi
  784.           movl    (%edi),%eax
  785.           shrdl   shcl %ebx,(%edi) # (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
  786.           # Letztes Digit in %eax.
  787.           decl    %edx
  788.           jnz     srslu1
  789. srslu2: movl    %eax,%ebx
  790. srslu3: xorl    %eax,%eax       # %eax := 0
  791.         shrdl   shcl %ebx,%eax  # %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
  792.         popl    %ebx            # %ebx zurⁿck
  793.         popl    %edi            # %edi zurⁿck
  794.         ret
  795.  
  796. # extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
  797. C(shiftrightcopy_loop_up:)
  798.         pushl   %esi            # %esi retten
  799.         pushl   %edi            # %edi retten
  800.         pushl   %ebx            # %ebx retten
  801.         movl    16(%esp),%esi   # %esi = sourceptr
  802.         movl    20(%esp),%edi   # %edi = destptr
  803.         movl    24(%esp),%edx   # count
  804.         movb    28(%esp),%cl    # i
  805.         negb    %cl             # 32-i
  806.         movl    32(%esp),%eax   # %eax = carry
  807.         orl     %edx,%edx       # count = 0 ?
  808.         jz      srcld3
  809.         subl    %edi,%esi
  810.         # erstes Digit shiften:
  811.         movl    (%edi,%esi),%ebx # *sourceptr in %ebx halten
  812.         shldl   shcl %ebx,%eax  # carry um %cl=32-i Bits links shiften, dabei *sourceptr rein
  813.         movl    %eax,(%edi)     # und als *destptr ablegen
  814.         # Letztes Digit in %ebx.
  815.         decl    %edx
  816.         jz      srcld2
  817. srcld1:   # weiteres Digit shiften:
  818.           leal    4(%edi),%edi    # sourceptr++, destptr++
  819.           movl    (%edi,%esi),%eax # nΣchstes Digit nach %eax
  820.           shldl   shcl %eax,%ebx  # %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften
  821.           movl    %ebx,(%edi)     # %ebx als *destptr ablegen
  822.           # Letztes Digit in %eax.
  823.           decl    %edx
  824.           jz      srcld3
  825.           # weiteres Digit shiften:
  826.           leal    4(%edi),%edi    # sourceptr++, destptr++
  827.           movl    (%edi,%esi),%ebx # nΣchstes Digit nach %ebx
  828.           shldl   shcl %ebx,%eax  # %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften
  829.           movl    %eax,(%edi)     # %eax als *destptr ablegen
  830.           # Letztes Digit in %ebx.
  831.           decl    %edx
  832.           jnz     srcld1
  833. srcld2: movl    %ebx,%eax
  834. srcld3: shll    %cl,%eax        # %eax um 32-i Bits nach links shiften
  835.         popl    %ebx            # %ebx zurⁿck
  836.         popl    %edi            # %edi zurⁿck
  837.         popl    %esi            # %esi zurⁿck
  838.         ret
  839.  
  840. # extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
  841. C(mulusmall_loop_down:)
  842.         pushl   %ebp            # %ebp retten
  843.         pushl   %edi            # %edi retten
  844.         pushl   %ebx            # %ebx retten
  845.         movl    16(%esp),%ebx   # %ebx = digit
  846.         movl    20(%esp),%edi   # %edi = ptr
  847.         movl    24(%esp),%ecx   # %ecx = len
  848.         movl    28(%esp),%ebp   # %ebp = carry := newdigit
  849.         movl    %ecx,%eax
  850.         negl    %eax            # %eax = -len
  851.         jz      msld2
  852.         leal    -4(%edi,%eax,4),%edi # %edi = &ptr[-1-len]
  853. msld1:    movl    (%edi,%ecx,4),%eax # *ptr
  854.           mull    %ebx               # %edx|%eax := digit * *ptr
  855.           addl    %ebp,%eax          # carry und Low-Teil des Produktes addieren
  856.           movl    $0,%ebp
  857.           adcl    %edx,%ebp          # ▄bertrag zum High-Teil %edx dazu, gibt neuen carry
  858.           movl    %eax,(%edi,%ecx,4) # Low-Teil als *ptr ablegen
  859.           decl    %ecx               # count--, ptr--
  860.           jnz     msld1
  861. msld2:  movl    %ebp,%eax       # Ergebnis := letzter ▄bertrag
  862.         popl    %ebx            # %ebx zurⁿck
  863.         popl    %edi            # %edi zurⁿck
  864.         popl    %ebp            # %ebp zurⁿck
  865.         ret
  866.  
  867. # extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
  868. C(mulu_loop_down:)
  869.         pushl   %ebp            # %ebp retten
  870.         pushl   %edi            # %edi retten
  871.         pushl   %esi            # %esi retten
  872.         pushl   %ebx            # %ebx retten
  873.         movl    20(%esp),%ebx   # %ebx = digit
  874.         movl    24(%esp),%esi   # %esi = sourceptr
  875.         movl    28(%esp),%edi   # %edi = destptr
  876.         movl    32(%esp),%ecx   # %ecx = len
  877.         movl    %ecx,%eax
  878.         notl    %eax            # %eax = -1-len
  879.         leal    (%esi,%eax,4),%esi # %esi = &sourceptr[-1-len]
  880.         leal    (%edi,%eax,4),%edi # %edi = &destptr[-1-len]
  881.         xorl    %ebp,%ebp       # %epb = carry := 0
  882. muld1:    movl    (%esi,%ecx,4),%eax # *sourceptr
  883.           mull    %ebx               # %edx|%eax := digit * *sourceptr
  884.           addl    %ebp,%eax          # carry und Low-Teil des Produktes addieren
  885.           movl    $0,%ebp
  886.           adcl    %edx,%ebp          # ▄bertrag zum High-Teil %edx dazu, gibt neuen carry
  887.           movl    %eax,(%edi,%ecx,4) # Low-Teil als *destptr ablegen
  888.           decl    %ecx               # count--, sourceptr--, destptr--
  889.           jnz     muld1
  890.         movl    %ebp,(%edi)     # letzten ▄bertrag ablegen
  891.         popl    %ebx            # %ebx zurⁿck
  892.         popl    %esi            # %esi zurⁿck
  893.         popl    %edi            # %edi zurⁿck
  894.         popl    %ebp            # %ebp zurⁿck
  895.         ret
  896.  
  897. # extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
  898. C(muluadd_loop_down:)
  899.         pushl   %ebp            # %ebp retten
  900.         pushl   %edi            # %edi retten
  901.         pushl   %esi            # %esi retten
  902.         pushl   %ebx            # %ebx retten
  903.         movl    20(%esp),%ebx   # %ebx = digit
  904.         movl    24(%esp),%esi   # %esi = sourceptr
  905.         movl    28(%esp),%edi   # %edi = destptr
  906.         movl    32(%esp),%ecx   # %ecx = len
  907.         movl    %ecx,%eax
  908.         notl    %eax            # %eax = -1-len
  909.         leal    (%esi,%eax,4),%esi # %esi = &sourceptr[-1-len]
  910.         leal    (%edi,%eax,4),%edi # %edi = &destptr[-1-len]
  911.         xorl    %ebp,%ebp       # %epb = carry := 0
  912. muald1:   movl    (%esi,%ecx,4),%eax # *sourceptr
  913.           mull    %ebx               # %edx|%eax := digit * *sourceptr
  914.           addl    %ebp,%eax          # carry und Low-Teil des Produktes addieren
  915.           movl    $0,%ebp
  916.           adcl    %ebp,%edx          # ▄bertrag zum High-Teil %edx dazu
  917.           addl    %eax,(%edi,%ecx,4) # Low-Teil zu *destptr addieren
  918.           adcl    %edx,%ebp          # zweiten ▄bertrag zu %edx addieren, gibt neuen carry
  919.           decl    %ecx               # count--, sourceptr--, destptr--
  920.           jnz     muald1
  921.         movl    %ebp,%eax       # Ergebnis := letzter ▄bertrag
  922.         popl    %ebx            # %ebx zurⁿck
  923.         popl    %esi            # %esi zurⁿck
  924.         popl    %edi            # %edi zurⁿck
  925.         popl    %ebp            # %ebp zurⁿck
  926.         ret
  927.  
  928. # extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
  929. C(mulusub_loop_down:)
  930.         pushl   %ebp            # %ebp retten
  931.         pushl   %edi            # %edi retten
  932.         pushl   %esi            # %esi retten
  933.         pushl   %ebx            # %ebx retten
  934.         movl    20(%esp),%ebx   # %ebx = digit
  935.         movl    24(%esp),%esi   # %esi = sourceptr
  936.         movl    28(%esp),%edi   # %edi = destptr
  937.         movl    32(%esp),%ecx   # %ecx = len
  938.         movl    %ecx,%eax
  939.         notl    %eax            # %eax = -1-len
  940.         leal    (%esi,%eax,4),%esi # %esi = &sourceptr[-1-len]
  941.         leal    (%edi,%eax,4),%edi # %edi = &destptr[-1-len]
  942.         xorl    %ebp,%ebp       # %epb = carry := 0
  943. musld1:   movl    (%esi,%ecx,4),%eax # *sourceptr
  944.           mull    %ebx               # %edx|%eax := digit * *sourceptr
  945.           addl    %ebp,%eax          # carry und Low-Teil des Produktes addieren
  946.           movl    $0,%ebp
  947.           adcl    %ebp,%edx          # ▄bertrag zum High-Teil %edx dazu
  948.           subl    %eax,(%edi,%ecx,4) # Low-Teil von *destptr subtrahieren
  949.           adcl    %edx,%ebp          # zweiten ▄bertrag zu %edx addieren, gibt neuen carry
  950.           decl    %ecx               # count--, sourceptr--, destptr--
  951.           jnz     musld1
  952.         movl    %ebp,%eax       # Ergebnis := letzter ▄bertrag
  953.         popl    %ebx            # %ebx zurⁿck
  954.         popl    %esi            # %esi zurⁿck
  955.         popl    %edi            # %edi zurⁿck
  956.         popl    %ebp            # %ebp zurⁿck
  957.         ret
  958.  
  959. # extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
  960. C(divu_loop_up:)
  961.         pushl   %edi            # %edi retten
  962.         pushl   %ebx            # %ebx retten
  963.         movl    12(%esp),%ebx   # %ebx = digit
  964.         movl    16(%esp),%edi   # %edi = ptr
  965.         movl    20(%esp),%ecx   # %ecx = len
  966.         xorl    %edx,%edx       # %edx = Rest := 0
  967.         jecxz   dlu2            # %ecx = 0 ?
  968. dlu1:     movl    (%edi),%eax     # nΣchstes Digit *ptr
  969.           divl    %ebx            # Division von %edx|%eax durch %ebx
  970.           movl    %eax,(%edi)     # Quotient %eax ablegen, Rest in %edx behalten
  971.           leal    4(%edi),%edi    # ptr++
  972.           decl    %ecx
  973.           jnz     dlu1
  974. dlu2:   movl    %edx,%eax       # Ergebnis := letzter Rest
  975.         popl    %ebx            # %ebx zurⁿck
  976.         popl    %edi            # %edi zurⁿck
  977.         ret
  978.  
  979. # extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
  980. C(divucopy_loop_up:)
  981.         pushl   %edi            # %edi retten
  982.         pushl   %esi            # %esi retten
  983.         pushl   %ebx            # %ebx retten
  984.         movl    16(%esp),%ebx   # %ebx = digit
  985.         movl    20(%esp),%esi   # %esi = sourceptr
  986.         movl    24(%esp),%edi   # %edi = destptr
  987.         movl    28(%esp),%ecx   # %ecx = len
  988.         xorl    %edx,%edx       # %edx = Rest := 0
  989.         jecxz   dclu2           # %ecx = 0 ?
  990.         subl    %edi,%esi
  991. dclu1:    movl    (%esi,%edi),%eax # nΣchstes Digit *ptr
  992.           divl    %ebx            # Division von %edx|%eax durch %ebx
  993.           movl    %eax,(%edi)     # Quotient %eax ablegen, Rest in %edx behalten
  994.           leal    4(%edi),%edi    # sourceptr++, destptr++
  995.           decl    %ecx
  996.           jnz     dclu1
  997. dclu2:  movl    %edx,%eax       # Ergebnis := letzter Rest
  998.         popl    %ebx            # %ebx zurⁿck
  999.         popl    %esi            # %esi zurⁿck
  1000.         popl    %edi            # %edi zurⁿck
  1001.         ret
  1002.  
  1003. #endif
  1004.  
  1005.