使用SSE在Delphi中进行舍入

Iam*_*mIC 4 delphi sse rounding delphi-7 inline-assembly

我编写了这个函数来将单例转换成整数:

function Round(const Val: Single): Integer;
begin
  asm
    cvtss2si eax,Val
    mov Result,eax
  end;
end;
Run Code Online (Sandbox Code Playgroud)

它有效,但我需要改变舍入模式.显然,按此,我需要设置MXCSR寄存器.

我如何在Delphi中执行此操作?

我之所以这样做的原因是我需要"远离零"舍入(就像在C#中一样),即使通过SetRoundingMode也是如此.

Dav*_*nan 8

在现代Delphi上,要设置MXCSR,您可以SetMXCSR从本System机调用.要读取当前值使用GetMXCSR.

请注意SetMXCSR,就像Set8087CW不是线程安全的一样.尽管我努力说服Embarcadero改变这一点,但似乎这个特殊的设计缺陷将永远留在我们身边.

在旧版本的Delphi中,您使用LDMXCSRSTMXCSR操作码.您可以编写自己的版本,如下所示:

function GetMXCSR: LongWord;
asm
  PUSH    EAX
  STMXCSR [ESP].DWord
  POP     EAX
end;

procedure SetMXCSR(NewMXCSR: LongWord);
//thread-safe version that does not abuse the global variable DefaultMXCSR
var
  MXCSR: LongWord;
asm
  AND     EAX, $FFC0 // Remove flag bits
  MOV     MXCSR, EAX
  LDMXCSR MXCSR
end;
Run Code Online (Sandbox Code Playgroud)

这些版本是线程安全的,我希望能够编译和处理旧的Delphi版本.

请注意,使用Round您的功能名称可能会导致很多混乱.我会建议你不要这样做.

最后,我查看了英特尔文档,两个英特尔浮点单元(x87,SSE)都提供了IEEE754标准规定的舍入模式.他们是:

  • 舍入到最近(偶数)
  • 向下舍入(朝-∞)
  • 向上舍入(朝向+∞)
  • 向零舍入(截断)

因此,您所需的舍入模式不可用.