Hallo to everyone.
My problem is to have the upper 4 Byte result of a multiply. For example:
unsigned int a=1000000000;//only example value unsigned int b=10000000000; unsigned int c;
the result of a*b = 0x8AC7230489E80000 How to get the upper 4 Bytes: 0x8AC72304 How to get the lower 4 Bytes: 0x89E80000
Can anybody help? I have to programm a super-fast-interrupt-routine for an microcontroller, there is not enough time for floating point.
but i get wrong result or
No, the result is not wrong, what you're doing is wrong. You're expecting the compiler to automatically expand the result to 64 bits, which it won't do.
Either you do it in assembly (ARM has very nice multiply instructions that can calculate the upper part, the lower part, or all 64 bits of a 32 bit * 32 bit multiplication), or you tell the compiler that it needs to use a 64 bit integer datatype. I wouldn't expect it to come up with optimal (super-fast) code however.
I hope you have a program-example in assembler or C for me, how to get this upper 4byte of the multiplikation (int * int).
Of cause i know The Compiler is allways right, i'am allways doing wrong... but how to change to the other side ;-) ;-) ;-)
:-)
"I hope you have a program-example in assembler or C"
Any particular reason you don't like the examples provide thusfar?
Any particular reason you don't like the examples provide thusfar? as i havent used unions before, i'am afraid of getting large and slow code.
I will test it tomorrow, i promise :-)
I hope you have a program-example in assembler or C
Actually, I don't.
I have a copy of the ARM instruction set here, which describes the MUL (32x32 bit multiplication, least significant 32 bits as result) and SMMUL (32x32 bit multiplication, most significant 32 bits as result) assembly instructions.
If you don't want to get your hands dirty doing assembly, there's enough examples here already that show how to do it in C using long long ints. Of course, this might not be super-fast, depending on the compiler. Maybe the compiler is smart enough to recognize something along the lines of
unsigned long long r; unsigned long a, b; ... r = (unsigned long long) a * b;
as a single 32x32 multiplication, maybe it is not. Take your chances.
as i havent used unions before,
Maybe you need to learn to walk before trying to run a marathon ?
i'am afraid of getting large and slow code.
Since you're not familiar with the internal architecture of ARM, how do you know that something will generate large and slow code ?
Of course, you can also try to do everything with 32 bit integers, using some elementary school-level maths:
(off the top of my head)
unsigned int a, b, ah, al, bh, bl, r1, r2, r3, r4, msw, lsw; ... ah = a >> 16; al = a & 0x0000FFFF; bh = b >> 16; bl = b & 0x0000FFFF; r1 = ah * bh; r2 = ah * bl; r3 = al * bh; r4 = bl * bl; msb = r1 + r2 >> 16 + r3 >> 16; r2 = r2 << 16; r3 = r3 << 16; lsb = r2 + r3; if((lsb < r2)) { msb = msb + 1; } lsb += r4; if((lsb < r4)) { msb = msb + 1; }
Do you think this kludge is going to be faster (on an ARM) than using long long ints ?
r4 = bl * bl;
should be
r4 = al * bl;
and all occurrences of msb/lsb should be msw/lsw.
Hi, here's my solution in Assembler:
//********************************************************************* // A unsigned multiply in ARM Assembler // Returns the upper 4 byte of a 32*32-bit-multiplication //********************************************************************* AREA ?C?bla, CODE, READONLY, ALIGN=2 PUBLIC MUL32x32_ret_upper?A MUL32x32_ret_upper?A PROC CODE32 UMULL R2,R0,R1,R0 ;R0,R2 := R1*R0 bx lr ; return R0 ENDP END //*********************************************************************
Looks good. I like it. Thanks for posting.