This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Bug in ARM implementation of modulo functions for libgcc


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 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]