]> www.ginac.de Git - cln.git/blob - src/base/digitseq/cl_asm_sparc_.cc
Finalize CLN 1.3.7 release.
[cln.git] / src / base / digitseq / cl_asm_sparc_.cc
1 // Externe Routinen zu ARILEV1.D
2 // Prozessor: SPARC
3 // Compiler: GNU-C oder SUN-C
4 // Parameter-Übergabe: in Registern %o0-%o5.
5 // Einstellungen: intCsize=32, intDsize=32.
6
7 #if defined(sparc_v8) || defined(__sparc_v8) || defined(__sparc_v8__)
8   #define sparcv8
9 #endif
10
11 #ifdef ASM_UNDERSCORE /* SunOS 4 */
12   #if defined(__STDC__) || defined (__cplusplus)
13     #define C(entrypoint) _##entrypoint
14   #else
15     #define C(entrypoint) _/**/entrypoint
16   #endif
17 #else /* SunOS 5 = Solaris 2 */
18   #define C(entrypoint) entrypoint
19 #endif
20
21 // When this file is compiled into a shared library, ELF linkers need to
22 // know which symbols are functions.
23 #if defined(__NetBSD__) || defined(__OpenBSD__)
24   #define DECLARE_FUNCTION(name) .type C(name),@function
25 #elif defined(__svr4__) || defined(__ELF__)
26   #define DECLARE_FUNCTION(name) .type C(name),#function
27 #else
28   #define DECLARE_FUNCTION(name)
29 #endif
30
31   // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots
32   // (diese werden VOR der vorigen Instruktion ausgeführt):
33   #define _             // Instruktion, die stets ausgeführt wird
34   #define __            // Instruktion, die nur im Sprung-Fall ausgeführt wird
35   // Abkürzungen für Anweisungen:
36   #define ret   jmp %i7+8    // return from subroutine
37   #define retl  jmp %o7+8    // return from leaf subroutine (no save/restore)
38
39         .seg "text"
40
41         .global C(mulu16_),C(mulu32_),C(mulu32_unchecked)
42         .global C(divu_6432_3232_),C(divu_3216_1616_)
43         .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down)
44         .global C(clear_loop_up),C(clear_loop_down)
45         .global C(test_loop_up),C(test_loop_down)
46         .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up)
47 #if CL_DS_BIG_ENDIAN_P
48         .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up)
49         .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up)
50         .global C(not_loop_up)
51         .global C(and_test_loop_up)
52         .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down)
53         .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down)
54         .global C(neg_loop_down)
55         .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down)
56         .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up)
57         .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down)
58         .global C(divu_loop_up),C(divucopy_loop_up)
59 #else
60         .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down)
61         .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down)
62         .global C(not_loop_down)
63         .global C(and_test_loop_down),C(compare_loop_down)
64         .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up)
65         .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up)
66         .global C(neg_loop_up)
67         .global C(shift1left_loop_up),C(shiftleft_loop_up)
68         .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down)
69         .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up)
70         .global C(divu_loop_down),C(divucopy_loop_down)
71 #endif
72
73 #define LOOP_TYPE  1    // 1: Standard-Schleifen
74                         // 2: Schleifen ohne Pointer, nur mit Zähler
75                         // 3: entrollte Schleifen
76 #define SLOW_LOOPS  0
77 #define STANDARD_LOOPS  (LOOP_TYPE==1)
78 #define COUNTER_LOOPS  (LOOP_TYPE==2)
79 #define UNROLLED_LOOPS  (LOOP_TYPE==3)
80 #define MULU32_INLINE  1  // 1: mulu32-Aufrufe inline in die Schleifen
81
82 // extern uint32 mulu16_ (uint16 arg1, uint16 arg2);
83 // ergebnis := arg1*arg2.
84         DECLARE_FUNCTION(mulu16_)
85 C(mulu16_:) // Input in %o0,%o1, Output in %o0
86 #ifdef sparcv8
87         umul    %o0,%o1,%o0
88         retl
89        _ nop
90 #else
91         mov     %o1,%y
92         nop                     // Wartetakt, nötig z.B. für SUN SPARCstation IPC
93         andcc   %g0,%g0,%o2
94         mulscc  %o2,%o0,%o2
95         mulscc  %o2,%o0,%o2
96         mulscc  %o2,%o0,%o2
97         mulscc  %o2,%o0,%o2
98         mulscc  %o2,%o0,%o2
99         mulscc  %o2,%o0,%o2
100         mulscc  %o2,%o0,%o2
101         mulscc  %o2,%o0,%o2
102         mulscc  %o2,%o0,%o2
103         mulscc  %o2,%o0,%o2
104         mulscc  %o2,%o0,%o2
105         mulscc  %o2,%o0,%o2
106         mulscc  %o2,%o0,%o2
107         mulscc  %o2,%o0,%o2
108         mulscc  %o2,%o0,%o2
109         mulscc  %o2,%o0,%o2
110         // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
111         // ergeben das Resultat. (Die anderen Bits sind Null.)
112         rd      %y,%o0
113         srl     %o0,17,%o0
114         sll     %o2,15,%o2
115         retl
116        _ or      %o2,%o0,%o0
117 #endif
118
119 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
120 // 2^32*hi+lo := arg1*arg2.
121         DECLARE_FUNCTION(mulu32_)
122 C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1
123 #ifdef sparcv8
124         umul    %o0,%o1,%o0
125         retl
126        _ rd      %y,%g1
127 #else
128         mov     %o1,%y
129         sra     %o0,31,%o3      // Wartetakt, nötig z.B. für SUN SPARCstation IPC
130         andcc   %g0,%g0,%o2
131         mulscc  %o2,%o0,%o2
132         mulscc  %o2,%o0,%o2
133         mulscc  %o2,%o0,%o2
134         mulscc  %o2,%o0,%o2
135         mulscc  %o2,%o0,%o2
136         mulscc  %o2,%o0,%o2
137         mulscc  %o2,%o0,%o2
138         mulscc  %o2,%o0,%o2
139         mulscc  %o2,%o0,%o2
140         mulscc  %o2,%o0,%o2
141         mulscc  %o2,%o0,%o2
142         mulscc  %o2,%o0,%o2
143         mulscc  %o2,%o0,%o2
144         mulscc  %o2,%o0,%o2
145         mulscc  %o2,%o0,%o2
146         mulscc  %o2,%o0,%o2
147         mulscc  %o2,%o0,%o2
148         mulscc  %o2,%o0,%o2
149         mulscc  %o2,%o0,%o2
150         mulscc  %o2,%o0,%o2
151         mulscc  %o2,%o0,%o2
152         mulscc  %o2,%o0,%o2
153         mulscc  %o2,%o0,%o2
154         mulscc  %o2,%o0,%o2
155         mulscc  %o2,%o0,%o2
156         mulscc  %o2,%o0,%o2
157         mulscc  %o2,%o0,%o2
158         mulscc  %o2,%o0,%o2
159         mulscc  %o2,%o0,%o2
160         mulscc  %o2,%o0,%o2
161         mulscc  %o2,%o0,%o2
162         mulscc  %o2,%o0,%o2
163         mulscc  %o2,%g0,%o2
164         and     %o3,%o1,%o3     // %o3 = (0 falls %o0>=0, %o1 falls %o0<0)
165         add     %o2,%o3,%g1     // hi
166         retl
167        _ rd      %y,%o0         // lo
168 #endif
169
170 // extern uint32 mulu32_unchecked (uint32 x, uint32 y);
171 // ergebnis := arg1*arg2 < 2^32.
172         DECLARE_FUNCTION(mulu32_unchecked)
173 C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0
174 #ifdef sparcv8
175         umul    %o0,%o1,%o0
176         retl
177        _ nop
178 #else
179         subcc   %o0,%o1,%g0
180         bcc,a   1f
181        __ mov     %o1,%y
182         // arg1 < arg2, also kann man arg1 < 2^16 annehmen.
183         mov     %o0,%y
184         nop                     // Wartetakt, nötig z.B. für SUN SPARCstation IPC
185         andcc   %g0,%g0,%o2
186         mulscc  %o2,%o1,%o2
187         mulscc  %o2,%o1,%o2
188         mulscc  %o2,%o1,%o2
189         mulscc  %o2,%o1,%o2
190         mulscc  %o2,%o1,%o2
191         mulscc  %o2,%o1,%o2
192         mulscc  %o2,%o1,%o2
193         mulscc  %o2,%o1,%o2
194         mulscc  %o2,%o1,%o2
195         mulscc  %o2,%o1,%o2
196         mulscc  %o2,%o1,%o2
197         mulscc  %o2,%o1,%o2
198         mulscc  %o2,%o1,%o2
199         mulscc  %o2,%o1,%o2
200         mulscc  %o2,%o1,%o2
201         mulscc  %o2,%o1,%o2
202         // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
203         // ergeben das Resultat. (Die anderen Bits sind Null.)
204         rd      %y,%o0
205         srl     %o0,17,%o0
206         sll     %o2,15,%o2
207         retl
208        _ or      %o2,%o0,%o0
209 1:      // arg1 >= arg2, also kann man arg2 < 2^16 annehmen.
210         nop                     // Wartetakt, nötig z.B. für SUN SPARCstation IPC
211         andcc   %g0,%g0,%o2
212         mulscc  %o2,%o0,%o2
213         mulscc  %o2,%o0,%o2
214         mulscc  %o2,%o0,%o2
215         mulscc  %o2,%o0,%o2
216         mulscc  %o2,%o0,%o2
217         mulscc  %o2,%o0,%o2
218         mulscc  %o2,%o0,%o2
219         mulscc  %o2,%o0,%o2
220         mulscc  %o2,%o0,%o2
221         mulscc  %o2,%o0,%o2
222         mulscc  %o2,%o0,%o2
223         mulscc  %o2,%o0,%o2
224         mulscc  %o2,%o0,%o2
225         mulscc  %o2,%o0,%o2
226         mulscc  %o2,%o0,%o2
227         mulscc  %o2,%o0,%o2
228         // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
229         // ergeben das Resultat.
230         rd      %y,%o0
231         srl     %o0,17,%o0
232         sll     %o2,15,%o2
233         retl
234        _ or      %o2,%o0,%o0
235 #endif
236
237 // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
238 // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y .
239         DECLARE_FUNCTION(divu_6432_3232_)
240 C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1
241 #if defined(sparcv8)
242         // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
243         wr      %o0,%g0,%y
244         nop                     // wait 1 | Necessary for certain sparcv8
245         nop                     // wait 2 | processors such as Ross Hypersparc,
246         nop                     // wait 3 | but not for most of the others.
247         udiv    %o1,%o2,%o0     // x durch y dividieren, %o0 := q
248         umul    %o0,%o2,%g1     // %g1 := (q*y) mod 2^32
249         retl
250        _ sub     %o1,%g1,%g1    // %g1 := (xlo-q*y) mod 2^32 = r
251 #else
252         // %o0 = xhi, %o1 = xlo, %o2 = y
253 // Divisions-Einzelschritte:
254 // %o0|%o1  wird jeweils um 1 Bit nach links geschoben,
255 // dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben.
256 // Je nachdem wird mit %o3|%o1 statt %o0|%o1 weitergemacht (spart 1 'mov').
257 // Deswegen muß man den Code doppelt vorsehen: einmal mit %o0, einmal mit %o3.
258 #define SA0(label) /* Vergleichsschritt mit %o0  */\
259         subcc   %o0,%o2,%o3; \
260         bcc     label;       \
261        _ addxcc  %o1,%o1,%o1
262 #define SA1(label) /* Vergleichsschritt mit %o3  */\
263         subcc   %o3,%o2,%o0; \
264         bcc     label;       \
265        _ addxcc  %o1,%o1,%o1
266 #define SB0() /* Additionsschritt mit %o0  */\
267         addx    %o0,%o0,%o0
268 #define SB1() /* Additionsschritt mit %o3  */\
269         addx    %o3,%o3,%o3
270 // Los geht's:
271         addcc   %o2,%o2,%g0     // y = %o2 < 2^31 ?
272         bcc     Lsmalldiv       // ja -> "kleine" Division
273        _ andcc   %o2,1,%g0      // y = %o2 gerade ?
274         be      Levendiv        // ja -> Division durch gerade Zahl
275        _ srl     %o2,1,%o2
276         // Division durch ungerade Zahl:
277         // floor(x / (2*y'-1)) = floor(floor(x/2) / y') + (0 oder 1 oder 2)
278         // da  0 <= x/(2*y'-1) - x/(2*y') = x/(2*y'-1) / (2*y') = x/y / (2*y')
279         //       < 2^32 / (2*y') < 2^32/y <= 2 .
280         add     %o2,1,%o2       // %o2 = ceiling(y/2) = y'
281         // Man spart im Vergleich zu Lsmalldiv
282         // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0()
283         // dafür am Schluß mehr zu tun...
284         SA0(Lb01)               // Bit 31 des Quotienten bestimmen
285 La01:   SB0(); SA0(Lb02)        // Bit 30 des Quotienten bestimmen
286 La02:   SB0(); SA0(Lb03)        // Bit 29 des Quotienten bestimmen
287 La03:   SB0(); SA0(Lb04)        // Bit 28 des Quotienten bestimmen
288 La04:   SB0(); SA0(Lb05)        // Bit 27 des Quotienten bestimmen
289 La05:   SB0(); SA0(Lb06)        // Bit 26 des Quotienten bestimmen
290 La06:   SB0(); SA0(Lb07)        // Bit 25 des Quotienten bestimmen
291 La07:   SB0(); SA0(Lb08)        // Bit 24 des Quotienten bestimmen
292 La08:   SB0(); SA0(Lb09)        // Bit 23 des Quotienten bestimmen
293 La09:   SB0(); SA0(Lb10)        // Bit 22 des Quotienten bestimmen
294 La10:   SB0(); SA0(Lb11)        // Bit 21 des Quotienten bestimmen
295 La11:   SB0(); SA0(Lb12)        // Bit 20 des Quotienten bestimmen
296 La12:   SB0(); SA0(Lb13)        // Bit 19 des Quotienten bestimmen
297 La13:   SB0(); SA0(Lb14)        // Bit 18 des Quotienten bestimmen
298 La14:   SB0(); SA0(Lb15)        // Bit 17 des Quotienten bestimmen
299 La15:   SB0(); SA0(Lb16)        // Bit 16 des Quotienten bestimmen
300 La16:   SB0(); SA0(Lb17)        // Bit 15 des Quotienten bestimmen
301 La17:   SB0(); SA0(Lb18)        // Bit 14 des Quotienten bestimmen
302 La18:   SB0(); SA0(Lb19)        // Bit 13 des Quotienten bestimmen
303 La19:   SB0(); SA0(Lb20)        // Bit 12 des Quotienten bestimmen
304 La20:   SB0(); SA0(Lb21)        // Bit 11 des Quotienten bestimmen
305 La21:   SB0(); SA0(Lb22)        // Bit 10 des Quotienten bestimmen
306 La22:   SB0(); SA0(Lb23)        // Bit 9 des Quotienten bestimmen
307 La23:   SB0(); SA0(Lb24)        // Bit 8 des Quotienten bestimmen
308 La24:   SB0(); SA0(Lb25)        // Bit 7 des Quotienten bestimmen
309 La25:   SB0(); SA0(Lb26)        // Bit 6 des Quotienten bestimmen
310 La26:   SB0(); SA0(Lb27)        // Bit 5 des Quotienten bestimmen
311 La27:   SB0(); SA0(Lb28)        // Bit 4 des Quotienten bestimmen
312 La28:   SB0(); SA0(Lb29)        // Bit 3 des Quotienten bestimmen
313 La29:   SB0(); SA0(Lb30)        // Bit 2 des Quotienten bestimmen
314 La30:   SB0(); SA0(Lb31)        // Bit 1 des Quotienten bestimmen
315 La31:   SB0(); SA0(Lb32)        // Bit 0 des Quotienten bestimmen
316 La32:   SB0()                   // %o0 = x mod (2*y')
317         xor     %o1,-1,%o1      // %o1 = floor( floor(x/2) / y') = floor(x/(2*y'))
318         add     %o2,%o2,%o2
319         sub     %o2,1,%o2       // wieder %o2 = 2*y'-1 = y
320         // Quotient und Rest umrechnen:
321         // x = %o1 * 2*y' + %o0 = %o1 * (2*y'-1) + (%o0+%o1)
322         // Also Quotient = %o1, Rest = %o0+%o1.
323         // Noch maximal 2 mal: Quotient += 1, Rest -= y.
324         addcc   %o1,%o0,%o0     // Rest mod y bestimmen
325         bcc     1f              // Additions-Überlauf -> Quotient erhöhen
326        _ subcc   %o0,%o2,%o3
327         subcc   %o3,%o2,%o0     // muß der Quotient nochmals erhöht werden?
328         bcs     2f
329        _ mov     %o3,%g1
330         // Quotient 2 mal erhöhen, Rest %o0
331         mov     %o0,%g1
332         retl
333        _ add     %o1,2,%o0
334 1:      // kein Additions-Überlauf.
335         // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden:
336         bcs     3f              // %o0 < %o2 -> Rest %o0 und Quotient %o1 OK
337        _ mov     %o3,%g1
338 2:      // Quotient %o1 erhöhen, Rest = %o0-%o2 = %o3
339         retl
340        _ add     %o1,1,%o0
341 3:      // Quotient %o1 und Rest %o0 OK
342         mov     %o0,%g1
343         retl
344        _ mov     %o1,%o0
345 // Parallelschiene zu La01..La32:
346 Lb01:   SB1(); SA1(La02)
347 Lb02:   SB1(); SA1(La03)
348 Lb03:   SB1(); SA1(La04)
349 Lb04:   SB1(); SA1(La05)
350 Lb05:   SB1(); SA1(La06)
351 Lb06:   SB1(); SA1(La07)
352 Lb07:   SB1(); SA1(La08)
353 Lb08:   SB1(); SA1(La09)
354 Lb09:   SB1(); SA1(La10)
355 Lb10:   SB1(); SA1(La11)
356 Lb11:   SB1(); SA1(La12)
357 Lb12:   SB1(); SA1(La13)
358 Lb13:   SB1(); SA1(La14)
359 Lb14:   SB1(); SA1(La15)
360 Lb15:   SB1(); SA1(La16)
361 Lb16:   SB1(); SA1(La17)
362 Lb17:   SB1(); SA1(La18)
363 Lb18:   SB1(); SA1(La19)
364 Lb19:   SB1(); SA1(La20)
365 Lb20:   SB1(); SA1(La21)
366 Lb21:   SB1(); SA1(La22)
367 Lb22:   SB1(); SA1(La23)
368 Lb23:   SB1(); SA1(La24)
369 Lb24:   SB1(); SA1(La25)
370 Lb25:   SB1(); SA1(La26)
371 Lb26:   SB1(); SA1(La27)
372 Lb27:   SB1(); SA1(La28)
373 Lb28:   SB1(); SA1(La29)
374 Lb29:   SB1(); SA1(La30)
375 Lb30:   SB1(); SA1(La31)
376 Lb31:   SB1(); SA1(La32)
377 Lb32:   SB1()                   // %o3 = x mod (2*y')
378         xor     %o1,-1,%o1      // %o1 = floor( floor(x/2) / y') = floor(x/(2*y'))
379         add     %o2,%o2,%o2
380         sub     %o2,1,%o2       // wieder %o2 = 2*y'-1 = y
381         // Quotient und Rest umrechnen:
382         // x = %o1 * 2*y' + %o3 = %o1 * (2*y'-1) + (%o3+%o1)
383         // Also Quotient = %o1, Rest = %o3+%o1.
384         // Noch maximal 2 mal: Quotient += 1, Rest -= y.
385         addcc   %o1,%o3,%o3     // Rest mod y bestimmen
386         bcc     1f              // Additions-Überlauf -> Quotient erhöhen
387        _ subcc   %o3,%o2,%o0
388         subcc   %o0,%o2,%o3     // muß der Quotient nochmals erhöht werden?
389         bcs     2f
390        _ mov     %o0,%g1
391         // Quotient 2 mal erhöhen, Rest %o3
392         mov     %o3,%g1
393         retl
394        _ add     %o1,2,%o0
395 1:      // kein Additions-Überlauf.
396         // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden:
397         bcs     3f              // %o3 < %o2 -> Rest %o3 und Quotient %o1 OK
398        _ mov     %o0,%g1
399 2:      // Quotient %o1 erhöhen, Rest = %o3-%o2 = %o0
400         retl
401        _ add     %o1,1,%o0
402 3:      // Quotient %o1 und Rest %o3 OK
403         mov     %o3,%g1
404         retl
405        _ mov     %o1,%o0
406 Lsmalldiv: // Division durch y < 2^31
407         addcc   %o1,%o1,%o1
408 Lc00:   SB0(); SA0(Ld01)        // Bit 31 des Quotienten bestimmen
409 Lc01:   SB0(); SA0(Ld02)        // Bit 30 des Quotienten bestimmen
410 Lc02:   SB0(); SA0(Ld03)        // Bit 29 des Quotienten bestimmen
411 Lc03:   SB0(); SA0(Ld04)        // Bit 28 des Quotienten bestimmen
412 Lc04:   SB0(); SA0(Ld05)        // Bit 27 des Quotienten bestimmen
413 Lc05:   SB0(); SA0(Ld06)        // Bit 26 des Quotienten bestimmen
414 Lc06:   SB0(); SA0(Ld07)        // Bit 25 des Quotienten bestimmen
415 Lc07:   SB0(); SA0(Ld08)        // Bit 24 des Quotienten bestimmen
416 Lc08:   SB0(); SA0(Ld09)        // Bit 23 des Quotienten bestimmen
417 Lc09:   SB0(); SA0(Ld10)        // Bit 22 des Quotienten bestimmen
418 Lc10:   SB0(); SA0(Ld11)        // Bit 21 des Quotienten bestimmen
419 Lc11:   SB0(); SA0(Ld12)        // Bit 20 des Quotienten bestimmen
420 Lc12:   SB0(); SA0(Ld13)        // Bit 19 des Quotienten bestimmen
421 Lc13:   SB0(); SA0(Ld14)        // Bit 18 des Quotienten bestimmen
422 Lc14:   SB0(); SA0(Ld15)        // Bit 17 des Quotienten bestimmen
423 Lc15:   SB0(); SA0(Ld16)        // Bit 16 des Quotienten bestimmen
424 Lc16:   SB0(); SA0(Ld17)        // Bit 15 des Quotienten bestimmen
425 Lc17:   SB0(); SA0(Ld18)        // Bit 14 des Quotienten bestimmen
426 Lc18:   SB0(); SA0(Ld19)        // Bit 13 des Quotienten bestimmen
427 Lc19:   SB0(); SA0(Ld20)        // Bit 12 des Quotienten bestimmen
428 Lc20:   SB0(); SA0(Ld21)        // Bit 11 des Quotienten bestimmen
429 Lc21:   SB0(); SA0(Ld22)        // Bit 10 des Quotienten bestimmen
430 Lc22:   SB0(); SA0(Ld23)        // Bit 9 des Quotienten bestimmen
431 Lc23:   SB0(); SA0(Ld24)        // Bit 8 des Quotienten bestimmen
432 Lc24:   SB0(); SA0(Ld25)        // Bit 7 des Quotienten bestimmen
433 Lc25:   SB0(); SA0(Ld26)        // Bit 6 des Quotienten bestimmen
434 Lc26:   SB0(); SA0(Ld27)        // Bit 5 des Quotienten bestimmen
435 Lc27:   SB0(); SA0(Ld28)        // Bit 4 des Quotienten bestimmen
436 Lc28:   SB0(); SA0(Ld29)        // Bit 3 des Quotienten bestimmen
437 Lc29:   SB0(); SA0(Ld30)        // Bit 2 des Quotienten bestimmen
438 Lc30:   SB0(); SA0(Ld31)        // Bit 1 des Quotienten bestimmen
439 Lc31:   SB0(); SA0(Ld32)        // Bit 0 des Quotienten bestimmen
440 Lc32:   mov     %o0,%g1         // Rest aus %o0 in %g1 abspeichern
441         retl
442        _ xor     %o1,-1,%o0     // Quotient nach %o0
443 // Parallelschiene zu Lc01..Lc32:
444 Ld01:   SB1(); SA1(Lc02)
445 Ld02:   SB1(); SA1(Lc03)
446 Ld03:   SB1(); SA1(Lc04)
447 Ld04:   SB1(); SA1(Lc05)
448 Ld05:   SB1(); SA1(Lc06)
449 Ld06:   SB1(); SA1(Lc07)
450 Ld07:   SB1(); SA1(Lc08)
451 Ld08:   SB1(); SA1(Lc09)
452 Ld09:   SB1(); SA1(Lc10)
453 Ld10:   SB1(); SA1(Lc11)
454 Ld11:   SB1(); SA1(Lc12)
455 Ld12:   SB1(); SA1(Lc13)
456 Ld13:   SB1(); SA1(Lc14)
457 Ld14:   SB1(); SA1(Lc15)
458 Ld15:   SB1(); SA1(Lc16)
459 Ld16:   SB1(); SA1(Lc17)
460 Ld17:   SB1(); SA1(Lc18)
461 Ld18:   SB1(); SA1(Lc19)
462 Ld19:   SB1(); SA1(Lc20)
463 Ld20:   SB1(); SA1(Lc21)
464 Ld21:   SB1(); SA1(Lc22)
465 Ld22:   SB1(); SA1(Lc23)
466 Ld23:   SB1(); SA1(Lc24)
467 Ld24:   SB1(); SA1(Lc25)
468 Ld25:   SB1(); SA1(Lc26)
469 Ld26:   SB1(); SA1(Lc27)
470 Ld27:   SB1(); SA1(Lc28)
471 Ld28:   SB1(); SA1(Lc29)
472 Ld29:   SB1(); SA1(Lc30)
473 Ld30:   SB1(); SA1(Lc31)
474 Ld31:   SB1(); SA1(Lc32)
475 Ld32:   mov     %o3,%g1         // Rest aus %o3 in %g1 abspeichern
476         retl
477        _ xor     %o1,-1,%o0     // Quotient nach %o0
478 Levendiv: // Division durch gerades y.
479         // x/2 durch y/2 dividieren, Quotient OK, Rest evtl. mit 2 multiplizieren.
480         // Es ist schon %o2 = y/2.
481         // Man spart im Vergleich zu Lsmalldiv
482         // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0()
483         // dafür am Schluß Bit 0 von x zum Rest dazuschieben.
484         SA0(Lf01)               // Bit 31 des Quotienten bestimmen
485 Le01:   SB0(); SA0(Lf02)        // Bit 30 des Quotienten bestimmen
486 Le02:   SB0(); SA0(Lf03)        // Bit 29 des Quotienten bestimmen
487 Le03:   SB0(); SA0(Lf04)        // Bit 28 des Quotienten bestimmen
488 Le04:   SB0(); SA0(Lf05)        // Bit 27 des Quotienten bestimmen
489 Le05:   SB0(); SA0(Lf06)        // Bit 26 des Quotienten bestimmen
490 Le06:   SB0(); SA0(Lf07)        // Bit 25 des Quotienten bestimmen
491 Le07:   SB0(); SA0(Lf08)        // Bit 24 des Quotienten bestimmen
492 Le08:   SB0(); SA0(Lf09)        // Bit 23 des Quotienten bestimmen
493 Le09:   SB0(); SA0(Lf10)        // Bit 22 des Quotienten bestimmen
494 Le10:   SB0(); SA0(Lf11)        // Bit 21 des Quotienten bestimmen
495 Le11:   SB0(); SA0(Lf12)        // Bit 20 des Quotienten bestimmen
496 Le12:   SB0(); SA0(Lf13)        // Bit 19 des Quotienten bestimmen
497 Le13:   SB0(); SA0(Lf14)        // Bit 18 des Quotienten bestimmen
498 Le14:   SB0(); SA0(Lf15)        // Bit 17 des Quotienten bestimmen
499 Le15:   SB0(); SA0(Lf16)        // Bit 16 des Quotienten bestimmen
500 Le16:   SB0(); SA0(Lf17)        // Bit 15 des Quotienten bestimmen
501 Le17:   SB0(); SA0(Lf18)        // Bit 14 des Quotienten bestimmen
502 Le18:   SB0(); SA0(Lf19)        // Bit 13 des Quotienten bestimmen
503 Le19:   SB0(); SA0(Lf20)        // Bit 12 des Quotienten bestimmen
504 Le20:   SB0(); SA0(Lf21)        // Bit 11 des Quotienten bestimmen
505 Le21:   SB0(); SA0(Lf22)        // Bit 10 des Quotienten bestimmen
506 Le22:   SB0(); SA0(Lf23)        // Bit 9 des Quotienten bestimmen
507 Le23:   SB0(); SA0(Lf24)        // Bit 8 des Quotienten bestimmen
508 Le24:   SB0(); SA0(Lf25)        // Bit 7 des Quotienten bestimmen
509 Le25:   SB0(); SA0(Lf26)        // Bit 6 des Quotienten bestimmen
510 Le26:   SB0(); SA0(Lf27)        // Bit 5 des Quotienten bestimmen
511 Le27:   SB0(); SA0(Lf28)        // Bit 4 des Quotienten bestimmen
512 Le28:   SB0(); SA0(Lf29)        // Bit 3 des Quotienten bestimmen
513 Le29:   SB0(); SA0(Lf30)        // Bit 2 des Quotienten bestimmen
514 Le30:   SB0(); SA0(Lf31)        // Bit 1 des Quotienten bestimmen
515 Le31:   SB0(); SA0(Lf32)        // Bit 0 des Quotienten bestimmen
516 Le32:   SB0()                   // Bit 0 des Restes bestimmen
517         mov     %o0,%g1         // Rest aus %o0 in %g1 abspeichern
518         retl
519        _ xor     %o1,-1,%o0     // Quotient nach %o0
520 // Parallelschiene zu Le01..Le32:
521 Lf01:   SB1(); SA1(Le02)
522 Lf02:   SB1(); SA1(Le03)
523 Lf03:   SB1(); SA1(Le04)
524 Lf04:   SB1(); SA1(Le05)
525 Lf05:   SB1(); SA1(Le06)
526 Lf06:   SB1(); SA1(Le07)
527 Lf07:   SB1(); SA1(Le08)
528 Lf08:   SB1(); SA1(Le09)
529 Lf09:   SB1(); SA1(Le10)
530 Lf10:   SB1(); SA1(Le11)
531 Lf11:   SB1(); SA1(Le12)
532 Lf12:   SB1(); SA1(Le13)
533 Lf13:   SB1(); SA1(Le14)
534 Lf14:   SB1(); SA1(Le15)
535 Lf15:   SB1(); SA1(Le16)
536 Lf16:   SB1(); SA1(Le17)
537 Lf17:   SB1(); SA1(Le18)
538 Lf18:   SB1(); SA1(Le19)
539 Lf19:   SB1(); SA1(Le20)
540 Lf20:   SB1(); SA1(Le21)
541 Lf21:   SB1(); SA1(Le22)
542 Lf22:   SB1(); SA1(Le23)
543 Lf23:   SB1(); SA1(Le24)
544 Lf24:   SB1(); SA1(Le25)
545 Lf25:   SB1(); SA1(Le26)
546 Lf26:   SB1(); SA1(Le27)
547 Lf27:   SB1(); SA1(Le28)
548 Lf28:   SB1(); SA1(Le29)
549 Lf29:   SB1(); SA1(Le30)
550 Lf30:   SB1(); SA1(Le31)
551 Lf31:   SB1(); SA1(Le32)
552 Lf32:   SB1()
553         mov     %o3,%g1         // Rest aus %o0 in %g1 abspeichern
554         retl
555        _ xor     %o1,-1,%o0     // Quotient nach %o0
556 #endif
557
558 // extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y);
559 // x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y .
560         DECLARE_FUNCTION(divu_3216_1616_)
561 C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient).
562 #if defined(sparcv8)
563         // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
564         wr      %g0,%g0,%y
565         nop                     // wait 1
566         nop                     // wait 2
567         nop                     // wait 3
568         udiv    %o0,%o1,%o0     // dividieren, Quotient nach %o0
569         rd      %y,%o1          // Rest aus %y
570         sll     %o1,16,%o1      // in die oberen 16 Bit schieben
571         retl
572        _ or      %o0,%o1,%o0
573 #else
574         // %o0 = x, %o1 = y
575 // Divisions-Einzelschritte:
576 // %o0  wird jeweils um 1 Bit nach links geschoben,
577 // dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben.
578 // Dann wird auf >= 2^15*y verglichen (nicht auf >= 2^16*y, weil man dann das
579 // links herausgeschobene Bit mit vergleichen müßte!)
580         sll %o1,16,%o1
581         srl %o1,1,%o1           // 2^15*y
582         sub %g0,%o1,%o2         // zum Addieren statt Subtrahieren: -2^15*y
583         // SC0(label) subtrahiert y, schiebt Carry-Bit rechts in %o0 rein
584         // (1 falls Subtraktion aufging, 0 sonst).
585         // Ging die Subtraktion nicht auf, so müßte man noch 2*y addieren.
586         // Das faßt man mit der nächsten Operation zusammen, indem man - statt
587         // y zu subtrahieren - y addiert:
588         // SC1(label) addiert y, schiebt Carry-Bit rechts in %o0 rein
589         // (1 falls Subtraktion aufgegangen wäre, man also wieder im
590         // "positiven Bereich" landet, 0 sonst).
591 #define SC0(label) \
592         addcc   %o0,%o2,%o0; \
593         bcc     label;       \
594        _ addx    %o0,%o0,%o0
595 #define SC1(label) \
596         addcc   %o0,%o1,%o0; \
597         bcs     label;       \
598        _ addx    %o0,%o0,%o0
599         SC0(Lh01)               // Bit 15 des Quotienten bestimmen
600 Lg01:   SC0(Lh02)               // Bit 14 des Quotienten bestimmen
601 Lg02:   SC0(Lh03)               // Bit 13 des Quotienten bestimmen
602 Lg03:   SC0(Lh04)               // Bit 12 des Quotienten bestimmen
603 Lg04:   SC0(Lh05)               // Bit 11 des Quotienten bestimmen
604 Lg05:   SC0(Lh06)               // Bit 10 des Quotienten bestimmen
605 Lg06:   SC0(Lh07)               // Bit 9 des Quotienten bestimmen
606 Lg07:   SC0(Lh08)               // Bit 8 des Quotienten bestimmen
607 Lg08:   SC0(Lh09)               // Bit 7 des Quotienten bestimmen
608 Lg09:   SC0(Lh10)               // Bit 6 des Quotienten bestimmen
609 Lg10:   SC0(Lh11)               // Bit 5 des Quotienten bestimmen
610 Lg11:   SC0(Lh12)               // Bit 4 des Quotienten bestimmen
611 Lg12:   SC0(Lh13)               // Bit 3 des Quotienten bestimmen
612 Lg13:   SC0(Lh14)               // Bit 2 des Quotienten bestimmen
613 Lg14:   SC0(Lh15)               // Bit 1 des Quotienten bestimmen
614 Lg15:   SC0(Lh16)               // Bit 0 des Quotienten bestimmen
615 Lg16:   // Die oberen 16 Bit von %o0 sind der Rest,
616         // die unteren 16 Bit von %o0 sind der Quotient.
617         retl
618        _ nop
619 Lh01:   SC1(Lg02)               // Bit 14 des Quotienten bestimmen
620 Lh02:   SC1(Lg03)               // Bit 13 des Quotienten bestimmen
621 Lh03:   SC1(Lg04)               // Bit 12 des Quotienten bestimmen
622 Lh04:   SC1(Lg05)               // Bit 11 des Quotienten bestimmen
623 Lh05:   SC1(Lg06)               // Bit 10 des Quotienten bestimmen
624 Lh06:   SC1(Lg07)               // Bit 9 des Quotienten bestimmen
625 Lh07:   SC1(Lg08)               // Bit 8 des Quotienten bestimmen
626 Lh08:   SC1(Lg09)               // Bit 7 des Quotienten bestimmen
627 Lh09:   SC1(Lg10)               // Bit 6 des Quotienten bestimmen
628 Lh10:   SC1(Lg11)               // Bit 5 des Quotienten bestimmen
629 Lh11:   SC1(Lg12)               // Bit 4 des Quotienten bestimmen
630 Lh12:   SC1(Lg13)               // Bit 3 des Quotienten bestimmen
631 Lh13:   SC1(Lg14)               // Bit 2 des Quotienten bestimmen
632 Lh14:   SC1(Lg15)               // Bit 1 des Quotienten bestimmen
633 Lh15:   SC1(Lg16)               // Bit 0 des Quotienten bestimmen
634 Lh16:   // Noch 2*y addieren:
635         add %o0,%o1,%o0
636         retl
637        _ add %o0,%o1,%o0
638 #endif
639
640 #if !defined(__GNUC__)
641         .global C(_get_g1)
642 // extern uint32 _get_g1 (void);
643         DECLARE_FUNCTION(_get_g1)
644 C(_get_g1:)
645         retl
646        _ mov %g1,%o0
647 #endif
648
649 // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
650         DECLARE_FUNCTION(copy_loop_up)
651 C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
652 #if STANDARD_LOOPS
653         andcc %o2,%o2,%g0
654         be 2f
655        _ nop
656 1:        ld [%o0],%o3
657           add %o0,4,%o0
658           st %o3,[%o1]
659           subcc %o2,1,%o2
660           bne 1b
661          _ add %o1,4,%o1
662 2:      retl
663        _ mov %o1,%o0
664 #endif
665 #if COUNTER_LOOPS
666         subcc %g0,%o2,%o2       // %o2 = -count
667         be 2f
668        _ sub %o1,4,%o1
669         sll %o2,2,%o2           // %o2 = -4*count
670         sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
671         sub %o1,%o2,%o1         // %o1 = &destptr[count-1]
672 1:        ld [%o0+%o2],%o3      // nächstes Digit holen
673           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
674           bne 1b
675          _ st %o3,[%o1+%o2]     // Digit ablegen
676 2:      retl
677        _ add %o1,4,%o0
678 #endif
679
680 // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
681         DECLARE_FUNCTION(copy_loop_down)
682 C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
683 #if STANDARD_LOOPS
684         andcc %o2,%o2,%g0
685         be 2f
686        _ sub %o0,4,%o0
687 1:        ld [%o0],%o3
688           sub %o1,4,%o1
689           st %o3,[%o1]
690           subcc %o2,1,%o2
691           bne 1b
692          _ sub %o0,4,%o0
693 2:      retl
694        _ mov %o1,%o0
695 #endif
696 #if COUNTER_LOOPS
697         andcc %o2,%o2,%g0
698         be 2f
699        _ sub %o0,4,%o0
700         sll %o2,2,%o2           // %o2 = 4*count
701         sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
702         sub %o1,%o2,%o1         // %o1 = &destptr[-count]
703 1:        ld [%o0+%o2],%o3      // nächstes Digit holen
704           subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
705           bne 1b
706          _ st %o3,[%o1+%o2]     // Digit ablegen
707 2:      retl
708        _ mov %o1,%o0
709 #endif
710
711 // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
712         DECLARE_FUNCTION(fill_loop_up)
713 C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
714 #if STANDARD_LOOPS
715         andcc %o1,%o1,%g0
716         be 2f
717        _ nop
718 1:        st %o2,[%o0]
719           subcc %o1,1,%o1
720           bne 1b
721          _ add %o0,4,%o0
722 2:      retl
723        _ nop
724 #endif
725 #if COUNTER_LOOPS
726         subcc %g0,%o1,%o1       // %o1 = -count
727         be 2f
728        _ sub %o0,4,%o0
729         sll %o1,2,%o1           // %o1 = -4*count
730         sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
731 1:        addcc %o1,4,%o1       // Zähler "erniedrigen", Pointer erhöhen
732           bne 1b
733          _ st %o2,[%o0+%o1]     // Digit ablegen
734 2:      retl
735        _ add %o0,4,%o0
736 #endif
737
738 // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
739         DECLARE_FUNCTION(fill_loop_down)
740 C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
741 #if STANDARD_LOOPS
742         andcc %o1,%o1,%g0
743         be 2f
744        _ sub %o0,4,%o0
745 1:        st %o2,[%o0]
746           subcc %o1,1,%o1
747           bne 1b
748          _ sub %o0,4,%o0
749 2:      retl
750        _ add %o0,4,%o0
751 #endif
752 #if COUNTER_LOOPS
753         andcc %o1,%o1,%g0
754         be 2f
755        _ sll %o1,2,%o1          // %o1 = 4*count
756         sub %o0,%o1,%o0         // %o0 = &destptr[-count]
757 1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
758           bne 1b
759          _ st %o2,[%o0+%o1]     // Digit ablegen
760 2:      retl
761        _ nop
762 #endif
763
764 // extern uintD* clear_loop_up (uintD* destptr, uintC count);
765         DECLARE_FUNCTION(clear_loop_up)
766 C(clear_loop_up:) // Input in %o0,%o1, Output in %o0
767 #if STANDARD_LOOPS
768         andcc %o1,%o1,%g0
769         be 2f
770        _ nop
771 1:        st %g0,[%o0]
772           subcc %o1,1,%o1
773           bne 1b
774          _ add %o0,4,%o0
775 2:      retl
776        _ nop
777 #endif
778 #if COUNTER_LOOPS
779         subcc %g0,%o1,%o1       // %o1 = -count
780         be 2f
781        _ sub %o0,4,%o0
782         sll %o1,2,%o1           // %o1 = -4*count
783         sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
784 1:        addcc %o1,4,%o1       // Zähler "erniedrigen", Pointer erhöhen
785           bne 1b
786          _ st %g0,[%o0+%o1]     // Digit 0 ablegen
787 2:      retl
788        _ add %o0,4,%o0
789 #endif
790
791 // extern uintD* clear_loop_down (uintD* destptr, uintC count);
792         DECLARE_FUNCTION(clear_loop_down)
793 C(clear_loop_down:) // Input in %o0,%o1, Output in %o0
794 #if STANDARD_LOOPS
795         andcc %o1,%o1,%g0
796         be 2f
797        _ sub %o0,4,%o0
798 1:        st %g0,[%o0]
799           subcc %o1,1,%o1
800           bne 1b
801          _ sub %o0,4,%o0
802 2:      retl
803        _ add %o0,4,%o0
804 #endif
805 #if COUNTER_LOOPS
806         andcc %o1,%o1,%g0
807         be 2f
808        _ sll %o1,2,%o1          // %o1 = 4*count
809         sub %o0,%o1,%o0         // %o0 = &destptr[-count]
810 1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
811           bne 1b
812          _ st %g0,[%o0+%o1]     // Digit 0 ablegen
813 2:      retl
814        _ nop
815 #endif
816
817 // extern boolean test_loop_up (uintD* ptr, uintC count);
818         DECLARE_FUNCTION(test_loop_up)
819 C(test_loop_up:) // Input in %o0,%o1, Output in %o0
820 #if STANDARD_LOOPS
821         andcc %o1,%o1,%g0
822         be 2f
823        _ nop
824           ld [%o0],%o2
825 1:        add %o0,4,%o0
826           andcc %o2,%o2,%g0
827           bne 3f
828          _ subcc %o1,1,%o1
829           bne,a 1b
830          __ ld [%o0],%o2
831 2:      retl
832        _ mov 0,%o0
833 3:      retl
834        _ mov 1,%o0
835 #endif
836 #if COUNTER_LOOPS
837         subcc %g0,%o1,%o1       // %o1 = -count
838         be 2f
839        _ sll %o1,2,%o1          // %o1 = -4*count
840         sub %o0,%o1,%o0         // %o0 = &ptr[count]
841           ld [%o0+%o1],%o2      // nächstes Digit holen
842 1:        andcc %o2,%o2,%g0     // testen
843           bne 3f
844          _ addcc %o1,4,%o1      // Zähler "erniedrigen", Pointer erhöhen
845           bne,a 1b
846          __ ld [%o0+%o1],%o2    // nächstes Digit holen
847 2:      retl
848        _ mov 0,%o0
849 3:      retl
850        _ mov 1,%o0
851 #endif
852
853 // extern boolean test_loop_down (uintD* ptr, uintC count);
854         DECLARE_FUNCTION(test_loop_down)
855 C(test_loop_down:) // Input in %o0,%o1, Output in %o0
856 #if STANDARD_LOOPS
857         andcc %o1,%o1,%g0
858         be 2f
859        _ sub %o0,4,%o0
860           ld [%o0],%o2
861 1:        sub %o0,4,%o0
862           andcc %o2,%o2,%g0
863           bne 3f
864          _ subcc %o1,1,%o1
865           bne,a 1b
866          __ ld [%o0],%o2
867 2:      retl
868        _ mov 0,%o0
869 3:      retl
870        _ mov 1,%o0
871 #endif
872 #if COUNTER_LOOPS
873         sll %o1,2,%o1           // %o1 = 4*count
874         sub %o0,%o1,%o0         // %o0 = &ptr[-count]
875         subcc %o1,4,%o1
876         bcs 4f
877        _ nop
878           ld [%o0+%o1],%o2      // nächstes Digit holen
879 1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
880           bcs 3f
881          _ andcc %o2,%o2,%g0    // testen
882           be,a 1b
883          __ ld [%o0+%o1],%o2    // nächstes Digit holen
884 2:      retl
885        _ mov 1,%o0
886 3:      bne 2b
887        _ nop
888 4:      retl
889        _ mov 0,%o0
890 #endif
891
892 #if CL_DS_BIG_ENDIAN_P
893
894 // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
895         DECLARE_FUNCTION(or_loop_up)
896 C(or_loop_up:) // Input in %o0,%o1,%o2
897 #if SLOW_LOOPS
898         andcc %o2,%o2,%g0
899         be 2f
900        _ nop
901 1:        ld [%o0],%o3
902           ld [%o1],%o4
903           add %o1,4,%o1
904           or %o3,%o4,%o3
905           st %o3,[%o0]
906           subcc %o2,1,%o2
907           bne 1b
908          _ add %o0,4,%o0
909 2:      retl
910        _ nop
911 #endif
912 #if STANDARD_LOOPS
913         andcc %o2,%o2,%g0
914         be 2f
915        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
916 1:        ld [%o0],%o3          // *xptr
917           ld [%o0+%o1],%o4      // *yptr
918           subcc %o2,1,%o2
919           or %o3,%o4,%o3        // verknüpfen
920           st %o3,[%o0]          // =: *xptr
921           bne 1b
922          _ add %o0,4,%o0        // xptr++, yptr++
923 2:      retl
924        _ nop
925 #endif
926 #if COUNTER_LOOPS
927         subcc %g0,%o2,%o2       // %o2 = -count
928         be 2f
929        _ sub %o0,4,%o0
930         sll %o2,2,%o2           // %o2 = -4*count
931         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
932         sub %o1,%o2,%o1         // %o1 = &yptr[count]
933 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
934           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
935           ld [%o0+%o2],%o4      // noch ein Digit holen
936           or %o4,%o3,%o3        // beide verknüpfen
937           bne 1b
938          _ st %o3,[%o1+%o2]     // Digit ablegen
939 2:      retl
940        _ nop
941 #endif
942
943 #endif
944
945 // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
946         DECLARE_FUNCTION(xor_loop_up)
947 C(xor_loop_up:) // Input in %o0,%o1,%o2
948 #if SLOW_LOOPS
949         andcc %o2,%o2,%g0
950         be 2f
951        _ nop
952 1:        ld [%o0],%o3
953           ld [%o1],%o4
954           add %o1,4,%o1
955           xor %o3,%o4,%o3
956           st %o3,[%o0]
957           subcc %o2,1,%o2
958           bne 1b
959          _ add %o0,4,%o0
960 2:      retl
961        _ nop
962 #endif
963 #if STANDARD_LOOPS
964         andcc %o2,%o2,%g0
965         be 2f
966        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
967 1:        ld [%o0],%o3          // *xptr
968           ld [%o0+%o1],%o4      // *yptr
969           subcc %o2,1,%o2
970           xor %o3,%o4,%o3       // verknüpfen
971           st %o3,[%o0]          // =: *xptr
972           bne 1b
973          _ add %o0,4,%o0        // xptr++, yptr++
974 2:      retl
975        _ nop
976 #endif
977 #if COUNTER_LOOPS
978         subcc %g0,%o2,%o2       // %o2 = -count
979         be 2f
980        _ sub %o0,4,%o0
981         sll %o2,2,%o2           // %o2 = -4*count
982         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
983         sub %o1,%o2,%o1         // %o1 = &yptr[count]
984 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
985           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
986           ld [%o0+%o2],%o4      // noch ein Digit holen
987           xor %o4,%o3,%o3       // beide verknüpfen
988           bne 1b
989          _ st %o3,[%o1+%o2]     // Digit ablegen
990 2:      retl
991        _ nop
992 #endif
993
994 #if CL_DS_BIG_ENDIAN_P
995
996 // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
997         DECLARE_FUNCTION(and_loop_up)
998 C(and_loop_up:) // Input in %o0,%o1,%o2
999 #if SLOW_LOOPS
1000         andcc %o2,%o2,%g0
1001         be 2f
1002        _ nop
1003 1:        ld [%o0],%o3
1004           ld [%o1],%o4
1005           add %o1,4,%o1
1006           and %o3,%o4,%o3
1007           st %o3,[%o0]
1008           subcc %o2,1,%o2
1009           bne 1b
1010          _ add %o0,4,%o0
1011 2:      retl
1012        _ nop
1013 #endif
1014 #if STANDARD_LOOPS
1015         andcc %o2,%o2,%g0
1016         be 2f
1017        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1018 1:        ld [%o0],%o3          // *xptr
1019           ld [%o0+%o1],%o4      // *yptr
1020           subcc %o2,1,%o2
1021           and %o3,%o4,%o3       // verknüpfen
1022           st %o3,[%o0]          // =: *xptr
1023           bne 1b
1024          _ add %o0,4,%o0        // xptr++, yptr++
1025 2:      retl
1026        _ nop
1027 #endif
1028 #if COUNTER_LOOPS
1029         subcc %g0,%o2,%o2       // %o2 = -count
1030         be 2f
1031        _ sub %o0,4,%o0
1032         sll %o2,2,%o2           // %o2 = -4*count
1033         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
1034         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1035 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
1036           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
1037           ld [%o0+%o2],%o4      // noch ein Digit holen
1038           and %o4,%o3,%o3       // beide verknüpfen
1039           bne 1b
1040          _ st %o3,[%o1+%o2]     // Digit ablegen
1041 2:      retl
1042        _ nop
1043 #endif
1044
1045 // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
1046         DECLARE_FUNCTION(eqv_loop_up)
1047 C(eqv_loop_up:) // Input in %o0,%o1,%o2
1048 #if SLOW_LOOPS
1049         andcc %o2,%o2,%g0
1050         be 2f
1051        _ nop
1052 1:        ld [%o0],%o3
1053           ld [%o1],%o4
1054           add %o1,4,%o1
1055           xnor %o3,%o4,%o3
1056           st %o3,[%o0]
1057           subcc %o2,1,%o2
1058           bne 1b
1059          _ add %o0,4,%o0
1060 2:      retl
1061        _ nop
1062 #endif
1063 #if STANDARD_LOOPS
1064         andcc %o2,%o2,%g0
1065         be 2f
1066        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1067 1:        ld [%o0],%o3          // *xptr
1068           ld [%o0+%o1],%o4      // *yptr
1069           subcc %o2,1,%o2
1070           xnor %o3,%o4,%o3      // verknüpfen
1071           st %o3,[%o0]          // =: *xptr
1072           bne 1b
1073          _ add %o0,4,%o0        // xptr++, yptr++
1074 2:      retl
1075        _ nop
1076 #endif
1077 #if COUNTER_LOOPS
1078         subcc %g0,%o2,%o2       // %o2 = -count
1079         be 2f
1080        _ sub %o0,4,%o0
1081         sll %o2,2,%o2           // %o2 = -4*count
1082         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
1083         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1084 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
1085           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
1086           ld [%o0+%o2],%o4      // noch ein Digit holen
1087           xnor %o4,%o3,%o3      // beide verknüpfen
1088           bne 1b
1089          _ st %o3,[%o1+%o2]     // Digit ablegen
1090 2:      retl
1091        _ nop
1092 #endif
1093
1094 // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
1095         DECLARE_FUNCTION(nand_loop_up)
1096 C(nand_loop_up:) // Input in %o0,%o1,%o2
1097 #if SLOW_LOOPS
1098         andcc %o2,%o2,%g0
1099         be 2f
1100        _ nop
1101 1:        ld [%o0],%o3
1102           ld [%o1],%o4
1103           add %o1,4,%o1
1104           and %o3,%o4,%o3
1105           xor %o3,-1,%o3
1106           st %o3,[%o0]
1107           subcc %o2,1,%o2
1108           bne 1b
1109          _ add %o0,4,%o0
1110 2:      retl
1111        _ nop
1112 #endif
1113 #if STANDARD_LOOPS
1114         andcc %o2,%o2,%g0
1115         be 2f
1116        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1117 1:        ld [%o0],%o3          // *xptr
1118           ld [%o0+%o1],%o4      // *yptr
1119           subcc %o2,1,%o2
1120           and %o3,%o4,%o3       // verknüpfen
1121           xor %o3,-1,%o3
1122           st %o3,[%o0]          // =: *xptr
1123           bne 1b
1124          _ add %o0,4,%o0        // xptr++, yptr++
1125 2:      retl
1126        _ nop
1127 #endif
1128 #if COUNTER_LOOPS
1129         subcc %g0,%o2,%o2       // %o2 = -count
1130         be 2f
1131        _ sub %o0,4,%o0
1132         sll %o2,2,%o2           // %o2 = -4*count
1133         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
1134         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1135 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
1136           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
1137           ld [%o0+%o2],%o4      // noch ein Digit holen
1138           and %o4,%o3,%o3       // beide verknüpfen
1139           xor %o3,-1,%o3
1140           bne 1b
1141          _ st %o3,[%o1+%o2]     // Digit ablegen
1142 2:      retl
1143        _ nop
1144 #endif
1145
1146 // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
1147         DECLARE_FUNCTION(nor_loop_up)
1148 C(nor_loop_up:) // Input in %o0,%o1,%o2
1149 #if SLOW_LOOPS
1150         andcc %o2,%o2,%g0
1151         be 2f
1152        _ nop
1153 1:        ld [%o0],%o3
1154           ld [%o1],%o4
1155           add %o1,4,%o1
1156           or %o3,%o4,%o3
1157           xor %o3,-1,%o3
1158           st %o3,[%o0]
1159           subcc %o2,1,%o2
1160           bne 1b
1161          _ add %o0,4,%o0
1162 2:      retl
1163        _ nop
1164 #endif
1165 #if STANDARD_LOOPS
1166         andcc %o2,%o2,%g0
1167         be 2f
1168        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1169 1:        ld [%o0],%o3          // *xptr
1170           ld [%o0+%o1],%o4      // *yptr
1171           subcc %o2,1,%o2
1172           or %o3,%o4,%o3        // verknüpfen
1173           xor %o3,-1,%o3
1174           st %o3,[%o0]          // =: *xptr
1175           bne 1b
1176          _ add %o0,4,%o0        // xptr++, yptr++
1177 2:      retl
1178        _ nop
1179 #endif
1180 #if COUNTER_LOOPS
1181         subcc %g0,%o2,%o2       // %o2 = -count
1182         be 2f
1183        _ sub %o0,4,%o0
1184         sll %o2,2,%o2           // %o2 = -4*count
1185         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
1186         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1187 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
1188           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
1189           ld [%o0+%o2],%o4      // noch ein Digit holen
1190           or %o4,%o3,%o3        // beide verknüpfen
1191           xor %o3,-1,%o3
1192           bne 1b
1193          _ st %o3,[%o1+%o2]     // Digit ablegen
1194 2:      retl
1195        _ nop
1196 #endif
1197
1198 // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
1199         DECLARE_FUNCTION(andc2_loop_up)
1200 C(andc2_loop_up:) // Input in %o0,%o1,%o2
1201 #if SLOW_LOOPS
1202         andcc %o2,%o2,%g0
1203         be 2f
1204        _ nop
1205 1:        ld [%o0],%o3
1206           ld [%o1],%o4
1207           add %o1,4,%o1
1208           andn %o3,%o4,%o3
1209           st %o3,[%o0]
1210           subcc %o2,1,%o2
1211           bne 1b
1212          _ add %o0,4,%o0
1213 2:      retl
1214        _ nop
1215 #endif
1216 #if STANDARD_LOOPS
1217         andcc %o2,%o2,%g0
1218         be 2f
1219        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1220 1:        ld [%o0],%o3          // *xptr
1221           ld [%o0+%o1],%o4      // *yptr
1222           subcc %o2,1,%o2
1223           andn %o3,%o4,%o3      // verknüpfen
1224           st %o3,[%o0]          // =: *xptr
1225           bne 1b
1226          _ add %o0,4,%o0        // xptr++, yptr++
1227 2:      retl
1228        _ nop
1229 #endif
1230 #if COUNTER_LOOPS
1231         subcc %g0,%o2,%o2       // %o2 = -count
1232         be 2f
1233        _ sub %o0,4,%o0
1234         sll %o2,2,%o2           // %o2 = -4*count
1235         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
1236         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1237 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
1238           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
1239           ld [%o0+%o2],%o4      // noch ein Digit holen
1240           andn %o4,%o3,%o3      // beide verknüpfen
1241           bne 1b
1242          _ st %o3,[%o1+%o2]     // Digit ablegen
1243 2:      retl
1244        _ nop
1245 #endif
1246
1247 // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
1248         DECLARE_FUNCTION(orc2_loop_up)
1249 C(orc2_loop_up:) // Input in %o0,%o1,%o2
1250 #if SLOW_LOOPS
1251         andcc %o2,%o2,%g0
1252         be 2f
1253        _ nop
1254 1:        ld [%o0],%o3
1255           ld [%o1],%o4
1256           add %o1,4,%o1
1257           orn %o3,%o4,%o3
1258           st %o3,[%o0]
1259           subcc %o2,1,%o2
1260           bne 1b
1261          _ add %o0,4,%o0
1262 2:      retl
1263        _ nop
1264 #endif
1265 #if STANDARD_LOOPS
1266         andcc %o2,%o2,%g0
1267         be 2f
1268        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
1269 1:        ld [%o0],%o3          // *xptr
1270           ld [%o0+%o1],%o4      // *yptr
1271           subcc %o2,1,%o2
1272           orn %o3,%o4,%o3       // verknüpfen
1273           st %o3,[%o0]          // =: *xptr
1274           bne 1b
1275          _ add %o0,4,%o0        // xptr++, yptr++
1276 2:      retl
1277        _ nop
1278 #endif
1279 #if COUNTER_LOOPS
1280         subcc %g0,%o2,%o2       // %o2 = -count
1281         be 2f
1282        _ sub %o0,4,%o0
1283         sll %o2,2,%o2           // %o2 = -4*count
1284         sub %o0,%o2,%o0         // %o0 = &xptr[count-1]
1285         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1286 1:        ld [%o1+%o2],%o3      // nächstes Digit holen
1287           addcc %o2,4,%o2       // Zähler "erniedrigen", Pointer erhöhen
1288           ld [%o0+%o2],%o4      // noch ein Digit holen
1289           orn %o4,%o3,%o3       // beide verknüpfen
1290           bne 1b
1291          _ st %o3,[%o1+%o2]     // Digit ablegen
1292 2:      retl
1293        _ nop
1294 #endif
1295
1296 // extern void not_loop_up (uintD* xptr, uintC count);
1297         DECLARE_FUNCTION(not_loop_up)
1298 C(not_loop_up:) // Input in %o0,%o1
1299 #if STANDARD_LOOPS
1300         andcc %o1,%o1,%g0
1301         be 2f
1302        _ nop
1303 1:        ld [%o0],%o2
1304           subcc %o1,1,%o1
1305           xor %o2,-1,%o2
1306           st %o2,[%o0]
1307           bne 1b
1308          _ add %o0,4,%o0
1309 2:      retl
1310        _ nop
1311 #endif
1312 #if COUNTER_LOOPS
1313         subcc %g0,%o1,%o1       // %o1 = -count
1314         be 2f
1315        _ sub %o0,4,%o0
1316         sll %o1,2,%o1           // %o1 = -4*count
1317         sub %o0,%o1,%o0         // %o0 = &destptr[count-1]
1318 1:        addcc %o1,4,%o1       // Zähler "erniedrigen", Pointer erhöhen
1319           ld [%o0+%o1],%o2      // nächstes Digit holen
1320           xor %o2,-1,%o2
1321           bne 1b
1322          _ st %o2,[%o0+%o1]     // Digit ablegen
1323 2:      retl
1324        _ nop
1325 #endif
1326
1327 // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
1328         DECLARE_FUNCTION(and_test_loop_up)
1329 C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1330 #if STANDARD_LOOPS
1331         andcc %o2,%o2,%g0
1332         be 2f
1333        _ nop
1334 1:        ld [%o0],%o3
1335           ld [%o1],%o4
1336           add %o0,4,%o0
1337           andcc %o3,%o4,%g0
1338           bne 3f
1339          _ subcc %o2,1,%o2
1340           bne 1b
1341          _ add %o1,4,%o1
1342 2:      retl
1343        _ mov 0,%o0
1344 3:      retl
1345        _ mov 1,%o0
1346 #endif
1347 #if COUNTER_LOOPS
1348         subcc %g0,%o2,%o2       // %o2 = -count
1349         be 2f
1350        _ sll %o2,2,%o2          // %o2 = -4*count
1351         sub %o0,%o2,%o0         // %o0 = &xptr[count]
1352         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1353           ld [%o0+%o2],%o3      // nächstes Digit holen
1354 1:        ld [%o1+%o2],%o4      // noch ein Digit holen
1355           andcc %o3,%o4,%g0     // beide verknüpfen
1356           bne 3f
1357          _ addcc %o2,4,%o2      // Zähler "erniedrigen", Pointer erhöhen
1358           bne,a 1b
1359          __ ld [%o0+%o2],%o3    // nächstes Digit holen
1360 2:      retl
1361        _ mov 0,%o0
1362 3:      retl
1363        _ mov 1,%o0
1364 #endif
1365
1366 #endif
1367
1368 // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
1369         DECLARE_FUNCTION(compare_loop_up)
1370 C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1371 #if STANDARD_LOOPS
1372         andcc %o2,%o2,%g0
1373         be 2f
1374        _ nop
1375           ld [%o0],%o3
1376 1:        ld [%o1],%o4
1377           add %o0,4,%o0
1378           subcc %o3,%o4,%g0
1379           bne 3f
1380          _ add %o1,4,%o1
1381           subcc %o2,1,%o2
1382           bne,a 1b
1383          __ ld [%o0],%o3
1384 2:      retl
1385        _ mov 0,%o0
1386 3:      blu 4f
1387        _ nop
1388         retl
1389        _ mov 1,%o0
1390 4:      retl
1391        _ mov -1,%o0
1392 #endif
1393 #if COUNTER_LOOPS
1394         subcc %g0,%o2,%o2       // %o2 = -count
1395         be 2f
1396        _ sll %o2,2,%o2          // %o2 = -4*count
1397         sub %o0,%o2,%o0         // %o0 = &xptr[count]
1398         sub %o1,%o2,%o1         // %o1 = &yptr[count]
1399           ld [%o0+%o2],%o3      // nächstes Digit holen
1400 1:        ld [%o1+%o2],%o4      // noch ein Digit holen
1401           subcc %o3,%o4,%g0     // vergleichen
1402           bne 3f
1403          _ addcc %o2,4,%o2      // Zähler "erniedrigen", Pointer erhöhen
1404           bne,a 1b
1405          __ ld [%o0+%o2],%o3    // nächstes Digit holen
1406 2:      retl
1407        _ mov 0,%o0
1408 3:      subcc %o3,%o4,%g0       // nochmals vergleichen
1409         blu 4f
1410        _ nop
1411         retl
1412        _ mov 1,%o0
1413 4:      retl
1414        _ mov -1,%o0
1415 #endif
1416
1417 #if CL_DS_BIG_ENDIAN_P
1418
1419 // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1420         DECLARE_FUNCTION(add_loop_down)
1421 C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1422 #if STANDARD_LOOPS
1423         andcc %o3,%o3,%g0
1424         be 2f
1425        _ mov %g0,%g1            // Carry := 0
1426         sub %o0,4,%o0
1427 1:        ld [%o0],%o4          // source1-digit
1428           sub %o1,4,%o1
1429           ld [%o1],%o5          // source2-digit
1430           subcc %g0,%g1,%g0     // carry
1431           addxcc %o4,%o5,%o4    // addieren
1432           addx %g0,%g0,%g1      // neuer Carry
1433           sub %o2,4,%o2
1434           st %o4,[%o2]          // Digit ablegen
1435           subcc %o3,1,%o3
1436           bne 1b
1437          _ sub %o0,4,%o0
1438 2:      retl
1439        _ mov %g1,%o0
1440 #endif
1441 #if COUNTER_LOOPS
1442         andcc %o3,%o3,%g0
1443         be 2f
1444        _ mov %g0,%g1            // Carry := 0
1445         sub %o0,4,%o0
1446         sub %o1,4,%o1
1447         sll %o3,2,%o3           // %o3 = 4*count
1448         sub %o0,%o3,%o0         // %o0 = &sourceptr1[-count-1]
1449         sub %o1,%o3,%o1         // %o1 = &sourceptr2[-count-1]
1450         sub %o2,%o3,%o2         // %o2 = &destptr[-count]
1451 1:        ld [%o0+%o3],%o4      // source1-digit
1452           ld [%o1+%o3],%o5      // source2-digit
1453           subcc %g0,%g1,%g0     // carry
1454           addxcc %o4,%o5,%o4    // addieren
1455           addx %g0,%g0,%g1      // neuer Carry
1456           subcc %o3,4,%o3
1457           bne 1b
1458          _ st %o4,[%o2+%o3]     // Digit ablegen
1459 2:      retl
1460        _ mov %g1,%o0
1461 #endif
1462 #if UNROLLED_LOOPS
1463         and %o3,7,%o4           // count mod 8
1464         sll %o4,2,%o5
1465         sub %o0,%o5,%o0         // %o0 = &sourceptr1[-(count mod 8)]
1466         sub %o1,%o5,%o1         // %o1 = &sourceptr2[-(count mod 8)]
1467         sub %o2,%o5,%o2         // %o2 = &destptr[-(count mod 8)]
1468         sll %o4,4,%o4
1469 #ifdef PIC
1470         mov %o7,%g2             // save return address
1471         call 0f                 // put address of label 0 into %o7
1472        _ add %o7,144,%o5
1473 0:
1474 #else
1475         set _add_loop_down+176,%o5
1476 #endif
1477         sub %o5,%o4,%o5
1478         jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1479        _ subcc %g0,%g0,%g0      // carry löschen
1480 1:        subcc %g0,%g1,%g0     // carry
1481           ld [%o0+28],%o4       // source1-digit
1482           ld [%o1+28],%o5       // source2-digit
1483           addxcc %o5,%o4,%o5    // addieren
1484           st %o5,[%o2+28]       // Digit ablegen
1485           ld [%o0+24],%o4       // source1-digit
1486           ld [%o1+24],%o5       // source2-digit
1487           addxcc %o5,%o4,%o5    // addieren
1488           st %o5,[%o2+24]       // Digit ablegen
1489           ld [%o0+20],%o4       // source1-digit
1490           ld [%o1+20],%o5       // source2-digit
1491           addxcc %o5,%o4,%o5    // addieren
1492           st %o5,[%o2+20]       // Digit ablegen
1493           ld [%o0+16],%o4       // source1-digit
1494           ld [%o1+16],%o5       // source2-digit
1495           addxcc %o5,%o4,%o5    // addieren
1496           st %o5,[%o2+16]       // Digit ablegen
1497           ld [%o0+12],%o4       // source1-digit
1498           ld [%o1+12],%o5       // source2-digit
1499           addxcc %o5,%o4,%o5    // addieren
1500           st %o5,[%o2+12]       // Digit ablegen
1501           ld [%o0+8],%o4        // source1-digit
1502           ld [%o1+8],%o5        // source2-digit
1503           addxcc %o5,%o4,%o5    // addieren
1504           st %o5,[%o2+8]        // Digit ablegen
1505           ld [%o0+4],%o4        // source1-digit
1506           ld [%o1+4],%o5        // source2-digit
1507           addxcc %o5,%o4,%o5    // addieren
1508           st %o5,[%o2+4]        // Digit ablegen
1509           ld [%o0],%o4          // source1-digit
1510           ld [%o1],%o5          // source2-digit
1511           addxcc %o5,%o4,%o5    // addieren
1512           st %o5,[%o2]          // Digit ablegen
1513           addx %g0,%g0,%g1      // neuer Carry
1514           sub %o0,32,%o0
1515           sub %o1,32,%o1
1516           subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
1517           bcc 1b
1518          _ sub %o2,32,%o2
1519 #ifdef PIC
1520         jmp %g2+8
1521 #else
1522         retl
1523 #endif
1524        _ mov %g1,%o0
1525 #endif
1526
1527 // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
1528         DECLARE_FUNCTION(addto_loop_down)
1529 C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1530 #if STANDARD_LOOPS
1531         andcc %o2,%o2,%g0
1532         be 2f
1533        _ mov %g0,%o5            // Carry := 0
1534         sub %o0,4,%o0
1535 1:        ld [%o0],%o3          // source-digit
1536           sub %o1,4,%o1
1537           ld [%o1],%o4          // dest-digit
1538           subcc %g0,%o5,%g0     // carry
1539           addxcc %o4,%o3,%o4    // addieren
1540           addx %g0,%g0,%o5      // neuer Carry
1541           st %o4,[%o1]          // Digit ablegen
1542           subcc %o2,1,%o2
1543           bne 1b
1544          _ sub %o0,4,%o0
1545 2:      retl
1546        _ mov %o5,%o0
1547 #endif
1548 #if COUNTER_LOOPS
1549         andcc %o2,%o2,%g0
1550         be 2f
1551        _ mov %g0,%o5            // Carry := 0
1552         sub %o0,4,%o0
1553         sub %o1,4,%o1
1554         sll %o2,2,%o2           // %o2 = 4*count
1555         sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
1556         sub %o1,%o2,%o1         // %o1 = &destptr[-count-1]
1557           ld [%o0+%o2],%o3      // source-digit
1558 1:        ld [%o1+%o2],%o4      // dest-digit
1559           subcc %g0,%o5,%g0     // carry
1560           addxcc %o4,%o3,%o4    // addieren
1561           addx %g0,%g0,%o5      // neuer Carry
1562           st %o4,[%o1+%o2]      // Digit ablegen
1563           subcc %o2,4,%o2
1564           bne,a 1b
1565          __ ld [%o0+%o2],%o3    // source-digit
1566 2:      retl
1567        _ mov %o5,%o0
1568 #endif
1569 #if UNROLLED_LOOPS
1570         and %o2,7,%o3           // count mod 8
1571         sll %o3,2,%o4
1572         sub %o0,%o4,%o0         // %o0 = &sourceptr[-(count mod 8)]
1573         sub %o1,%o4,%o1         // %o1 = &destptr[-(count mod 8)]
1574         sll %o3,4,%o3
1575 #ifdef PIC
1576         mov %o7,%g2             // save return address
1577         call 0f                 // put address of label 0 into %o7
1578        _ add %o7,144,%o4
1579 0:
1580 #else
1581         set _addto_loop_down+172,%o4
1582 #endif
1583         sub %o4,%o3,%o4
1584         jmp %o4                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1585        _ subcc %g0,%g0,%g0      // carry löschen
1586 1:        subcc %g0,%o5,%g0     // carry
1587           ld [%o0+28],%o3       // source-digit
1588           ld [%o1+28],%o4       // dest-digit
1589           addxcc %o4,%o3,%o4    // addieren
1590           st %o4,[%o1+28]       // Digit ablegen
1591           ld [%o0+24],%o3       // source-digit
1592           ld [%o1+24],%o4       // dest-digit
1593           addxcc %o4,%o3,%o4    // addieren
1594           st %o4,[%o1+24]       // Digit ablegen
1595           ld [%o0+20],%o3       // source-digit
1596           ld [%o1+20],%o4       // dest-digit
1597           addxcc %o4,%o3,%o4    // addieren
1598           st %o4,[%o1+20]       // Digit ablegen
1599           ld [%o0+16],%o3       // source-digit
1600           ld [%o1+16],%o4       // dest-digit
1601           addxcc %o4,%o3,%o4    // addieren
1602           st %o4,[%o1+16]       // Digit ablegen
1603           ld [%o0+12],%o3       // source-digit
1604           ld [%o1+12],%o4       // dest-digit
1605           addxcc %o4,%o3,%o4    // addieren
1606           st %o4,[%o1+12]       // Digit ablegen
1607           ld [%o0+8],%o3        // source-digit
1608           ld [%o1+8],%o4        // dest-digit
1609           addxcc %o4,%o3,%o4    // addieren
1610           st %o4,[%o1+8]        // Digit ablegen
1611           ld [%o0+4],%o3        // source-digit
1612           ld [%o1+4],%o4        // dest-digit
1613           addxcc %o4,%o3,%o4    // addieren
1614           st %o4,[%o1+4]        // Digit ablegen
1615           ld [%o0],%o3          // source-digit
1616           ld [%o1],%o4          // dest-digit
1617           addxcc %o4,%o3,%o4    // addieren
1618           st %o4,[%o1]          // Digit ablegen
1619           addx %g0,%g0,%o5      // neuer Carry
1620           sub %o0,32,%o0
1621           subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
1622           bcc 1b
1623          _ sub %o1,32,%o1
1624 #ifdef PIC
1625         jmp %g2+8
1626 #else
1627         retl
1628 #endif
1629        _ mov %o5,%o0
1630 #endif
1631
1632 // extern uintD inc_loop_down (uintD* ptr, uintC count);
1633         DECLARE_FUNCTION(inc_loop_down)
1634 C(inc_loop_down:) // Input in %o0,%o1, Output in %o0
1635 #if STANDARD_LOOPS
1636         andcc %o1,%o1,%g0
1637         be 2f
1638        _ sub %o0,4,%o0
1639 1:        ld [%o0],%o2
1640           addcc %o2,1,%o2
1641           bne 3f
1642          _ st %o2,[%o0]
1643           subcc %o1,1,%o1
1644           bne 1b
1645          _ sub %o0,4,%o0
1646 2:      retl
1647        _ mov 1,%o0
1648 3:      retl
1649        _ mov 0,%o0
1650 #endif
1651 #if COUNTER_LOOPS
1652         andcc %o1,%o1,%g0
1653         be 2f
1654        _ sub %o0,4,%o0
1655         sll %o1,2,%o1           // %o1 = 4*count
1656         sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
1657           ld [%o0+%o1],%o2      // digit holen
1658 1:        addcc %o2,1,%o2       // incrementieren
1659           bne 3f
1660          _ st %o2,[%o0+%o1]     // ablegen
1661           subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
1662           bne,a 1b
1663          __ ld [%o0+%o1],%o2
1664 2:      retl
1665        _ mov 1,%o0
1666 3:      retl
1667        _ mov 0,%o0
1668 #endif
1669
1670 // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1671         DECLARE_FUNCTION(sub_loop_down)
1672 C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1673 #if STANDARD_LOOPS
1674         andcc %o3,%o3,%g0
1675         be 2f
1676        _ mov %g0,%g1            // Carry := 0
1677         sub %o0,4,%o0
1678 1:        ld [%o0],%o4          // source1-digit
1679           sub %o1,4,%o1
1680           ld [%o1],%o5          // source2-digit
1681           subcc %g0,%g1,%g0     // carry
1682           subxcc %o4,%o5,%o4    // subtrahieren
1683           addx %g0,%g0,%g1      // neuer Carry
1684           sub %o2,4,%o2
1685           st %o4,[%o2]          // Digit ablegen
1686           subcc %o3,1,%o3
1687           bne 1b
1688          _ sub %o0,4,%o0
1689 2:      retl
1690        _ mov %g1,%o0
1691 #endif
1692 #if COUNTER_LOOPS
1693         andcc %o3,%o3,%g0
1694         be 2f
1695        _ mov %g0,%g1            // Carry := 0
1696         sub %o0,4,%o0
1697         sub %o1,4,%o1
1698         sll %o3,2,%o3           // %o3 = 4*count
1699         sub %o0,%o3,%o0         // %o0 = &sourceptr1[-count-1]
1700         sub %o1,%o3,%o1         // %o1 = &sourceptr2[-count-1]
1701         sub %o2,%o3,%o2         // %o2 = &destptr[-count]
1702 1:        ld [%o0+%o3],%o4      // source1-digit
1703           ld [%o1+%o3],%o5      // source2-digit
1704           subcc %g0,%g1,%g0     // carry
1705           subxcc %o4,%o5,%o4    // subtrahieren
1706           addx %g0,%g0,%g1      // neuer Carry
1707           subcc %o3,4,%o3
1708           bne 1b
1709          _ st %o4,[%o2+%o3]     // Digit ablegen
1710 2:      retl
1711        _ mov %g1,%o0
1712 #endif
1713 #if UNROLLED_LOOPS
1714         and %o3,7,%o4           // count mod 8
1715         sll %o4,2,%o5
1716         sub %o0,%o5,%o0         // %o0 = &sourceptr1[-(count mod 8)]
1717         sub %o1,%o5,%o1         // %o1 = &sourceptr2[-(count mod 8)]
1718         sub %o2,%o5,%o2         // %o2 = &destptr[-(count mod 8)]
1719         sll %o4,4,%o4
1720 #ifdef PIC
1721         mov %o7,%g2             // save return address
1722         call 0f                 // put address of label 0 into %o7
1723        _ add %o7,144,%o5
1724 0:
1725 #else
1726         set _sub_loop_down+176,%o5
1727 #endif
1728         sub %o5,%o4,%o5
1729         jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1730        _ subcc %g0,%g0,%g0      // carry löschen
1731 1:        subcc %g0,%g1,%g0     // carry
1732           ld [%o0+28],%o4       // source1-digit
1733           ld [%o1+28],%o5       // source2-digit
1734           subxcc %o4,%o5,%o4    // subtrahieren
1735           st %o4,[%o2+28]       // Digit ablegen
1736           ld [%o0+24],%o4       // source1-digit
1737           ld [%o1+24],%o5       // source2-digit
1738           subxcc %o4,%o5,%o4    // subtrahieren
1739           st %o4,[%o2+24]       // Digit ablegen
1740           ld [%o0+20],%o4       // source1-digit
1741           ld [%o1+20],%o5       // source2-digit
1742           subxcc %o4,%o5,%o4    // subtrahieren
1743           st %o4,[%o2+20]       // Digit ablegen
1744           ld [%o0+16],%o4       // source1-digit
1745           ld [%o1+16],%o5       // source2-digit
1746           subxcc %o4,%o5,%o4    // subtrahieren
1747           st %o4,[%o2+16]       // Digit ablegen
1748           ld [%o0+12],%o4       // source1-digit
1749           ld [%o1+12],%o5       // source2-digit
1750           subxcc %o4,%o5,%o4    // subtrahieren
1751           st %o4,[%o2+12]       // Digit ablegen
1752           ld [%o0+8],%o4        // source1-digit
1753           ld [%o1+8],%o5        // source2-digit
1754           subxcc %o4,%o5,%o4    // subtrahieren
1755           st %o4,[%o2+8]        // Digit ablegen
1756           ld [%o0+4],%o4        // source1-digit
1757           ld [%o1+4],%o5        // source2-digit
1758           subxcc %o4,%o5,%o4    // subtrahieren
1759           st %o4,[%o2+4]        // Digit ablegen
1760           ld [%o0],%o4          // source1-digit
1761           ld [%o1],%o5          // source2-digit
1762           subxcc %o4,%o5,%o4    // subtrahieren
1763           st %o4,[%o2]          // Digit ablegen
1764           addx %g0,%g0,%g1      // neuer Carry
1765           sub %o0,32,%o0
1766           sub %o1,32,%o1
1767           subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
1768           bcc 1b
1769          _ sub %o2,32,%o2
1770 #ifdef PIC
1771         jmp %g2+8
1772 #else
1773         retl
1774 #endif
1775        _ mov %g1,%o0
1776 #endif
1777
1778 // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
1779         DECLARE_FUNCTION(subx_loop_down)
1780 C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
1781 #if STANDARD_LOOPS
1782         andcc %o3,%o3,%g0
1783         be 2f
1784        _ mov %o4,%g1            // Carry
1785         sub %o0,4,%o0
1786 1:        ld [%o0],%o4          // source1-digit
1787           sub %o1,4,%o1
1788           ld [%o1],%o5          // source2-digit
1789           subcc %g0,%g1,%g0     // carry
1790           subxcc %o4,%o5,%o4    // subtrahieren
1791           addx %g0,%g0,%g1      // neuer Carry
1792           sub %o2,4,%o2
1793           st %o4,[%o2]          // Digit ablegen
1794           subcc %o3,1,%o3
1795           bne 1b
1796          _ sub %o0,4,%o0
1797 2:      retl
1798        _ mov %g1,%o0
1799 #endif
1800 #if COUNTER_LOOPS
1801         andcc %o3,%o3,%g0
1802         be 2f
1803        _ mov %o4,%g1            // Carry
1804         sub %o0,4,%o0
1805         sub %o1,4,%o1
1806         sll %o3,2,%o3           // %o3 = 4*count
1807         sub %o0,%o3,%o0         // %o0 = &sourceptr1[-count-1]
1808         sub %o1,%o3,%o1         // %o1 = &sourceptr2[-count-1]
1809         sub %o2,%o3,%o2         // %o2 = &destptr[-count]
1810 1:        ld [%o0+%o3],%o4      // source1-digit
1811           ld [%o1+%o3],%o5      // source2-digit
1812           subcc %g0,%g1,%g0     // carry
1813           subxcc %o4,%o5,%o4    // subtrahieren
1814           addx %g0,%g0,%g1      // neuer Carry
1815           subcc %o3,4,%o3
1816           bne 1b
1817          _ st %o4,[%o2+%o3]     // Digit ablegen
1818 2:      retl
1819        _ mov %g1,%o0
1820 #endif
1821 #if UNROLLED_LOOPS
1822         and %o3,7,%o5           // count mod 8
1823         sll %o5,2,%g1
1824         sub %o0,%g1,%o0         // %o0 = &sourceptr1[-(count mod 8)]
1825         sub %o1,%g1,%o1         // %o1 = &sourceptr2[-(count mod 8)]
1826         sub %o2,%g1,%o2         // %o2 = &destptr[-(count mod 8)]
1827         sll %o5,4,%o5
1828 #ifdef PIC
1829         mov %o7,%g2             // save return address
1830         call 0f                 // put address of label 0 into %o7
1831        _ add %o7,144,%g1
1832 0:
1833 #else
1834         set _subx_loop_down+176,%g1
1835 #endif
1836         sub %g1,%o5,%g1
1837         jmp %g1                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1838        _ subcc %g0,%o4,%g0      // carry initialisieren
1839 1:        subcc %g0,%g1,%g0     // carry
1840           ld [%o0+28],%o4       // source1-digit
1841           ld [%o1+28],%o5       // source2-digit
1842           subxcc %o4,%o5,%o4    // subtrahieren
1843           st %o4,[%o2+28]       // Digit ablegen
1844           ld [%o0+24],%o4       // source1-digit
1845           ld [%o1+24],%o5       // source2-digit
1846           subxcc %o4,%o5,%o4    // subtrahieren
1847           st %o4,[%o2+24]       // Digit ablegen
1848           ld [%o0+20],%o4       // source1-digit
1849           ld [%o1+20],%o5       // source2-digit
1850           subxcc %o4,%o5,%o4    // subtrahieren
1851           st %o4,[%o2+20]       // Digit ablegen
1852           ld [%o0+16],%o4       // source1-digit
1853           ld [%o1+16],%o5       // source2-digit
1854           subxcc %o4,%o5,%o4    // subtrahieren
1855           st %o4,[%o2+16]       // Digit ablegen
1856           ld [%o0+12],%o4       // source1-digit
1857           ld [%o1+12],%o5       // source2-digit
1858           subxcc %o4,%o5,%o4    // subtrahieren
1859           st %o4,[%o2+12]       // Digit ablegen
1860           ld [%o0+8],%o4        // source1-digit
1861           ld [%o1+8],%o5        // source2-digit
1862           subxcc %o4,%o5,%o4    // subtrahieren
1863           st %o4,[%o2+8]        // Digit ablegen
1864           ld [%o0+4],%o4        // source1-digit
1865           ld [%o1+4],%o5        // source2-digit
1866           subxcc %o4,%o5,%o4    // subtrahieren
1867           st %o4,[%o2+4]        // Digit ablegen
1868           ld [%o0],%o4          // source1-digit
1869           ld [%o1],%o5          // source2-digit
1870           subxcc %o4,%o5,%o4    // subtrahieren
1871           st %o4,[%o2]          // Digit ablegen
1872           addx %g0,%g0,%g1      // neuer Carry
1873           sub %o0,32,%o0
1874           sub %o1,32,%o1
1875           subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
1876           bcc 1b
1877          _ sub %o2,32,%o2
1878 #ifdef PIC
1879         jmp %g2+8
1880 #else
1881         retl
1882 #endif
1883        _ mov %g1,%o0
1884 #endif
1885
1886 // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
1887         DECLARE_FUNCTION(subfrom_loop_down)
1888 C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1889 #if STANDARD_LOOPS
1890         andcc %o2,%o2,%g0
1891         be 2f
1892        _ mov %g0,%o5            // Carry := 0
1893         sub %o0,4,%o0
1894 1:        ld [%o0],%o3          // source-digit
1895           sub %o1,4,%o1
1896           ld [%o1],%o4          // dest-digit
1897           subcc %g0,%o5,%g0     // carry
1898           subxcc %o4,%o3,%o4    // subtrahieren
1899           addx %g0,%g0,%o5      // neuer Carry
1900           st %o4,[%o1]          // Digit ablegen
1901           subcc %o2,1,%o2
1902           bne 1b
1903          _ sub %o0,4,%o0
1904 2:      retl
1905        _ mov %o5,%o0
1906 #endif
1907 #if COUNTER_LOOPS
1908         andcc %o2,%o2,%g0
1909         be 2f
1910        _ mov %g0,%o5            // Carry := 0
1911         sub %o0,4,%o0
1912         sub %o1,4,%o1
1913         sll %o2,2,%o2           // %o2 = 4*count
1914         sub %o0,%o2,%o0         // %o0 = &sourceptr[-count-1]
1915         sub %o1,%o2,%o1         // %o1 = &destptr[-count-1]
1916           ld [%o0+%o2],%o3      // source-digit
1917 1:        ld [%o1+%o2],%o4      // dest-digit
1918           subcc %g0,%o5,%g0     // carry
1919           subxcc %o4,%o3,%o4    // subtrahieren
1920           addx %g0,%g0,%o5      // neuer Carry
1921           st %o4,[%o1+%o2]      // Digit ablegen
1922           subcc %o2,4,%o2
1923           bne,a 1b
1924          __ ld [%o0+%o2],%o3    // source-digit
1925 2:      retl
1926        _ mov %o5,%o0
1927 #endif
1928 #if UNROLLED_LOOPS
1929         and %o2,7,%o3           // count mod 8
1930         sll %o3,2,%o4
1931         sub %o0,%o4,%o0         // %o0 = &sourceptr[-(count mod 8)]
1932         sub %o1,%o4,%o1         // %o1 = &destptr[-(count mod 8)]
1933         sll %o3,4,%o3
1934 #ifdef PIC
1935         mov %o7,%g2             // save return address
1936         call 0f                 // put address of label 0 into %o7
1937        _ add %o7,144,%o4
1938 0:
1939 #else
1940         set _subfrom_loop_down+172,%o4
1941 #endif
1942         sub %o4,%o3,%o4
1943         jmp %o4                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1944        _ subcc %g0,%g0,%g0      // carry löschen
1945 1:        subcc %g0,%o5,%g0     // carry
1946           ld [%o0+28],%o3       // source-digit
1947           ld [%o1+28],%o4       // dest-digit
1948           subxcc %o4,%o3,%o4    // subtrahieren
1949           st %o4,[%o1+28]       // Digit ablegen
1950           ld [%o0+24],%o3       // source-digit
1951           ld [%o1+24],%o4       // dest-digit
1952           subxcc %o4,%o3,%o4    // subtrahieren
1953           st %o4,[%o1+24]       // Digit ablegen
1954           ld [%o0+20],%o3       // source-digit
1955           ld [%o1+20],%o4       // dest-digit
1956           subxcc %o4,%o3,%o4    // subtrahieren
1957           st %o4,[%o1+20]       // Digit ablegen
1958           ld [%o0+16],%o3       // source-digit
1959           ld [%o1+16],%o4       // dest-digit
1960           subxcc %o4,%o3,%o4    // subtrahieren
1961           st %o4,[%o1+16]       // Digit ablegen
1962           ld [%o0+12],%o3       // source-digit
1963           ld [%o1+12],%o4       // dest-digit
1964           subxcc %o4,%o3,%o4    // subtrahieren
1965           st %o4,[%o1+12]       // Digit ablegen
1966           ld [%o0+8],%o3        // source-digit
1967           ld [%o1+8],%o4        // dest-digit
1968           subxcc %o4,%o3,%o4    // subtrahieren
1969           st %o4,[%o1+8]        // Digit ablegen
1970           ld [%o0+4],%o3        // source-digit
1971           ld [%o1+4],%o4        // dest-digit
1972           subxcc %o4,%o3,%o4    // subtrahieren
1973           st %o4,[%o1+4]        // Digit ablegen
1974           ld [%o0],%o3          // source-digit
1975           ld [%o1],%o4          // dest-digit
1976           subxcc %o4,%o3,%o4    // subtrahieren
1977           st %o4,[%o1]          // Digit ablegen
1978           addx %g0,%g0,%o5      // neuer Carry
1979           sub %o0,32,%o0
1980           subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
1981           bcc 1b
1982          _ sub %o1,32,%o1
1983 #ifdef PIC
1984         jmp %g2+8
1985 #else
1986         retl
1987 #endif
1988        _ mov %o5,%o0
1989 #endif
1990
1991 // extern uintD dec_loop_down (uintD* ptr, uintC count);
1992         DECLARE_FUNCTION(dec_loop_down)
1993 C(dec_loop_down:) // Input in %o0,%o1, Output in %o0
1994 #if STANDARD_LOOPS
1995         andcc %o1,%o1,%g0
1996         be 2f
1997        _ sub %o0,4,%o0
1998 1:        ld [%o0],%o2
1999           subcc %o2,1,%o2
2000           bcc 3f
2001          _ st %o2,[%o0]
2002           subcc %o1,1,%o1
2003           bne 1b
2004          _ sub %o0,4,%o0
2005 2:      retl
2006        _ mov -1,%o0
2007 3:      retl
2008        _ mov 0,%o0
2009 #endif
2010 #if COUNTER_LOOPS
2011         andcc %o1,%o1,%g0
2012         be 2f
2013        _ sub %o0,4,%o0
2014         sll %o1,2,%o1           // %o1 = 4*count
2015         sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
2016           ld [%o0+%o1],%o2      // digit holen
2017 1:        subcc %o2,1,%o2       // decrementieren
2018           bcc 3f
2019          _ st %o2,[%o0+%o1]     // ablegen
2020           subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
2021           bne,a 1b
2022          __ ld [%o0+%o1],%o2
2023 2:      retl
2024        _ mov -1,%o0
2025 3:      retl
2026        _ mov 0,%o0
2027 #endif
2028
2029 // extern uintD neg_loop_down (uintD* ptr, uintC count);
2030         DECLARE_FUNCTION(neg_loop_down)
2031 C(neg_loop_down:) // Input in %o0,%o1, Output in %o0
2032 #if STANDARD_LOOPS
2033         // erstes Digit /=0 suchen:
2034         andcc %o1,%o1,%g0
2035         be 2f
2036        _ sub %o0,4,%o0
2037 1:        ld [%o0],%o2
2038           subcc %g0,%o2,%o2
2039           bne 3f
2040          _ subcc %o1,1,%o1
2041           bne 1b
2042          _ sub %o0,4,%o0
2043 2:      retl
2044        _ mov 0,%o0
2045 3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2046         st %o2,[%o0]            // 1 Digit negieren
2047         // alle anderen Digits invertieren:
2048         be 5f
2049        _ sub %o0,4,%o0
2050 4:        ld [%o0],%o2
2051           subcc %o1,1,%o1
2052           xor %o2,-1,%o2
2053           st %o2,[%o0]
2054           bne 4b
2055          _ sub %o0,4,%o0
2056 5:      retl
2057        _ mov -1,%o0
2058 #endif
2059 #if COUNTER_LOOPS
2060         // erstes Digit /=0 suchen:
2061         andcc %o1,%o1,%g0
2062         be 2f
2063        _ sub %o0,4,%o0
2064         sll %o1,2,%o1           // %o1 = 4*count
2065         sub %o0,%o1,%o0         // %o0 = &ptr[-count-1]
2066           ld [%o0+%o1],%o2      // digit holen
2067 1:        subcc %g0,%o2,%o2     // negieren, testen
2068           bne 3f
2069          _ subcc %o1,4,%o1      // Zähler erniedrigen, Pointer erniedrigen
2070           bne,a 1b
2071          __ ld [%o0+%o1],%o2
2072 2:      retl
2073        _ mov 0,%o0
2074 3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2075         // alle anderen Digits invertieren:
2076         add %o1,4,%o1
2077         st %o2,[%o0+%o1]        // ablegen
2078         subcc %o1,4,%o1
2079         be 5f
2080        _ nop
2081           ld [%o0+%o1],%o2
2082 4:        xor %o2,-1,%o2
2083           st %o2,[%o0+%o1]
2084           subcc %o1,4,%o1
2085           bne,a 4b
2086          __ ld [%o0+%o1],%o2
2087 5:      retl
2088        _ mov -1,%o0
2089 #endif
2090
2091 // extern uintD shift1left_loop_down (uintD* ptr, uintC count);
2092         DECLARE_FUNCTION(shift1left_loop_down)
2093 C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0
2094         andcc %o1,%o1,%g0
2095         be 2f
2096        _ mov 0,%o3              // Carry := 0
2097         sub %o0,4,%o0
2098 1:        ld [%o0],%o2          // Digit
2099           subcc %g0,%o3,%g0     // carry
2100           addxcc %o2,%o2,%o2    // shiften
2101           addx %g0,%g0,%o3      // neues Carry
2102           st %o2,[%o0]          // Digit ablegen
2103           subcc %o1,1,%o1
2104           bne 1b
2105          _ sub %o0,4,%o0
2106 2:      retl
2107        _ mov %o3,%o0
2108
2109 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
2110         DECLARE_FUNCTION(shiftleft_loop_down)
2111 C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2112         andcc %o1,%o1,%g0
2113         be 2f
2114        _ sub %g0,%o2,%g1        // 32-i (mod 32)
2115         sub %o0,4,%o0
2116 1:        ld [%o0],%o4          // Digit
2117           subcc %o1,1,%o1
2118           sll %o4,%o2,%o5       // dessen niedere (32-i) Bits
2119           or %o3,%o5,%o5        // mit dem alten Carry kombinieren
2120           st %o5,[%o0]          // Digit ablegen
2121           srl %o4,%g1,%o3       // dessen höchste i Bits liefern den neuen Carry
2122           bne 1b
2123          _ sub %o0,4,%o0
2124 2:      retl
2125        _ mov %o3,%o0
2126
2127 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
2128         DECLARE_FUNCTION(shiftleftcopy_loop_down)
2129 C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
2130         andcc %o2,%o2,%g0
2131         be 2f
2132        _ mov 0,%o4              // Carry := 0
2133         sub %g0,%o3,%g1         // 32-i (mod 32)
2134         sub %o0,4,%o0
2135 1:        ld [%o0],%o5          // Digit
2136           subcc %o2,1,%o2
2137           sll %o5,%o3,%g2       // dessen niedere (32-i) Bits
2138           or %o4,%g2,%g2        // mit dem alten Carry kombinieren
2139           sub %o1,4,%o1
2140           st %g2,[%o1]          // Digit ablegen
2141           srl %o5,%g1,%o4       // dessen höchste i Bits liefern den neuen Carry
2142           bne 1b
2143          _ sub %o0,4,%o0
2144 2:      retl
2145        _ mov %o4,%o0
2146
2147 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
2148         DECLARE_FUNCTION(shift1right_loop_up)
2149 C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
2150         andcc %o1,%o1,%g0
2151         be 2f
2152        _ sll %o2,31,%o2         // Carry
2153 1:        ld [%o0],%o3          // Digit
2154           subcc %o1,1,%o1
2155           srl %o3,1,%o4         // shiften
2156           or %o2,%o4,%o4        // und mit altem Carry kombinieren
2157           st %o4,[%o0]          // und ablegen
2158           sll %o3,31,%o2        // neuer Carry
2159           bne 1b
2160          _ add %o0,4,%o0
2161 2:      retl
2162        _ mov %o2,%o0
2163
2164 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
2165         DECLARE_FUNCTION(shiftright_loop_up)
2166 C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2167         sub %g0,%o2,%g1         // 32-i (mod 32)
2168         andcc %o1,%o1,%g0
2169         be 2f
2170        _ or %g0,%g0,%o3         // Carry := 0
2171 1:        ld [%o0],%o4          // Digit
2172           subcc %o1,1,%o1
2173           srl %o4,%o2,%o5       // shiften
2174           or %o3,%o5,%o5        // und mit altem Carry kombinieren
2175           st %o5,[%o0]          // und ablegen
2176           sll %o4,%g1,%o3       // neuer Carry
2177           bne 1b
2178          _ add %o0,4,%o0
2179 2:      retl
2180        _ mov %o3,%o0
2181
2182 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
2183         DECLARE_FUNCTION(shiftrightsigned_loop_up)
2184 C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2185         ld [%o0],%o4            // erstes Digit
2186         sub %g0,%o2,%g1         // 32-i (mod 32)
2187         sra %o4,%o2,%o5         // shiften
2188         st %o5,[%o0]            // und ablegen
2189         sll %o4,%g1,%o3         // neuer Carry
2190         subcc %o1,1,%o1
2191         be 2f
2192        _ add %o0,4,%o0
2193 1:        ld [%o0],%o4          // Digit
2194           subcc %o1,1,%o1
2195           srl %o4,%o2,%o5       // shiften
2196           or %o3,%o5,%o5        // und mit altem Carry kombinieren
2197           st %o5,[%o0]          // und ablegen
2198           sll %o4,%g1,%o3       // neuer Carry
2199           bne 1b
2200          _ add %o0,4,%o0
2201 2:      retl
2202        _ mov %o3,%o0
2203
2204 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
2205         DECLARE_FUNCTION(shiftrightcopy_loop_up)
2206 C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
2207         sub %g0,%o3,%g1         // 32-i (mod 32)
2208         andcc %o2,%o2,%g0
2209         be 2f
2210        _ sll %o4,%g1,%g2        // erster Carry
2211 1:        ld [%o0],%o4          // Digit
2212           add %o0,4,%o0
2213           srl %o4,%o3,%o5       // shiften
2214           or %g2,%o5,%o5        // und mit altem Carry kombinieren
2215           st %o5,[%o1]          // und ablegen
2216           sll %o4,%g1,%g2       // neuer Carry
2217           subcc %o2,1,%o2
2218           bne 1b
2219          _ add %o1,4,%o1
2220 2:      retl
2221        _ mov %g2,%o0
2222
2223 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
2224         DECLARE_FUNCTION(mulusmall_loop_down)
2225 C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0
2226         andcc %o2,%o2,%g0
2227         be 3f
2228        _ sub %o1,4,%o1
2229 1:        // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
2230           // und kleinen Carry %o3 dazu:
2231           mov %o0,%y
2232           ld [%o1],%o4          // Wartetakt!
2233           addcc %o3,%o3,%o5
2234           mulscc %o5,%o4,%o5
2235           mulscc %o5,%o4,%o5
2236           mulscc %o5,%o4,%o5
2237           mulscc %o5,%o4,%o5
2238           mulscc %o5,%o4,%o5
2239           mulscc %o5,%o4,%o5
2240           mulscc %o5,%g0,%o5
2241           // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y
2242           // ergeben das Resultat. (Die anderen Bits sind Null.)
2243           tst %o4               // Korrektur, falls %o4 negativ war
2244           bge 2f
2245          _ sra %o5,26,%o3       // 6 obere Bits von %o5 -> neuer Carry
2246           add %o3,%o0,%o3       // (falls %o4 negativ war, noch + %o0)
2247 2:        rd %y,%o4
2248           srl %o4,26,%o4        // 6 obere Bits von %y
2249           sll %o5,6,%o5         // 26 untere Bits von %o5
2250           or %o5,%o4,%o4        // neues Digit
2251           st %o4,[%o1]          // ablegen
2252           subcc %o2,1,%o2
2253           bne 1b
2254          _ sub %o1,4,%o1
2255 3:      retl
2256        _ mov %o3,%o0
2257
2258 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2259 #if !MULU32_INLINE
2260         DECLARE_FUNCTION(mulu_loop_down)
2261 C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
2262         save %sp,-96,%sp
2263         mov 0,%l0               // Carry
2264 1:        sub %i1,4,%i1
2265           ld [%i1],%o1          // nächstes Digit
2266           call _mulu32_         // mit digit multiplizieren
2267          _ mov %i0,%o0
2268           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
2269           addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
2270           sub %i2,4,%i2
2271           subcc %i3,1,%i3
2272           bne 1b
2273          _ st %o0,[%i2]         // Low-Digit ablegen
2274         st %l0,[%i2-4]          // letzten Carry ablegen
2275         ret
2276        _ restore
2277 #else
2278         DECLARE_FUNCTION(mulu_loop_down)
2279 C(mulu_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1
2280         mov 0,%o4               // Carry
2281 1:        ld [%o1-4],%g1        // nächstes Digit
2282           // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
2283 #ifdef sparcv8
2284           sub     %o1,4,%o1
2285           umul    %g1,%o0,%g1
2286           rd      %y,%o5
2287 #else
2288           mov     %g1,%y
2289           sub     %o1,4,%o1     // Wartetakt!
2290           andcc   %g0,%g0,%o5
2291           mulscc  %o5,%o0,%o5
2292           mulscc  %o5,%o0,%o5
2293           mulscc  %o5,%o0,%o5
2294           mulscc  %o5,%o0,%o5
2295           mulscc  %o5,%o0,%o5
2296           mulscc  %o5,%o0,%o5
2297           mulscc  %o5,%o0,%o5
2298           mulscc  %o5,%o0,%o5
2299           mulscc  %o5,%o0,%o5
2300           mulscc  %o5,%o0,%o5
2301           mulscc  %o5,%o0,%o5
2302           mulscc  %o5,%o0,%o5
2303           mulscc  %o5,%o0,%o5
2304           mulscc  %o5,%o0,%o5
2305           mulscc  %o5,%o0,%o5
2306           mulscc  %o5,%o0,%o5
2307           mulscc  %o5,%o0,%o5
2308           mulscc  %o5,%o0,%o5
2309           mulscc  %o5,%o0,%o5
2310           mulscc  %o5,%o0,%o5
2311           mulscc  %o5,%o0,%o5
2312           mulscc  %o5,%o0,%o5
2313           mulscc  %o5,%o0,%o5
2314           mulscc  %o5,%o0,%o5
2315           mulscc  %o5,%o0,%o5
2316           mulscc  %o5,%o0,%o5
2317           mulscc  %o5,%o0,%o5
2318           mulscc  %o5,%o0,%o5
2319           mulscc  %o5,%o0,%o5
2320           mulscc  %o5,%o0,%o5
2321           mulscc  %o5,%o0,%o5
2322           mulscc  %o5,%o0,%o5
2323           mulscc  %o5,%g0,%o5
2324           tst     %o0
2325           bl,a    2f
2326          __ add     %o5,%g1,%o5
2327 2:        rd      %y,%g1
2328 #endif
2329           addcc %o4,%g1,%g1     // und bisherigen Carry addieren
2330           addx %g0,%o5,%o4      // High-Digit gibt neuen Carry
2331           sub %o2,4,%o2
2332           subcc %o3,1,%o3
2333           bne 1b
2334          _ st %g1,[%o2]         // Low-Digit ablegen
2335         retl
2336        _ st %o4,[%o2-4]         // letzten Carry ablegen
2337 #endif
2338
2339 // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2340         DECLARE_FUNCTION(muluadd_loop_down)
2341 C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2342 #if !MULU32_INLINE
2343         save %sp,-96,%sp
2344         mov 0,%l0               // Carry
2345 1:        sub %i1,4,%i1
2346           ld [%i1],%o1          // nächstes source-Digit
2347           call _mulu32_         // mit digit multiplizieren
2348          _ mov %i0,%o0
2349           sub %i2,4,%i2
2350           ld [%i2],%o1          // nächstes dest-digit
2351           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
2352           addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
2353           addcc %o1,%o0,%o0     // addieren
2354           addx %g0,%l0,%l0
2355           subcc %i3,1,%i3
2356           bne 1b
2357          _ st %o0,[%i2]         // Low-Digit ablegen
2358         mov %l0,%i0             // letzter Carry
2359         ret
2360        _ restore
2361 #else
2362         save %sp,-96,%sp
2363         mov 0,%l0               // Carry
2364 #ifndef sparcv8
2365         sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
2366 #endif
2367 1:        ld [%i1-4],%o1        // nächstes source-Digit
2368           sub %i1,4,%i1
2369           // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
2370 #ifdef sparcv8
2371           umul    %i0,%o1,%o0
2372           rd      %y,%o2
2373 #else
2374           mov     %o1,%y
2375           and     %o1,%l1,%o3   // Wartetakt!
2376           andcc   %g0,%g0,%o2
2377           mulscc  %o2,%i0,%o2
2378           mulscc  %o2,%i0,%o2
2379           mulscc  %o2,%i0,%o2
2380           mulscc  %o2,%i0,%o2
2381           mulscc  %o2,%i0,%o2
2382           mulscc  %o2,%i0,%o2
2383           mulscc  %o2,%i0,%o2
2384           mulscc  %o2,%i0,%o2
2385           mulscc  %o2,%i0,%o2
2386           mulscc  %o2,%i0,%o2
2387           mulscc  %o2,%i0,%o2
2388           mulscc  %o2,%i0,%o2
2389           mulscc  %o2,%i0,%o2
2390           mulscc  %o2,%i0,%o2
2391           mulscc  %o2,%i0,%o2
2392           mulscc  %o2,%i0,%o2
2393           mulscc  %o2,%i0,%o2
2394           mulscc  %o2,%i0,%o2
2395           mulscc  %o2,%i0,%o2
2396           mulscc  %o2,%i0,%o2
2397           mulscc  %o2,%i0,%o2
2398           mulscc  %o2,%i0,%o2
2399           mulscc  %o2,%i0,%o2
2400           mulscc  %o2,%i0,%o2
2401           mulscc  %o2,%i0,%o2
2402           mulscc  %o2,%i0,%o2
2403           mulscc  %o2,%i0,%o2
2404           mulscc  %o2,%i0,%o2
2405           mulscc  %o2,%i0,%o2
2406           mulscc  %o2,%i0,%o2
2407           mulscc  %o2,%i0,%o2
2408           mulscc  %o2,%i0,%o2
2409           mulscc  %o2,%g0,%o2
2410           add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
2411           rd      %y,%o0
2412 #endif
2413           sub %i2,4,%i2
2414           ld [%i2],%o1          // nächstes dest-digit
2415           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
2416           addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
2417           addcc %o1,%o0,%o0     // addieren
2418           addx %g0,%l0,%l0
2419           subcc %i3,1,%i3
2420           bne 1b
2421          _ st %o0,[%i2]         // Low-Digit ablegen
2422         mov %l0,%i0             // letzter Carry
2423         ret
2424        _ restore
2425 #endif
2426
2427 // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2428         DECLARE_FUNCTION(mulusub_loop_down)
2429 C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2430 #if !MULU32_INLINE
2431         save %sp,-96,%sp
2432         mov 0,%l0               // Carry
2433 1:        sub %i1,4,%i1
2434           ld [%i1],%o1          // nächstes source-Digit
2435           call _mulu32_         // mit digit multiplizieren
2436          _ mov %i0,%o0
2437           sub %i2,4,%i2
2438           ld [%i2],%o1          // nächstes dest-digit
2439           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
2440           addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
2441           subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
2442           addx %g0,%l0,%l0
2443           subcc %i3,1,%i3
2444           bne 1b
2445          _ st %o1,[%i2]         // dest-Digit ablegen
2446         mov %l0,%i0             // letzter Carry
2447         ret
2448        _ restore
2449 #else
2450         save %sp,-96,%sp
2451         mov 0,%l0               // Carry
2452 #ifndef sparcv8
2453         sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
2454 #endif
2455 1:        ld [%i1-4],%o1        // nächstes source-Digit
2456           sub %i1,4,%i1
2457           // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
2458 #ifdef sparcv8
2459           umul    %i0,%o1,%o0
2460           rd      %y,%o2
2461 #else
2462           mov     %o1,%y
2463           and     %o1,%l1,%o3   // Wartetakt!
2464           andcc   %g0,%g0,%o2
2465           mulscc  %o2,%i0,%o2
2466           mulscc  %o2,%i0,%o2
2467           mulscc  %o2,%i0,%o2
2468           mulscc  %o2,%i0,%o2
2469           mulscc  %o2,%i0,%o2
2470           mulscc  %o2,%i0,%o2
2471           mulscc  %o2,%i0,%o2
2472           mulscc  %o2,%i0,%o2
2473           mulscc  %o2,%i0,%o2
2474           mulscc  %o2,%i0,%o2
2475           mulscc  %o2,%i0,%o2
2476           mulscc  %o2,%i0,%o2
2477           mulscc  %o2,%i0,%o2
2478           mulscc  %o2,%i0,%o2
2479           mulscc  %o2,%i0,%o2
2480           mulscc  %o2,%i0,%o2
2481           mulscc  %o2,%i0,%o2
2482           mulscc  %o2,%i0,%o2
2483           mulscc  %o2,%i0,%o2
2484           mulscc  %o2,%i0,%o2
2485           mulscc  %o2,%i0,%o2
2486           mulscc  %o2,%i0,%o2
2487           mulscc  %o2,%i0,%o2
2488           mulscc  %o2,%i0,%o2
2489           mulscc  %o2,%i0,%o2
2490           mulscc  %o2,%i0,%o2
2491           mulscc  %o2,%i0,%o2
2492           mulscc  %o2,%i0,%o2
2493           mulscc  %o2,%i0,%o2
2494           mulscc  %o2,%i0,%o2
2495           mulscc  %o2,%i0,%o2
2496           mulscc  %o2,%i0,%o2
2497           mulscc  %o2,%g0,%o2
2498           add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
2499           rd      %y,%o0
2500 #endif
2501           sub %i2,4,%i2
2502           ld [%i2],%o1          // nächstes dest-digit
2503           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
2504           addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
2505           subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
2506           addx %g0,%l0,%l0
2507           subcc %i3,1,%i3
2508           bne 1b
2509          _ st %o1,[%i2]         // dest-Digit ablegen
2510         mov %l0,%i0             // letzter Carry
2511         ret
2512        _ restore
2513 #endif
2514
2515 // extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
2516         DECLARE_FUNCTION(divu_loop_up)
2517 C(divu_loop_up:) // Input in %i0,%i1,%i2, Output in %i0
2518         save %sp,-96,%sp
2519         andcc %i2,%i2,%g0
2520         be 2f
2521        _ mov 0,%g1                 // Rest
2522 1:        mov %g1,%o0              // Rest als High-Digit
2523           ld [%i1],%o1             // nächstes Digit als Low-Digit
2524           call C(divu_6432_3232_)  // zusammen durch digit dividieren
2525          _ mov %i0,%o2
2526           st %o0,[%i1]             // Quotient ablegen, Rest in %g1
2527           subcc %i2,1,%i2
2528           bne 1b
2529          _ add %i1,4,%i1
2530 2:      mov %g1,%i0                // Rest als Ergebnis
2531         ret
2532        _ restore
2533
2534 // extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2535         DECLARE_FUNCTION(divucopy_loop_up)
2536 C(divucopy_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2537         save %sp,-96,%sp
2538         andcc %i3,%i3,%g0
2539         be 2f
2540        _ mov 0,%g1                 // Rest
2541 1:        mov %g1,%o0              // Rest als High-Digit
2542           ld [%i1],%o1             // nächstes Digit als Low-Digit
2543           call C(divu_6432_3232_)  // zusammen durch digit dividieren
2544          _ mov %i0,%o2
2545           st %o0,[%i2]             // Quotient ablegen, Rest in %g1
2546           add %i1,4,%i1
2547           subcc %i3,1,%i3
2548           bne 1b
2549          _ add %i2,4,%i2
2550 2:      mov %g1,%i0                // Rest als Ergebnis
2551         ret
2552        _ restore
2553
2554 #endif
2555
2556 #if !CL_DS_BIG_ENDIAN_P
2557
2558 // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
2559         DECLARE_FUNCTION(or_loop_down)
2560 C(or_loop_down:) // Input in %o0,%o1,%o2
2561 #if SLOW_LOOPS
2562         andcc %o2,%o2,%g0
2563         be 2f
2564        _ sub %o0,4,%o0
2565 1:        ld [%o0],%o3
2566           sub %o1,4,%o1
2567           ld [%o1],%o4
2568           subcc %o2,1,%o2
2569           or %o3,%o4,%o3
2570           st %o3,[%o0]
2571           bne 1b
2572          _ sub %o0,4,%o0
2573 2:      retl
2574        _ nop
2575 #endif
2576 #if STANDARD_LOOPS
2577         andcc %o2,%o2,%g0
2578         be 2f
2579        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2580         sub %o0,4,%o0
2581 1:        ld [%o0],%o3          // *xptr
2582           ld [%o0+%o1],%o4      // *yptr
2583           subcc %o2,1,%o2
2584           or %o3,%o4,%o3        // verknüpfen
2585           st %o3,[%o0]          // =: *xptr
2586           bne 1b
2587          _ sub %o0,4,%o0        // xptr++, yptr++
2588 2:      retl
2589        _ nop
2590 #endif
2591 #if COUNTER_LOOPS
2592         andcc %o2,%o2,%g0
2593         be 2f
2594        _ sll %o2,2,%o2          // %o2 = 4*count
2595         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2596         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2597 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2598           ld [%o1+%o2],%o3      // nächstes Digit holen
2599           ld [%o0+%o2],%o4      // noch ein Digit holen
2600           or %o4,%o3,%o3        // beide verknüpfen
2601           bne 1b
2602          _ st %o3,[%o1+%o2]     // Digit ablegen
2603 2:      retl
2604        _ nop
2605 #endif
2606
2607 // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
2608         DECLARE_FUNCTION(xor_loop_down)
2609 C(xor_loop_down:) // Input in %o0,%o1,%o2
2610 #if SLOW_LOOPS
2611         andcc %o2,%o2,%g0
2612         be 2f
2613        _ sub %o0,4,%o0
2614 1:        ld [%o0],%o3
2615           sub %o1,4,%o1
2616           ld [%o1],%o4
2617           subcc %o2,1,%o2
2618           xor %o3,%o4,%o3
2619           st %o3,[%o0]
2620           bne 1b
2621          _ sub %o0,4,%o0
2622 2:      retl
2623        _ nop
2624 #endif
2625 #if STANDARD_LOOPS
2626         andcc %o2,%o2,%g0
2627         be 2f
2628        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2629         sub %o0,4,%o0
2630 1:        ld [%o0],%o3          // *xptr
2631           ld [%o0+%o1],%o4      // *yptr
2632           subcc %o2,1,%o2
2633           xor %o3,%o4,%o3       // verknüpfen
2634           st %o3,[%o0]          // =: *xptr
2635           bne 1b
2636          _ sub %o0,4,%o0        // xptr++, yptr++
2637 2:      retl
2638        _ nop
2639 #endif
2640 #if COUNTER_LOOPS
2641         andcc %o2,%o2,%g0
2642         be 2f
2643        _ sll %o2,2,%o2          // %o2 = 4*count
2644         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2645         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2646 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2647           ld [%o1+%o2],%o3      // nächstes Digit holen
2648           ld [%o0+%o2],%o4      // noch ein Digit holen
2649           xor %o4,%o3,%o3       // beide verknüpfen
2650           bne 1b
2651          _ st %o3,[%o1+%o2]     // Digit ablegen
2652 2:      retl
2653        _ nop
2654 #endif
2655
2656 // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
2657         DECLARE_FUNCTION(and_loop_down)
2658 C(and_loop_down:) // Input in %o0,%o1,%o2
2659 #if SLOW_LOOPS
2660         andcc %o2,%o2,%g0
2661         be 2f
2662        _ sub %o0,4,%o0
2663 1:        ld [%o0],%o3
2664           sub %o1,4,%o1
2665           ld [%o1],%o4
2666           subcc %o2,1,%o2
2667           and %o3,%o4,%o3
2668           st %o3,[%o0]
2669           bne 1b
2670          _ sub %o0,4,%o0
2671 2:      retl
2672        _ nop
2673 #endif
2674 #if STANDARD_LOOPS
2675         andcc %o2,%o2,%g0
2676         be 2f
2677        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2678         sub %o0,4,%o0
2679 1:        ld [%o0],%o3          // *xptr
2680           ld [%o0+%o1],%o4      // *yptr
2681           subcc %o2,1,%o2
2682           and %o3,%o4,%o3       // verknüpfen
2683           st %o3,[%o0]          // =: *xptr
2684           bne 1b
2685          _ sub %o0,4,%o0        // xptr++, yptr++
2686 2:      retl
2687        _ nop
2688 #endif
2689 #if COUNTER_LOOPS
2690         andcc %o2,%o2,%g0
2691         be 2f
2692        _ sll %o2,2,%o2          // %o2 = 4*count
2693         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2694         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2695 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2696           ld [%o1+%o2],%o3      // nächstes Digit holen
2697           ld [%o0+%o2],%o4      // noch ein Digit holen
2698           and %o4,%o3,%o3       // beide verknüpfen
2699           bne 1b
2700          _ st %o3,[%o1+%o2]     // Digit ablegen
2701 2:      retl
2702        _ nop
2703 #endif
2704
2705 // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
2706         DECLARE_FUNCTION(eqv_loop_down)
2707 C(eqv_loop_down:) // Input in %o0,%o1,%o2
2708 #if SLOW_LOOPS
2709         andcc %o2,%o2,%g0
2710         be 2f
2711        _ sub %o0,4,%o0
2712 1:        ld [%o0],%o3
2713           sub %o1,4,%o1
2714           ld [%o1],%o4
2715           subcc %o2,1,%o2
2716           xnor %o3,%o4,%o3
2717           st %o3,[%o0]
2718           bne 1b
2719          _ sub %o0,4,%o0
2720 2:      retl
2721        _ nop
2722 #endif
2723 #if STANDARD_LOOPS
2724         andcc %o2,%o2,%g0
2725         be 2f
2726        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2727         sub %o0,4,%o0
2728 1:        ld [%o0],%o3          // *xptr
2729           ld [%o0+%o1],%o4      // *yptr
2730           subcc %o2,1,%o2
2731           xnor %o3,%o4,%o3      // verknüpfen
2732           st %o3,[%o0]          // =: *xptr
2733           bne 1b
2734          _ sub %o0,4,%o0        // xptr++, yptr++
2735 2:      retl
2736        _ nop
2737 #endif
2738 #if COUNTER_LOOPS
2739         andcc %o2,%o2,%g0
2740         be 2f
2741        _ sll %o2,2,%o2          // %o2 = 4*count
2742         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2743         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2744 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2745           ld [%o1+%o2],%o3      // nächstes Digit holen
2746           ld [%o0+%o2],%o4      // noch ein Digit holen
2747           xnor %o4,%o3,%o3      // beide verknüpfen
2748           bne 1b
2749          _ st %o3,[%o1+%o2]     // Digit ablegen
2750 2:      retl
2751        _ nop
2752 #endif
2753
2754 // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
2755         DECLARE_FUNCTION(nand_loop_down)
2756 C(nand_loop_down:) // Input in %o0,%o1,%o2
2757 #if SLOW_LOOPS
2758         andcc %o2,%o2,%g0
2759         be 2f
2760        _ sub %o0,4,%o0
2761 1:        ld [%o0],%o3
2762           sub %o1,4,%o1
2763           ld [%o1],%o4
2764           subcc %o2,1,%o2
2765           and %o3,%o4,%o3
2766           xor %o3,-1,%o3
2767           st %o3,[%o0]
2768           bne 1b
2769          _ sub %o0,4,%o0
2770 2:      retl
2771        _ nop
2772 #endif
2773 #if STANDARD_LOOPS
2774         andcc %o2,%o2,%g0
2775         be 2f
2776        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2777         sub %o0,4,%o0
2778 1:        ld [%o0],%o3          // *xptr
2779           ld [%o0+%o1],%o4      // *yptr
2780           subcc %o2,1,%o2
2781           and %o3,%o4,%o3       // verknüpfen
2782           xor %o3,-1,%o3
2783           st %o3,[%o0]          // =: *xptr
2784           bne 1b
2785          _ sub %o0,4,%o0        // xptr++, yptr++
2786 2:      retl
2787        _ nop
2788 #endif
2789 #if COUNTER_LOOPS
2790         andcc %o2,%o2,%g0
2791         be 2f
2792        _ sll %o2,2,%o2          // %o2 = 4*count
2793         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2794         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2795 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2796           ld [%o1+%o2],%o3      // nächstes Digit holen
2797           ld [%o0+%o2],%o4      // noch ein Digit holen
2798           and %o4,%o3,%o3       // beide verknüpfen
2799           xor %o3,-1,%o3
2800           bne 1b
2801          _ st %o3,[%o1+%o2]     // Digit ablegen
2802 2:      retl
2803        _ nop
2804 #endif
2805
2806 // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
2807         DECLARE_FUNCTION(nor_loop_down)
2808 C(nor_loop_down:) // Input in %o0,%o1,%o2
2809 #if SLOW_LOOPS
2810         andcc %o2,%o2,%g0
2811         be 2f
2812        _ sub %o0,4,%o0
2813 1:        ld [%o0],%o3
2814           sub %o1,4,%o1
2815           ld [%o1],%o4
2816           subcc %o2,1,%o2
2817           or %o3,%o4,%o3
2818           xor %o3,-1,%o3
2819           st %o3,[%o0]
2820           bne 1b
2821          _ sub %o0,4,%o0
2822 2:      retl
2823        _ nop
2824 #endif
2825 #if STANDARD_LOOPS
2826         andcc %o2,%o2,%g0
2827         be 2f
2828        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2829         sub %o0,4,%o0
2830 1:        ld [%o0],%o3          // *xptr
2831           ld [%o0+%o1],%o4      // *yptr
2832           subcc %o2,1,%o2
2833           or %o3,%o4,%o3        // verknüpfen
2834           xor %o3,-1,%o3
2835           st %o3,[%o0]          // =: *xptr
2836           bne 1b
2837          _ sub %o0,4,%o0        // xptr++, yptr++
2838 2:      retl
2839        _ nop
2840 #endif
2841 #if COUNTER_LOOPS
2842         andcc %o2,%o2,%g0
2843         be 2f
2844        _ sll %o2,2,%o2          // %o2 = 4*count
2845         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2846         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2847 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2848           ld [%o1+%o2],%o3      // nächstes Digit holen
2849           ld [%o0+%o2],%o4      // noch ein Digit holen
2850           or %o4,%o3,%o3        // beide verknüpfen
2851           xor %o3,-1,%o3
2852           bne 1b
2853          _ st %o3,[%o1+%o2]     // Digit ablegen
2854 2:      retl
2855        _ nop
2856 #endif
2857
2858 // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
2859         DECLARE_FUNCTION(andc2_loop_down)
2860 C(andc2_loop_down:) // Input in %o0,%o1,%o2
2861 #if SLOW_LOOPS
2862         andcc %o2,%o2,%g0
2863         be 2f
2864        _ sub %o0,4,%o0
2865 1:        ld [%o0],%o3
2866           sub %o1,4,%o1
2867           ld [%o1],%o4
2868           subcc %o2,1,%o2
2869           andn %o3,%o4,%o3
2870           st %o3,[%o0]
2871           bne 1b
2872          _ sub %o0,4,%o0
2873 2:      retl
2874        _ nop
2875 #endif
2876 #if STANDARD_LOOPS
2877         andcc %o2,%o2,%g0
2878         be 2f
2879        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2880         sub %o0,4,%o0
2881 1:        ld [%o0],%o3          // *xptr
2882           ld [%o0+%o1],%o4      // *yptr
2883           subcc %o2,1,%o2
2884           andn %o3,%o4,%o3      // verknüpfen
2885           st %o3,[%o0]          // =: *xptr
2886           bne 1b
2887          _ sub %o0,4,%o0        // xptr++, yptr++
2888 2:      retl
2889        _ nop
2890 #endif
2891 #if COUNTER_LOOPS
2892         andcc %o2,%o2,%g0
2893         be 2f
2894        _ sll %o2,2,%o2          // %o2 = 4*count
2895         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2896         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2897 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2898           ld [%o1+%o2],%o3      // nächstes Digit holen
2899           ld [%o0+%o2],%o4      // noch ein Digit holen
2900           andn %o4,%o3,%o3      // beide verknüpfen
2901           bne 1b
2902          _ st %o3,[%o1+%o2]     // Digit ablegen
2903 2:      retl
2904        _ nop
2905 #endif
2906
2907 // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
2908         DECLARE_FUNCTION(orc2_loop_down)
2909 C(orc2_loop_down:) // Input in %o0,%o1,%o2
2910 #if SLOW_LOOPS
2911         andcc %o2,%o2,%g0
2912         be 2f
2913        _ sub %o0,4,%o0
2914 1:        ld [%o0],%o3
2915           sub %o1,4,%o1
2916           ld [%o1],%o4
2917           subcc %o2,1,%o2
2918           orn %o3,%o4,%o3
2919           st %o3,[%o0]
2920           bne 1b
2921          _ sub %o0,4,%o0
2922 2:      retl
2923        _ nop
2924 #endif
2925 #if STANDARD_LOOPS
2926         andcc %o2,%o2,%g0
2927         be 2f
2928        _ sub %o1,%o0,%o1        // %o1 = yptr-xptr
2929         sub %o0,4,%o0
2930 1:        ld [%o0],%o3          // *xptr
2931           ld [%o0+%o1],%o4      // *yptr
2932           subcc %o2,1,%o2
2933           orn %o3,%o4,%o3       // verknüpfen
2934           st %o3,[%o0]          // =: *xptr
2935           bne 1b
2936          _ sub %o0,4,%o0        // xptr++, yptr++
2937 2:      retl
2938        _ nop
2939 #endif
2940 #if COUNTER_LOOPS
2941         andcc %o2,%o2,%g0
2942         be 2f
2943        _ sll %o2,2,%o2          // %o2 = 4*count
2944         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
2945         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
2946 1:        subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
2947           ld [%o1+%o2],%o3      // nächstes Digit holen
2948           ld [%o0+%o2],%o4      // noch ein Digit holen
2949           orn %o4,%o3,%o3       // beide verknüpfen
2950           bne 1b
2951          _ st %o3,[%o1+%o2]     // Digit ablegen
2952 2:      retl
2953        _ nop
2954 #endif
2955
2956 // extern void not_loop_down (uintD* xptr, uintC count);
2957         DECLARE_FUNCTION(not_loop_down)
2958 C(not_loop_down:) // Input in %o0,%o1
2959 #if STANDARD_LOOPS
2960         andcc %o1,%o1,%g0
2961         be 2f
2962        _ sub %o0,4,%o0
2963 1:        ld [%o0],%o2
2964           subcc %o1,1,%o1
2965           xor %o2,-1,%o2
2966           st %o2,[%o0]
2967           bne 1b
2968          _ sub %o0,4,%o0
2969 2:      retl
2970        _ nop
2971 #endif
2972 #if COUNTER_LOOPS
2973         andcc %o1,%o1,%g0
2974         be 2f
2975        _ sll %o1,2,%o1          // %o1 = 4*count
2976         sub %o0,%o1,%o0         // %o0 = &destptr[-count]
2977 1:        subcc %o1,4,%o1       // Zähler erniedrigen, Pointer erniedrigen
2978           ld [%o0+%o1],%o2      // nächstes Digit holen
2979           xor %o2,-1,%o2
2980           bne 1b
2981          _ st %o2,[%o0+%o1]     // Digit ablegen
2982 2:      retl
2983        _ nop
2984 #endif
2985
2986 // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
2987         DECLARE_FUNCTION(and_test_loop_down)
2988 C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
2989 #if STANDARD_LOOPS
2990         andcc %o2,%o2,%g0
2991         be 4f
2992        _ sub %o0,4,%o0
2993 1:        ld [%o0],%o3
2994           sub %o1,4,%o1
2995           ld [%o1],%o4
2996           subcc %o2,1,%o2
2997           be 3f
2998          _ andcc %o3,%o4,%g0
2999           be 1b
3000          _ sub %o0,4,%o0
3001 2:      retl
3002        _ mov 1,%o0
3003 3:      bne 2b
3004        _ nop
3005 4:      retl
3006        _ mov 0,%o0
3007 #endif
3008 #if COUNTER_LOOPS
3009         sll %o2,2,%o2           // %o2 = 4*count
3010         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
3011         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
3012         subcc %o2,4,%o2
3013         bcs 2f
3014        _ nop
3015           ld [%o0+%o2],%o3      // nächstes Digit holen
3016 1:        ld [%o1+%o2],%o4      // noch ein Digit holen
3017           andcc %o3,%o4,%g0     // beide verknüpfen
3018           bne 3f
3019          _ subcc %o2,4,%o2      // Zähler erniedrigen, Pointer erniedrigen
3020           bcc,a 1b
3021          __ ld [%o0+%o2],%o3    // nächstes Digit holen
3022 2:      retl
3023        _ mov 0,%o0
3024 3:      retl
3025        _ mov 1,%o0
3026 #endif
3027
3028 // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
3029         DECLARE_FUNCTION(compare_loop_down)
3030 C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
3031 #if STANDARD_LOOPS
3032         andcc %o2,%o2,%g0
3033         be 2f
3034        _ nop
3035 1:        ld [%o0-4],%o3
3036           ld [%o1-4],%o4
3037           subcc %o3,%o4,%g0
3038           bne 3f
3039          _ sub %o0,4,%o0
3040           subcc %o2,1,%o2
3041           bne 1b
3042          _ sub %o1,4,%o1
3043 2:      retl
3044        _ mov 0,%o0
3045 3:      blu 4f
3046        _ nop
3047         retl
3048        _ mov 1,%o0
3049 4:      retl
3050        _ mov -1,%o0
3051 #endif
3052 #if COUNTER_LOOPS
3053         sll %o2,2,%o2           // %o2 = 4*count
3054         sub %o0,%o2,%o0         // %o0 = &xptr[-count]
3055         sub %o1,%o2,%o1         // %o1 = &yptr[-count]
3056         subcc %o2,4,%o2
3057         bcs 5f
3058        _ nop
3059           ld [%o0+%o2],%o3      // nächstes Digit holen
3060 1:        ld [%o1+%o2],%o4      // noch ein Digit holen
3061           subcc %o2,4,%o2       // Zähler erniedrigen, Pointer erniedrigen
3062           bcs 4f
3063          _ subcc %o3,%o4,%g0    // vergleichen
3064           be,a 1b
3065          __ ld [%o0+%o2],%o3    // nächstes Digit holen
3066 2:      blu 3f
3067        _ nop
3068         retl
3069        _ mov 1,%o0
3070 3:      retl
3071        _ mov -1,%o0
3072 4:      bne 2b
3073        _ nop
3074 5:      retl
3075        _ mov 0,%o0
3076 #endif
3077
3078 // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
3079         DECLARE_FUNCTION(add_loop_up)
3080 C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
3081 #if STANDARD_LOOPS
3082         andcc %o3,%o3,%g0
3083         be 2f
3084        _ subcc %g0,%g0,%g0      // Carry := 0
3085 1:        ld [%o0],%o4          // source1-digit
3086           add %o0,4,%o0
3087           ld [%o1],%o5          // source2-digit
3088           add %o1,4,%o1
3089           addxcc %o4,%o5,%o4    // addieren
3090           addx %g0,%g0,%g1      // neuer Carry
3091           st %o4,[%o2]          // Digit ablegen
3092           add %o2,4,%o2
3093           subcc %o3,1,%o3
3094           bne 1b
3095          _ subcc %g0,%g1,%g0    // carry
3096 2:      retl
3097        _ addx %g0,%g0,%o0
3098 #endif
3099 #if COUNTER_LOOPS
3100         subcc %g0,%o3,%o3       // %o3 = -count
3101         be 2f
3102        _ mov %g0,%g1            // Carry := 0
3103         sll %o3,2,%o3           // %o3 = -4*count
3104         sub %o2,4,%o2
3105         sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
3106         sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
3107         sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
3108 1:        ld [%o0+%o3],%o4      // source1-digit
3109           ld [%o1+%o3],%o5      // source2-digit
3110           subcc %g0,%g1,%g0     // carry
3111           addxcc %o4,%o5,%o4    // addieren
3112           addx %g0,%g0,%g1      // neuer Carry
3113           addcc %o3,4,%o3       // Zähler erniedrigen, Pointer erhöhen
3114           bne 1b
3115          _ st %o4,[%o2+%o3]     // Digit ablegen
3116 2:      retl
3117        _ mov %g1,%o0
3118 #endif
3119 #if UNROLLED_LOOPS
3120         and %o3,7,%o4           // count mod 8
3121         sll %o4,2,%o5
3122         add %o0,%o5,%o0         // %o0 = &sourceptr1[count mod 8]
3123         add %o1,%o5,%o1         // %o1 = &sourceptr2[count mod 8]
3124         add %o2,%o5,%o2         // %o2 = &destptr[count mod 8]
3125         sll %o4,4,%o4
3126 #ifdef PIC
3127         mov %o7,%g2             // save return address
3128         call 0f                 // put address of label 0 into %o7
3129        _ add %o7,144,%o5
3130 0:
3131 #else
3132         set _add_loop_up+176,%o5
3133 #endif
3134         sub %o5,%o4,%o5
3135         jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
3136        _ subcc %g0,%g0,%g0      // carry löschen
3137 1:        subcc %g0,%g1,%g0     // carry
3138           ld [%o0-32],%o4       // source1-digit
3139           ld [%o1-32],%o5       // source2-digit
3140           addxcc %o5,%o4,%o5    // addieren
3141           st %o5,[%o2-32]       // Digit ablegen
3142           ld [%o0-28],%o4       // source1-digit
3143           ld [%o1-28],%o5       // source2-digit
3144           addxcc %o5,%o4,%o5    // addieren
3145           st %o5,[%o2-28]       // Digit ablegen
3146           ld [%o0-24],%o4       // source1-digit
3147           ld [%o1-24],%o5       // source2-digit
3148           addxcc %o5,%o4,%o5    // addieren
3149           st %o5,[%o2-24]       // Digit ablegen
3150           ld [%o0-20],%o4       // source1-digit
3151           ld [%o1-20],%o5       // source2-digit
3152           addxcc %o5,%o4,%o5    // addieren
3153           st %o5,[%o2-20]       // Digit ablegen
3154           ld [%o0-16],%o4       // source1-digit
3155           ld [%o1-16],%o5       // source2-digit
3156           addxcc %o5,%o4,%o5    // addieren
3157           st %o5,[%o2-16]       // Digit ablegen
3158           ld [%o0-12],%o4       // source1-digit
3159           ld [%o1-12],%o5       // source2-digit
3160           addxcc %o5,%o4,%o5    // addieren
3161           st %o5,[%o2-12]       // Digit ablegen
3162           ld [%o0-8],%o4        // source1-digit
3163           ld [%o1-8],%o5        // source2-digit
3164           addxcc %o5,%o4,%o5    // addieren
3165           st %o5,[%o2-8]        // Digit ablegen
3166           ld [%o0-4],%o4        // source1-digit
3167           ld [%o1-4],%o5        // source2-digit
3168           addxcc %o5,%o4,%o5    // addieren
3169           st %o5,[%o2-4]        // Digit ablegen
3170           addx %g0,%g0,%g1      // neuer Carry
3171           add %o0,32,%o0
3172           add %o1,32,%o1
3173           subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
3174           bcc 1b
3175          _ add %o2,32,%o2
3176 #ifdef PIC
3177         jmp %g2+8
3178 #else
3179         retl
3180 #endif
3181        _ mov %g1,%o0
3182 #endif
3183
3184 // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
3185         DECLARE_FUNCTION(addto_loop_up)
3186 C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
3187 #if STANDARD_LOOPS
3188         andcc %o2,%o2,%g0
3189         be 2f
3190        _ mov %g0,%o5            // Carry := 0
3191 1:        ld [%o0],%o3          // source-digit
3192           add %o0,4,%o0
3193           ld [%o1],%o4          // dest-digit
3194           subcc %g0,%o5,%g0     // carry
3195           addxcc %o4,%o3,%o4    // addieren
3196           addx %g0,%g0,%o5      // neuer Carry
3197           st %o4,[%o1]          // Digit ablegen
3198           subcc %o2,1,%o2
3199           bne 1b
3200          _ add %o1,4,%o1
3201 2:      retl
3202        _ mov %o5,%o0
3203 #endif
3204 #if COUNTER_LOOPS
3205         subcc %g0,%o2,%o2       // %o2 = -count
3206         be 2f
3207        _ mov %g0,%o5            // Carry := 0
3208         sll %o2,2,%o2           // %o2 = -4*count
3209         sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
3210         sub %o1,%o2,%o1         // %o1 = &destptr[count]
3211           ld [%o0+%o2],%o3      // source-digit
3212 1:        ld [%o1+%o2],%o4      // dest-digit
3213           subcc %g0,%o5,%g0     // carry
3214           addxcc %o4,%o3,%o4    // addieren
3215           addx %g0,%g0,%o5      // neuer Carry
3216           st %o4,[%o1+%o2]      // Digit ablegen
3217           addcc %o2,4,%o2       // Zähler erniedrigen, Pointer erhöhen
3218           bne,a 1b
3219          __ ld [%o0+%o2],%o3    // source-digit
3220 2:      retl
3221        _ mov %o5,%o0
3222 #endif
3223 #if UNROLLED_LOOPS
3224         and %o2,7,%o3           // count mod 8
3225         sll %o3,2,%o4
3226         add %o0,%o4,%o0         // %o0 = &sourceptr[count mod 8]
3227         add %o1,%o4,%o1         // %o1 = &destptr[count mod 8]
3228         sll %o3,4,%o3
3229 #ifdef PIC
3230         mov %o7,%g2             // save return address
3231         call 0f                 // put address of label 0 into %o7
3232        _ add %o7,144,%o4
3233 0:
3234 #else
3235         set _addto_loop_up+172,%o4
3236 #endif
3237         sub %o4,%o3,%o4
3238         jmp %o4                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
3239        _ subcc %g0,%g0,%g0      // carry löschen
3240 1:        subcc %g0,%o5,%g0     // carry
3241           ld [%o0-32],%o3       // source-digit
3242           ld [%o1-32],%o4       // dest-digit
3243           addxcc %o4,%o3,%o4    // addieren
3244           st %o4,[%o1-32]       // Digit ablegen
3245           ld [%o0-28],%o3       // source-digit
3246           ld [%o1-28],%o4       // dest-digit
3247           addxcc %o4,%o3,%o4    // addieren
3248           st %o4,[%o1-28]       // Digit ablegen
3249           ld [%o0-24],%o3       // source-digit
3250           ld [%o1-24],%o4       // dest-digit
3251           addxcc %o4,%o3,%o4    // addieren
3252           st %o4,[%o1-24]       // Digit ablegen
3253           ld [%o0-20],%o3       // source-digit
3254           ld [%o1-20],%o4       // dest-digit
3255           addxcc %o4,%o3,%o4    // addieren
3256           st %o4,[%o1-20]       // Digit ablegen
3257           ld [%o0-16],%o3       // source-digit
3258           ld [%o1-16],%o4       // dest-digit
3259           addxcc %o4,%o3,%o4    // addieren
3260           st %o4,[%o1-16]       // Digit ablegen
3261           ld [%o0-12],%o3       // source-digit
3262           ld [%o1-12],%o4       // dest-digit
3263           addxcc %o4,%o3,%o4    // addieren
3264           st %o4,[%o1-12]       // Digit ablegen
3265           ld [%o0-8],%o3        // source-digit
3266           ld [%o1-8],%o4        // dest-digit
3267           addxcc %o4,%o3,%o4    // addieren
3268           st %o4,[%o1-8]        // Digit ablegen
3269           ld [%o0-4],%o3        // source-digit
3270           ld [%o1-4],%o4        // dest-digit
3271           addxcc %o4,%o3,%o4    // addieren
3272           st %o4,[%o1-4]        // Digit ablegen
3273           addx %g0,%g0,%o5      // neuer Carry
3274           add %o0,32,%o0
3275           subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
3276           bcc 1b
3277          _ add %o1,32,%o1
3278 #ifdef PIC
3279         jmp %g2+8
3280 #else
3281         retl
3282 #endif
3283        _ mov %o5,%o0
3284 #endif
3285
3286 // extern uintD inc_loop_up (uintD* ptr, uintC count);
3287         DECLARE_FUNCTION(inc_loop_up)
3288 C(inc_loop_up:) // Input in %o0,%o1, Output in %o0
3289 #if STANDARD_LOOPS
3290         andcc %o1,%o1,%g0
3291         be 2f
3292        _ nop
3293           ld [%o0],%o2
3294 1:        add %o0,4,%o0
3295           addcc %o2,1,%o2
3296           bne 3f
3297          _ st %o2,[%o0-4]
3298           subcc %o1,1,%o1
3299           bne,a 1b
3300          __ ld [%o0],%o2
3301 2:      retl
3302        _ mov 1,%o0
3303 3:      retl
3304        _ mov 0,%o0
3305 #endif
3306 #if COUNTER_LOOPS
3307         subcc %g0,%o1,%o1       // %o1 = -count
3308         be 2f
3309        _ sll %o1,2,%o1          // %o1 = -4*count
3310         sub %o0,%o1,%o0         // %o0 = &ptr[count]
3311           ld [%o0+%o1],%o2      // digit holen
3312 1:        addcc %o2,1,%o2       // incrementieren
3313           bne 3f
3314          _ st %o2,[%o0+%o1]     // ablegen
3315           addcc %o1,4,%o1       // Zähler erniedrigen, Pointer erhöhen
3316           bne,a 1b
3317          __ ld [%o0+%o1],%o2
3318 2:      retl
3319        _ mov 1,%o0
3320 3:      retl
3321        _ mov 0,%o0
3322 #endif
3323
3324 // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
3325         DECLARE_FUNCTION(sub_loop_up)
3326 C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
3327 #if STANDARD_LOOPS
3328         andcc %o3,%o3,%g0
3329         be 2f
3330        _ subcc %g0,%g0,%g0      // Carry := 0
3331 1:        ld [%o0],%o4          // source1-digit
3332           add %o0,4,%o0
3333           ld [%o1],%o5          // source2-digit
3334           add %o1,4,%o1
3335           subxcc %o4,%o5,%o4    // subtrahieren
3336           addx %g0,%g0,%g1      // neuer Carry
3337           st %o4,[%o2]          // Digit ablegen
3338           add %o2,4,%o2
3339           subcc %o3,1,%o3
3340           bne 1b
3341          _ subcc %g0,%g1,%g0    // carry
3342 2:      retl
3343        _ addx %g0,%g0,%o0
3344 #endif
3345 #if COUNTER_LOOPS
3346         subcc %g0,%o3,%o3       // %o3 = -count
3347         be 2f
3348        _ mov %g0,%g1            // Carry := 0
3349         sll %o3,2,%o3           // %o3 = -4*count
3350         sub %o2,4,%o2
3351         sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
3352         sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
3353         sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
3354 1:        ld [%o0+%o3],%o4      // source1-digit
3355           ld [%o1+%o3],%o5      // source2-digit
3356           subcc %g0,%g1,%g0     // carry
3357           subxcc %o4,%o5,%o4    // subtrahieren
3358           addx %g0,%g0,%g1      // neuer Carry
3359           addcc %o3,4,%o3
3360           bne 1b
3361          _ st %o4,[%o2+%o3]     // Digit ablegen
3362 2:      retl
3363        _ mov %g1,%o0
3364 #endif
3365 #if UNROLLED_LOOPS
3366         and %o3,7,%o4           // count mod 8
3367         sll %o4,2,%o5
3368         add %o0,%o5,%o0         // %o0 = &sourceptr1[count mod 8]
3369         add %o1,%o5,%o1         // %o1 = &sourceptr2[count mod 8]
3370         add %o2,%o5,%o2         // %o2 = &destptr[count mod 8]
3371         sll %o4,4,%o4
3372 #ifdef PIC
3373         mov %o7,%g2             // save return address
3374         call 0f                 // put address of label 0 into %o7
3375        _ add %o7,144,%o5
3376 0:
3377 #else
3378         set _sub_loop_up+176,%o5
3379 #endif
3380         sub %o5,%o4,%o5
3381         jmp %o5                 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
3382        _ subcc %g0,%g0,%g0      // carry löschen
3383 1:        subcc %g0,%g1,%g0     // carry
3384           ld [%o0-32],%o4       // source1-digit
3385           ld [%o1-32],%o5       // source2-digit
3386           subxcc %o4,%o5,%o4    // subtrahieren
3387           st %o4,[%o2-32]       // Digit ablegen
3388           ld [%o0-28],%o4       // source1-digit
3389           ld [%o1-28],%o5       // source2-digit
3390           subxcc %o4,%o5,%o4    // subtrahieren
3391           st %o4,[%o2-28]       // Digit ablegen
3392           ld [%o0-24],%o4       // source1-digit
3393           ld [%o1-24],%o5       // source2-digit
3394           subxcc %o4,%o5,%o4    // subtrahieren
3395           st %o4,[%o2-24]       // Digit ablegen
3396           ld [%o0-20],%o4       // source1-digit
3397           ld [%o1-20],%o5       // source2-digit
3398           subxcc %o4,%o5,%o4    // subtrahieren
3399           st %o4,[%o2-20]       // Digit ablegen
3400           ld [%o0-16],%o4       // source1-digit
3401           ld [%o1-16],%o5       // source2-digit
3402           subxcc %o4,%o5,%o4    // subtrahieren
3403           st %o4,[%o2-16]       // Digit ablegen
3404           ld [%o0-12],%o4       // source1-digit
3405           ld [%o1-12],%o5       // source2-digit
3406           subxcc %o4,%o5,%o4    // subtrahieren
3407           st %o4,[%o2-12]       // Digit ablegen
3408           ld [%o0-8],%o4        // source1-digit
3409           ld [%o1-8],%o5        // source2-digit
3410           subxcc %o4,%o5,%o4    // subtrahieren
3411           st %o4,[%o2-8]        // Digit ablegen
3412           ld [%o0-4],%o4        // source1-digit
3413           ld [%o1-4],%o5        // source2-digit
3414           subxcc %o4,%o5,%o4    // subtrahieren
3415           st %o4,[%o2-4]        // Digit ablegen
3416           addx %g0,%g0,%g1      // neuer Carry
3417           add %o0,32,%o0
3418           add %o1,32,%o1
3419           subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
3420           bcc 1b
3421          _ add %o2,32,%o2
3422 #ifdef PIC
3423         jmp %g2+8
3424 #else
3425         retl
3426 #endif
3427        _ mov %g1,%o0
3428 #endif
3429
3430 // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
3431         DECLARE_FUNCTION(subx_loop_up)
3432 C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
3433 #if STANDARD_LOOPS
3434         andcc %o3,%o3,%g0
3435         be 2f
3436        _ subcc %g0,%o4,%g0      // Carry
3437 1:        ld [%o0],%o4          // source1-digit
3438           add %o0,4,%o0
3439           ld [%o1],%o5          // source2-digit
3440           add %o1,4,%o1
3441           subxcc %o4,%o5,%o4    // subtrahieren
3442           addx %g0,%g0,%g1      // neuer Carry
3443           st %o4,[%o2]          // Digit ablegen
3444           add %o2,4,%o2
3445           subcc %o3,1,%o3
3446           bne 1b
3447          _ subcc %g0,%g1,%g0    // carry
3448 2:      retl
3449        _ addx %g0,%g0,%o0
3450 #endif
3451 #if COUNTER_LOOPS
3452         subcc %g0,%o3,%o3       // %o3 = -count
3453         be 2f
3454        _ mov %o4,%g1            // Carry
3455         sll %o3,2,%o3           // %o3 = -4*count
3456         sub %o2,4,%o2
3457         sub %o0,%o3,%o0         // %o0 = &sourceptr1[count]
3458         sub %o1,%o3,%o1         // %o1 = &sourceptr2[count]
3459         sub %o2,%o3,%o2         // %o2 = &destptr[count-1]
3460 1:        ld [%o0+%o3],%o4      // source1-digit
3461           ld [%o1+%o3],%o5      // source2-digit
3462           subcc %g0,%g1,%g0     // carry
3463           subxcc %o4,%o5,%o4    // subtrahieren
3464           addx %g0,%g0,%g1      // neuer Carry
3465           addcc %o3,4,%o3
3466           bne 1b
3467          _ st %o4,[%o2+%o3]     // Digit ablegen
3468 2:      retl
3469        _ mov %g1,%o0
3470 #endif
3471 #if UNROLLED_LOOPS
3472         and %o3,7,%o5           // count mod 8
3473         sll %o5,2,%g1
3474         add %o0,%g1,%o0         // %o0 = &sourceptr1[count mod 8]
3475         add %o1,%g1,%o1         // %o1 = &sourceptr2[count mod 8]
3476         add %o2,%g1,%o2         // %o2 = &destptr[count mod 8]
3477         sll %o5,4,%o5
3478 #ifdef PIC
3479         mov %o7,%g2             // save return address
3480         call 0f                 // put address of label 0 into %o7
3481        _ add %o7,144,%g1
3482 0:
3483 #else
3484         set _subx_loop_up+176,%g1
3485 #endif
3486         sub %g1,%o5,%g1
3487         jmp %g1                 // Sprung nach _subx_loop_up+4*(12+4*8-4*(count mod 8))
3488        _ subcc %g0,%o4,%g0      // carry initialisieren
3489 1:        subcc %g0,%g1,%g0     // carry
3490           ld [%o0-32],%o4       // source1-digit
3491           ld [%o1-32],%o5       // source2-digit
3492           subxcc %o4,%o5,%o4    // subtrahieren
3493           st %o4,[%o2-32]       // Digit ablegen
3494           ld [%o0-28],%o4       // source1-digit
3495           ld [%o1-28],%o5       // source2-digit
3496           subxcc %o4,%o5,%o4    // subtrahieren
3497           st %o4,[%o2-28]       // Digit ablegen
3498           ld [%o0-24],%o4       // source1-digit
3499           ld [%o1-24],%o5       // source2-digit
3500           subxcc %o4,%o5,%o4    // subtrahieren
3501           st %o4,[%o2-24]       // Digit ablegen
3502           ld [%o0-20],%o4       // source1-digit
3503           ld [%o1-20],%o5       // source2-digit
3504           subxcc %o4,%o5,%o4    // subtrahieren
3505           st %o4,[%o2-20]       // Digit ablegen
3506           ld [%o0-16],%o4       // source1-digit
3507           ld [%o1-16],%o5       // source2-digit
3508           subxcc %o4,%o5,%o4    // subtrahieren
3509           st %o4,[%o2-16]       // Digit ablegen
3510           ld [%o0-12],%o4       // source1-digit
3511           ld [%o1-12],%o5       // source2-digit
3512           subxcc %o4,%o5,%o4    // subtrahieren
3513           st %o4,[%o2-12]       // Digit ablegen
3514           ld [%o0-8],%o4        // source1-digit
3515           ld [%o1-8],%o5        // source2-digit
3516           subxcc %o4,%o5,%o4    // subtrahieren
3517           st %o4,[%o2-8]        // Digit ablegen
3518           ld [%o0-4],%o4        // source1-digit
3519           ld [%o1-4],%o5        // source2-digit
3520           subxcc %o4,%o5,%o4    // subtrahieren
3521           st %o4,[%o2-4]        // Digit ablegen
3522           addx %g0,%g0,%g1      // neuer Carry
3523           add %o0,32,%o0
3524           add %o1,32,%o1
3525           subcc %o3,8,%o3       // noch mindestens 8 Digits abzuarbeiten?
3526           bcc 1b
3527          _ add %o2,32,%o2
3528 #ifdef PIC
3529         jmp %g2+8
3530 #else
3531         retl
3532 #endif
3533        _ mov %g1,%o0
3534 #endif
3535
3536 // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
3537         DECLARE_FUNCTION(subfrom_loop_up)
3538 C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
3539 #if STANDARD_LOOPS
3540         andcc %o2,%o2,%g0
3541         be 2f
3542        _ mov %g0,%o5            // Carry := 0
3543 1:        ld [%o0],%o3          // source-digit
3544           add %o0,4,%o0
3545           ld [%o1],%o4          // dest-digit
3546           subcc %g0,%o5,%g0     // carry
3547           subxcc %o4,%o3,%o4    // subtrahieren
3548           addx %g0,%g0,%o5      // neuer Carry
3549           st %o4,[%o1]          // Digit ablegen
3550           subcc %o2,1,%o2
3551           bne 1b
3552          _ add %o1,4,%o1
3553 2:      retl
3554        _ mov %o5,%o0
3555 #endif
3556 #if COUNTER_LOOPS
3557         subcc %g0,%o2,%o2       // %o2 = -count
3558         be 2f
3559        _ mov %g0,%o5            // Carry := 0
3560         sll %o2,2,%o2           // %o2 = -4*count
3561         sub %o0,%o2,%o0         // %o0 = &sourceptr[count]
3562         sub %o1,%o2,%o1         // %o1 = &destptr[count]
3563           ld [%o0+%o2],%o3      // source-digit
3564 1:        ld [%o1+%o2],%o4      // dest-digit
3565           subcc %g0,%o5,%g0     // carry
3566           subxcc %o4,%o3,%o4    // subtrahieren
3567           addx %g0,%g0,%o5      // neuer Carry
3568           st %o4,[%o1+%o2]      // Digit ablegen
3569           addcc %o2,4,%o2
3570           bne,a 1b
3571          __ ld [%o0+%o2],%o3    // source-digit
3572 2:      retl
3573        _ mov %o5,%o0
3574 #endif
3575 #if UNROLLED_LOOPS
3576         and %o2,7,%o3           // count mod 8
3577         sll %o3,2,%o4
3578         add %o0,%o4,%o0         // %o0 = &sourceptr[count mod 8]
3579         add %o1,%o4,%o1         // %o1 = &destptr[count mod 8]
3580         sll %o3,4,%o3
3581 #ifdef PIC
3582         mov %o7,%g2             // save return address
3583         call 0f                 // put address of label 0 into %o7
3584        _ add %o7,144,%o4
3585 0:
3586 #else
3587         set _subfrom_loop_up+172,%o4
3588 #endif
3589         sub %o4,%o3,%o4
3590         jmp %o4                 // Sprung nach _subfrom_loop_up+4*(11+4*8-4*(count mod 8))
3591        _ subcc %g0,%g0,%g0      // carry löschen
3592 1:        subcc %g0,%o5,%g0     // carry
3593           ld [%o0-32],%o3       // source-digit
3594           ld [%o1-32],%o4       // dest-digit
3595           subxcc %o4,%o3,%o4    // subtrahieren
3596           st %o4,[%o1-32]       // Digit ablegen
3597           ld [%o0-28],%o3       // source-digit
3598           ld [%o1-28],%o4       // dest-digit
3599           subxcc %o4,%o3,%o4    // subtrahieren
3600           st %o4,[%o1-28]       // Digit ablegen
3601           ld [%o0-24],%o3       // source-digit
3602           ld [%o1-24],%o4       // dest-digit
3603           subxcc %o4,%o3,%o4    // subtrahieren
3604           st %o4,[%o1-24]       // Digit ablegen
3605           ld [%o0-20],%o3       // source-digit
3606           ld [%o1-20],%o4       // dest-digit
3607           subxcc %o4,%o3,%o4    // subtrahieren
3608           st %o4,[%o1-20]       // Digit ablegen
3609           ld [%o0-16],%o3       // source-digit
3610           ld [%o1-16],%o4       // dest-digit
3611           subxcc %o4,%o3,%o4    // subtrahieren
3612           st %o4,[%o1-16]       // Digit ablegen
3613           ld [%o0-12],%o3       // source-digit
3614           ld [%o1-12],%o4       // dest-digit
3615           subxcc %o4,%o3,%o4    // subtrahieren
3616           st %o4,[%o1-12]       // Digit ablegen
3617           ld [%o0-8],%o3        // source-digit
3618           ld [%o1-8],%o4        // dest-digit
3619           subxcc %o4,%o3,%o4    // subtrahieren
3620           st %o4,[%o1-8]        // Digit ablegen
3621           ld [%o0-4],%o3        // source-digit
3622           ld [%o1-4],%o4        // dest-digit
3623           subxcc %o4,%o3,%o4    // subtrahieren
3624           st %o4,[%o1-4]        // Digit ablegen
3625           addx %g0,%g0,%o5      // neuer Carry
3626           add %o0,32,%o0
3627           subcc %o2,8,%o2       // noch mindestens 8 Digits abzuarbeiten?
3628           bcc 1b
3629          _ add %o1,32,%o1
3630 #ifdef PIC
3631         jmp %g2+8
3632 #else
3633         retl
3634 #endif
3635        _ mov %o5,%o0
3636 #endif
3637
3638 // extern uintD dec_loop_up (uintD* ptr, uintC count);
3639         DECLARE_FUNCTION(dec_loop_up)
3640 C(dec_loop_up:) // Input in %o0,%o1, Output in %o0
3641 #if STANDARD_LOOPS
3642         andcc %o1,%o1,%g0
3643         be 2f
3644        _ nop
3645           ld [%o0],%o2
3646 1:        add %o0,4,%o0
3647           subcc %o2,1,%o2
3648           bcc 3f
3649          _ st %o2,[%o0-4]
3650           subcc %o1,1,%o1
3651           bne,a 1b
3652          __ ld [%o0],%o2
3653 2:      retl
3654        _ mov -1,%o0
3655 3:      retl
3656        _ mov 0,%o0
3657 #endif
3658 #if COUNTER_LOOPS
3659         subcc %g0,%o1,%o1       // %o1 = -count
3660         be 2f
3661        _ sll %o1,2,%o1          // %o1 = -4*count
3662         sub %o0,%o1,%o0         // %o0 = &ptr[count]
3663           ld [%o0+%o1],%o2      // digit holen
3664 1:        subcc %o2,1,%o2       // decrementieren
3665           bcc 3f
3666          _ st %o2,[%o0+%o1]     // ablegen
3667           addcc %o1,4,%o1       // Zähler erniedrigen, Pointer erhöhen
3668           bne,a 1b
3669          __ ld [%o0+%o1],%o2
3670 2:      retl
3671        _ mov -1,%o0
3672 3:      retl
3673        _ mov 0,%o0
3674 #endif
3675
3676 // extern uintD neg_loop_up (uintD* ptr, uintC count);
3677         DECLARE_FUNCTION(neg_loop_up)
3678 C(neg_loop_up:) // Input in %o0,%o1, Output in %o0
3679 #if STANDARD_LOOPS
3680         // erstes Digit /=0 suchen:
3681         andcc %o1,%o1,%g0
3682         be 2f
3683        _ add %o0,4,%o0
3684 1:        ld [%o0-4],%o2
3685           subcc %g0,%o2,%o2
3686           bne 3f
3687          _ subcc %o1,1,%o1
3688           bne 1b
3689          _ add %o0,4,%o0
3690 2:      retl
3691        _ mov 0,%o0
3692 3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
3693         // 1 Digit negieren, alle anderen Digits invertieren:
3694         be 5f
3695        _ st %o2,[%o0-4]
3696 4:        ld [%o0],%o2
3697           subcc %o1,1,%o1
3698           xor %o2,-1,%o2
3699           st %o2,[%o0]
3700           bne 4b
3701          _ add %o0,4,%o0
3702 5:      retl
3703        _ mov -1,%o0
3704 #endif
3705 #if COUNTER_LOOPS
3706         // erstes Digit /=0 suchen:
3707         subcc %g0,%o1,%o1       // %o1 = -count
3708         be 2f
3709        _ sll %o1,2,%o1          // %o1 = -4*count
3710         sub %o0,%o1,%o0         // %o0 = &ptr[count]
3711           ld [%o0+%o1],%o2      // digit holen
3712 1:        subcc %g0,%o2,%o2     // negieren, testen
3713           bne 3f
3714          _ addcc %o1,4,%o1      // Zähler erniedrigen, Pointer erhöhen
3715           bne,a 1b
3716          __ ld [%o0+%o1],%o2
3717 2:      retl
3718        _ mov 0,%o0
3719 3:      // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
3720         // alle anderen Digits invertieren:
3721         sub %o1,4,%o1
3722         st %o2,[%o0+%o1]        // ablegen
3723         addcc %o1,4,%o1
3724         be 5f
3725        _ nop
3726           ld [%o0+%o1],%o2
3727 4:        xor %o2,-1,%o2
3728           st %o2,[%o0+%o1]
3729           addcc %o1,4,%o1
3730           bne,a 4b
3731          __ ld [%o0+%o1],%o2
3732 5:      retl
3733        _ mov -1,%o0
3734 #endif
3735
3736 // extern uintD shift1left_loop_up (uintD* ptr, uintC count);
3737         DECLARE_FUNCTION(shift1left_loop_up)
3738 C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0
3739         andcc %o1,%o1,%g0
3740         be 2f
3741        _ mov 0,%o3              // Carry := 0
3742 1:        ld [%o0],%o2          // Digit
3743           subcc %g0,%o3,%g0     // carry
3744           addxcc %o2,%o2,%o2    // shiften
3745           addx %g0,%g0,%o3      // neues Carry
3746           st %o2,[%o0]          // Digit ablegen
3747           subcc %o1,1,%o1
3748           bne 1b
3749          _ add %o0,4,%o0
3750 2:      retl
3751        _ mov %o3,%o0
3752
3753 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
3754         DECLARE_FUNCTION(shiftleft_loop_up)
3755 C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
3756         andcc %o1,%o1,%g0
3757         be 2f
3758        _ sub %g0,%o2,%g1        // 32-i (mod 32)
3759 1:        ld [%o0],%o4          // Digit
3760           subcc %o1,1,%o1
3761           sll %o4,%o2,%o5       // dessen niedere (32-i) Bits
3762           or %o3,%o5,%o5        // mit dem alten Carry kombinieren
3763           st %o5,[%o0]          // Digit ablegen
3764           srl %o4,%g1,%o3       // dessen höchste i Bits liefern den neuen Carry
3765           bne 1b
3766          _ add %o0,4,%o0
3767 2:      retl
3768        _ mov %o3,%o0
3769
3770 #endif
3771
3772 // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
3773         DECLARE_FUNCTION(shiftleftcopy_loop_up)
3774 C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
3775         andcc %o2,%o2,%g0
3776         be 2f
3777        _ mov 0,%o4              // Carry := 0
3778         sub %g0,%o3,%g1         // 32-i (mod 32)
3779 1:        ld [%o0],%o5          // Digit
3780           subcc %o2,1,%o2
3781           sll %o5,%o3,%g2       // dessen niedere (32-i) Bits
3782           or %o4,%g2,%g2        // mit dem alten Carry kombinieren
3783           st %g2,[%o1]          // Digit ablegen
3784           add %o1,4,%o1
3785           srl %o5,%g1,%o4       // dessen höchste i Bits liefern den neuen Carry
3786           bne 1b
3787          _ add %o0,4,%o0
3788 2:      retl
3789        _ mov %o4,%o0
3790
3791 #if !CL_DS_BIG_ENDIAN_P
3792
3793 // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
3794         DECLARE_FUNCTION(shift1right_loop_down)
3795 C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
3796         andcc %o1,%o1,%g0
3797         be 2f
3798        _ sll %o2,31,%o2         // Carry
3799         sub %o0,4,%o0
3800 1:        ld [%o0],%o3          // Digit
3801           subcc %o1,1,%o1
3802           srl %o3,1,%o4         // shiften
3803           or %o2,%o4,%o4        // und mit altem Carry kombinieren
3804           st %o4,[%o0]          // und ablegen
3805           sll %o3,31,%o2        // neuer Carry
3806           bne 1b
3807          _ sub %o0,4,%o0
3808 2:      retl
3809        _ mov %o2,%o0
3810
3811 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
3812         DECLARE_FUNCTION(shiftright_loop_down)
3813 C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
3814         sub %g0,%o2,%g1         // 32-i (mod 32)
3815         andcc %o1,%o1,%g0
3816         be 2f
3817        _ or %g0,%g0,%o3         // Carry := 0
3818         sub %o0,4,%o0
3819 1:        ld [%o0],%o4          // Digit
3820           subcc %o1,1,%o1
3821           srl %o4,%o2,%o5       // shiften
3822           or %o3,%o5,%o5        // und mit altem Carry kombinieren
3823           st %o5,[%o0]          // und ablegen
3824           sll %o4,%g1,%o3       // neuer Carry
3825           bne 1b
3826          _ sub %o0,4,%o0
3827 2:      retl
3828        _ mov %o3,%o0
3829
3830 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
3831         DECLARE_FUNCTION(shiftrightsigned_loop_down)
3832 C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
3833         ld [%o0-4],%o4          // erstes Digit
3834         sub %g0,%o2,%g1         // 32-i (mod 32)
3835         sra %o4,%o2,%o5         // shiften
3836         st %o5,[%o0-4]          // und ablegen
3837         sll %o4,%g1,%o3         // neuer Carry
3838         subcc %o1,1,%o1
3839         be 2f
3840        _ sub %o0,8,%o0
3841 1:        ld [%o0],%o4          // Digit
3842           subcc %o1,1,%o1
3843           srl %o4,%o2,%o5       // shiften
3844           or %o3,%o5,%o5        // und mit altem Carry kombinieren
3845           st %o5,[%o0]          // und ablegen
3846           sll %o4,%g1,%o3       // neuer Carry
3847           bne 1b
3848          _ sub %o0,4,%o0
3849 2:      retl
3850        _ mov %o3,%o0
3851
3852 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
3853         DECLARE_FUNCTION(shiftrightcopy_loop_down)
3854 C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
3855         sub %g0,%o3,%g1         // 32-i (mod 32)
3856         andcc %o2,%o2,%g0
3857         be 2f
3858        _ sll %o4,%g1,%g2        // erster Carry
3859           sub %o0,4,%o0
3860 1:        ld [%o0],%o4          // Digit
3861           sub %o1,4,%o1
3862           srl %o4,%o3,%o5       // shiften
3863           or %g2,%o5,%o5        // und mit altem Carry kombinieren
3864           st %o5,[%o1]          // und ablegen
3865           sll %o4,%g1,%g2       // neuer Carry
3866           subcc %o2,1,%o2
3867           bne 1b
3868          _ sub %o0,4,%o0
3869 2:      retl
3870        _ mov %g2,%o0
3871
3872 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
3873         DECLARE_FUNCTION(mulusmall_loop_up)
3874 C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0
3875         andcc %o2,%o2,%g0
3876         be 3f
3877        _ nop
3878 1:        // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
3879           // und kleinen Carry %o3 dazu:
3880           mov %o0,%y
3881           ld [%o1],%o4          // Wartetakt!
3882           addcc %o3,%o3,%o5
3883           mulscc %o5,%o4,%o5
3884           mulscc %o5,%o4,%o5
3885           mulscc %o5,%o4,%o5
3886           mulscc %o5,%o4,%o5
3887           mulscc %o5,%o4,%o5
3888           mulscc %o5,%o4,%o5
3889           mulscc %o5,%g0,%o5
3890           // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y
3891           // ergeben das Resultat. (Die anderen Bits sind Null.)
3892           tst %o4               // Korrektur, falls %o4 negativ war
3893           bge 2f
3894          _ sra %o5,26,%o3       // 6 obere Bits von %o5 -> neuer Carry
3895           add %o3,%o0,%o3       // (falls %o4 negativ war, noch + %o0)
3896 2:        rd %y,%o4
3897           srl %o4,26,%o4        // 6 obere Bits von %y
3898           sll %o5,6,%o5         // 26 untere Bits von %o5
3899           or %o5,%o4,%o4        // neues Digit
3900           st %o4,[%o1]          // ablegen
3901           subcc %o2,1,%o2
3902           bne 1b
3903          _ add %o1,4,%o1
3904 3:      retl
3905        _ mov %o3,%o0
3906
3907 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
3908 #if !MULU32_INLINE
3909         DECLARE_FUNCTION(mulu_loop_up)
3910 C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
3911         save %sp,-96,%sp
3912         mov 0,%l0               // Carry
3913 1:        ld [%i1],%o1          // nächstes Digit
3914           add %i1,4,%i1
3915           call _mulu32_         // mit digit multiplizieren
3916          _ mov %i0,%o0
3917           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
3918           addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
3919           st %o0,[%i2]         // Low-Digit ablegen
3920           subcc %i3,1,%i3
3921           bne 1b
3922          _ add %i2,4,%i2
3923         st %l0,[%i2]            // letzten Carry ablegen
3924         ret
3925        _ restore
3926 #else
3927         DECLARE_FUNCTION(mulu_loop_up)
3928 C(mulu_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1
3929         mov 0,%o4               // Carry
3930 1:        ld [%o1],%g1          // nächstes Digit
3931           // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
3932 #ifdef sparcv8
3933           add     %o1,4,%o1
3934           umul    %g1,%o0,%g1
3935           rd      %y,%o5
3936 #else
3937           mov     %g1,%y
3938           add     %o1,4,%o1     // Wartetakt!
3939           andcc   %g0,%g0,%o5
3940           mulscc  %o5,%o0,%o5
3941           mulscc  %o5,%o0,%o5
3942           mulscc  %o5,%o0,%o5
3943           mulscc  %o5,%o0,%o5
3944           mulscc  %o5,%o0,%o5
3945           mulscc  %o5,%o0,%o5
3946           mulscc  %o5,%o0,%o5
3947           mulscc  %o5,%o0,%o5
3948           mulscc  %o5,%o0,%o5
3949           mulscc  %o5,%o0,%o5
3950           mulscc  %o5,%o0,%o5
3951           mulscc  %o5,%o0,%o5
3952           mulscc  %o5,%o0,%o5
3953           mulscc  %o5,%o0,%o5
3954           mulscc  %o5,%o0,%o5
3955           mulscc  %o5,%o0,%o5
3956           mulscc  %o5,%o0,%o5
3957           mulscc  %o5,%o0,%o5
3958           mulscc  %o5,%o0,%o5
3959           mulscc  %o5,%o0,%o5
3960           mulscc  %o5,%o0,%o5
3961           mulscc  %o5,%o0,%o5
3962           mulscc  %o5,%o0,%o5
3963           mulscc  %o5,%o0,%o5
3964           mulscc  %o5,%o0,%o5
3965           mulscc  %o5,%o0,%o5
3966           mulscc  %o5,%o0,%o5
3967           mulscc  %o5,%o0,%o5
3968           mulscc  %o5,%o0,%o5
3969           mulscc  %o5,%o0,%o5
3970           mulscc  %o5,%o0,%o5
3971           mulscc  %o5,%o0,%o5
3972           mulscc  %o5,%g0,%o5
3973           tst     %o0
3974           bl,a    2f
3975          __ add     %o5,%g1,%o5
3976 2:        rd      %y,%g1
3977 #endif
3978           addcc %o4,%g1,%g1     // und bisherigen Carry addieren
3979           addx %g0,%o5,%o4      // High-Digit gibt neuen Carry
3980           st %g1,[%o2]          // Low-Digit ablegen
3981           subcc %o3,1,%o3
3982           bne 1b
3983          _ add %o2,4,%o2
3984         retl
3985        _ st %o4,[%o2]           // letzten Carry ablegen
3986 #endif
3987
3988 // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
3989         DECLARE_FUNCTION(muluadd_loop_up)
3990 C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
3991 #if !MULU32_INLINE
3992         save %sp,-96,%sp
3993         mov 0,%l0               // Carry
3994 1:        ld [%i1],%o1          // nächstes source-Digit
3995           add %i1,4,%i1
3996           call _mulu32_         // mit digit multiplizieren
3997          _ mov %i0,%o0
3998           ld [%i2],%o1          // nächstes dest-digit
3999           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
4000           addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
4001           addcc %o1,%o0,%o0     // addieren
4002           addx %g0,%l0,%l0
4003           st %o0,[%i2]          // Low-Digit ablegen
4004           subcc %i3,1,%i3
4005           bne 1b
4006          _ add %i2,4,%i2
4007         mov %l0,%i0             // letzter Carry
4008         ret
4009        _ restore
4010 #else
4011         save %sp,-96,%sp
4012         mov 0,%l0               // Carry
4013 #ifndef sparcv8
4014         sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
4015 #endif
4016 1:        ld [%i1],%o1          // nächstes source-Digit
4017           add %i1,4,%i1
4018           // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
4019 #ifdef sparcv8
4020           umul    %i0,%o1,%o0
4021           rd      %y,%o2
4022 #else
4023           mov     %o1,%y
4024           and     %o1,%l1,%o3   // Wartetakt!
4025           andcc   %g0,%g0,%o2
4026           mulscc  %o2,%i0,%o2
4027           mulscc  %o2,%i0,%o2
4028           mulscc  %o2,%i0,%o2
4029           mulscc  %o2,%i0,%o2
4030           mulscc  %o2,%i0,%o2
4031           mulscc  %o2,%i0,%o2
4032           mulscc  %o2,%i0,%o2
4033           mulscc  %o2,%i0,%o2
4034           mulscc  %o2,%i0,%o2
4035           mulscc  %o2,%i0,%o2
4036           mulscc  %o2,%i0,%o2
4037           mulscc  %o2,%i0,%o2
4038           mulscc  %o2,%i0,%o2
4039           mulscc  %o2,%i0,%o2
4040           mulscc  %o2,%i0,%o2
4041           mulscc  %o2,%i0,%o2
4042           mulscc  %o2,%i0,%o2
4043           mulscc  %o2,%i0,%o2
4044           mulscc  %o2,%i0,%o2
4045           mulscc  %o2,%i0,%o2
4046           mulscc  %o2,%i0,%o2
4047           mulscc  %o2,%i0,%o2
4048           mulscc  %o2,%i0,%o2
4049           mulscc  %o2,%i0,%o2
4050           mulscc  %o2,%i0,%o2
4051           mulscc  %o2,%i0,%o2
4052           mulscc  %o2,%i0,%o2
4053           mulscc  %o2,%i0,%o2
4054           mulscc  %o2,%i0,%o2
4055           mulscc  %o2,%i0,%o2
4056           mulscc  %o2,%i0,%o2
4057           mulscc  %o2,%i0,%o2
4058           mulscc  %o2,%g0,%o2
4059           add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
4060           rd      %y,%o0
4061 #endif
4062           ld [%i2],%o1          // nächstes dest-digit
4063           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
4064           addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
4065           addcc %o1,%o0,%o0     // addieren
4066           addx %g0,%l0,%l0
4067           st %o0,[%i2]          // Low-Digit ablegen
4068           subcc %i3,1,%i3
4069           bne 1b
4070          _ add %i2,4,%i2
4071         mov %l0,%i0             // letzter Carry
4072         ret
4073        _ restore
4074 #endif
4075
4076 // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
4077         DECLARE_FUNCTION(mulusub_loop_up)
4078 C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
4079 #if !MULU32_INLINE
4080         save %sp,-96,%sp
4081         mov 0,%l0               // Carry
4082 1:        ld [%i1],%o1          // nächstes source-Digit
4083           add %i1,4,%i1
4084           call _mulu32_         // mit digit multiplizieren
4085          _ mov %i0,%o0
4086           ld [%i2],%o1          // nächstes dest-digit
4087           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
4088           addx %g0,%g1,%l0      // High-Digit gibt neuen Carry
4089           subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
4090           addx %g0,%l0,%l0
4091           st %o1,[%i2]         // dest-Digit ablegen
4092           subcc %i3,1,%i3
4093           bne 1b
4094          _ add %i2,4,%i2
4095         mov %l0,%i0             // letzter Carry
4096         ret
4097        _ restore
4098 #else
4099         save %sp,-96,%sp
4100         mov 0,%l0               // Carry
4101 #ifndef sparcv8
4102         sra %i0,31,%l1          // 0 falls %i0>=0, -1 falls %i0<0
4103 #endif
4104 1:        ld [%i1],%o1          // nächstes source-Digit
4105           add %i1,4,%i1
4106           // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
4107 #ifdef sparcv8
4108           umul    %i0,%o1,%o0
4109           rd      %y,%o2
4110 #else
4111           mov     %o1,%y
4112           and     %o1,%l1,%o3   // Wartetakt!
4113           andcc   %g0,%g0,%o2
4114           mulscc  %o2,%i0,%o2
4115           mulscc  %o2,%i0,%o2
4116           mulscc  %o2,%i0,%o2
4117           mulscc  %o2,%i0,%o2
4118           mulscc  %o2,%i0,%o2
4119           mulscc  %o2,%i0,%o2
4120           mulscc  %o2,%i0,%o2
4121           mulscc  %o2,%i0,%o2
4122           mulscc  %o2,%i0,%o2
4123           mulscc  %o2,%i0,%o2
4124           mulscc  %o2,%i0,%o2
4125           mulscc  %o2,%i0,%o2
4126           mulscc  %o2,%i0,%o2
4127           mulscc  %o2,%i0,%o2
4128           mulscc  %o2,%i0,%o2
4129           mulscc  %o2,%i0,%o2
4130           mulscc  %o2,%i0,%o2
4131           mulscc  %o2,%i0,%o2
4132           mulscc  %o2,%i0,%o2
4133           mulscc  %o2,%i0,%o2
4134           mulscc  %o2,%i0,%o2
4135           mulscc  %o2,%i0,%o2
4136           mulscc  %o2,%i0,%o2
4137           mulscc  %o2,%i0,%o2
4138           mulscc  %o2,%i0,%o2
4139           mulscc  %o2,%i0,%o2
4140           mulscc  %o2,%i0,%o2
4141           mulscc  %o2,%i0,%o2
4142           mulscc  %o2,%i0,%o2
4143           mulscc  %o2,%i0,%o2
4144           mulscc  %o2,%i0,%o2
4145           mulscc  %o2,%i0,%o2
4146           mulscc  %o2,%g0,%o2
4147           add     %o2,%o3,%o2   // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
4148           rd      %y,%o0
4149 #endif
4150           ld [%i2],%o1          // nächstes dest-digit
4151           addcc %l0,%o0,%o0     // und bisherigen Carry addieren
4152           addx %g0,%o2,%l0      // High-Digit gibt neuen Carry
4153           subcc %o1,%o0,%o1     // davon das Low-Digit subtrahieren
4154           addx %g0,%l0,%l0
4155           st %o1,[%i2]          // dest-Digit ablegen
4156           subcc %i3,1,%i3
4157           bne 1b
4158          _ add %i2,4,%i2
4159         mov %l0,%i0             // letzter Carry
4160         ret
4161        _ restore
4162 #endif
4163
4164 // extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len);
4165         DECLARE_FUNCTION(divu_loop_down)
4166 C(divu_loop_down:) // Input in %i0,%i1,%i2, Output in %i0
4167         save %sp,-96,%sp
4168         andcc %i2,%i2,%g0
4169         be 2f
4170        _ mov 0,%g1                 // Rest
4171 1:        mov %g1,%o0              // Rest als High-Digit
4172           ld [%i1-4],%o1           // nächstes Digit als Low-Digit
4173           call C(divu_6432_3232_)  // zusammen durch digit dividieren
4174          _ mov %i0,%o2
4175           st %o0,[%i1-4]           // Quotient ablegen, Rest in %g1
4176           subcc %i2,1,%i2
4177           bne 1b
4178          _ sub %i1,4,%i1
4179 2:      mov %g1,%i0                // Rest als Ergebnis
4180         ret
4181        _ restore
4182
4183 // extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
4184         DECLARE_FUNCTION(divucopy_loop_down)
4185 C(divucopy_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
4186         save %sp,-96,%sp
4187         andcc %i3,%i3,%g0
4188         be 2f
4189        _ mov 0,%g1                 // Rest
4190 1:        mov %g1,%o0              // Rest als High-Digit
4191           ld [%i1-4],%o1           // nächstes Digit als Low-Digit
4192           call C(divu_6432_3232_)  // zusammen durch digit dividieren
4193          _ mov %i0,%o2
4194           sub %i2,4,%i2
4195           st %o0,[%i2]             // Quotient ablegen, Rest in %g1
4196           subcc %i3,1,%i3
4197           bne 1b
4198          _ sub %i1,4,%i1
4199 2:      mov %g1,%i0                // Rest als Ergebnis
4200         ret
4201        _ restore
4202
4203 #endif
4204
4205 // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
4206         DECLARE_FUNCTION(shiftxor_loop_up)
4207 C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2
4208         andcc %o2,%o2,%g0
4209         be 2f
4210        _ sub %g0,%o3,%g1        // 32-i (mod 32)
4211         sub %o1,%o0,%o1
4212         ld [%o0],%o4            // *xptr holen
4213 1:        ld [%o0+%o1],%o5      // *yptr holen
4214           subcc %o2,1,%o2
4215           sll %o5,%o3,%g2       // dessen niedere (32-i) Bits
4216           xor %o4,%g2,%o4       // mit dem modifizierten *xptr kombinieren
4217           st %o4,[%o0]          // und ablegen
4218           add %o0,4,%o0
4219           srl %o5,%g1,%g2       // höchste i Bits von *yptr
4220           ld [%o0],%o4          // schon mal mit dem nächsten *xptr
4221           bne 1b
4222          _ xor %o4,%g2,%o4      // verknüpfen
4223         st %o4,[%o0]            // und ablegen
4224 2:      retl
4225        _ nop
4226