1 // Externe Routinen zu ARILEV1.D
3 // Compiler: GNU-C oder SUN-C
4 // Parameter-Übergabe: in Registern %o0-%o5.
5 // Einstellungen: intCsize=32, intDsize=32.
7 #if defined(sparc_v8) || defined(__sparc_v8) || defined(__sparc_v8__)
11 #ifdef ASM_UNDERSCORE /* SunOS 4 */
12 #if defined(__STDC__) || defined (__cplusplus)
13 #define C(entrypoint) _##entrypoint
15 #define C(entrypoint) _/**/entrypoint
17 #else /* SunOS 5 = Solaris 2 */
18 #define C(entrypoint) entrypoint
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
28 #define DECLARE_FUNCTION(name)
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)
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)
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)
73 #define LOOP_TYPE 1 // 1: Standard-Schleifen
74 // 2: Schleifen ohne Pointer, nur mit Zähler
75 // 3: entrollte Schleifen
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
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
92 nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC
110 // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
111 // ergeben das Resultat. (Die anderen Bits sind Null.)
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
129 sra %o0,31,%o3 // Wartetakt, nötig z.B. für SUN SPARCstation IPC
164 and %o3,%o1,%o3 // %o3 = (0 falls %o0>=0, %o1 falls %o0<0)
165 add %o2,%o3,%g1 // hi
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
182 // arg1 < arg2, also kann man arg1 < 2^16 annehmen.
184 nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC
202 // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
203 // ergeben das Resultat. (Die anderen Bits sind Null.)
209 1: // arg1 >= arg2, also kann man arg2 < 2^16 annehmen.
210 nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC
228 // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
229 // ergeben das Resultat.
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
242 // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
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
250 _ sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r
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 */\
262 #define SA1(label) /* Vergleichsschritt mit %o3 */\
266 #define SB0() /* Additionsschritt mit %o0 */\
268 #define SB1() /* Additionsschritt mit %o3 */\
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
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'))
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
327 subcc %o3,%o2,%o0 // muß der Quotient nochmals erhöht werden?
330 // Quotient 2 mal erhöhen, Rest %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
338 2: // Quotient %o1 erhöhen, Rest = %o0-%o2 = %o3
341 3: // Quotient %o1 und Rest %o0 OK
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'))
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
388 subcc %o0,%o2,%o3 // muß der Quotient nochmals erhöht werden?
391 // Quotient 2 mal erhöhen, Rest %o3
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
399 2: // Quotient %o1 erhöhen, Rest = %o3-%o2 = %o0
402 3: // Quotient %o1 und Rest %o3 OK
406 Lsmalldiv: // Division durch y < 2^31
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
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
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
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)
553 mov %o3,%g1 // Rest aus %o0 in %g1 abspeichern
555 _ xor %o1,-1,%o0 // Quotient nach %o0
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).
563 // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
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
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!)
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).
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.
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:
640 #if !defined(__GNUC__)
642 // extern uint32 _get_g1 (void);
643 DECLARE_FUNCTION(_get_g1)
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
666 subcc %g0,%o2,%o2 // %o2 = -count
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
675 _ st %o3,[%o1+%o2] // Digit ablegen
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
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
706 _ st %o3,[%o1+%o2] // Digit ablegen
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
726 subcc %g0,%o1,%o1 // %o1 = -count
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
733 _ st %o2,[%o0+%o1] // Digit ablegen
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
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
759 _ st %o2,[%o0+%o1] // Digit ablegen
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
779 subcc %g0,%o1,%o1 // %o1 = -count
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
786 _ st %g0,[%o0+%o1] // Digit 0 ablegen
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
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
812 _ st %g0,[%o0+%o1] // Digit 0 ablegen
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
837 subcc %g0,%o1,%o1 // %o1 = -count
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
844 _ addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen
846 __ ld [%o0+%o1],%o2 // nächstes Digit holen
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
873 sll %o1,2,%o1 // %o1 = 4*count
874 sub %o0,%o1,%o0 // %o0 = &ptr[-count]
878 ld [%o0+%o1],%o2 // nächstes Digit holen
879 1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
881 _ andcc %o2,%o2,%g0 // testen
883 __ ld [%o0+%o1],%o2 // nächstes Digit holen
892 #if CL_DS_BIG_ENDIAN_P
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
915 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
916 1: ld [%o0],%o3 // *xptr
917 ld [%o0+%o1],%o4 // *yptr
919 or %o3,%o4,%o3 // verknüpfen
920 st %o3,[%o0] // =: *xptr
922 _ add %o0,4,%o0 // xptr++, yptr++
927 subcc %g0,%o2,%o2 // %o2 = -count
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
938 _ st %o3,[%o1+%o2] // Digit ablegen
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
966 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
967 1: ld [%o0],%o3 // *xptr
968 ld [%o0+%o1],%o4 // *yptr
970 xor %o3,%o4,%o3 // verknüpfen
971 st %o3,[%o0] // =: *xptr
973 _ add %o0,4,%o0 // xptr++, yptr++
978 subcc %g0,%o2,%o2 // %o2 = -count
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
989 _ st %o3,[%o1+%o2] // Digit ablegen
994 #if CL_DS_BIG_ENDIAN_P
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
1017 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1018 1: ld [%o0],%o3 // *xptr
1019 ld [%o0+%o1],%o4 // *yptr
1021 and %o3,%o4,%o3 // verknüpfen
1022 st %o3,[%o0] // =: *xptr
1024 _ add %o0,4,%o0 // xptr++, yptr++
1029 subcc %g0,%o2,%o2 // %o2 = -count
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
1040 _ st %o3,[%o1+%o2] // Digit ablegen
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
1066 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1067 1: ld [%o0],%o3 // *xptr
1068 ld [%o0+%o1],%o4 // *yptr
1070 xnor %o3,%o4,%o3 // verknüpfen
1071 st %o3,[%o0] // =: *xptr
1073 _ add %o0,4,%o0 // xptr++, yptr++
1078 subcc %g0,%o2,%o2 // %o2 = -count
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
1089 _ st %o3,[%o1+%o2] // Digit ablegen
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
1116 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1117 1: ld [%o0],%o3 // *xptr
1118 ld [%o0+%o1],%o4 // *yptr
1120 and %o3,%o4,%o3 // verknüpfen
1122 st %o3,[%o0] // =: *xptr
1124 _ add %o0,4,%o0 // xptr++, yptr++
1129 subcc %g0,%o2,%o2 // %o2 = -count
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
1141 _ st %o3,[%o1+%o2] // Digit ablegen
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
1168 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1169 1: ld [%o0],%o3 // *xptr
1170 ld [%o0+%o1],%o4 // *yptr
1172 or %o3,%o4,%o3 // verknüpfen
1174 st %o3,[%o0] // =: *xptr
1176 _ add %o0,4,%o0 // xptr++, yptr++
1181 subcc %g0,%o2,%o2 // %o2 = -count
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
1193 _ st %o3,[%o1+%o2] // Digit ablegen
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
1219 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1220 1: ld [%o0],%o3 // *xptr
1221 ld [%o0+%o1],%o4 // *yptr
1223 andn %o3,%o4,%o3 // verknüpfen
1224 st %o3,[%o0] // =: *xptr
1226 _ add %o0,4,%o0 // xptr++, yptr++
1231 subcc %g0,%o2,%o2 // %o2 = -count
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
1242 _ st %o3,[%o1+%o2] // Digit ablegen
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
1268 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1269 1: ld [%o0],%o3 // *xptr
1270 ld [%o0+%o1],%o4 // *yptr
1272 orn %o3,%o4,%o3 // verknüpfen
1273 st %o3,[%o0] // =: *xptr
1275 _ add %o0,4,%o0 // xptr++, yptr++
1280 subcc %g0,%o2,%o2 // %o2 = -count
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
1291 _ st %o3,[%o1+%o2] // Digit ablegen
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
1313 subcc %g0,%o1,%o1 // %o1 = -count
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
1322 _ st %o2,[%o0+%o1] // Digit ablegen
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
1348 subcc %g0,%o2,%o2 // %o2 = -count
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
1357 _ addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1359 __ ld [%o0+%o2],%o3 // nächstes Digit holen
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
1394 subcc %g0,%o2,%o2 // %o2 = -count
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
1403 _ addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1405 __ ld [%o0+%o2],%o3 // nächstes Digit holen
1408 3: subcc %o3,%o4,%g0 // nochmals vergleichen
1417 #if CL_DS_BIG_ENDIAN_P
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
1425 _ mov %g0,%g1 // Carry := 0
1427 1: ld [%o0],%o4 // source1-digit
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
1434 st %o4,[%o2] // Digit ablegen
1444 _ mov %g0,%g1 // Carry := 0
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
1458 _ st %o4,[%o2+%o3] // Digit ablegen
1463 and %o3,7,%o4 // count mod 8
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)]
1470 mov %o7,%g2 // save return address
1471 call 0f // put address of label 0 into %o7
1475 set _add_loop_down+176,%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
1516 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
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
1533 _ mov %g0,%o5 // Carry := 0
1535 1: ld [%o0],%o3 // source-digit
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
1551 _ mov %g0,%o5 // Carry := 0
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
1565 __ ld [%o0+%o2],%o3 // source-digit
1570 and %o2,7,%o3 // count mod 8
1572 sub %o0,%o4,%o0 // %o0 = &sourceptr[-(count mod 8)]
1573 sub %o1,%o4,%o1 // %o1 = &destptr[-(count mod 8)]
1576 mov %o7,%g2 // save return address
1577 call 0f // put address of label 0 into %o7
1581 set _addto_loop_down+172,%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
1621 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
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
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
1660 _ st %o2,[%o0+%o1] // ablegen
1661 subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
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
1676 _ mov %g0,%g1 // Carry := 0
1678 1: ld [%o0],%o4 // source1-digit
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
1685 st %o4,[%o2] // Digit ablegen
1695 _ mov %g0,%g1 // Carry := 0
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
1709 _ st %o4,[%o2+%o3] // Digit ablegen
1714 and %o3,7,%o4 // count mod 8
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)]
1721 mov %o7,%g2 // save return address
1722 call 0f // put address of label 0 into %o7
1726 set _sub_loop_down+176,%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
1767 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
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
1784 _ mov %o4,%g1 // Carry
1786 1: ld [%o0],%o4 // source1-digit
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
1793 st %o4,[%o2] // Digit ablegen
1803 _ mov %o4,%g1 // Carry
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
1817 _ st %o4,[%o2+%o3] // Digit ablegen
1822 and %o3,7,%o5 // count mod 8
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)]
1829 mov %o7,%g2 // save return address
1830 call 0f // put address of label 0 into %o7
1834 set _subx_loop_down+176,%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
1875 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
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
1892 _ mov %g0,%o5 // Carry := 0
1894 1: ld [%o0],%o3 // source-digit
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
1910 _ mov %g0,%o5 // Carry := 0
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
1924 __ ld [%o0+%o2],%o3 // source-digit
1929 and %o2,7,%o3 // count mod 8
1931 sub %o0,%o4,%o0 // %o0 = &sourceptr[-(count mod 8)]
1932 sub %o1,%o4,%o1 // %o1 = &destptr[-(count mod 8)]
1935 mov %o7,%g2 // save return address
1936 call 0f // put address of label 0 into %o7
1940 set _subfrom_loop_down+172,%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
1980 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
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
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
2019 _ st %o2,[%o0+%o1] // ablegen
2020 subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
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
2033 // erstes Digit /=0 suchen:
2045 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2046 st %o2,[%o0] // 1 Digit negieren
2047 // alle anderen Digits invertieren:
2060 // erstes Digit /=0 suchen:
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
2069 _ subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
2074 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2075 // alle anderen Digits invertieren:
2077 st %o2,[%o0+%o1] // ablegen
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
2096 _ mov 0,%o3 // Carry := 0
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
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
2114 _ sub %g0,%o2,%g1 // 32-i (mod 32)
2116 1: ld [%o0],%o4 // Digit
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
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
2132 _ mov 0,%o4 // Carry := 0
2133 sub %g0,%o3,%g1 // 32-i (mod 32)
2135 1: ld [%o0],%o5 // Digit
2137 sll %o5,%o3,%g2 // dessen niedere (32-i) Bits
2138 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
2140 st %g2,[%o1] // Digit ablegen
2141 srl %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
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
2152 _ sll %o2,31,%o2 // Carry
2153 1: ld [%o0],%o3 // Digit
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
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)
2170 _ or %g0,%g0,%o3 // Carry := 0
2171 1: ld [%o0],%o4 // Digit
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
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
2193 1: ld [%o0],%o4 // Digit
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
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)
2210 _ sll %o4,%g1,%g2 // erster Carry
2211 1: ld [%o0],%o4 // Digit
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
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
2229 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
2230 // und kleinen Carry %o3 dazu:
2232 ld [%o1],%o4 // Wartetakt!
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
2245 _ sra %o5,26,%o3 // 6 obere Bits von %o5 -> neuer Carry
2246 add %o3,%o0,%o3 // (falls %o4 negativ war, noch + %o0)
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
2258 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2260 DECLARE_FUNCTION(mulu_loop_down)
2261 C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
2265 ld [%i1],%o1 // nächstes Digit
2266 call _mulu32_ // mit digit multiplizieren
2268 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
2269 addx %g0,%g1,%l0 // High-Digit gibt neuen Carry
2273 _ st %o0,[%i2] // Low-Digit ablegen
2274 st %l0,[%i2-4] // letzten Carry ablegen
2278 DECLARE_FUNCTION(mulu_loop_down)
2279 C(mulu_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1
2281 1: ld [%o1-4],%g1 // nächstes Digit
2282 // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
2289 sub %o1,4,%o1 // Wartetakt!
2329 addcc %o4,%g1,%g1 // und bisherigen Carry addieren
2330 addx %g0,%o5,%o4 // High-Digit gibt neuen Carry
2334 _ st %g1,[%o2] // Low-Digit ablegen
2336 _ st %o4,[%o2-4] // letzten Carry ablegen
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
2346 ld [%i1],%o1 // nächstes source-Digit
2347 call _mulu32_ // mit digit multiplizieren
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
2357 _ st %o0,[%i2] // Low-Digit ablegen
2358 mov %l0,%i0 // letzter Carry
2365 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
2367 1: ld [%i1-4],%o1 // nächstes source-Digit
2369 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
2375 and %o1,%l1,%o3 // Wartetakt!
2410 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
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
2421 _ st %o0,[%i2] // Low-Digit ablegen
2422 mov %l0,%i0 // letzter Carry
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
2434 ld [%i1],%o1 // nächstes source-Digit
2435 call _mulu32_ // mit digit multiplizieren
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
2445 _ st %o1,[%i2] // dest-Digit ablegen
2446 mov %l0,%i0 // letzter Carry
2453 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
2455 1: ld [%i1-4],%o1 // nächstes source-Digit
2457 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
2463 and %o1,%l1,%o3 // Wartetakt!
2498 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
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
2509 _ st %o1,[%i2] // dest-Digit ablegen
2510 mov %l0,%i0 // letzter Carry
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
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
2526 st %o0,[%i1] // Quotient ablegen, Rest in %g1
2530 2: mov %g1,%i0 // Rest als Ergebnis
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
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
2545 st %o0,[%i2] // Quotient ablegen, Rest in %g1
2550 2: mov %g1,%i0 // Rest als Ergebnis
2556 #if !CL_DS_BIG_ENDIAN_P
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
2579 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2581 1: ld [%o0],%o3 // *xptr
2582 ld [%o0+%o1],%o4 // *yptr
2584 or %o3,%o4,%o3 // verknüpfen
2585 st %o3,[%o0] // =: *xptr
2587 _ sub %o0,4,%o0 // xptr++, yptr++
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
2602 _ st %o3,[%o1+%o2] // Digit ablegen
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
2628 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2630 1: ld [%o0],%o3 // *xptr
2631 ld [%o0+%o1],%o4 // *yptr
2633 xor %o3,%o4,%o3 // verknüpfen
2634 st %o3,[%o0] // =: *xptr
2636 _ sub %o0,4,%o0 // xptr++, yptr++
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
2651 _ st %o3,[%o1+%o2] // Digit ablegen
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
2677 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2679 1: ld [%o0],%o3 // *xptr
2680 ld [%o0+%o1],%o4 // *yptr
2682 and %o3,%o4,%o3 // verknüpfen
2683 st %o3,[%o0] // =: *xptr
2685 _ sub %o0,4,%o0 // xptr++, yptr++
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
2700 _ st %o3,[%o1+%o2] // Digit ablegen
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
2726 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2728 1: ld [%o0],%o3 // *xptr
2729 ld [%o0+%o1],%o4 // *yptr
2731 xnor %o3,%o4,%o3 // verknüpfen
2732 st %o3,[%o0] // =: *xptr
2734 _ sub %o0,4,%o0 // xptr++, yptr++
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
2749 _ st %o3,[%o1+%o2] // Digit ablegen
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
2776 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2778 1: ld [%o0],%o3 // *xptr
2779 ld [%o0+%o1],%o4 // *yptr
2781 and %o3,%o4,%o3 // verknüpfen
2783 st %o3,[%o0] // =: *xptr
2785 _ sub %o0,4,%o0 // xptr++, yptr++
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
2801 _ st %o3,[%o1+%o2] // Digit ablegen
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
2828 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2830 1: ld [%o0],%o3 // *xptr
2831 ld [%o0+%o1],%o4 // *yptr
2833 or %o3,%o4,%o3 // verknüpfen
2835 st %o3,[%o0] // =: *xptr
2837 _ sub %o0,4,%o0 // xptr++, yptr++
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
2853 _ st %o3,[%o1+%o2] // Digit ablegen
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
2879 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2881 1: ld [%o0],%o3 // *xptr
2882 ld [%o0+%o1],%o4 // *yptr
2884 andn %o3,%o4,%o3 // verknüpfen
2885 st %o3,[%o0] // =: *xptr
2887 _ sub %o0,4,%o0 // xptr++, yptr++
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
2902 _ st %o3,[%o1+%o2] // Digit ablegen
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
2928 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2930 1: ld [%o0],%o3 // *xptr
2931 ld [%o0+%o1],%o4 // *yptr
2933 orn %o3,%o4,%o3 // verknüpfen
2934 st %o3,[%o0] // =: *xptr
2936 _ sub %o0,4,%o0 // xptr++, yptr++
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
2951 _ st %o3,[%o1+%o2] // Digit ablegen
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
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
2981 _ st %o2,[%o0+%o1] // Digit ablegen
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
3009 sll %o2,2,%o2 // %o2 = 4*count
3010 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
3011 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
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
3019 _ subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
3021 __ ld [%o0+%o2],%o3 // nächstes Digit holen
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
3053 sll %o2,2,%o2 // %o2 = 4*count
3054 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
3055 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
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
3063 _ subcc %o3,%o4,%g0 // vergleichen
3065 __ ld [%o0+%o2],%o3 // nächstes Digit holen
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
3084 _ subcc %g0,%g0,%g0 // Carry := 0
3085 1: ld [%o0],%o4 // source1-digit
3087 ld [%o1],%o5 // source2-digit
3089 addxcc %o4,%o5,%o4 // addieren
3090 addx %g0,%g0,%g1 // neuer Carry
3091 st %o4,[%o2] // Digit ablegen
3095 _ subcc %g0,%g1,%g0 // carry
3100 subcc %g0,%o3,%o3 // %o3 = -count
3102 _ mov %g0,%g1 // Carry := 0
3103 sll %o3,2,%o3 // %o3 = -4*count
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
3115 _ st %o4,[%o2+%o3] // Digit ablegen
3120 and %o3,7,%o4 // count mod 8
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]
3127 mov %o7,%g2 // save return address
3128 call 0f // put address of label 0 into %o7
3132 set _add_loop_up+176,%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
3173 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
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
3190 _ mov %g0,%o5 // Carry := 0
3191 1: ld [%o0],%o3 // source-digit
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
3205 subcc %g0,%o2,%o2 // %o2 = -count
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
3219 __ ld [%o0+%o2],%o3 // source-digit
3224 and %o2,7,%o3 // count mod 8
3226 add %o0,%o4,%o0 // %o0 = &sourceptr[count mod 8]
3227 add %o1,%o4,%o1 // %o1 = &destptr[count mod 8]
3230 mov %o7,%g2 // save return address
3231 call 0f // put address of label 0 into %o7
3235 set _addto_loop_up+172,%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
3275 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
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
3307 subcc %g0,%o1,%o1 // %o1 = -count
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
3314 _ st %o2,[%o0+%o1] // ablegen
3315 addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen
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
3330 _ subcc %g0,%g0,%g0 // Carry := 0
3331 1: ld [%o0],%o4 // source1-digit
3333 ld [%o1],%o5 // source2-digit
3335 subxcc %o4,%o5,%o4 // subtrahieren
3336 addx %g0,%g0,%g1 // neuer Carry
3337 st %o4,[%o2] // Digit ablegen
3341 _ subcc %g0,%g1,%g0 // carry
3346 subcc %g0,%o3,%o3 // %o3 = -count
3348 _ mov %g0,%g1 // Carry := 0
3349 sll %o3,2,%o3 // %o3 = -4*count
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
3361 _ st %o4,[%o2+%o3] // Digit ablegen
3366 and %o3,7,%o4 // count mod 8
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]
3373 mov %o7,%g2 // save return address
3374 call 0f // put address of label 0 into %o7
3378 set _sub_loop_up+176,%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
3419 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
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
3436 _ subcc %g0,%o4,%g0 // Carry
3437 1: ld [%o0],%o4 // source1-digit
3439 ld [%o1],%o5 // source2-digit
3441 subxcc %o4,%o5,%o4 // subtrahieren
3442 addx %g0,%g0,%g1 // neuer Carry
3443 st %o4,[%o2] // Digit ablegen
3447 _ subcc %g0,%g1,%g0 // carry
3452 subcc %g0,%o3,%o3 // %o3 = -count
3454 _ mov %o4,%g1 // Carry
3455 sll %o3,2,%o3 // %o3 = -4*count
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
3467 _ st %o4,[%o2+%o3] // Digit ablegen
3472 and %o3,7,%o5 // count mod 8
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]
3479 mov %o7,%g2 // save return address
3480 call 0f // put address of label 0 into %o7
3484 set _subx_loop_up+176,%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
3525 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
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
3542 _ mov %g0,%o5 // Carry := 0
3543 1: ld [%o0],%o3 // source-digit
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
3557 subcc %g0,%o2,%o2 // %o2 = -count
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
3571 __ ld [%o0+%o2],%o3 // source-digit
3576 and %o2,7,%o3 // count mod 8
3578 add %o0,%o4,%o0 // %o0 = &sourceptr[count mod 8]
3579 add %o1,%o4,%o1 // %o1 = &destptr[count mod 8]
3582 mov %o7,%g2 // save return address
3583 call 0f // put address of label 0 into %o7
3587 set _subfrom_loop_up+172,%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
3627 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
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
3659 subcc %g0,%o1,%o1 // %o1 = -count
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
3666 _ st %o2,[%o0+%o1] // ablegen
3667 addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen
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
3680 // erstes Digit /=0 suchen:
3692 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
3693 // 1 Digit negieren, alle anderen Digits invertieren:
3706 // erstes Digit /=0 suchen:
3707 subcc %g0,%o1,%o1 // %o1 = -count
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
3714 _ addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen
3719 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
3720 // alle anderen Digits invertieren:
3722 st %o2,[%o0+%o1] // ablegen
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
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
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
3758 _ sub %g0,%o2,%g1 // 32-i (mod 32)
3759 1: ld [%o0],%o4 // Digit
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
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
3777 _ mov 0,%o4 // Carry := 0
3778 sub %g0,%o3,%g1 // 32-i (mod 32)
3779 1: ld [%o0],%o5 // Digit
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
3785 srl %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
3791 #if !CL_DS_BIG_ENDIAN_P
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
3798 _ sll %o2,31,%o2 // Carry
3800 1: ld [%o0],%o3 // Digit
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
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)
3817 _ or %g0,%g0,%o3 // Carry := 0
3819 1: ld [%o0],%o4 // Digit
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
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
3841 1: ld [%o0],%o4 // Digit
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
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)
3858 _ sll %o4,%g1,%g2 // erster Carry
3860 1: ld [%o0],%o4 // Digit
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
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
3878 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
3879 // und kleinen Carry %o3 dazu:
3881 ld [%o1],%o4 // Wartetakt!
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
3894 _ sra %o5,26,%o3 // 6 obere Bits von %o5 -> neuer Carry
3895 add %o3,%o0,%o3 // (falls %o4 negativ war, noch + %o0)
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
3907 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
3909 DECLARE_FUNCTION(mulu_loop_up)
3910 C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
3913 1: ld [%i1],%o1 // nächstes Digit
3915 call _mulu32_ // mit digit multiplizieren
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
3923 st %l0,[%i2] // letzten Carry ablegen
3927 DECLARE_FUNCTION(mulu_loop_up)
3928 C(mulu_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1
3930 1: ld [%o1],%g1 // nächstes Digit
3931 // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
3938 add %o1,4,%o1 // Wartetakt!
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
3985 _ st %o4,[%o2] // letzten Carry ablegen
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
3994 1: ld [%i1],%o1 // nächstes source-Digit
3996 call _mulu32_ // mit digit multiplizieren
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
4003 st %o0,[%i2] // Low-Digit ablegen
4007 mov %l0,%i0 // letzter Carry
4014 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
4016 1: ld [%i1],%o1 // nächstes source-Digit
4018 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
4024 and %o1,%l1,%o3 // Wartetakt!
4059 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
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
4067 st %o0,[%i2] // Low-Digit ablegen
4071 mov %l0,%i0 // letzter Carry
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
4082 1: ld [%i1],%o1 // nächstes source-Digit
4084 call _mulu32_ // mit digit multiplizieren
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
4091 st %o1,[%i2] // dest-Digit ablegen
4095 mov %l0,%i0 // letzter Carry
4102 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
4104 1: ld [%i1],%o1 // nächstes source-Digit
4106 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
4112 and %o1,%l1,%o3 // Wartetakt!
4147 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
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
4155 st %o1,[%i2] // dest-Digit ablegen
4159 mov %l0,%i0 // letzter Carry
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
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
4175 st %o0,[%i1-4] // Quotient ablegen, Rest in %g1
4179 2: mov %g1,%i0 // Rest als Ergebnis
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
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
4195 st %o0,[%i2] // Quotient ablegen, Rest in %g1
4199 2: mov %g1,%i0 // Rest als Ergebnis
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
4210 _ sub %g0,%o3,%g1 // 32-i (mod 32)
4212 ld [%o0],%o4 // *xptr holen
4213 1: ld [%o0+%o1],%o5 // *yptr holen
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
4219 srl %o5,%g1,%g2 // höchste i Bits von *yptr
4220 ld [%o0],%o4 // schon mal mit dem nächsten *xptr
4222 _ xor %o4,%g2,%o4 // verknüpfen
4223 st %o4,[%o0] // und ablegen