avr-gcc-list
[Top][All Lists]

## [avr-gcc-list] Re: Optimizing a 16-bit * 8-bit -> 24-bit multiplication

 From: David Nicol Subject: [avr-gcc-list] Re: Optimizing a 16-bit * 8-bit -> 24-bit multiplication Date: Mon, 4 Dec 2006 13:00:37 -0600

```here's an ignorant, naive, and very likely wrong attempt:

what happens if you mask off the high and low bytes of the
larger number, do two 8,8->16 multiplies, left shift the result
of the result of the higher one, and add, as a macro?

#define _mul8x16(c,s)  (  \
(long int) ((c) * (unsigned char) ( (s) & 0x00FF) )\
+
(long int) ( \
(long int) ( (c) * (unsigned char) ( ( (s) & 0xFF00 ) >> 8)) \
<< 8  \
) \
)

what would that do?  I don't know which if any of the casting is needed,
or what exactly you have to do to suppress upgrading the
internal representations to 32-bit until the left-shift and the add;
one would expect that multiplying a char by a short on this platform
would produce that code, and that the avr-gcc-list would be the
right place to find someone who could make that happen.

since you know the endianness of your machine, you could reasonably
pull chars out of the long directly instead of shifting and masking, also
you could store the to-be-shifted result directly into an address one byte
off from the address of the integer that you will add the low result to --
that's what you're proposing unions for, right?

On 12/1/06, Shaun Jackman <address@hidden> wrote:
```
```I would like to multiply a 16-bit number by an 8-bit number and
produce a 24-bit result on the AVR. The AVR has a hardware 8-bit *
8-bit -> 16-bit multiplier.

If I multiply a 16-bit number by a 16-bit number, it produces a 16-bit
result, which isn't wide enough to hold the result.

If I cast one of the operands to 32-bit and multiply a 32-bit number
by a 16-bit number, GCC generates a call to __mulsi3, which is the
routine to multiply a 32-bit number by a 32-bit number and produce a
32-bit result and requires ten 8-bit * 8-bit multiplications.

A 16-bit * 8-bit -> 24-bit multiplication only requires two 8-bit *
8-bit multiplications. A 16-bit * 16-bit -> 32-bit multiplication
requires four 8-bit * 8-bit multiplications.

I could write a mul24_16_8 (16-bit * 8-bit -> 24-bit) function using
unions and 8-bit * 8-bit -> 16-bit multiplications, but before I go
down that path, is there any way to coerce GCC into generating the
code I desire?

Cheers,
Shaun

```
```

--
perl -le'1while(1x++\$_)=~/^(11+)\1+\$/||print'

```