* * *

Author Topic: Strange Floating Point XMM Errors on WIN64  (Read 2084 times)

schuler

  • Jr. Member
  • **
  • Posts: 90
Strange Floating Point XMM Errors on WIN64
« on: October 13, 2017, 09:07:17 am »
 :) Hello Pascal Lovers  :)

I'm not sure if I'm typing here with the goal to save time to others in the case that they get the same error as I got or if I want to know if I found a bug. Anyway, here we go.

I have 3 functions: A, B and C. Function A calls B. B calls C. C contains both pascal and asm code.

Function A shows strange floating point errors including division by zero error.

This is a portion of function C:

Code: Pascal  [Select]
  1.   asm
  2.   ...
  3.   vmovups ymm6, [rax+64]
  4.   ...
  5.     end
  6.   [
  7.     'RAX',
  8.     'XMM6',
  9.     'ymm6'
  10.   ];
  11.  

After 4 or 5 hours debugging, I found that a floating point value stored on XMM6 on function A was being lost. Then, I found this link:

http://wiki.lazarus.freepascal.org/Win64/AMD64_API

From above link, I can read:
Quote
other nonvolatile registers, if used, should be pushed on stack. These registers are R12 through R15, RDI, RSI, RBX, XMM6 through XMM15

I though that signaling usage of either XMM6 or YMM6 would solve the problem:
https://www.freepascal.org/docs-html/prog/progse12.html#x149-1500003.4

But I think that this is not the case. Not sure if this is a bug or not. If I were coding the compiler, I would not to be sure although I'm tempted to look at how the signaling was implemented.

HOW TO SOLVE
This is how I solved in my case:

Code: Pascal  [Select]
  1. var
  2.   mxmm6: array[0..3] of Single;
  3. begin
  4.   ...
  5.   asm
  6.   movups mxmm6, xmm6  // saves xmm6
  7.   ...
  8.   movups xmm6, mxmm6 // restores xmm6 - YAY!!!
  9.   end ['RAX'];
  10.  

So far, this problem shows up on Windows 64 only. Linux 64 with same code works well so far.

Please feel free to comment.

:) wish everyone happy coding :)

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6540
Re: Strange Floating Point XMM Errors on WIN64
« Reply #1 on: October 13, 2017, 10:01:48 am »
Some tips:

Please try to make a small demo that demonstrates the problem, that we can compile with -a on various branches. Fragments can be useful if sb directly sees the problem, but this probably requires further investigation

ABI only knows and saves XMM registers, the upper part of YMM is always considered lost.

If you use YMM you are supposed to run a vzeroupper afterwards, though afaik that is only a performance optimization.

schuler

  • Jr. Member
  • **
  • Posts: 90
Re: Strange Floating Point XMM Errors on WIN64
« Reply #2 on: October 15, 2017, 08:06:25 am »
Hello Marcov,
I'll try to create a small demo and post here.

Thank you for your help.

schuler

  • Jr. Member
  • **
  • Posts: 90
Re: Strange Floating Point XMM Errors on WIN64
« Reply #3 on: October 25, 2017, 02:07:06 am »
MARCOV!!!

Just been able to reproduce with:
Code: Pascal  [Select]
  1. procedure TestC(); inline;
  2. begin
  3.   asm
  4.     vxorps xmm6, xmm6, xmm6
  5.   end ['XMM6','YMM6'];
  6. end;
  7.  
  8. procedure TestA();
  9. var
  10.   S1: Single;
  11. begin
  12.   S1 := 1;
  13.  
  14.   TestC();
  15.  
  16.   WriteLn(S1:4:2);
  17. end;
  18.  

If you call TestA above, you'll see that 1 is loaded into xmm6. Then, xmm6 is zeroed by TestC.

Should I log a bug report?

 :) Wish everyone happy coding :)

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6540
Re: Strange Floating Point XMM Errors on WIN64
« Reply #4 on: November 05, 2017, 04:41:00 am »
I can't quickly reproduce since my local build seems corrupt (keeps saying can't find identifier XMM6).

I think having both xmm6 and ymm6 in the save register list is wrong (should be only ymm6), and probably never inlinable.

But yes, file a bug even if only for better errrorgeneration

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus