Forum > General

Saving XMM register state

(1/2) > >>

Hello, just started migrating a very large Delphi project to FPC/Lazarus (because I found out FPC has vectorcall!) and I'm running into some problems with saving XMM register state. Previously I would do this:

  movdqa   [rsp-24], xmm6  // When entering the function

  movdqa   xmm6, [rsp-24]  // When exiting the function

But with FPC this causes an access violation. I guess FPC handles the stack differently from Delphi and this is why I'm running into problems
(I do have  {$MODE Delphi} and {$asmmode intel} set).

Any idea what the differences in the stack are and how I can fix this?

Also, I'm assuming I need to preserve the state of the same registers as I would in Delphi or MSVC? (xmm6-15, RDI, RSI, RBX, RBP, RSP, R12, R13, R14, R15)?


Another somewhat related question. Can I somehow declare global constants and variables that are 16 byte aligned?

Like in Delphi you shouldn't directly save but let the compiler do it.

Your example is somewhat weird since it addresses the stack at -24 which is not a multiple of 16 byte. Of course that can still be ok, but better be sure.

Unfortunately, the Delphi and FPC ways to dealing with this are different. Delphi has the .pushnv pseudo instructions, and FPC uses an ASM block with a register list to save in the END[ block.

For a source that does both see

the standard stuff don't work for you?

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Function Test(A:Integer):Integer; Assembler; Var{$ASMMODE INTEL}   I:Integer; ASm   movdqa I, xmm6;   movdqa xmm6, I; end;                       
Put a break point on that and see what you have. A Stack is generated so you can store your variable as you can see there.

First, you can add “assembler; nostackframe” procedure directives so your stack pointer will be at 16N + 8. By subtracting another 16N + 8, you will have aligned pointer again.

This is because the stack is aligned (by convention) before the call, so pushing the return address itself misaligns it by 8. Without nostackframe, there is also an implicit push rbp so your stack is aligned right away and subtracting anything but 16N misaligns it (at least without local variables).

Second, you should not access [rsp − N]. First subtract N, then access non-negative offsets. At least on Windows, all memory below rsp is volatile and can change at any time.

--- Quote from: Madoc on November 24, 2023, 11:30:31 pm ---Another somewhat related question. Can I somehow declare global constants and variables that are 16 byte aligned?

--- End quote ---

Either try but beware of bugs, or, better, use align modifier for records.


[0] Message Index

[#] Next page

Go to full version