Hello all,Since GCC 7, a new function `__divmoddi4()` is added in libgcc. When GCC performs division of two 64-bit integers on i686, a call to this function is emitted, which could result in undefined references to this function when we are building part of the CRT (winpthreads for example, but I am not totally sure that our CRT is free of such issues). I suggest we implement weak versions of these functions that are used only by the CRT (strong ones from libgcc are used if whenever available).
Source attached. Any ideas on this? -- Best regards, LH_Mouse
#include <stdint.h> static uint64_t udivmoddi4_unchecked(uint64_t dvnd, uint64_t dvsr, uint64_t *rem_ptr){ uint64_t quo, rem; int lz_dvnd, lz_dvsr; int scale, i; uint64_t sub; if(dvsr == 0){ /* Division by zero? */ __builtin_trap(); } quo = 0; rem = dvnd; if(dvnd != 0){ lz_dvnd = __builtin_clzll(dvnd); lz_dvsr = __builtin_clzll(dvsr); scale = lz_dvsr - lz_dvnd; if(scale < 0){ /* The divisor has fewer leading zeroes than the dividend. This means the divisor is greater than the dividend. There is nothing to do. */ } else { /* Align the MSBs of the dividend and the divisor. */ sub = dvsr << scale; i = 0; for(;;){ /* Calculate the quotient bit by bit, as what we do in primary school. */ quo <<= 1; if(rem >= sub){ quo += 1; rem -= sub; if(__builtin_expect(rem == 0, 0)){ /* Take the faster branch. */ quo <<= scale - i; break; } } if(i == scale){ break; } ++i; sub >>= 1; } } } *rem_ptr = rem; return quo; } /* If we are linking against a real libgcc, use that implementation instead. */ #define ATTRIBUTE_WEAK __attribute__((__weak__)) ATTRIBUTE_WEAK uint64_t __udivmoddi4(uint64_t dvnd, uint64_t dvsr, uint64_t *rem_ptr){ uint64_t uquo, urem; uquo = udivmoddi4_unchecked(dvnd, dvsr, &urem); if(rem_ptr){ *rem_ptr = urem; } return uquo; } ATTRIBUTE_WEAK int64_t __divmoddi4(int64_t dvnd, int64_t dvsr, int64_t *rem_ptr){ int64_t quo, rem; uint64_t uquo, urem; if(dvnd >= 0){ if(dvsr >= 0){ uquo = udivmoddi4_unchecked((uint64_t)dvnd, (uint64_t)dvsr, &urem); quo = (int64_t)uquo; } else { uquo = udivmoddi4_unchecked((uint64_t)dvnd, (uint64_t)-dvsr, &urem); quo = -(int64_t)uquo; } rem = (int64_t)urem; } else { if(dvsr >= 0){ uquo = udivmoddi4_unchecked((uint64_t)-dvnd, (uint64_t)dvsr, &urem); quo = -(int64_t)uquo; } else { uquo = udivmoddi4_unchecked((uint64_t)-dvnd, (uint64_t)-dvsr, &urem); quo = (int64_t)uquo; } rem = -(int64_t)urem; } if(rem_ptr){ *rem_ptr = rem; } return quo; } #include <stdio.h> int main(){ long long dvnd, dvsr, quo, rem; dvnd = 1021; dvsr = -25; quo = __divmoddi4(dvnd, dvsr, &rem); __mingw_printf("%lld / %lld = %lld ... %lld\n", dvnd, dvsr, quo, rem); return 0; }
------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public