SIMD Single Instruction Multiple Data
keine Überläufe
Bei AMD heißt das 3D-Now!
Acht neue 64-Bit Register
MM0 bis MM7
Vorbereitung, Programm-Code
.mmx
.k3d
.xmm (Pentium 3)
Prüfen ob Verfügbar:
CPUID, 1 in EAX-Register
Prüfen, ob Bit 23 gesetzt
Verfügbarkeit bei 3DNow!
80000000h in EAX und CPUID, wenn größer dann: Existiert
mov eax, 00000001
cpuid
test edx, 000800000h
jnz vorhanden
emms = empty mmx state markiert die FPU-Register für die FPU-Befehle als verfügbar
femms: 3DNow!
fxsave: FPU, MMX, XMM, MXCSR-Register in 512 Byte großen Speicherbereich
fxstor: Lädt
movq mm0, summand0
movq mm1, summand1
movq mm2, summand2
movq mm3, summand3
paddsub mm0, mm1
Befehle:
Packen, Entpacken
Entpackbefehle
Pack-Befehle:
packsswb
packuswb
Entpack-Befehle:
punpckhbw
punpckhwd
punpcklbw
punpcklbw
punpckldq
7 Add-Varianten
paddb
paddw
paddd
paddsb
paddsw
paddusb
paddusw
and:
pand
pandn
cmp
pcmpeqb
pcmpeqw
pcmpeqd
pcmpgtb
pcmpgtw
pcmpgtd
mov:
movd
movq
mul
pmaddwd
pmuhlw
pmullw
shr, sub, xor
mmx: mm0 .. mm7
sse: xmm0 .. xmm15
avx, avx2: ymm0 .. ymm15
avx-512: zmm0 .. zmm31
sse4.1
Skalarprodukt: dpps, dppd
bedingtes Überblenden: blendps blendpd blendvps blendvpd
Minima, maxima: PMINSB, PMAXSB, PMINUW, PMAXUW, PMINUD, PMAXUD, PMINSD, PMAXSD
Integer-Umwandlung: PMOVSXBW/-D/-Q, PMOVZXBW/-D/-Q, PMOVSXWD/-Q, PMOVZXWD/-Q, PMOVSXDQ, PMOVZXDQ
avx:
VBROADCASTSS
VBROADCASTSD
VBROADCASTF128 Kopiert einen 32-Bit-, 64-Bit- oder 128-Bit-Speicheroperanden in alle Elemente eines XMM- oder YMM-Registers.
VINSERTF128 Ersetzt entweder die obere oder untere Hälfte eines 256-Bit-YMM-Register mit dem Wert aus dem 128-Bit-Operanden. Die andere Hälfte bleibt unverändert.
VEXTRACTF128 Extrahiert entweder die obere oder untere Hälfte eines 256-Bit-YMM-Registers und kopiert den Wert in den 128-Bit-Operanden.
VMASKMOVPS
VMASKMOVPD Liest eine beliebige Anzahl von Vektorelementen bedingt aus einem SIMD-Speicheroperand in ein Zielregister, wobei der verbleibende Platz mit Nullen gefüllt wird.
Alternativ schreibt es eine beliebige Anzahl von Vektorelementen bedingt von einem SIMD-Register in ein SIMD-Speicheroperanden, wobei der verbleibende Platz
im Speicher nicht verändert wird.
VPERMILPS
VPERMILPD Tauscht 32-Bit- oder 64-Bit-Vektorelemente aus.
VPERM2F128 Mischt die vier 128-Bit-Vektorelemente aus zwei 256-Bit-Ursprungsoperanden in ein 256-Bit-Zieloperanden.
VTESTPS, VTESTPD Setzt die Flag-Bits CF und ZF entsprechend einem Vergleich aller Vorzeichenbits.
VZEROALL Füllt alle YMM-Register mit Nullen und markiert sie als unbenutzt. Wird beim Umschalten zwischen 128-Bit- und 256-Bit-Modus verwendet.
VZEROUPPER Füllt die obere Hälfte aller YMM-Register mit Nullen. Wird beim Umschalten zwischen 128-Bit- und 256-Bit-Modus verwendet.
global _LerpARGB
_LerpARGB:
; load the pixels and expand to 4 words
movd mm1, [esp+4] ; mm1 = 0 0 0 0 aA aR aG aB
movd mm2, [esp+8] ; mm2 = 0 0 0 0 bA bR bG bB
pxor mm5, mm5 ; mm5 = 0 0 0 0 0 0 0 0
punpcklbw mm1, mm5 ; mm1 = 0 aA 0 aR 0 aG 0 aB
punpcklbw mm2, mm5 ; mm2 = 0 bA 0 bR 0 bG 0 bB
; load the factor and increase range to [0-256]
movd mm3, [esp+12] ; mm3 = 0 0 0 0 faA faR faG faB
punpcklbw mm3, mm5 ; mm3 = 0 faA 0 faR 0 faG 0 faB
movq mm6, mm3 ; mm6 = faA faR faG faB [0 - 255]
psrlw mm6, 7 ; mm6 = faA faR faG faB [0 - 1]
paddw mm3, mm6 ; mm3 = faA faR faG faB [0 - 256]
; fb = 256 - fa
pcmpeqw mm4, mm4 ; mm4 = 0xFFFF 0xFFFF 0xFFFF 0xFFFF
psrlw mm4, 15 ; mm4 = 1 1 1 1
psllw mm4, 8 ; mm4 = 256 256 256 256
psubw mm4, mm3 ; mm4 = fbA fbR fbG fbB
; res = (a*fa + b*fb)/256
pmullw mm1, mm3 ; mm1 = aA aR aG aB
pmullw mm2, mm4 ; mm2 = bA bR bG bB
paddw mm1, mm2 ; mm1 = rA rR rG rB
psrlw mm1, 8 ; mm1 = 0 rA 0 rR 0 rG 0 rB
; pack into eax
packuswb mm1, mm1 ; mm1 = 0 0 0 0 rA rR rG rB
movd eax, mm1 ; eax = rA rR rG rB
ret