ARM和NEON指令 very gooooooood.............

http://blog.csdn.net/chshplp_liaoping/article/details/12752749

在移动平台上进行一些复杂算法的开发,一般需要用到指令集来进行加速。目前在移动上使用最多的是ARM芯片。

ARM是微处理器行业的一家知名企业,其芯片结构有:armv5、armv6、armv7和armv8系列。芯片类型有:arm7、arm9、arm11、cortex系列。指令集有:armv5、armv6和neon指令。关于ARM到知识参考:http://baike.baidu.com/view/11200.htm

最初的ARM指令集为通用计算型指令集,指令集都是针对单个数据进行计算,没有并行计算到功能。随着版本的更新,后面逐渐加入了一些复杂到指令以及并行计算到指令。而NEON指令是专门针对大规模到并行运算而设计的。

NEON 技术可加速多媒体和信号处理算法(如视频编码/解码、2D/3D 图形、游戏、音频和语音处理、图像处理技术、电话和声音合成),其性能至少为ARMv5 性能的3倍,为 ARMv6 SIMD性能的2倍。

关于SIMD和SISD:Single Instruction Multiple Data,单指令多数据流。反之SISD是单指令单数据。以加法指令为例,单指令单数据(SISD)的CPU对加法指令译码后,执行部件先访问内存,取得第一个操作数;之后再一次访问内存,取得第二个操作数;随后才能进行求和运算。而在SIMD型的CPU中,指令译码后几个执行部件同时访问内存,一次性获得所有操作数进行运算。这个特点使SIMD特别适合于多媒体应用等数据密集型运算。如下图所示:

   

如何才能快速到写出高效的指令代码?这就需要对各个指令比较熟悉,知道各个指令的使用规范和使用场合。

ARM指令有16个32位通用寄存器,为r0-r15,其中r13为堆栈指针寄存器,r15为指令计算寄存器。实际可以使用的寄存器只有14个。r0-r3一般作为函数参数使用,函数返回值放在r0中。若函数参数超过4个,超过到参数压入堆栈。

有效立即数的概念:每个立即数采用一个8位的常数(bit[7:0])循环右移偶数位而间接得到,其中循环右移的位数由一个4位二进制(bit[11:8] )的两倍表示。如果立即数记作<immediate> , 8位常数记作immed_8 , 4位的循环右移值记作rotate_imm ,有效的立即数是由一个8位的立即数循环右移偶数位得到,可以表示成:

<immediate>=immed_8循环右移( 2×rotate_imm)

如:mov r4 , #0x8000 000A    #0x8000 000A 由0xA8循环右移0x2位得到。

下面介绍一些比较常用到一些指令。


内存访问指令:

LDR和STR,有三种方式,比较容易搞混

