2001-04-05 05:29:43

by Manoj Sontakke

[permalink] [raw]
Subject: which gcc version?

Hi
I am getting linker error "undefined reference to __divdi3".
This is because c = a/b; where a,b,c are of type "long long"
I understand this is gcc problem.
I am doing this on a pentium with gcc -v = egcs-2.91.66

Thanks for all the help.

Manoj


2001-04-05 05:49:24

by Alexander Viro

[permalink] [raw]
Subject: Re: which gcc version?



On Thu, 5 Apr 2001, Manoj Sontakke wrote:

> Hi
> I am getting linker error "undefined reference to __divdi3".
> This is because c = a/b; where a,b,c are of type "long long"
> I understand this is gcc problem.
> I am doing this on a pentium with gcc -v = egcs-2.91.66

Don't do it in the kernel. It has nothing to gcc version.

2001-04-05 09:03:25

by Manoj Sontakke

[permalink] [raw]
Subject: Re: which gcc version?

hi

On Thu, 5 Apr 2001, Alexander Viro wrote:
> On Thu, 5 Apr 2001, Manoj Sontakke wrote:
>
> > Hi
> > I am getting linker error "undefined reference to __divdi3".
> > This is because c = a/b; where a,b,c are of type "long long"
> > I understand this is gcc problem.
> > I am doing this on a pentium with gcc -v = egcs-2.91.66
>
> Don't do it in the kernel. It has nothing to gcc version.

Addition and subtraction works fine. The problem is with multiplication
and division. I am doing this to avoid floating point calculation and
doing fixed point calculation. The rage is large enough to need "long
long" Any other way to achieve this?

thanks
manoj

2001-04-05 11:43:53

by Bart Trojanowski

[permalink] [raw]
Subject: Re: which gcc version?

On Thu, 5 Apr 2001, Manoj Sontakke wrote:

> Addition and subtraction works fine. The problem is with multiplication
> and division. I am doing this to avoid floating point calculation and
> doing fixed point calculation. The rage is large enough to need "long
> long" Any other way to achieve this?

gcc requires a function call to do a mul/div on a long long. There is no
easy way to do a 64bit op of this type on a 32 bit CPU...

IFF you are making a module that will never be part of the kernel tree you
can get away with adding `gcc -print-libgcc-file-name` to your link line.
And by that I mean:

${LD} ${LDFLAGS} -o $@ $< `gcc -print-libgcc-file-name`

This is a hack that will link in the __div3 function from glibc into your
module. NOTE that this will never be done for you in the kernel... so if
you can don't use div or mul on long long.

Cheers,
Bart.

--
WebSig: http://www.jukie.net/~bart/sig/


2001-04-05 11:46:44

by Matti Aarnio

[permalink] [raw]
Subject: Re: which gcc version?

On Thu, Apr 05, 2001 at 07:39:14PM +0530, Manoj Sontakke wrote:
> hi
>
> On Thu, 5 Apr 2001, Alexander Viro wrote:
> > On Thu, 5 Apr 2001, Manoj Sontakke wrote:
> >
> > > Hi
> > > I am getting linker error "undefined reference to __divdi3".
> > > This is because c = a/b; where a,b,c are of type "long long"
> > > I understand this is gcc problem.
> > > I am doing this on a pentium with gcc -v = egcs-2.91.66
> >
> > Don't do it in the kernel. It has nothing to gcc version.
>
> Addition and subtraction works fine. The problem is with multiplication
> and division. I am doing this to avoid floating point calculation and
> doing fixed point calculation. The rage is large enough to need "long
> long" Any other way to achieve this?

How arbitrary is the divisor ?
Not by change a power-of-two ?

If it is arbitrary, how large ?
The printk() contains support routine doing longlong/int
division when a) speed is *not* important, b) divisor is
sufficiently small, and I think c) divisor is positive.

