Visual Studio和Unity Mono注册了clobbering

问题描述 投票:0回答:1

根据Saving the XMM register before function call,似乎XMM6到XMM15需要通过Windows上的函数调用来保留,但不需要在Linux上保留。

我有一个由Visual Studio 2015编译的本机插件,用于使用Mono的Unity。 C#代码将委托传递给本机插件,该插件将其作为函数指针接收(为了32位构建,注释为stdcall,尽管我遇到的问题是64位代码)。因此,这意味着本机代码可以调用由Mono实现的函数。

当我这样做时,单声道功能似乎是在破坏XMM6到XMM15。 Visual Studio编译的代码显然没有预料到这一点,并且会出现故障。

有什么方法可以解决这个问题吗?是否可以注释特定的函数指针,以便Microsoft知道它们的行为是错误的?我们可以调用内在函数来保存和恢复那些我们知道有这个问题的调用吗?其他想法?


编辑并进一步发现:

寄存器仅在第一次调用给定的C#函数时被破坏。我已将它追溯到Mono AMD64普通蹦床。 This commit修复了这个bug,但Unity使用了旧版本的Mono,它仍然拥有它。问题是XMM0到XMM7是使用MOVSD保存和恢复的,#include <immintrin.h> alignas(16) std::array<uint8_t, 512> regs; _fxsave64(regs.data()); callToMonoGoesHere(); _fxrstor64(regs.data()); 只保存低64位并将高64位重置为0,而XMM8到XMM15根本没有保存,这可能很重要,如果要使用它们。

mono 64bit pinvoke cpu-registers
1个回答
0
投票

这似乎适用于简单的情况:

alignas(16) std::array<uint8_t, 512> before, after;
_fxsave64(before.data());
float f = callToMonoGoesHere();
_fxsave64(after.data());
memcpy(after.data() + 256, before.data() + 256, 160); //XMM6 to 15
_fxrstor64(after.data());

如果函数返回浮点值,则必须执行额外的步骤:

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