If a char parameter is passed to a routine in Aarch64 is the top of the word undefined? and is the same true for if a char value is returned? I think the answer is yes but it would be good to be certain. This means if the char is used in some arithmetic the UXTB, or SXTB for signed, modifiers as described at A64 Shift and Extend Operations: Operand Modifiers must be used in an instruction using a register containing a char passed into or returned from a routine.
I presume the same is true for short as well so a signed short might for instance come in with the top two bytes containing zero
According to AAPCS64, the unused bits have "unspecified value". This is actually a good thing overall, since it removes the need for the caller to explicitly clear those bits before calling a function which doesn't care anyway (because it can use something like UXTB or SXTB). This applies to char, short, int, float, or anything else that doesn't use the full 8 bytes of an X or D register or procedure-call stack slot.
Finally, note that this is different from the 32-bit AAPCS behaviour, where small values have to be zero- or sign-extended.
Thanks very much for that and the reference. That seems to be pretty definitive though unspecfied sounds a bit like they hadn't made up their minds as compared to undefined where one is saying it explicitly. The modifiers in the Aarch64 instructions make it all much easier than for the 32-bit instruction set so zero or sign extended must have made more sense then.
A bit of a niggle occurred to me whilst reading that document. Surely that wouldn't apply to pointers in ILP32? One wouldn't want to be always worrying about the tops of those pointers when they are passed as parameters. I can't see that they would have the top 'unspecified'.
It's not that they hadn't made up their minds as such: it is designed to simplify the argument placement when calling functions that probably don't require it anyway. I think it's a very deliberate decision. (Yes, the extend-mode modifiers make this approach feasible in A64, but less so in ARM and Thumb.)
I haven't experimented much with ILP32, but it does indeed look like the callee has to zero-extend the pointer before using it, so our interpretations agree, at least. (The ILP32 changes are labelled "beta", but I don't know what that really means in this context, and the date on the document is over a year ago.) It does say that the link register and frame pointer use 64-bit stack slots even on ILP32, which is interesting. I'm curious about the reasoning behind that.
I think it would be a big mistake for ILP32 to require that subroutines assume that the top of the pointer parameters might be rubbish. I very much hope that is just an oversight. That will work fine for the integer types because of those modifiers but there's no such modifier for the base register in loads and stores. I know this would be different from how integer type are handled but pointers are very important.
It is a bit strange about the frame format for ilp32, I don't see that there is any real requirement for compatibility with lp64.
I wonder if the frame layout remains the same as LP64 to keep the stack pointer 16-byte aligned even with empty frames.
View all questions in Arm Development Studio forum