#176998 - Dwedit - Fri Nov 18, 2011 8:15 pm
According to the Arm Procedure Call Standard, there is only one efficient way to return values greater than 32-bits from a function, and that is to use 64-bit integers. A struct that consists of two int values will not work, since it will force the compiler to use the stack.
So here's an example of how to efficiently return two ints from a function:
When you want to call ExampleFunction, you can just use something like "AssignToTwoInts(ExampleFunction(a,b),a,b)".
ExampleFunction gives this assembly code:
If you look at the assembly code for this example function, you can see that despite creating a temporary union value and assigning variables to it, the compiler simply returns the two ints as r0 and r1. r0 and r1 also happen to be the first two int arguments to a function, so you can make fast functions that taken in two ints, do something, then return the next two ints to use.
Additionally, the compiler is also smart enough to properly handle inlining the function that returns two integers.
Compile this at at least -O1, otherwise you get really bad code.
I also tried other ways to build and separate a 64 bit value, but only the union/struct method seemed to generate good code. Bit shifting didn't work very well.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
So here's an example of how to efficiently return two ints from a function:
Code: |
typedef unsigned int u32; typedef unsigned long long u64; typedef union { u64 doubleword; struct { u32 a; u32 b; } words; } doubleword; #define ReturnTwoInts(a,b) \ {\ doubleword dw;\ dw.words.a = (a);\ dw.words.b = (b);\ return dw.doubleword;\ } #define AssignToTwoInts(c,a,b) \ {\ doubleword dw;\ dw.doubleword = (c);\ (a) = dw.words.a;\ (b) = dw.words.b;\ } u64 ExampleFunction(u32 a, u32 b) { a+=4; b+=4; ReturnTwoInts(a,b); } |
When you want to call ExampleFunction, you can just use something like "AssignToTwoInts(ExampleFunction(a,b),a,b)".
ExampleFunction gives this assembly code:
Code: |
ExampleFunction: add r0, r0, #4 add r1, r1, #4 bx lr |
If you look at the assembly code for this example function, you can see that despite creating a temporary union value and assigning variables to it, the compiler simply returns the two ints as r0 and r1. r0 and r1 also happen to be the first two int arguments to a function, so you can make fast functions that taken in two ints, do something, then return the next two ints to use.
Additionally, the compiler is also smart enough to properly handle inlining the function that returns two integers.
Compile this at at least -O1, otherwise you get really bad code.
I also tried other ways to build and separate a 64 bit value, but only the union/struct method seemed to generate good code. Bit shifting didn't work very well.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."