This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Arm7 long multiply in C

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.

Parents Reply Children
  • "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.