|
@@ -0,0 +1,61 @@
|
|
|
+{ %CPU=x86_64 }
|
|
|
+{ %TARGET=linux }
|
|
|
+program vectorcall_pd_test1;
|
|
|
+
|
|
|
+{$IFNDEF CPUX86_64}
|
|
|
+ {$FATAL This test program can only be compiled on Linux 64-bit with an Intel processor }
|
|
|
+{$ENDIF}
|
|
|
+{$IFNDEF LINUX}
|
|
|
+ {$FATAL This test program can only be compiled on Linux 64-bit with an Intel processor }
|
|
|
+{$ENDIF}
|
|
|
+{$MODESWITCH ADVANCEDRECORDS}
|
|
|
+{$ASMMODE Intel}
|
|
|
+type
|
|
|
+ { TM128 }
|
|
|
+ {$push}
|
|
|
+ {$CODEALIGN RECORDMIN=16}
|
|
|
+ {$PACKRECORDS C}
|
|
|
+ TM128 = record
|
|
|
+ public
|
|
|
+ function Add(A: TM128): TM128; vectorcall;
|
|
|
+ case Byte of
|
|
|
+ 0: (M128_F32: array[0..3] of Single);
|
|
|
+ 1: (M128_F64: array[0..1] of Double);
|
|
|
+ end;
|
|
|
+ {$pop}
|
|
|
+
|
|
|
+{ TM128 }
|
|
|
+
|
|
|
+function TM128.Add(A: TM128): TM128; vectorcall; assembler; nostackframe;
|
|
|
+asm
|
|
|
+ addps xmm0, [RDI] // expected convention for Self - add result into first parameter and return as result (xmm0 = first parameter and return value)
|
|
|
+end;
|
|
|
+
|
|
|
+var
|
|
|
+ xm1, xm2, xm3: TM128;
|
|
|
+
|
|
|
+begin
|
|
|
+ WriteLn('Linux "vectorcall" test with Self (is it in RDI?)'#10
|
|
|
+ + '-------------------------------------------------');
|
|
|
+ xm1.M128_F32[0] := 1.0;
|
|
|
+ xm1.M128_F32[1] := 2.0;
|
|
|
+ xm1.M128_F32[2] := 3.0;
|
|
|
+ xm1.M128_F32[3] := 4.0;
|
|
|
+ xm2.M128_F32[0] := 5.0;
|
|
|
+ xm2.M128_F32[1] := 6.0;
|
|
|
+ xm2.M128_F32[2] := 7.0;
|
|
|
+ xm2.M128_F32[3] := 8.0;
|
|
|
+
|
|
|
+ WriteLn('xm1 = (', xm1.M128_F32[0], ', ', xm1.M128_F32[1], ', ', xm1.M128_F32[2], ', ', xm1.M128_F32[3]);
|
|
|
+ WriteLn('xm2 = (', xm2.M128_F32[0], ', ', xm2.M128_F32[1], ', ', xm2.M128_F32[2], ', ', xm2.M128_F32[3]);
|
|
|
+ xm3 := xm1.Add(xm2); { This will likely raise an exception if RDI doesn't contain Self }
|
|
|
+ WriteLn('xm3 = (', xm3.M128_F32[0], ', ', xm3.M128_F32[1], ', ', xm3.M128_F32[2], ', ', xm3.M128_F32[3]);
|
|
|
+
|
|
|
+ if (xm3.M128_F32[0] <> 6.0) or (xm3.M128_F32[1] <> 8.0) or (xm3.M128_F32[2] <> 10.0) or (xm3.M128_F32[3] <> 12.0) then
|
|
|
+ begin
|
|
|
+ WriteLn('FAIL');
|
|
|
+ Halt(1);
|
|
|
+ end;
|
|
|
+
|
|
|
+ WriteLn('ok');
|
|
|
+end.
|