Hello, all. ARM and ia64 apparently don't generically have opcode to make division of pointer-sized integers. Alpha has the same property but alpha port is in very sorry state anyway so it doesn't matter anyway. Looking at libgcc code at functions at question, I see that they use algorithm very similar to what we have in divmod64. IA64 version uses FPU which probably worked more by luck since we don't do proper FPU setup on any platform. Alpha version also uses FPU and probably doesn't work. In my alpha port I redirected all division functions to grub_divmod64. What do you think about attached patch?
diff --git a/configure.ac b/configure.ac index ea38f09..956cfed 100644 --- a/configure.ac +++ b/configure.ac @@ -820,7 +820,7 @@ CFLAGS="$TARGET_CFLAGS -Wl,--defsym,abort=main" fi # Check for libgcc symbols -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __ucmpdi2 _restgpr_14_x __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3 __ctzdi2 __ctzsi2) +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __ucmpdi2 _restgpr_14_x __ctzdi2 __ctzsi2) if test "x$TARGET_APPLE_CC" = x1 ; then CFLAGS="$TARGET_CFLAGS -nostdlib" diff --git a/grub-core/kern/arm/misc.S b/grub-core/kern/arm/misc.S index 9d4c333..68e4828 100644 --- a/grub-core/kern/arm/misc.S +++ b/grub-core/kern/arm/misc.S @@ -30,6 +30,26 @@ .align 2 + .macro division parent + + stmfd sp!, {lr} + sub sp, sp, #12 + mov r2, r1 + add r1, sp, #4 + str r1, [sp, #0] + mov r1, #0 + mov r3, #0 + bl \parent + ldr r1, [sp, #4] + add sp, sp, #12 + ldmfd sp!, {lr} + bx lr + .endm + +FUNCTION(__aeabi_uidivmod) + division grub_divmod64 + + /* * Null divide-by-zero handler */ diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index f883fb9..caf7779 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -589,6 +589,49 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) return q; } +#if defined (__arm__) + +grub_uint32_t +__udivsi3 (grub_uint32_t a, grub_uint32_t b) +{ + return grub_divmod64 (a, b, 0); +} + +grub_uint32_t +__umodsi3 (grub_uint32_t a, grub_uint32_t b) +{ + grub_uint64_t ret; + grub_divmod64 (a, b, &ret); + return ret; +} + + +#endif + +#ifdef __arm__ +grub_uint32_t +__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b) + __attribute__ ((alias ("__udivsi3"))); +#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 + /* Convert a long long value to a string. This function avoids 64-bit modular arithmetic or divisions. */ static char * diff --git a/grub-core/lib/libgcrypt/cipher/idea.c b/grub-core/lib/libgcrypt/cipher/idea.c index c025c95..3c5578f 100644 --- a/grub-core/lib/libgcrypt/cipher/idea.c +++ b/grub-core/lib/libgcrypt/cipher/idea.c @@ -72,8 +72,8 @@ mul_inv( u16 x ) if( x < 2 ) return x; - t1 = 0x10001L / x; - y = 0x10001L % x; + t1 = 0x10001UL / x; + y = 0x10001UL % x; if( y == 1 ) return (1-t1) & 0xffff; diff --git a/grub-core/term/tparm.c b/grub-core/term/tparm.c index 8c1c288..f659f13 100644 --- a/grub-core/term/tparm.c +++ b/grub-core/term/tparm.c @@ -614,13 +614,13 @@ tparam_internal(const char *string, va_list ap) case '/': y = npop(); x = npop(); - npush(y ? (x / y) : 0); + npush(y ? ((unsigned)x / (unsigned)y) : 0); break; case 'm': y = npop(); x = npop(); - npush(y ? (x % y) : 0); + npush(y ? ((unsigned)x % (unsigned)y) : 0); break; case 'A': diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h index d101db4..fdc6611 100644 --- a/include/grub/libgcc.h +++ b/include/grub/libgcc.h @@ -42,30 +42,6 @@ void EXPORT_FUNC (__bswapsi2) (void); # ifdef HAVE___BSWAPDI2 void EXPORT_FUNC (__bswapdi2) (void); # endif -# ifdef HAVE___UDIVSI3 -void EXPORT_FUNC (__udivsi3) (void); -# endif -# ifdef HAVE___UMODSI3 -void EXPORT_FUNC (__umodsi3) (void); -# endif -# ifdef HAVE___UMODDI3 -void EXPORT_FUNC (__umoddi3) (void); -# endif -# ifdef HAVE___UDIVDI3 -void EXPORT_FUNC (__udivdi3) (void); -# endif -# ifdef HAVE___MODDI3 -void EXPORT_FUNC (__moddi3) (void); -# endif -# ifdef HAVE___DIVDI3 -void EXPORT_FUNC (__divdi3) (void); -# endif -# ifdef HAVE___DIVSI3 -void EXPORT_FUNC (__divsi3) (void); -# endif -# ifdef HAVE___MODSI3 -void EXPORT_FUNC (__modsi3) (void); -# endif # ifdef HAVE___CTZDI2 void EXPORT_FUNC (__ctzdi2) (void); # endif @@ -114,12 +90,8 @@ void EXPORT_FUNC (_savegpr_31) (void); #endif #if defined (__arm__) -void EXPORT_FUNC (__aeabi_idiv) (void); -void EXPORT_FUNC (__aeabi_idivmod) (void); void EXPORT_FUNC (__aeabi_lasr) (void); void EXPORT_FUNC (__aeabi_llsl) (void); void EXPORT_FUNC (__aeabi_llsr) (void); -void EXPORT_FUNC (__aeabi_uidiv) (void); -void EXPORT_FUNC (__aeabi_uidivmod) (void); void EXPORT_FUNC (__aeabi_ulcmp) (void); #endif diff --git a/include/grub/misc.h b/include/grub/misc.h index 9583724..6767953 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -449,6 +449,35 @@ grub_error_load (const struct grub_error_saved *save) grub_errno = save->grub_errno; } +#if defined (__arm__) + +grub_uint32_t +EXPORT_FUNC (__udivsi3) (grub_uint32_t a, grub_uint32_t b); + +grub_uint32_t +EXPORT_FUNC (__umodsi3) (grub_uint32_t a, grub_uint32_t b); + +#endif + +#ifdef __arm__ +grub_uint32_t +EXPORT_FUNC (__aeabi_uidiv) (grub_uint32_t a, grub_uint32_t b); +grub_uint32_t +EXPORT_FUNC (__aeabi_uidivmod) (grub_uint32_t a, grub_uint32_t b); + +#endif + +#if defined (__ia64__) + +grub_uint64_t +EXPORT_FUNC (__udivdi3) (grub_uint64_t a, grub_uint64_t b); + +grub_uint64_t +EXPORT_FUNC (__umoddi3) (grub_uint64_t a, grub_uint64_t b); + +#endif + + #if BOOT_TIME_STATS struct grub_boot_time {
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel