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 <[EMAIL PROTECTED]> 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'