So verschieben Sie 128-Bit-Immediate in XMM-Register
Gibt es schon eine Frage auf diese, aber es war geschlossen als "mehrdeutig" also, ich bin eine neue zu öffnen - ich habe die Antwort gefunden, vielleicht hilft es anderen auch.
Die Frage ist: wie schreibt man eine Folge von Assembler-code zur Initialisierung eines XMM-Registers mit einer 128-bit-immediate (Konstante) Wert?
InformationsquelleAutor der Frage Virgil | 2011-07-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wollte nur hinzufügen, dass man Lesen kann über die verschiedenen Konstanten mit Montage in Agner Fog ' s manual Optimierung von Unterprogrammen in Assemblerdie Generierung von Konstanten, Abschnitt 13.4, Seite 121.
InformationsquelleAutor der Antwort Norbert P.
Können Sie es so machen, mit nur einem
movaps
Anleitung:Laden mit laden der Daten ist in der Regel vorzuziehen Einbettung in den Unterricht stream, besonders weil, wie viele Anweisungen es braucht. Das sind mehrere zusätzliche uops für die CPU zum ausführen, für eine beliebige Konstante, kann nicht erzeugt werden von allen-diejenigen, die mit ein paar Verschiebungen.
Wenn es einfacher ist, Sie können die Konstanten direkt vor oder nach einer Funktion, die Sie jit-kompilieren, statt in einem separaten Abschnitt. Aber da die CPUs aufgeteilt L1d /L1i-caches und TLBs, ist es im Allgemeinen am besten zu Konstanten Gruppe zusammen getrennt von Anweisungen.
Wenn beide Hälften Ihre Konstanten sind die gleichen, Sie können broadcast-laden Sie es mit SSE3
movddup (m64), %xmm0
.InformationsquelleAutor der Antwort Paul R
Gibt es mehrere Möglichkeiten, von Einbettung Konstanten in der instruction stream:
So, während es gibt keine Möglichkeit zu tun, eine eine sofortige Belastung in eine
XMM
registrieren, ist es möglich, eine PC-relative Last (in 64bit) aus einem gespeicherten Wert "rechts neben", wo der code ausgeführt wird. Das schafft so etwas wie:Beim zerlegen:
ist äußerst kompakte23 Byte.
Andere Optionen zu konstruieren, der Wert auf den stack legen und wieder laden Sie es von dort. Im 32-bit-x86, wo Sie nicht
%rip
-relative-memory-access, kann man immer noch tun, dass in 24 Bytes (vorausgesetzt der stackpointer ist ausgerichtet auf Eintrag; sonst, unaligned load erforderlich):Während in 64bit (stackpointer-Ausrichtung an der Funktion Eintrag ist garantiert, da der ABI) ,hatte eine 27 Bytes:
Wenn Sie vergleichen diese mit den
MOVLHPS
version, werden Sie feststellen, es ist die längste:33 Bytes.
Der andere Vorteil von dem laden direkt aus dem instruction memory ist, dass die
movdqa
hängt nicht von irgendetwas vorherigen. Wahrscheinlich die erste version, wie @Paul R, ist der Schnellste, den man bekommen kann.InformationsquelleAutor der Antwort FrankH.
Als einer der 10000 Möglichkeiten, es zu tun, verwenden Sie SSE4.1
pinsrq
InformationsquelleAutor der Antwort Pierre
Die beste Lösung (vor allem, wenn Sie halten wollen, SSE2, d.h. Sie zu vermeiden, mit AVX) zum initialisieren von zwei Registern (sagen, xmm0 und xmm1) mit den beiden 64-bit-Hälften von Ihrem unmittelbaren Wert, tun MOVLHPS xmm0,xmm1
Zur Initialisierung eines 64-bit-Wert, die einfachste Lösung ist die Verwendung eines general-purpose-register (sagen, AX), und verwenden Sie dann MOVQ übertragen Ihren Wert auf die XMM-register.
Also die Reihenfolge wäre in etwa so:
InformationsquelleAutor der Antwort Virgil