This function will be used in a follow-up patch to implement TARGET_EXPAND_DIVMOD_LIBFUNC for x86 targets. Other targets can call this function, so IMO it should be part of a generic library.
2016-10-31 Uros Bizjak <ubiz...@gmail.com> * Makefile.in (LIB2_DIVMOD_FUNCS): Add _divmoddi4. * libgcc2.c (__divmoddi4): New function. * libgcc2.h (__divmoddi4): Declare. * libgcc-std.ver.in (GCC_7.0.0): New. Add __PFX_divmoddi4 and __PFX_divmodti4. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32} with a follow-up target-dependent patch. OK for mainline? Uros.
Index: Makefile.in =================================================================== --- Makefile.in (revision 241697) +++ Makefile.in (working copy) @@ -255,10 +255,6 @@ LIB2FUNCS_ST = _eprintf __gcc_bcmp # List of functions not to build from libgcc2.c. LIB2FUNCS_EXCLUDE = -# These might cause a divide overflow trap and so are compiled with -# unwinder info. -LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4 - # List of extra C and assembler files to add to static and shared libgcc2. # Assembler files should have names ending in `.S'. LIB2ADD = @@ -455,7 +451,8 @@ endif # These might cause a divide overflow trap and so are compiled with # unwinder info. -LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4 +LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _divmoddi4 \ + _udivdi3 _umoddi3 _udivmoddi4 _udiv_w_sdiv # Remove any objects from lib2funcs and LIB2_DIVMOD_FUNCS that are # defined as optimized assembly code in LIB1ASMFUNCS or as C code Index: libgcc-std.ver.in =================================================================== --- libgcc-std.ver.in (revision 241697) +++ libgcc-std.ver.in (working copy) @@ -1938,3 +1938,9 @@ GCC_4.7.0 { %inherit GCC_4.8.0 GCC_4.7.0 GCC_4.8.0 { } + +%inherit GCC_7.0.0 GCC_4.8.0 +GCC_7.0.0 { + __PFX__divmoddi4 + __PFX__divmodti4 +} Index: libgcc2.c =================================================================== --- libgcc2.c (revision 241697) +++ libgcc2.c (working copy) @@ -680,7 +680,8 @@ __udiv_w_sdiv (UWtype *rp __attribute__ ((__unused #endif #if (defined (L_udivdi3) || defined (L_divdi3) || \ - defined (L_umoddi3) || defined (L_moddi3)) + defined (L_umoddi3) || defined (L_moddi3) || \ + defined (L_divmoddi4)) #define L_udivmoddi4 #endif @@ -937,7 +938,8 @@ __parityDI2 (UDWtype x) #ifdef TARGET_HAS_NO_HW_DIVIDE #if (defined (L_udivdi3) || defined (L_divdi3) || \ - defined (L_umoddi3) || defined (L_moddi3)) + defined (L_umoddi3) || defined (L_moddi3) || \ + defined (L_divmoddi4)) static inline __attribute__ ((__always_inline__)) #endif UDWtype @@ -1004,7 +1006,8 @@ __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) #else #if (defined (L_udivdi3) || defined (L_divdi3) || \ - defined (L_umoddi3) || defined (L_moddi3)) + defined (L_umoddi3) || defined (L_moddi3) || \ + defined (L_divmoddi4)) static inline __attribute__ ((__always_inline__)) #endif UDWtype @@ -1269,6 +1272,34 @@ __moddi3 (DWtype u, DWtype v) } #endif +#ifdef L_divmoddi4 +DWtype +__divmoddi4 (DWtype u, DWtype v, DWtype *rp) +{ + Wtype c1 = 0, c2 = 0; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; + DWtype w; + DWtype r; + + if (uu.s.high < 0) + c1 = ~c1, c2 = ~c2, + uu.ll = -uu.ll; + if (vv.s.high < 0) + c1 = ~c1, + vv.ll = -vv.ll; + + w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&r); + if (c1) + w = -w; + if (c2) + r = -r; + + *rp = r; + return w; +} +#endif + #ifdef L_umoddi3 UDWtype __umoddi3 (UDWtype u, UDWtype v) Index: libgcc2.h =================================================================== --- libgcc2.h (revision 241697) +++ libgcc2.h (working copy) @@ -281,6 +281,7 @@ typedef int shift_count_type __attribute__((mode ( #define __ashrdi3 __NDW(ashr,3) #define __cmpdi2 __NDW(cmp,2) #define __ucmpdi2 __NDW(ucmp,2) +#define __divmoddi4 __NDW(divmod,4) #define __udivmoddi4 __NDW(udivmod,4) #define __fixunstfDI __NDW(fixunstf,) #define __fixtfdi __NDW(fixtf,) @@ -376,10 +377,12 @@ extern DWtype __divdi3 (DWtype, DWtype); extern UDWtype __udivdi3 (UDWtype, UDWtype); extern UDWtype __umoddi3 (UDWtype, UDWtype); extern DWtype __moddi3 (DWtype, DWtype); +extern DWtype __divmoddi4 (DWtype, DWtype, DWtype *); /* __udivmoddi4 is static inline when building other libgcc2 portions. */ #if (!defined (L_udivdi3) && !defined (L_divdi3) && \ - !defined (L_umoddi3) && !defined (L_moddi3)) + !defined (L_umoddi3) && !defined (L_moddi3) && \ + !defined (L_divmoddi4)) extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *); #endif