Supply signed division to fix ARM compilation.

Previously we supplied only unsigned divisions on platforms that need software
division.
Yet compiler may itself use a signed division. A typical example would be a
difference between 2 pointers which involves division by object size.
This commit is contained in:
Vladimir Serbinenko 2015-02-22 17:24:28 +01:00
parent e1d4520bfb
commit f034fab620
6 changed files with 198 additions and 51 deletions

View file

@ -594,10 +594,10 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
grub_uint64_t m = 0;
/* ARM and IA64 don't have a fast 32-bit division.
Using that code would just make us use libgcc routines, calling
them twice (once for modulo and once for quotient.
Using that code would just make us use software division routines, calling
ourselves indirectly and hence getting infinite recursion.
*/
#if !defined (__arm__) && !defined (__ia64__)
#if !GRUB_DIVISION_IN_SOFTWARE
/* Skip the slow computation if 32-bit arithmetic is possible. */
if (n < 0xffffffff && d < 0xffffffff)
{
@ -633,7 +633,7 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
#if !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
#if defined (__arm__)
#if GRUB_DIVISION_IN_SOFTWARE
grub_uint32_t
__udivsi3 (grub_uint32_t a, grub_uint32_t b)
@ -641,6 +641,12 @@ __udivsi3 (grub_uint32_t a, grub_uint32_t b)
return grub_divmod64 (a, b, 0);
}
grub_int32_t
__divsi3 (grub_int32_t a, grub_int32_t b)
{
return grub_divmod64s (a, b, 0);
}
grub_uint32_t
__umodsi3 (grub_uint32_t a, grub_uint32_t b)
{
@ -649,6 +655,42 @@ __umodsi3 (grub_uint32_t a, grub_uint32_t b)
return ret;
}
grub_int32_t
__modsi3 (grub_int32_t a, grub_int32_t b)
{
grub_int64_t ret;
grub_divmod64s (a, b, &ret);
return ret;
}
grub_uint64_t
__udivdi3 (grub_uint64_t a, grub_uint64_t b)
{
return grub_divmod64 (a, b, 0);
}
grub_uint64_t
__umoddi3 (grub_uint64_t a, grub_uint64_t b)
{
grub_uint64_t ret;
grub_divmod64 (a, b, &ret);
return ret;
}
grub_int64_t
__divdi3 (grub_int64_t a, grub_int64_t b)
{
return grub_divmod64s (a, b, 0);
}
grub_int64_t
__moddi3 (grub_int64_t a, grub_int64_t b)
{
grub_int64_t ret;
grub_divmod64s (a, b, &ret);
return ret;
}
#endif
#ifdef NEED_CTZDI2
@ -735,30 +777,15 @@ __ctzsi2 (grub_uint32_t x)
grub_uint32_t
__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b)
__attribute__ ((alias ("__udivsi3")));
grub_int32_t
__aeabi_idiv (grub_int32_t a, grub_int32_t b)
__attribute__ ((alias ("__divsi3")));
void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n)
__attribute__ ((alias ("grub_memcpy")));
void *__aeabi_memset (void *s, int c, grub_size_t n)
__attribute__ ((alias ("grub_memset")));
#endif
#if defined (__ia64__)
grub_uint64_t
__udivdi3 (grub_uint64_t a, grub_uint64_t b)
{
return grub_divmod64 (a, b, 0);
}
grub_uint64_t
__umoddi3 (grub_uint64_t a, grub_uint64_t b)
{
grub_uint64_t ret;
grub_divmod64 (a, b, &ret);
return ret;
}
#endif
#endif /* GRUB_UTIL */
/* Convert a long long value to a string. This function avoids 64-bit