LDR r0, [r1, #4]   r0 := mem[r1+4]   ,#4是直接偏移量,这时候只能在正负4Kb到范围内。也可以是寄存器偏移,用+/-表示。记住r1不进行偏移。

LDR r0, [r1, #4]!  r0 :=mem[r1+4],r1 := r1 + 4,取值是取偏移量到值,并且r1进行偏移。

LDR r0, [r1], #4   r0 :=mem[r1] ,r1 := r1 +4,取值是取r1地方到值,取值后进行偏移。运算后自动加4,后变址。

另外:LDRB是无符号字节,SB是有符号字节,H无符号半字,SH有符号半字。

 

存储器和寄存器数据交换:SWP,SWPB

如SWP r0, r1, [r2]   r0 := mem[r2],mem[r2] := r1

多寄存器数据传输:

LDMIA r1, {r0,r2,r5}  r0 = mem[r1], r2 = mem[r1+4], r5=mem[r1+8]

 

通用数据处理指令

第二操作数,常用到有LSR,LSL等,如mov r1, r2, lsl #2 将r2左移2位然后赋值到r1中。

常用到操作有ADD、SUB、AND、ORR、EOR、BIC、ORN,如果加上了S则会更新条件标记。

MOV移动,MVN取反移动。MOV可以是R寄存器,立即数以及接第二操作数。

REV:在字或半字内反转字节或位到顺序

MUL、MLA和MLS,乘法、乘加和乘减。MLA R1,R2,R3,R4表示R1=R2*R3+R4,还有有符号和无符号乘法等。

 

跳转指令

B:无条件跳转,BL:带链接到跳转,BX跳转并交换指令集等。

 

重点介绍一下NEON指令,目前使用较多。而且使用难度也较大,很多文档上都没有比较详细到介绍,也没有给出相应到例子或者图示。

 

一、NEON基本知识

NEON的寄存器:

有16个128位四字到寄存器Q0-Q15,32个64位双子寄存器D0-D31,两个寄存器是重叠的,在使用到时候需要特别注意,不小心就会覆盖掉。如下图所示:

两个寄存器的关系:Qn =D2n和D2n+1,如Q8是d16和d17的组合。

 

NEON的数据类型:

注意数据类型针对到时操作数,而不是目标数,这点在写的时候要特别注意,很容易搞错,尤其是对那些长指令宽指令的时候,因为经常Q和D一起操作。

 

NEON中的正常指令、宽指令、窄指令、饱和指令、长指令

正常指令:生成大小相同且类型通常与操作数向量相同到结果向量

长指令:对双字向量操作数执行运算,生产四字向量到结果。所生成的元素一般是操作数元素宽度到两倍,并属于同一类型。L标记,如VMOVL。

宽指令:一个双字向量操作数和一个四字向量操作数执行运算,生成四字向量结果。W标记,如VADDW。

窄指令:四字向量操作数执行运算,并生成双字向量结果,所生成的元素一般是操作数元素宽度的一半。N标记,如VMOVN。

饱和指令:当超过数据类型指定到范围则自动限制在该范围内。Q标记,如VQSHRUN

 

二、NEON指令

NEON指令较多,下面主要介绍一些常见的指令用法。

 

复制指令:

VMOV:

两个arm寄存器和d之间

vmov d0, r0, r1:将r1的内容送到d0到低半部分,r0的内容送到d0到高半部分

vmov r0, r1, d0:将d0的低半部分送到r0,d0的高半部分内容送到r1

一个arm寄存器和d之间

vmov.U32 d0[0], r0:将r0的内容送到d0[0]中,d0[0]指d0到低32位

vmov.U32 r0, d0[0]:将d0[0]的内容送到r0中

立即数:

vmov.U16 d0, #1:将立即数1赋值给d0的每个16位

vmov.U32 q0, #1:将立即数1赋值给q0的每个32位

长指令:VMOVL:d赋值给q

vmovl.U16 q0, d0:将d0的每个16位数据赋值到q0的每个32位数据中

窄指令:VMOVN:q赋值给d

vmovn.I32 d0, q0:将q0的每32位数据赋值到q0的每16位数据中

饱和指令:VQMOVN等,饱和到指定的数据类型

 vqmovun.S32 d0, q0:将q0到每个32位移动到d0中到每个16位中,范围是0-65535

        

VDUP:

VDUP.8 d0, r0:将r0复制到d0中,8位

VDUP.16 q0, r0:将r0复制到q0中,16位

VDUP.32 q0, d2[0]:将d2的一半复制到q0中

VDUP.32 d0, d2[1]:将d2的一半复制到d0中

注意是vdup可以将r寄存器中的内容复制到整个neon寄存器中,不能将立即数进行vdup,立即数只能用vmov

 

逻辑运算

VADD:按位与;VBIC:位清除;VEOR:按位异或;VORN:按位或非;VORR:按位或

 

移位指令:

VSHL:左移、VSHLL:左移扩展、VQSHL:左移饱和、VQSHLU:无符号左移饱和扩展

VSHR:右移、VSHRN:右移窄、VRSHR:右移舍入、VQSHRUN:无符号右移饱和舍入

 

通用算术指令:

VABA:绝对值累加、VABD:绝对值相加、VABS:绝对值、VNEG:求反、VADD、VADDW、VADDL、VSUB、VSUBL、VSUBW:加减

VPADD:将两个向量的相邻元素相加

如VPADD.I16 {d2}, d0, d1


VPADDL:VPADDL.S16 d0, d1


VMAX:最大值,VMIN:最小值

VMUL、VMULL、VMLA(乘加)、VMLS(乘减)、

 

加载存储指令:

VLD和VST



交叉存取的示意图:

VREV反转元素指令:

 

VEXT移位指令:

 

VTRN转置指令:可以用于矩阵的转置



VZIP指令:压缩,类似交叉存取

VUZP指令:解压操作,类似交叉存取


 

VTBL查表指令:从d0,d1中查找d3中的索引值,如果找到则取出,没有找到则为0,存入d2中

 

三、需要注意的地方

    load数据的时候,第一次load会把数据放在cache里面,只要不超过cache的大小,下一次load同样数据的时候,则会比第一次load要快很多,会直接从cache中load数据,这样在汇编程序设计的时候是非常需要考虑的问题。

     如:求取一个图像的均值,8*8的窗口,先行求和,然后列求和出来均值,这时候会有两个函数,数据会加载两遍,如果按照这样去优化的话则优化不了多少。如果换成上面这种思路,先做行16行,然后再做列,这样数据都在cache里面,做列的时候load数据会很快。

   在做neon乘法指令的时候会有大约2个clock的阻塞时间,如果你要立即使用乘法的结果,则就会阻塞在这里,在写neon指令的时候需要特别注意。乘法的结果不能立即使用,可以将一些其他的操作插入到乘法后面而不会有时间的消耗。

如:vmul.u16 q1, d3, d4 

         vadd.u32 q1, q2, q3

此时直接使用乘法的结果q1则会阻塞,执行vadd需要再等待2个clock的时间

使用饱和指令的时候,如乘法饱和的时候,在做乘法后会再去做一次饱和,所以时间要比直接做乘法要慢。

如:  vmul.u16 q1, d3, d4

          vqmul.u32 q1, q2, q3

后一个的时间要比第一个的时间要久。

在对16位数据进行load或者store操作的时候,需要注意的是字节移位。比如是16位数据,则load 8个16位数据,如果指定寄存器进行偏移,此时需要特别注意。

例如:vld1.64 {d0}, [r0], r1

 

参考资料:

http://blogs.arm.com/software-enablement/277-coding-for-neon-part-4-shifting-left-and-right/

http://blogs.arm.com/software-enablement/161-coding-for-neon-part-1-load-and-stores/

http://blogs.arm.com/software-enablement/684-coding-for-neon-part-5-rearranging-vectors/


转自:http://blog.csdn.net/chshplp_liaoping/article/details/12752749


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/242946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

未成年人可以申请贷款吗?

缺钱是很多人都会遇到的问题&#xff0c;包括未成年人&#xff0c;所以我们经常看到一些未成年人去申请贷款&#xff0c;那未成年人到底能不能贷款呢&#xff1f;在这可以肯定的告诉大家&#xff0c;如果是正规的贷款机构&#xff0c;是不允许给未成年人放贷的。那为什么贷款机…

逾期之后还能贷款吗?

逾期是一件很让人头疼的事情&#xff0c;因为一旦和逾期扯上关系&#xff0c;贷款就比较困难。甚至有一句话说到“一旦逾期深似海&#xff0c;从此贷款是路人”&#xff0c;虽然这句话有点夸大其词&#xff0c;但是逾期对贷款申请的影响是不争的事实。银行对征信的要求有一个原…

VCS安装

基于软件 ubuntu-14.04.2-desktop-amd64.iso/rhel-server-7.1-x86_64-dvd.iso/synopsys vcs-mx_vI-2014.03... software: installer v3.1 & scl v11.7 & vcs-mx_vI-2014.03 & ubuntu 14.04 原始synopsis vcs是 RedHat Enterprise Linux 4.0 编译的&#xff0c;&a…

你是信用卡卡奴吗?怎么摆脱卡奴?

信用卡是一把双刃剑&#xff0c;用得好对生活理财都有很大的帮助&#xff0c;用得不好&#xff0c;就会陷入卡奴的无底深渊&#xff0c;还不完的卡债&#xff0c;给不完的利息。所以&#xff0c;在使用信用卡之前&#xff0c;要多学习信用卡的相关知识&#xff0c;让信用卡成为…

CAN总线笔记

CAN总线 协议11898 边界条件 物理构成 controler&#xff08;控制器&#xff09; transver&#xff08;收发器&#xff09; 低速can收发器 高速can收发器 抗干扰能力 总线逻辑 线与逻辑 communication&#xff08;通讯&#xff09; 通信矩阵 帧格式 数据帧 总线…

常用电平标准

常用电平标准 现在常用的电平标准有TTL、CMOS、LVTTL、LVCMOS、ECL、PECL、LVPECL、RS232、RS485等&#xff0c;还有一些速度 比较高的LVDS、GTL、PGTL、CML、HSTL、SSTL等。下面简单介绍一下各自的供电电源、电平标准以及使用注意事项。 TTL&#xff1a;Transistor-Transistor…

借钱不还,法院可以单方拍卖房产吗?

借钱不还是一个让人很尴尬的事情&#xff0c;虽然有的是人确实有难处还不上&#xff0c;但是对于那些有能力还却不想还的&#xff0c;实在让人深恶痛绝。据法制晚报报道&#xff0c;有一名欠钱不还的老赖&#xff0c;不但拒绝偿还债权人的钱&#xff0c;还和法院玩起了躲猫猫&a…

最小系统介绍

最小系统介绍 &#xff08;1&#xff09;电源电路 &#xff08;2&#xff09;复位电路 &#xff08;3&#xff09;晶振电路 &#xff08;4&#xff09;下载电路 1 电源电路 2 复位电路 3 晶振电路 4 下载电路 TMS320F28335支持多种启动模式

央行无意放宽松,7月贷款仍有可能吃紧

6月的信贷市场可谓硝烟四起&#xff0c;加息揽存&#xff0c;停贷&#xff0c;上调房贷利率&#xff0c;调高首付比例。。。一切看起来就是资金很紧张的局面&#xff0c;所以有不少借款需求的人在观望&#xff0c;6月过后&#xff0c;7月贷款是否会变得容易一些&#xff1f;央行…

CCS6软件安装

CCS6软件安装 第一步&#xff1a;点击右键->以管理员身份安装&#xff08;安装路径不能有中文&#xff09; 第二步&#xff1a;安装驱动

贷款不还要坐牢吗?

欠债还钱&#xff0c;天经地义&#xff0c;这是中国的古训。但是并非每个人都会遵守这个古训&#xff0c;有的人欠钱之后并不一定会按时还钱&#xff0c;甚至有的干脆赖账不还了。对于那些贷款不还的人&#xff0c;法律是否有相关的惩罚呢&#xff1f;贷款不还会坐牢吗&#xf…

存储器与寄存器

存储器与寄存器 1 存储器的映射 存储器本身不具有地址信息&#xff0c;它的地址是由芯片厂商或用户分配&#xff0c;给存储器分配地址的过程称为储存器映射&#xff0c;如果再分配一个地址就叫重映射。

有本事的人才能借钱

先来问大家一个问题&#xff0c;如果有四个人问你借钱&#xff0c;一个是无业游民&#xff0c;无收入无负债&#xff1b;一个是上班族&#xff0c;月收入5000&#xff0c;无负债&#xff1b;一个是公司高管&#xff0c;年薪50万&#xff0c;负债80万&#xff1b;最后一个是上市…

申请贷款必须留联系人吗?不留行不行?

不管是申请贷款还是申请信用卡&#xff0c;在填写贷款申请表的时候&#xff0c;需要留下联系人&#xff0c;少的一两个&#xff0c;多的则是5-6个&#xff0c;特别是贷款都是必须填的&#xff0c;比如亲属2个同事2个朋友2个等。为什么贷款机构必须要求借款人在填申请表的时候留…

工程模板的创建

工程模板的创建 1 获取工程模板基础文件-放入到建立工程的文件夹里 2 创建工程模板 在F盘根目录下面新建一个“CCS Project”文件夹&#xff0c;用于保存工作区间&#xff0c;名字可以不和这个相同&#xff0c;但是最好是建在某个盘符的根目录&…

一发工资就全部取出,会对银行流水有影响吗?

大家都知道银行流水在贷款中举到很关键的作用&#xff0c;不管是申请房贷还是一般贷款&#xff0c;没有足够的银行流水是很通过申请的。那贷款机构是如何判定银行流水的呢&#xff1f;还有一个问题就是&#xff0c;如果发了工资之后全部转出来&#xff0c;用于理财或者其他用途…

Intel INDE(集成原生开发人员体验)的Windows开发指导

Intel INDE Getting Started Guide for Developing Windows* Applications https://software.intel.com/en-us/articles/intel-inde-getting-started-guide-for-windows-platforms 其中的Intel 实现的OpenCL开发 OpenCL™ Code Builder 教程 https://software.intel.com/en-u…

银行卡睡眠多久才会被注销?

从2017年7月15日起开始&#xff0c;各大银行将会对“睡眠卡”进行统一注销。对于“睡眠卡”大家估计都没有什么概念&#xff0c;什么叫睡眠卡&#xff1f;多久不用才叫睡眠卡呢&#xff1f;所谓睡眠卡简单来说就是没有余额或余额较小又长期不用的银行卡。睡眠卡可以分为借记卡睡…

F28335时钟及控制系统

F28335时钟及控制系统 1 F28335系统时钟来源 紧接着放入程序&#xff01;