Re: inline Assembler

Gabriel Paubert (paubert@iram.es)
Thu, 17 Sep 1998 16:33:05 +0200 (METDST)


On Thu, 17 Sep 1998, Vasili Goutas wrote:

> #define NTAPI
>
> __inline LARGE_INTEGER
> NTAPI
> RtlEnlargedIntegerMultiply (
> LONG Multiplicand,
> LONG Multiplier
> )
> {
> LARGE_INTEGER rc;
> /*
> rc.QuadPart = Multiplicand * Multiplier;
> return rc;
> */
> __asm__ __volatile__("imull %0\n\t"
> : "=A"(rc.QuadPart)
> : "%eax"(Multiplicand), "0"(Multiplier)
> : "eax");
> return rc;

This is plain wrong, the constraints in the input and output operands
must be register classes, not names. So he "%eax" is completely bogus.
OTOH, the names in the clobbered registers are physical names, yes I know
it's confusing.

Then the "%0" would correspond to the output parameter of class "A" which
is a 64 bit pseudo register created out of %eax and %edx.

The following should work:

__asm__ __volatile__("imull %2\n\t"
: "=A"(rc.QuadPart)
: "a"(Multiplicand), "rm"(Multiplier)
return rc;

I think that GCC will not be confused by the fact that one input operand
partially overlaps the output operand (it should not). The "rm"
constraint is used instead of "g" because immediate addressing "i" is not
allowed for this instruction.

However, latest version of GCC (egcs) are much smarter about 64 bit
integer handling, it is even possible that:

return (long long) Mulitplicand * Multiplier

generates exactly the same code. Declare the function as inline
for performance.

Gabriel.

P.S.: this is off-topic on linux-kernel.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/