/media/sda-magnetic/david/Dok-15-2023-11-27/fernuni-hagen/cs-i-ii/old-cs-2-02/mmx-2022-06-25/mmx.txt


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