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 // Some preprocessors keep the backslash in place, some don't.
27 // Some complain about the # being not in front of an ANSI C macro.
28 // Therefore we use a dollar, which will be sed-converted to # later.
29 #define DECLARE_FUNCTION(name) .type C(name),$function
31 #define DECLARE_FUNCTION(name)
34 // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots
35 // (diese werden VOR der vorigen Instruktion ausgeführt):
36 #define _ // Instruktion, die stets ausgeführt wird
37 #define __ // Instruktion, die nur im Sprung-Fall ausgeführt wird
38 // Abkürzungen für Anweisungen:
39 #define ret jmp %i7+8 // return from subroutine
40 #define retl jmp %o7+8 // return from leaf subroutine (no save/restore)
44 .global C(mulu16_),C(mulu32_),C(mulu32_unchecked)
45 .global C(divu_6432_3232_),C(divu_3216_1616_)
46 .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down)
47 .global C(clear_loop_up),C(clear_loop_down)
48 .global C(test_loop_up),C(test_loop_down)
49 .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up)
50 #if CL_DS_BIG_ENDIAN_P
51 .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up)
52 .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up)
53 .global C(not_loop_up)
54 .global C(and_test_loop_up)
55 .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down)
56 .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down)
57 .global C(neg_loop_down)
58 .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down)
59 .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up)
60 .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down)
61 .global C(divu_loop_up),C(divucopy_loop_up)
63 .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down)
64 .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down)
65 .global C(not_loop_down)
66 .global C(and_test_loop_down),C(compare_loop_down)
67 .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up)
68 .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up)
69 .global C(neg_loop_up)
70 .global C(shift1left_loop_up),C(shiftleft_loop_up)
71 .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down)
72 .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up)
73 .global C(divu_loop_down),C(divucopy_loop_down)
76 #define LOOP_TYPE 1 // 1: Standard-Schleifen
77 // 2: Schleifen ohne Pointer, nur mit Zähler
78 // 3: entrollte Schleifen
80 #define STANDARD_LOOPS (LOOP_TYPE==1)
81 #define COUNTER_LOOPS (LOOP_TYPE==2)
82 #define UNROLLED_LOOPS (LOOP_TYPE==3)
83 #define MULU32_INLINE 1 // 1: mulu32-Aufrufe inline in die Schleifen
85 // extern uint32 mulu16_ (uint16 arg1, uint16 arg2);
86 // ergebnis := arg1*arg2.
87 DECLARE_FUNCTION(mulu16_)
88 C(mulu16_:) // Input in %o0,%o1, Output in %o0
95 nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC
113 // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
114 // ergeben das Resultat. (Die anderen Bits sind Null.)
122 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2);
123 // 2^32*hi+lo := arg1*arg2.
124 DECLARE_FUNCTION(mulu32_)
125 C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1
132 sra %o0,31,%o3 // Wartetakt, nötig z.B. für SUN SPARCstation IPC
167 and %o3,%o1,%o3 // %o3 = (0 falls %o0>=0, %o1 falls %o0<0)
168 add %o2,%o3,%g1 // hi
173 // extern uint32 mulu32_unchecked (uint32 x, uint32 y);
174 // ergebnis := arg1*arg2 < 2^32.
175 DECLARE_FUNCTION(mulu32_unchecked)
176 C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0
185 // arg1 < arg2, also kann man arg1 < 2^16 annehmen.
187 nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC
205 // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
206 // ergeben das Resultat. (Die anderen Bits sind Null.)
212 1: // arg1 >= arg2, also kann man arg2 < 2^16 annehmen.
213 nop // Wartetakt, nötig z.B. für SUN SPARCstation IPC
231 // Die 17 unteren Bits von %o2 und die 15 oberen Bits von %y
232 // ergeben das Resultat.
240 // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y);
241 // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y .
242 DECLARE_FUNCTION(divu_6432_3232_)
243 C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1
245 // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
247 nop // wait 1 | Necessary for certain sparcv8
248 nop // wait 2 | processors such as Ross Hypersparc,
249 nop // wait 3 | but not for most of the others.
250 udiv %o1,%o2,%o0 // x durch y dividieren, %o0 := q
251 umul %o0,%o2,%g1 // %g1 := (q*y) mod 2^32
253 _ sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r
255 // %o0 = xhi, %o1 = xlo, %o2 = y
256 // Divisions-Einzelschritte:
257 // %o0|%o1 wird jeweils um 1 Bit nach links geschoben,
258 // dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben.
259 // Je nachdem wird mit %o3|%o1 statt %o0|%o1 weitergemacht (spart 1 'mov').
260 // Deswegen muß man den Code doppelt vorsehen: einmal mit %o0, einmal mit %o3.
261 #define SA0(label) /* Vergleichsschritt mit %o0 */\
265 #define SA1(label) /* Vergleichsschritt mit %o3 */\
269 #define SB0() /* Additionsschritt mit %o0 */\
271 #define SB1() /* Additionsschritt mit %o3 */\
274 addcc %o2,%o2,%g0 // y = %o2 < 2^31 ?
275 bcc Lsmalldiv // ja -> "kleine" Division
276 _ andcc %o2,1,%g0 // y = %o2 gerade ?
277 be Levendiv // ja -> Division durch gerade Zahl
279 // Division durch ungerade Zahl:
280 // floor(x / (2*y'-1)) = floor(floor(x/2) / y') + (0 oder 1 oder 2)
281 // da 0 <= x/(2*y'-1) - x/(2*y') = x/(2*y'-1) / (2*y') = x/y / (2*y')
282 // < 2^32 / (2*y') < 2^32/y <= 2 .
283 add %o2,1,%o2 // %o2 = ceiling(y/2) = y'
284 // Man spart im Vergleich zu Lsmalldiv
285 // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0()
286 // dafür am Schluß mehr zu tun...
287 SA0(Lb01) // Bit 31 des Quotienten bestimmen
288 La01: SB0(); SA0(Lb02) // Bit 30 des Quotienten bestimmen
289 La02: SB0(); SA0(Lb03) // Bit 29 des Quotienten bestimmen
290 La03: SB0(); SA0(Lb04) // Bit 28 des Quotienten bestimmen
291 La04: SB0(); SA0(Lb05) // Bit 27 des Quotienten bestimmen
292 La05: SB0(); SA0(Lb06) // Bit 26 des Quotienten bestimmen
293 La06: SB0(); SA0(Lb07) // Bit 25 des Quotienten bestimmen
294 La07: SB0(); SA0(Lb08) // Bit 24 des Quotienten bestimmen
295 La08: SB0(); SA0(Lb09) // Bit 23 des Quotienten bestimmen
296 La09: SB0(); SA0(Lb10) // Bit 22 des Quotienten bestimmen
297 La10: SB0(); SA0(Lb11) // Bit 21 des Quotienten bestimmen
298 La11: SB0(); SA0(Lb12) // Bit 20 des Quotienten bestimmen
299 La12: SB0(); SA0(Lb13) // Bit 19 des Quotienten bestimmen
300 La13: SB0(); SA0(Lb14) // Bit 18 des Quotienten bestimmen
301 La14: SB0(); SA0(Lb15) // Bit 17 des Quotienten bestimmen
302 La15: SB0(); SA0(Lb16) // Bit 16 des Quotienten bestimmen
303 La16: SB0(); SA0(Lb17) // Bit 15 des Quotienten bestimmen
304 La17: SB0(); SA0(Lb18) // Bit 14 des Quotienten bestimmen
305 La18: SB0(); SA0(Lb19) // Bit 13 des Quotienten bestimmen
306 La19: SB0(); SA0(Lb20) // Bit 12 des Quotienten bestimmen
307 La20: SB0(); SA0(Lb21) // Bit 11 des Quotienten bestimmen
308 La21: SB0(); SA0(Lb22) // Bit 10 des Quotienten bestimmen
309 La22: SB0(); SA0(Lb23) // Bit 9 des Quotienten bestimmen
310 La23: SB0(); SA0(Lb24) // Bit 8 des Quotienten bestimmen
311 La24: SB0(); SA0(Lb25) // Bit 7 des Quotienten bestimmen
312 La25: SB0(); SA0(Lb26) // Bit 6 des Quotienten bestimmen
313 La26: SB0(); SA0(Lb27) // Bit 5 des Quotienten bestimmen
314 La27: SB0(); SA0(Lb28) // Bit 4 des Quotienten bestimmen
315 La28: SB0(); SA0(Lb29) // Bit 3 des Quotienten bestimmen
316 La29: SB0(); SA0(Lb30) // Bit 2 des Quotienten bestimmen
317 La30: SB0(); SA0(Lb31) // Bit 1 des Quotienten bestimmen
318 La31: SB0(); SA0(Lb32) // Bit 0 des Quotienten bestimmen
319 La32: SB0() // %o0 = x mod (2*y')
320 xor %o1,-1,%o1 // %o1 = floor( floor(x/2) / y') = floor(x/(2*y'))
322 sub %o2,1,%o2 // wieder %o2 = 2*y'-1 = y
323 // Quotient und Rest umrechnen:
324 // x = %o1 * 2*y' + %o0 = %o1 * (2*y'-1) + (%o0+%o1)
325 // Also Quotient = %o1, Rest = %o0+%o1.
326 // Noch maximal 2 mal: Quotient += 1, Rest -= y.
327 addcc %o1,%o0,%o0 // Rest mod y bestimmen
328 bcc 1f // Additions-Überlauf -> Quotient erhöhen
330 subcc %o3,%o2,%o0 // muß der Quotient nochmals erhöht werden?
333 // Quotient 2 mal erhöhen, Rest %o0
337 1: // kein Additions-Überlauf.
338 // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden:
339 bcs 3f // %o0 < %o2 -> Rest %o0 und Quotient %o1 OK
341 2: // Quotient %o1 erhöhen, Rest = %o0-%o2 = %o3
344 3: // Quotient %o1 und Rest %o0 OK
348 // Parallelschiene zu La01..La32:
349 Lb01: SB1(); SA1(La02)
350 Lb02: SB1(); SA1(La03)
351 Lb03: SB1(); SA1(La04)
352 Lb04: SB1(); SA1(La05)
353 Lb05: SB1(); SA1(La06)
354 Lb06: SB1(); SA1(La07)
355 Lb07: SB1(); SA1(La08)
356 Lb08: SB1(); SA1(La09)
357 Lb09: SB1(); SA1(La10)
358 Lb10: SB1(); SA1(La11)
359 Lb11: SB1(); SA1(La12)
360 Lb12: SB1(); SA1(La13)
361 Lb13: SB1(); SA1(La14)
362 Lb14: SB1(); SA1(La15)
363 Lb15: SB1(); SA1(La16)
364 Lb16: SB1(); SA1(La17)
365 Lb17: SB1(); SA1(La18)
366 Lb18: SB1(); SA1(La19)
367 Lb19: SB1(); SA1(La20)
368 Lb20: SB1(); SA1(La21)
369 Lb21: SB1(); SA1(La22)
370 Lb22: SB1(); SA1(La23)
371 Lb23: SB1(); SA1(La24)
372 Lb24: SB1(); SA1(La25)
373 Lb25: SB1(); SA1(La26)
374 Lb26: SB1(); SA1(La27)
375 Lb27: SB1(); SA1(La28)
376 Lb28: SB1(); SA1(La29)
377 Lb29: SB1(); SA1(La30)
378 Lb30: SB1(); SA1(La31)
379 Lb31: SB1(); SA1(La32)
380 Lb32: SB1() // %o3 = x mod (2*y')
381 xor %o1,-1,%o1 // %o1 = floor( floor(x/2) / y') = floor(x/(2*y'))
383 sub %o2,1,%o2 // wieder %o2 = 2*y'-1 = y
384 // Quotient und Rest umrechnen:
385 // x = %o1 * 2*y' + %o3 = %o1 * (2*y'-1) + (%o3+%o1)
386 // Also Quotient = %o1, Rest = %o3+%o1.
387 // Noch maximal 2 mal: Quotient += 1, Rest -= y.
388 addcc %o1,%o3,%o3 // Rest mod y bestimmen
389 bcc 1f // Additions-Überlauf -> Quotient erhöhen
391 subcc %o0,%o2,%o3 // muß der Quotient nochmals erhöht werden?
394 // Quotient 2 mal erhöhen, Rest %o3
398 1: // kein Additions-Überlauf.
399 // Wegen y>=2^31 muß der Quotient noch höchstens 1 mal erhöht werden:
400 bcs 3f // %o3 < %o2 -> Rest %o3 und Quotient %o1 OK
402 2: // Quotient %o1 erhöhen, Rest = %o3-%o2 = %o0
405 3: // Quotient %o1 und Rest %o3 OK
409 Lsmalldiv: // Division durch y < 2^31
411 Lc00: SB0(); SA0(Ld01) // Bit 31 des Quotienten bestimmen
412 Lc01: SB0(); SA0(Ld02) // Bit 30 des Quotienten bestimmen
413 Lc02: SB0(); SA0(Ld03) // Bit 29 des Quotienten bestimmen
414 Lc03: SB0(); SA0(Ld04) // Bit 28 des Quotienten bestimmen
415 Lc04: SB0(); SA0(Ld05) // Bit 27 des Quotienten bestimmen
416 Lc05: SB0(); SA0(Ld06) // Bit 26 des Quotienten bestimmen
417 Lc06: SB0(); SA0(Ld07) // Bit 25 des Quotienten bestimmen
418 Lc07: SB0(); SA0(Ld08) // Bit 24 des Quotienten bestimmen
419 Lc08: SB0(); SA0(Ld09) // Bit 23 des Quotienten bestimmen
420 Lc09: SB0(); SA0(Ld10) // Bit 22 des Quotienten bestimmen
421 Lc10: SB0(); SA0(Ld11) // Bit 21 des Quotienten bestimmen
422 Lc11: SB0(); SA0(Ld12) // Bit 20 des Quotienten bestimmen
423 Lc12: SB0(); SA0(Ld13) // Bit 19 des Quotienten bestimmen
424 Lc13: SB0(); SA0(Ld14) // Bit 18 des Quotienten bestimmen
425 Lc14: SB0(); SA0(Ld15) // Bit 17 des Quotienten bestimmen
426 Lc15: SB0(); SA0(Ld16) // Bit 16 des Quotienten bestimmen
427 Lc16: SB0(); SA0(Ld17) // Bit 15 des Quotienten bestimmen
428 Lc17: SB0(); SA0(Ld18) // Bit 14 des Quotienten bestimmen
429 Lc18: SB0(); SA0(Ld19) // Bit 13 des Quotienten bestimmen
430 Lc19: SB0(); SA0(Ld20) // Bit 12 des Quotienten bestimmen
431 Lc20: SB0(); SA0(Ld21) // Bit 11 des Quotienten bestimmen
432 Lc21: SB0(); SA0(Ld22) // Bit 10 des Quotienten bestimmen
433 Lc22: SB0(); SA0(Ld23) // Bit 9 des Quotienten bestimmen
434 Lc23: SB0(); SA0(Ld24) // Bit 8 des Quotienten bestimmen
435 Lc24: SB0(); SA0(Ld25) // Bit 7 des Quotienten bestimmen
436 Lc25: SB0(); SA0(Ld26) // Bit 6 des Quotienten bestimmen
437 Lc26: SB0(); SA0(Ld27) // Bit 5 des Quotienten bestimmen
438 Lc27: SB0(); SA0(Ld28) // Bit 4 des Quotienten bestimmen
439 Lc28: SB0(); SA0(Ld29) // Bit 3 des Quotienten bestimmen
440 Lc29: SB0(); SA0(Ld30) // Bit 2 des Quotienten bestimmen
441 Lc30: SB0(); SA0(Ld31) // Bit 1 des Quotienten bestimmen
442 Lc31: SB0(); SA0(Ld32) // Bit 0 des Quotienten bestimmen
443 Lc32: mov %o0,%g1 // Rest aus %o0 in %g1 abspeichern
445 _ xor %o1,-1,%o0 // Quotient nach %o0
446 // Parallelschiene zu Lc01..Lc32:
447 Ld01: SB1(); SA1(Lc02)
448 Ld02: SB1(); SA1(Lc03)
449 Ld03: SB1(); SA1(Lc04)
450 Ld04: SB1(); SA1(Lc05)
451 Ld05: SB1(); SA1(Lc06)
452 Ld06: SB1(); SA1(Lc07)
453 Ld07: SB1(); SA1(Lc08)
454 Ld08: SB1(); SA1(Lc09)
455 Ld09: SB1(); SA1(Lc10)
456 Ld10: SB1(); SA1(Lc11)
457 Ld11: SB1(); SA1(Lc12)
458 Ld12: SB1(); SA1(Lc13)
459 Ld13: SB1(); SA1(Lc14)
460 Ld14: SB1(); SA1(Lc15)
461 Ld15: SB1(); SA1(Lc16)
462 Ld16: SB1(); SA1(Lc17)
463 Ld17: SB1(); SA1(Lc18)
464 Ld18: SB1(); SA1(Lc19)
465 Ld19: SB1(); SA1(Lc20)
466 Ld20: SB1(); SA1(Lc21)
467 Ld21: SB1(); SA1(Lc22)
468 Ld22: SB1(); SA1(Lc23)
469 Ld23: SB1(); SA1(Lc24)
470 Ld24: SB1(); SA1(Lc25)
471 Ld25: SB1(); SA1(Lc26)
472 Ld26: SB1(); SA1(Lc27)
473 Ld27: SB1(); SA1(Lc28)
474 Ld28: SB1(); SA1(Lc29)
475 Ld29: SB1(); SA1(Lc30)
476 Ld30: SB1(); SA1(Lc31)
477 Ld31: SB1(); SA1(Lc32)
478 Ld32: mov %o3,%g1 // Rest aus %o3 in %g1 abspeichern
480 _ xor %o1,-1,%o0 // Quotient nach %o0
481 Levendiv: // Division durch gerades y.
482 // x/2 durch y/2 dividieren, Quotient OK, Rest evtl. mit 2 multiplizieren.
483 // Es ist schon %o2 = y/2.
484 // Man spart im Vergleich zu Lsmalldiv
485 // zu Beginn eine Verdoppelung von %o0|%o1 : addcc %o1,%o1,%o1; SB0()
486 // dafür am Schluß Bit 0 von x zum Rest dazuschieben.
487 SA0(Lf01) // Bit 31 des Quotienten bestimmen
488 Le01: SB0(); SA0(Lf02) // Bit 30 des Quotienten bestimmen
489 Le02: SB0(); SA0(Lf03) // Bit 29 des Quotienten bestimmen
490 Le03: SB0(); SA0(Lf04) // Bit 28 des Quotienten bestimmen
491 Le04: SB0(); SA0(Lf05) // Bit 27 des Quotienten bestimmen
492 Le05: SB0(); SA0(Lf06) // Bit 26 des Quotienten bestimmen
493 Le06: SB0(); SA0(Lf07) // Bit 25 des Quotienten bestimmen
494 Le07: SB0(); SA0(Lf08) // Bit 24 des Quotienten bestimmen
495 Le08: SB0(); SA0(Lf09) // Bit 23 des Quotienten bestimmen
496 Le09: SB0(); SA0(Lf10) // Bit 22 des Quotienten bestimmen
497 Le10: SB0(); SA0(Lf11) // Bit 21 des Quotienten bestimmen
498 Le11: SB0(); SA0(Lf12) // Bit 20 des Quotienten bestimmen
499 Le12: SB0(); SA0(Lf13) // Bit 19 des Quotienten bestimmen
500 Le13: SB0(); SA0(Lf14) // Bit 18 des Quotienten bestimmen
501 Le14: SB0(); SA0(Lf15) // Bit 17 des Quotienten bestimmen
502 Le15: SB0(); SA0(Lf16) // Bit 16 des Quotienten bestimmen
503 Le16: SB0(); SA0(Lf17) // Bit 15 des Quotienten bestimmen
504 Le17: SB0(); SA0(Lf18) // Bit 14 des Quotienten bestimmen
505 Le18: SB0(); SA0(Lf19) // Bit 13 des Quotienten bestimmen
506 Le19: SB0(); SA0(Lf20) // Bit 12 des Quotienten bestimmen
507 Le20: SB0(); SA0(Lf21) // Bit 11 des Quotienten bestimmen
508 Le21: SB0(); SA0(Lf22) // Bit 10 des Quotienten bestimmen
509 Le22: SB0(); SA0(Lf23) // Bit 9 des Quotienten bestimmen
510 Le23: SB0(); SA0(Lf24) // Bit 8 des Quotienten bestimmen
511 Le24: SB0(); SA0(Lf25) // Bit 7 des Quotienten bestimmen
512 Le25: SB0(); SA0(Lf26) // Bit 6 des Quotienten bestimmen
513 Le26: SB0(); SA0(Lf27) // Bit 5 des Quotienten bestimmen
514 Le27: SB0(); SA0(Lf28) // Bit 4 des Quotienten bestimmen
515 Le28: SB0(); SA0(Lf29) // Bit 3 des Quotienten bestimmen
516 Le29: SB0(); SA0(Lf30) // Bit 2 des Quotienten bestimmen
517 Le30: SB0(); SA0(Lf31) // Bit 1 des Quotienten bestimmen
518 Le31: SB0(); SA0(Lf32) // Bit 0 des Quotienten bestimmen
519 Le32: SB0() // Bit 0 des Restes bestimmen
520 mov %o0,%g1 // Rest aus %o0 in %g1 abspeichern
522 _ xor %o1,-1,%o0 // Quotient nach %o0
523 // Parallelschiene zu Le01..Le32:
524 Lf01: SB1(); SA1(Le02)
525 Lf02: SB1(); SA1(Le03)
526 Lf03: SB1(); SA1(Le04)
527 Lf04: SB1(); SA1(Le05)
528 Lf05: SB1(); SA1(Le06)
529 Lf06: SB1(); SA1(Le07)
530 Lf07: SB1(); SA1(Le08)
531 Lf08: SB1(); SA1(Le09)
532 Lf09: SB1(); SA1(Le10)
533 Lf10: SB1(); SA1(Le11)
534 Lf11: SB1(); SA1(Le12)
535 Lf12: SB1(); SA1(Le13)
536 Lf13: SB1(); SA1(Le14)
537 Lf14: SB1(); SA1(Le15)
538 Lf15: SB1(); SA1(Le16)
539 Lf16: SB1(); SA1(Le17)
540 Lf17: SB1(); SA1(Le18)
541 Lf18: SB1(); SA1(Le19)
542 Lf19: SB1(); SA1(Le20)
543 Lf20: SB1(); SA1(Le21)
544 Lf21: SB1(); SA1(Le22)
545 Lf22: SB1(); SA1(Le23)
546 Lf23: SB1(); SA1(Le24)
547 Lf24: SB1(); SA1(Le25)
548 Lf25: SB1(); SA1(Le26)
549 Lf26: SB1(); SA1(Le27)
550 Lf27: SB1(); SA1(Le28)
551 Lf28: SB1(); SA1(Le29)
552 Lf29: SB1(); SA1(Le30)
553 Lf30: SB1(); SA1(Le31)
554 Lf31: SB1(); SA1(Le32)
556 mov %o3,%g1 // Rest aus %o0 in %g1 abspeichern
558 _ xor %o1,-1,%o0 // Quotient nach %o0
561 // extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y);
562 // x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y .
563 DECLARE_FUNCTION(divu_3216_1616_)
564 C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient).
566 // Problem: Is udiv worth using (gmp-2.0.2 doesn't use it) ??
571 udiv %o0,%o1,%o0 // dividieren, Quotient nach %o0
572 rd %y,%o1 // Rest aus %y
573 sll %o1,16,%o1 // in die oberen 16 Bit schieben
578 // Divisions-Einzelschritte:
579 // %o0 wird jeweils um 1 Bit nach links geschoben,
580 // dafür wird rechts in %o1 ein Ergebnisbit (negiert!) reingeschoben.
581 // Dann wird auf >= 2^15*y verglichen (nicht auf >= 2^16*y, weil man dann das
582 // links herausgeschobene Bit mit vergleichen müßte!)
584 srl %o1,1,%o1 // 2^15*y
585 sub %g0,%o1,%o2 // zum Addieren statt Subtrahieren: -2^15*y
586 // SC0(label) subtrahiert y, schiebt Carry-Bit rechts in %o0 rein
587 // (1 falls Subtraktion aufging, 0 sonst).
588 // Ging die Subtraktion nicht auf, so müßte man noch 2*y addieren.
589 // Das faßt man mit der nächsten Operation zusammen, indem man - statt
590 // y zu subtrahieren - y addiert:
591 // SC1(label) addiert y, schiebt Carry-Bit rechts in %o0 rein
592 // (1 falls Subtraktion aufgegangen wäre, man also wieder im
593 // "positiven Bereich" landet, 0 sonst).
602 SC0(Lh01) // Bit 15 des Quotienten bestimmen
603 Lg01: SC0(Lh02) // Bit 14 des Quotienten bestimmen
604 Lg02: SC0(Lh03) // Bit 13 des Quotienten bestimmen
605 Lg03: SC0(Lh04) // Bit 12 des Quotienten bestimmen
606 Lg04: SC0(Lh05) // Bit 11 des Quotienten bestimmen
607 Lg05: SC0(Lh06) // Bit 10 des Quotienten bestimmen
608 Lg06: SC0(Lh07) // Bit 9 des Quotienten bestimmen
609 Lg07: SC0(Lh08) // Bit 8 des Quotienten bestimmen
610 Lg08: SC0(Lh09) // Bit 7 des Quotienten bestimmen
611 Lg09: SC0(Lh10) // Bit 6 des Quotienten bestimmen
612 Lg10: SC0(Lh11) // Bit 5 des Quotienten bestimmen
613 Lg11: SC0(Lh12) // Bit 4 des Quotienten bestimmen
614 Lg12: SC0(Lh13) // Bit 3 des Quotienten bestimmen
615 Lg13: SC0(Lh14) // Bit 2 des Quotienten bestimmen
616 Lg14: SC0(Lh15) // Bit 1 des Quotienten bestimmen
617 Lg15: SC0(Lh16) // Bit 0 des Quotienten bestimmen
618 Lg16: // Die oberen 16 Bit von %o0 sind der Rest,
619 // die unteren 16 Bit von %o0 sind der Quotient.
622 Lh01: SC1(Lg02) // Bit 14 des Quotienten bestimmen
623 Lh02: SC1(Lg03) // Bit 13 des Quotienten bestimmen
624 Lh03: SC1(Lg04) // Bit 12 des Quotienten bestimmen
625 Lh04: SC1(Lg05) // Bit 11 des Quotienten bestimmen
626 Lh05: SC1(Lg06) // Bit 10 des Quotienten bestimmen
627 Lh06: SC1(Lg07) // Bit 9 des Quotienten bestimmen
628 Lh07: SC1(Lg08) // Bit 8 des Quotienten bestimmen
629 Lh08: SC1(Lg09) // Bit 7 des Quotienten bestimmen
630 Lh09: SC1(Lg10) // Bit 6 des Quotienten bestimmen
631 Lh10: SC1(Lg11) // Bit 5 des Quotienten bestimmen
632 Lh11: SC1(Lg12) // Bit 4 des Quotienten bestimmen
633 Lh12: SC1(Lg13) // Bit 3 des Quotienten bestimmen
634 Lh13: SC1(Lg14) // Bit 2 des Quotienten bestimmen
635 Lh14: SC1(Lg15) // Bit 1 des Quotienten bestimmen
636 Lh15: SC1(Lg16) // Bit 0 des Quotienten bestimmen
637 Lh16: // Noch 2*y addieren:
643 #if !defined(__GNUC__)
645 // extern uint32 _get_g1 (void);
646 DECLARE_FUNCTION(_get_g1)
652 // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
653 DECLARE_FUNCTION(copy_loop_up)
654 C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
669 subcc %g0,%o2,%o2 // %o2 = -count
672 sll %o2,2,%o2 // %o2 = -4*count
673 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
674 sub %o1,%o2,%o1 // %o1 = &destptr[count-1]
675 1: ld [%o0+%o2],%o3 // nächstes Digit holen
676 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
678 _ st %o3,[%o1+%o2] // Digit ablegen
683 // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
684 DECLARE_FUNCTION(copy_loop_down)
685 C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
703 sll %o2,2,%o2 // %o2 = 4*count
704 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
705 sub %o1,%o2,%o1 // %o1 = &destptr[-count]
706 1: ld [%o0+%o2],%o3 // nächstes Digit holen
707 subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
709 _ st %o3,[%o1+%o2] // Digit ablegen
714 // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler);
715 DECLARE_FUNCTION(fill_loop_up)
716 C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
729 subcc %g0,%o1,%o1 // %o1 = -count
732 sll %o1,2,%o1 // %o1 = -4*count
733 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
734 1: addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen
736 _ st %o2,[%o0+%o1] // Digit ablegen
741 // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler);
742 DECLARE_FUNCTION(fill_loop_down)
743 C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
758 _ sll %o1,2,%o1 // %o1 = 4*count
759 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
760 1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
762 _ st %o2,[%o0+%o1] // Digit ablegen
767 // extern uintD* clear_loop_up (uintD* destptr, uintC count);
768 DECLARE_FUNCTION(clear_loop_up)
769 C(clear_loop_up:) // Input in %o0,%o1, Output in %o0
782 subcc %g0,%o1,%o1 // %o1 = -count
785 sll %o1,2,%o1 // %o1 = -4*count
786 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
787 1: addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen
789 _ st %g0,[%o0+%o1] // Digit 0 ablegen
794 // extern uintD* clear_loop_down (uintD* destptr, uintC count);
795 DECLARE_FUNCTION(clear_loop_down)
796 C(clear_loop_down:) // Input in %o0,%o1, Output in %o0
811 _ sll %o1,2,%o1 // %o1 = 4*count
812 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
813 1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
815 _ st %g0,[%o0+%o1] // Digit 0 ablegen
820 // extern boolean test_loop_up (uintD* ptr, uintC count);
821 DECLARE_FUNCTION(test_loop_up)
822 C(test_loop_up:) // Input in %o0,%o1, Output in %o0
840 subcc %g0,%o1,%o1 // %o1 = -count
842 _ sll %o1,2,%o1 // %o1 = -4*count
843 sub %o0,%o1,%o0 // %o0 = &ptr[count]
844 ld [%o0+%o1],%o2 // nächstes Digit holen
845 1: andcc %o2,%o2,%g0 // testen
847 _ addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen
849 __ ld [%o0+%o1],%o2 // nächstes Digit holen
856 // extern boolean test_loop_down (uintD* ptr, uintC count);
857 DECLARE_FUNCTION(test_loop_down)
858 C(test_loop_down:) // Input in %o0,%o1, Output in %o0
876 sll %o1,2,%o1 // %o1 = 4*count
877 sub %o0,%o1,%o0 // %o0 = &ptr[-count]
881 ld [%o0+%o1],%o2 // nächstes Digit holen
882 1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
884 _ andcc %o2,%o2,%g0 // testen
886 __ ld [%o0+%o1],%o2 // nächstes Digit holen
895 #if CL_DS_BIG_ENDIAN_P
897 // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count);
898 DECLARE_FUNCTION(or_loop_up)
899 C(or_loop_up:) // Input in %o0,%o1,%o2
918 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
919 1: ld [%o0],%o3 // *xptr
920 ld [%o0+%o1],%o4 // *yptr
922 or %o3,%o4,%o3 // verknüpfen
923 st %o3,[%o0] // =: *xptr
925 _ add %o0,4,%o0 // xptr++, yptr++
930 subcc %g0,%o2,%o2 // %o2 = -count
933 sll %o2,2,%o2 // %o2 = -4*count
934 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
935 sub %o1,%o2,%o1 // %o1 = &yptr[count]
936 1: ld [%o1+%o2],%o3 // nächstes Digit holen
937 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
938 ld [%o0+%o2],%o4 // noch ein Digit holen
939 or %o4,%o3,%o3 // beide verknüpfen
941 _ st %o3,[%o1+%o2] // Digit ablegen
948 // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count);
949 DECLARE_FUNCTION(xor_loop_up)
950 C(xor_loop_up:) // Input in %o0,%o1,%o2
969 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
970 1: ld [%o0],%o3 // *xptr
971 ld [%o0+%o1],%o4 // *yptr
973 xor %o3,%o4,%o3 // verknüpfen
974 st %o3,[%o0] // =: *xptr
976 _ add %o0,4,%o0 // xptr++, yptr++
981 subcc %g0,%o2,%o2 // %o2 = -count
984 sll %o2,2,%o2 // %o2 = -4*count
985 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
986 sub %o1,%o2,%o1 // %o1 = &yptr[count]
987 1: ld [%o1+%o2],%o3 // nächstes Digit holen
988 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
989 ld [%o0+%o2],%o4 // noch ein Digit holen
990 xor %o4,%o3,%o3 // beide verknüpfen
992 _ st %o3,[%o1+%o2] // Digit ablegen
997 #if CL_DS_BIG_ENDIAN_P
999 // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count);
1000 DECLARE_FUNCTION(and_loop_up)
1001 C(and_loop_up:) // Input in %o0,%o1,%o2
1020 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1021 1: ld [%o0],%o3 // *xptr
1022 ld [%o0+%o1],%o4 // *yptr
1024 and %o3,%o4,%o3 // verknüpfen
1025 st %o3,[%o0] // =: *xptr
1027 _ add %o0,4,%o0 // xptr++, yptr++
1032 subcc %g0,%o2,%o2 // %o2 = -count
1035 sll %o2,2,%o2 // %o2 = -4*count
1036 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
1037 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1038 1: ld [%o1+%o2],%o3 // nächstes Digit holen
1039 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1040 ld [%o0+%o2],%o4 // noch ein Digit holen
1041 and %o4,%o3,%o3 // beide verknüpfen
1043 _ st %o3,[%o1+%o2] // Digit ablegen
1048 // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count);
1049 DECLARE_FUNCTION(eqv_loop_up)
1050 C(eqv_loop_up:) // Input in %o0,%o1,%o2
1069 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1070 1: ld [%o0],%o3 // *xptr
1071 ld [%o0+%o1],%o4 // *yptr
1073 xnor %o3,%o4,%o3 // verknüpfen
1074 st %o3,[%o0] // =: *xptr
1076 _ add %o0,4,%o0 // xptr++, yptr++
1081 subcc %g0,%o2,%o2 // %o2 = -count
1084 sll %o2,2,%o2 // %o2 = -4*count
1085 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
1086 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1087 1: ld [%o1+%o2],%o3 // nächstes Digit holen
1088 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1089 ld [%o0+%o2],%o4 // noch ein Digit holen
1090 xnor %o4,%o3,%o3 // beide verknüpfen
1092 _ st %o3,[%o1+%o2] // Digit ablegen
1097 // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count);
1098 DECLARE_FUNCTION(nand_loop_up)
1099 C(nand_loop_up:) // Input in %o0,%o1,%o2
1119 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1120 1: ld [%o0],%o3 // *xptr
1121 ld [%o0+%o1],%o4 // *yptr
1123 and %o3,%o4,%o3 // verknüpfen
1125 st %o3,[%o0] // =: *xptr
1127 _ add %o0,4,%o0 // xptr++, yptr++
1132 subcc %g0,%o2,%o2 // %o2 = -count
1135 sll %o2,2,%o2 // %o2 = -4*count
1136 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
1137 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1138 1: ld [%o1+%o2],%o3 // nächstes Digit holen
1139 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1140 ld [%o0+%o2],%o4 // noch ein Digit holen
1141 and %o4,%o3,%o3 // beide verknüpfen
1144 _ st %o3,[%o1+%o2] // Digit ablegen
1149 // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count);
1150 DECLARE_FUNCTION(nor_loop_up)
1151 C(nor_loop_up:) // Input in %o0,%o1,%o2
1171 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1172 1: ld [%o0],%o3 // *xptr
1173 ld [%o0+%o1],%o4 // *yptr
1175 or %o3,%o4,%o3 // verknüpfen
1177 st %o3,[%o0] // =: *xptr
1179 _ add %o0,4,%o0 // xptr++, yptr++
1184 subcc %g0,%o2,%o2 // %o2 = -count
1187 sll %o2,2,%o2 // %o2 = -4*count
1188 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
1189 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1190 1: ld [%o1+%o2],%o3 // nächstes Digit holen
1191 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1192 ld [%o0+%o2],%o4 // noch ein Digit holen
1193 or %o4,%o3,%o3 // beide verknüpfen
1196 _ st %o3,[%o1+%o2] // Digit ablegen
1201 // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
1202 DECLARE_FUNCTION(andc2_loop_up)
1203 C(andc2_loop_up:) // Input in %o0,%o1,%o2
1222 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1223 1: ld [%o0],%o3 // *xptr
1224 ld [%o0+%o1],%o4 // *yptr
1226 andn %o3,%o4,%o3 // verknüpfen
1227 st %o3,[%o0] // =: *xptr
1229 _ add %o0,4,%o0 // xptr++, yptr++
1234 subcc %g0,%o2,%o2 // %o2 = -count
1237 sll %o2,2,%o2 // %o2 = -4*count
1238 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
1239 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1240 1: ld [%o1+%o2],%o3 // nächstes Digit holen
1241 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1242 ld [%o0+%o2],%o4 // noch ein Digit holen
1243 andn %o4,%o3,%o3 // beide verknüpfen
1245 _ st %o3,[%o1+%o2] // Digit ablegen
1250 // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count);
1251 DECLARE_FUNCTION(orc2_loop_up)
1252 C(orc2_loop_up:) // Input in %o0,%o1,%o2
1271 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
1272 1: ld [%o0],%o3 // *xptr
1273 ld [%o0+%o1],%o4 // *yptr
1275 orn %o3,%o4,%o3 // verknüpfen
1276 st %o3,[%o0] // =: *xptr
1278 _ add %o0,4,%o0 // xptr++, yptr++
1283 subcc %g0,%o2,%o2 // %o2 = -count
1286 sll %o2,2,%o2 // %o2 = -4*count
1287 sub %o0,%o2,%o0 // %o0 = &xptr[count-1]
1288 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1289 1: ld [%o1+%o2],%o3 // nächstes Digit holen
1290 addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1291 ld [%o0+%o2],%o4 // noch ein Digit holen
1292 orn %o4,%o3,%o3 // beide verknüpfen
1294 _ st %o3,[%o1+%o2] // Digit ablegen
1299 // extern void not_loop_up (uintD* xptr, uintC count);
1300 DECLARE_FUNCTION(not_loop_up)
1301 C(not_loop_up:) // Input in %o0,%o1
1316 subcc %g0,%o1,%o1 // %o1 = -count
1319 sll %o1,2,%o1 // %o1 = -4*count
1320 sub %o0,%o1,%o0 // %o0 = &destptr[count-1]
1321 1: addcc %o1,4,%o1 // Zähler "erniedrigen", Pointer erhöhen
1322 ld [%o0+%o1],%o2 // nächstes Digit holen
1325 _ st %o2,[%o0+%o1] // Digit ablegen
1330 // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count);
1331 DECLARE_FUNCTION(and_test_loop_up)
1332 C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1351 subcc %g0,%o2,%o2 // %o2 = -count
1353 _ sll %o2,2,%o2 // %o2 = -4*count
1354 sub %o0,%o2,%o0 // %o0 = &xptr[count]
1355 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1356 ld [%o0+%o2],%o3 // nächstes Digit holen
1357 1: ld [%o1+%o2],%o4 // noch ein Digit holen
1358 andcc %o3,%o4,%g0 // beide verknüpfen
1360 _ addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1362 __ ld [%o0+%o2],%o3 // nächstes Digit holen
1371 // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count);
1372 DECLARE_FUNCTION(compare_loop_up)
1373 C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
1397 subcc %g0,%o2,%o2 // %o2 = -count
1399 _ sll %o2,2,%o2 // %o2 = -4*count
1400 sub %o0,%o2,%o0 // %o0 = &xptr[count]
1401 sub %o1,%o2,%o1 // %o1 = &yptr[count]
1402 ld [%o0+%o2],%o3 // nächstes Digit holen
1403 1: ld [%o1+%o2],%o4 // noch ein Digit holen
1404 subcc %o3,%o4,%g0 // vergleichen
1406 _ addcc %o2,4,%o2 // Zähler "erniedrigen", Pointer erhöhen
1408 __ ld [%o0+%o2],%o3 // nächstes Digit holen
1411 3: subcc %o3,%o4,%g0 // nochmals vergleichen
1420 #if CL_DS_BIG_ENDIAN_P
1422 // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1423 DECLARE_FUNCTION(add_loop_down)
1424 C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1428 _ mov %g0,%g1 // Carry := 0
1430 1: ld [%o0],%o4 // source1-digit
1432 ld [%o1],%o5 // source2-digit
1433 subcc %g0,%g1,%g0 // carry
1434 addxcc %o4,%o5,%o4 // addieren
1435 addx %g0,%g0,%g1 // neuer Carry
1437 st %o4,[%o2] // Digit ablegen
1447 _ mov %g0,%g1 // Carry := 0
1450 sll %o3,2,%o3 // %o3 = 4*count
1451 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
1452 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
1453 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
1454 1: ld [%o0+%o3],%o4 // source1-digit
1455 ld [%o1+%o3],%o5 // source2-digit
1456 subcc %g0,%g1,%g0 // carry
1457 addxcc %o4,%o5,%o4 // addieren
1458 addx %g0,%g0,%g1 // neuer Carry
1461 _ st %o4,[%o2+%o3] // Digit ablegen
1466 and %o3,7,%o4 // count mod 8
1468 sub %o0,%o5,%o0 // %o0 = &sourceptr1[-(count mod 8)]
1469 sub %o1,%o5,%o1 // %o1 = &sourceptr2[-(count mod 8)]
1470 sub %o2,%o5,%o2 // %o2 = &destptr[-(count mod 8)]
1473 mov %o7,%g2 // save return address
1474 call 0f // put address of label 0 into %o7
1478 set _add_loop_down+176,%o5
1481 jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1482 _ subcc %g0,%g0,%g0 // carry löschen
1483 1: subcc %g0,%g1,%g0 // carry
1484 ld [%o0+28],%o4 // source1-digit
1485 ld [%o1+28],%o5 // source2-digit
1486 addxcc %o5,%o4,%o5 // addieren
1487 st %o5,[%o2+28] // Digit ablegen
1488 ld [%o0+24],%o4 // source1-digit
1489 ld [%o1+24],%o5 // source2-digit
1490 addxcc %o5,%o4,%o5 // addieren
1491 st %o5,[%o2+24] // Digit ablegen
1492 ld [%o0+20],%o4 // source1-digit
1493 ld [%o1+20],%o5 // source2-digit
1494 addxcc %o5,%o4,%o5 // addieren
1495 st %o5,[%o2+20] // Digit ablegen
1496 ld [%o0+16],%o4 // source1-digit
1497 ld [%o1+16],%o5 // source2-digit
1498 addxcc %o5,%o4,%o5 // addieren
1499 st %o5,[%o2+16] // Digit ablegen
1500 ld [%o0+12],%o4 // source1-digit
1501 ld [%o1+12],%o5 // source2-digit
1502 addxcc %o5,%o4,%o5 // addieren
1503 st %o5,[%o2+12] // Digit ablegen
1504 ld [%o0+8],%o4 // source1-digit
1505 ld [%o1+8],%o5 // source2-digit
1506 addxcc %o5,%o4,%o5 // addieren
1507 st %o5,[%o2+8] // Digit ablegen
1508 ld [%o0+4],%o4 // source1-digit
1509 ld [%o1+4],%o5 // source2-digit
1510 addxcc %o5,%o4,%o5 // addieren
1511 st %o5,[%o2+4] // Digit ablegen
1512 ld [%o0],%o4 // source1-digit
1513 ld [%o1],%o5 // source2-digit
1514 addxcc %o5,%o4,%o5 // addieren
1515 st %o5,[%o2] // Digit ablegen
1516 addx %g0,%g0,%g1 // neuer Carry
1519 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
1530 // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
1531 DECLARE_FUNCTION(addto_loop_down)
1532 C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1536 _ mov %g0,%o5 // Carry := 0
1538 1: ld [%o0],%o3 // source-digit
1540 ld [%o1],%o4 // dest-digit
1541 subcc %g0,%o5,%g0 // carry
1542 addxcc %o4,%o3,%o4 // addieren
1543 addx %g0,%g0,%o5 // neuer Carry
1544 st %o4,[%o1] // Digit ablegen
1554 _ mov %g0,%o5 // Carry := 0
1557 sll %o2,2,%o2 // %o2 = 4*count
1558 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
1559 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
1560 ld [%o0+%o2],%o3 // source-digit
1561 1: ld [%o1+%o2],%o4 // dest-digit
1562 subcc %g0,%o5,%g0 // carry
1563 addxcc %o4,%o3,%o4 // addieren
1564 addx %g0,%g0,%o5 // neuer Carry
1565 st %o4,[%o1+%o2] // Digit ablegen
1568 __ ld [%o0+%o2],%o3 // source-digit
1573 and %o2,7,%o3 // count mod 8
1575 sub %o0,%o4,%o0 // %o0 = &sourceptr[-(count mod 8)]
1576 sub %o1,%o4,%o1 // %o1 = &destptr[-(count mod 8)]
1579 mov %o7,%g2 // save return address
1580 call 0f // put address of label 0 into %o7
1584 set _addto_loop_down+172,%o4
1587 jmp %o4 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1588 _ subcc %g0,%g0,%g0 // carry löschen
1589 1: subcc %g0,%o5,%g0 // carry
1590 ld [%o0+28],%o3 // source-digit
1591 ld [%o1+28],%o4 // dest-digit
1592 addxcc %o4,%o3,%o4 // addieren
1593 st %o4,[%o1+28] // Digit ablegen
1594 ld [%o0+24],%o3 // source-digit
1595 ld [%o1+24],%o4 // dest-digit
1596 addxcc %o4,%o3,%o4 // addieren
1597 st %o4,[%o1+24] // Digit ablegen
1598 ld [%o0+20],%o3 // source-digit
1599 ld [%o1+20],%o4 // dest-digit
1600 addxcc %o4,%o3,%o4 // addieren
1601 st %o4,[%o1+20] // Digit ablegen
1602 ld [%o0+16],%o3 // source-digit
1603 ld [%o1+16],%o4 // dest-digit
1604 addxcc %o4,%o3,%o4 // addieren
1605 st %o4,[%o1+16] // Digit ablegen
1606 ld [%o0+12],%o3 // source-digit
1607 ld [%o1+12],%o4 // dest-digit
1608 addxcc %o4,%o3,%o4 // addieren
1609 st %o4,[%o1+12] // Digit ablegen
1610 ld [%o0+8],%o3 // source-digit
1611 ld [%o1+8],%o4 // dest-digit
1612 addxcc %o4,%o3,%o4 // addieren
1613 st %o4,[%o1+8] // Digit ablegen
1614 ld [%o0+4],%o3 // source-digit
1615 ld [%o1+4],%o4 // dest-digit
1616 addxcc %o4,%o3,%o4 // addieren
1617 st %o4,[%o1+4] // Digit ablegen
1618 ld [%o0],%o3 // source-digit
1619 ld [%o1],%o4 // dest-digit
1620 addxcc %o4,%o3,%o4 // addieren
1621 st %o4,[%o1] // Digit ablegen
1622 addx %g0,%g0,%o5 // neuer Carry
1624 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
1635 // extern uintD inc_loop_down (uintD* ptr, uintC count);
1636 DECLARE_FUNCTION(inc_loop_down)
1637 C(inc_loop_down:) // Input in %o0,%o1, Output in %o0
1658 sll %o1,2,%o1 // %o1 = 4*count
1659 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
1660 ld [%o0+%o1],%o2 // digit holen
1661 1: addcc %o2,1,%o2 // incrementieren
1663 _ st %o2,[%o0+%o1] // ablegen
1664 subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
1673 // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
1674 DECLARE_FUNCTION(sub_loop_down)
1675 C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
1679 _ mov %g0,%g1 // Carry := 0
1681 1: ld [%o0],%o4 // source1-digit
1683 ld [%o1],%o5 // source2-digit
1684 subcc %g0,%g1,%g0 // carry
1685 subxcc %o4,%o5,%o4 // subtrahieren
1686 addx %g0,%g0,%g1 // neuer Carry
1688 st %o4,[%o2] // Digit ablegen
1698 _ mov %g0,%g1 // Carry := 0
1701 sll %o3,2,%o3 // %o3 = 4*count
1702 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
1703 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
1704 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
1705 1: ld [%o0+%o3],%o4 // source1-digit
1706 ld [%o1+%o3],%o5 // source2-digit
1707 subcc %g0,%g1,%g0 // carry
1708 subxcc %o4,%o5,%o4 // subtrahieren
1709 addx %g0,%g0,%g1 // neuer Carry
1712 _ st %o4,[%o2+%o3] // Digit ablegen
1717 and %o3,7,%o4 // count mod 8
1719 sub %o0,%o5,%o0 // %o0 = &sourceptr1[-(count mod 8)]
1720 sub %o1,%o5,%o1 // %o1 = &sourceptr2[-(count mod 8)]
1721 sub %o2,%o5,%o2 // %o2 = &destptr[-(count mod 8)]
1724 mov %o7,%g2 // save return address
1725 call 0f // put address of label 0 into %o7
1729 set _sub_loop_down+176,%o5
1732 jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1733 _ subcc %g0,%g0,%g0 // carry löschen
1734 1: subcc %g0,%g1,%g0 // carry
1735 ld [%o0+28],%o4 // source1-digit
1736 ld [%o1+28],%o5 // source2-digit
1737 subxcc %o4,%o5,%o4 // subtrahieren
1738 st %o4,[%o2+28] // Digit ablegen
1739 ld [%o0+24],%o4 // source1-digit
1740 ld [%o1+24],%o5 // source2-digit
1741 subxcc %o4,%o5,%o4 // subtrahieren
1742 st %o4,[%o2+24] // Digit ablegen
1743 ld [%o0+20],%o4 // source1-digit
1744 ld [%o1+20],%o5 // source2-digit
1745 subxcc %o4,%o5,%o4 // subtrahieren
1746 st %o4,[%o2+20] // Digit ablegen
1747 ld [%o0+16],%o4 // source1-digit
1748 ld [%o1+16],%o5 // source2-digit
1749 subxcc %o4,%o5,%o4 // subtrahieren
1750 st %o4,[%o2+16] // Digit ablegen
1751 ld [%o0+12],%o4 // source1-digit
1752 ld [%o1+12],%o5 // source2-digit
1753 subxcc %o4,%o5,%o4 // subtrahieren
1754 st %o4,[%o2+12] // Digit ablegen
1755 ld [%o0+8],%o4 // source1-digit
1756 ld [%o1+8],%o5 // source2-digit
1757 subxcc %o4,%o5,%o4 // subtrahieren
1758 st %o4,[%o2+8] // Digit ablegen
1759 ld [%o0+4],%o4 // source1-digit
1760 ld [%o1+4],%o5 // source2-digit
1761 subxcc %o4,%o5,%o4 // subtrahieren
1762 st %o4,[%o2+4] // Digit ablegen
1763 ld [%o0],%o4 // source1-digit
1764 ld [%o1],%o5 // source2-digit
1765 subxcc %o4,%o5,%o4 // subtrahieren
1766 st %o4,[%o2] // Digit ablegen
1767 addx %g0,%g0,%g1 // neuer Carry
1770 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
1781 // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
1782 DECLARE_FUNCTION(subx_loop_down)
1783 C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
1787 _ mov %o4,%g1 // Carry
1789 1: ld [%o0],%o4 // source1-digit
1791 ld [%o1],%o5 // source2-digit
1792 subcc %g0,%g1,%g0 // carry
1793 subxcc %o4,%o5,%o4 // subtrahieren
1794 addx %g0,%g0,%g1 // neuer Carry
1796 st %o4,[%o2] // Digit ablegen
1806 _ mov %o4,%g1 // Carry
1809 sll %o3,2,%o3 // %o3 = 4*count
1810 sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1]
1811 sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1]
1812 sub %o2,%o3,%o2 // %o2 = &destptr[-count]
1813 1: ld [%o0+%o3],%o4 // source1-digit
1814 ld [%o1+%o3],%o5 // source2-digit
1815 subcc %g0,%g1,%g0 // carry
1816 subxcc %o4,%o5,%o4 // subtrahieren
1817 addx %g0,%g0,%g1 // neuer Carry
1820 _ st %o4,[%o2+%o3] // Digit ablegen
1825 and %o3,7,%o5 // count mod 8
1827 sub %o0,%g1,%o0 // %o0 = &sourceptr1[-(count mod 8)]
1828 sub %o1,%g1,%o1 // %o1 = &sourceptr2[-(count mod 8)]
1829 sub %o2,%g1,%o2 // %o2 = &destptr[-(count mod 8)]
1832 mov %o7,%g2 // save return address
1833 call 0f // put address of label 0 into %o7
1837 set _subx_loop_down+176,%g1
1840 jmp %g1 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1841 _ subcc %g0,%o4,%g0 // carry initialisieren
1842 1: subcc %g0,%g1,%g0 // carry
1843 ld [%o0+28],%o4 // source1-digit
1844 ld [%o1+28],%o5 // source2-digit
1845 subxcc %o4,%o5,%o4 // subtrahieren
1846 st %o4,[%o2+28] // Digit ablegen
1847 ld [%o0+24],%o4 // source1-digit
1848 ld [%o1+24],%o5 // source2-digit
1849 subxcc %o4,%o5,%o4 // subtrahieren
1850 st %o4,[%o2+24] // Digit ablegen
1851 ld [%o0+20],%o4 // source1-digit
1852 ld [%o1+20],%o5 // source2-digit
1853 subxcc %o4,%o5,%o4 // subtrahieren
1854 st %o4,[%o2+20] // Digit ablegen
1855 ld [%o0+16],%o4 // source1-digit
1856 ld [%o1+16],%o5 // source2-digit
1857 subxcc %o4,%o5,%o4 // subtrahieren
1858 st %o4,[%o2+16] // Digit ablegen
1859 ld [%o0+12],%o4 // source1-digit
1860 ld [%o1+12],%o5 // source2-digit
1861 subxcc %o4,%o5,%o4 // subtrahieren
1862 st %o4,[%o2+12] // Digit ablegen
1863 ld [%o0+8],%o4 // source1-digit
1864 ld [%o1+8],%o5 // source2-digit
1865 subxcc %o4,%o5,%o4 // subtrahieren
1866 st %o4,[%o2+8] // Digit ablegen
1867 ld [%o0+4],%o4 // source1-digit
1868 ld [%o1+4],%o5 // source2-digit
1869 subxcc %o4,%o5,%o4 // subtrahieren
1870 st %o4,[%o2+4] // Digit ablegen
1871 ld [%o0],%o4 // source1-digit
1872 ld [%o1],%o5 // source2-digit
1873 subxcc %o4,%o5,%o4 // subtrahieren
1874 st %o4,[%o2] // Digit ablegen
1875 addx %g0,%g0,%g1 // neuer Carry
1878 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
1889 // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count);
1890 DECLARE_FUNCTION(subfrom_loop_down)
1891 C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
1895 _ mov %g0,%o5 // Carry := 0
1897 1: ld [%o0],%o3 // source-digit
1899 ld [%o1],%o4 // dest-digit
1900 subcc %g0,%o5,%g0 // carry
1901 subxcc %o4,%o3,%o4 // subtrahieren
1902 addx %g0,%g0,%o5 // neuer Carry
1903 st %o4,[%o1] // Digit ablegen
1913 _ mov %g0,%o5 // Carry := 0
1916 sll %o2,2,%o2 // %o2 = 4*count
1917 sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1]
1918 sub %o1,%o2,%o1 // %o1 = &destptr[-count-1]
1919 ld [%o0+%o2],%o3 // source-digit
1920 1: ld [%o1+%o2],%o4 // dest-digit
1921 subcc %g0,%o5,%g0 // carry
1922 subxcc %o4,%o3,%o4 // subtrahieren
1923 addx %g0,%g0,%o5 // neuer Carry
1924 st %o4,[%o1+%o2] // Digit ablegen
1927 __ ld [%o0+%o2],%o3 // source-digit
1932 and %o2,7,%o3 // count mod 8
1934 sub %o0,%o4,%o0 // %o0 = &sourceptr[-(count mod 8)]
1935 sub %o1,%o4,%o1 // %o1 = &destptr[-(count mod 8)]
1938 mov %o7,%g2 // save return address
1939 call 0f // put address of label 0 into %o7
1943 set _subfrom_loop_down+172,%o4
1946 jmp %o4 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
1947 _ subcc %g0,%g0,%g0 // carry löschen
1948 1: subcc %g0,%o5,%g0 // carry
1949 ld [%o0+28],%o3 // source-digit
1950 ld [%o1+28],%o4 // dest-digit
1951 subxcc %o4,%o3,%o4 // subtrahieren
1952 st %o4,[%o1+28] // Digit ablegen
1953 ld [%o0+24],%o3 // source-digit
1954 ld [%o1+24],%o4 // dest-digit
1955 subxcc %o4,%o3,%o4 // subtrahieren
1956 st %o4,[%o1+24] // Digit ablegen
1957 ld [%o0+20],%o3 // source-digit
1958 ld [%o1+20],%o4 // dest-digit
1959 subxcc %o4,%o3,%o4 // subtrahieren
1960 st %o4,[%o1+20] // Digit ablegen
1961 ld [%o0+16],%o3 // source-digit
1962 ld [%o1+16],%o4 // dest-digit
1963 subxcc %o4,%o3,%o4 // subtrahieren
1964 st %o4,[%o1+16] // Digit ablegen
1965 ld [%o0+12],%o3 // source-digit
1966 ld [%o1+12],%o4 // dest-digit
1967 subxcc %o4,%o3,%o4 // subtrahieren
1968 st %o4,[%o1+12] // Digit ablegen
1969 ld [%o0+8],%o3 // source-digit
1970 ld [%o1+8],%o4 // dest-digit
1971 subxcc %o4,%o3,%o4 // subtrahieren
1972 st %o4,[%o1+8] // Digit ablegen
1973 ld [%o0+4],%o3 // source-digit
1974 ld [%o1+4],%o4 // dest-digit
1975 subxcc %o4,%o3,%o4 // subtrahieren
1976 st %o4,[%o1+4] // Digit ablegen
1977 ld [%o0],%o3 // source-digit
1978 ld [%o1],%o4 // dest-digit
1979 subxcc %o4,%o3,%o4 // subtrahieren
1980 st %o4,[%o1] // Digit ablegen
1981 addx %g0,%g0,%o5 // neuer Carry
1983 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
1994 // extern uintD dec_loop_down (uintD* ptr, uintC count);
1995 DECLARE_FUNCTION(dec_loop_down)
1996 C(dec_loop_down:) // Input in %o0,%o1, Output in %o0
2017 sll %o1,2,%o1 // %o1 = 4*count
2018 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
2019 ld [%o0+%o1],%o2 // digit holen
2020 1: subcc %o2,1,%o2 // decrementieren
2022 _ st %o2,[%o0+%o1] // ablegen
2023 subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
2032 // extern uintD neg_loop_down (uintD* ptr, uintC count);
2033 DECLARE_FUNCTION(neg_loop_down)
2034 C(neg_loop_down:) // Input in %o0,%o1, Output in %o0
2036 // erstes Digit /=0 suchen:
2048 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2049 st %o2,[%o0] // 1 Digit negieren
2050 // alle anderen Digits invertieren:
2063 // erstes Digit /=0 suchen:
2067 sll %o1,2,%o1 // %o1 = 4*count
2068 sub %o0,%o1,%o0 // %o0 = &ptr[-count-1]
2069 ld [%o0+%o1],%o2 // digit holen
2070 1: subcc %g0,%o2,%o2 // negieren, testen
2072 _ subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
2077 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
2078 // alle anderen Digits invertieren:
2080 st %o2,[%o0+%o1] // ablegen
2094 // extern uintD shift1left_loop_down (uintD* ptr, uintC count);
2095 DECLARE_FUNCTION(shift1left_loop_down)
2096 C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0
2099 _ mov 0,%o3 // Carry := 0
2101 1: ld [%o0],%o2 // Digit
2102 subcc %g0,%o3,%g0 // carry
2103 addxcc %o2,%o2,%o2 // shiften
2104 addx %g0,%g0,%o3 // neues Carry
2105 st %o2,[%o0] // Digit ablegen
2112 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry);
2113 DECLARE_FUNCTION(shiftleft_loop_down)
2114 C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
2117 _ sub %g0,%o2,%g1 // 32-i (mod 32)
2119 1: ld [%o0],%o4 // Digit
2121 sll %o4,%o2,%o5 // dessen niedere (32-i) Bits
2122 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
2123 st %o5,[%o0] // Digit ablegen
2124 srl %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
2130 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
2131 DECLARE_FUNCTION(shiftleftcopy_loop_down)
2132 C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
2135 _ mov 0,%o4 // Carry := 0
2136 sub %g0,%o3,%g1 // 32-i (mod 32)
2138 1: ld [%o0],%o5 // Digit
2140 sll %o5,%o3,%g2 // dessen niedere (32-i) Bits
2141 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
2143 st %g2,[%o1] // Digit ablegen
2144 srl %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
2150 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry);
2151 DECLARE_FUNCTION(shift1right_loop_up)
2152 C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
2155 _ sll %o2,31,%o2 // Carry
2156 1: ld [%o0],%o3 // Digit
2158 srl %o3,1,%o4 // shiften
2159 or %o2,%o4,%o4 // und mit altem Carry kombinieren
2160 st %o4,[%o0] // und ablegen
2161 sll %o3,31,%o2 // neuer Carry
2167 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i);
2168 DECLARE_FUNCTION(shiftright_loop_up)
2169 C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2170 sub %g0,%o2,%g1 // 32-i (mod 32)
2173 _ or %g0,%g0,%o3 // Carry := 0
2174 1: ld [%o0],%o4 // Digit
2176 srl %o4,%o2,%o5 // shiften
2177 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2178 st %o5,[%o0] // und ablegen
2179 sll %o4,%g1,%o3 // neuer Carry
2185 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i);
2186 DECLARE_FUNCTION(shiftrightsigned_loop_up)
2187 C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
2188 ld [%o0],%o4 // erstes Digit
2189 sub %g0,%o2,%g1 // 32-i (mod 32)
2190 sra %o4,%o2,%o5 // shiften
2191 st %o5,[%o0] // und ablegen
2192 sll %o4,%g1,%o3 // neuer Carry
2196 1: ld [%o0],%o4 // Digit
2198 srl %o4,%o2,%o5 // shiften
2199 or %o3,%o5,%o5 // und mit altem Carry kombinieren
2200 st %o5,[%o0] // und ablegen
2201 sll %o4,%g1,%o3 // neuer Carry
2207 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
2208 DECLARE_FUNCTION(shiftrightcopy_loop_up)
2209 C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
2210 sub %g0,%o3,%g1 // 32-i (mod 32)
2213 _ sll %o4,%g1,%g2 // erster Carry
2214 1: ld [%o0],%o4 // Digit
2216 srl %o4,%o3,%o5 // shiften
2217 or %g2,%o5,%o5 // und mit altem Carry kombinieren
2218 st %o5,[%o1] // und ablegen
2219 sll %o4,%g1,%g2 // neuer Carry
2226 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit);
2227 DECLARE_FUNCTION(mulusmall_loop_down)
2228 C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0
2232 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
2233 // und kleinen Carry %o3 dazu:
2235 ld [%o1],%o4 // Wartetakt!
2244 // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y
2245 // ergeben das Resultat. (Die anderen Bits sind Null.)
2246 tst %o4 // Korrektur, falls %o4 negativ war
2248 _ sra %o5,26,%o3 // 6 obere Bits von %o5 -> neuer Carry
2249 add %o3,%o0,%o3 // (falls %o4 negativ war, noch + %o0)
2251 srl %o4,26,%o4 // 6 obere Bits von %y
2252 sll %o5,6,%o5 // 26 untere Bits von %o5
2253 or %o5,%o4,%o4 // neues Digit
2254 st %o4,[%o1] // ablegen
2261 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2263 DECLARE_FUNCTION(mulu_loop_down)
2264 C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3
2268 ld [%i1],%o1 // nächstes Digit
2269 call _mulu32_ // mit digit multiplizieren
2271 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
2272 addx %g0,%g1,%l0 // High-Digit gibt neuen Carry
2276 _ st %o0,[%i2] // Low-Digit ablegen
2277 st %l0,[%i2-4] // letzten Carry ablegen
2281 DECLARE_FUNCTION(mulu_loop_down)
2282 C(mulu_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1
2284 1: ld [%o1-4],%g1 // nächstes Digit
2285 // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
2292 sub %o1,4,%o1 // Wartetakt!
2332 addcc %o4,%g1,%g1 // und bisherigen Carry addieren
2333 addx %g0,%o5,%o4 // High-Digit gibt neuen Carry
2337 _ st %g1,[%o2] // Low-Digit ablegen
2339 _ st %o4,[%o2-4] // letzten Carry ablegen
2342 // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2343 DECLARE_FUNCTION(muluadd_loop_down)
2344 C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2349 ld [%i1],%o1 // nächstes source-Digit
2350 call _mulu32_ // mit digit multiplizieren
2353 ld [%i2],%o1 // nächstes dest-digit
2354 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
2355 addx %g0,%g1,%l0 // High-Digit gibt neuen Carry
2356 addcc %o1,%o0,%o0 // addieren
2360 _ st %o0,[%i2] // Low-Digit ablegen
2361 mov %l0,%i0 // letzter Carry
2368 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
2370 1: ld [%i1-4],%o1 // nächstes source-Digit
2372 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
2378 and %o1,%l1,%o3 // Wartetakt!
2413 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
2417 ld [%i2],%o1 // nächstes dest-digit
2418 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
2419 addx %g0,%o2,%l0 // High-Digit gibt neuen Carry
2420 addcc %o1,%o0,%o0 // addieren
2424 _ st %o0,[%i2] // Low-Digit ablegen
2425 mov %l0,%i0 // letzter Carry
2430 // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2431 DECLARE_FUNCTION(mulusub_loop_down)
2432 C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2437 ld [%i1],%o1 // nächstes source-Digit
2438 call _mulu32_ // mit digit multiplizieren
2441 ld [%i2],%o1 // nächstes dest-digit
2442 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
2443 addx %g0,%g1,%l0 // High-Digit gibt neuen Carry
2444 subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren
2448 _ st %o1,[%i2] // dest-Digit ablegen
2449 mov %l0,%i0 // letzter Carry
2456 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
2458 1: ld [%i1-4],%o1 // nächstes source-Digit
2460 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
2466 and %o1,%l1,%o3 // Wartetakt!
2501 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
2505 ld [%i2],%o1 // nächstes dest-digit
2506 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
2507 addx %g0,%o2,%l0 // High-Digit gibt neuen Carry
2508 subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren
2512 _ st %o1,[%i2] // dest-Digit ablegen
2513 mov %l0,%i0 // letzter Carry
2518 // extern uintD divu_loop_up (uintD digit, uintD* ptr, uintC len);
2519 DECLARE_FUNCTION(divu_loop_up)
2520 C(divu_loop_up:) // Input in %i0,%i1,%i2, Output in %i0
2525 1: mov %g1,%o0 // Rest als High-Digit
2526 ld [%i1],%o1 // nächstes Digit als Low-Digit
2527 call C(divu_6432_3232_) // zusammen durch digit dividieren
2529 st %o0,[%i1] // Quotient ablegen, Rest in %g1
2533 2: mov %g1,%i0 // Rest als Ergebnis
2537 // extern uintD divucopy_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
2538 DECLARE_FUNCTION(divucopy_loop_up)
2539 C(divucopy_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
2544 1: mov %g1,%o0 // Rest als High-Digit
2545 ld [%i1],%o1 // nächstes Digit als Low-Digit
2546 call C(divu_6432_3232_) // zusammen durch digit dividieren
2548 st %o0,[%i2] // Quotient ablegen, Rest in %g1
2553 2: mov %g1,%i0 // Rest als Ergebnis
2559 #if !CL_DS_BIG_ENDIAN_P
2561 // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count);
2562 DECLARE_FUNCTION(or_loop_down)
2563 C(or_loop_down:) // Input in %o0,%o1,%o2
2582 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2584 1: ld [%o0],%o3 // *xptr
2585 ld [%o0+%o1],%o4 // *yptr
2587 or %o3,%o4,%o3 // verknüpfen
2588 st %o3,[%o0] // =: *xptr
2590 _ sub %o0,4,%o0 // xptr++, yptr++
2597 _ sll %o2,2,%o2 // %o2 = 4*count
2598 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2599 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2600 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2601 ld [%o1+%o2],%o3 // nächstes Digit holen
2602 ld [%o0+%o2],%o4 // noch ein Digit holen
2603 or %o4,%o3,%o3 // beide verknüpfen
2605 _ st %o3,[%o1+%o2] // Digit ablegen
2610 // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count);
2611 DECLARE_FUNCTION(xor_loop_down)
2612 C(xor_loop_down:) // Input in %o0,%o1,%o2
2631 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2633 1: ld [%o0],%o3 // *xptr
2634 ld [%o0+%o1],%o4 // *yptr
2636 xor %o3,%o4,%o3 // verknüpfen
2637 st %o3,[%o0] // =: *xptr
2639 _ sub %o0,4,%o0 // xptr++, yptr++
2646 _ sll %o2,2,%o2 // %o2 = 4*count
2647 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2648 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2649 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2650 ld [%o1+%o2],%o3 // nächstes Digit holen
2651 ld [%o0+%o2],%o4 // noch ein Digit holen
2652 xor %o4,%o3,%o3 // beide verknüpfen
2654 _ st %o3,[%o1+%o2] // Digit ablegen
2659 // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count);
2660 DECLARE_FUNCTION(and_loop_down)
2661 C(and_loop_down:) // Input in %o0,%o1,%o2
2680 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2682 1: ld [%o0],%o3 // *xptr
2683 ld [%o0+%o1],%o4 // *yptr
2685 and %o3,%o4,%o3 // verknüpfen
2686 st %o3,[%o0] // =: *xptr
2688 _ sub %o0,4,%o0 // xptr++, yptr++
2695 _ sll %o2,2,%o2 // %o2 = 4*count
2696 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2697 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2698 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2699 ld [%o1+%o2],%o3 // nächstes Digit holen
2700 ld [%o0+%o2],%o4 // noch ein Digit holen
2701 and %o4,%o3,%o3 // beide verknüpfen
2703 _ st %o3,[%o1+%o2] // Digit ablegen
2708 // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count);
2709 DECLARE_FUNCTION(eqv_loop_down)
2710 C(eqv_loop_down:) // Input in %o0,%o1,%o2
2729 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2731 1: ld [%o0],%o3 // *xptr
2732 ld [%o0+%o1],%o4 // *yptr
2734 xnor %o3,%o4,%o3 // verknüpfen
2735 st %o3,[%o0] // =: *xptr
2737 _ sub %o0,4,%o0 // xptr++, yptr++
2744 _ sll %o2,2,%o2 // %o2 = 4*count
2745 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2746 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2747 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2748 ld [%o1+%o2],%o3 // nächstes Digit holen
2749 ld [%o0+%o2],%o4 // noch ein Digit holen
2750 xnor %o4,%o3,%o3 // beide verknüpfen
2752 _ st %o3,[%o1+%o2] // Digit ablegen
2757 // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count);
2758 DECLARE_FUNCTION(nand_loop_down)
2759 C(nand_loop_down:) // Input in %o0,%o1,%o2
2779 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2781 1: ld [%o0],%o3 // *xptr
2782 ld [%o0+%o1],%o4 // *yptr
2784 and %o3,%o4,%o3 // verknüpfen
2786 st %o3,[%o0] // =: *xptr
2788 _ sub %o0,4,%o0 // xptr++, yptr++
2795 _ sll %o2,2,%o2 // %o2 = 4*count
2796 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2797 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2798 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2799 ld [%o1+%o2],%o3 // nächstes Digit holen
2800 ld [%o0+%o2],%o4 // noch ein Digit holen
2801 and %o4,%o3,%o3 // beide verknüpfen
2804 _ st %o3,[%o1+%o2] // Digit ablegen
2809 // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count);
2810 DECLARE_FUNCTION(nor_loop_down)
2811 C(nor_loop_down:) // Input in %o0,%o1,%o2
2831 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2833 1: ld [%o0],%o3 // *xptr
2834 ld [%o0+%o1],%o4 // *yptr
2836 or %o3,%o4,%o3 // verknüpfen
2838 st %o3,[%o0] // =: *xptr
2840 _ sub %o0,4,%o0 // xptr++, yptr++
2847 _ sll %o2,2,%o2 // %o2 = 4*count
2848 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2849 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2850 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2851 ld [%o1+%o2],%o3 // nächstes Digit holen
2852 ld [%o0+%o2],%o4 // noch ein Digit holen
2853 or %o4,%o3,%o3 // beide verknüpfen
2856 _ st %o3,[%o1+%o2] // Digit ablegen
2861 // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
2862 DECLARE_FUNCTION(andc2_loop_down)
2863 C(andc2_loop_down:) // Input in %o0,%o1,%o2
2882 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2884 1: ld [%o0],%o3 // *xptr
2885 ld [%o0+%o1],%o4 // *yptr
2887 andn %o3,%o4,%o3 // verknüpfen
2888 st %o3,[%o0] // =: *xptr
2890 _ sub %o0,4,%o0 // xptr++, yptr++
2897 _ sll %o2,2,%o2 // %o2 = 4*count
2898 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2899 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2900 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2901 ld [%o1+%o2],%o3 // nächstes Digit holen
2902 ld [%o0+%o2],%o4 // noch ein Digit holen
2903 andn %o4,%o3,%o3 // beide verknüpfen
2905 _ st %o3,[%o1+%o2] // Digit ablegen
2910 // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count);
2911 DECLARE_FUNCTION(orc2_loop_down)
2912 C(orc2_loop_down:) // Input in %o0,%o1,%o2
2931 _ sub %o1,%o0,%o1 // %o1 = yptr-xptr
2933 1: ld [%o0],%o3 // *xptr
2934 ld [%o0+%o1],%o4 // *yptr
2936 orn %o3,%o4,%o3 // verknüpfen
2937 st %o3,[%o0] // =: *xptr
2939 _ sub %o0,4,%o0 // xptr++, yptr++
2946 _ sll %o2,2,%o2 // %o2 = 4*count
2947 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
2948 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
2949 1: subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
2950 ld [%o1+%o2],%o3 // nächstes Digit holen
2951 ld [%o0+%o2],%o4 // noch ein Digit holen
2952 orn %o4,%o3,%o3 // beide verknüpfen
2954 _ st %o3,[%o1+%o2] // Digit ablegen
2959 // extern void not_loop_down (uintD* xptr, uintC count);
2960 DECLARE_FUNCTION(not_loop_down)
2961 C(not_loop_down:) // Input in %o0,%o1
2978 _ sll %o1,2,%o1 // %o1 = 4*count
2979 sub %o0,%o1,%o0 // %o0 = &destptr[-count]
2980 1: subcc %o1,4,%o1 // Zähler erniedrigen, Pointer erniedrigen
2981 ld [%o0+%o1],%o2 // nächstes Digit holen
2984 _ st %o2,[%o0+%o1] // Digit ablegen
2989 // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count);
2990 DECLARE_FUNCTION(and_test_loop_down)
2991 C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
3012 sll %o2,2,%o2 // %o2 = 4*count
3013 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
3014 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
3018 ld [%o0+%o2],%o3 // nächstes Digit holen
3019 1: ld [%o1+%o2],%o4 // noch ein Digit holen
3020 andcc %o3,%o4,%g0 // beide verknüpfen
3022 _ subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
3024 __ ld [%o0+%o2],%o3 // nächstes Digit holen
3031 // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count);
3032 DECLARE_FUNCTION(compare_loop_down)
3033 C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
3056 sll %o2,2,%o2 // %o2 = 4*count
3057 sub %o0,%o2,%o0 // %o0 = &xptr[-count]
3058 sub %o1,%o2,%o1 // %o1 = &yptr[-count]
3062 ld [%o0+%o2],%o3 // nächstes Digit holen
3063 1: ld [%o1+%o2],%o4 // noch ein Digit holen
3064 subcc %o2,4,%o2 // Zähler erniedrigen, Pointer erniedrigen
3066 _ subcc %o3,%o4,%g0 // vergleichen
3068 __ ld [%o0+%o2],%o3 // nächstes Digit holen
3081 // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
3082 DECLARE_FUNCTION(add_loop_up)
3083 C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
3087 _ subcc %g0,%g0,%g0 // Carry := 0
3088 1: ld [%o0],%o4 // source1-digit
3090 ld [%o1],%o5 // source2-digit
3092 addxcc %o4,%o5,%o4 // addieren
3093 addx %g0,%g0,%g1 // neuer Carry
3094 st %o4,[%o2] // Digit ablegen
3098 _ subcc %g0,%g1,%g0 // carry
3103 subcc %g0,%o3,%o3 // %o3 = -count
3105 _ mov %g0,%g1 // Carry := 0
3106 sll %o3,2,%o3 // %o3 = -4*count
3108 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
3109 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
3110 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
3111 1: ld [%o0+%o3],%o4 // source1-digit
3112 ld [%o1+%o3],%o5 // source2-digit
3113 subcc %g0,%g1,%g0 // carry
3114 addxcc %o4,%o5,%o4 // addieren
3115 addx %g0,%g0,%g1 // neuer Carry
3116 addcc %o3,4,%o3 // Zähler erniedrigen, Pointer erhöhen
3118 _ st %o4,[%o2+%o3] // Digit ablegen
3123 and %o3,7,%o4 // count mod 8
3125 add %o0,%o5,%o0 // %o0 = &sourceptr1[count mod 8]
3126 add %o1,%o5,%o1 // %o1 = &sourceptr2[count mod 8]
3127 add %o2,%o5,%o2 // %o2 = &destptr[count mod 8]
3130 mov %o7,%g2 // save return address
3131 call 0f // put address of label 0 into %o7
3135 set _add_loop_up+176,%o5
3138 jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
3139 _ subcc %g0,%g0,%g0 // carry löschen
3140 1: subcc %g0,%g1,%g0 // carry
3141 ld [%o0-32],%o4 // source1-digit
3142 ld [%o1-32],%o5 // source2-digit
3143 addxcc %o5,%o4,%o5 // addieren
3144 st %o5,[%o2-32] // Digit ablegen
3145 ld [%o0-28],%o4 // source1-digit
3146 ld [%o1-28],%o5 // source2-digit
3147 addxcc %o5,%o4,%o5 // addieren
3148 st %o5,[%o2-28] // Digit ablegen
3149 ld [%o0-24],%o4 // source1-digit
3150 ld [%o1-24],%o5 // source2-digit
3151 addxcc %o5,%o4,%o5 // addieren
3152 st %o5,[%o2-24] // Digit ablegen
3153 ld [%o0-20],%o4 // source1-digit
3154 ld [%o1-20],%o5 // source2-digit
3155 addxcc %o5,%o4,%o5 // addieren
3156 st %o5,[%o2-20] // Digit ablegen
3157 ld [%o0-16],%o4 // source1-digit
3158 ld [%o1-16],%o5 // source2-digit
3159 addxcc %o5,%o4,%o5 // addieren
3160 st %o5,[%o2-16] // Digit ablegen
3161 ld [%o0-12],%o4 // source1-digit
3162 ld [%o1-12],%o5 // source2-digit
3163 addxcc %o5,%o4,%o5 // addieren
3164 st %o5,[%o2-12] // Digit ablegen
3165 ld [%o0-8],%o4 // source1-digit
3166 ld [%o1-8],%o5 // source2-digit
3167 addxcc %o5,%o4,%o5 // addieren
3168 st %o5,[%o2-8] // Digit ablegen
3169 ld [%o0-4],%o4 // source1-digit
3170 ld [%o1-4],%o5 // source2-digit
3171 addxcc %o5,%o4,%o5 // addieren
3172 st %o5,[%o2-4] // Digit ablegen
3173 addx %g0,%g0,%g1 // neuer Carry
3176 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
3187 // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
3188 DECLARE_FUNCTION(addto_loop_up)
3189 C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
3193 _ mov %g0,%o5 // Carry := 0
3194 1: ld [%o0],%o3 // source-digit
3196 ld [%o1],%o4 // dest-digit
3197 subcc %g0,%o5,%g0 // carry
3198 addxcc %o4,%o3,%o4 // addieren
3199 addx %g0,%g0,%o5 // neuer Carry
3200 st %o4,[%o1] // Digit ablegen
3208 subcc %g0,%o2,%o2 // %o2 = -count
3210 _ mov %g0,%o5 // Carry := 0
3211 sll %o2,2,%o2 // %o2 = -4*count
3212 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
3213 sub %o1,%o2,%o1 // %o1 = &destptr[count]
3214 ld [%o0+%o2],%o3 // source-digit
3215 1: ld [%o1+%o2],%o4 // dest-digit
3216 subcc %g0,%o5,%g0 // carry
3217 addxcc %o4,%o3,%o4 // addieren
3218 addx %g0,%g0,%o5 // neuer Carry
3219 st %o4,[%o1+%o2] // Digit ablegen
3220 addcc %o2,4,%o2 // Zähler erniedrigen, Pointer erhöhen
3222 __ ld [%o0+%o2],%o3 // source-digit
3227 and %o2,7,%o3 // count mod 8
3229 add %o0,%o4,%o0 // %o0 = &sourceptr[count mod 8]
3230 add %o1,%o4,%o1 // %o1 = &destptr[count mod 8]
3233 mov %o7,%g2 // save return address
3234 call 0f // put address of label 0 into %o7
3238 set _addto_loop_up+172,%o4
3241 jmp %o4 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
3242 _ subcc %g0,%g0,%g0 // carry löschen
3243 1: subcc %g0,%o5,%g0 // carry
3244 ld [%o0-32],%o3 // source-digit
3245 ld [%o1-32],%o4 // dest-digit
3246 addxcc %o4,%o3,%o4 // addieren
3247 st %o4,[%o1-32] // Digit ablegen
3248 ld [%o0-28],%o3 // source-digit
3249 ld [%o1-28],%o4 // dest-digit
3250 addxcc %o4,%o3,%o4 // addieren
3251 st %o4,[%o1-28] // Digit ablegen
3252 ld [%o0-24],%o3 // source-digit
3253 ld [%o1-24],%o4 // dest-digit
3254 addxcc %o4,%o3,%o4 // addieren
3255 st %o4,[%o1-24] // Digit ablegen
3256 ld [%o0-20],%o3 // source-digit
3257 ld [%o1-20],%o4 // dest-digit
3258 addxcc %o4,%o3,%o4 // addieren
3259 st %o4,[%o1-20] // Digit ablegen
3260 ld [%o0-16],%o3 // source-digit
3261 ld [%o1-16],%o4 // dest-digit
3262 addxcc %o4,%o3,%o4 // addieren
3263 st %o4,[%o1-16] // Digit ablegen
3264 ld [%o0-12],%o3 // source-digit
3265 ld [%o1-12],%o4 // dest-digit
3266 addxcc %o4,%o3,%o4 // addieren
3267 st %o4,[%o1-12] // Digit ablegen
3268 ld [%o0-8],%o3 // source-digit
3269 ld [%o1-8],%o4 // dest-digit
3270 addxcc %o4,%o3,%o4 // addieren
3271 st %o4,[%o1-8] // Digit ablegen
3272 ld [%o0-4],%o3 // source-digit
3273 ld [%o1-4],%o4 // dest-digit
3274 addxcc %o4,%o3,%o4 // addieren
3275 st %o4,[%o1-4] // Digit ablegen
3276 addx %g0,%g0,%o5 // neuer Carry
3278 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
3289 // extern uintD inc_loop_up (uintD* ptr, uintC count);
3290 DECLARE_FUNCTION(inc_loop_up)
3291 C(inc_loop_up:) // Input in %o0,%o1, Output in %o0
3310 subcc %g0,%o1,%o1 // %o1 = -count
3312 _ sll %o1,2,%o1 // %o1 = -4*count
3313 sub %o0,%o1,%o0 // %o0 = &ptr[count]
3314 ld [%o0+%o1],%o2 // digit holen
3315 1: addcc %o2,1,%o2 // incrementieren
3317 _ st %o2,[%o0+%o1] // ablegen
3318 addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen
3327 // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count);
3328 DECLARE_FUNCTION(sub_loop_up)
3329 C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
3333 _ subcc %g0,%g0,%g0 // Carry := 0
3334 1: ld [%o0],%o4 // source1-digit
3336 ld [%o1],%o5 // source2-digit
3338 subxcc %o4,%o5,%o4 // subtrahieren
3339 addx %g0,%g0,%g1 // neuer Carry
3340 st %o4,[%o2] // Digit ablegen
3344 _ subcc %g0,%g1,%g0 // carry
3349 subcc %g0,%o3,%o3 // %o3 = -count
3351 _ mov %g0,%g1 // Carry := 0
3352 sll %o3,2,%o3 // %o3 = -4*count
3354 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
3355 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
3356 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
3357 1: ld [%o0+%o3],%o4 // source1-digit
3358 ld [%o1+%o3],%o5 // source2-digit
3359 subcc %g0,%g1,%g0 // carry
3360 subxcc %o4,%o5,%o4 // subtrahieren
3361 addx %g0,%g0,%g1 // neuer Carry
3364 _ st %o4,[%o2+%o3] // Digit ablegen
3369 and %o3,7,%o4 // count mod 8
3371 add %o0,%o5,%o0 // %o0 = &sourceptr1[count mod 8]
3372 add %o1,%o5,%o1 // %o1 = &sourceptr2[count mod 8]
3373 add %o2,%o5,%o2 // %o2 = &destptr[count mod 8]
3376 mov %o7,%g2 // save return address
3377 call 0f // put address of label 0 into %o7
3381 set _sub_loop_up+176,%o5
3384 jmp %o5 // Sprung nach (label 1)+4*(1+4*8-4*(count mod 8))
3385 _ subcc %g0,%g0,%g0 // carry löschen
3386 1: subcc %g0,%g1,%g0 // carry
3387 ld [%o0-32],%o4 // source1-digit
3388 ld [%o1-32],%o5 // source2-digit
3389 subxcc %o4,%o5,%o4 // subtrahieren
3390 st %o4,[%o2-32] // Digit ablegen
3391 ld [%o0-28],%o4 // source1-digit
3392 ld [%o1-28],%o5 // source2-digit
3393 subxcc %o4,%o5,%o4 // subtrahieren
3394 st %o4,[%o2-28] // Digit ablegen
3395 ld [%o0-24],%o4 // source1-digit
3396 ld [%o1-24],%o5 // source2-digit
3397 subxcc %o4,%o5,%o4 // subtrahieren
3398 st %o4,[%o2-24] // Digit ablegen
3399 ld [%o0-20],%o4 // source1-digit
3400 ld [%o1-20],%o5 // source2-digit
3401 subxcc %o4,%o5,%o4 // subtrahieren
3402 st %o4,[%o2-20] // Digit ablegen
3403 ld [%o0-16],%o4 // source1-digit
3404 ld [%o1-16],%o5 // source2-digit
3405 subxcc %o4,%o5,%o4 // subtrahieren
3406 st %o4,[%o2-16] // Digit ablegen
3407 ld [%o0-12],%o4 // source1-digit
3408 ld [%o1-12],%o5 // source2-digit
3409 subxcc %o4,%o5,%o4 // subtrahieren
3410 st %o4,[%o2-12] // Digit ablegen
3411 ld [%o0-8],%o4 // source1-digit
3412 ld [%o1-8],%o5 // source2-digit
3413 subxcc %o4,%o5,%o4 // subtrahieren
3414 st %o4,[%o2-8] // Digit ablegen
3415 ld [%o0-4],%o4 // source1-digit
3416 ld [%o1-4],%o5 // source2-digit
3417 subxcc %o4,%o5,%o4 // subtrahieren
3418 st %o4,[%o2-4] // Digit ablegen
3419 addx %g0,%g0,%g1 // neuer Carry
3422 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
3433 // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry);
3434 DECLARE_FUNCTION(subx_loop_up)
3435 C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0
3439 _ subcc %g0,%o4,%g0 // Carry
3440 1: ld [%o0],%o4 // source1-digit
3442 ld [%o1],%o5 // source2-digit
3444 subxcc %o4,%o5,%o4 // subtrahieren
3445 addx %g0,%g0,%g1 // neuer Carry
3446 st %o4,[%o2] // Digit ablegen
3450 _ subcc %g0,%g1,%g0 // carry
3455 subcc %g0,%o3,%o3 // %o3 = -count
3457 _ mov %o4,%g1 // Carry
3458 sll %o3,2,%o3 // %o3 = -4*count
3460 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count]
3461 sub %o1,%o3,%o1 // %o1 = &sourceptr2[count]
3462 sub %o2,%o3,%o2 // %o2 = &destptr[count-1]
3463 1: ld [%o0+%o3],%o4 // source1-digit
3464 ld [%o1+%o3],%o5 // source2-digit
3465 subcc %g0,%g1,%g0 // carry
3466 subxcc %o4,%o5,%o4 // subtrahieren
3467 addx %g0,%g0,%g1 // neuer Carry
3470 _ st %o4,[%o2+%o3] // Digit ablegen
3475 and %o3,7,%o5 // count mod 8
3477 add %o0,%g1,%o0 // %o0 = &sourceptr1[count mod 8]
3478 add %o1,%g1,%o1 // %o1 = &sourceptr2[count mod 8]
3479 add %o2,%g1,%o2 // %o2 = &destptr[count mod 8]
3482 mov %o7,%g2 // save return address
3483 call 0f // put address of label 0 into %o7
3487 set _subx_loop_up+176,%g1
3490 jmp %g1 // Sprung nach _subx_loop_up+4*(12+4*8-4*(count mod 8))
3491 _ subcc %g0,%o4,%g0 // carry initialisieren
3492 1: subcc %g0,%g1,%g0 // carry
3493 ld [%o0-32],%o4 // source1-digit
3494 ld [%o1-32],%o5 // source2-digit
3495 subxcc %o4,%o5,%o4 // subtrahieren
3496 st %o4,[%o2-32] // Digit ablegen
3497 ld [%o0-28],%o4 // source1-digit
3498 ld [%o1-28],%o5 // source2-digit
3499 subxcc %o4,%o5,%o4 // subtrahieren
3500 st %o4,[%o2-28] // Digit ablegen
3501 ld [%o0-24],%o4 // source1-digit
3502 ld [%o1-24],%o5 // source2-digit
3503 subxcc %o4,%o5,%o4 // subtrahieren
3504 st %o4,[%o2-24] // Digit ablegen
3505 ld [%o0-20],%o4 // source1-digit
3506 ld [%o1-20],%o5 // source2-digit
3507 subxcc %o4,%o5,%o4 // subtrahieren
3508 st %o4,[%o2-20] // Digit ablegen
3509 ld [%o0-16],%o4 // source1-digit
3510 ld [%o1-16],%o5 // source2-digit
3511 subxcc %o4,%o5,%o4 // subtrahieren
3512 st %o4,[%o2-16] // Digit ablegen
3513 ld [%o0-12],%o4 // source1-digit
3514 ld [%o1-12],%o5 // source2-digit
3515 subxcc %o4,%o5,%o4 // subtrahieren
3516 st %o4,[%o2-12] // Digit ablegen
3517 ld [%o0-8],%o4 // source1-digit
3518 ld [%o1-8],%o5 // source2-digit
3519 subxcc %o4,%o5,%o4 // subtrahieren
3520 st %o4,[%o2-8] // Digit ablegen
3521 ld [%o0-4],%o4 // source1-digit
3522 ld [%o1-4],%o5 // source2-digit
3523 subxcc %o4,%o5,%o4 // subtrahieren
3524 st %o4,[%o2-4] // Digit ablegen
3525 addx %g0,%g0,%g1 // neuer Carry
3528 subcc %o3,8,%o3 // noch mindestens 8 Digits abzuarbeiten?
3539 // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count);
3540 DECLARE_FUNCTION(subfrom_loop_up)
3541 C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0
3545 _ mov %g0,%o5 // Carry := 0
3546 1: ld [%o0],%o3 // source-digit
3548 ld [%o1],%o4 // dest-digit
3549 subcc %g0,%o5,%g0 // carry
3550 subxcc %o4,%o3,%o4 // subtrahieren
3551 addx %g0,%g0,%o5 // neuer Carry
3552 st %o4,[%o1] // Digit ablegen
3560 subcc %g0,%o2,%o2 // %o2 = -count
3562 _ mov %g0,%o5 // Carry := 0
3563 sll %o2,2,%o2 // %o2 = -4*count
3564 sub %o0,%o2,%o0 // %o0 = &sourceptr[count]
3565 sub %o1,%o2,%o1 // %o1 = &destptr[count]
3566 ld [%o0+%o2],%o3 // source-digit
3567 1: ld [%o1+%o2],%o4 // dest-digit
3568 subcc %g0,%o5,%g0 // carry
3569 subxcc %o4,%o3,%o4 // subtrahieren
3570 addx %g0,%g0,%o5 // neuer Carry
3571 st %o4,[%o1+%o2] // Digit ablegen
3574 __ ld [%o0+%o2],%o3 // source-digit
3579 and %o2,7,%o3 // count mod 8
3581 add %o0,%o4,%o0 // %o0 = &sourceptr[count mod 8]
3582 add %o1,%o4,%o1 // %o1 = &destptr[count mod 8]
3585 mov %o7,%g2 // save return address
3586 call 0f // put address of label 0 into %o7
3590 set _subfrom_loop_up+172,%o4
3593 jmp %o4 // Sprung nach _subfrom_loop_up+4*(11+4*8-4*(count mod 8))
3594 _ subcc %g0,%g0,%g0 // carry löschen
3595 1: subcc %g0,%o5,%g0 // carry
3596 ld [%o0-32],%o3 // source-digit
3597 ld [%o1-32],%o4 // dest-digit
3598 subxcc %o4,%o3,%o4 // subtrahieren
3599 st %o4,[%o1-32] // Digit ablegen
3600 ld [%o0-28],%o3 // source-digit
3601 ld [%o1-28],%o4 // dest-digit
3602 subxcc %o4,%o3,%o4 // subtrahieren
3603 st %o4,[%o1-28] // Digit ablegen
3604 ld [%o0-24],%o3 // source-digit
3605 ld [%o1-24],%o4 // dest-digit
3606 subxcc %o4,%o3,%o4 // subtrahieren
3607 st %o4,[%o1-24] // Digit ablegen
3608 ld [%o0-20],%o3 // source-digit
3609 ld [%o1-20],%o4 // dest-digit
3610 subxcc %o4,%o3,%o4 // subtrahieren
3611 st %o4,[%o1-20] // Digit ablegen
3612 ld [%o0-16],%o3 // source-digit
3613 ld [%o1-16],%o4 // dest-digit
3614 subxcc %o4,%o3,%o4 // subtrahieren
3615 st %o4,[%o1-16] // Digit ablegen
3616 ld [%o0-12],%o3 // source-digit
3617 ld [%o1-12],%o4 // dest-digit
3618 subxcc %o4,%o3,%o4 // subtrahieren
3619 st %o4,[%o1-12] // Digit ablegen
3620 ld [%o0-8],%o3 // source-digit
3621 ld [%o1-8],%o4 // dest-digit
3622 subxcc %o4,%o3,%o4 // subtrahieren
3623 st %o4,[%o1-8] // Digit ablegen
3624 ld [%o0-4],%o3 // source-digit
3625 ld [%o1-4],%o4 // dest-digit
3626 subxcc %o4,%o3,%o4 // subtrahieren
3627 st %o4,[%o1-4] // Digit ablegen
3628 addx %g0,%g0,%o5 // neuer Carry
3630 subcc %o2,8,%o2 // noch mindestens 8 Digits abzuarbeiten?
3641 // extern uintD dec_loop_up (uintD* ptr, uintC count);
3642 DECLARE_FUNCTION(dec_loop_up)
3643 C(dec_loop_up:) // Input in %o0,%o1, Output in %o0
3662 subcc %g0,%o1,%o1 // %o1 = -count
3664 _ sll %o1,2,%o1 // %o1 = -4*count
3665 sub %o0,%o1,%o0 // %o0 = &ptr[count]
3666 ld [%o0+%o1],%o2 // digit holen
3667 1: subcc %o2,1,%o2 // decrementieren
3669 _ st %o2,[%o0+%o1] // ablegen
3670 addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen
3679 // extern uintD neg_loop_up (uintD* ptr, uintC count);
3680 DECLARE_FUNCTION(neg_loop_up)
3681 C(neg_loop_up:) // Input in %o0,%o1, Output in %o0
3683 // erstes Digit /=0 suchen:
3695 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
3696 // 1 Digit negieren, alle anderen Digits invertieren:
3709 // erstes Digit /=0 suchen:
3710 subcc %g0,%o1,%o1 // %o1 = -count
3712 _ sll %o1,2,%o1 // %o1 = -4*count
3713 sub %o0,%o1,%o0 // %o0 = &ptr[count]
3714 ld [%o0+%o1],%o2 // digit holen
3715 1: subcc %g0,%o2,%o2 // negieren, testen
3717 _ addcc %o1,4,%o1 // Zähler erniedrigen, Pointer erhöhen
3722 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys
3723 // alle anderen Digits invertieren:
3725 st %o2,[%o0+%o1] // ablegen
3739 // extern uintD shift1left_loop_up (uintD* ptr, uintC count);
3740 DECLARE_FUNCTION(shift1left_loop_up)
3741 C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0
3744 _ mov 0,%o3 // Carry := 0
3745 1: ld [%o0],%o2 // Digit
3746 subcc %g0,%o3,%g0 // carry
3747 addxcc %o2,%o2,%o2 // shiften
3748 addx %g0,%g0,%o3 // neues Carry
3749 st %o2,[%o0] // Digit ablegen
3756 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry);
3757 DECLARE_FUNCTION(shiftleft_loop_up)
3758 C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0
3761 _ sub %g0,%o2,%g1 // 32-i (mod 32)
3762 1: ld [%o0],%o4 // Digit
3764 sll %o4,%o2,%o5 // dessen niedere (32-i) Bits
3765 or %o3,%o5,%o5 // mit dem alten Carry kombinieren
3766 st %o5,[%o0] // Digit ablegen
3767 srl %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry
3775 // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i);
3776 DECLARE_FUNCTION(shiftleftcopy_loop_up)
3777 C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0
3780 _ mov 0,%o4 // Carry := 0
3781 sub %g0,%o3,%g1 // 32-i (mod 32)
3782 1: ld [%o0],%o5 // Digit
3784 sll %o5,%o3,%g2 // dessen niedere (32-i) Bits
3785 or %o4,%g2,%g2 // mit dem alten Carry kombinieren
3786 st %g2,[%o1] // Digit ablegen
3788 srl %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry
3794 #if !CL_DS_BIG_ENDIAN_P
3796 // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry);
3797 DECLARE_FUNCTION(shift1right_loop_down)
3798 C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0
3801 _ sll %o2,31,%o2 // Carry
3803 1: ld [%o0],%o3 // Digit
3805 srl %o3,1,%o4 // shiften
3806 or %o2,%o4,%o4 // und mit altem Carry kombinieren
3807 st %o4,[%o0] // und ablegen
3808 sll %o3,31,%o2 // neuer Carry
3814 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i);
3815 DECLARE_FUNCTION(shiftright_loop_down)
3816 C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
3817 sub %g0,%o2,%g1 // 32-i (mod 32)
3820 _ or %g0,%g0,%o3 // Carry := 0
3822 1: ld [%o0],%o4 // Digit
3824 srl %o4,%o2,%o5 // shiften
3825 or %o3,%o5,%o5 // und mit altem Carry kombinieren
3826 st %o5,[%o0] // und ablegen
3827 sll %o4,%g1,%o3 // neuer Carry
3833 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i);
3834 DECLARE_FUNCTION(shiftrightsigned_loop_down)
3835 C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0
3836 ld [%o0-4],%o4 // erstes Digit
3837 sub %g0,%o2,%g1 // 32-i (mod 32)
3838 sra %o4,%o2,%o5 // shiften
3839 st %o5,[%o0-4] // und ablegen
3840 sll %o4,%g1,%o3 // neuer Carry
3844 1: ld [%o0],%o4 // Digit
3846 srl %o4,%o2,%o5 // shiften
3847 or %o3,%o5,%o5 // und mit altem Carry kombinieren
3848 st %o5,[%o0] // und ablegen
3849 sll %o4,%g1,%o3 // neuer Carry
3855 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry);
3856 DECLARE_FUNCTION(shiftrightcopy_loop_down)
3857 C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0
3858 sub %g0,%o3,%g1 // 32-i (mod 32)
3861 _ sll %o4,%g1,%g2 // erster Carry
3863 1: ld [%o0],%o4 // Digit
3865 srl %o4,%o3,%o5 // shiften
3866 or %g2,%o5,%o5 // und mit altem Carry kombinieren
3867 st %o5,[%o1] // und ablegen
3868 sll %o4,%g1,%g2 // neuer Carry
3875 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit);
3876 DECLARE_FUNCTION(mulusmall_loop_up)
3877 C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0
3881 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren
3882 // und kleinen Carry %o3 dazu:
3884 ld [%o1],%o4 // Wartetakt!
3893 // Die 26 unteren Bits von %o5 und die 6 oberen Bits von %y
3894 // ergeben das Resultat. (Die anderen Bits sind Null.)
3895 tst %o4 // Korrektur, falls %o4 negativ war
3897 _ sra %o5,26,%o3 // 6 obere Bits von %o5 -> neuer Carry
3898 add %o3,%o0,%o3 // (falls %o4 negativ war, noch + %o0)
3900 srl %o4,26,%o4 // 6 obere Bits von %y
3901 sll %o5,6,%o5 // 26 untere Bits von %o5
3902 or %o5,%o4,%o4 // neues Digit
3903 st %o4,[%o1] // ablegen
3910 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
3912 DECLARE_FUNCTION(mulu_loop_up)
3913 C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3
3916 1: ld [%i1],%o1 // nächstes Digit
3918 call _mulu32_ // mit digit multiplizieren
3920 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
3921 addx %g0,%g1,%l0 // High-Digit gibt neuen Carry
3922 st %o0,[%i2] // Low-Digit ablegen
3926 st %l0,[%i2] // letzten Carry ablegen
3930 DECLARE_FUNCTION(mulu_loop_up)
3931 C(mulu_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1
3933 1: ld [%o1],%g1 // nächstes Digit
3934 // mit digit multiplizieren: %o0 * %g1 -> %o5|%g1
3941 add %o1,4,%o1 // Wartetakt!
3981 addcc %o4,%g1,%g1 // und bisherigen Carry addieren
3982 addx %g0,%o5,%o4 // High-Digit gibt neuen Carry
3983 st %g1,[%o2] // Low-Digit ablegen
3988 _ st %o4,[%o2] // letzten Carry ablegen
3991 // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
3992 DECLARE_FUNCTION(muluadd_loop_up)
3993 C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
3997 1: ld [%i1],%o1 // nächstes source-Digit
3999 call _mulu32_ // mit digit multiplizieren
4001 ld [%i2],%o1 // nächstes dest-digit
4002 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
4003 addx %g0,%g1,%l0 // High-Digit gibt neuen Carry
4004 addcc %o1,%o0,%o0 // addieren
4006 st %o0,[%i2] // Low-Digit ablegen
4010 mov %l0,%i0 // letzter Carry
4017 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
4019 1: ld [%i1],%o1 // nächstes source-Digit
4021 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
4027 and %o1,%l1,%o3 // Wartetakt!
4062 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
4065 ld [%i2],%o1 // nächstes dest-digit
4066 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
4067 addx %g0,%o2,%l0 // High-Digit gibt neuen Carry
4068 addcc %o1,%o0,%o0 // addieren
4070 st %o0,[%i2] // Low-Digit ablegen
4074 mov %l0,%i0 // letzter Carry
4079 // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
4080 DECLARE_FUNCTION(mulusub_loop_up)
4081 C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0
4085 1: ld [%i1],%o1 // nächstes source-Digit
4087 call _mulu32_ // mit digit multiplizieren
4089 ld [%i2],%o1 // nächstes dest-digit
4090 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
4091 addx %g0,%g1,%l0 // High-Digit gibt neuen Carry
4092 subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren
4094 st %o1,[%i2] // dest-Digit ablegen
4098 mov %l0,%i0 // letzter Carry
4105 sra %i0,31,%l1 // 0 falls %i0>=0, -1 falls %i0<0
4107 1: ld [%i1],%o1 // nächstes source-Digit
4109 // mit digit multiplizieren: %i0 * %o1 -> %o2|%o0
4115 and %o1,%l1,%o3 // Wartetakt!
4150 add %o2,%o3,%o2 // %o3 = (0 falls %i0>=0, %o1 falls %i0<0)
4153 ld [%i2],%o1 // nächstes dest-digit
4154 addcc %l0,%o0,%o0 // und bisherigen Carry addieren
4155 addx %g0,%o2,%l0 // High-Digit gibt neuen Carry
4156 subcc %o1,%o0,%o1 // davon das Low-Digit subtrahieren
4158 st %o1,[%i2] // dest-Digit ablegen
4162 mov %l0,%i0 // letzter Carry
4167 // extern uintD divu_loop_down (uintD digit, uintD* ptr, uintC len);
4168 DECLARE_FUNCTION(divu_loop_down)
4169 C(divu_loop_down:) // Input in %i0,%i1,%i2, Output in %i0
4174 1: mov %g1,%o0 // Rest als High-Digit
4175 ld [%i1-4],%o1 // nächstes Digit als Low-Digit
4176 call C(divu_6432_3232_) // zusammen durch digit dividieren
4178 st %o0,[%i1-4] // Quotient ablegen, Rest in %g1
4182 2: mov %g1,%i0 // Rest als Ergebnis
4186 // extern uintD divucopy_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
4187 DECLARE_FUNCTION(divucopy_loop_down)
4188 C(divucopy_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0
4193 1: mov %g1,%o0 // Rest als High-Digit
4194 ld [%i1-4],%o1 // nächstes Digit als Low-Digit
4195 call C(divu_6432_3232_) // zusammen durch digit dividieren
4198 st %o0,[%i2] // Quotient ablegen, Rest in %g1
4202 2: mov %g1,%i0 // Rest als Ergebnis
4208 // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i);
4209 DECLARE_FUNCTION(shiftxor_loop_up)
4210 C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2
4213 _ sub %g0,%o3,%g1 // 32-i (mod 32)
4215 ld [%o0],%o4 // *xptr holen
4216 1: ld [%o0+%o1],%o5 // *yptr holen
4218 sll %o5,%o3,%g2 // dessen niedere (32-i) Bits
4219 xor %o4,%g2,%o4 // mit dem modifizierten *xptr kombinieren
4220 st %o4,[%o0] // und ablegen
4222 srl %o5,%g1,%g2 // höchste i Bits von *yptr
4223 ld [%o0],%o4 // schon mal mit dem nächsten *xptr
4225 _ xor %o4,%g2,%o4 // verknüpfen
4226 st %o4,[%o0] // und ablegen