关于ARMv8指令的几个问题

2020-01-20来源: eefocus关键字:ARMv8  指令  寄存器

NOTE:以下内容只针对ARMv8。


问题一:ARMv8 branch指令格式及用法(《ARMv8ISA overview》中 page 25有相关叙述):


1、无条件分支+立即数:直接跳转到某地址,不能跳转到寄存器


指令有两个:”b label”  ”bl label”。在编译过程,编译器会将label翻译成立即数。


举例:编写汇编代码如下


main:


     label:  nop


      b label


      ret


编译并且反汇编后:


0000000000400510

:


label():


  400510:       d503201f        nop


  400514:       17ffffff                        b       400510


  400518:       d65f03c0        ret


2、无条件分支+寄存器:


blr   Xm:跳转到由Xm目标寄存器指定的地址处,同时将下一条指令存放到X30寄存器中。例如:blr  x20.


br      Xm:跳转到由Xm目标寄存器指定的地址处。不是子程序返回


ret     {Xm}:跳转到由Xm目标寄存器指定的地址处。是子程序返回。Xm可以不写,默认是X30.


3、条件分支:所有条件分支的跳转目标都是立即数!


ARMv8的条件分支写法:b.cond   label。其中cond是条件码共十六个(EQ,NE,CS等等)


问题二:ARMv8指令分类:


关于ARMv8的指令,在《ARMv8ISA overview》中做了分类,5.2章——5.6章是INT型指令,5.7是浮点指令,5.8是SIMD(即ARMv7中提到的NEON)指令。


关于SIMD指令如何操作,在5.8节有简单介绍,建议先看下4.4.2节关于FP/SIMD寄存器的说明。


另外,INT指令与FP指令之间的操作是针对不同的寄存器,所有两者之间没多少关系,至多就是INT型指令修改了寄存器内容,FP指令将修改后的寄存器当做源操作数读取。


问题三:


1、 ARMv8有没有两个目的操作数的指令?


答:有。例如LDP指令,从内存某地址处加载两个字到目的寄存器中,用法:LDP Wt1, Wt2, addr。  


2、 ARMv8中源操作数超过三个的指令及分类:


(1)    扩展寄存器类操作,如:ADD   X1, X2, W3, UXTB #2


这里把UXTB和#2分别当做一个源操作数。


(2)    移位寄存器类操作,如:ADD         W1,W2,W3, lsl #2


目前能确定的只有这两类,最多不超过四种类型。如果需要我会做出详细的表。


另外,关于问题一中,为什么b指令的base opcode是0x14000000,而“b   label”指令翻译成二级制是0x17ffffff的解答如下:


Branch指令是相对当前pc的分支指令。


1、 在ARMv8中,相对于当前b指令向后跳转时,编译器生成指令的二进制encoding(即b指令最终生成的二进制代码)的过程如下:


向后跳转时,branch指令将除base opcode之外的位全部置一,然后做减法如下:


指令的Encoding = (0x14000000 | 0x03ffffff)—(当前b指令所在的指令地址—branch指令的目标地址)/4—1


即当前b指令地址与目标地址做差后整出4(因为是32位地址),再减一。


label():


  400510:       d503201f        nop


  400514:       17ffffff                        b       400510


  400518:       d65f03c0        ret


上面的例子中,b指令所在地址为400514,label所在的地址是400510(label只是个标签,不占用空间,其指示的是离自己最近的下一条指令地址),根据上述公式能得到encoding=0x17ffffff—(400514—400510)/4=0x17ffffff.


同理就能理解以下代码:


000000000040051c :


label2():


  40051c:      d503201f        nop


  400520:       d503201f        nop


  400524:       d503201f        nop


  400528:       17fffffd        b       40051c


Encoding=0x17ffffff—(400528—40051c)/4—1= 0x17ffffff—2 = 17fffffd       


2、理解了向后跳转,则向前跳转是同理的:


向前跳转时,branch指令将除base opcode之外的位全部置零,然后做加法如下:


指令的Encoding = (0x14000000 &0xfc000000)+(branch指令的目标地址—当前b指令所在的指令地址)/4


0000000000400510

:


$x():


  400510:       14000003        b       40051c


  400514:       aa0203e1        mov    x1, x2


  400518:       aa0203e1        mov    x1, x2


000000000040051c :


Encoding=0x14000000 + (40051c—400510)/4 = 0x14000000 + 3=0x14000003


