]> www.ginac.de Git - cln.git/commitdiff
Fix ARM implementation of mulusmall_loop_up(digit, ptr, len, newdigit)...
authorRichard Kreckel <kreckel@ginac.de>
Sat, 23 Apr 2022 23:14:14 +0000 (01:14 +0200)
committerRichard Kreckel <kreckel@ginac.de>
Sat, 23 Apr 2022 23:14:14 +0000 (01:14 +0200)
...by removing the shortcut for small 'digit' and calling
mulu32_64_vregs instead (which handles digits >= 2^16 fine).

The requirement that 'digit' be small (<= 36) is documented in cl_DS.h
but nowhere enforced. Indeed, it is clearly violated in the base-N
input function digits_to_I_baseN().

I am not sure what to do. This ARM asm seems to be the only code which
relies on small 'digit'. A future patch should either fix the input
method to guarntee that 'digit' is small or accept that it can be
large and remove the shortcut in mulusmall_loop_up for good (and also
fix the comments in cl_DS.h).

src/base/digitseq/cl_asm_arm_.cc
src/integer/conv/cl_I_from_digits.cc

index 0e23d9a6eb385ff4ac484df6c965964b5eb8df20..75ce5db1f64bd84e7e451240002ea408fa53e51e 100644 (file)
@@ -3278,12 +3278,15 @@ LABEL(mulusmall_loop_up_l1)
         MOV     a1,a4                   // return carry
         LDMFD   sp!,{v1,pc}
 #else
-        STMFD   sp!,{v1-v2,lr}
+        STMFD   sp!,{v1-v4,lr}
 LABEL(mulusmall_loop_up_l1)
         LDR     ip,[a2]
 
-//      BL      mulu32_64_vregs         // muluD(digit,*ptr,hi=,lo=)
-// replaced by multiplication of a small x = a1 and a big y = ip :
+#if 1
+        BL      mulu32_64_vregs         // muluD(digit,*ptr,hi=,lo=)
+#else
+// this code requires that digit is small, but this condition is violated in
+// digits_to_I_baseN(const char * MSBptr, uintC len, uintD base)
         MOV     v1,ip,LSR #16           // top half of y
         BIC     ip,ip,v1,LSL #16        // bottom half of y
         MUL     v2,a1,v1                // middle section of result
@@ -3291,14 +3294,14 @@ LABEL(mulusmall_loop_up_l1)
         MOV     ip,#0                   // high section of result
         ADDS    v1,v1,v2,LSL #16        // bottom 32 bits of result
         ADC     ip,ip,v2,LSR #16        // top 32 bits of result
-
+#endif
         ADDS    v1,v1,a4                // lo += carry
         ADC     a4,ip,#0                // if (lo<carry) { hi += 1 }; carry=hi
         STR     v1,[a2],#4              // *ptr++ = lo
         SUBS    a3,a3,#1                // len--
         BNE     mulusmall_loop_up_l1    // until len==0
         MOV     a1,a4                   // return carry
-        LDMFD   sp!,{v1-v2,pc}
+        LDMFD   sp!,{v1-v4,pc}
 #endif
 
 // extern void mulu_loop_up (uintD digit, uintD* sourceptr, uintD* destptr, uintC len);
index 681c51dde796a72f7ad30cb809b20cf5aa6cc1c5..1819f5e89ea0eb4d94a17ffc76661424ea322500 100644 (file)
@@ -134,6 +134,7 @@ static const cl_I digits_to_I_baseN (const char * MSBptr, uintC len, uintD base)
                        chx++;
                        len--;
                }
+               // FIXME: mulusmall_loop_up/down are documented to require a small factor (<= 36).
                var uintD carry = mulusmall_loop_lsp(factor,erg_LSDptr,erg_len,newdigit);
                if (carry!=0) {
                        // need to extend NUDS: