首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

关于ARM v8指令的几个问题

关于ARM v8指令的几个问题

问题一:ARMv8 branch指令格式及用法(《ARMv8ISA overview》中 page 25有相关叙述):
1、 无条件分支+立即数:直接跳转到某地址,不能跳转到寄存器
指令有两个:”b label”  ”bl label”。在编译过程,编译器会将label翻译成立即数。
举例:编写汇编代码如下
main:
     label:  nop
      b label
      ret
编译并且反汇编后:
0000000000400510 <main>:
label():
  400510:       d503201f        nop
  400514:       17ffffff                        b       400510 <main>
      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指令的目标地址)/41
即当前b指令地址与目标地址做差后整出4(因为是32位地址),再减一。
label():
  400510:       d503201f        nop
  400514:       17ffffff                        b       400510 <main>
      400518:       d65f03c0        ret
上面的例子中,b指令所在地址为400514,label所在的地址是400510(label只是个标签,不占用空间,其指示的是离自己最近的下一条指令地址),根据上述公式能得到encoding=0x17ffffff—(400514—400510)/4=0x17ffffff.

同理就能理解以下代码:

000000000040051c <label2>:
label2():
  40051c:      d503201f        nop
  400520:       d503201f        nop
  400524:       d503201f        nop
400528:       17fffffd       b       40051c <label2>
Encoding=0x17ffffff—400528—40051c/4—1= 0x17ffffff—2 = 17fffffd      
2、理解了向后跳转,则向前跳转是同理的:
向前跳转时,branch指令将除base opcode之外的位全部置零,然后做加法如下:
指令的Encoding = 0x14000000 &0xfc000000+branch指令的目标地址当前b指令所在的指令地址)/4

0000000000400510 <main>:
$x():
  400510:       14000003       b       40051c <label2>
  400514:       aa0203e1        mov    x1, x2
  400518:       aa0203e1        mov    x1, x2

000000000040051c <label2>:

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

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