(其他体系结构暂时没做过测试,不过估计应该一样)

关键字:ARMv8  指令  寄存器 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic486243.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:从编译器源码中提取ARMv8的指令编码
下一篇:armv8(aarch64)linux内核中flush_dcache_all函数详细分析

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

ARMv7体系结构学习笔记(一)
本轮学习过程主要集中在ARM NEON技术的学习,主要包括指令的学习、编程技巧的总结。ARM NEON 技术是ARMv7体系结构的可选组件。NEON是针对高级媒体和信号处理应用程序以及嵌入式处理器64/128位混合SIMD技术,它是作为ARM内核的一部分实现的,但有自己的执行管道和寄存器组,该寄存器组不同于ARM核心寄存器组。NEON支持整数、定点和单精度浮点SIMD运算。这些指令在ARM和Thumb-2中都可用。NEON 扩展寄存器组:--- 16-128bit 四字寄存器Q0~Q15--- 32-64bit 双字寄存器D0~D31许多NEON数据处理指令可具有正常指令、长指令、宽指令、窄指令和饱和指令变体
发表于 2020-02-04
ARMv7用户层发生指令异常的处理流程
1、用户层发生指令异常的处理流程?用户层程序正在执行时,遇到未定义的指令(ARM不是别的指令)或者SWI软件中断指令(产生系统调用),就会产生异常,这里以未定义指令异常为例进行说明:一旦出现未定义指令异常,CPU会自动做如下操作:(1)未定义模式(ARM其中运行模式的一种)下对应的lr(即R14)寄存器保存当前发生异常的指令下一条指令的地址。例如,在用户态有A B C 三条指令,指令A发生未定义指令异常,则指令B的地址就会由CPU保存到未定义模式下的lr寄存器中,用于异常返回。(2)CPU修改CPSR寄存器,进入未定义模式:CPSR[4:0]=0b11011   /*将CPSR的低五位置位11011,正好对应未定
发表于 2020-01-20
ARMv8 Linux内核head.S源码分析
ARMv8Linux内核head.S主要工作内容:1、 从el2特权级退回到el12、 确认处理器类型3、 计算内核镜像的起始物理地址及物理地址与虚拟地址之间的偏移4、 验证设备树的地址是否有效5、 创建页表,用于启动内核6、 设置CPU(cpu_setup),用于使能MMU7、 使能MMU8、 交换数据段9、 跳转到start_kernel函数继续运行。/* *Low-level CPU initialisation *Based on arch/arm/kernel/head.S * *Copyright (C) 1994-2002 Russell King 
发表于 2020-01-20
armv8(aarch64)linux内核中flush_dcache_all函数详细分析
字段,clidr_el1的格式见《ARMv8 ARM》    add x2, x10, x10, lsr #1        /      //x0逻辑右移x2位,给x1,提取cache类型放到x1中,x0中存放:clidr_el1    lsr x1, x0, x2                //掩掉高位,只取当前cache类型    and x1, x1, #7      
发表于 2020-01-20
armv8(aarch64)linux内核中flush_dcache_all函数详细分析
从编译器源码中提取ARMv8的指令编码
问题1:提取ARMv8的指令编码答:ARMv8指令的opcode可以在支持ARMv8的编译器binutils中找到,该工具能在网上找到,见参考资料[1],或者在[1]中搜索aarch64_opcode_table。为了说明指令编码细节,现将网页中部分内容摘录如下:1208 struct aarch64_opcode aarch64_opcode_table[] =1209 {1210  /* Add/subtract (with carry).  */1211  {"adc", 0x1a000000, 0x7fe0fc00, addsub_carry, 0, CORE, OP3
发表于 2020-01-20
从编译器源码中提取ARMv8的指令编码
ARM指令分类学习
指令分类:1、算数和逻辑指令2、比较指令3、跳转指令4、移位指令5、程序状态字访问指令6、存储器访问指令++++++++++++++++++++++++++++++++++++++++++++++++++学习指令的资料《arm汇编手册(中文版).chm》 ,注:这个资料是 ARM汇编手册,我们用的是GNU的汇编,所以语法 大小写上是有差别的。使用上一篇文章中的汇编程序来,学习使用每个指令的用法。一、算数和逻辑指令1、mov指令作用、格式、例子从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器。MOV{条件}{S}  <dest>, <op 1>   。其中<
发表于 2020-02-22
ARM指令分类学习
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved