This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Bug in ARM implementation of modulo functions for libgcc
- To: gcc-patches at gcc dot gnu dot org
- Subject: Bug in ARM implementation of modulo functions for libgcc
- From: Nick Clifton <nickc at redhat dot com>
- Date: Tue, 15 Aug 2000 17:48:16 -0700
Hi Guys,
Below is a testcase and patch to fix a bug recently discovered in
the implementations of __umodsi3 and __modsi3 for the ARM port. If
these functions were given a very large dividend (eg 0x50000000) and
a very small divisor (eg 2) they would end up erroneously adding
back in one or more of the subtractions, producing a result that was
a) wrong
b) bigger than the divisor.
Any objections to my applying this patch and adding the test case ?
Cheers
Nick
gcc/testsuite/ChangLog
2000-08-15 Nick Clifton <nickc@redhat.com>
* gcc.c-torture/execute/20000815-1.c: New test. Used to
trigger bug in implementations of __modi3 and __umodsi3 for
the ARM port.
gcc/ChangeLog
2000-08-15 Nick Clifton <nickc@redhat.com>
* config/arm/lib1funcs.asm (__umodi3): If dividend is reduced
to zero, terminate early by branching to end of code, rather
than dropping through.
(__modis3): The same.
*** /dev/null Tue May 5 13:32:27 1998
--- gcc/testsuite/gcc.c-torture/execute/20000815-1.c Tue Aug 15 17:24:56 2000
***************
*** 0 ****
--- 1,23 ----
+ int a = 0x50000000;
+ int b = 2;
+ unsigned int c = 0x50000000;
+ unsigned int d = 2;
+
+ int
+ main (void)
+ {
+ int mod1;
+ unsigned int mod2;
+
+ mod1 = a % b;
+
+ if (mod1 >= b)
+ abort ();
+
+ mod2 = c % d;
+
+ if (mod2 >= d)
+ abort ();
+
+ exit (0);
+ }
Index: gcc/config/arm/lib1funcs.asm
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/arm/lib1funcs.asm,v
retrieving revision 1.11
diff -p -r1.11 lib1funcs.asm
*** lib1funcs.asm 2000/08/11 00:30:55 1.11
--- lib1funcs.asm 2000/08/16 00:42:40
*************** Loop3:
*** 482,487 ****
--- 482,488 ----
orrcs overdone, overdone, curbit, ror #3
mov ip, curbit
cmp dividend, #0 @ Early termination?
+ RETc(eq) @ No fixups needed
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
movne divisor, divisor, lsr #4
bne Loop3
*************** Loop3:
*** 489,497 ****
@ Any subtractions that we should not have done will be recorded in
@ the top three bits of "overdone". Exactly which were not needed
@ are governed by the position of the bit, stored in ip.
- @ If we terminated early, because dividend became zero,
- @ then none of the below will match, since the bit in ip will not be
- @ in the bottom nibble.
ands overdone, overdone, #0xe0000000
RETc(eq) @ No fixups needed
tst overdone, ip, ror #3
--- 490,495 ----
*************** Loop3:
*** 888,893 ****
--- 886,892 ----
orrcs overdone, overdone, curbit, ror #3
mov ip, curbit
cmp dividend, #0 @ Early termination?
+ beq Lgot_result @ No fixups needed
movnes curbit, curbit, lsr #4 @ No, any more bits to do?
movne divisor, divisor, lsr #4
bne Loop3
*************** Loop3:
*** 895,903 ****
@ Any subtractions that we should not have done will be recorded in
@ the top three bits of "overdone". Exactly which were not needed
@ are governed by the position of the bit, stored in ip.
- @ If we terminated early, because dividend became zero,
- @ then none of the below will match, since the bit in ip will not be
- @ in the bottom nibble.
ands overdone, overdone, #0xe0000000
beq Lgot_result
tst overdone, ip, ror #3
--- 894,899 ----