When you look at that code, you should begin to grasp,
what kind of monster is the longlong/longlong code at -lgcc ...
(and why gcc doesn't produce inline code for it.)

> thanks
> manoj

/Matti Aarnio

2001-04-05 11:50:53

by christophe barbé

[permalink] [raw]
Subject: Re: which gcc version?

Which kernel are you using ?
GFS use this kind of computation. And with kernel 2.2, a module divdi3.o provides all missing symbol like __divdi3.

Christophe

On jeu, 05 avr 2001 16:09:14 Manoj Sontakke wrote:
> hi
>
> On Thu, 5 Apr 2001, Alexander Viro wrote:
> > On Thu, 5 Apr 2001, Manoj Sontakke wrote:
> >
> > > Hi
> > > I am getting linker error "undefined reference to __divdi3".
> > > This is because c = a/b; where a,b,c are of type "long long"
> > > I understand this is gcc problem.
> > > I am doing this on a pentium with gcc -v = egcs-2.91.66
> >
> > Don't do it in the kernel. It has nothing to gcc version.
>
> Addition and subtraction works fine. The problem is with multiplication
> and division. I am doing this to avoid floating point calculation and
> doing fixed point calculation. The rage is large enough to need "long
> long" Any other way to achieve this?
>
> thanks
> manoj
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
--
Christophe Barb?
Software Engineer
Lineo High Availability Group
42-46, rue M?d?ric
92110 Clichy - France
phone (33).1.41.40.02.12
fax (33).1.41.40.02.01
http://www.lineo.com

2001-04-05 12:03:34

by Matti Aarnio

[permalink] [raw]
Subject: Re: which gcc version?

On Thu, Apr 05, 2001 at 07:37:03AM -0400, Bart Trojanowski wrote:
> On Thu, 5 Apr 2001, Manoj Sontakke wrote:
> gcc requires a function call to do a mul/div on a long long. There is no
> easy way to do a 64bit op of this type on a 32 bit CPU...

Actually there is -- presuming your CPU has lots of registers,
which i386 does not have...

This rule -- "no -lgcc in kernel code" -- is to trap code which
in fast-paths would call those slow routines.
Fastpaths should either not grok such values, or at most use
shifts.

To think of it, there really should be explicitely callable
versions of these with LinuxKernel names for them, not gcc
builtins.? That way people would *know* they are doing
something, which is potentially very slow.
(And the API would not change from underneath them.)

> Cheers,
> Bart.
> --
> WebSig: http://www.jukie.net/~bart/sig/

/Matti Aarnio

2001-04-05 12:32:58

by David Woodhouse

[permalink] [raw]
Subject: Re: which gcc version?


[email protected] said:
> To think of it, there really should be explicitely callable
> versions of these with LinuxKernel names for them, not gcc
> builtins.? That way people would *know* they are doing
> something, which is potentially very slow.
> (And the API would not change from underneath them.)

Like include/asm-*/div64.h::do_div()?

--
dwmw2


2001-04-05 12:33:49

by Matti Aarnio

[permalink] [raw]
Subject: Re: which gcc version?

On Thu, Apr 05, 2001 at 01:26:32PM +0100, David Woodhouse wrote:
> [email protected] said:
> > To think of it, there really should be explicitely callable
> > versions of these with LinuxKernel names for them, not gcc
> > builtins.? That way people would *know* they are doing
> > something, which is potentially very slow.
> > (And the API would not change from underneath them.)
>
> Like include/asm-*/div64.h::do_div()?

Like that (*) - but that has limited value spaces,
the divider can be at most 32 bits, probably far less.

> --
> dwmw2

/Matti Aarnio

(*) Trying to recall when I, and few others, created that beast.
The divisor code in itself isn't mine, but the idea of supporting
%Ld at printk() most definitely is..

2001-04-05 13:11:40

by Richard B. Johnson

[permalink] [raw]
Subject: Re: which gcc version?

On Thu, 5 Apr 2001, David Woodhouse wrote:

>
> [email protected] said:
> > To think of it, there really should be explicitely callable
> > versions of these with LinuxKernel names for them, not gcc
> > builtins.? That way people would *know* they are doing
> > something, which is potentially very slow.
> > (And the API would not change from underneath them.)
>
> Like include/asm-*/div64.h::do_div()?
>

Some, perhaps all, of the recent requirements for a 64 bit division
can be handled with the (Intel) 32-bit division because only the
dividend is 64 bits, and the division can be unsigned, i.e.

HIGHLONG = 0x08 ; Depends upon caller's stack.
LOWLONG = 0x0C
DIVISOR = 0x10

movl HIGHLONG(%esp), %edx
movl LOWLLONG(%esp), %eax
movl DIVISOR(%esp), %ecx
divl %ecx,%eax

... returns a longword in %eax

This could be an __inline__ function. Most other stuff can be reduced
with shifts before a 32-bit divide.

64 bit signed division is a bitch in any 32-bit machine because it's
done just line 4th grade long division. There are remainders that have
to carried, etc.


Cheers,
Dick Johnson

Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips).

"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.