// Externe Routinen zu ARILEV1.D // Prozessor: SPARC 64-bit // Compiler: GNU-C oder ... // Parameter-Übergabe: in Registern %o0-%o5. // Parameter-Übergabe: in Registern %o0-%o5. // Argumente vom Typ uint8, uint16, uint32 sind bereits vom Aufrufer zu // uint64 umgewandelt worden (zero-extend, "srl reg,0,reg"). // Argumente vom Typ sint8, sint16, sint32 sind bereits vom Aufrufer zu // sint64 umgewandelt worden (sign-extend, "sra reg,0,reg"). // Ergebnisse vom Typ uint8, uint16, uint32 müssen vor Rückgabe zu uint64 // umgewandelt werden (zero-extend, "srl reg,0,reg"). // Ergebnisse vom Typ sint8, sint16, sint32 müssen vor Rückgabe zu sint64 // umgewandelt werden (sign-extend, "sra reg,0,reg"). // Einstellungen: intCsize=32, intDsize=32. #ifdef ASM_UNDERSCORE #define C(entrypoint) _##entrypoint #else #define C(entrypoint) entrypoint #endif // When this file is compiled into a shared library, ELF linkers need to // know which symbols are functions. #if defined(__NetBSD__) || defined(__OpenBSD__) #define DECLARE_FUNCTION(name) .type C(name),@function #elif defined(__svr4__) || defined(__ELF__) // Some preprocessors keep the backslash in place, some don't. // Some complain about the # being not in front of an ANSI C macro. // Therefore we use a dollar, which will be sed-converted to # later. #define DECLARE_FUNCTION(name) .type C(name),$function #else #define DECLARE_FUNCTION(name) #endif // Indikatoren für Anweisungen (Instruktionen) in Delay-Slots // (diese werden VOR der vorigen Instruktion ausgeführt): #define _ // Instruktion, die stets ausgeführt wird #define __ // Instruktion, die nur im Sprung-Fall ausgeführt wird // Abkürzungen für Anweisungen: #define ret jmp %i7+8 // return from subroutine #define retl jmp %o7+8 // return from leaf subroutine (no save/restore) .seg "text" .global C(mulu16_),C(mulu32_),C(mulu32_unchecked),C(mulu64_) .global C(divu_6432_3232_),C(divu_3216_1616_) .global C(copy_loop_up),C(copy_loop_down),C(fill_loop_up),C(fill_loop_down) .global C(clear_loop_up),C(clear_loop_down) .global C(test_loop_up),C(test_loop_down) .global C(xor_loop_up),C(compare_loop_up),C(shiftleftcopy_loop_up),C(shiftxor_loop_up) #if CL_DS_BIG_ENDIAN_P .global C(or_loop_up),C(and_loop_up),C(eqv_loop_up) .global C(nand_loop_up),C(nor_loop_up),C(andc2_loop_up),C(orc2_loop_up) .global C(not_loop_up) .global C(and_test_loop_up) .global C(add_loop_down),C(addto_loop_down),C(inc_loop_down) .global C(sub_loop_down),C(subx_loop_down),C(subfrom_loop_down),C(dec_loop_down) .global C(neg_loop_down) .global C(shift1left_loop_down),C(shiftleft_loop_down),C(shiftleftcopy_loop_down) .global C(shift1right_loop_up),C(shiftright_loop_up),C(shiftrightsigned_loop_up),C(shiftrightcopy_loop_up) .global C(mulusmall_loop_down),C(mulu_loop_down),C(muluadd_loop_down),C(mulusub_loop_down) #else .global C(or_loop_down),C(xor_loop_down),C(and_loop_down),C(eqv_loop_down) .global C(nand_loop_down),C(nor_loop_down),C(andc2_loop_down),C(orc2_loop_down) .global C(not_loop_down) .global C(and_test_loop_down),C(compare_loop_down) .global C(add_loop_up),C(addto_loop_up),C(inc_loop_up) .global C(sub_loop_up),C(subx_loop_up),C(subfrom_loop_up),C(dec_loop_up) .global C(neg_loop_up) .global C(shift1left_loop_up),C(shiftleft_loop_up) .global C(shift1right_loop_down),C(shiftright_loop_down),C(shiftrightsigned_loop_down),C(shiftrightcopy_loop_down) .global C(mulusmall_loop_up),C(mulu_loop_up),C(muluadd_loop_up),C(mulusub_loop_up) #endif #define LOOP_TYPE 1 // 1: Standard-Schleifen // 2: Schleifen ohne Pointer, nur mit Zähler #define STANDARD_LOOPS (LOOP_TYPE==1) #define COUNTER_LOOPS (LOOP_TYPE==2) // extern uint32 mulu16_ (uint16 arg1, uint16 arg2); // ergebnis := arg1*arg2. DECLARE_FUNCTION(mulu16_) C(mulu16_:) // Input in %o0,%o1, Output in %o0 umul %o0,%o1,%o2 retl _ srl %o2,0,%o0 // extern struct { uint32 lo; uint32 hi; } mulu32_ (uint32 arg1, uint32 arg2); // 2^32*hi+lo := arg1*arg2. DECLARE_FUNCTION(mulu32_) C(mulu32_:) // Input in %o0,%o1, Output in %o0,%g1 umul %o0,%o1,%o2 rd %y,%g1 retl _ srl %o2,0,%o0 // extern uint32 mulu32_unchecked (uint32 x, uint32 y); // ergebnis := arg1*arg2 < 2^32. DECLARE_FUNCTION(mulu32_unchecked) C(mulu32_unchecked:) // Input in %o0,%o1, Output in %o0 umul %o0,%o1,%o2 retl _ srl %o2,0,%o0 // extern struct { uint64 lo; uint64 hi; } mulu64_ (uint64 arg1, uint64 arg2); // 2^64*hi+lo := arg1*arg2. DECLARE_FUNCTION(mulu64_) C(mulu64_:) // Input in %o0,%o1, Output in %o0,%g2 srlx %o0,32,%o2 // %o2 = high32(arg1) srl %o0,0,%o0 // %o0 = low32(arg1) srlx %o1,32,%o3 // %o3 = high32(arg2) srl %o1,0,%o1 // %o1 = low32(arg2) mulx %o2,%o3,%g2 // high part mulx %o2,%o1,%o2 // first mid part mulx %o0,%o3,%o3 // second mid part addcc %o2,%o3,%o2 // sum of mid parts mov 0,%o3 movcs %xcc,1,%o3 // carry from sum of mid parts sllx %o3,32,%o3 add %g2,%o3,%g2 // add to high part srlx %o2,32,%o3 add %g2,%o3,%g2 // add high32(midparts) to high part mulx %o0,%o1,%o0 // low part sllx %o2,32,%o2 addcc %o0,%o2,%o0 // add low32(midparts)*2^32 to low part add %g2,1,%o3 retl _ movcs %xcc,%o3,%g2 // add carry to high part // extern struct { uint32 q; uint32 r; } divu_6432_3232_ (uint32 xhi, uint32 xlo, uint32 y); // x = 2^32*xhi+xlo = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^32*y . DECLARE_FUNCTION(divu_6432_3232_) C(divu_6432_3232_:) // Input in %o0,%o1,%o2, Output in %o0,%g1 wr %o0,%g0,%y udiv %o1,%o2,%o0 // x durch y dividieren, %o0 := q umul %o0,%o2,%g1 // %g1 := (q*y) mod 2^32 sub %o1,%g1,%g1 // %g1 := (xlo-q*y) mod 2^32 = r retl _ srl %o0,0,%o0 // extern struct { uint16 q; uint16 r; } divu_3216_1616_ (uint32 x, uint16 y); // x = q*y+r schreiben. Sei bekannt, daß 0 <= x < 2^16*y . DECLARE_FUNCTION(divu_3216_1616_) C(divu_3216_1616_:) // Input in %o0,%o1, Output in %o0 (Rest und Quotient). wr %g0,%g0,%y udiv %o0,%o1,%o2 // dividieren, Quotient nach %o2 #if 0 // Who says that %y has some meaningful contents after `udiv' ?? rd %y,%g1 // Rest aus %y #else umul %o2,%o1,%g1 // %g1 := (q*y) mod 2^32 sub %o0,%g1,%g1 // %g1 := (x-q*y) mod 2^32 = r #endif sll %g1,16,%g1 // in die oberen 16 Bit schieben or %o2,%g1,%o0 retl _ srl %o0,0,%o0 #if !defined(__GNUC__) .global C(_get_g1) // extern uint32 _get_g1 (void); DECLARE_FUNCTION(_get_g1) C(_get_g1:) retl _ srl %g1,0,%o0 #endif #if !defined(__GNUC__) .global C(_get_g2) // extern uint64 _get_g2 (void); DECLARE_FUNCTION(_get_g2) C(_get_g2:) retl _ mov %g2,%o0 #endif // extern uintD* copy_loop_up (uintD* sourceptr, uintD* destptr, uintC count); DECLARE_FUNCTION(copy_loop_up) C(copy_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ nop 1: ldx [%o0],%o3 add %o0,8,%o0 stx %o3,[%o1] subcc %o2,1,%o2 bne,pt %xcc,1b _ add %o1,8,%o1 2: retl _ mov %o1,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,8,%o1 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &sourceptr[count] sub %o1,%o2,%o1 // %o1 = &destptr[count-1] 1: ldx [%o0+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ add %o1,8,%o0 #endif // extern uintD* copy_loop_down (uintD* sourceptr, uintD* destptr, uintC count); DECLARE_FUNCTION(copy_loop_down) C(copy_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 1: ldx [%o0],%o3 sub %o1,8,%o1 stx %o3,[%o1] subcc %o2,1,%o2 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o1,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] sub %o1,%o2,%o1 // %o1 = &destptr[-count] 1: ldx [%o0+%o2],%o3 // nächstes Digit holen subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ mov %o1,%o0 #endif // extern uintD* fill_loop_up (uintD* destptr, uintC count, uintD filler); DECLARE_FUNCTION(fill_loop_up) C(fill_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ nop 1: stx %o2,[%o0] subcc %o1,1,%o1 bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 sub %g0,%o1,%o1 // %o1 = -count sllx %o1,3,%o1 // %o1 = -8*count sub %o0,%o1,%o0 // %o0 = &destptr[count-1] 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen bne,pt %xcc,1b _ stx %o2,[%o0+%o1] // Digit ablegen 2: retl _ add %o0,8,%o0 #endif // extern uintD* fill_loop_down (uintD* destptr, uintC count, uintD filler); DECLARE_FUNCTION(fill_loop_down) C(fill_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 1: stx %o2,[%o0] subcc %o1,1,%o1 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ add %o0,8,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sllx %o1,3,%o1 // %o1 = 8*count sub %o0,%o1,%o0 // %o0 = &destptr[-count] 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen bne,pt %xcc,1b _ stx %o2,[%o0+%o1] // Digit ablegen 2: retl _ nop #endif // extern uintD* clear_loop_up (uintD* destptr, uintC count); DECLARE_FUNCTION(clear_loop_up) C(clear_loop_up:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ nop 1: stx %g0,[%o0] subcc %o1,1,%o1 bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 sub %g0,%o1,%o1 // %o1 = -count sllx %o1,3,%o1 // %o1 = -8*count sub %o0,%o1,%o0 // %o0 = &destptr[count-1] 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen bne,pt %xcc,1b _ stx %g0,[%o0+%o1] // Digit 0 ablegen 2: retl _ add %o0,8,%o0 #endif // extern uintD* clear_loop_down (uintD* destptr, uintC count); DECLARE_FUNCTION(clear_loop_down) C(clear_loop_down:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 1: stx %g0,[%o0] subcc %o1,1,%o1 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ add %o0,8,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sllx %o1,3,%o1 // %o1 = 8*count sub %o0,%o1,%o0 // %o0 = &destptr[-count] 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen bne,pt %xcc,1b _ stx %g0,[%o0+%o1] // Digit 0 ablegen 2: retl _ nop #endif // extern boolean test_loop_up (uintD* ptr, uintC count); DECLARE_FUNCTION(test_loop_up) C(test_loop_up:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ nop ldx [%o0],%o2 1: add %o0,8,%o0 brnz,pn %o2,3f _ subcc %o1,1,%o1 bne,a,pt %xcc,1b __ ldx [%o0],%o2 2: retl _ mov 0,%o0 3: retl _ mov 1,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %g0,%o1,%o1 // %o1 = -count sllx %o1,3,%o1 // %o1 = -8*count sub %o0,%o1,%o0 // %o0 = &ptr[count] ldx [%o0+%o1],%o2 // nächstes Digit holen 1: brnz,pn %o2,3f // testen _ addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen bne,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 // nächstes Digit holen 2: retl _ mov 0,%o0 3: retl _ mov 1,%o0 #endif // extern boolean test_loop_down (uintD* ptr, uintC count); DECLARE_FUNCTION(test_loop_down) C(test_loop_down:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 ldx [%o0],%o2 1: sub %o0,8,%o0 brnz,pn %o2,3f _ subcc %o1,1,%o1 bne,a,pt %xcc,1b __ ldx [%o0],%o2 2: retl _ mov 0,%o0 3: retl _ mov 1,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sllx %o1,3,%o1 // %o1 = 8*count sub %o0,%o1,%o0 // %o0 = &ptr[-count] sub %o1,8,%o1 ldx [%o0+%o1],%o2 // nächstes Digit holen 1: brnz,pn %o2,3f // testen _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen bcc,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 // nächstes Digit holen 2: retl _ mov 0,%o0 3: retl _ mov 1,%o0 #endif #if CL_DS_BIG_ENDIAN_P // extern void or_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(or_loop_up) C(or_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 or %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen or %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif #endif // extern void xor_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(xor_loop_up) C(xor_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 xor %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen xor %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif #if CL_DS_BIG_ENDIAN_P // extern void and_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(and_loop_up) C(and_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 and %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen and %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void eqv_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(eqv_loop_up) C(eqv_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 xnor %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen xnor %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void nand_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(nand_loop_up) C(nand_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 and %o3,%o4,%o3 // verknüpfen xnor %g0,%o3,%o3 stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen and %o4,%o3,%o3 // beide verknüpfen xnor %g0,%o3,%o3 bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void nor_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(nor_loop_up) C(nor_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 or %o3,%o4,%o3 // verknüpfen xnor %g0,%o3,%o3 stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen or %o4,%o3,%o3 // beide verknüpfen xnor %g0,%o3,%o3 bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void andc2_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(andc2_loop_up) C(andc2_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 andn %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen andn %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void orc2_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(orc2_loop_up) C(orc2_loop_up:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 orn %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ add %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o0,8,%o0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count-1] sub %o1,%o2,%o1 // %o1 = &yptr[count] 1: ldx [%o1+%o2],%o3 // nächstes Digit holen addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o2],%o4 // noch ein Digit holen orn %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void not_loop_up (uintD* xptr, uintC count); DECLARE_FUNCTION(not_loop_up) C(not_loop_up:) // Input in %o0,%o1 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ nop 1: ldx [%o0],%o2 subcc %o1,1,%o1 xnor %g0,%o2,%o2 stx %o2,[%o0] bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 sub %g0,%o1,%o1 // %o1 = -count sllx %o1,3,%o1 // %o1 = -8*count sub %o0,%o1,%o0 // %o0 = &destptr[count-1] 1: addcc %o1,8,%o1 // Zähler "erniedrigen", Pointer erhöhen ldx [%o0+%o1],%o2 // nächstes Digit holen xnor %g0,%o2,%o2 bne,pt %xcc,1b _ stx %o2,[%o0+%o1] // Digit ablegen 2: retl _ nop #endif // extern boolean and_test_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(and_test_loop_up) C(and_test_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ nop 1: ldx [%o0],%o3 ldx [%o1],%o4 add %o0,8,%o0 andcc %o3,%o4,%g0 bne,pn %xcc,3f _ subcc %o2,1,%o2 bne,pt %xcc,1b _ add %o1,8,%o1 2: retl _ mov 0,%o0 3: retl _ mov 1,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count] sub %o1,%o2,%o1 // %o1 = &yptr[count] ldx [%o0+%o2],%o3 // nächstes Digit holen 1: ldx [%o1+%o2],%o4 // noch ein Digit holen andcc %o3,%o4,%g0 // beide verknüpfen bne,pn %xcc,3f _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen bne,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // nächstes Digit holen 2: retl _ mov 0,%o0 3: retl _ mov 1,%o0 #endif #endif // extern cl_signean compare_loop_up (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(compare_loop_up) C(compare_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ nop ldx [%o0],%o3 1: ldx [%o1],%o4 add %o0,8,%o0 subcc %o3,%o4,%g0 bne,pn %xcc,3f _ add %o1,8,%o1 subcc %o2,1,%o2 bne,a,pt %xcc,1b __ ldx [%o0],%o3 2: retl _ mov 0,%o0 3: mov 1,%o0 movlu %xcc,-1,%o0 retl _ sra %o0,0,%o0 // sign-extend %o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &xptr[count] sub %o1,%o2,%o1 // %o1 = &yptr[count] ldx [%o0+%o2],%o3 // nächstes Digit holen 1: ldx [%o1+%o2],%o4 // noch ein Digit holen subcc %o3,%o4,%g0 // vergleichen bne,pn %xcc,3f _ addcc %o2,8,%o2 // Zähler "erniedrigen", Pointer erhöhen bne,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // nächstes Digit holen 2: retl _ mov 0,%o0 3: subcc %o3,%o4,%g0 // nochmals vergleichen mov 1,%o0 movlu %xcc,-1,%o0 retl _ sra %o0,0,%o0 // sign-extend %o0 #endif #if CL_DS_BIG_ENDIAN_P // extern uintD add_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); DECLARE_FUNCTION(add_loop_down) C(add_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 #if STANDARD_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 sub %o0,8,%o0 1: ldx [%o0],%o4 // source1-digit sub %o1,8,%o1 ldx [%o1],%o5 // source2-digit addcc %o4,%g1,%o4 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 addcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 sub %o2,8,%o2 stx %o4,[%o2] // Digit ablegen subcc %o3,1,%o3 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %g1,%o0 #endif #if COUNTER_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 sub %o0,8,%o0 sub %o1,8,%o1 sllx %o3,3,%o3 // %o3 = 8*count sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] sub %o2,%o3,%o2 // %o2 = &destptr[-count] 1: ldx [%o0+%o3],%o4 // source1-digit ldx [%o1+%o3],%o5 // source2-digit addcc %o4,%g1,%o4 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 addcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 subcc %o3,8,%o3 bne,pt %xcc,1b _ stx %o4,[%o2+%o3] // Digit ablegen 2: retl _ mov %g1,%o0 #endif // extern uintD addto_loop_down (uintD* sourceptr, uintD* destptr, uintC count); DECLARE_FUNCTION(addto_loop_down) C(addto_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 sub %o0,8,%o0 1: ldx [%o0],%o3 // source-digit sub %o1,8,%o1 ldx [%o1],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 addcc %o3,%o4,%o4 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 stx %o4,[%o1] // Digit ablegen subcc %o2,1,%o2 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o5,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 sub %o0,8,%o0 sub %o1,8,%o1 sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] sub %o1,%o2,%o1 // %o1 = &destptr[-count-1] ldx [%o0+%o2],%o3 // source-digit 1: ldx [%o1+%o2],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 addcc %o3,%o4,%o4 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 stx %o4,[%o1+%o2] // Digit ablegen subcc %o2,8,%o2 bne,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // source-digit 2: retl _ mov %o5,%o0 #endif // extern uintD inc_loop_down (uintD* ptr, uintC count); DECLARE_FUNCTION(inc_loop_down) C(inc_loop_down:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 1: ldx [%o0],%o2 addcc %o2,1,%o2 bne,pn %xcc,3f _ stx %o2,[%o0] subcc %o1,1,%o1 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov 1,%o0 3: retl _ mov 0,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 sllx %o1,3,%o1 // %o1 = 8*count sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] ldx [%o0+%o1],%o2 // digit holen 1: addcc %o2,1,%o2 // incrementieren bne,pn %xcc,3f _ stx %o2,[%o0+%o1] // ablegen subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen bne,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 2: retl _ mov 1,%o0 3: retl _ mov 0,%o0 #endif // extern uintD sub_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); DECLARE_FUNCTION(sub_loop_down) C(sub_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 #if STANDARD_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 sub %o1,8,%o1 1: ldx [%o1],%o5 // source2-digit sub %o0,8,%o0 ldx [%o0],%o4 // source1-digit addcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 sub %o2,8,%o2 stx %o4,[%o2] // Digit ablegen subcc %o3,1,%o3 bne,pt %xcc,1b _ sub %o1,8,%o1 2: retl _ mov %g1,%o0 #endif #if COUNTER_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 sub %o0,8,%o0 sub %o1,8,%o1 sllx %o3,3,%o3 // %o3 = 8*count sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] sub %o2,%o3,%o2 // %o2 = &destptr[-count] 1: ldx [%o0+%o3],%o4 // source1-digit ldx [%o1+%o3],%o5 // source2-digit addcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 subcc %o3,8,%o3 bne,pt %xcc,1b _ stx %o4,[%o2+%o3] // Digit ablegen 2: retl _ mov %g1,%o0 #endif // extern uintD subx_loop_down (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); DECLARE_FUNCTION(subx_loop_down) C(subx_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0 #if STANDARD_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %o4,%g1 // Carry (0 oder -1) sub %o1,8,%o1 1: ldx [%o1],%o5 // source2-digit sub %o0,8,%o0 ldx [%o0],%o4 // source1-digit subcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 sub %o2,8,%o2 stx %o4,[%o2] // Digit ablegen subcc %o3,1,%o3 bne,pt %xcc,1b _ sub %o1,8,%o1 2: retl _ mov %g1,%o0 #endif #if COUNTER_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %o4,%g1 // Carry (0 oder -1) sub %o0,8,%o0 sub %o1,8,%o1 sllx %o3,3,%o3 // %o3 = 8*count sub %o0,%o3,%o0 // %o0 = &sourceptr1[-count-1] sub %o1,%o3,%o1 // %o1 = &sourceptr2[-count-1] sub %o2,%o3,%o2 // %o2 = &destptr[-count] 1: ldx [%o1+%o3],%o5 // source2-digit ldx [%o0+%o3],%o4 // source1-digit subcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 subcc %o3,8,%o3 bne,pt %xcc,1b _ stx %o4,[%o2+%o3] // Digit ablegen 2: retl _ mov %g1,%o0 #endif // extern uintD subfrom_loop_down (uintD* sourceptr, uintD* destptr, uintC count); DECLARE_FUNCTION(subfrom_loop_down) C(subfrom_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 sub %o0,8,%o0 1: ldx [%o0],%o3 // source-digit sub %o1,8,%o1 ldx [%o1],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 subcc %o4,%o3,%o4 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 stx %o4,[%o1] // Digit ablegen subcc %o2,1,%o2 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o5,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 sub %o0,8,%o0 sub %o1,8,%o1 sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &sourceptr[-count-1] sub %o1,%o2,%o1 // %o1 = &destptr[-count-1] ldx [%o0+%o2],%o3 // source-digit 1: ldx [%o1+%o2],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 subcc %o4,%o3,%o4 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 stx %o4,[%o1+%o2] // Digit ablegen subcc %o2,8,%o2 bne,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // source-digit 2: retl _ mov %o5,%o0 #endif // extern uintD dec_loop_down (uintD* ptr, uintC count); DECLARE_FUNCTION(dec_loop_down) C(dec_loop_down:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 1: ldx [%o0],%o2 subcc %o2,1,%o2 bcc,pn %xcc,3f _ stx %o2,[%o0] subcc %o1,1,%o1 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov -1,%o0 3: retl _ mov 0,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 sllx %o1,3,%o1 // %o1 = 8*count sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] ldx [%o0+%o1],%o2 // digit holen 1: subcc %o2,1,%o2 // decrementieren bcc,pn %xcc,3f _ stx %o2,[%o0+%o1] // ablegen subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen bne,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 2: retl _ mov -1,%o0 3: retl _ mov 0,%o0 #endif // extern uintD neg_loop_down (uintD* ptr, uintC count); DECLARE_FUNCTION(neg_loop_down) C(neg_loop_down:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count // erstes Digit /=0 suchen: brz,pn %o1,2f _ sub %o0,8,%o0 1: ldx [%o0],%o2 subcc %g0,%o2,%o2 bne,pn %xcc,3f _ subcc %o1,1,%o1 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov 0,%o0 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys stx %o2,[%o0] // 1 Digit negieren // alle anderen Digits invertieren: be,pn %xcc,5f _ sub %o0,8,%o0 4: ldx [%o0],%o2 subcc %o1,1,%o1 xnor %g0,%o2,%o2 stx %o2,[%o0] bne,pt %xcc,4b _ sub %o0,8,%o0 5: retl _ mov -1,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count // erstes Digit /=0 suchen: brz,pn %o1,2f _ sub %o0,8,%o0 sllx %o1,3,%o1 // %o1 = 8*count sub %o0,%o1,%o0 // %o0 = &ptr[-count-1] ldx [%o0+%o1],%o2 // digit holen 1: subcc %g0,%o2,%o2 // negieren, testen bne,pn %xcc,3f _ subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen bne,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 2: retl _ mov 0,%o0 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys // alle anderen Digits invertieren: add %o1,8,%o1 stx %o2,[%o0+%o1] // ablegen subcc %o1,8,%o1 be,pn %xcc,5f _ nop ldx [%o0+%o1],%o2 4: xnor %g0,%o2,%o2 stx %o2,[%o0+%o1] subcc %o1,8,%o1 bne,a,pt %xcc,4b __ ldx [%o0+%o1],%o2 5: retl _ mov -1,%o0 #endif // extern uintD shift1left_loop_down (uintD* ptr, uintC count); DECLARE_FUNCTION(shift1left_loop_down) C(shift1left_loop_down:) // Input in %o0,%o1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ mov 0,%o3 // Carry := 0 sub %o0,8,%o0 1: ldx [%o0],%o2 // Digit addcc %o2,%o2,%o4 // shiften add %o4,%o3,%o4 // und carry srlx %o2,63,%o3 // neues Carry stx %o4,[%o0] // Digit ablegen subcc %o1,1,%o1 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o3,%o0 // extern uintD shiftleft_loop_down (uintD* ptr, uintC count, uintC i, uintD carry); DECLARE_FUNCTION(shiftleft_loop_down) C(shiftleft_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %g0,%o2,%g1 // 64-i (mod 64) sub %o0,8,%o0 1: ldx [%o0],%o4 // Digit subcc %o1,1,%o1 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits or %o3,%o5,%o5 // mit dem alten Carry kombinieren stx %o5,[%o0] // Digit ablegen srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o3,%o0 // extern uintD shiftleftcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i); DECLARE_FUNCTION(shiftleftcopy_loop_down) C(shiftleftcopy_loop_down:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0 // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov 0,%o4 // Carry := 0 sub %g0,%o3,%g1 // 64-i (mod 64) sub %o0,8,%o0 1: ldx [%o0],%o5 // Digit subcc %o2,1,%o2 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits or %o4,%g2,%g2 // mit dem alten Carry kombinieren sub %o1,8,%o1 stx %g2,[%o1] // Digit ablegen srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o4,%o0 // extern uintD shift1right_loop_up (uintD* ptr, uintC count, uintD carry); DECLARE_FUNCTION(shift1right_loop_up) C(shift1right_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sllx %o2,63,%o2 // Carry 1: ldx [%o0],%o3 // Digit subcc %o1,1,%o1 srlx %o3,1,%o4 // shiften or %o2,%o4,%o4 // und mit altem Carry kombinieren stx %o4,[%o0] // und ablegen sllx %o3,63,%o2 // neuer Carry bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ mov %o2,%o0 // extern uintD shiftright_loop_up (uintD* ptr, uintC count, uintC i); DECLARE_FUNCTION(shiftright_loop_up) C(shiftright_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count sub %g0,%o2,%g1 // 64-i (mod 64) brz,pn %o1,2f _ or %g0,%g0,%o3 // Carry := 0 1: ldx [%o0],%o4 // Digit subcc %o1,1,%o1 srlx %o4,%o2,%o5 // shiften or %o3,%o5,%o5 // und mit altem Carry kombinieren stx %o5,[%o0] // und ablegen sllx %o4,%g1,%o3 // neuer Carry bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ mov %o3,%o0 // extern uintD shiftrightsigned_loop_up (uintD* ptr, uintC count, uintC i); DECLARE_FUNCTION(shiftrightsigned_loop_up) C(shiftrightsigned_loop_up:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count ldx [%o0],%o4 // erstes Digit sub %g0,%o2,%g1 // 64-i (mod 64) srax %o4,%o2,%o5 // shiften stx %o5,[%o0] // und ablegen sllx %o4,%g1,%o3 // neuer Carry subcc %o1,1,%o1 be,pn %xcc,2f _ add %o0,8,%o0 1: ldx [%o0],%o4 // Digit subcc %o1,1,%o1 srlx %o4,%o2,%o5 // shiften or %o3,%o5,%o5 // und mit altem Carry kombinieren stx %o5,[%o0] // und ablegen sllx %o4,%g1,%o3 // neuer Carry bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ mov %o3,%o0 // extern uintD shiftrightcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); DECLARE_FUNCTION(shiftrightcopy_loop_up) C(shiftrightcopy_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0 // srl %o2,0,%o2 // zero-extend %o2 = count sub %g0,%o3,%g1 // 64-i (mod 64) brz,pn %o2,2f _ sllx %o4,%g1,%g2 // erster Carry 1: ldx [%o0],%o4 // Digit add %o0,8,%o0 srlx %o4,%o3,%o5 // shiften or %g2,%o5,%o5 // und mit altem Carry kombinieren stx %o5,[%o1] // und ablegen sllx %o4,%g1,%g2 // neuer Carry subcc %o2,1,%o2 bne,pt %xcc,1b _ add %o1,8,%o1 2: retl _ mov %g2,%o0 // extern uintD mulusmall_loop_down (uintD digit, uintD* ptr, uintC len, uintD newdigit); DECLARE_FUNCTION(mulusmall_loop_down) C(mulusmall_loop_down:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1 // srl %o2,0,%o2 // zero-extend %o2 = len brz,pn %o2,2f _ sub %o1,8,%o1 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren // und kleinen Carry %o3 dazu: ldx [%o1],%o4 sub %o2,1,%o2 srlx %o4,32,%o5 // high32(x) srl %o4,0,%o4 // low32(x) mulx %o4,%o0,%o4 // low32(x)*digit mulx %o5,%o0,%o5 // high32(x)*digit sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32 add %g1,%o3,%g1 // plus carry addcc %o4,%g1,%o4 // plus low32(x)*digit srlx %o5,32,%o3 // high32(high32(x)*digit) add %o3,1,%g1 movcs %xcc,%g1,%o3 // neuer Carry stx %o4,[%o1] // neues Digit ablegen brnz,pt %o2,1b _ sub %o1,8,%o1 2: retl _ mov %o3,%o0 // extern void mulu_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); DECLARE_FUNCTION(mulu_loop_down) C(mulu_loop_down:) // Input in %i0,%i1,%i2,%i3 save %sp,-192,%sp mov 0,%l0 // Carry srlx %i0,32,%l1 // %l1 = high32(digit) srl %i0,0,%l2 // %l2 = low32(digit) mov 1,%l3 sllx %l3,32,%l3 // %l3 = 2^32 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr 1: sub %i2,8,%i2 ldx [%i1+%i2],%o0 // nächstes Digit subcc %i3,1,%i3 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 srlx %o0,32,%o1 srl %o0,0,%o2 mulx %l1,%o1,%o3 // high part mulx %l1,%o2,%o4 // first mid part mulx %l2,%o1,%o1 // second mid part mulx %l2,%o2,%o2 // low part srlx %o2,32,%o5 // low part's upper half add %o4,%o5,%o4 // add to one of the mid parts, no carry addcc %o4,%o1,%o4 // add other mid part add %o3,%l3,%o5 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part srlx %o4,32,%o5 sllx %o4,32,%o4 srl %o2,0,%o2 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) addcc %o0,%l0,%o0 // alten Carry addieren add %o3,%o5,%l0 // add high32(midparts) to high part add %l0,1,%o5 movcs %xcc,%o5,%l0 // neuer Carry // Multiplikation fertig brnz,pt %i3,1b _ stx %o0,[%i2] // Low-Digit ablegen stx %l0,[%i2-8] // letzten Carry ablegen ret _ restore // extern uintD muluadd_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); DECLARE_FUNCTION(muluadd_loop_down) C(muluadd_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0 save %sp,-192,%sp mov 0,%l0 // Carry srlx %i0,32,%l1 // %l1 = high32(digit) srl %i0,0,%l2 // %l2 = low32(digit) mov 1,%l3 sllx %l3,32,%l3 // %l3 = 2^32 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr 1: sub %i2,8,%i2 ldx [%i1+%i2],%o0 // nächstes Digit ldx [%i2],%i4 // *destptr subcc %i3,1,%i3 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 srlx %o0,32,%o1 srl %o0,0,%o2 mulx %l1,%o1,%o3 // high part mulx %l1,%o2,%o4 // first mid part mulx %l2,%o1,%o1 // second mid part mulx %l2,%o2,%o2 // low part srlx %o2,32,%o5 // low part's upper half add %o4,%o5,%o4 // add to one of the mid parts, no carry addcc %o4,%o1,%o4 // add other mid part add %o3,%l3,%o5 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part srlx %o4,32,%o5 sllx %o4,32,%o4 srl %o2,0,%o2 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) addcc %o0,%l0,%o0 // alten Carry addieren add %o3,%o5,%l0 // add high32(midparts) to high part add %l0,1,%o5 movcs %xcc,%o5,%l0 // neuer Carry // Multiplikation fertig addcc %i4,%o0,%o0 // alten *destptr addieren add %l0,1,%o2 movcs %xcc,%o2,%l0 // neuer Carry brnz,pt %i3,1b _ stx %o0,[%i2] // Low-Digit ablegen mov %l0,%i0 // letzter Carry ret _ restore // extern uintD mulusub_loop_down (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); DECLARE_FUNCTION(mulusub_loop_down) C(mulusub_loop_down:) // Input in %i0,%i1,%i2,%i3, Output in %i0 save %sp,-192,%sp mov 0,%l0 // Carry srlx %i0,32,%l1 // %l1 = high32(digit) srl %i0,0,%l2 // %l2 = low32(digit) mov 1,%l3 sllx %l3,32,%l3 // %l3 = 2^32 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr 1: sub %i2,8,%i2 ldx [%i1+%i2],%o0 // nächstes Digit ldx [%i2],%i4 // *destptr subcc %i3,1,%i3 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 srlx %o0,32,%o1 srl %o0,0,%o2 mulx %l1,%o1,%o3 // high part mulx %l1,%o2,%o4 // first mid part mulx %l2,%o1,%o1 // second mid part mulx %l2,%o2,%o2 // low part srlx %o2,32,%o5 // low part's upper half add %o4,%o5,%o4 // add to one of the mid parts, no carry addcc %o4,%o1,%o4 // add other mid part add %o3,%l3,%o5 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part srlx %o4,32,%o5 sllx %o4,32,%o4 srl %o2,0,%o2 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) addcc %o0,%l0,%o0 // alten Carry addieren add %o3,%o5,%l0 // add high32(midparts) to high part add %l0,1,%o5 movcs %xcc,%o5,%l0 // neuer Carry // Multiplikation fertig subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren add %l0,1,%o2 movcs %xcc,%o2,%l0 // neuer Carry brnz,pt %i3,1b _ stx %o0,[%i2] // Low-Digit ablegen mov %l0,%i0 // letzter Carry ret _ restore #endif #if !CL_DS_BIG_ENDIAN_P // extern void or_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(or_loop_down) C(or_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 or %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen or %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void xor_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(xor_loop_down) C(xor_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 xor %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen xor %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void and_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(and_loop_down) C(and_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 and %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen and %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void eqv_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(eqv_loop_down) C(eqv_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 xnor %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen xnor %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void nand_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(nand_loop_down) C(nand_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 and %o3,%o4,%o3 // verknüpfen xnor %g0,%o3,%o3 stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen and %o4,%o3,%o3 // beide verknüpfen xnor %g0,%o3,%o3 bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void nor_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(nor_loop_down) C(nor_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 or %o3,%o4,%o3 // verknüpfen xnor %g0,%o3,%o3 stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen or %o4,%o3,%o3 // beide verknüpfen xnor %g0,%o3,%o3 bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void andc2_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(andc2_loop_down) C(andc2_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 andn %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen andn %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void orc2_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(orc2_loop_down) C(orc2_loop_down:) // Input in %o0,%o1,%o2 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %o1,%o0,%o1 // %o1 = yptr-xptr sub %o0,8,%o0 1: ldx [%o0],%o3 // *xptr ldx [%o0+%o1],%o4 // *yptr subcc %o2,1,%o2 orn %o3,%o4,%o3 // verknüpfen stx %o3,[%o0] // =: *xptr bne,pt %xcc,1b _ sub %o0,8,%o0 // xptr++, yptr++ 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] 1: subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen ldx [%o1+%o2],%o3 // nächstes Digit holen ldx [%o0+%o2],%o4 // noch ein Digit holen orn %o4,%o3,%o3 // beide verknüpfen bne,pt %xcc,1b _ stx %o3,[%o1+%o2] // Digit ablegen 2: retl _ nop #endif // extern void not_loop_down (uintD* xptr, uintC count); DECLARE_FUNCTION(not_loop_down) C(not_loop_down:) // Input in %o0,%o1 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %o0,8,%o0 1: ldx [%o0],%o2 subcc %o1,1,%o1 xnor %g0,%o2,%o2 stx %o2,[%o0] bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ nop #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sllx %o1,3,%o1 // %o1 = 8*count sub %o0,%o1,%o0 // %o0 = &destptr[-count] 1: subcc %o1,8,%o1 // Zähler erniedrigen, Pointer erniedrigen ldx [%o0+%o1],%o2 // nächstes Digit holen xnor %g0,%o2,%o2 bne,pt %xcc,1b _ stx %o2,[%o0+%o1] // Digit ablegen 2: retl _ nop #endif // extern boolean and_test_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(and_test_loop_down) C(and_test_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,4f _ sub %o0,8,%o0 1: ldx [%o0],%o3 sub %o1,8,%o1 ldx [%o1],%o4 subcc %o2,1,%o2 be,pn %xcc,3f _ andcc %o3,%o4,%g0 be,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov 1,%o0 3: bne 2b _ nop 4: retl _ mov 0,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] subcc %o2,8,%o2 bcs,pn %xcc,2f _ nop ldx [%o0+%o2],%o3 // nächstes Digit holen 1: ldx [%o1+%o2],%o4 // noch ein Digit holen andcc %o3,%o4,%g0 // beide verknüpfen bne,pn %xcc,3f _ subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen bcc,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // nächstes Digit holen 2: retl _ mov 0,%o0 3: retl _ mov 1,%o0 #endif // extern cl_signean compare_loop_down (uintD* xptr, uintD* yptr, uintC count); DECLARE_FUNCTION(compare_loop_down) C(compare_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ nop 1: ldx [%o0-8],%o3 ldx [%o1-8],%o4 subcc %o3,%o4,%g0 bne,pn %xcc,3f _ sub %o0,8,%o0 subcc %o2,1,%o2 bne,pn %xcc,1b _ sub %o1,8,%o1 2: retl _ mov 0,%o0 3: mov 1,%o0 movlu %xcc,-1,%o0 retl _ sra %o0,0,%o0 // sign-extend %o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count sllx %o2,3,%o2 // %o2 = 8*count sub %o0,%o2,%o0 // %o0 = &xptr[-count] sub %o1,%o2,%o1 // %o1 = &yptr[-count] subcc %o2,8,%o2 bcs,pn %xcc,4f _ nop ldx [%o0+%o2],%o3 // nächstes Digit holen 1: ldx [%o1+%o2],%o4 // noch ein Digit holen subcc %o2,8,%o2 // Zähler erniedrigen, Pointer erniedrigen bcs,pn %xcc,3f _ subcc %o3,%o4,%g0 // vergleichen be,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // nächstes Digit holen 2: mov 1,%o0 movlu %xcc,-1,%o0 retl _ sra %o0,0,%o0 // sign-extend %o0 3: bne 2b _ nop 4: retl _ mov 0,%o0 #endif // extern uintD add_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); DECLARE_FUNCTION(add_loop_up) C(add_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 #if STANDARD_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 1: ldx [%o0],%o4 // source1-digit add %o0,8,%o0 ldx [%o1],%o5 // source2-digit add %o1,8,%o1 addcc %o4,%g1,%o4 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 addcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 stx %o4,[%o2] // Digit ablegen subcc %o3,1,%o3 bne,pt %xcc,1b _ add %o2,8,%o2 2: retl _ mov %g1,%o0 #endif #if COUNTER_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 sub %g0,%o3,%o3 // %o3 = -count sllx %o3,3,%o3 // %o3 = -8*count sub %o2,8,%o2 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] sub %o2,%o3,%o2 // %o2 = &destptr[count-1] 1: ldx [%o0+%o3],%o4 // source1-digit ldx [%o1+%o3],%o5 // source2-digit addcc %o4,%g1,%o4 movcc %xcc,0,%g1 // %g1|%o4 := %o4 + alter Carry %g1 addcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %g1|%o4 := %o4 + alter Carry %g1 + %o5 addcc %o3,8,%o3 // Zähler erniedrigen, Pointer erhöhen bne,pt %xcc,1b _ stx %o4,[%o2+%o3] // Digit ablegen 2: retl _ mov %g1,%o0 #endif // extern uintD addto_loop_up (uintD* sourceptr, uintD* destptr, uintC count); DECLARE_FUNCTION(addto_loop_up) C(addto_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 1: ldx [%o0],%o3 // source-digit add %o0,8,%o0 ldx [%o1],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 addcc %o3,%o4,%o4 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 stx %o4,[%o1] // Digit ablegen subcc %o2,1,%o2 bne,pt %xcc,1b _ add %o1,8,%o1 2: retl _ mov %o5,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &sourceptr[count] sub %o1,%o2,%o1 // %o1 = &destptr[count] ldx [%o0+%o2],%o3 // source-digit 1: ldx [%o1+%o2],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 addcc %o3,%o4,%o4 movcs %xcc,1,%o5 // %o5|%o4 := %o3 + alter Carry %o5 + %o4 stx %o4,[%o1+%o2] // Digit ablegen addcc %o2,8,%o2 // Zähler erniedrigen, Pointer erhöhen bne,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // source-digit 2: retl _ mov %o5,%o0 #endif // extern uintD inc_loop_up (uintD* ptr, uintC count); DECLARE_FUNCTION(inc_loop_up) C(inc_loop_up:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ nop ldx [%o0],%o2 1: add %o0,8,%o0 addcc %o2,1,%o2 bne,pn %xcc,3f _ stx %o2,[%o0-8] subcc %o1,1,%o1 bne,a,pt %xcc,1b __ ldx [%o0],%o2 2: retl _ mov 1,%o0 3: retl _ mov 0,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %g0,%o1,%o1 // %o1 = -count sllx %o1,3,%o1 // %o1 = -8*count sub %o0,%o1,%o0 // %o0 = &ptr[count] ldx [%o0+%o1],%o2 // digit holen 1: addcc %o2,1,%o2 // incrementieren bne,pn %xcc,3f _ stx %o2,[%o0+%o1] // ablegen addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen bne,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 2: retl _ mov 1,%o0 3: retl _ mov 0,%o0 #endif // extern uintD sub_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count); DECLARE_FUNCTION(sub_loop_up) C(sub_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 #if STANDARD_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 1: ldx [%o0],%o4 // source1-digit add %o0,8,%o0 ldx [%o1],%o5 // source2-digit add %o1,8,%o1 addcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 stx %o4,[%o2] // Digit ablegen subcc %o3,1,%o3 bne,pt %xcc,1b _ add %o2,8,%o2 2: retl _ mov %g1,%o0 #endif #if COUNTER_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %g0,%g1 // Carry := 0 sub %g0,%o3,%o3 // %o3 = -count sllx %o3,3,%o3 // %o3 = -8*count sub %o2,8,%o2 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] sub %o2,%o3,%o2 // %o2 = &destptr[count-1] 1: ldx [%o1+%o3],%o5 // source2-digit ldx [%o0+%o3],%o4 // source1-digit addcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %g1|%o5 := %o5 + alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,1,%g1 // %o4-2^64*%g1 := %o4 - %o5 - alter Carry %g1 addcc %o3,8,%o3 bne,pt %xcc,1b _ stx %o4,[%o2+%o3] // Digit ablegen 2: retl _ mov %g1,%o0 #endif // extern uintD subx_loop_up (uintD* sourceptr1, uintD* sourceptr2, uintD* destptr, uintC count, uintD carry); DECLARE_FUNCTION(subx_loop_up) C(subx_loop_up:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1, Output in %o0 #if STANDARD_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %o4,%g1 // Carry (0 oder -1) 1: ldx [%o0],%o4 // source1-digit add %o0,8,%o0 ldx [%o1],%o5 // source2-digit add %o1,8,%o1 subcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 stx %o4,[%o2] // Digit ablegen subcc %o3,1,%o3 bne,pt %xcc,1b _ add %o2,8,%o2 2: retl _ mov %g1,%o0 #endif #if COUNTER_LOOPS // srl %o3,0,%o3 // zero-extend %o3 = count brz,pn %o3,2f _ mov %o4,%g1 // Carry (0 oder -1) sub %g0,%o3,%o3 // %o3 = -count sllx %o3,3,%o3 // %o3 = -8*count sub %o2,8,%o2 sub %o0,%o3,%o0 // %o0 = &sourceptr1[count] sub %o1,%o3,%o1 // %o1 = &sourceptr2[count] sub %o2,%o3,%o2 // %o2 = &destptr[count-1] 1: ldx [%o1+%o3],%o5 // source2-digit ldx [%o0+%o3],%o4 // source1-digit subcc %o5,%g1,%o5 movcc %xcc,0,%g1 // %o5-2^64*%g1 := %o5 - alter Carry %g1 subcc %o4,%o5,%o4 movcs %xcc,-1,%g1 // %o4+2^64*%g1 := %o4 - %o5 + alter Carry %g1 addcc %o3,8,%o3 bne,pt %xcc,1b _ stx %o4,[%o2+%o3] // Digit ablegen 2: retl _ mov %g1,%o0 #endif // extern uintD subfrom_loop_up (uintD* sourceptr, uintD* destptr, uintC count); DECLARE_FUNCTION(subfrom_loop_up) C(subfrom_loop_up:) // Input in %o0,%o1,%o2, Output in %o0 #if STANDARD_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 1: ldx [%o0],%o3 // source-digit add %o0,8,%o0 ldx [%o1],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 subcc %o4,%o3,%o4 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 stx %o4,[%o1] // Digit ablegen subcc %o2,1,%o2 bne,pt %xcc,1b _ add %o1,8,%o1 2: retl _ mov %o5,%o0 #endif #if COUNTER_LOOPS // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov %g0,%o5 // Carry := 0 sub %g0,%o2,%o2 // %o2 = -count sllx %o2,3,%o2 // %o2 = -8*count sub %o0,%o2,%o0 // %o0 = &sourceptr[count] sub %o1,%o2,%o1 // %o1 = &destptr[count] ldx [%o0+%o2],%o3 // source-digit 1: ldx [%o1+%o2],%o4 // dest-digit addcc %o3,%o5,%o3 movcc %xcc,0,%o5 // %o5|%o3 := %o3 + alter Carry %o5 subcc %o4,%o3,%o4 movcs %xcc,1,%o5 // %o4-2^64*%o5 := %o4 - %o3 - alter Carry %o5 stx %o4,[%o1+%o2] // Digit ablegen addcc %o2,8,%o2 bne,a,pt %xcc,1b __ ldx [%o0+%o2],%o3 // source-digit 2: retl _ mov %o5,%o0 #endif // extern uintD dec_loop_up (uintD* ptr, uintC count); DECLARE_FUNCTION(dec_loop_up) C(dec_loop_up:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ nop ldx [%o0],%o2 1: add %o0,8,%o0 subcc %o2,1,%o2 bcc,pn %xcc,3f _ stx %o2,[%o0-8] subcc %o1,1,%o1 bne,a,pt %xcc,1b __ ldx [%o0],%o2 2: retl _ mov -1,%o0 3: retl _ mov 0,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %g0,%o1,%o1 // %o1 = -count sllx %o1,3,%o1 // %o1 = -8*count sub %o0,%o1,%o0 // %o0 = &ptr[count] ldx [%o0+%o1],%o2 // digit holen 1: subcc %o2,1,%o2 // decrementieren bcc,pn %xcc,3f _ stx %o2,[%o0+%o1] // ablegen addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen bne,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 2: retl _ mov -1,%o0 3: retl _ mov 0,%o0 #endif // extern uintD neg_loop_up (uintD* ptr, uintC count); DECLARE_FUNCTION(neg_loop_up) C(neg_loop_up:) // Input in %o0,%o1, Output in %o0 #if STANDARD_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count // erstes Digit /=0 suchen: brz,pn %o1,2f _ add %o0,8,%o0 1: ldx [%o0-8],%o2 subcc %g0,%o2,%o2 bne,pn %xcc,3f _ subcc %o1,1,%o1 bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ mov 0,%o0 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys // 1 Digit negieren, alle anderen Digits invertieren: be,pn %xcc,5f _ stx %o2,[%o0-8] 4: ldx [%o0],%o2 subcc %o1,1,%o1 xnor %g0,%o2,%o2 stx %o2,[%o0] bne,pt %xcc,4b _ add %o0,8,%o0 5: retl _ mov -1,%o0 #endif #if COUNTER_LOOPS // srl %o1,0,%o1 // zero-extend %o1 = count // erstes Digit /=0 suchen: brz,pn %o1,2f _ sub %g0,%o1,%o1 // %o1 = -count sllx %o1,3,%o1 // %o1 = -8*count sub %o0,%o1,%o0 // %o0 = &ptr[count] ldx [%o0+%o1],%o2 // digit holen 1: subcc %g0,%o2,%o2 // negieren, testen bne,pn %xcc,3f _ addcc %o1,8,%o1 // Zähler erniedrigen, Pointer erhöhen bne,a,pt %xcc,1b __ ldx [%o0+%o1],%o2 2: retl _ mov 0,%o0 3: // erstes Digit /=0 gefunden, ab jetzt gibt's Carrys // alle anderen Digits invertieren: sub %o1,8,%o1 stx %o2,[%o0+%o1] // ablegen addcc %o1,8,%o1 be,pn %xcc,5f _ nop ldx [%o0+%o1],%o2 4: xnor %g0,%o2,%o2 stx %o2,[%o0+%o1] addcc %o1,8,%o1 bne,a,pt %xcc,4b __ ldx [%o0+%o1],%o2 5: retl _ mov -1,%o0 #endif // extern uintD shift1left_loop_up (uintD* ptr, uintC count); DECLARE_FUNCTION(shift1left_loop_up) C(shift1left_loop_up:) // Input in %o0,%o1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ mov 0,%o3 // Carry := 0 1: ldx [%o0],%o2 // Digit addcc %o2,%o2,%o4 // shiften add %o4,%o3,%o4 // und carry srlx %o2,63,%o3 // neues Carry stx %o4,[%o0] // Digit ablegen subcc %o1,1,%o1 bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ mov %o3,%o0 // extern uintD shiftleft_loop_up (uintD* ptr, uintC count, uintC i, uintD carry); DECLARE_FUNCTION(shiftleft_loop_up) C(shiftleft_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sub %g0,%o2,%g1 // 64-i (mod 64) 1: ldx [%o0],%o4 // Digit subcc %o1,1,%o1 sllx %o4,%o2,%o5 // dessen niedere (64-i) Bits or %o3,%o5,%o5 // mit dem alten Carry kombinieren stx %o5,[%o0] // Digit ablegen srlx %o4,%g1,%o3 // dessen höchste i Bits liefern den neuen Carry bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ mov %o3,%o0 #endif // extern uintD shiftleftcopy_loop_up (uintD* sourceptr, uintD* destptr, uintC count, uintC i); DECLARE_FUNCTION(shiftleftcopy_loop_up) C(shiftleftcopy_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2, Output in %o0 // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ mov 0,%o4 // Carry := 0 sub %g0,%o3,%g1 // 64-i (mod 64) 1: ldx [%o0],%o5 // Digit subcc %o2,1,%o2 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits or %o4,%g2,%g2 // mit dem alten Carry kombinieren stx %g2,[%o1] // Digit ablegen add %o1,8,%o1 srlx %o5,%g1,%o4 // dessen höchste i Bits liefern den neuen Carry bne,pt %xcc,1b _ add %o0,8,%o0 2: retl _ mov %o4,%o0 #if !CL_DS_BIG_ENDIAN_P // extern uintD shift1right_loop_down (uintD* ptr, uintC count, uintD carry); DECLARE_FUNCTION(shift1right_loop_down) C(shift1right_loop_down:) // Input in %o0,%o1,%o2, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count brz,pn %o1,2f _ sllx %o2,63,%o2 // Carry sub %o0,8,%o0 1: ldx [%o0],%o3 // Digit subcc %o1,1,%o1 srlx %o3,1,%o4 // shiften or %o2,%o4,%o4 // und mit altem Carry kombinieren stx %o4,[%o0] // und ablegen sllx %o3,63,%o2 // neuer Carry bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o2,%o0 // extern uintD shiftright_loop_down (uintD* ptr, uintC count, uintC i); DECLARE_FUNCTION(shiftright_loop_down) C(shiftright_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count sub %g0,%o2,%g1 // 64-i (mod 64) brz,pn %o1,2f _ or %g0,%g0,%o3 // Carry := 0 sub %o0,8,%o0 1: ldx [%o0],%o4 // Digit subcc %o1,1,%o1 srlx %o4,%o2,%o5 // shiften or %o3,%o5,%o5 // und mit altem Carry kombinieren stx %o5,[%o0] // und ablegen sllx %o4,%g1,%o3 // neuer Carry bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o3,%o0 // extern uintD shiftrightsigned_loop_down (uintD* ptr, uintC count, uintC i); DECLARE_FUNCTION(shiftrightsigned_loop_down) C(shiftrightsigned_loop_down:) // Input in %o0,%o1,%o2, verändert %g1, Output in %o0 // srl %o1,0,%o1 // zero-extend %o1 = count ldx [%o0-8],%o4 // erstes Digit sub %g0,%o2,%g1 // 64-i (mod 64) srax %o4,%o2,%o5 // shiften stx %o5,[%o0-8] // und ablegen sllx %o4,%g1,%o3 // neuer Carry subcc %o1,1,%o1 be,pn %xcc,2f _ sub %o0,16,%o0 1: ldx [%o0],%o4 // Digit subcc %o1,1,%o1 srlx %o4,%o2,%o5 // shiften or %o3,%o5,%o5 // und mit altem Carry kombinieren stx %o5,[%o0] // und ablegen sllx %o4,%g1,%o3 // neuer Carry bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %o3,%o0 // extern uintD shiftrightcopy_loop_down (uintD* sourceptr, uintD* destptr, uintC count, uintC i, uintD carry); DECLARE_FUNCTION(shiftrightcopy_loop_down) C(shiftrightcopy_loop_down:) // Input in %o0,%o1,%o2,%o3,%o4, verändert %g1,%g2, Output in %o0 // srl %o2,0,%o2 // zero-extend %o2 = count sub %g0,%o3,%g1 // 64-i (mod 64) brz,pn %o2,2f _ sllx %o4,%g1,%g2 // erster Carry sub %o0,8,%o0 1: ldx [%o0],%o4 // Digit sub %o1,8,%o1 srlx %o4,%o3,%o5 // shiften or %g2,%o5,%o5 // und mit altem Carry kombinieren stx %o5,[%o1] // und ablegen sllx %o4,%g1,%g2 // neuer Carry subcc %o2,1,%o2 bne,pt %xcc,1b _ sub %o0,8,%o0 2: retl _ mov %g2,%o0 // extern uintD mulusmall_loop_up (uintD digit, uintD* ptr, uintC len, uintD newdigit); DECLARE_FUNCTION(mulusmall_loop_up) C(mulusmall_loop_up:) // Input in %o0,%o1,%o2,%o3, Output in %o0, verändert %g1 // srl %o2,0,%o2 // zero-extend %o2 = len brz,pn %o2,2f _ nop 1: // nächstes Digit [%o1] mit der 6-Bit-Zahl %o0 multiplizieren // und kleinen Carry %o3 dazu: ldx [%o1],%o4 sub %o2,1,%o2 srlx %o4,32,%o5 // high32(x) srl %o4,0,%o4 // low32(x) mulx %o4,%o0,%o4 // low32(x)*digit mulx %o5,%o0,%o5 // high32(x)*digit sllx %o5,32,%g1 // low32(high32(x)*digit)*2^32 add %g1,%o3,%g1 // plus carry addcc %o4,%g1,%o4 // plus low32(x)*digit srlx %o5,32,%o3 // high32(high32(x)*digit) add %o3,1,%g1 movcs %xcc,%g1,%o3 // neuer Carry stx %o4,[%o1] // neues Digit ablegen brnz,pt %o2,1b _ add %o1,8,%o1 2: retl _ mov %o3,%o0 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); DECLARE_FUNCTION(mulu_loop_up) C(mulu_loop_up:) // Input in %i0,%i1,%i2,%i3 save %sp,-192,%sp mov 0,%l0 // Carry srlx %i0,32,%l1 // %l1 = high32(digit) srl %i0,0,%l2 // %l2 = low32(digit) mov 1,%l3 sllx %l3,32,%l3 // %l3 = 2^32 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr 1: ldx [%i1+%i2],%o0 // nächstes Digit subcc %i3,1,%i3 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 srlx %o0,32,%o1 srl %o0,0,%o2 mulx %l1,%o1,%o3 // high part mulx %l1,%o2,%o4 // first mid part mulx %l2,%o1,%o1 // second mid part mulx %l2,%o2,%o2 // low part srlx %o2,32,%o5 // low part's upper half add %o4,%o5,%o4 // add to one of the mid parts, no carry addcc %o4,%o1,%o4 // add other mid part add %o3,%l3,%o5 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part srlx %o4,32,%o5 sllx %o4,32,%o4 srl %o2,0,%o2 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) addcc %o0,%l0,%o0 // alten Carry addieren add %o3,%o5,%l0 // add high32(midparts) to high part add %l0,1,%o5 movcs %xcc,%o5,%l0 // neuer Carry // Multiplikation fertig stx %o0,[%i2] // Low-Digit ablegen brnz,pt %i3,1b _ add %i2,8,%i2 stx %l0,[%i2] // letzten Carry ablegen ret _ restore // extern uintD muluadd_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); DECLARE_FUNCTION(muluadd_loop_up) C(muluadd_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0 save %sp,-192,%sp mov 0,%l0 // Carry srlx %i0,32,%l1 // %l1 = high32(digit) srl %i0,0,%l2 // %l2 = low32(digit) mov 1,%l3 sllx %l3,32,%l3 // %l3 = 2^32 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr 1: ldx [%i1+%i2],%o0 // nächstes Digit ldx [%i2],%i4 // *destptr subcc %i3,1,%i3 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 srlx %o0,32,%o1 srl %o0,0,%o2 mulx %l1,%o1,%o3 // high part mulx %l1,%o2,%o4 // first mid part mulx %l2,%o1,%o1 // second mid part mulx %l2,%o2,%o2 // low part srlx %o2,32,%o5 // low part's upper half add %o4,%o5,%o4 // add to one of the mid parts, no carry addcc %o4,%o1,%o4 // add other mid part add %o3,%l3,%o5 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part srlx %o4,32,%o5 sllx %o4,32,%o4 srl %o2,0,%o2 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) addcc %o0,%l0,%o0 // alten Carry addieren add %o3,%o5,%l0 // add high32(midparts) to high part add %l0,1,%o5 movcs %xcc,%o5,%l0 // neuer Carry // Multiplikation fertig addcc %i4,%o0,%o0 // alten *destptr addieren add %l0,1,%o2 movcs %xcc,%o2,%l0 // neuer Carry stx %o0,[%i2] // Low-Digit ablegen brnz,pt %i3,1b _ add %i2,8,%i2 mov %l0,%i0 // letzter Carry ret _ restore // extern uintD mulusub_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len); DECLARE_FUNCTION(mulusub_loop_up) C(mulusub_loop_up:) // Input in %i0,%i1,%i2,%i3, Output in %i0 save %sp,-192,%sp mov 0,%l0 // Carry srlx %i0,32,%l1 // %l1 = high32(digit) srl %i0,0,%l2 // %l2 = low32(digit) mov 1,%l3 sllx %l3,32,%l3 // %l3 = 2^32 sub %i1,%i2,%i1 // %i1 = sourceptr - destptr 1: ldx [%i1+%i2],%o0 // nächstes Digit ldx [%i2],%i4 // *destptr subcc %i3,1,%i3 // mit digit multiplizieren: (%l1*2^32+%l2) * %o0 + %l0 -> %l0|%o0 srlx %o0,32,%o1 srl %o0,0,%o2 mulx %l1,%o1,%o3 // high part mulx %l1,%o2,%o4 // first mid part mulx %l2,%o1,%o1 // second mid part mulx %l2,%o2,%o2 // low part srlx %o2,32,%o5 // low part's upper half add %o4,%o5,%o4 // add to one of the mid parts, no carry addcc %o4,%o1,%o4 // add other mid part add %o3,%l3,%o5 movcs %xcc,%o5,%o3 // if carry, add 2^32 to the high part srlx %o4,32,%o5 sllx %o4,32,%o4 srl %o2,0,%o2 add %o2,%o4,%o0 // combine low32(midparts) and low32(lowpart) addcc %o0,%l0,%o0 // alten Carry addieren add %o3,%o5,%l0 // add high32(midparts) to high part add %l0,1,%o5 movcs %xcc,%o5,%l0 // neuer Carry // Multiplikation fertig subcc %i4,%o0,%o0 // vom alten *destptr subtrahieren add %l0,1,%o2 movcs %xcc,%o2,%l0 // neuer Carry stx %o0,[%i2] // Low-Digit ablegen brnz,pt %i3,1b _ add %i2,8,%i2 mov %l0,%i0 // letzter Carry ret _ restore #endif // extern void shiftxor_loop_up (uintD* xptr, const uintD* yptr, uintC count, uintC i); DECLARE_FUNCTION(shiftxor_loop_up) C(shiftxor_loop_up:) // Input in %o0,%o1,%o2,%o3, verändert %g1,%g2 // srl %o2,0,%o2 // zero-extend %o2 = count brz,pn %o2,2f _ sub %g0,%o3,%g1 // 64-i (mod 64) sub %o1,%o0,%o1 ldx [%o0],%o4 // *xptr holen 1: ldx [%o0+%o1],%o5 // *yptr holen subcc %o2,1,%o2 sllx %o5,%o3,%g2 // dessen niedere (64-i) Bits xor %o4,%g2,%o4 // mit dem modifizierten *xptr kombinieren stx %o4,[%o0] // und ablegen add %o0,8,%o0 srlx %o5,%g1,%g2 // höchste i Bits von *yptr ldx [%o0],%o4 // schon mal mit dem nächsten *xptr bne,pt %xcc,1b _ xor %o4,%g2,%o4 // verknüpfen stx %o4,[%o0] // und ablegen 2: retl _ nop