[OSy] chybejici __udivdi3

Branislav Repček brepcek at gmail.com
Sun Nov 4 11:31:05 CET 2007


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
> >
>


More information about the NSWI004 mailing list