ASM Calling convention differences beetween FPC 3.0.4 and 3.3.1 lazarus / 64-FPC development ---------------------------------------------------------------------- BeanzMaster · 2019-07-06 11:14 Hi to all i want to update my vector math lib  here : https://github.com/jdelauney/SIMD-VectorMath-UnitTest for FPC 3.0.4 to fpc 3.1.x min and up. Actually i have Lazarus 2.1 with fpc 3.3.1 SVN Rev 61197 installed So. Actually i'm declaring my record for 2D Integer vector, as is (same way for 2D Single, Double Vector, 4D Single,..... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Type  TBZVector2iType = packed array[0..1] of Integer; //< Tableau aligné pour les vecteurs 2D Integer   { TBZVector2i : Vecteur 2D Integer }  TBZVector2i = record     { Initialisation des valeurs X et Y value }  procedure Create(aX, aY:Integer); overload;     { Retourne une chaine de caractères formaté représentant le vecteur : '(x, y)' }    function ToString : String;     { Ajoute deux vecteurs TBZVector2i      Exemple (V1, V2 et resultat sont des variables de type TBZVector2i  :      Resultat := V1 + V2;}    class operator +(constref A, B: TBZVector2i): TBZVector2i; overload;     { Ajoute un vecteurs TBZVector2i avec une variable de type Integer      Exemple (V12 et resultat sont des variables de type TBZVector2i, I est de type Integer  :      Resultat := V1 + I ;}    class operator +(constref A: TBZVector2i; constref B:Integer): TBZVector2i; overload;     { Ajoute une variable de type Single a un vecteurs TBZVector2i avec      Exemple (V12 et resultat sont des variables de type TBZVector2i, I est de type Single  :      Resultat := V1 div I ;}    class operator +(constref A: TBZVector2i; constref B:Single): TBZVector2i; overload;  .....     function Abs:TBZVector2i;overload;     case Byte of      0: (V: TBZVector2iType);      1: (X, Y : Integer);      2: (Width, Height : Integer);  end; and currently, with FPC 3.0.4 I have the following implementation : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i class operator TBZVector2i.+(constref A, B: TBZVector2i): TBZVector2i;assembler; nostackframe;register;asm  movq  xmm0, [A]  movq  xmm1, [B]  paddd xmm0, xmm1  movq  RAX, {%H-}xmm0end; class operator TBZVector2i.+(constref A: TBZVector2i; constref B:Single): TBZVector2i;  assembler; nostackframe; register;asm  movq   xmm0, [A]  movq   xmm1, [B]  pshufd xmm1, xmm1, $00  paddd xmm0, xmm1  movq   RAX, {%H-}xmm0end; class operator TBZVector2i.+(constref A: TBZVector2i; constref B:Integer): TBZVector2i; assembler; nostackframe; register;asm  movq   xmm0, [A]  movq   xmm1, [B]  pshufd xmm1, xmm1, $00  paddd xmm0, xmm1  movq   RAX, {%H-}xmm0end; With FPC 3.3.1 i would like to implement VectorCall so i did this Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$IF fpc_fullversion >= 030100}   {$DEFINE USE_VECTORCALL}{$ENDIF}     class operator TBZVector2i.+(constref A, B: TBZVector2i): TBZVector2i; {$ifdef USE_VECTORCALL} vectorcall {$else} register; {$endif} assembler; nostackframe;asm  {$ifndef USE_VECTORCALL}  movq  xmm0, [A]  movq  xmm1, [B]  {$endif}  paddd xmm0, xmm1  movq  RAX, {%H-}xmm0end; class operator TBZVector2i.+(constref A: TBZVector2i; constref B:Single): TBZVector2i; {$ifdef USE_VECTORCALL} vectorcall {$else} register; {$endif} assembler; nostackframe;asm  {$ifndef USE_VECTORCALL}  movq   xmm0, [A]  movq   xmm1, [B]  {$endif}  pshufd xmm1, xmm1, $00  paddd xmm0, xmm1  {.$ifndef USE_VECTORCALL}  movq   RAX, {%H-}xmm0  {.$endif}end;  class operator TBZVector2i.+(constref A: TBZVector2i; constref B:Integer): TBZVector2i; {$ifdef USE_VECTORCALL} vectorcall {$else} register; {$endif} assembler; nostackframe;asm  {$ifndef USE_VECTORCALL}  movq   xmm0, [A]  movq   xmm1, [B]  {$endif}  pshufd xmm1, xmm1, $00  paddd xmm0, xmm1  movq   RAX, {%H-}xmm0end; FPC say Quotevectormath_vector2i_win64_sse_imp.inc(3,28) Error: Calling convention doesn't match forward BZVectorMath.pas(233,20) Error: Found declaration: operator +(constref TBZVector2i;constref TBZVector2i):; Static; BZVectorMath.pas(263,20) Error: Found declaration: operator +(constref TBZVector2i;constref LongInt):; Static; BZVectorMath.pas(269,20) Error: Found declaration: operator +(constref TBZVector2i;constref Single):; Static; vectormath_vector2i_win64_sse_imp.inc(49,28) Error: Calling convention doesn't match forward vectormath_vector2i_win64_sse_imp.inc(3,28) Error: Found declaration: operator +(constref TBZVector2i;constref TBZVector2i):; Register; Static; BZVectorMath.pas(263,20) Error: Found declaration: operator +(constref TBZVector2i;constref LongInt):; Static; BZVectorMath.pas(269,20) Error: Found declaration: operator +(constref TBZVector2i;constref Single):; Static; vectormath_vector2i_win64_sse_imp.inc(62,28) Error: Calling convention doesn't match forward vectormath_vector2i_win64_sse_imp.inc(3,28) Error: Found declaration: operator +(constref TBZVector2i;constref TBZVector2i):; Register; Static; BZVectorMath.pas(263,20) Error: Found declaration: operator +(constref TBZVector2i;constref LongInt):; Static; vectormath_vector2i_win64_sse_imp.inc(49,28) Error: Found declaration: operator +(constref TBZVector2i;constref Single):; Register; Static; So what the correct declaration in interface ? And for 2D Double vector, I have also this error Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i class operator TBZVector2d.*(constref A: TBZVector2d; constref B : TBZVector2i): TBZVector2d; assembler; nostackframe; register;asm  movapd   xmm0, [A]  cvtdq2pd xmm2, [B]  mulpd    xmm0, xmm2  movapd   [Result], xmm0end; With FPC 3.3.1 cvtdq2pd xmm2, FPC return "vectormath_vector2d_win64_sse_imp.inc(30,3) Error: Asm: [cvtdq2pd reg??,mem128] invalid combination of opcode and operands" (Work well with FPC 3.0.4) Thanks in advance Best regards ---------------------------------------------------------------------- julkas · 2019-07-06 16:16 Please give information about CPU and OS. ---------------------------------------------------------------------- marcov · 2019-07-06 16:20 Vectorcall afaik puts vector parameters in vector registers. But that is for value types, not ref types. Try removing the constref. ---------------------------------------------------------------------- BeanzMaster · 2019-07-06 21:34 Quote from: julkas on July 06, 2019, 06:16:33 pmPlease give information about CPU and OS. Actually library run under  Windows and Linux 32 and 64bit. And should be work with MacOS with Intel CPU. Quote from: marcov on July 06, 2019, 06:20:38 pmVectorcall afaik puts vector parameters in vector registers. But that is for value types, not ref types. Try removing the constref. Thanks Marcov. I've found how do. ConstRef seems to be accepted. At this time vectorcall should be declared in the interface too Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i    class operator +(Constref A, B: TBZVector2i): TBZVector2i; {$ifdef USE_VECTORCALL} vectorcall; {$endif}overload; and in implementation Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i class operator TBZVector2i.+(Constref A, B: TBZVector2i): TBZVector2i; {$ifdef USE_VECTORCALL} vectorcall; {$else} register; {$endif} assembler; nostackframe;asm  {$ifndef USE_VECTORCALL}  movq  xmm0, [A]  movq  xmm1, [B]  {$endif}  paddd xmm0, xmm1  movq  RAX, {%H-}xmm0end; I'll run my unit test later for check results But at this stage i always get this error with Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i class operator TBZVector2d.*(constref A: TBZVector2d; constref B : TBZVector2i): TBZVector2d; assembler; nostackframe; register;asm  movapd   xmm0, [A]  cvtdq2pd xmm2, [B] // ERROR HERE  mulpd    xmm0, xmm2  movapd   [Result], xmm0end; QuoteWith FPC 3.3.1 cvtdq2pd xmm2, FPC return "vectormath_vector2d_win64_sse_imp.inc(30,3) Error: Asm: [cvtdq2pd reg??,mem128] invalid combination of opcode and operands" (Work well with FPC 3.0.4) i'll check manual of SIMD instruction later. Perhaps i'll should load with a movq before doing the conversion (don't remember why i used XMM2 instead of XMM1) and i must try with vectorcall enabled Thanks ---------------------------------------------------------------------- marcov · 2019-07-06 21:44 That looks like AT&T style, and then the last register is usually the destination. Is that what you want? It seems to me use AT&T mnemonics (with q and d suffix), but intel argument order. ---------------------------------------------------------------------- BeanzMaster · 2019-07-07 06:55 Quote from: marcov on July 06, 2019, 11:44:56 pmThat looks like AT&T style, and then the last register is usually the destination. Is that what you want? It seems to me use AT&T mnemonics (with q and d suffix), but intel argument order. For why i' used xmm0 and xmm2 it due to the Linux ABI see the code for Linux : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i class operator TBZVector2d.*(constref A: TBZVector2d; constref B : TBZVector2i): TBZVector2d; assembler; nostackframe; register;asm  movapd   xmm0, [A]  cvtdq2pd xmm2, [B]  mulpd    xmm0, xmm2  movhlps xmm1, xmm0end; For  cvtdq2pd the term and order of argurments are rights (i'm in Intel mode). See this doc :  https://www.felixcloutier.com/x86/cvtdq2pd So probably a bug with FPC 3.3.1 or i must do something else, somewhere..... (i must convert a lot of code, so perhaps,  it is possible that it is just an echo of another part of the code sent by the fpc compiler. . I'll also try with a Const instead ConstRef, but I'm not persuading that this is the problem) PS : i did a strong "Unit Test" (include on the Github) so actually I'm sure the results and the code are right with FPC 3.0.4 with both Linux and Windows 64bits