ar18 wrote: ↑30 Aug 2018 00:34
if you decide to not support this, then make it clear in your documentation that €ASM only partially supports the Win64 ABI.
Actually it's not €ASM's job to support various ABI invokations (Win64, SystemV, Delphi etc), they are implemented as external macros, totally in the hands of €ASM users. So let's make them more compliant.
Current version (20180804) of macros
WinAPI and
Invoke push all arguments (at least four) on stack, which reserves the shadow space, too, and allows to use scratch registers as macro operands in arbitrary order. Then are RCX,RDX,R8,R9 loaded from the shadow space and function is called. The function now has all its arguments available on stack frame:
%1 is in [RBP+16] and RCX
%2 is in [RBP+24] and RDX
%3 is in [RBP+32] and R8
%4 is in [RBP+40] and R9
%5 is in [RBP+48]
%6 is in [RBP+56]
and so on.
If any of the first four argument is declared as float, the function expects it in the lower half of XMM0,XMM1.XMM2,XMM3 instead of RCX,RDX,R8,R9. Lets load those XMM registers from RCX,RDX,R8,R9 immediately after they have been loaded from the shadow space, regardless if their arguments were declared as float or not. XMM0..XMM5 as well as RCX,RDX,R8..R11 are caller-save, so nobody will miss their original contents.
%1 is in [RBP+16] and RCX and XMM0
%2 is in [RBP+24] and RDX and XMM1
%3 is in [RBP+32] and R8 and XMM2
%4 is in [RBP+40] and R9 and XMM3
%5 is in [RBP+48]
%6 is in [RBP+56]
and so on.
This solution requires four instructions (MOVQ XMM0,RCX etc) which would bloat every Invoke, so they should be emitted on demand only, when the function uses floating-point argument(s). I'm considering boolean keyword operand SIMD=No|Yes added to macros
Invoke and
WinAPI. This would be backward compatible with their current version, which is already used in sample programs.
ar18 wrote: ↑30 Aug 2018 18:34
That is the purpose of having a PROTO in the vast majority of all other assemblers. Personally I don't like protos. They make the language verboose, less readable, and bloat the code.
Ditto.
ar18 wrote:
You only need to check for the xmm register type because that is the only SIMD type the ABI specifies, and even then it is specified as a QWORD value instead of the default 128-bit value of the xmm registers.
movq r11,xmm
push r11
Now, when the first four argument values are correctly passed in registers, let's look at the possibility to use XMM as ordinal operands in
Invoke and
WinAPI.
Presence of XMM register in operands can be checked with
%IF "%1[1..3]" == "XMM"
MOVQ R11,%1
PUSH R11
%ELSE
PUSHQ %1
%ENDIF
but it's not much reliable. User could pass a symbolic value defined as
XmmIsGood EQU 1234 and this would throw false positive.
You can enhance macro
Invoke if you need this for your Paint functions, but somehow I should solve the asm-time register recognition anyway, which will take some time. Anyway, thank you for testing, Andy.