[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