Cortex-M4和Cortex-M7中的SIMD指令

SIMD指令簡(jiǎn)介

單指令多數(shù)據(jù)流,即SIMD(Single Instruction举哟, Multiple Data)指一類(lèi)能夠在單個(gè)指令周期內(nèi)同時(shí)處理多個(gè)數(shù)據(jù)元素的指令集,利用的是數(shù)據(jù)級(jí)并行來(lái)提高運(yùn)行效率。

不同處理器架構(gòu)所支持的SIMD指令集各不相同敞临,比如嵌入式處理器ARM Cortex-A系列中支持NEON指令集。而我們常用的ARM Cortex-M系列單片機(jī)則使用了ARMv6-M/ARMv7-M架構(gòu)麸澜,指令集較為簡(jiǎn)化挺尿,不支持NEON。其中Cortex-M4和Cortex-M7所使用的指令集也被稱(chēng)為ARMv7E-M炊邦,支持部分SIMD指令编矾。對(duì)于Cortex-A系列來(lái)說(shuō),其指令集向下包含馁害,即許多Cortex-M中的SIMD指令窄俏,也能夠在Cortex-A中使用。

SIMD指令集的最初設(shè)計(jì)目標(biāo)就是為了提高多媒體應(yīng)用的性能(圖像相關(guān)運(yùn)算)碘菜,因?yàn)閳D像數(shù)據(jù)的像素點(diǎn)都是8位數(shù)據(jù)凹蜈,而CPU寄存器通常是32位以上的,因此一條指令只用于計(jì)算一個(gè)像素點(diǎn)不免顯得非常浪費(fèi)忍啸。在32位處理器上仰坦,可以用SIMD指令一次性計(jì)算4個(gè)8位數(shù)據(jù),極大地提升了運(yùn)算效率计雌。

直接使用C語(yǔ)言編寫(xiě)的程序悄晃,編譯器是不會(huì)自動(dòng)翻譯成SIMD指令的。因此為了在嵌入式處理器如單片機(jī)上提升圖像數(shù)據(jù)運(yùn)算速度凿滤,需要專(zhuān)門(mén)使用SIMD指令進(jìn)行優(yōu)化传泊。得益于SIMD指令加速,我們能夠在STM32F4上實(shí)現(xiàn)簡(jiǎn)單的光流算法鸭巴,有興趣的可以看一下PX4Flow的算法部分眷细。為了能夠在優(yōu)化圖像算法,使其能以較快速度運(yùn)行于嵌入式平臺(tái)鹃祖,熟悉掌握SIMD指令是非常有必要的溪椎,下面列出一些可以在Cortex-M4和Cortex-M7上使用的SIMD指令(不全面,忽略了部分16位操作數(shù)指令),Cortex-A系列處理器基本上都兼容這些指令校读,當(dāng)然在那上面還有強(qiáng)大的NEON指令集可以使用沼侣。

在STM32的庫(kù)文件core_cm4_simd.h中可以看到所有SIMD指令的宏定義

部分SIMD指令說(shuō)明

飽和加法: a+b=c,當(dāng)計(jì)算結(jié)果大于c可表示的最大值或者小于c可表示的最小值時(shí)歉秫,計(jì)算結(jié)果取值為這個(gè)最大值或最小值蛾洛。

非飽和加法: a+b=c,如果計(jì)算結(jié)果一出雁芙,則直接去掉一出位轧膘,剩下的就是結(jié)果。

  • __USAD8
    指令說(shuō)明:無(wú)符號(hào)值的差的絕對(duì)值求和
    指令定義:uint32_t __USAD8 (uint32_t val1, uint32_t val2)
    指令操作:
absdiff1  = val1[7:0]   - val2[7:0]
absdiff2  = val1[15:8]  - val2[15:8]
absdiff3  = val1[23:16] - val2[23:16]
absdiff4  = val1[31:24] - val2[31:24]
res[31:0] = absdiff1 + absdiff2 + absdiff3 + absdiff4
  • __USADA8
    指令說(shuō)明:無(wú)符號(hào)值的差的絕對(duì)值求和累加
    指令定義:uint32_t __USADA8 (uint32_t val1, uint32_t val2, uint32_t val3)
    指令操作:
absdiff1  = val1[7:0]   - val2[7:0]
absdiff2  = val1[15:8]  - val2[15:8]
absdiff3  = val1[23:16] - val2[23:16]
absdiff4  = val1[31:24] - val2[31:24]
sum       = absdiff1 + absdiff2 + absdiff3 + absdiff4
res[31:0] = sum[31:0] + val3[31:0]

并行加法

  • __SADD8
    指令說(shuō)明:有符號(hào)8位操作數(shù)的并行加法
    指令定義:uint32_t __SADD8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   + val2[7:0] 
res[15:8]  = val1[15:8]  + val2[15:8] 
res[23:16] = val1[23:16] + val2[23:16] 
res[31:24] = val1[31:24] + val2[31:24]    
  • __QADD8
    指令說(shuō)明:有符號(hào)8位操作數(shù)的并行飽和加法
    指令定義:uint32_t __QADD8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   + val2[7:0] 
res[15:8]  = val1[15:8]  + val2[15:8] 
res[23:16] = val1[23:16] + val2[23:16] 
res[31:24] = val1[31:24] + val2[31:24]   
  • __SHADD8
    指令說(shuō)明:有符號(hào)8位操作數(shù)的并行減半加法
    指令定義:uint32_t __SHADD8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   + val2[7:0]  >> 1
