为什么Windows x64调用约定不使用XMM寄存器传递超过4个整数args?

问题描述 投票:4回答:2

(微软)x64 calling convention说:

参数在寄存器RCX,RDX,R8和R9中传递。如果参数是float / double,则它们在XMM0L,XMM1L,XMM2L和XMM3L中传递。

这很好,但为什么只是漂浮/双打?为什么不通过XMM寄存器传递整数(也可能是指针)? 似乎有点浪费可用空间,不是吗?

windows assembly x86-64 sse calling-convention
2个回答
6
投票

因为非FP值(即整数和地址)上的大多数操作被设计为使用通用寄存器。

存在整数SSE操作但它们仅是算术的。

因此,如果调用约定支持通过SSE寄存器传递整数和地址,则几乎总是需要将值复制到通用寄存器。


2
投票

函数通常希望使用带指针的整数args(作为索引或将结束指针计算为循环边界),或与GP寄存器中的其他整数args一起使用。或者从内存加载的其他整数,他们想要在GP寄存器中使用

您不能有效地将XMM reg中的整数用作循环计数器或绑定,因为没有打包整数比较为分支指令设置整数标志。 (pcmpgtd创建一个0 / -1元素的掩码)。

另请参阅Why not store function parameters in XMM vector registers?和其他答案。


但即便如此,这个设计理念甚至不是Windows x64 fastcall / vectorcall的选项。

Windows x64选择浪费空间以简化可变参数功能。寄存器args可以转储到返回地址上方的32字节“阴影空间”/“home空间”中,以形成args数组。

这就是为什么(例如)Windows x64在R8或XMM2中传递第3个arg,而不管早​​期args的类型。为什么调用可变参数函数也需要将FP args复制到相应的整数寄存器,因此函数序言可以转储arg regs而不必确定哪些变量args是FP,哪些是整数。

为了使arg-array工作,只有4个args可以在寄存器中传递,无论你是否混合了整数和FP args。有足够的GP整数寄存器来保存寄存器args的最大数量,即使它们都是整数。


(与x86-64 System V不同,无论使用多少整数/指针arg传递寄存器,都会在xmm0..7中传递第一个最多8个FP args。)

Why does Windows64 use a different calling convention from all other OSes on x86-64?

© www.soinside.com 2019 - 2024. All rights reserved.