views:

63

answers:

1

Newbie ARM assembler question. I am writing my first arm assembler program and I am trying to code this C fragment.

int x = somevalue1 << 12; // s19.12 

int y = somevalue2 << 12; // s19.12

int a = somevalue3 << 12; // s19.12 

int b = somevalue4 << 12; // s19.12

int c = somevalue4 << 12; // s19.12

long long acc = (long long) a * b;

acc += (long long) x * y;

int res = (acc >> 24);

acc += (long long) c * a;

I have coded the first part and computed the sum in r10, r11 registers.

@ r6 =a, r4 = b, r0 = x,r2 =y, r3=c

smull r10, r11, r6, r4  @acc = a * b

smlal r10, r11, r0, r2  @acc += x * y

Now I need to extract the value of "res" back from the r10 and r11 registers by right shifting the "long long" by 24 bits. How do I do that ?

-thanks,

+3  A: 

r10 contains the lower 32-bits, and r11 contains the upper 32-bits.

r10           r11
0  1  2  3    4  5  6  7

The result you want looks like this:

r12
3  4  5  6

That is, the final result will include lower 24 bits of r11 and the upper 8 bits of r10. If you use unsigned arithmetic, extracting the bits is that simple. Since you're using signed arithmetic, you need to preserve the sign. Also note that of necessity, you are also discarding the upper 8 bits by converting long long into an integer.

First, let's move lower 24 bits of r11 into their final position. The arithmetic left shift ensures that the sign is preserved.

mov r12, r11 asl #8

Now insert these bits into the appropriate place in r12. We already ensured that the sign was correct for the upper bits, so here, just use a logical shift.

orr r12, r10 lsr #24

The above is equivalent to this C:

r12 = ((signed)r11 << 8);
r12 |= ((unsigned)r10 >> 24);

You can, of course, just let the compiler generate code like this for you. To get the compiler to shift a long long correctly in C you would need to use:

int res = (acc >> 24LL);
jbarlow
Correct apart from the last statement. C's integer promotion rules will never narrow an operand of a binary operator; in `(acc >> 24)`, `24` will be widened to `long long` to match `acc`.
Mike Seymour
@Mike Seymour. Fixed.
jbarlow