MMX的数据结构 MMX指令集
源地址:http://dev.gameres.com/Program/Other/MMXData.htm
? ? ? ?http://www.360doc.com/content/12/1129/18/1317564_251021032.shtml
MMX的數(shù)據(jù)結(jié)構(gòu)
? ? 多媒體軟件具有如下顯著的特點(diǎn):
1、 小整型數(shù)據(jù)類(lèi)型(圖形數(shù)據(jù)為8位 ,聲頻數(shù)據(jù)為16位)
2、 對(duì)小整型數(shù)據(jù)的頻繁且重復(fù)的計(jì)算操作(例如被頻繁調(diào)用的核心算法);
3、 許多操作具有內(nèi)存的并行性(例如對(duì)大量的數(shù)據(jù)進(jìn)行同一個(gè)加,減或乘法運(yùn)算操作);
? ? MMX技術(shù)設(shè)計(jì)了一套基本的,通用的緊縮整形指令,共57條。
所謂“緊縮整形數(shù)據(jù)”是指多個(gè)8/16/32位的整形數(shù)據(jù)組合成為一個(gè)64位的數(shù)據(jù).MMX指令主要就是使用
這種緊縮整形數(shù)據(jù),它又分成4種整形類(lèi)型:緊縮字節(jié)、緊縮字、緊縮雙字、緊縮4字
? ? *緊縮字節(jié)(Packed Byte): 8個(gè)字節(jié)組合成一個(gè)64位的數(shù)據(jù);
? ? *緊縮字 (Packed Word): 4個(gè)字組合成一個(gè)64位的數(shù)據(jù);
? ? *緊縮雙字(Packed Doubleword): 2個(gè)雙字組合成一個(gè)64位的數(shù)據(jù);
? ? *緊縮4字 (Packed Quadword):一個(gè)64位數(shù)據(jù)
? ? 這樣一條MMX指令就能夠同時(shí)處理8/4/2個(gè)數(shù)據(jù)單元,這就是所謂的“單指令多數(shù)據(jù)SIMD”結(jié)構(gòu)。這種結(jié)構(gòu)
是MMX技術(shù)把機(jī)器性能提高的最根本因素。
? ? 為了方便使用64位緊縮整形數(shù)據(jù),MMX技術(shù)含有8個(gè)64位的MMX寄存器(MM0-MM7),只有MMX指令可以使用MMX寄存器。值得一提的是,MMX寄存器是隨機(jī)存取的,但實(shí)際上是借用了8個(gè)浮點(diǎn)數(shù)據(jù)寄存器實(shí)現(xiàn)的。浮點(diǎn)處理單元FPU有8個(gè)浮點(diǎn)寄存器FPR,以堆棧方式存取。每個(gè)浮點(diǎn)數(shù)據(jù)寄存器有80位,高16位用于指數(shù)和符號(hào),低64位用于有效數(shù)字。MMX利用其64位有效數(shù)字部分用做隨機(jī)存取的64位的MMX寄存器。也就是說(shuō)MMX寄存器并非獨(dú)立寄存器,而是復(fù)用了fpu數(shù)據(jù)堆棧寄存器,也就是說(shuō)使用mmx指令集會(huì)破壞fpu的計(jì)算,如果同時(shí)使用著兩種特性,一定要注意這點(diǎn),避免出現(xiàn)莫名的錯(cuò)誤。
MMX指令集
1、算術(shù)運(yùn)算:
PADD[B、W、D] 環(huán)繞加[字節(jié),字,雙字]
PADDS[B , W] 有符號(hào)飽和加[字節(jié),字]
PADDUS[B , W] 無(wú)符號(hào)飽和加[字節(jié),字]
PSUB[B、W、D] 環(huán)繞減[字節(jié),字,雙字]
PSUBS[B,W] 有符號(hào)飽和減[字節(jié),字]
PSUBUS[D,W] 無(wú)符號(hào)飽和減[字節(jié),字]
PMULHW 緊縮字乘后取高位
PMULLW 緊縮字乘后取低位
PMADDWD 緊縮字乘,積相加
2、比較:
PCMPEQ[B,W,D] 緊縮比較是否相等[字節(jié),字,雙字]
PCMPGT[B,W,D] 緊縮比較是否大于[字節(jié),字,雙字]
3、類(lèi)型轉(zhuǎn)換:
PACKUSWB 按無(wú)符號(hào)飽和壓縮[字成字節(jié)]
PACKSS[WB,DW] 按有符號(hào)飽和壓縮[字/雙字成/字節(jié)/字]
PUNPCKH[BW,WD,DQ] 擴(kuò)展高位[字節(jié),字,雙字成字,雙字,4字]
PUNPCKL[BW,WD,DQ] 擴(kuò)展地位[字節(jié),字,雙字成字,雙字,4字]
4、邏輯運(yùn)算:
PAND 緊縮邏輯與
PANDN 緊縮邏輯與非
POR 緊縮邏輯或
PXOR 緊縮邏輯異或
5、位移:
PSLL[W,D,Q] 緊縮邏輯左移[字,雙字,4字]
PSRL[W,D,Q] 緊縮邏輯右移[字,雙字,4字]
PSRA[W,D] 緊縮算術(shù)右移[字,雙字]
7、數(shù)據(jù)傳送:
MOV[D,Q] 從MMX寄存器傳人/傳出[雙字/4字]
8、狀態(tài)清除
EMMS 清除MMX狀態(tài)
首先mmx指令集需要cpu的支持,但不是所有cpu都支持,不然也不會(huì)稱之為高級(jí)特性 了,所以在使用之前需要檢測(cè),檢測(cè)指令為cpuid,獲得cpu的特性,cpuid雖然只有一條指令,但是其隱含的內(nèi)容太多,這里僅僅介紹檢測(cè)SIMD指令集所需要的部分,其他一些信息可參閱Intel 手冊(cè)獲得。
當(dāng)eax為1時(shí),cpuid指令返回cpu簽名信息,放入ecx和edx寄存器中,相應(yīng)位為1表示支持。檢測(cè)SIMD指令集的結(jié)果如下:
寄存器 位 特性
EDX ? ?? 23 支持MMX
EDX 25 支持SSE
EDX 26 支持SSE2
ECX 0 支持SSE3
具體檢測(cè)代碼如下(AT&T 語(yǔ)法):
.section .data
mmxstring: .asciz "支持mmx指令集\n"
ssestring: .asciz "支持sse指令集\n"
sse2string: .asciz "支持sse2指令集\n"
sse3string: .asciz "支持sse3指令集\n"
.section .text
.globl _main
_main:
movl $1, %eax
cpuid
mmxop:
test $0x800000, %edx
jz sseop
pushl $mmxstring
call _printf
sseop:
test $0x2000000, %edx
jz sse2op
pushl $ssestring
call _printf
sse2op:
test $0x4000000, %edx
jz sse3op
pushl $sse2string
call _printf
sse3op:
test $0x01, %ecx
jz end
pushl $sse3string
call _printf
end:
pushl $0
call _exit
? ? ??
? ? ? 下面正式開(kāi)始mmx指令集的介紹,使用mmx需要三個(gè)步驟:
1、從整數(shù)值創(chuàng)建打包整數(shù),載入mmx寄存器
2、使用mmx指令集計(jì)算
3、從mmx獲得結(jié)果,存入內(nèi)存
? ? ? 第一個(gè)和最后一個(gè)步驟比較簡(jiǎn)單,僅僅是數(shù)據(jù)移動(dòng)而已,這里提到打包,因?yàn)檫@里要單指令多數(shù)據(jù),所以需要把多數(shù)據(jù)合成一個(gè)操作數(shù)進(jìn)行計(jì)算,存入64位的mmx寄存器中,打包的過(guò)程就是把 8個(gè)字節(jié)/4個(gè)字/2個(gè)雙字合成一個(gè)64位數(shù)據(jù)。
? ? ?從加減法說(shuō)起,對(duì)于普通數(shù)據(jù),如果數(shù)據(jù)溢出可以置標(biāo)記位,但是對(duì)于多數(shù)據(jù)的運(yùn)算,由于同時(shí)計(jì)算多個(gè)加法,就不能單純的設(shè)置標(biāo)志,對(duì)mmx計(jì)算有幾種情況:
環(huán)繞運(yùn)算 截?cái)嗥渲?#xff0c;丟棄進(jìn)位
帶符號(hào)飽和 最大/最小 帶符號(hào)值
無(wú)符號(hào)飽和 最大/最小 無(wú)符號(hào)值
? ? ? 其中飽和運(yùn)算的預(yù)設(shè)值根據(jù)結(jié)果的位數(shù)決定,有符號(hào)8位最大為127,如果超過(guò)127,結(jié)果按127計(jì)算,其他情況與此類(lèi)似,這里方便與一些圖形處理,比如色彩黑色為0,為無(wú)符號(hào)最小值,小于其值也按黑色處理。
? ? ? 好 了,到此可以看一下具體的指令,這里的指令有相同的格式,instruction source, destination;其中source可以是mmx寄存器或者64位內(nèi)存,destination為mmx寄存器。這是AT&T語(yǔ)法,對(duì)于 MASM語(yǔ)法源目的操作數(shù)相反。
? ?指令 說(shuō)明
paddb 環(huán)繞打包字節(jié)整數(shù)加法
paddw 環(huán)繞打包字整數(shù)加法
paddd 環(huán)繞打包雙字整數(shù)加法
paddsb 帶符號(hào)飽和打包字節(jié)整數(shù)加法
paddsw 帶符號(hào)飽和打包字整數(shù)加法
paddusb ?? 無(wú)符號(hào)飽和打包字節(jié)整數(shù)加法
paddusw 無(wú)符號(hào)飽和打包字整數(shù)加法
psubb 環(huán)繞打包字節(jié)整數(shù)減法
psubw 環(huán)繞打包字整數(shù)減法
psubd 環(huán)繞打包雙字整數(shù)減法
psubsb ? ? 帶符號(hào)飽和打包字節(jié)整數(shù)減法
psubsw ?? 帶符號(hào)飽和打包字整數(shù)減法
psubusb 無(wú)符號(hào)飽和打包字節(jié)整數(shù)減法
psubusw 無(wú)符號(hào)飽和打包字整數(shù)減法
下面以AT&T加法為例進(jìn)行說(shuō)明,這里以飽和方式計(jì)算4個(gè)無(wú)符號(hào)字之和:
# add four word
# output : result is 18932, 7631, 65535, 510
.section .data
value1: .short 12300, 2384, 60000, 456
value2: .short 6632, 5247, 40000, 54
outstring: .asciz "result is %u, %u, %u, %u\n"
.section .text
.globl _main
_main:
movq value1, %mm0
movq value2, %mm1
paddusw %mm1, %mm0
movq %mm0, value1
movl $value1, %ebx
xorl %eax, %eax
movw 6(%ebx), %ax
pushl %eax
movw 4(%ebx), %ax
pushl %eax
movw 2(%ebx), %ax
pushl %eax
movw (%ebx), %ax
pushl %eax
pushl $outstring
call _printf
pushl $0
call _exit
? ? ? movq 指令把內(nèi)存中的數(shù)據(jù)傳送至mmx寄存器,如果數(shù)據(jù)之前在內(nèi)存中不是連續(xù)的,則需要集中存放,即進(jìn)行打包,之后使用paddusw進(jìn)行加法計(jì)算,輸出時(shí) word需轉(zhuǎn)化成dword放入堆棧,可以看到以飽和方式第三個(gè)結(jié)果為65535,即16位無(wú)符號(hào)數(shù)的最大值。從這里例子可以看出,通過(guò)一條指令計(jì)算了四 個(gè)word整數(shù)相加,很大程度上提高了計(jì)算的效率,但是同時(shí)需要注意,整數(shù)的打包以及傳送過(guò)程也需要耗時(shí),如果打包操作很多,結(jié)果不是提高效率而是降低效率了。
? ? ?mmx指令集的加法根據(jù)需要有飽和方式和環(huán)繞方式計(jì)算,但對(duì)于乘法而言,由于結(jié)果的寬度可能是操作數(shù)的兩倍,所以兩種方式看上去都不合適,所以intel提供了兩個(gè)指令,一個(gè)得到計(jì)算結(jié)果的低字節(jié),另一個(gè)得到計(jì)算結(jié)果的高字節(jié)。
? ? 指令 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?描述
pmulluw ? ? ? ??對(duì)無(wú)符號(hào)16位整數(shù)相乘取結(jié)果低16位
pmulhuw 對(duì)無(wú)符號(hào)16位整數(shù)相乘取結(jié)果高16位
pmullw ? ? ? ? ?對(duì)有符號(hào)16位整數(shù)相乘取結(jié)果低16位
pmulhw ? ? ? ??對(duì)有符號(hào)16位整數(shù)相乘取結(jié)果高16位
pmaddwd 對(duì)4個(gè)帶符號(hào)整數(shù)相乘,高位兩個(gè)結(jié)果相加存入高32位,低位相同
? ? ? mmx 指令集還提供對(duì)四字值進(jìn)行布爾邏輯操作和移位指令:
? 指令 ? ? ? ? ? ? ? ? ? ? ?描述
pand 對(duì)源和目標(biāo)操作數(shù)按位與操作
pandn 對(duì)目標(biāo)操作數(shù)進(jìn)行按位邏輯非操作,然后對(duì)源和目標(biāo)操作數(shù)按位與操作
por ? ? ? ? ? 對(duì)源和目標(biāo)操作數(shù)按位或操作
pxor ? ? ? ??對(duì)源和目標(biāo)操作數(shù)按位異或操作
psll ? ? ? ? ?對(duì)目標(biāo)操作數(shù)執(zhí)行邏輯左移操作,使用0填充空位
psra 對(duì)目標(biāo)操作數(shù)執(zhí)行邏輯右移操作,使用0填充空位
其AT&T指令格式如下:
pand source, destination
其中source是mmx寄存器或者64位內(nèi)存,destination必須是mmx寄存器。移位指令可以使用字,雙字或者四字操作數(shù),還有移位的位置數(shù)量。MASM格式的源目的操作數(shù)相反。
mmx構(gòu)架提供了用于比較兩個(gè)值的指令:
? ? ?指令 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?描述
pcmpeqb 比較打包字節(jié)整數(shù)值的相等性
pcmpeqw 比較打包字整數(shù)值的相等性
pcmpeqd 比較打包雙字整數(shù)值的相等性
pcmpgtb 判斷打包字節(jié)整數(shù)值是否大于另一個(gè)
pcmpgtw 判斷打包字整數(shù)值是否大于另一個(gè)
pcmpgtd 判斷打包雙字整數(shù)值是否大于另一個(gè)
? ? 因?yàn)閙mx同時(shí)比較多個(gè)數(shù)據(jù),所以不能設(shè)置標(biāo)志,替換的做法是把判斷結(jié)果放到目標(biāo)打包整數(shù)值中,如果打包整數(shù)值滿足對(duì)比提交,就把結(jié)果設(shè)置為全1,否則設(shè)置為全0。
? ? 由于mmx指令集并非所有cpu都可以支持,所以對(duì)c語(yǔ)言這種編譯通用性的程序而言,是不會(huì)貿(mào)然使用mmx指令集的,這也對(duì)我們手工匯編優(yōu)化程序提供了很大的空間,但是需要注意打包整數(shù)的效率損耗。
總結(jié)
以上是生活随笔為你收集整理的MMX的数据结构 MMX指令集的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: OpenCV算法加速(2)使用SIMD指
- 下一篇: Intel汇编-传送MMX整数