Suppose we have a C (or C++) function with the following signature:
void foo(int64_t a, double b, int64_t c, double d);
When compiled on Linux, Mac, or any OS that uses the System V ABI (x86_64), a and c get passed in the rdi and rsi registers, and b and d get passed in xmm0 and xmm1. Okay, nothing wrong with that. But then I do the same in Windows (x86_64), and it looks like it skips some registers. a and c get passed in rcx and r8 (rdx skipped), and b and d get passed in xmm1 and xmm3 (xmm0 and xmm2 skipped). Why does the Win64 do this instead of "compacting" the arguments like System V? With System V, I imagine being able to pass, say, 4 qwords and 4 doubles without needing to pass anything on the stack, whereas Win64, as I'm guessing it would, would pass anything past the 4th argument on the stack.
I am aware of the differences in the order of the registers in argument passing in Win64 vs SysV, but order shouldn't be relevant. I'm just curious as to why Win64 would skip over registers, especially when it only has 4 for non-stack argument passing.