Recent

Author Topic: x64 assembly routine - size of integer parameter is ignored  (Read 1529 times)

ncs-sniper

  • Jr. Member
  • **
  • Posts: 53
Hello all!
Today, I have finally updated Lazarus to new version (2.2.2, FPC 3.2.2) - I was using Laz 2.0.8 (FPC 3.0.4) - and tried to compile some of my code to see what is broken 8).

I have found that the x64 compiler simply ignores size of integer parameters in assembly. Let's have following code:
Code: Pascal  [Select][+][-]
  1. {$MODE ObjFPC}
  2. {$ASMMODE Intel}
  3. ...
  4. procedure Foo(Value: Byte); register; assembler;
  5. asm
  6.   MOVZX   EDX,  Value
  7. end;
  8.  
In x86, this is correctly compiled as
Code: Pascal  [Select][+][-]
  1. 0fb6d0  movzbl %al,%edx
... but in x64, the compiler just throws error:
Code: Pascal  [Select][+][-]
  1. Error: Asm: [movzx reg32,reg32] invalid combination of opcode and operands

Ok, I can work around it - for example not using parameter names and writing the registers directly (which is annoying as they differ in windows and linux). But it gets worse, because this:
Code: Pascal  [Select][+][-]
  1. procedure Foo(Value: Byte); register; assembler;
  2. asm
  3.   MOV   DL,  Value
  4. end;
... is in x64 compiled as:
Code: Pascal  [Select][+][-]
  1. 89ca  mov    %ecx,%edx
which is imho totally wrong, and no error or warning is issued. If you expect higher 24bits of EDX to be preserved (they should be), you are in for a nasty surprise. The same happens whether you use Intel or ATT syntax.

This was not hapenning in FPC 3.0.4 that I was using before, there it produces:
Code: Pascal  [Select][+][-]
  1. 88ca  mov    %cl,%dl

Am I wrong here, am I missing something, or is this a bug? And is it known? If this is to be expected, can someone point me to some documentation describing this?

Note - I am not able to go and try newer FPC versions.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #1 on: June 18, 2022, 10:04:41 am »
FPC trunk compiles it fine to    movzbl   %cl,%edx on win64. (AT&T style)

ncs-sniper

  • Jr. Member
  • **
  • Posts: 53
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #2 on: June 18, 2022, 03:28:36 pm »
Yes, trunk compiles it correctly, but still - 3.2.2 is bundled with current Lazarus, so I gues it is (one of) the most widespread version. And if this is confirmed (I have tried three instalations myself, all manifest this error), then it is, at least for me, a serious bug - it can break completely valid asm code that was previously working. Seriously, it changes width of the explicitly requested register without issuing warning or even a note.
So, can anyone confirm this behaviour? And does anyone know any workaround, save for rewriting all assembly that uses parameters via their names?
« Last Edit: June 18, 2022, 05:24:45 pm by ncs-sniper »

Thaddy

  • Hero Member
  • *****
  • Posts: 14214
  • Probably until I exterminate Putin.
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #3 on: June 18, 2022, 03:54:10 pm »
1. The 3.2.2 fixes branch might also work (current)
2. If not, ask for a back-port to fixes from trunk on the bug tracker
3. Otherwise be patient or use trunk.

This is the usual order. Back-ports to a release are very, very rare.
Specialize a type, not a var.

WooBean

  • Full Member
  • ***
  • Posts: 229
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #4 on: June 18, 2022, 04:34:12 pm »
@ncs-sniper
Proposed workarround for 64bit code (if you want to save unchanged large blocks of asm code with using named parameters):

Code: Pascal  [Select][+][-]
  1. {$IFDEF CPUX86_64}
  2. procedure Foo(Value: Byte); register;
  3. begin
  4.   asm
  5.    MOVZX   EDX,  Value;
  6.   end;
  7. end;
  8. {$ELSE}
  9. procedure Foo(Value: Byte); register; assembler;
  10. asm
  11.   MOVZX   EDX,  Value
  12. end;
  13. {$ENDIF}
  14.  

BTW see doc at https://www.freepascal.org/docs-html/ref/refsu89.html#x210-23400014.9.18 which is not much promissing for the future.
« Last Edit: June 18, 2022, 04:38:17 pm by WooBean »
Platforms: Win7/64, Linux Mint Ulyssa/64

