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 ASM_UNDERSCORE
14     #if defined(__STDC__) || defined (__cplusplus)
15       #define C(entrypoint) _##entrypoint
16     #else
17       #define C(entrypoint) _/**/entrypoint
18     #endif
19   #else
20     #define C(entrypoint) entrypoint
21   #endif
22   #ifdef ASM_UNDERSCORE
23     #if defined(__STDC__) || defined (__cplusplus)
24       #define L(label) L##label
25     #else
26       #define L(label) L/**/label
27     #endif
28   #else
29     #if defined(__STDC__) || defined (__cplusplus)
30       #define L(label) .L##label
31     #else
32       #define L(label) .L/**/label
33     #endif
34   #endif
35   #if defined(ASM_UNDERSCORE) || defined(COHERENT) /* defined(__EMX__) || defined(__GO32__) || defined(linux) || defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(COHERENT) || ... */
36     // GNU-Assembler oder MWC-Assembler
37     #define repz     repe
38     #define shcl     %cl,
39   #else /* defined(sun) || ... */
40     // SUN-Assembler oder Consensys-Assembler
41     #define jecxz    orl %ecx,%ecx ; jz
42     #define shcl
43   #endif
44   #if defined(__EMX__)
45     // Direction-Flag ist defaultmäßig gelöscht
46     #define dir0start
47     #define dir0end
48     #define dir1start  std
49     #define dir1end    cld
50   #elif 1
51     // Wir gehen auf Nummer sicher.
52     #define dir0start  cld
53     #define dir0end
54     #define dir1start  std
55     #define dir1end    cld
56   #else
57     // Direction-Flag darf nach Belieben modifiziert werden
58     #define dir0start  cld
59     #define dir0end
60     #define dir1start  std
61     #define dir1end
62   #endif
63   // Alignment. Note that some assemblers need ".align 3,0x90" whereas other
64   // assemblers don't like this syntax. So we put in the "nop"s by hand.
65   #if defined(ASM_UNDERSCORE) && !(defined(__CYGWIN32__) || defined(__MINGW32__))
66     // BSD syntax assembler
67     #define ALIGN  .align 3
68   #else
69     // ELF syntax assembler
70     #define ALIGN  .align 8
71   #endif
72   // When this file is compiled into a shared library, ELF linkers need to
73   // know which symbols are functions.
74   #if defined(__svr4__) || defined(__ELF__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__ROSE__) || defined(_SEQUENT_) || defined(DGUX) || defined(_SCO_COFF) || defined(_SCO_ELF)
75     #define DECLARE_FUNCTION(name) .type C(name),@function
76   #else
77     #define DECLARE_FUNCTION(name)
78   #endif
79 
80             .text
81 
82             .globl C(copy_loop_up)
83             .globl C(copy_loop_down)
84             .globl C(fill_loop_up)
85             .globl C(fill_loop_down)
86             .globl C(clear_loop_up)
87             .globl C(clear_loop_down)
88             .globl C(test_loop_up)
89             .globl C(test_loop_down)
90             .globl C(xor_loop_up)
91             .globl C(compare_loop_up)
92             .globl C(shiftleftcopy_loop_up)
93             .globl C(shiftxor_loop_up)
94 #if CL_DS_BIG_ENDIAN_P
95             .globl C(or_loop_up)
96             .globl C(and_loop_up)
97             .globl C(eqv_loop_up)
98             .globl C(nand_loop_up)
99             .globl C(nor_loop_up)
100             .globl C(andc2_loop_up)
101             .globl C(orc2_loop_up)
102             .globl C(not_loop_up)
103             .globl C(and_test_loop_up)
104             .globl C(add_loop_down)
105             .globl C(addto_loop_down)
106             .globl C(inc_loop_down)
107             .globl C(sub_loop_down)
108             .globl C(subx_loop_down)
109             .globl C(subfrom_loop_down)
110             .globl C(dec_loop_down)
111             .globl C(neg_loop_down)
112             .globl C(shift1left_loop_down)
113             .globl C(shiftleft_loop_down)
114             .globl C(shiftleftcopy_loop_down)
115             .globl C(shift1right_loop_up)
116             .globl C(shiftright_loop_up)
117             .globl C(shiftrightsigned_loop_up)
118             .globl C(shiftrightcopy_loop_up)
119             .globl C(mulusmall_loop_down)
120             .globl C(mulu_loop_down)
121             .globl C(muluadd_loop_down)
122             .globl C(mulusub_loop_down)
123             .globl C(divu_loop_up)
124             .globl C(divucopy_loop_up)
125 #else
126             .globl C(or_loop_down)
127             .globl C(xor_loop_down)
128             .globl C(and_loop_down)
129             .globl C(eqv_loop_down)
130             .globl C(nand_loop_down)
131             .globl C(nor_loop_down)
132             .globl C(andc2_loop_down)
133             .globl C(orc2_loop_down)
134             .globl C(not_loop_down)
135             .globl C(and_test_loop_down)
136             .globl C(compare_loop_down)
137             .globl C(add_loop_up)
138             .globl C(addto_loop_up)
139             .globl C(inc_loop_up)
140             .globl C(sub_loop_up)
141             .globl C(subx_loop_up)
142             .globl C(subfrom_loop_up)
143             .globl C(dec_loop_up)
144             .globl C(neg_loop_up)
145             .globl C(shift1left_loop_up)
146             .globl C(shiftleft_loop_up)
147             .globl C(shift1right_loop_down)
148             .globl C(shiftright_loop_down)
149             .globl C(shiftrightsigned_loop_down)
150             .globl C(shiftrightcopy_loop_down)
151             .globl C(mulusmall_loop_up)
152             .globl C(mulu_loop_up)
153             .globl C(muluadd_loop_up)
154             .globl C(mulusub_loop_up)
155             .globl C(divu_loop_down)
156             .globl C(divucopy_loop_down)
157 #endif
158 
159 #ifndef __GNUC__ /* mit GNU-C machen wir mulu32() als Macro, der inline multipliziert */
160 
161 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
162 // 2^32*hi+lo := arg1*arg2.
163             .globl C(mulu32_)
164             ALIGN
165             DECLARE_FUNCTION(mulu32_)
166 C(mulu32_:)
167             movl    4(%esp),%eax    // arg1
168             mull    8(%esp)         // %edx|%eax := arg1 * arg2
169             movl    %edx,C(mulu32_high) // %edx = hi abspeichern
170             ret                     // %eax = lo als Ergebnis
171 
172 #endif
173 
174 #ifndef __GNUC__ /* mit GNU-C machen wir divu_6432_3232() als Macro, der inline dividiert */
175 
176 // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
177 // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y .
178             .globl C(divu_6432_3232_)
179             ALIGN
180             DECLARE_FUNCTION(divu_6432_3232_)
181 C(divu_6432_3232_:)
182             movl    4(%esp),%edx
183             movl    8(%esp),%eax
184             divl    12(%esp)       // x = %edx|%eax durch dividieren
185             movl    %edx,C(divu_32_rest) // Rest %edx = r abspeichern
186             ret                    // Quotient %eax = q als Ergebnis
187 
188 #endif
189 
190 // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
191             ALIGN
192             DECLARE_FUNCTION(copy_loop_up)
193 C(copy_loop_up:)
194             movl    %edi,%edx       // %edi retten
195             movl    %esi,%eax       // %esi retten
196             movl    4(%esp),%esi    // %esi = sourceptr
197             movl    8(%esp),%edi    // %edi = destptr
198             movl    12(%esp),%ecx   // %ecx = count
199             dir0start
200             rep
201               movsl                 // %ecx mal aufwärts (%edi) := (%esi)
202             dir0end
203             movl    %eax,%esi       // %esi zurück
204             movl    %edi,%eax       // %edi als Ergebnis
205             movl    %edx,%edi       // %edi zurück
206             ret
207 
208 // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
209             ALIGN
210             DECLARE_FUNCTION(copy_loop_down)
211 C(copy_loop_down:)
212             movl    %edi,%edx       // %edi retten
213             movl    %esi,%eax       // %esi retten
214             movl    4(%esp),%esi    // %esi = sourceptr
215             movl    8(%esp),%edi    // %edi = destptr
216             movl    12(%esp),%ecx   // %ecx = count
217             leal    -4(%esi),%esi
218             leal    -4(%edi),%edi
219             dir1start
220             rep
221               movsl                 // %ecx mal abwärts (%edi) := (%esi)
222             dir1end
223             movl    %eax,%esi       // %esi zurück
224             leal    4(%edi),%eax    // %edi als Ergebnis
225             movl    %edx,%edi       // %edi zurück
226             ret
227 
228 // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
229             ALIGN
230             DECLARE_FUNCTION(fill_loop_up)
231 C(fill_loop_up:)
232             movl    %edi,%edx       // %edi retten
233             movl    4(%esp),%edi    // %edi = destptr
234             movl    8(%esp),%ecx    // %ecx = count
235             movl    12(%esp),%eax   // %eax = filler
236             dir0start
237             rep
238               stosl                 // %ecx mal aufwärts (%edi) := %eax
239             dir0end
240             movl    %edi,%eax       // %edi als Ergebnis
241             movl    %edx,%edi       // %edi zurück
242             ret
243 
244 // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
245             ALIGN
246             DECLARE_FUNCTION(fill_loop_down)
247 C(fill_loop_down:)
248             movl    %edi,%edx       // %edi retten
249             movl    4(%esp),%edi    // %edi = destptr
250             movl    8(%esp),%ecx    // %ecx = count
251             movl    12(%esp),%eax   // %eax = filler
252             leal    -4(%edi),%edi
253             dir1start
254             rep
255               stosl                 // %ecx mal abwärts (%edi) := %eax
256             dir1end
257             leal    4(%edi),%eax    // %edi als Ergebnis
258             movl    %edx,%edi       // %edi zurück
259             ret
260 
261 // extern uintD* clear_loop_up (uintD* destptr, uintC count);
262             ALIGN
263             DECLARE_FUNCTION(clear_loop_up)
264 C(clear_loop_up:)
265             movl    %edi,%edx       // %edi retten
266             movl    4(%esp),%edi    // %edi = destptr
267             movl    8(%esp),%ecx    // %ecx = count
268             xorl    %eax,%eax       // %eax = 0
269             dir0start
270             rep
271               stosl                 // %ecx mal aufwärts (%edi) := %eax
272             dir0end
273             movl    %edi,%eax       // %edi als Ergebnis
274             movl    %edx,%edi       // %edi zurück
275             ret
276 
277 // extern uintD* clear_loop_down (uintD* destptr, uintC count);
278             ALIGN
279             DECLARE_FUNCTION(clear_loop_down)
280 C(clear_loop_down:)
281             movl    %edi,%edx       // %edi retten
282             movl    4(%esp),%edi    // %edi = destptr
283             movl    8(%esp),%ecx    // %ecx = count
284             leal    -4(%edi),%edi
285             xorl    %eax,%eax       // %eax = 0
286             dir1start
287             rep
288               stosl                 // %ecx mal abwärts (%edi) := %eax
289             dir1end
290             leal    4(%edi),%eax    // %edi als Ergebnis
291             movl    %edx,%edi       // %edi zurück
292             ret
293 
294 // extern boolean test_loop_up (uintD* ptr, uintC count);
295             ALIGN
296             DECLARE_FUNCTION(test_loop_up)
297 C(test_loop_up:)
298             movl    %edi,%edx       // %edi retten
299             movl    4(%esp),%edi    // %edi = ptr
300             movl    8(%esp),%ecx    // %ecx = count
301             xorl    %eax,%eax       // %eax = 0
302             dir0start
303             repz                    // Falls %ecx > 0:
304               scasl                 // %ecx mal aufwärts (%edi) testen
305                                     // und weiterschleifen, falls Z, d.h. (%edi)=0.
306             dir0end
307             // Noch ist %eax = 0.
308             jz      L(tlu1)         // alles =0 -> Ergebnis 0
309             incl    %eax            // Ergebnis 1
310 L(tlu1:)    movl    %edx,%edi       // %edi zurück
311             ret
312 
313 // extern boolean test_loop_down (uintD* ptr, uintC count);
314             ALIGN
315             DECLARE_FUNCTION(test_loop_down)
316 C(test_loop_down:)
317             movl    %edi,%edx       // %edi retten
318             movl    4(%esp),%edi    // %edi = ptr
319             movl    8(%esp),%ecx    // %ecx = count
320             xorl    %eax,%eax       // %eax = 0
321             leal    -4(%edi),%edi
322             dir1start
323             repz                    // Falls %ecx > 0:
324               scasl                 // %ecx mal aufwärts (%edi) testen
325                                     // und weiterschleifen, falls Z, d.h. (%edi)=0.
326             dir1end
327             // Noch ist %eax = 0.
328             jz      L(tld1)         // alles =0 -> Ergebnis 0
329             incl    %eax            // Ergebnis 1
330 L(tld1:)    movl    %edx,%edi       // %edi zurück
331             ret
332 
333 #if CL_DS_BIG_ENDIAN_P
334 
335 // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
336             ALIGN
337             DECLARE_FUNCTION(or_loop_up)
338 C(or_loop_up:)
339             pushl   %esi            // %esi retten
340             movl    8(%esp),%edx    // %edx = xptr
341             movl    12(%esp),%esi   // %esi = yptr
342             movl    16(%esp),%ecx   // %ecx = count
343             subl    %edx,%esi
344             jecxz   L(olu2)         // %ecx = 0 ?
345 L(olu1:)      movl    (%edx,%esi),%eax // *yptr
346               orl     %eax,(%edx)      // *xptr |= ...
347               leal    4(%edx),%edx     // xptr++, yptr++
348               decl    %ecx
349               jnz     L(olu1)
350 L(olu2:)    popl    %esi            // %esi zurück
351             ret
352 
353 #endif
354 
355 // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
356             ALIGN
357             DECLARE_FUNCTION(xor_loop_up)
358 C(xor_loop_up:)
359             pushl   %esi            // %esi retten
360             movl    8(%esp),%edx    // %edx = xptr
361             movl    12(%esp),%esi   // %esi = yptr
362             movl    16(%esp),%ecx   // %ecx = count
363             subl    %edx,%esi
364             jecxz   L(xlu2)         // %ecx = 0 ?
365 L(xlu1:)      movl    (%edx,%esi),%eax // *yptr
366               xorl    %eax,(%edx)      // *xptr ^= ...
367               leal    4(%edx),%edx     // xptr++, yptr++
368               decl    %ecx
369               jnz     L(xlu1)
370 L(xlu2:)    popl    %esi            // %esi zurück
371             ret
372 
373 #if CL_DS_BIG_ENDIAN_P
374 
375 // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
376             ALIGN
377             DECLARE_FUNCTION(and_loop_up)
378 C(and_loop_up:)
379             pushl   %esi            // %esi retten
380             movl    8(%esp),%edx    // %edx = xptr
381             movl    12(%esp),%esi   // %esi = yptr
382             movl    16(%esp),%ecx   // %ecx = count
383             subl    %edx,%esi
384             jecxz   L(alu2)         // %ecx = 0 ?
385 L(alu1:)      movl    (%edx,%esi),%eax // *yptr
386               andl    %eax,(%edx)      // *xptr &= ...
387               leal    4(%edx),%edx     // xptr++, yptr++
388               decl    %ecx
389               jnz     L(alu1)
390 L(alu2:)    popl    %esi            // %esi zurück
391             ret
392 
393 // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
394             ALIGN
395             DECLARE_FUNCTION(eqv_loop_up)
396 C(eqv_loop_up:)
397             pushl   %esi            // %esi retten
398             movl    8(%esp),%edx    // %edx = xptr
399             movl    12(%esp),%esi   // %esi = yptr
400             movl    16(%esp),%ecx   // %ecx = count
401             subl    %edx,%esi
402             jecxz   L(elu2)         // %ecx = 0 ?
403 L(elu1:)      movl    (%edx),%eax      // *xptr
404               xorl    (%edx,%esi),%eax // ^ *yptr
405               notl    %eax             // ~(...)
406               movl    %eax,(%edx)      // =: *xptr
407               leal    4(%edx),%edx     // xptr++, yptr++
408               decl    %ecx
409               jnz     L(elu1)
410 L(elu2:)    popl    %esi            // %esi zurück
411             ret
412 
413 // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
414             ALIGN
415             DECLARE_FUNCTION(nand_loop_up)
416 C(nand_loop_up:)
417             pushl   %esi            // %esi retten
418             movl    8(%esp),%edx    // %edx = xptr
419             movl    12(%esp),%esi   // %esi = yptr
420             movl    16(%esp),%ecx   // %ecx = count
421             subl    %edx,%esi
422             jecxz   L(nalu2)        // %ecx = 0 ?
423 L(nalu1:)     movl    (%edx),%eax      // *xptr
424               andl    (%edx,%esi),%eax // & *yptr
425               notl    %eax             // ~(...)
426               movl    %eax,(%edx)      // =: *xptr
427               leal    4(%edx),%edx     // xptr++, yptr++
428               decl    %ecx
429               jnz     L(nalu1)
430 L(nalu2:)   popl    %esi            // %esi zurück
431             ret
432 
433 // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
434             ALIGN
435             DECLARE_FUNCTION(nor_loop_up)
436 C(nor_loop_up:)
437             pushl   %esi            // %esi retten
438             movl    8(%esp),%edx    // %edx = xptr
439             movl    12(%esp),%esi   // %esi = yptr
440             movl    16(%esp),%ecx   // %ecx = count
441             subl    %edx,%esi
442             jecxz   L(nolu2)        // %ecx = 0 ?
443 L(nolu1:)     movl    (%edx),%eax      // *xptr
444               orl     (%edx,%esi),%eax // | *yptr
445               notl    %eax             // ~(...)
446               movl    %eax,(%edx)      // =: *xptr
447               leal    4(%edx),%edx     // xptr++, yptr++
448               decl    %ecx
449               jnz     L(nolu1)
450 L(nolu2:)   popl    %esi            // %esi zurück
451             ret
452 
453 // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
454             ALIGN
455             DECLARE_FUNCTION(andc2_loop_up)
456 C(andc2_loop_up:)
457             pushl   %esi            // %esi retten
458             movl    8(%esp),%edx    // %edx = xptr
459             movl    12(%esp),%esi   // %esi = yptr
460             movl    16(%esp),%ecx   // %ecx = count
461             subl    %edx,%esi
462             jecxz   L(aclu2)        // %ecx = 0 ?
463 L(aclu1:)     movl    (%edx,%esi),%eax // *yptr
464               notl    %eax             // ~ *yptr
465               andl    %eax,(%edx)      // *xptr &= ...
466               leal    4(%edx),%edx     // xptr++, yptr++
467               decl    %ecx
468               jnz     L(aclu1)
469 L(aclu2:)   popl    %esi            // %esi zurück
470             ret
471 
472 // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
473             ALIGN
474             DECLARE_FUNCTION(orc2_loop_up)
475 C(orc2_loop_up:)
476             pushl   %esi            // %esi retten
477             movl    8(%esp),%edx    // %edx = xptr
478             movl    12(%esp),%esi   // %esi = yptr
479             movl    16(%esp),%ecx   // %ecx = count
480             subl    %edx,%esi
481             jecxz   L(oclu2)        // %ecx = 0 ?
482 L(oclu1:)     movl    (%edx,%esi),%eax // *yptr
483               notl    %eax             // ~ *yptr
484               orl     %eax,(%edx)      // *xptr |= ...
485               leal    4(%edx),%edx     // xptr++, yptr++
486               decl    %ecx
487               jnz     L(oclu1)
488 L(oclu2:)   popl    %esi            // %esi zurück
489             ret
490 
491 // extern void not_loop_up (uintD* xptr, uintC count);
492             ALIGN
493             DECLARE_FUNCTION(not_loop_up)
494 C(not_loop_up:)
495             movl    4(%esp),%edx    // %edx = xptr
496             movl    8(%esp),%ecx    // %ecx = count
497             jecxz   L(nlu2)         // %ecx = 0 ?
498             nop ; nop ; nop ; nop ; nop ; nop
499 L(nlu1:)      notl    (%edx)           // ~= *xptr
500               leal    4(%edx),%edx     // xptr++
501               decl    %ecx
502               jnz     L(nlu1)
503 L(nlu2:)    ret
504 
505 // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
506             ALIGN
507             DECLARE_FUNCTION(and_test_loop_up)
508 C(and_test_loop_up:)
509             pushl   %esi            // %esi retten
510             movl    8(%esp),%edx    // %edx = xptr
511             movl    12(%esp),%esi   // %esi = yptr
512             movl    16(%esp),%ecx   // %ecx = count
513             jecxz   L(atlu2)        // %ecx = 0 ?
514             subl    %edx,%esi
515 L(atlu1:)     movl    (%edx,%esi),%eax // *yptr
516               andl    (%edx),%eax      // *xptr & ...
517               jnz     L(atlu3)
518               leal    4(%edx),%edx     // xptr++, yptr++
519               decl    %ecx
520               jnz     L(atlu1)
521 L(atlu2:)   xorl    %eax,%eax       // Ergebnis 0
522             popl    %esi            // %esi zurück
523             ret
524 L(atlu3:)   movl    $1,%eax         // Ergebnis 1 (nicht irgendwas /=0 !)
525             popl    %esi            // %esi zurück
526             ret
527 
528 #endif
529 
530 // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
531             ALIGN
532             DECLARE_FUNCTION(compare_loop_up)
533 C(compare_loop_up:)
534             movl    %esi,%edx       // %esi retten
535             movl    %edi,%eax       // %edi retten
536             movl    4(%esp),%esi    // %esi = xptr
537             movl    8(%esp),%edi    // %edi = yptr
538             movl    12(%esp),%ecx   // %ecx = count
539             cmpl    %ecx,%ecx       // initialize flags for the case %ecx is 0
540             dir0start
541             repz                    // Falls %ecx > 0:
542               cmpsl                 // %ecx mal aufwärts (%edi) und (%esi) vergleichen
543                                     // und weiterschleifen, falls Z, d.h. (%edi)=(%esi).
544             dir0end
545             // Flags -> Ergebnis:
546             // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0
547             // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x<y -> Ergebnis -1
548             // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1
549             movl    %eax,%edi       // %edi zurück
550             movl    %edx,%esi       // %esi zurück
551             jbe     L(cmlu1)        // "be" = Z oder C
552             movl    $1,%eax         // Ergebnis +1
553             ret
554 L(cmlu1:)   sbbl    %eax,%eax       // Ergebnis -1 (falls C) oder 0 (falls NC)
555             ret
556 
557 #if CL_DS_BIG_ENDIAN_P
558 
559 // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
560             ALIGN
561             DECLARE_FUNCTION(add_loop_down)
562 C(add_loop_down:)
563             pushl   %esi            // %esi retten
564             pushl   %edi            // %edi retten
565             movl    12(%esp),%edx   // %edx = sourceptr1
566             movl    16(%esp),%esi   // %esi = sourceptr2
567             movl    20(%esp),%edi   // %edi = destptr
568             movl    24(%esp),%ecx   // %ecx = count
569             subl    %edi,%edx
570             subl    %edi,%esi
571             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
572             jz      L(ald2)
573 L(ald1:)      leal    -4(%edi),%edi   // sourceptr1--, sourceptr2--, destptr--
574               movl    (%edx,%edi),%eax // *sourceptr1
575               adcl    (%esi,%edi),%eax // + *sourceptr2 + carry
576               movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
577               decl    %ecx
578               jnz     L(ald1)
579 L(ald2:)    sbbl    %eax,%eax      // Ergebnis := - Carry
580             popl    %edi           // %edi zurück
581             popl    %esi           // %esi zurück
582             ret
583 
584 // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
585             ALIGN
586             DECLARE_FUNCTION(addto_loop_down)
587 C(addto_loop_down:)
588             pushl   %edi            // %edi retten
589             movl    8(%esp),%edx    // %edx = sourceptr
590             movl    12(%esp),%edi   // %edi = destptr
591             movl    16(%esp),%ecx   // %ecx = count
592             subl    %edi,%edx
593             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
594             jz      L(atld2)
595 L(atld1:)     leal    -4(%edi),%edi   // sourceptr--, destptr--
596               movl    (%edx,%edi),%eax // *sourceptr
597               adcl    %eax,(%edi)     // + *destptr + carry =: *destptr, neuer Carry
598               decl    %ecx
599               jnz     L(atld1)
600 L(atld2:)   sbbl    %eax,%eax       // Ergebnis := - Carry
601             popl    %edi            // %edi zurück
602             ret
603 
604 // extern uintD inc_loop_down (uintD* ptr, uintC count);
605             ALIGN
606             DECLARE_FUNCTION(inc_loop_down)
607 C(inc_loop_down:)
608             movl    4(%esp),%edx    // %edx = ptr
609             movl    8(%esp),%ecx    // %ecx = count
610             jecxz   L(ild2)         // %ecx = 0 ?
611 L(ild1:)      leal    -4(%edx),%edx
612               addl    $1,(%edx)       // (*ptr)++
613               jnc     L(ild3)         // kein Carry -> fertig
614               decl    %ecx
615               jnz     L(ild1)
616 L(ild2:)    movl    $1,%eax         // Ergebnis := 1
617             ret
618 L(ild3:)    xorl    %eax,%eax       // Ergebnis := 0
619             ret
620 
621 // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
622             ALIGN
623             DECLARE_FUNCTION(sub_loop_down)
624 C(sub_loop_down:)
625             pushl   %esi            // %esi retten
626             pushl   %edi            // %edi retten
627             movl    12(%esp),%edx   // %edx = sourceptr1
628             movl    16(%esp),%esi   // %esi = sourceptr2
629             movl    20(%esp),%edi   // %edi = destptr
630             movl    24(%esp),%ecx   // %ecx = count
631             subl    %edi,%edx
632             subl    %edi,%esi
633             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
634             jz      L(sld2)
635 L(sld1:)      leal    -4(%edi),%edi   // sourceptr1--, sourceptr2--, destptr--
636               movl    (%edx,%edi),%eax // *sourceptr1
637               sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
638               movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
639               decl    %ecx
640               jnz     L(sld1)
641 L(sld2:)    sbbl    %eax,%eax      // Ergebnis := - Carry
642             popl    %edi           // %edi zurück
643             popl    %esi           // %esi zurück
644             ret
645 
646 // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
647             ALIGN
648             DECLARE_FUNCTION(subx_loop_down)
649 C(subx_loop_down:)
650             pushl   %esi            // %esi retten
651             pushl   %edi            // %edi retten
652             movl    12(%esp),%edx   // %edx = sourceptr1
653             movl    16(%esp),%esi   // %esi = sourceptr2
654             movl    20(%esp),%edi   // %edi = destptr
655             movl    24(%esp),%ecx   // %ecx = count
656             jecxz   L(sxld2)        // %ecx = 0 ?
657             subl    %edi,%edx
658             subl    %edi,%esi
659             movl    28(%esp),%eax   // carry, 0 oder -1
660             addl    %eax,%eax       // Bit 31 davon in den Carry
661             nop ; nop
662 L(sxld1:)     leal    -4(%edi),%edi   // sourceptr1--, sourceptr2--, destptr--
663               movl    (%edx,%edi),%eax // *sourceptr1
664               sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
665               movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
666               decl    %ecx
667               jnz     L(sxld1)
668             sbbl    %eax,%eax      // Ergebnis := - Carry
669             popl    %edi           // %edi zurück
670             popl    %esi           // %esi zurück
671             ret
672 L(sxld2:)   movl    28(%esp),%eax  // Ergebnis := carry
673             popl    %edi           // %edi zurück
674             popl    %esi           // %esi zurück
675             ret
676 
677 // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
678             ALIGN
679             DECLARE_FUNCTION(subfrom_loop_down)
680 C(subfrom_loop_down:)
681             pushl   %edi            // %edi retten
682             movl    8(%esp),%edx    // %edx = sourceptr
683             movl    12(%esp),%edi   // %edi = destptr
684             movl    16(%esp),%ecx   // %ecx = count
685             subl    %edi,%edx
686             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
687             jz      L(sfld2)
688 L(sfld1:)     leal    -4(%edi),%edi   // sourceptr--, destptr--
689               movl    (%edx,%edi),%eax // *sourceptr
690               sbbl    %eax,(%edi)     // *destptr - *sourceptr - carry =: *destptr, neuer Carry
691               decl    %ecx
692               jnz     L(sfld1)
693 L(sfld2:)   sbbl    %eax,%eax       // Ergebnis := - Carry
694             popl    %edi            // %edi zurück
695             ret
696 
697 // extern uintD dec_loop_down (uintD* ptr, uintC count);
698             ALIGN
699             DECLARE_FUNCTION(dec_loop_down)
700 C(dec_loop_down:)
701             movl    4(%esp),%edx    // %edx = ptr
702             movl    8(%esp),%ecx    // %ecx = count
703             jecxz   L(dld2)         // %ecx = 0 ?
704 L(dld1:)      leal    -4(%edx),%edx
705               subl    $1,(%edx)       // (*ptr)--
706               jnc     L(dld3)         // kein Carry -> fertig
707               decl    %ecx
708               jnz     L(dld1)
709 L(dld2:)    movl    $-1,%eax        // Ergebnis := -1
710             ret
711 L(dld3:)    xorl    %eax,%eax       // Ergebnis := 0
712             ret
713 
714 // extern uintD neg_loop_down (uintD* ptr, uintC count);
715             ALIGN
716             DECLARE_FUNCTION(neg_loop_down)
717 C(neg_loop_down:)
718             movl    4(%esp),%edx    // %edx = ptr
719             movl    8(%esp),%ecx    // %ecx = count
720             // erstes Digit /=0 suchen:
721             jecxz   L(nld2)         // %ecx = 0 ?
722 L(nld1:)      leal    -4(%edx),%edx
723               negl    (%edx)
724               jnz     L(nld3)
725               decl    %ecx
726               jnz     L(nld1)
727 L(nld2:)    xorl    %eax,%eax       // Ergebnis := 0
728             ret
729             nop ; nop ; nop ; nop ; nop ; nop
730 L(nld3:)    // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
731             // alle anderen Digits invertieren:
732             decl    %ecx
733             jz      L(nld5)
734 L(nld4:)      leal    -4(%edx),%edx
735               notl    (%edx)
736               decl    %ecx
737               jnz     L(nld4)
738 L(nld5:)    movl    $-1,%eax        // Ergebnis := -1
739             ret
740 
741 // extern uintD shift1left_loop_down (uintD* ptr, uintC count);
742             ALIGN
743             DECLARE_FUNCTION(shift1left_loop_down)
744 C(shift1left_loop_down:)
745             movl    4(%esp),%edx    // %edx = ptr
746             movl    8(%esp),%ecx    // %ecx = count
747             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
748             jz      L(s1lld2)
749             nop ; nop ; nop ; nop
750 L(s1lld1:)    leal    -4(%edx),%edx   // ptr--
751               rcll    $1,(%edx)       // *ptr und Carry um 1 Bit links rotieren
752               decl    %ecx
753               jnz     L(s1lld1)
754 L(s1lld2:)  sbbl    %eax,%eax       // Ergebnis := - Carry
755             ret
756 
757 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
758             ALIGN
759             DECLARE_FUNCTION(shiftleft_loop_down)
760 C(shiftleft_loop_down:)
761             pushl   %edi            // %edi retten
762             pushl   %ebx            // %ebx retten
763             movl    12(%esp),%edi   // %edi = ptr
764             movl    16(%esp),%edx   // %edx = count
765             movb    20(%esp),%cl    // %cl = i
766             orl     %edx,%edx       // count = 0 ?
767             jz      L(slld4)
768             // erstes Digit shiften:
769             leal    -4(%edi),%edi
770             movl    (%edi),%eax     // Digit in %eax halten
771             movl    %eax,%ebx       // und in %ebx rechnen:
772             shll    %cl,%ebx        // um i Bits links shiften
773             orl     24(%esp),%ebx   // und die unteren i Bits eintragen
774             movl    %ebx,(%edi)     // und wieder ablegen
775             // Letztes Digit in %eax.
776             decl    %edx
777             jz      L(slld2)
778             nop ; nop ; nop ; nop
779 L(slld1:)     // weiteres Digit shiften:
780               leal    -4(%edi),%edi
781               movl    (%edi),%ebx
782               shldl   shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften
783               // Letztes Digit in %ebx.
784               decl    %edx
785               jz      L(slld3)
786               // weiteres Digit shiften:
787               leal    -4(%edi),%edi
788               movl    (%edi),%eax
789               shldl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften
790               // Letztes Digit in %eax.
791               decl    %edx
792               jnz     L(slld1)
793 L(slld2:)   movl    %eax,%ebx
794 L(slld3:)   xorl    %eax,%eax       // %eax := 0
795             shldl   shcl %ebx,%eax  // %eax := höchste %cl=i Bits von %ebx
796             popl    %ebx            // %ebx zurück
797             popl    %edi            // %edi zurück
798             ret
799 L(slld4:)   movl    24(%esp),%eax   // %eax := carry
800             popl    %ebx            // %ebx zurück
801             popl    %edi            // %edi zurück
802             ret
803 
804 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
805             ALIGN
806             DECLARE_FUNCTION(shiftleftcopy_loop_down)
807 C(shiftleftcopy_loop_down:)
808             pushl   %esi            // %esi retten
809             pushl   %edi            // %edi retten
810             pushl   %ebx            // %ebx retten
811             movl    16(%esp),%esi   // %esi = sourceptr
812             movl    20(%esp),%edi   // %edi = destptr
813             movl    24(%esp),%edx   // count
814             movb    28(%esp),%cl    // i
815             orl     %edx,%edx       // count = 0 ?
816             jz      L(slcld4)
817             subl    %edi,%esi
818             // erstes Digit shiften:
819             leal    -4(%edi),%edi   // sourceptr--, destptr--
820             movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
821             movl    %ebx,%eax       // und in %eax rechnen:
822             shll    %cl,%eax        // um i Bits links shiften, rechts Nullen rein
823             movl    %eax,(%edi)     // und als *destptr ablegen
824             // Letztes Digit in %ebx.
825             negb    %cl             // 32-i
826             decl    %edx
827             jz      L(slcld2)
828 L(slcld1:)    // weiteres Digit shiften:
829               leal    -4(%edi),%edi   // sourceptr--, destptr--
830               movl    (%edi,%esi),%eax // nächstes Digit nach %eax
831               shrdl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften
832               movl    %ebx,(%edi)     // %ebx als *destptr ablegen
833               // Letztes Digit in %eax.
834               decl    %edx
835               jz      L(slcld3)
836               // weiteres Digit shiften:
837               leal    -4(%edi),%edi   // sourceptr--, destptr--
838               movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
839               shrdl   shcl %ebx,%eax  // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften
840               movl    %eax,(%edi)     // %eax als *destptr ablegen
841               // Letztes Digit in %ebx.
842               decl    %edx
843               jnz     L(slcld1)
844 L(slcld2:)  movl    %ebx,%eax
845 L(slcld3:)  shrl    %cl,%eax        // %eax um 32-i Bits nach rechts shiften
846             popl    %ebx            // %ebx zurück
847             popl    %edi            // %edi zurück
848             popl    %esi            // %esi zurück
849             ret
850 L(slcld4:)  xorl    %eax,%eax       // %eax := 0
851             popl    %ebx            // %ebx zurück
852             popl    %edi            // %edi zurück
853             popl    %esi            // %esi zurück
854             ret
855 
856 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
857             ALIGN
858             DECLARE_FUNCTION(shift1right_loop_up)
859 C(shift1right_loop_up:)
860             movl    4(%esp),%edx    // %edx = ptr
861             movl    8(%esp),%ecx    // %ecx = count
862             movl    12(%esp),%eax   // %eax = carry (0 oder -1)
863             jecxz   L(s1rld3)       // %ecx = 0 ?
864             addl    %eax,%eax       // Carry := Bit 31 von carry
865 L(s1rld1:)    rcrl    $1,(%edx)       // *ptr und Carry um 1 Bit rechts rotieren
866               leal    4(%edx),%edx    // ptr++
867               decl    %ecx
868               jnz     L(s1rld1)
869 L(s1rld2:)  sbbl    %eax,%eax       // Ergebnis := - Carry
870 L(s1rld3:)  ret
871 
872 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
873             ALIGN
874             DECLARE_FUNCTION(shiftright_loop_up)
875 C(shiftright_loop_up:)
876             pushl   %edi            // %edi retten
877             pushl   %ebx            // %ebx retten
878             movl    12(%esp),%edi   // %edi = ptr
879             movl    16(%esp),%edx   // %edx = count
880             movb    20(%esp),%cl    // %cl = i
881             orl     %edx,%edx       // count = 0 ?
882             jz      L(srlu4)
883             // erstes Digit shiften:
884             movl    (%edi),%eax     // Digit in %eax halten
885             movl    %eax,%ebx       // und in %ebx rechnen:
886             shrl    %cl,%ebx        // um i Bits rechts shiften
887             movl    %ebx,(%edi)     // und wieder ablegen
888             // Letztes Digit in %eax.
889             decl    %edx
890             jz      L(srlu2)
891             nop ; nop ; nop
892 L(srlu1:)     // weiteres Digit shiften:
893               leal    4(%edi),%edi
894               movl    (%edi),%ebx
895               shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
896               // Letztes Digit in %ebx.
897               decl    %edx
898               jz      L(srlu3)
899               // weiteres Digit shiften:
900               leal    4(%edi),%edi
901               movl    (%edi),%eax
902               shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
903               // Letztes Digit in %eax.
904               decl    %edx
905               jnz     L(srlu1)
906 L(srlu2:)   movl    %eax,%ebx
907 L(srlu3:)   xorl    %eax,%eax       // %eax := 0
908             shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
909             popl    %ebx            // %ebx zurück
910             popl    %edi            // %edi zurück
911             ret
912 L(srlu4:)   xorl    %eax,%eax       // %eax := 0
913             popl    %ebx            // %ebx zurück
914             popl    %edi            // %edi zurück
915             ret
916 
917 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
918             ALIGN
919             DECLARE_FUNCTION(shiftrightsigned_loop_up)
920 C(shiftrightsigned_loop_up:)
921             pushl   %edi            // %edi retten
922             pushl   %ebx            // %ebx retten
923             movl    12(%esp),%edi   // %edi = ptr
924             movl    16(%esp),%edx   // %edx = count
925             movb    20(%esp),%cl    // %cl = i
926             // erstes Digit shiften:
927             movl    (%edi),%eax     // Digit in %eax halten
928             movl    %eax,%ebx       // und in %ebx rechnen:
929             sarl    %cl,%ebx        // um i Bits rechts shiften, Vorzeichen vervielfachen
930             movl    %ebx,(%edi)     // und wieder ablegen
931             // Letztes Digit in %eax.
932             decl    %edx
933             jz      L(srslu2)
934 L(srslu1:)    // weiteres Digit shiften:
935               leal    4(%edi),%edi
936               movl    (%edi),%ebx
937               shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
938               // Letztes Digit in %ebx.
939               decl    %edx
940               jz      L(srslu3)
941               // weiteres Digit shiften:
942               leal    4(%edi),%edi
943               movl    (%edi),%eax
944               shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
945               // Letztes Digit in %eax.
946               decl    %edx
947               jnz     L(srslu1)
948 L(srslu2:)  movl    %eax,%ebx
949 L(srslu3:)  xorl    %eax,%eax       // %eax := 0
950             shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
951             popl    %ebx            // %ebx zurück
952             popl    %edi            // %edi zurück
953             ret
954 
955 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
956             ALIGN
957             DECLARE_FUNCTION(shiftrightcopy_loop_up)
958 C(shiftrightcopy_loop_up:)
959             pushl   %esi            // %esi retten
960             pushl   %edi            // %edi retten
961             pushl   %ebx            // %ebx retten
962             movl    16(%esp),%esi   // %esi = sourceptr
963             movl    20(%esp),%edi   // %edi = destptr
964             movl    24(%esp),%edx   // count
965             movb    28(%esp),%cl    // i
966             negb    %cl             // 32-i
967             movl    32(%esp),%eax   // %eax = carry
968             orl     %edx,%edx       // count = 0 ?
969             jz      L(srcld3)
970             subl    %edi,%esi
971             // erstes Digit shiften:
972             movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
973             shldl   shcl %ebx,%eax  // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein
974             movl    %eax,(%edi)     // und als *destptr ablegen
975             // Letztes Digit in %ebx.
976             decl    %edx
977             jz      L(srcld2)
978 L(srcld1:)    // weiteres Digit shiften:
979               leal    4(%edi),%edi    // sourceptr++, destptr++
980               movl    (%edi,%esi),%eax // nächstes Digit nach %eax
981               shldl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften
982               movl    %ebx,(%edi)     // %ebx als *destptr ablegen
983               // Letztes Digit in %eax.
984               decl    %edx
985               jz      L(srcld3)
986               // weiteres Digit shiften:
987               leal    4(%edi),%edi    // sourceptr++, destptr++
988               movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
989               shldl   shcl %ebx,%eax  // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften
990               movl    %eax,(%edi)     // %eax als *destptr ablegen
991               // Letztes Digit in %ebx.
992               decl    %edx
993               jnz     L(srcld1)
994 L(srcld2:)  movl    %ebx,%eax
995 L(srcld3:)  shll    %cl,%eax        // %eax um 32-i Bits nach links shiften
996             popl    %ebx            // %ebx zurück
997             popl    %edi            // %edi zurück
998             popl    %esi            // %esi zurück
999             ret
1000 
1001 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
1002             ALIGN
1003             DECLARE_FUNCTION(mulusmall_loop_down)
1004 C(mulusmall_loop_down:)
1005             pushl   %ebp            // %ebp retten
1006             pushl   %edi            // %edi retten
1007             pushl   %ebx            // %ebx retten
1008             movl    16(%esp),%ebx   // %ebx = digit
1009             movl    20(%esp),%edi   // %edi = ptr
1010             movl    24(%esp),%ecx   // %ecx = len
1011             movl    28(%esp),%ebp   // %ebp = carry := newdigit
1012             movl    %ecx,%eax
1013             negl    %eax            // %eax = -len
1014             jz      L(msld2)
1015             leal    -4(%edi,%eax,4),%edi // %edi = &ptr[-1-len]
1016             nop ; nop ; nop
1017 L(msld1:)     movl    (%edi,%ecx,4),%eax // *ptr
1018               mull    %ebx               // %edx|%eax := digit * *ptr
1019               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1020               movl    $0,%ebp
1021               adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
1022               movl    %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen
1023               decl    %ecx               // count--, ptr--
1024               jnz     L(msld1)
1025 L(msld2:)   movl    %ebp,%eax       // Ergebnis := letzter Übertrag
1026             popl    %ebx            // %ebx zurück
1027             popl    %edi            // %edi zurück
1028             popl    %ebp            // %ebp zurück
1029             ret
1030 
1031 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1032             ALIGN
1033             DECLARE_FUNCTION(mulu_loop_down)
1034 C(mulu_loop_down:)
1035             pushl   %ebp            // %ebp retten
1036             pushl   %edi            // %edi retten
1037             pushl   %esi            // %esi retten
1038             pushl   %ebx            // %ebx retten
1039             movl    20(%esp),%ebx   // %ebx = digit
1040             movl    24(%esp),%esi   // %esi = sourceptr
1041             movl    28(%esp),%edi   // %edi = destptr
1042             movl    32(%esp),%ecx   // %ecx = len
1043             movl    %ecx,%eax
1044             notl    %eax            // %eax = -1-len
1045             leal    (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len]
1046             leal    (%edi,%eax,4),%edi // %edi = &destptr[-1-len]
1047             xorl    %ebp,%ebp       // %epb = carry := 0
1048 L(muld1:)     movl    (%esi,%ecx,4),%eax // *sourceptr
1049               mull    %ebx               // %edx|%eax := digit * *sourceptr
1050               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1051               movl    $0,%ebp
1052               adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
1053               movl    %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen
1054               decl    %ecx               // count--, sourceptr--, destptr--
1055               jnz     L(muld1)
1056             movl    %ebp,(%edi)     // letzten Übertrag ablegen
1057             popl    %ebx            // %ebx zurück
1058             popl    %esi            // %esi zurück
1059             popl    %edi            // %edi zurück
1060             popl    %ebp            // %ebp zurück
1061             ret
1062 
1063 // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1064             ALIGN
1065             DECLARE_FUNCTION(muluadd_loop_down)
1066 C(muluadd_loop_down:)
1067             pushl   %ebp            // %ebp retten
1068             pushl   %edi            // %edi retten
1069             pushl   %esi            // %esi retten
1070             pushl   %ebx            // %ebx retten
1071             movl    20(%esp),%ebx   // %ebx = digit
1072             movl    24(%esp),%esi   // %esi = sourceptr
1073             movl    28(%esp),%edi   // %edi = destptr
1074             movl    32(%esp),%ecx   // %ecx = len
1075             movl    %ecx,%eax
1076             notl    %eax            // %eax = -1-len
1077             leal    (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len]
1078             leal    (%edi,%eax,4),%edi // %edi = &destptr[-1-len]
1079             xorl    %ebp,%ebp       // %epb = carry := 0
1080 L(muald1:)    movl    (%esi,%ecx,4),%eax // *sourceptr
1081               mull    %ebx               // %edx|%eax := digit * *sourceptr
1082               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1083               movl    $0,%ebp
1084               adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
1085               addl    %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren
1086               adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
1087               decl    %ecx               // count--, sourceptr--, destptr--
1088               jnz     L(muald1)
1089             movl    %ebp,%eax       // Ergebnis := letzter Übertrag
1090             popl    %ebx            // %ebx zurück
1091             popl    %esi            // %esi zurück
1092             popl    %edi            // %edi zurück
1093             popl    %ebp            // %ebp zurück
1094             ret
1095 
1096 // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1097             ALIGN
1098             DECLARE_FUNCTION(mulusub_loop_down)
1099 C(mulusub_loop_down:)
1100             pushl   %ebp            // %ebp retten
1101             pushl   %edi            // %edi retten
1102             pushl   %esi            // %esi retten
1103             pushl   %ebx            // %ebx retten
1104             movl    20(%esp),%ebx   // %ebx = digit
1105             movl    24(%esp),%esi   // %esi = sourceptr
1106             movl    28(%esp),%edi   // %edi = destptr
1107             movl    32(%esp),%ecx   // %ecx = len
1108             movl    %ecx,%eax
1109             notl    %eax            // %eax = -1-len
1110             leal    (%esi,%eax,4),%esi // %esi = &sourceptr[-1-len]
1111             leal    (%edi,%eax,4),%edi // %edi = &destptr[-1-len]
1112             xorl    %ebp,%ebp       // %epb = carry := 0
1113 L(musld1:)    movl    (%esi,%ecx,4),%eax // *sourceptr
1114               mull    %ebx               // %edx|%eax := digit * *sourceptr
1115               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1116               movl    $0,%ebp
1117               adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
1118               subl    %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren
1119               adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
1120               decl    %ecx               // count--, sourceptr--, destptr--
1121               jnz     L(musld1)
1122             movl    %ebp,%eax       // Ergebnis := letzter Übertrag
1123             popl    %ebx            // %ebx zurück
1124             popl    %esi            // %esi zurück
1125             popl    %edi            // %edi zurück
1126             popl    %ebp            // %ebp zurück
1127             ret
1128 
1129 // extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
1130             ALIGN
1131             DECLARE_FUNCTION(divu_loop_up)
1132 C(divu_loop_up:)
1133             pushl   %edi            // %edi retten
1134             pushl   %ebx            // %ebx retten
1135             movl    12(%esp),%ebx   // %ebx = digit
1136             movl    16(%esp),%edi   // %edi = ptr
1137             movl    20(%esp),%ecx   // %ecx = len
1138             xorl    %edx,%edx       // %edx = Rest := 0
1139             jecxz   L(dlu2)         // %ecx = 0 ?
1140 L(dlu1:)      movl    (%edi),%eax     // nächstes Digit *ptr
1141               divl    %ebx            // Division von %edx|%eax durch %ebx
1142               movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
1143               leal    4(%edi),%edi    // ptr++
1144               decl    %ecx
1145               jnz     L(dlu1)
1146 L(dlu2:)    movl    %edx,%eax       // Ergebnis := letzter Rest
1147             popl    %ebx            // %ebx zurück
1148             popl    %edi            // %edi zurück
1149             ret
1150 
1151 // extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1152             ALIGN
1153             DECLARE_FUNCTION(divucopy_loop_up)
1154 C(divucopy_loop_up:)
1155             pushl   %edi            // %edi retten
1156             pushl   %esi            // %esi retten
1157             pushl   %ebx            // %ebx retten
1158             movl    16(%esp),%ebx   // %ebx = digit
1159             movl    20(%esp),%esi   // %esi = sourceptr
1160             movl    24(%esp),%edi   // %edi = destptr
1161             movl    28(%esp),%ecx   // %ecx = len
1162             xorl    %edx,%edx       // %edx = Rest := 0
1163             jecxz   L(dclu2)        // %ecx = 0 ?
1164             subl    %edi,%esi
1165 L(dclu1:)     movl    (%esi,%edi),%eax // nächstes Digit *ptr
1166               divl    %ebx            // Division von %edx|%eax durch %ebx
1167               movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
1168               leal    4(%edi),%edi    // sourceptr++, destptr++
1169               decl    %ecx
1170               jnz     L(dclu1)
1171 L(dclu2:)   movl    %edx,%eax       // Ergebnis := letzter Rest
1172             popl    %ebx            // %ebx zurück
1173             popl    %esi            // %esi zurück
1174             popl    %edi            // %edi zurück
1175             ret
1176 
1177 #endif
1178 
1179 #if !CL_DS_BIG_ENDIAN_P
1180 
1181 // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
1182             ALIGN
1183             DECLARE_FUNCTION(or_loop_down)
1184 C(or_loop_down:)
1185             pushl   %esi            // %esi retten
1186             movl    8(%esp),%edx    // %edx = xptr
1187             movl    12(%esp),%esi   // %esi = yptr
1188             movl    16(%esp),%ecx   // %ecx = count
1189             subl    %edx,%esi
1190             jecxz   L(old2)         // %ecx = 0 ?
1191 L(old1:)      leal    -4(%edx),%edx    // xptr--, yptr--
1192               movl    (%edx,%esi),%eax // *yptr
1193               orl     %eax,(%edx)      // *xptr |= ...
1194               decl    %ecx
1195               jnz     L(old1)
1196 L(old2:)    popl    %esi            // %esi zurück
1197             ret
1198 
1199 // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1200             ALIGN
1201             DECLARE_FUNCTION(xor_loop_down)
1202 C(xor_loop_down:)
1203             pushl   %esi            // %esi retten
1204             movl    8(%esp),%edx    // %edx = xptr
1205             movl    12(%esp),%esi   // %esi = yptr
1206             movl    16(%esp),%ecx   // %ecx = count
1207             subl    %edx,%esi
1208             jecxz   L(xld2)         // %ecx = 0 ?
1209 L(xld1:)      leal    -4(%edx),%edx    // xptr--, yptr--
1210               movl    (%edx,%esi),%eax // *yptr
1211               xorl    %eax,(%edx)      // *xptr ^= ...
1212               decl    %ecx
1213               jnz     L(xld1)
1214 L(xld2:)    popl    %esi            // %esi zurück
1215             ret
1216 
1217 // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
1218             ALIGN
1219             DECLARE_FUNCTION(and_loop_down)
1220 C(and_loop_down:)
1221             pushl   %esi            // %esi retten
1222             movl    8(%esp),%edx    // %edx = xptr
1223             movl    12(%esp),%esi   // %esi = yptr
1224             movl    16(%esp),%ecx   // %ecx = count
1225             subl    %edx,%esi
1226             jecxz   L(ald2)         // %ecx = 0 ?
1227 L(ald1:)      leal    -4(%edx),%edx    // xptr--, yptr--
1228               movl    (%edx,%esi),%eax // *yptr
1229               andl    %eax,(%edx)      // *xptr &= ...
1230               decl    %ecx
1231               jnz     L(ald1)
1232 L(ald2:)    popl    %esi            // %esi zurück
1233             ret
1234 
1235 // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
1236             ALIGN
1237             DECLARE_FUNCTION(eqv_loop_down)
1238 C(eqv_loop_down:)
1239             pushl   %esi            // %esi retten
1240             movl    8(%esp),%edx    // %edx = xptr
1241             movl    12(%esp),%esi   // %esi = yptr
1242             movl    16(%esp),%ecx   // %ecx = count
1243             subl    %edx,%esi
1244             jecxz   L(eld2)         // %ecx = 0 ?
1245 L(eld1:)      leal    -4(%edx),%edx    // xptr--, yptr--
1246               movl    (%edx),%eax      // *xptr
1247               xorl    (%edx,%esi),%eax // ^ *yptr
1248               notl    %eax             // ~(...)
1249               movl    %eax,(%edx)      // =: *xptr
1250               decl    %ecx
1251               jnz     L(eld1)
1252 L(eld2:)    popl    %esi            // %esi zurück
1253             ret
1254 
1255 // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
1256             ALIGN
1257             DECLARE_FUNCTION(nand_loop_down)
1258 C(nand_loop_down:)
1259             pushl   %esi            // %esi retten
1260             movl    8(%esp),%edx    // %edx = xptr
1261             movl    12(%esp),%esi   // %esi = yptr
1262             movl    16(%esp),%ecx   // %ecx = count
1263             subl    %edx,%esi
1264             jecxz   L(nald2)        // %ecx = 0 ?
1265 L(nald1:)     leal    -4(%edx),%edx    // xptr--, yptr--
1266               movl    (%edx),%eax      // *xptr
1267               andl    (%edx,%esi),%eax // & *yptr
1268               notl    %eax             // ~(...)
1269               movl    %eax,(%edx)      // =: *xptr
1270               decl    %ecx
1271               jnz     L(nald1)
1272 L(nald2:)   popl    %esi            // %esi zurück
1273             ret
1274 
1275 // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
1276             ALIGN
1277             DECLARE_FUNCTION(nor_loop_down)
1278 C(nor_loop_down:)
1279             pushl   %esi            // %esi retten
1280             movl    8(%esp),%edx    // %edx = xptr
1281             movl    12(%esp),%esi   // %esi = yptr
1282             movl    16(%esp),%ecx   // %ecx = count
1283             subl    %edx,%esi
1284             jecxz   L(nold2)        // %ecx = 0 ?
1285 L(nold1:)     leal    -4(%edx),%edx    // xptr--, yptr--
1286               movl    (%edx),%eax      // *xptr
1287               orl     (%edx,%esi),%eax // | *yptr
1288               notl    %eax             // ~(...)
1289               movl    %eax,(%edx)      // =: *xptr
1290               decl    %ecx
1291               jnz     L(nold1)
1292 L(nold2:)   popl    %esi            // %esi zurück
1293             ret
1294 
1295 // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1296             ALIGN
1297             DECLARE_FUNCTION(andc2_loop_down)
1298 C(andc2_loop_down:)
1299             pushl   %esi            // %esi retten
1300             movl    8(%esp),%edx    // %edx = xptr
1301             movl    12(%esp),%esi   // %esi = yptr
1302             movl    16(%esp),%ecx   // %ecx = count
1303             subl    %edx,%esi
1304             jecxz   L(acld2)        // %ecx = 0 ?
1305 L(acld1:)     leal    -4(%edx),%edx    // xptr--, yptr--
1306               movl    (%edx,%esi),%eax // *yptr
1307               notl    %eax             // ~ *yptr
1308               andl    %eax,(%edx)      // *xptr &= ...
1309               decl    %ecx
1310               jnz     L(acld1)
1311 L(acld2:)   popl    %esi            // %esi zurück
1312             ret
1313 
1314 // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
1315             ALIGN
1316             DECLARE_FUNCTION(orc2_loop_down)
1317 C(orc2_loop_down:)
1318             pushl   %esi            // %esi retten
1319             movl    8(%esp),%edx    // %edx = xptr
1320             movl    12(%esp),%esi   // %esi = yptr
1321             movl    16(%esp),%ecx   // %ecx = count
1322             subl    %edx,%esi
1323             jecxz   L(ocld2)        // %ecx = 0 ?
1324 L(ocld1:)     leal    -4(%edx),%edx    // xptr--, yptr--
1325               movl    (%edx,%esi),%eax // *yptr
1326               notl    %eax             // ~ *yptr
1327               orl     %eax,(%edx)      // *xptr |= ...
1328               decl    %ecx
1329               jnz     L(ocld1)
1330 L(ocld2:)   popl    %esi            // %esi zurück
1331             ret
1332 
1333 // extern void not_loop_down (uintD* xptr, uintC count);
1334             ALIGN
1335             DECLARE_FUNCTION(not_loop_down)
1336 C(not_loop_down:)
1337             movl    4(%esp),%edx    // %edx = xptr
1338             movl    8(%esp),%ecx    // %ecx = count
1339             jecxz   L(nld2)         // %ecx = 0 ?
1340             nop ; nop ; nop ; nop ; nop ; nop
1341 L(nld1:)      leal    -4(%edx),%edx    // xptr--
1342               notl    (%edx)           // ~= *xptr
1343               decl    %ecx
1344               jnz     L(nld1)
1345 L(nld2:)    ret
1346 
1347 // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
1348             ALIGN
1349             DECLARE_FUNCTION(and_test_loop_down)
1350 C(and_test_loop_down:)
1351             pushl   %esi            // %esi retten
1352             movl    8(%esp),%edx    // %edx = xptr
1353             movl    12(%esp),%esi   // %esi = yptr
1354             movl    16(%esp),%ecx   // %ecx = count
1355             jecxz   L(atld2)        // %ecx = 0 ?
1356             subl    %edx,%esi
1357 L(atld1:)     leal    -4(%edx),%edx    // xptr--, yptr--
1358               movl    (%edx,%esi),%eax // *yptr
1359               andl    (%edx),%eax      // *xptr & ...
1360               jnz     L(atld3)
1361               decl    %ecx
1362               jnz     L(atld1)
1363 L(atld2:)   xorl    %eax,%eax       // Ergebnis 0
1364             popl    %esi            // %esi zurück
1365             ret
1366 L(atld3:)   movl    $1,%eax         // Ergebnis 1 (nicht irgendwas /=0 !)
1367             popl    %esi            // %esi zurück
1368             ret
1369 
1370 // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
1371             ALIGN
1372             DECLARE_FUNCTION(compare_loop_down)
1373 C(compare_loop_down:)
1374             movl    %esi,%edx       // %esi retten
1375             movl    %edi,%eax       // %edi retten
1376             movl    4(%esp),%esi    // %esi = xptr
1377             movl    8(%esp),%edi    // %edi = yptr
1378             movl    12(%esp),%ecx   // %ecx = count
1379             leal    -4(%esi),%esi
1380             leal    -4(%edi),%edi
1381             cmpl    %ecx,%ecx       // initialize flags for the case %ecx is 0
1382             dir1start
1383             repz                    // Falls %ecx > 0:
1384               cmpsl                 // %ecx mal aufwärts (%edi) und (%esi) vergleichen
1385                                     // und weiterschleifen, falls Z, d.h. (%edi)=(%esi).
1386             dir1end
1387             // Flags -> Ergebnis:
1388             // Z,NC -> bis zum Schluß (%esi)-(%edi) = 0 -> x=y -> Ergebnis 0
1389             // NZ,C -> schließlich (%esi)-(%edi) < 0 -> x<y -> Ergebnis -1
1390             // NZ,NC -> schließlich (%esi)-(%edi) > 0 -> x>y -> Ergebnis +1
1391             movl    %eax,%edi       // %edi zurück
1392             movl    %edx,%esi       // %esi zurück
1393             jbe     L(cmld1)        // "be" = Z oder C
1394             movl    $1,%eax         // Ergebnis +1
1395             ret
1396 L(cmld1:)   sbbl    %eax,%eax       // Ergebnis -1 (falls C) oder 0 (falls NC)
1397             ret
1398 
1399 // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1400             ALIGN
1401             DECLARE_FUNCTION(add_loop_up)
1402 C(add_loop_up:)
1403             pushl   %esi            // %esi retten
1404             pushl   %edi            // %edi retten
1405             movl    12(%esp),%edx   // %edx = sourceptr1
1406             movl    16(%esp),%esi   // %esi = sourceptr2
1407             movl    20(%esp),%edi   // %edi = destptr
1408             movl    24(%esp),%ecx   // %ecx = count
1409             subl    %edi,%edx
1410             subl    %edi,%esi
1411             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
1412             jz      L(alu2)
1413 L(alu1:)      movl    (%edx,%edi),%eax // *sourceptr1
1414               adcl    (%esi,%edi),%eax // + *sourceptr2 + carry
1415               movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
1416               leal    4(%edi),%edi    // sourceptr1++, sourceptr2++, destptr++
1417               decl    %ecx
1418               jnz     L(alu1)
1419 L(alu2:)    sbbl    %eax,%eax      // Ergebnis := - Carry
1420             popl    %edi           // %edi zurück
1421             popl    %esi           // %esi zurück
1422             ret
1423 
1424 // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
1425             ALIGN
1426             DECLARE_FUNCTION(addto_loop_up)
1427 C(addto_loop_up:)
1428             pushl   %edi            // %edi retten
1429             movl    8(%esp),%edx    // %edx = sourceptr
1430             movl    12(%esp),%edi   // %edi = destptr
1431             movl    16(%esp),%ecx   // %ecx = count
1432             subl    %edi,%edx
1433             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
1434             jz      L(atlu2)
1435 L(atlu1:)     movl    (%edx,%edi),%eax // *sourceptr
1436               adcl    %eax,(%edi)     // + *destptr + carry =: *destptr, neuer Carry
1437               leal    4(%edi),%edi    // sourceptr++, destptr++
1438               decl    %ecx
1439               jnz     L(atlu1)
1440 L(atlu2:)   sbbl    %eax,%eax       // Ergebnis := - Carry
1441             popl    %edi            // %edi zurück
1442             ret
1443 
1444 // extern uintD inc_loop_up (uintD* ptr, uintC count);
1445             ALIGN
1446             DECLARE_FUNCTION(inc_loop_up)
1447 C(inc_loop_up:)
1448             movl    4(%esp),%edx    // %edx = ptr
1449             movl    8(%esp),%ecx    // %ecx = count
1450             jecxz   L(ilu2)         // %ecx = 0 ?
1451 L(ilu1:)      addl    $1,(%edx)       // (*ptr)++
1452               jnc     L(ilu3)         // kein Carry -> fertig
1453               leal    4(%edx),%edx
1454               decl    %ecx
1455               jnz     L(ilu1)
1456 L(ilu2:)    movl    $1,%eax         // Ergebnis := 1
1457             ret
1458 L(ilu3:)    xorl    %eax,%eax       // Ergebnis := 0
1459             ret
1460 
1461 // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1462             ALIGN
1463             DECLARE_FUNCTION(sub_loop_up)
1464 C(sub_loop_up:)
1465             pushl   %esi            // %esi retten
1466             pushl   %edi            // %edi retten
1467             movl    12(%esp),%edx   // %edx = sourceptr1
1468             movl    16(%esp),%esi   // %esi = sourceptr2
1469             movl    20(%esp),%edi   // %edi = destptr
1470             movl    24(%esp),%ecx   // %ecx = count
1471             subl    %edi,%edx
1472             subl    %edi,%esi
1473             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
1474             jz      L(slu2)
1475 L(slu1:)      movl    (%edx,%edi),%eax // *sourceptr1
1476               sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
1477               movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
1478               leal    4(%edi),%edi    // sourceptr1++, sourceptr2++, destptr++
1479               decl    %ecx
1480               jnz     L(slu1)
1481 L(slu2:)    sbbl    %eax,%eax      // Ergebnis := - Carry
1482             popl    %edi           // %edi zurück
1483             popl    %esi           // %esi zurück
1484             ret
1485 
1486 // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
1487             ALIGN
1488             DECLARE_FUNCTION(subx_loop_up)
1489 C(subx_loop_up:)
1490             pushl   %esi            // %esi retten
1491             pushl   %edi            // %edi retten
1492             movl    12(%esp),%edx   // %edx = sourceptr1
1493             movl    16(%esp),%esi   // %esi = sourceptr2
1494             movl    20(%esp),%edi   // %edi = destptr
1495             movl    24(%esp),%ecx   // %ecx = count
1496             jecxz   L(sxlu2)        // %ecx = 0 ?
1497             subl    %edi,%edx
1498             subl    %edi,%esi
1499             movl    28(%esp),%eax   // carry, 0 oder -1
1500             addl    %eax,%eax       // Bit 31 davon in den Carry
1501             nop ; nop
1502 L(sxlu1:)     movl    (%edx,%edi),%eax // *sourceptr1
1503               sbbl    (%esi,%edi),%eax // - *sourceptr2 - carry
1504               movl    %eax,(%edi)     // =: *destptr, neuen Carry behalten
1505               leal    4(%edi),%edi    // sourceptr1++, sourceptr2++, destptr++
1506               decl    %ecx
1507               jnz     L(sxlu1)
1508             sbbl    %eax,%eax      // Ergebnis := - Carry
1509             popl    %edi           // %edi zurück
1510             popl    %esi           // %esi zurück
1511             ret
1512 L(sxlu2:)   movl    28(%esp),%eax  // Ergebnis := carry
1513             popl    %edi           // %edi zurück
1514             popl    %esi           // %esi zurück
1515             ret
1516 
1517 // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
1518             ALIGN
1519             DECLARE_FUNCTION(subfrom_loop_up)
1520 C(subfrom_loop_up:)
1521             pushl   %edi            // %edi retten
1522             movl    8(%esp),%edx    // %edx = sourceptr
1523             movl    12(%esp),%edi   // %edi = destptr
1524             movl    16(%esp),%ecx   // %ecx = count
1525             subl    %edi,%edx
1526             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
1527             jz      L(sflu2)
1528 L(sflu1:)     movl    (%edx,%edi),%eax // *sourceptr
1529               sbbl    %eax,(%edi)     // *destptr - *sourceptr - carry =: *destptr, neuer Carry
1530               leal    4(%edi),%edi    // sourceptr++, destptr++
1531               decl    %ecx
1532               jnz     L(sflu1)
1533 L(sflu2:)   sbbl    %eax,%eax       // Ergebnis := - Carry
1534             popl    %edi            // %edi zurück
1535             ret
1536 
1537 // extern uintD dec_loop_up (uintD* ptr, uintC count);
1538             ALIGN
1539             DECLARE_FUNCTION(dec_loop_up)
1540 C(dec_loop_up:)
1541             movl    4(%esp),%edx    // %edx = ptr
1542             movl    8(%esp),%ecx    // %ecx = count
1543             jecxz   L(dlu2)         // %ecx = 0 ?
1544 L(dlu1:)      subl    $1,(%edx)       // (*ptr)--
1545               jnc     L(dlu3)         // kein Carry -> fertig
1546               leal    4(%edx),%edx
1547               decl    %ecx
1548               jnz     L(dlu1)
1549 L(dlu2:)    movl    $-1,%eax        // Ergebnis := -1
1550             ret
1551 L(dlu3:)    xorl    %eax,%eax       // Ergebnis := 0
1552             ret
1553 
1554 // extern uintD neg_loop_up (uintD* ptr, uintC count);
1555             ALIGN
1556             DECLARE_FUNCTION(neg_loop_up)
1557 C(neg_loop_up:)
1558             movl    4(%esp),%edx    // %edx = ptr
1559             movl    8(%esp),%ecx    // %ecx = count
1560             // erstes Digit /=0 suchen:
1561             jecxz   L(nlu2)         // %ecx = 0 ?
1562 L(nlu1:)      negl    (%edx)
1563               jnz     L(nlu3)
1564               leal    4(%edx),%edx
1565               decl    %ecx
1566               jnz     L(nlu1)
1567 L(nlu2:)    xorl    %eax,%eax       // Ergebnis := 0
1568             ret
1569             nop ; nop ; nop ; nop ; nop ; nop
1570 L(nlu3:)    // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
1571             // alle anderen Digits invertieren:
1572             decl    %ecx
1573             jz      L(nlu5)
1574 L(nlu4:)      leal    4(%edx),%edx
1575               notl    (%edx)
1576               decl    %ecx
1577               jnz     L(nlu4)
1578 L(nlu5:)    movl    $-1,%eax        // Ergebnis := -1
1579             ret
1580 
1581 // extern uintD shift1left_loop_up (uintD* ptr, uintC count);
1582             ALIGN
1583             DECLARE_FUNCTION(shift1left_loop_up)
1584 C(shift1left_loop_up:)
1585             movl    4(%esp),%edx    // %edx = ptr
1586             movl    8(%esp),%ecx    // %ecx = count
1587             orl     %ecx,%ecx       // %ecx = 0 ?, Carry löschen
1588             jz      L(s1llu2)
1589             nop ; nop ; nop ; nop
1590 L(s1llu1:)    rcll    $1,(%edx)       // *ptr und Carry um 1 Bit links rotieren
1591               leal    4(%edx),%edx    // ptr++
1592               decl    %ecx
1593               jnz     L(s1llu1)
1594 L(s1llu2:)  sbbl    %eax,%eax       // Ergebnis := - Carry
1595             ret
1596 
1597 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
1598             ALIGN
1599             DECLARE_FUNCTION(shiftleft_loop_up)
1600 C(shiftleft_loop_up:)
1601             pushl   %edi            // %edi retten
1602             pushl   %ebx            // %ebx retten
1603             movl    12(%esp),%edi   // %edi = ptr
1604             movl    16(%esp),%edx   // %edx = count
1605             movb    20(%esp),%cl    // %cl = i
1606             orl     %edx,%edx       // count = 0 ?
1607             jz      L(sllu4)
1608             // erstes Digit shiften:
1609             movl    (%edi),%eax     // Digit in %eax halten
1610             movl    %eax,%ebx       // und in %ebx rechnen:
1611             shll    %cl,%ebx        // um i Bits links shiften
1612             orl     24(%esp),%ebx   // und die unteren i Bits eintragen
1613             movl    %ebx,(%edi)     // und wieder ablegen
1614             leal    4(%edi),%edi
1615             // Letztes Digit in %eax.
1616             decl    %edx
1617             jz      L(sllu2)
1618             nop ; nop ; nop ; nop
1619 L(sllu1:)     // weiteres Digit shiften:
1620               movl    (%edi),%ebx
1621               shldl   shcl %eax,(%edi) // (%edi) um %cl=i Bits links shiften, %eax von rechts reinshiften
1622               leal    4(%edi),%edi
1623               // Letztes Digit in %ebx.
1624               decl    %edx
1625               jz      L(sllu3)
1626               // weiteres Digit shiften:
1627               movl    (%edi),%eax
1628               shldl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits links shiften, %ebx von rechts reinshiften
1629               leal    4(%edi),%edi
1630               // Letztes Digit in %eax.
1631               decl    %edx
1632               jnz     L(sllu1)
1633 L(sllu2:)   movl    %eax,%ebx
1634 L(sllu3:)   xorl    %eax,%eax       // %eax := 0
1635             shldl   shcl %ebx,%eax  // %eax := höchste %cl=i Bits von %ebx
1636             popl    %ebx            // %ebx zurück
1637             popl    %edi            // %edi zurück
1638             ret
1639 L(sllu4:)   movl    24(%esp),%eax   // %eax := carry
1640             popl    %ebx            // %ebx zurück
1641             popl    %edi            // %edi zurück
1642             ret
1643 
1644 #endif
1645 
1646 // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
1647             ALIGN
1648             DECLARE_FUNCTION(shiftleftcopy_loop_up)
1649 C(shiftleftcopy_loop_up:)
1650             pushl   %esi            // %esi retten
1651             pushl   %edi            // %edi retten
1652             pushl   %ebx            // %ebx retten
1653             movl    16(%esp),%esi   // %esi = sourceptr
1654             movl    20(%esp),%edi   // %edi = destptr
1655             movl    24(%esp),%edx   // count
1656             movb    28(%esp),%cl    // i
1657             orl     %edx,%edx       // count = 0 ?
1658             jz      L(slclu4)
1659             subl    %edi,%esi
1660             // erstes Digit shiften:
1661             movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
1662             movl    %ebx,%eax       // und in %eax rechnen:
1663             shll    %cl,%eax        // um i Bits links shiften, rechts Nullen rein
1664             movl    %eax,(%edi)     // und als *destptr ablegen
1665             leal    4(%edi),%edi    // sourceptr++, destptr++
1666             // Letztes Digit in %ebx.
1667             negb    %cl             // 32-i
1668             decl    %edx
1669             jz      L(slclu2)
1670 L(slclu1:)    // weiteres Digit shiften:
1671               movl    (%edi,%esi),%eax // nächstes Digit nach %eax
1672               shrdl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften
1673               movl    %ebx,(%edi)     // %ebx als *destptr ablegen
1674               leal    4(%edi),%edi    // sourceptr++, destptr++
1675               // Letztes Digit in %eax.
1676               decl    %edx
1677               jz      L(slclu3)
1678               // weiteres Digit shiften:
1679               movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
1680               shrdl   shcl %ebx,%eax  // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften
1681               movl    %eax,(%edi)     // %eax als *destptr ablegen
1682               leal    4(%edi),%edi    // sourceptr++, destptr++
1683               // Letztes Digit in %ebx.
1684               decl    %edx
1685               jnz     L(slclu1)
1686 L(slclu2:)  movl    %ebx,%eax
1687 L(slclu3:)  shrl    %cl,%eax        // %eax um 32-i Bits nach rechts shiften
1688             popl    %ebx            // %ebx zurück
1689             popl    %edi            // %edi zurück
1690             popl    %esi            // %esi zurück
1691             ret
1692 L(slclu4:)  xorl    %eax,%eax       // %eax := 0
1693             popl    %ebx            // %ebx zurück
1694             popl    %edi            // %edi zurück
1695             popl    %esi            // %esi zurück
1696             ret
1697 
1698 #if !CL_DS_BIG_ENDIAN_P
1699 
1700 // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
1701             ALIGN
1702             DECLARE_FUNCTION(shift1right_loop_down)
1703 C(shift1right_loop_down:)
1704             movl    4(%esp),%edx    // %edx = ptr
1705             movl    8(%esp),%ecx    // %ecx = count
1706             movl    12(%esp),%eax   // %eax = carry (0 oder -1)
1707             jecxz   L(s1rlu3)       // %ecx = 0 ?
1708             addl    %eax,%eax       // Carry := Bit 31 von carry
1709 L(s1rlu1:)    leal    -4(%edx),%edx   // ptr--
1710               rcrl    $1,(%edx)       // *ptr und Carry um 1 Bit rechts rotieren
1711               decl    %ecx
1712               jnz     L(s1rlu1)
1713 L(s1rlu2:)  sbbl    %eax,%eax       // Ergebnis := - Carry
1714 L(s1rlu3:)  ret
1715 
1716 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
1717             ALIGN
1718             DECLARE_FUNCTION(shiftright_loop_down)
1719 C(shiftright_loop_down:)
1720             pushl   %edi            // %edi retten
1721             pushl   %ebx            // %ebx retten
1722             movl    12(%esp),%edi   // %edi = ptr
1723             movl    16(%esp),%edx   // %edx = count
1724             movb    20(%esp),%cl    // %cl = i
1725             orl     %edx,%edx       // count = 0 ?
1726             jz      L(srld4)
1727             // erstes Digit shiften:
1728             leal    -4(%edi),%edi
1729             movl    (%edi),%eax     // Digit in %eax halten
1730             movl    %eax,%ebx       // und in %ebx rechnen:
1731             shrl    %cl,%ebx        // um i Bits rechts shiften
1732             movl    %ebx,(%edi)     // und wieder ablegen
1733             // Letztes Digit in %eax.
1734             decl    %edx
1735             jz      L(srld2)
1736 L(srld1:)     // weiteres Digit shiften:
1737               leal    -4(%edi),%edi
1738               movl    (%edi),%ebx
1739               shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
1740               // Letztes Digit in %ebx.
1741               decl    %edx
1742               jz      L(srld3)
1743               // weiteres Digit shiften:
1744               leal    -4(%edi),%edi
1745               movl    (%edi),%eax
1746               shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
1747               // Letztes Digit in %eax.
1748               decl    %edx
1749               jnz     L(srld1)
1750 L(srld2:)   movl    %eax,%ebx
1751 L(srld3:)   xorl    %eax,%eax       // %eax := 0
1752             shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
1753             popl    %ebx            // %ebx zurück
1754             popl    %edi            // %edi zurück
1755             ret
1756 L(srld4:)   xorl    %eax,%eax       // %eax := 0
1757             popl    %ebx            // %ebx zurück
1758             popl    %edi            // %edi zurück
1759             ret
1760 
1761 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
1762             ALIGN
1763             DECLARE_FUNCTION(shiftrightsigned_loop_down)
1764 C(shiftrightsigned_loop_down:)
1765             pushl   %edi            // %edi retten
1766             pushl   %ebx            // %ebx retten
1767             movl    12(%esp),%edi   // %edi = ptr
1768             movl    16(%esp),%edx   // %edx = count
1769             movb    20(%esp),%cl    // %cl = i
1770             // erstes Digit shiften:
1771             leal    -4(%edi),%edi
1772             movl    (%edi),%eax     // Digit in %eax halten
1773             movl    %eax,%ebx       // und in %ebx rechnen:
1774             sarl    %cl,%ebx        // um i Bits rechts shiften, Vorzeichen vervielfachen
1775             movl    %ebx,(%edi)     // und wieder ablegen
1776             // Letztes Digit in %eax.
1777             decl    %edx
1778             jz      L(srsld2)
1779             nop ; nop ; nop ; nop
1780 L(srsld1:)    // weiteres Digit shiften:
1781               leal    -4(%edi),%edi
1782               movl    (%edi),%ebx
1783               shrdl   shcl %eax,(%edi) // (%edi) um %cl=i Bits rechts shiften, %eax von links reinshiften
1784               // Letztes Digit in %ebx.
1785               decl    %edx
1786               jz      L(srsld3)
1787               // weiteres Digit shiften:
1788               leal    -4(%edi),%edi
1789               movl    (%edi),%eax
1790               shrdl   shcl %ebx,(%edi) // (%edi) um %cl=i Bits rechts shiften, %ebx von links reinshiften
1791               // Letztes Digit in %eax.
1792               decl    %edx
1793               jnz     L(srsld1)
1794 L(srsld2:)  movl    %eax,%ebx
1795 L(srsld3:)  xorl    %eax,%eax       // %eax := 0
1796             shrdl   shcl %ebx,%eax  // %eax := niedrigste %cl=i Bits von %ebx, als Bits 31..32-i
1797             popl    %ebx            // %ebx zurück
1798             popl    %edi            // %edi zurück
1799             ret
1800 
1801 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
1802             ALIGN
1803             DECLARE_FUNCTION(shiftrightcopy_loop_down)
1804 C(shiftrightcopy_loop_down:)
1805             pushl   %esi            // %esi retten
1806             pushl   %edi            // %edi retten
1807             pushl   %ebx            // %ebx retten
1808             movl    16(%esp),%esi   // %esi = sourceptr
1809             movl    20(%esp),%edi   // %edi = destptr
1810             movl    24(%esp),%edx   // count
1811             movb    28(%esp),%cl    // i
1812             negb    %cl             // 32-i
1813             movl    32(%esp),%eax   // %eax = carry
1814             orl     %edx,%edx       // count = 0 ?
1815             jz      L(srclu3)
1816             subl    %edi,%esi
1817             // erstes Digit shiften:
1818             leal    -4(%edi),%edi   // sourceptr--, destptr--
1819             movl    (%edi,%esi),%ebx // *sourceptr in %ebx halten
1820             shldl   shcl %ebx,%eax  // carry um %cl=32-i Bits links shiften, dabei *sourceptr rein
1821             movl    %eax,(%edi)     // und als *destptr ablegen
1822             // Letztes Digit in %ebx.
1823             decl    %edx
1824             jz      L(srclu2)
1825             nop ; nop ; nop
1826 L(srclu1:)    // weiteres Digit shiften:
1827               leal    -4(%edi),%edi   // sourceptr--, destptr--
1828               movl    (%edi,%esi),%eax // nächstes Digit nach %eax
1829               shldl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits links shiften, %eax von rechts reinshiften
1830               movl    %ebx,(%edi)     // %ebx als *destptr ablegen
1831               // Letztes Digit in %eax.
1832               decl    %edx
1833               jz      L(srclu3)
1834               // weiteres Digit shiften:
1835               leal    -4(%edi),%edi   // sourceptr--, destptr--
1836               movl    (%edi,%esi),%ebx // nächstes Digit nach %ebx
1837               shldl   shcl %ebx,%eax  // %eax um %cl=32-i Bits links shiften, %ebx von rechts reinshiften
1838               movl    %eax,(%edi)     // %eax als *destptr ablegen
1839               // Letztes Digit in %ebx.
1840               decl    %edx
1841               jnz     L(srclu1)
1842 L(srclu2:)  movl    %ebx,%eax
1843 L(srclu3:)  shll    %cl,%eax        // %eax um 32-i Bits nach links shiften
1844             popl    %ebx            // %ebx zurück
1845             popl    %edi            // %edi zurück
1846             popl    %esi            // %esi zurück
1847             ret
1848 
1849 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
1850             ALIGN
1851             DECLARE_FUNCTION(mulusmall_loop_up)
1852 C(mulusmall_loop_up:)
1853             pushl   %ebp            // %ebp retten
1854             pushl   %edi            // %edi retten
1855             pushl   %ebx            // %ebx retten
1856             movl    16(%esp),%ebx   // %ebx = digit
1857             movl    20(%esp),%edi   // %edi = ptr
1858             movl    24(%esp),%ecx   // %ecx = len
1859             movl    28(%esp),%ebp   // %ebp = carry := newdigit
1860             leal    (%edi,%ecx,4),%edi // %edi = &ptr[len]
1861             negl    %ecx            // %ecx = -count
1862             jz      L(mslu2)
1863 L(mslu1:)     movl    (%edi,%ecx,4),%eax // *ptr
1864               mull    %ebx               // %edx|%eax := digit * *ptr
1865               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1866               movl    $0,%ebp
1867               adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
1868               movl    %eax,(%edi,%ecx,4) // Low-Teil als *ptr ablegen
1869               incl    %ecx               // count--, ptr++
1870               jnz     L(mslu1)
1871 L(mslu2:)   movl    %ebp,%eax       // Ergebnis := letzter Übertrag
1872             popl    %ebx            // %ebx zurück
1873             popl    %edi            // %edi zurück
1874             popl    %ebp            // %ebp zurück
1875             ret
1876 
1877 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1878             ALIGN
1879             DECLARE_FUNCTION(mulu_loop_up)
1880 C(mulu_loop_up:)
1881             pushl   %ebp            // %ebp retten
1882             pushl   %edi            // %edi retten
1883             pushl   %esi            // %esi retten
1884             pushl   %ebx            // %ebx retten
1885             movl    20(%esp),%ebx   // %ebx = digit
1886             movl    24(%esp),%esi   // %esi = sourceptr
1887             movl    28(%esp),%edi   // %edi = destptr
1888             movl    32(%esp),%ecx   // %ecx = len
1889             leal    (%esi,%ecx,4),%esi // %esi = &sourceptr[len]
1890             leal    (%edi,%ecx,4),%edi // %edi = &destptr[len]
1891             negl    %ecx            // %ecx = -count
1892             xorl    %ebp,%ebp       // %epb = carry := 0
1893             nop ; nop
1894 L(mulu1:)     movl    (%esi,%ecx,4),%eax // *sourceptr
1895               mull    %ebx               // %edx|%eax := digit * *sourceptr
1896               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1897               movl    $0,%ebp
1898               adcl    %edx,%ebp          // Übertrag zum High-Teil %edx dazu, gibt neuen carry
1899               movl    %eax,(%edi,%ecx,4) // Low-Teil als *destptr ablegen
1900               incl    %ecx               // count--, sourceptr++, destptr++
1901               jnz     L(mulu1)
1902             movl    %ebp,(%edi)     // letzten Übertrag ablegen
1903             popl    %ebx            // %ebx zurück
1904             popl    %esi            // %esi zurück
1905             popl    %edi            // %edi zurück
1906             popl    %ebp            // %ebp zurück
1907             ret
1908 
1909 // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1910             ALIGN
1911             DECLARE_FUNCTION(muluadd_loop_up)
1912 C(muluadd_loop_up:)
1913             pushl   %ebp            // %ebp retten
1914             pushl   %edi            // %edi retten
1915             pushl   %esi            // %esi retten
1916             pushl   %ebx            // %ebx retten
1917             movl    20(%esp),%ebx   // %ebx = digit
1918             movl    24(%esp),%esi   // %esi = sourceptr
1919             movl    28(%esp),%edi   // %edi = destptr
1920             movl    32(%esp),%ecx   // %ecx = len
1921             leal    (%esi,%ecx,4),%esi // %esi = &sourceptr[len]
1922             leal    (%edi,%ecx,4),%edi // %edi = &destptr[len]
1923             negl    %ecx            // %ecx = -count
1924             xorl    %ebp,%ebp       // %epb = carry := 0
1925             nop ; nop
1926 L(mualu1:)    movl    (%esi,%ecx,4),%eax // *sourceptr
1927               mull    %ebx               // %edx|%eax := digit * *sourceptr
1928               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1929               movl    $0,%ebp
1930               adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
1931               addl    %eax,(%edi,%ecx,4) // Low-Teil zu *destptr addieren
1932               adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
1933               incl    %ecx               // count--, sourceptr++, destptr++
1934               jnz     L(mualu1)
1935             movl    %ebp,%eax       // Ergebnis := letzter Übertrag
1936             popl    %ebx            // %ebx zurück
1937             popl    %esi            // %esi zurück
1938             popl    %edi            // %edi zurück
1939             popl    %ebp            // %ebp zurück
1940             ret
1941 
1942 // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1943             ALIGN
1944             DECLARE_FUNCTION(mulusub_loop_up)
1945 C(mulusub_loop_up:)
1946             pushl   %ebp            // %ebp retten
1947             pushl   %edi            // %edi retten
1948             pushl   %esi            // %esi retten
1949             pushl   %ebx            // %ebx retten
1950             movl    20(%esp),%ebx   // %ebx = digit
1951             movl    24(%esp),%esi   // %esi = sourceptr
1952             movl    28(%esp),%edi   // %edi = destptr
1953             movl    32(%esp),%ecx   // %ecx = len
1954             leal    (%esi,%ecx,4),%esi // %esi = &sourceptr[len]
1955             leal    (%edi,%ecx,4),%edi // %edi = &destptr[len]
1956             negl    %ecx            // %ecx = -count
1957             xorl    %ebp,%ebp       // %epb = carry := 0
1958             nop ; nop
1959 L(muslu1:)    movl    (%esi,%ecx,4),%eax // *sourceptr
1960               mull    %ebx               // %edx|%eax := digit * *sourceptr
1961               addl    %ebp,%eax          // carry und Low-Teil des Produktes addieren
1962               movl    $0,%ebp
1963               adcl    %ebp,%edx          // Übertrag zum High-Teil %edx dazu
1964               subl    %eax,(%edi,%ecx,4) // Low-Teil von *destptr subtrahieren
1965               adcl    %edx,%ebp          // zweiten Übertrag zu %edx addieren, gibt neuen carry
1966               incl    %ecx               // count--, sourceptr++, destptr++
1967               jnz     L(muslu1)
1968             movl    %ebp,%eax       // Ergebnis := letzter Übertrag
1969             popl    %ebx            // %ebx zurück
1970             popl    %esi            // %esi zurück
1971             popl    %edi            // %edi zurück
1972             popl    %ebp            // %ebp zurück
1973             ret
1974 
1975 // extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len);
1976             ALIGN
1977             DECLARE_FUNCTION(divu_loop_down)
1978 C(divu_loop_down:)
1979             pushl   %edi            // %edi retten
1980             pushl   %ebx            // %ebx retten
1981             movl    12(%esp),%ebx   // %ebx = digit
1982             movl    16(%esp),%edi   // %edi = ptr
1983             movl    20(%esp),%ecx   // %ecx = len
1984             xorl    %edx,%edx       // %edx = Rest := 0
1985             jecxz   L(dld2)         // %ecx = 0 ?
1986 L(dld1:)      leal    -4(%edi),%edi   // ptr--
1987               movl    (%edi),%eax     // nächstes Digit *ptr
1988               divl    %ebx            // Division von %edx|%eax durch %ebx
1989               movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
1990               decl    %ecx
1991               jnz     L(dld1)
1992 L(dld2:)    movl    %edx,%eax       // Ergebnis := letzter Rest
1993             popl    %ebx            // %ebx zurück
1994             popl    %edi            // %edi zurück
1995             ret
1996 
1997 // extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
1998             ALIGN
1999             DECLARE_FUNCTION(divucopy_loop_down)
2000 C(divucopy_loop_down:)
2001             pushl   %edi            // %edi retten
2002             pushl   %esi            // %esi retten
2003             pushl   %ebx            // %ebx retten
2004             movl    16(%esp),%ebx   // %ebx = digit
2005             movl    20(%esp),%esi   // %esi = sourceptr
2006             movl    24(%esp),%edi   // %edi = destptr
2007             movl    28(%esp),%ecx   // %ecx = len
2008             xorl    %edx,%edx       // %edx = Rest := 0
2009             jecxz   L(dcld2)        // %ecx = 0 ?
2010             subl    %edi,%esi
2011 L(dcld1:)     leal    -4(%edi),%edi   // sourceptr--, destptr--
2012               movl    (%esi,%edi),%eax // nächstes Digit *ptr
2013               divl    %ebx            // Division von %edx|%eax durch %ebx
2014               movl    %eax,(%edi)     // Quotient %eax ablegen, Rest in %edx behalten
2015               decl    %ecx
2016               jnz     L(dcld1)
2017 L(dcld2:)   movl    %edx,%eax       // Ergebnis := letzter Rest
2018             popl    %ebx            // %ebx zurück
2019             popl    %esi            // %esi zurück
2020             popl    %edi            // %edi zurück
2021             ret
2022 
2023 #endif
2024 
2025 // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
2026             ALIGN
2027             DECLARE_FUNCTION(shiftxor_loop_up)
2028 C(shiftxor_loop_up:)
2029             pushl   %esi            // %esi retten
2030             pushl   %edi            // %edi retten
2031             pushl   %ebx            // %ebx retten
2032             movl    16(%esp),%esi   // %esi = xptr
2033             movl    20(%esp),%edi   // %edi = yptr
2034             movl    24(%esp),%edx   // count
2035             movb    28(%esp),%cl    // i
2036             orl     %edx,%edx       // count = 0 ?
2037             jz      L(shxlu4)
2038             subl    %esi,%edi
2039             // erstes Digit shiften:
2040             movl    (%esi,%edi),%ebx // *yptr in %ebx halten
2041             movl    %ebx,%eax       // und in %eax rechnen:
2042             shll    %cl,%eax        // um i Bits links shiften, rechts Nullen rein
2043             xorl    %eax,(%esi)     // und mit *xptr verknüpfen und ablegen
2044             leal    4(%esi),%esi    // sourceptr++, destptr++
2045             // Letztes Digit in %ebx.
2046             negb    %cl             // 32-i
2047             decl    %edx
2048             jz      L(shxlu2)
2049 L(shxlu1:)    // weiteres Digit shiften:
2050               movl    (%esi,%edi),%eax // nächstes Digit nach %eax
2051               shrdl   shcl %eax,%ebx  // %ebx um %cl=32-i Bits rechts shiften, %eax von links reinshiften
2052               xorl    %ebx,(%esi)     // %ebx mit *xptr verknüpfen und ablegen
2053               leal    4(%esi),%esi    // xptr++, yptr++
2054               // Letztes Digit in %eax.
2055               decl    %edx
2056               jz      L(shxlu3)
2057               // weiteres Digit shiften:
2058               movl    (%esi,%edi),%ebx // nächstes Digit nach %ebx
2059               shrdl   shcl %ebx,%eax  // %eax um %cl=32-i Bits rechts shiften, %ebx von links reinshiften
2060               xorl    %eax,(%esi)     // %eax mit *xptr verknüpfen und ablegen
2061               leal    4(%esi),%esi    // xptr++, yptr++
2062               // Letztes Digit in %ebx.
2063               decl    %edx
2064               jnz     L(shxlu1)
2065 L(shxlu2:)  movl    %ebx,%eax
2066 L(shxlu3:)  shrl    %cl,%eax        // %eax um 32-i Bits nach rechts shiften
2067             xorl    %eax,(%esi)     // und mit *xptr verknüpfen und ablegen
2068 L(shxlu4:)  popl    %ebx            // %ebx zurück
2069             popl    %edi            // %edi zurück
2070             popl    %esi            // %esi zurück
2071             ret
2072 
2073