[OSy] chybejici __udivdi3

Jakub Jermar jakub at jermar.eu
Sun Nov 4 11:40:22 CET 2007


Mene masochisticka varianta je napsat ten __udivdi3 v C.

Jakub

On Nov 4, 2007, at 11:31 AM, Branislav Repček wrote:

> Zdravim.
>
> Podla mojich testov funguje do_div spravne. Ked skusim do
> nasledujuceho kodu dat tvoje hodnoty, tak mam spravne vysledky...
>
> uint64_t temp = usec * tps;
> printk("usec: %u\n", (unative_t) usec);
> printk(" Temp: lo=%u hi=%u\n", ((uint32_t *) &temp)[0], ((uint32_t *)
> &temp)[1]);
> do_div(temp, 1000000);
> printk(" Res: lo=%u hi=%u\n", ((uint32_t *) &temp)[0], ((uint32_t  
> *) &temp)[1]);
>
> Vystup je:
>
> usec: 2000000
>  Temp: lo=1780113024 hi=3581
>  Res: lo=15382058 hi=0
>
> Co po prepocitani dava Temp=2^32 * 3581 + 1780113024 = 15382058000000.
> Z toho je jasne, ze Res je tiez spravne.
>
> To je v podstate aj to, co by som cakal. Ako som spominal, do_div je
> prevzate z Linux 2.6.23.1 a jedina moja uprava je substitucia makra
> GCC_REG_ACCUM v do_div makre za "$0".
>
> -- 
> Branislav Repcek
> http://minimal.matfyz.cz
>
>
> On Nov 3, 2007 11:29 PM, Josef Reidinger  
> <josef.reidinger at seznam.cz> wrote:
>> Zkousel sem tvoje reseni a vysledek neni moc dobry, mozna to jen  
>> spatne
>> pouzivam.
>>
>> kod:
>>  unsigned long long tmp = tmr->usec*tics_per_second;
>>   dprintk(" usec: %u tps: %u \n",tmr->usec,tics_per_second);
>>   unsigned micro = 1000000;
>>   do_div(tmp,micro);
>>
>> vysledek:
>> function timer_start: 113 -  usec: 2000000 tps: 7691029
>> function timer_start: 118 - counted ticks is 1780
>>
>>
>> Branislav Repček napsal(a):
>>
>>> Zdravim,
>>>
>>> ja som mal tiez tento problem a vyriesil som ho tak, ze som si
>>> "napisal" makro, ktore robi 64 bitove delenie za mna.
>>>
>>> longdiv.h:
>>>
>>> #ifndef LONGDIV_H
>>> #define LONGDIV_H
>>>
>>> #include "types.h"
>>>
>>> #define do_div64_32(res, high, low, base) ({ \
>>>       unsigned long __quot32, __mod32; \
>>>       unsigned long __cf, __tmp, __tmp2, __i; \
>>>       \
>>>       __asm__(".set   push\n\t" \
>>>               ".set   noat\n\t" \
>>>               ".set   noreorder\n\t" \
>>
>>>               "move   %2, $0\n\t" \
>>
>>>               "move   %3, $0\n\t" \
>>
>>>               "b      1f\n\t" \
>>
>>>               " li    %4, 0x21\n" \
>>
>>>               "0:\n\t" \
>>
>>>               "sll    $1, %0, 0x1\n\t" \
>>
>>>               "srl    %3, %0, 0x1f\n\t" \
>>
>>>               "or     %0, $1, %5\n\t" \
>>
>>>               "sll    %1, %1, 0x1\n\t" \
>>
>>>               "sll    %2, %2, 0x1\n" \
>>
>>>               "1:\n\t" \
>>
>>>               "bnez   %3, 2f\n\t" \
>>
>>>               " sltu  %5, %0, %z6\n\t" \
>>
>>>               "bnez   %5, 3f\n" \
>>
>>>               "2:\n\t" \
>>
>>>               " addiu %4, %4, -1\n\t" \
>>
>>>               "subu   %0, %0, %z6\n\t" \
>>
>>>               "addiu  %2, %2, 1\n" \
>>
>>>               "3:\n\t" \
>>
>>>               "bnez   %4, 0b\n\t" \
>>
>>>               " srl   %5, %1, 0x1f\n\t" \
>>
>>>               ".set   pop" \
>>
>>>               : "=&r" (__mod32), "=&r" (__tmp), \
>>
>>>                 "=&r" (__quot32), "=&r" (__cf), \
>>
>>>                 "=&r" (__i), "=&r" (__tmp2) \
>>
>>>               : "Jr" (base), "0" (high), "1" (low)); \
>>
>>>       \
>>
>>>       (res) = __quot32; \
>>
>>>       __mod32; })
>>
>>>
>>
>>> #define do_div(n, base) ({ \
>>
>>>       unsigned long long __quot; \
>>
>>>       unsigned long __mod; \
>>
>>>       unsigned long long __div; \
>>
>>>       unsigned long __upper, __low, __high, __base; \
>>
>>>       \
>>
>>>       __div = (n); \
>>
>>>       __base = (base); \
>>
>>>       \
>>
>>>       __high = __div >> 32; \
>>
>>>       __low = __div; \
>>
>>>       __upper = __high; \
>>
>>>       \
>>
>>>       if (__high) \
>>
>>>               __asm__("divu   $0, %z2, %z3" \
>>
>>>                       : "=h" (__upper), "=l" (__high) \
>>
>>>                       : "Jr" (__high), "Jr" (__base) \
>>
>>>                       : "$0"); \
>>
>>>       \
>>
>>>       __mod = do_div64_32(__low, __upper, __low, __base); \
>>
>>>       \
>>
>>>       __quot = __high; \
>>
>>>       __quot = __quot << 32 | __low; \
>>
>>>       (n) = __quot; \
>>
>>>       __mod; })
>>
>>>
>>
>>> #endif
>>
>>>
>>
>>> Tento kod je prakticky cely prebraty z
>>> linux-2.6.23.1/include/asm-mips/div64.h a zatial mi funguje bez
>>> problemov...
>>>
>>> On Nov 3, 2007 2:33 PM, Zdeněk Doležal <zdenek.dolezal at gmail.com>  
>>> wrote:
>>>> Ahoj,
>>>> nevim, zda je tohle stejny pripad jako nas, zkus make clean a
>>>> distclean a pak prolozit znovu. Delalo nam to podobnou chybu.
>>>>
>>>>
>>>> On 11/3/07, Josef Reidinger <josef.reidinger at seznam.cz> wrote:
>>>>> Ahoj,
>>>>> mam problem, ze pri prekladu deleni unsigned long long mi to pise
>>>>> .../prereq/timer.o: In function `timer_start'
>>>>> timer.c:(.text+0x4ac): undefined reference to `__udivdi3'
>>>>> timer.c:(.text+0x4ac): relocation truncated to fit: R_MIPS_26  
>>>>> against
>>>>> `__udivdi3
>>>>>
>>>>> pri googleni mi to naslo, ze by to melo byt v nejaky knihovne
>>>>> /lib/libuuid.so.1 ale tu jsem nenasel a nejde mi slinkovat tedy  
>>>>> kernel.
>>>>> Netusite nekdo cim by se to dalo opravit?
>>>>>
>>>> --
>>>> S pozdravem
>>>> Zdenek Dolezal
>>>
>>
> _______________________________________________
> OSy mailing list
> OSy at dsrg.mff.cuni.cz
> https://dsrg.mff.cuni.cz/mailman/listinfo/osy





More information about the NSWI004 mailing list