ncs-sniper

  • Jr. Member
  • **
  • Posts: 53
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #5 on: June 18, 2022, 05:19:00 pm »
I am fully aware that register calling convention is 32bit-only, in x64 it never had any effect and was ignored. Technically it has no effect even in x86, because register is the default calling convention, so specifying it is superfluous. I am using it pretty much only for delphi compatibility, which is pecifically mentioned in the document you linked.

As for your workaround, that is unfortunatelly not exactly equivalent and I cannot use it in most cases (the real functions are more complex and this could and would break them).
« Last Edit: June 18, 2022, 05:20:57 pm by ncs-sniper »

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #6 on: June 18, 2022, 05:56:04 pm »
In intel mode, if memory serves I believe you may need to help it a little.

using BYTE PTR in the phrase for example and things like that to help the inline ASM better evaluate the phase otherwise it may take the best optimize route.

 I would need to look at the exact details but I its there.
The only true wisdom is knowing you know nothing

ncs-sniper

  • Jr. Member
  • **
  • Posts: 53
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #7 on: June 18, 2022, 06:23:07 pm »
Using BYTE PTR [Value] will load byte from memory address stored in parameter Value, not the Value itself.
I know of no construct how to force assembler to use proper size. Even in AT&T syntax, with instruction mnemonics suffix...
Code: Pascal  [Select][+][-]
  1. movb   %DL, Value
... is compiled as:
Code: Pascal  [Select][+][-]
  1. 8bca  mov    %edx,%ecx
%)
« Last Edit: June 18, 2022, 06:36:33 pm by ncs-sniper »

WooBean

  • Full Member
  • ***
  • Posts: 229
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #8 on: June 18, 2022, 06:44:06 pm »
I am fully aware ....

As for your workaround, that is unfortunatelly not exactly equivalent ....

What do you mean by  x64 compiler and what were  targets of compilation? I tried your sample from Win7/64, Lazarus 2.2.0, FPC 3.2.2, x86_64-win64 and first platform target was win32/i386 and second win64/x86_64. First platform - win32/i383 target was compiled OK. As for target win64/x86_64 code was not compiled sucessfully (error message axactly matched your info).
My workaround proposal solves problem defined at initial post (assuming your target is win64/x86_64).
Platforms: Win7/64, Linux Mint Ulyssa/64

Thaddy

  • Hero Member
  • *****
  • Posts: 14214
  • Probably until I exterminate Putin.
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #9 on: June 18, 2022, 06:53:58 pm »
Your work-around would be temporary and that contaminates code.
Use fixes or trunk if you really need it.
Specialize a type, not a var.

ncs-sniper

  • Jr. Member
  • **
  • Posts: 53
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #10 on: June 18, 2022, 06:57:46 pm »
Targets were x86_64 linux (lin64) and x86_64 win64. By x64 i mean a compiler that compiles into AMD64/x86-64 binaries, irrespective of OS (btw. I know ABIs are different in Win64 and other x64 systems).
It solves the sample code, yes, but I cannot use it in real-life code.
Will try the 3.2.3 (3.2 fixes branch) now.

EDIT
So I have tested 3.2.3 - the error is still there.
To be more clear - I don't mind the MOVZ thing being marked as error, as I have said I can work with that. Really the problem is silent change of register width in case of MOV DL, Value.
« Last Edit: June 18, 2022, 09:57:44 pm by ncs-sniper »

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #11 on: June 19, 2022, 03:37:41 pm »
I just tested 3.2.0 here and yes, it compiles as you stated, using 32 bit registers but 3.0.4 works well.

This maybe one of the issues I have where i can't get a DLL i have to work correctly using the 3.2.0 compiler because of other things I found I also use a lot asm code in there to speed the process up.

 Currently the DLL remains in 3.0.4 land.
The only true wisdom is knowing you know nothing

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #12 on: June 20, 2022, 10:11:42 am »
I tested, and up to date fixes branch, 3.2.3 still gives the error.

So please file a bug mentioning that trunk is ok, and fixes not, and if the relevant fix could be merged to fixes (for 3.2.4's sake)

ncs-sniper

  • Jr. Member
  • **
  • Posts: 53
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #13 on: June 20, 2022, 11:16:25 am »
I am currently on waaaay old computer with old browser, so if the gitlab will work, I will do. Is following the correct place?
https://gitlab.com/groups/freepascal.org/fpc/-/issues

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: x64 assembly routine - size of integer parameter is ignored
« Reply #14 on: June 20, 2022, 11:57:58 am »
Yes

 

TinyPortal © 2005-2018