Bei All4, gehen beide Versionen, egal ob Pointer oder direkt.
Code: Alles auswählen
function All4(f: PSingle): TVector4f; assembler;
asm
Movss Xmm0, [f]
Pshufd Xmm0, Xmm0, $00
Movups [Result], Xmm0
end;
function All4(f: Single): TVector4f; assembler;
asm
Movss Xmm0, f
Pshufd Xmm0, Xmm0, $00
Movups [Result], Xmm0
end;
function All8(f: PSingle): TVector8f; assembler;
asm
Vbroadcastss ymm0, [f]
Vmovups [Result], ymm0
end;
function All8(f: Single): TVector8f; assembler;
asm
Vbroadcastss ymm0, f // Hier SIGILL
Vmovups [Result], ymm0
end;
TestCode:
Code: Alles auswählen
WriteLn('4 Vektor mit Pointer');
f := 12.34;
c := All4(@f);
WriteVector(c);
WriteLn();
WriteLn('4 Vektor ohne Pointer');
f := 23.45;
c := All4(f);
WriteVector(c);
WriteLn();
WriteLn('8 Vektor mit Pointer');
f := 34.56;
cc := All8(@f);
WriteVector(cc);
WriteLn();
WriteLn('8 Vektor ohne Pointer');
f := 45.67;
cc := All8(f);
WriteVector(cc);
WriteLn();
Interessanterweise, wird alles anstandslos kompiliert, obwohl SIGILL eine ungültige Assembleranweisung ist.
Code: Alles auswählen
000000000045FEE0 55 push %rbp
000000000045FEE1 4889e5 mov %rsp,%rbp
unit1.pas:163 Movss Xmm0, [f]
000000000045FEE4 f30f1006 movss (%rsi),%xmm0
unit1.pas:164 Pshufd Xmm0, Xmm0, $00
000000000045FEE8 660f70c000 pshufd $0x0,%xmm0,%xmm0
unit1.pas:165 Movups [Result], Xmm0
000000000045FEED 0f1107 movups %xmm0,(%rdi)
unit1.pas:166 end;
000000000045FEF0 c9 leaveq
000000000045FEF1 c30000000000000000000000 retq
unit1.pas:169 asm
000000000045FF00 55 push %rbp
000000000045FF01 4889e5 mov %rsp,%rbp
unit1.pas:170 Movss Xmm0, f
000000000045FF04 f30f10c0 movss %xmm0,%xmm0
unit1.pas:171 Pshufd Xmm0, Xmm0, $00
000000000045FF08 660f70c000 pshufd $0x0,%xmm0,%xmm0
unit1.pas:172 Movups [Result], Xmm0
000000000045FF0D 0f1107 movups %xmm0,(%rdi)
unit1.pas:173 end;
000000000045FF10 c9 leaveq
000000000045FF11 c30000000000000000000000 retq
unit1.pas:176 asm
000000000045FF20 55 push %rbp
000000000045FF21 4889e5 mov %rsp,%rbp
unit1.pas:177 Vbroadcastss ymm0, [f]
000000000045FF24 c4e27d1806 vbroadcastss (%rsi),%ymm0
unit1.pas:178 Vmovups [Result], ymm0
000000000045FF29 c5fc1107 vmovups %ymm0,(%rdi)
unit1.pas:179 end;
000000000045FF2D c9 leaveq
000000000045FF2E c300 retq
unit1.pas:182 asm
000000000045FF30 55 push %rbp
000000000045FF31 4889e5 mov %rsp,%rbp
unit1.pas:183 Vbroadcastss ymm0, f // Hier SIGILL
000000000045FF34 c4e27d18c0 vbroadcastss %xmm0,%ymm0
unit1.pas:184 Vmovups [Result], ymm0
000000000045FF39 c5fc1107 vmovups %ymm0,(%rdi)
unit1.pas:185 end;
000000000045FF3D c9 leaveq
000000000045FF3E c300 retq
Nachtrag:
Mit FPC 3.1.1 neuste Trunk, wird nicht mal folgender Code übersetzt, welcher mit FPC 3.0.4 einwandfrei funktionierte.
Aber die Zeile mit dem SIGILL wird übersetzt.
Code: Alles auswählen
function All8(f: PSingle): TVector8f; assembler;
asm
Vbroadcastss ymm0, [f]
Vmovups [Result], ymm0
end;
Kann es sein, das FPC mit Vbroadcastss ein wenig Mühe hat ?