https://blog.csdn.net/SoaringLee_fighting/article/details/80764811
https://blog.csdn.net/SoaringLee_fighting/article/details/81287824
https://blog.csdn.net/SoaringLee_fighting/article/details/81058147
https://blog.csdn.net/SoaringLee_fighting/article/details/80770034
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0018a/index.htmlcss
ARM是RISC(精简指令集)处理器,不一样于x86指令集(CISC,复杂指令集)。
Arm32位是ARMV7架构,32位的,对应处理器为Cortex-A15;
iphone5之前均是32位的;
须要注意:ARMV7-A和ARMV7-R系列支持neon指令集,ARMv7-M系列不支持neon指令集。html
ARMV7架构A和R系列参考手册下载地址:
https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdfbash
Arm64位是ARMV8架构,64位的,对应处理器有Cortex-A5三、Cortex-A5七、iphone5s的A七、iphone6的A8等。
ARMV8架构参考手册下载地址:
https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
https://static.docs.arm.com/ddi0487/ca/DDI0487C_a_armv8_arm.pdf
全部ARM参考文档地址:
https://developer.arm.com/docs
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0403e.b/index.html架构
主要分为ARM寄存器和NEON寄存器。
ARM32寄存器包括15个通用寄存器R0~R14和一个程序计数器PC,共16个,均为32位宽。
ARM32位寄存器的调用规则:遵循ATPCS调用规则,详细参见
https://blog.csdn.net/SoaringLee_fighting/article/details/81287824jsp
32位 NEON寄存器:
包括:32个S寄存器,S0~S31,(单字,32bit)
32个D寄存器,D0~D31,(双字,64bit)
16个Q寄存器,Q0~Q15,(四字,128bit)
寄存器的对应关系以下图所示:
优化
使用注意:
一、NEON寄存器将每一个寄存器均视为一个向量,该向量又包含1,2,4,8或16个大小和类型均相同的元素。也能够将各个元素当作标量访问。
NEON的这三种寄存器是重叠的,物理地址是同样的。
二、NEON寄存器在使用时,若是用到d8~d15寄存器,须要先入栈保存vpush {d8-d15},使用完以后要出栈vpop {d8-d15}ui
ARM指令集的寻址方式与x86指令集大部分相同,但也有其特有的寻址方式,好比寄存器偏移寻址,多寄存器寻址和堆栈寻址。
ARM指令共有9种寻址方式,具体参见:
https://blog.csdn.net/SoaringLee_fighting/article/details/80770034spa
ARM汇编特色1:LDR/STR架构
ARM采用RISC架构,CPU自己不能直接读取内存,而须要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理。
ldr(load register)指令将内存内容加载入通用寄存器。
str(store register)指令将寄存器内容存入内存空间中。
ldr/str组合用来实现 ARM CPU和内存数据交换。.net
ARM汇编特色2:指令后缀
同一指令常常附带不一样后缀,变成不一样的指令。常用的后缀有:
B(byte)功能不变,操做长度变为8位
H(half word)功能不变,长度变为16位
S(signed)功能不变,操做数变为有符号
如 ldr ldrb ldrh ldrsb ldrsh
S(S标志)功能不变,影响CPSR标志位
W(宽型)
L(长型)
N(窄型)
S(饱和)
Q(舍入取整)
ARM汇编特色3:条件执行
subgt,addle等,只有在上一条指令执行以后相应标志位知足条件以后,当前指令才会执行,经过使用条件执行指令能够减小分支跳转。
ARM汇编特色4:多级流水线技术
ARM7处理器(对应架构armv3或armv4)采用3级流水线的冯·诺伊曼结构;而ARM9(对应架构armv4或armv5)用5级流水线的哈佛结构,ARM11(对应架构armv6)为8级流水线哈佛结构(从arm9开始都采用了哈佛结构)。增长的流水线设计提升了时钟频率和并行处理能力。5级流水线可以将每个指令处理分配到5个时钟周期内,在每个时钟周期内同时有5个指令在执行。在经常使用的芯片生产工艺下,ARM7通常运行在100MHz左右,而ARM9则至少在200MHz以上.ARM11首先推出350M~500MHz时钟频率的内核,目前上升到1GHz时钟频率。
参考:https://blog.csdn.net/SoaringLee_fighting/article/details/81411760
ARM NEON优化技巧总结,参见:
https://blog.csdn.net/SoaringLee_fighting/article/details/81265865
https://blog.csdn.net/SoaringLee_fighting/article/details/81705311
ARM指令集:32位,工做在ARM模式下。
Thumb指令集:16位,工做在Thumb模式下。
NEON指令集:以v开头,基于ARMv7架构的SIMD和向量浮点VFPv3指令集。
ARM算术指令:
add, adc, sub, subs, rsb, mul, udiv等
ARM移位指令:
lsl, lsr, ror,asr等
ARM饱和指令:
ssat, usat,qadd,qsub
ARM逻辑运算指令:
orr,and,orn,eor,
NEON逻辑运算和比较指令:
vand,vorr, vbic, vorn
vbif,bsl,vbit
vmov,vmvn
vceq,vcge,vcgt,vcle,vclt
vtst
NEON移位指令:
vshr,vshl,vqshl,vqrshrun
vsli,vsri
NEON通用算术指令:
vabs,vabd,vneg, vadd,vsub,vqadd,vqsub,vaddl,vaddw,vsubl,vsubw
vaddhn,vsubhn
vhadd,vhsub
vpadd,vpadal
vmax,vmin,vpmax,vpmin
NEON乘法指令:
vmul,vmla,vmls
vext指令:向量提取
vext.8 d2, d0, d1, #3
说明:取d1寄存器中低3位向量做为高位,d0寄存器的高5位向量做为低位,构成目标向量。
asr和lsr的区别:
asr r0, r1, #5 //算术右移,符号位填充左侧空出的位 lsr r0, r1, #5 //逻辑右移,0填充左侧空出的位
vpadd:向量按对加
vceq,vcgt,vcge, vcle,vclt指令:
向量比较,获取向量中每一个元素的值,并将其与另外一个向量重相应元素或零进行比较。若是条件为真,则将目标向量中的所有元素设置为1,不然设置为0。
vrshr指令:舍入右移 ,能够实现(a+(1<<(b-1)))>>b的操做。
vaddl和vaddw指令:加法长指令、加法宽指令
vqmovun指令:有无符号操做数,无符号结果
vqmovun.s16 d0, q0
说明: 将q0中每一个16位有符号向量饱和到d0中每一个8位无符号向量。
1)、vld1加载:
vld1.8 {d0,d1} , [r1], r2
说明: 将r1地址里面的连续的128bits数据依次赋给d0和d1,而后r1+r2。这里的.8表示以8bit为单位。
2)、
vld1.16 {d0[],d1[]}, [r0:16]
说明:这里d0和d1中的数据相同,将地址r0中取4个16位数据加载到d0和d1中。
https://blog.csdn.net/SoaringLee_fighting/article/details/81150083
ARM汇编格式主要有两种,arm asm汇编格式和gnu asm汇编格式。
gnu asm汇编格式:
.arm .text .align 4 .global name .type %function name: FUNCTION STATEMENT @注释行 /* 多行注释 */ //单行注释,用于.S汇编文件 bx lr
arm asm汇编格式:
EXPORT |name| ARM AREA ||.text||, CODE, READONLY,ALIGN=2 |name| PROC ;注释 ENDP END
1)标签名称不能以数字开始,可是可使用纯数字的局部标签。
2)ld1连续存储数据时,所用的寄存器必须是连续的。
3)Arm32位下数据在不一样寄存器之间转换:
从r寄存器到d寄存器:
vmov d0, r0, r1 vmov.u32 d0[0], r1
从d寄存器到r寄存器:
vmov r0, r1, d0 vmov.u32 r1, d0[0]
从标量寄存器d[x]到矢量寄存器d:
vdup.16 d1, d6[0] vdup.16 d1, r12
4)Arm32位下替代判断的命令:
vceq,vbsl,vbit, vbif
5)Arm32下取数据地址问题
arm下默认地址r0加1,是加一个字节,若是r0对应的数据是int类型的,则取idx位置的数据则为:r0+idx*4
下面是最基本的方法:
汇编文件中添加以下宏代码:
.macro print_m in1=r0, in2=d0 push {r0-r3, lr} vstl.u64 {\in2\()}, [\in1\()] mov r0, \in1 bl cprintf pop {r0-r3, pc} .endm
C文件中添加cprintf实现代码:
void cprintf(unsigned char *srcu8) { int i=0; char *srcs8 = (char *)srcu8; for(i=0; i < 16; i++){ printf("%d ", srcu8[i]) } for(i=0; i < 16; i++){ printf("%d ", srcs8[i]) } printf("\n"); }
关于arm寄存器的打印调试方法,参见:
https://blog.csdn.net/SoaringLee_fighting/article/details/80834098
除了上述基本方法之外,能够借助RVDS或GDB软件进行调试。
注意事项:
一、RVDS只能用于ARM32位调试,ARMV8架构不支持RVDS。
二、采用GDB调试的前提是ARM开发板上已经安装好了GDB,采用GDB进行调试是很方便的。
THE END!