It's a bit of a newbie question, but I've been wondering if you can intermix hard float VFPv3-D16 code with VFPv3-D32 code. You can as:
According to the ABI: * d0-d15 are used for floating point parameters, no matter if you are D16 or D32 * d0-d15 are not preserved across function calls * d16-d31 must be preserved across function calls
The scenarios are: A D32 function calls a D16 function: * The first 16 (!) parameters are passed in D0-D15 * Any remaining are passed on the stack * The D16 function doesn't know about D16-D31, doesn't use them, and hence preserves them
A D16 function calls a D32 function: * The first 16 parameters are passed in D0-D15 * Any remaining are passed on the stack * The D32 function preserves any of the D16-D31 registers that it uses. Redundant, but fine.
A D32 function (A) calls a D16 function (B) which calls a D32 function (C): * Parameters are OK, as above * B doesn't use D16-D31 and hence preserves them * C preserves any of the D16-D31 that it uses, which preserves them from A's point of view
-- Michael
Hi,
On Wed, Nov 24, 2010 at 9:49 PM, Michael Hope michael.hope@linaro.org wrote:
It's a bit of a newbie question, but I've been wondering if you can intermix hard float VFPv3-D16 code with VFPv3-D32 code. You can as:
According to the ABI: * d0-d15 are used for floating point parameters, no matter if you are D16 or D32 * d0-d15 are not preserved across function calls * d16-d31 must be preserved across function calls
No, I don't think that's correct - see the procedure call standard section 5.1.2.1 "VFP register usage conventions (VFP v2, v3 and the Advanced SIMD Extension)"
It's not too hard to misread ... my understanding is as follows---
* d0-d7 (s0-s15; q0-q3) are not callee-saved and are the only regs used for parameter and return value exchange in the standard ABI variants * d8-d15 (s16-s31; q4-q7) are _callee-saved_ * d16-d31 (q8-q15) are _not callee-saved_
Any time a function calls an unknown function with live data in d0-d7 or d16-d31, the caller must preserve and restore them around the call to avoid losing the data.
By definition, a D16 function never has live data in d16-d31 (since the registers don't exist from its point of view) - so such functions don't need to care about any related saving/restoring. If the D16's functions own caller had live data in those regs, that caller would already have had to preserve them in order to call the D16 function - so the D16 function can call other functions (uncluding D32) with impunity.
So basically, D32 code just gets to use d16-d31 for extra scratchpad bandwidth _in between_ external function call sites. (Of course, compiler-generated or hand-written code can relax the rules locally in some circumstances, just as for the integer ABI)
Note that in your scenarios below, it is d0-d7 and not d0-d15 which are used to pass arguments.
Cheers ---Dave
The scenarios are: A D32 function calls a D16 function: * The first 16 (!) parameters are passed in D0-D15 * Any remaining are passed on the stack * The D16 function doesn't know about D16-D31, doesn't use them, and hence preserves them
A D16 function calls a D32 function: * The first 16 parameters are passed in D0-D15 * Any remaining are passed on the stack * The D32 function preserves any of the D16-D31 registers that it uses. Redundant, but fine.
A D32 function (A) calls a D16 function (B) which calls a D32 function (C): * Parameters are OK, as above * B doesn't use D16-D31 and hence preserves them * C preserves any of the D16-D31 that it uses, which preserves them from A's point of view
-- Michael
linaro-toolchain mailing list linaro-toolchain@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-toolchain
On Fri, Nov 26, 2010 at 12:00 AM, Dave Martin dave.martin@linaro.org wrote:
Hi,
On Wed, Nov 24, 2010 at 9:49 PM, Michael Hope michael.hope@linaro.org wrote:
It's a bit of a newbie question, but I've been wondering if you can intermix hard float VFPv3-D16 code with VFPv3-D32 code. You can as:
According to the ABI: * d0-d15 are used for floating point parameters, no matter if you are D16 or D32 * d0-d15 are not preserved across function calls * d16-d31 must be preserved across function calls
No, I don't think that's correct - see the procedure call standard section 5.1.2.1 "VFP register usage conventions (VFP v2, v3 and the Advanced SIMD Extension)"
It's not too hard to misread ... my understanding is as follows---
* d0-d7 (s0-s15; q0-q3) are not callee-saved and are the only regs used for parameter and return value exchange in the standard ABI variants * d8-d15 (s16-s31; q4-q7) are _callee-saved_ * d16-d31 (q8-q15) are _not callee-saved_
Ah, I got the s* and d* registers mixed up. So if you have a function which takes doubles, the first eight parameters go in registers. If the function takes floats, then the first sixteen go in registers. D8-D15 are preserved across calls, D16+ aren't.
So basically, D32 code just gets to use d16-d31 for extra scratchpad bandwidth _in between_ external function call sites. (Of course, compiler-generated or hand-written code can relax the rules locally in some circumstances, just as for the integer ABI)
I think the conclusion is the same: you can intermix VFP-D16 and VFP-D32 code as D16 code doesn't use D16-D31 and D32 code doesn't expect D16-D31 to be preserved across function calls.
-- Michael
On Thu, Nov 25, 2010 at 10:15 PM, Michael Hope michael.hope@linaro.org wrote:
On Fri, Nov 26, 2010 at 12:00 AM, Dave Martin dave.martin@linaro.org wrote:
Hi,
On Wed, Nov 24, 2010 at 9:49 PM, Michael Hope michael.hope@linaro.org wrote:
It's a bit of a newbie question, but I've been wondering if you can intermix hard float VFPv3-D16 code with VFPv3-D32 code. You can as:
According to the ABI: * d0-d15 are used for floating point parameters, no matter if you are D16 or D32 * d0-d15 are not preserved across function calls * d16-d31 must be preserved across function calls
No, I don't think that's correct - see the procedure call standard section 5.1.2.1 "VFP register usage conventions (VFP v2, v3 and the Advanced SIMD Extension)"
It's not too hard to misread ... my understanding is as follows---
* d0-d7 (s0-s15; q0-q3) are not callee-saved and are the only regs used for parameter and return value exchange in the standard ABI variants * d8-d15 (s16-s31; q4-q7) are _callee-saved_ * d16-d31 (q8-q15) are _not callee-saved_
Ah, I got the s* and d* registers mixed up. So if you have a function which takes doubles, the first eight parameters go in registers. If the function takes floats, then the first sixteen go in registers. D8-D15 are preserved across calls, D16+ aren't.
yup
So basically, D32 code just gets to use d16-d31 for extra scratchpad bandwidth _in between_ external function call sites. (Of course, compiler-generated or hand-written code can relax the rules locally in some circumstances, just as for the integer ABI)
I think the conclusion is the same: you can intermix VFP-D16 and VFP-D32 code as D16 code doesn't use D16-D31 and D32 code doesn't expect D16-D31 to be preserved across function calls.
Yes--- agreed (actually, I misread your first paragraph and thought you were arguing that they _couldn't_ be intermixed)
The ABI was deliberately specified that way to allow that AFAIK--- to VFPv3-D32 is just another "extension" which islands of code can optionally use or not use; just like v5E, v6 SIMD or NEON.
Cheers ---Dave
linaro-toolchain@lists.linaro.org