res[15:8]  = val1[15:8]  + val2[15:8] >> 1
res[23:16] = val1[23:16] + val2[23:16] >> 1
res[31:24] = val1[31:24] + val2[31:24] >> 1  
  • __UADD8
    指令說(shuō)明:無(wú)符號(hào)8位操作數(shù)的并行加法
    指令定義:uint32_t __UADD8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   + val2[7:0] 
res[15:8]  = val1[15:8]  + val2[15:8] 
res[23:16] = val1[23:16] + val2[23:16] 
res[31:24] = val1[31:24] + val2[31:24]    
  • __UQADD8
    指令說(shuō)明:無(wú)符號(hào)8位操作數(shù)的并行飽和加法
    指令定義:uint32_t __UQADD8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   + val2[7:0] 
res[15:8]  = val1[15:8]  + val2[15:8] 
res[23:16] = val1[23:16] + val2[23:16] 
res[31:24] = val1[31:24] + val2[31:24]    
  • __UHADD8
    指令說(shuō)明:無(wú)符號(hào)8位操作數(shù)的并行減半加法
    指令定義:uint32_t __UHADD8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   + val2[7:0]  >> 1
res[15:8]  = val1[15:8]  + val2[15:8] >> 1
res[23:16] = val1[23:16] + val2[23:16] >> 1
res[31:24] = val1[31:24] + val2[31:24] >> 1  

并行減法

  • __SSUB8
    指令說(shuō)明:有符號(hào)8位操作數(shù)的并行減法
    指令定義:uint32_t __SSUB8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   - val2[7:0] 
res[15:8]  = val1[15:8]  - val2[15:8]
res[23:16] = val1[23:16] - val2[23:16]
res[31:24] = val1[31:24] - val2[31:24]
  • __QSUB8
    指令說(shuō)明:有符號(hào)8位操作數(shù)的并行飽和減法
    指令定義:uint32_t __QSUB8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   - val2[7:0] 
res[15:8]  = val1[15:8]  - val2[15:8]
res[23:16] = val1[23:16] - val2[23:16]
res[31:24] = val1[31:24] - val2[31:24]
  • __SHSUB8
    指令說(shuō)明:有符號(hào)8位操作數(shù)的并行減半減法
    指令定義:uint32_t __SHSUB8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   - val2[7:0]   >> 1
res[15:8]  = val1[15:8]  - val2[15:8]  >> 1
res[23:16] = val1[23:16] - val2[23:16] >> 1
res[31:24] = val1[31:24] - val2[31:24] >> 1
  • __USUB8
    指令說(shuō)明:無(wú)符號(hào)8位操作數(shù)的并行減法
    指令定義:uint32_t __USUB8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   - val2[7:0] 
res[15:8]  = val1[15:8]  - val2[15:8]
res[23:16] = val1[23:16] - val2[23:16]
res[31:24] = val1[31:24] - val2[31:24]
  • __UQSUB8
    指令說(shuō)明:無(wú)符號(hào)8位操作數(shù)的并行飽和減法
    指令定義:uint32_t __UQSUB8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   - val2[7:0] 
res[15:8]  = val1[15:8]  - val2[15:8]
res[23:16] = val1[23:16] - val2[23:16]
res[31:24] = val1[31:24] - val2[31:24]
  • __UHSUB8
    指令說(shuō)明:無(wú)符號(hào)8位操作數(shù)的并行減半減法
    指令定義:uint32_t __UHSUB8 (uint32_t val1, uint32_t val2 )
    指令操作:
res[7:0]   = val1[7:0]   - val2[7:0]   >> 1
res[15:8]  = val1[15:8]  - val2[15:8]  >> 1
res[23:16] = val1[23:16] - val2[23:16] >> 1
res[31:24] = val1[31:24] - val2[31:24] >> 1

指令集詳細(xì)參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兔甘,一起剝皮案震驚了整個(gè)濱河市谎碍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌洞焙,老刑警劉巖蟆淀,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異澡匪,居然都是意外死亡熔任,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)唁情,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疑苔,“玉大人,你說(shuō)我怎么就攤上這事荠瘪。” “怎么了赛惩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵哀墓,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我喷兼,道長(zhǎng)篮绰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任季惯,我火速辦了婚禮吠各,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘勉抓。我一直安慰自己贾漏,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布藕筋。 她就那樣靜靜地躺著纵散,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伍掀,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天掰茶,我揣著相機(jī)與錄音,去河邊找鬼蜜笤。 笑死濒蒋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的把兔。 我是一名探鬼主播沪伙,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼垛贤!你這毒婦竟也來(lái)了焰坪?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤聘惦,失蹤者是張志新(化名)和其女友劉穎某饰,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體善绎,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黔漂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禀酱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炬守。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剂跟,靈堂內(nèi)的尸體忽然破棺而出减途,到底是詐尸還是另有隱情,我是刑警寧澤曹洽,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布鳍置,位于F島的核電站,受9級(jí)特大地震影響送淆,放射性物質(zhì)發(fā)生泄漏税产。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一偷崩、第九天 我趴在偏房一處隱蔽的房頂上張望辟拷。 院中可真熱鬧,春花似錦阐斜、人聲如沸衫冻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)羽杰。三九已至渡紫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間考赛,已是汗流浹背惕澎。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留颜骤,地道東北人唧喉。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像忍抽,于是被迫代替她去往敵國(guó)和親八孝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容