概述

ARMv8体系结构中引入的最重要的变化之一是添加了64位指令集。该指令集补充了现有的32位指令集体系结构。此新增提供了对64位宽整数寄存器和数据操作的访问,以及使用64位大小的内存指针的能力。新指令集称为A64,在AArch64状态下执行。ARMv8还包括原始ARM指令集,现在称为A32和Thumb(T32)指令集。32和T32都在AArch32状态下执行,并与ARMv7兼容。
尽管ARMv8-A提供了与32位ARM体系结构的向后兼容性,A64指令集与旧的指令集不同,编码方式也不同。A64增加了一些附加功能,同时删除了有可能限制性能速度或能耗的其他功能。ARMv8体系结构还包括对32位指令集(A32和T32)的一些新增。但是,使用这些特性的代码与较旧的ARMv7实现不兼容。然而,A64指令集中的指令操作码仍然是32位,而不是64位。

1、The ARMv8 instruction sets

新的A64指令集与现有的A32指令集类似。指令的宽度为32位,并且具有类似的语法。
指令集在ARMv8体系结构中使用通用命名方式,因此原始32位指令集状态现在称为:

  • A32:在AArch32状态下,指令集基本上与ARMv7兼容,尽管存在差异。请参阅,ARMv8-A体系结构参考手册。它还提供了一些新指令,以与A64指令集中引入的一些功能保持一致。
  • T32:Thumb指令集开始只包含在ARM7TDMI处理器中,并且最初只包含16位指令。16位指令以牺牲一些性能为代价提供了更小的程序。ARMv7处理器,包括Cortex-A系列中的处理器,支持Thumb-2技术,该技术扩展Thumb指令集,以提供16位和32位指令的混合。这提供了与ARM类似的性能,同时兼容了对于代码尺寸的优化。由于其尺寸和性能优势,编译或组装所有32位代码以利用Thumb-2越来越普遍技术。

新的指令集在AArch64状态下使用,成为A64,A64提供与ARMv7或AArch32中的A32和T32指令集类似的功能。新A64指令集的设计几项改进如下:

  • 相同的编码体系:A32中某些指令的延迟加载导致了编码方案中的一些不一致性。例如,对半字操作的的LDR和STR指令支持的编码与主流字节和字传输指令略有不同。其结果是寻址模式的不同。
  • 常量范围增大:A64指令为常数提供了大量选项,每个选项都是根据特定指令类型的要求定制的,如算术指令通常接受12位立即数常量、逻辑指令通常接受32位或64位常量,它的编码有一些限制、MOV指令接受16位立即数,它可以被转移到任何16位边界、地址指令适用于与4KB页面大小对齐的地址。
    位操作指令中使用的常量规则稍微复杂一些。但是,位字段操作指令可以在源操作数或目标操作数中寻址任何连续的位序列。A64提供了灵活的常量,但要对它们进行编码,需要确定某个特定常量是否可以在特定上下文中合法编码。
  • 更加简洁的数据类型:A64可以更加方便的处理64bit的运算,更加简洁有效。
  • 更大的偏移:A64指令通常提供较长的偏移量,用于PC跳转和偏移量寻址。动态生成的代码通常放在堆上,但实际上它可以位于任何位置。系统运行时,可跳转的地址范围变大可以更加方便的管理,并减少bug的产生。
  • 指针:AArch64中的指针是64位的,虚拟内存要寻址的内存范围增大,并为地址映射提供更多自由度。但是,使用64位指针确实会产生一些成本。使用64位指针运行时,同一段代码通常比使用32位指针运行时使用更多内存。每个指针都存储在内存中,需要八字节而不是四字节。这听起来可能微不足道,但加起来可能是一个重大的影响。同时过大的内存地址范围会导致缓存命中率下降。有些语言可以用压缩指针实现,例如作为Java,它可以避免性能问题。
  • 使用条件构造代替IT块:IT块是T32的一个有用功能,能够实现高效的序列,避免在未执行的指令周围使用短的前向分支。然而,硬件有时很难有效地处理这些问题。A64删除这些块并用条件指令(如CSEL、条件选择和CINC或条件增量)替换它们。这些条件结构更简单,更易于处理,无需特殊情况。
  • 移位和翻转行为更直观:A32或T32的移位和翻转行为并不总是容易映射到高级语言所期望的行为。ARMv7提供了一个桶形移位器,可以用作数据处理指令的一部分。但是,指定移位类型和移位量需要一定数量的操作码位,可以在其他地方使用。A64指令因此删除了很少使用的选项,而是添加了新的显式指令以执行更复杂的换档操作。
  • 代码生成:在为常用算术函数生成静态和动态代码时,A32和T32通常需要不同的指令或指令序列。这是为了处理不同的数据类型。A64中的这些操作更加一致,因此更容易为不同大小的数据类型上的简单操作生成公共序列。例如,在T32中,根据使用的寄存器(低寄存器或高寄存器),同一条指令可以有不同的编码。A64指令集编码更加规则和合理。因此,A64的汇编程序通常比T32的汇编程序需要更少的代码行。
  • 定长指令:所有A64指令长度相同,而T32是一个可变长度指令集。这使得生成的代码序列的管理和跟踪更加容易,特别是影响动态代码生成器。
  • 三态操作映射更优:通常,A32为数据处理操作保留真正的三态操作数结构。另一方面,T32包含大量的两态操作数指令格式,这使得它在生成代码时灵活性稍差。A64坚持一致的三态操作数语法,这进一步有助于指令集的规则性和一致性,以利于编译器

1.1 区分32位和64位A64指令

A64指令集中的大多数整数指令有两种形式,它们在64位通用寄存器文件中对32位或64位值进行操作。
查看指令使用的寄存器名时:

  • 如果寄存器名以X开头,则为64位值。
  • 如果寄存器名以W开头,则为32位值。

如果选择32位指令形式,则以下遵循以下:

  • 右移和翻转指令在第31bit,而不是63bit
  • 由指令设置的条件标志由较低的32位计算
  • 写入W寄存器,将会使X寄存器的位[63:32]清零

即使当32位指令和64位的低32位指令结果一致时,这种区别也适用。
例如,可以使用64位ORR执行32位按位ORR,只需忽略结果的前32位。A64指令集包括单独的32位和64位ORR指令形式。
因此,新的A64指令集提供了独特的符号和零扩展指令。另外,A64指令集意味着可以扩展和移位ADD、SUB、CMN或CMP指令的源寄存器以及Load或Store指令的索引寄存器。这将导致高效实现涉及64位数组指针和32位数组索引的数组索引计算。

1.2 寻址

当处理器可以在单个寄存器中存储64位值时,访问程序中的大量内存就变得简单多了。
在32位内核上执行的单个线程仅限于访问4GB的地址空间,该空间的大部分保留供操作系统内核、库代码、外围设备等使用。因此,空间不足意味着程序在执行时可能需要映射内存中或内存外的一些数据。使用更大的地址空间和64位指针可以避免此问题。它还使内存映射文件等技术更具吸引力,使用起来更方便。文件内容映射到线程的内存映射中,即使物理RAM可能不足以容纳整个文件。
其他的改动包括:

  • 独立访问:字节、半字、字和双字的独立存储。对于2word的访问可以原子更新,例如循环列表插入。所有其他的访问必须自然对齐,排他对访问必须对齐到数据大小的两倍,即一对64位值为128位。

  • 增加PC相对偏移量寻址:PC相对寻址是加载的文本偏移范围可为±1MB。与A32的PC相对寻址相比,这减少了文本池的数量,并增加了函数之间文本数据共享。反过来,这又减少了I-cache和TLB污染。在大部分函数的条件分支中1MB的范围足以满足需求。
    无条件分支(包括分支和链接)的范围为±128MB,预计足以跨越大多数可执行加载模块和共享对象的静态代码段,而无需插入链接器。
    仅使用两条指令即可在线执行范围为±4GB的PC相对加载、存储和地址生成,也就是说,不需要从文本池加载偏移量。
    文本池的本质就是ARM汇编语言代码节中的一块用来存放常量数据而非可执行代码的内存块。

  • 未对齐地址支持:除独占和有序访问外,所有加载和存储都支持在访问普通内存时使用未对齐的地址。这简化了将代码移植到A64的过程。

  • 批量传输:A64中不存在LDM、STM、PUSH和POP指令。可以使用LDP和STP指令构造批量传输。这些指令从连续的内存位置加载并存储一对独立的寄存器。LDNP和STNP指令提供流式或非时态提示,即数据不需要保留在缓存中。PRFM或预回迁内存指令可以将预回迁定向到特定的缓存级别。

  • Load/Store:所有加载/存储指令现在都支持一致的寻址模式。例如,当从内存加载和存储时,这使得以相同的方式处理char、short、int和long变得更加容易。浮点和NEON寄存器现在支持与内核寄存器相同的寻址模式,从而更容易使用这两个寄存器组。

  • 对齐检查:在AArch64中执行时,会附加对齐检测在取指中,使用sp指针进行加载或存储时,会对PC或当前SP的进行未对齐检查。此方法优于强制PC或SP正确对齐,因为PC或SP未对齐通常表示软件错误,例如软件中的地址损坏。
    有多种类型的对齐检查
    每当试图执行AArch64中未对齐PC获取的指令时,程序计数器对齐检查会生成与指令获取相关的异常。未对准PC被定义为PC的位[1:0]不为00的PC。当使用AArch64处理异常时,相关的异常链接寄存器以其未对齐的形式保存整个PC,故障地址寄存器FAR_ELn也是如此,用于处理异常的异常级别。
    每当尝试在AArch64中使用堆栈指针作为基址进行加载或存储时,堆栈指针(SP)对齐检查将生成与数据内存访问相关联的异常。未对齐的堆栈指针是堆栈指针的位[3:0],用作计算的基址,不是0000。当堆栈指针用作基址时,它必须是16字节对齐的。
    堆栈指针对齐检查仅在AArch64中执行,并且可以针对每个异常级别单独启用:
    EL0和EL1由SCTLR_EL1中的两个独立位控制、EL2由SCTLR_EL2中的一个位控制、EL3由SCTLR_EL3中的一个位控制。

1.3 寄存器

A64 64位寄存器组有助于降低大多数应用中的寄存器压力。A64过程调用标准(PCS)在寄存器(X0-X7)中传递多达八个参数,相比之下,A32和T32在寄存器中只传递四个参数,多余的参数只能使用堆栈进行传递。PCS还定义了一个专用的帧指针(FP),使调试和调用关系分析更容易,因为它可以可靠地展开堆栈。有关更多信息,请参阅第9章ARM 64位体系结构的ABI。
采用64位寄存器的结果是编程语言使用的变量宽度不同。目前正在使用许多标准模式,它们主要不同于为整数、long和指针的大小:

64位Linux实现使用LP64,A64过程调用标准支持这一点。定义了可由其他操作系统使用的其他PC变体。

zero寄存器
零寄存器(WZR/XZR)用在一些编码技巧中。例如,没有简单的乘法编码,只有乘加器。指令MUL W0,W1,W2与使用零寄存器的MADD W0,W1,W2,WZR相同。并非所有指令都可以使用XZR/WZR。正如我们在第4章中提到的,零寄存器与堆栈指针共享相同的编码。这意味着,对于某些参数,对于数量非常有限的指令,WZR/XZR不可用,而是使用WSP/SP。


零寄存器的一个方便的隐藏作用是,有许多NOP指令具有大的立即数字段。

Stack pointer
大多数指令无法引用堆栈指针。某些形式的算术指令可以读取或写入当前堆栈指针。这可能是为了调整函数开始或尾声中的堆栈指针位置。例如:添加SP,SP,#256//SP=SP+256

PC指针
当前程序计数器(PC)不能像通用寄存器的一部分那样以数字表示,因此不能用作算术指令的源或目标,也不能用作加载和存储指令的基、索引或传输寄存器。读取PC的唯一指令是那些其功能是计算PC相对地址(ADR、ADRP、文字加载和直接分支)的指令,以及在链接寄存器(BL和BLR)中存储返回地址的分支和链接指令。
修改程序计数器的唯一方法是使用分支、异常生成和异常返回指令。
如果PC被一条指令读取以计算PC的相对地址,那么它的值就是该指令的地址。与A32和T32不同,没有4或8字节的隐含偏移量。

FP and NEON registers
对NEON寄存器最重要的更新是NEON现在有32个16字节寄存器,而不是以前的16个寄存器。浮点寄存器组和NEON寄存器组中不同寄存器大小之间的简单映射方案使这些寄存器更易于使用。编译器和优化器更容易对映射进行建模和分析。

寄存器索引寻址
A64指令集提供了与A32相关的附加寻址模式,允许将64位索引寄存器添加到64位基址寄存器,并根据访问大小对索引进行可选缩放。此外,它在索引寄存器中提供32位值的符号或零扩展,同样具有可选的缩放。

2、C/C++内联汇编

在本节中,我们简要介绍了如何在C或C++语言模块中包含汇编代码。
asm关键字可以将内联GCC语法汇编代码合并到函数中。例如:

asm内联汇编语句的一般形式为:
asm(code [: output_operand_list [: input_operand_list [: clobber_list]]]);

code:汇编代码,在如上例子中就是 ADD %[result], %[input_i], %[input_j]
output_operand_list:输出操作数的可选列表,用逗号分隔。每个操作数由方括号中的符号名、约束字符串和括号中的C表达式组成。在如上例子中就是**[result] “=r” (res)**
input_operand_list:输入操作数的可选列表,用逗号分隔。输入操作数使用与输出操作数相同的语法。在如上例子中有两个输入,[input_i]“r” (i) and [input_j] “r” (j)
clobber_list:一个可选的被删除寄存器或其他值列表。
在C/C++和汇编代码之间调用函数时,必须遵循AAPCS64规则。
详见https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html#Using-Assembly-Language-with-C

3、在指令集之间切换

不可能在单个应用程序中使用来自两个执行状态的代码。在ARMv8中,A64与A32或T32指令集之间没有互通,A32与T32指令集之间也没有互通。用A64编写的用于ARMv8处理器的代码不能在ARMv7 Cortex-A系列处理器上运行。但是,为ARMv7-A处理器编写的代码可以在AArch32执行状态下在ARMv8处理器上运行。图5-1对此进行了总结:

ARM V8A体系结构-第五章 ARMv8指令集简介相关推荐

  1. ARM V8A体系结构-第七章 AArch64的浮点和NEON

    概述 ARM高级SIMD体系结构.相关实现和支持软件通常被称为NEON技术.AArch32(相当于ARMv7 NEON指令)和AArch64都有NEON指令集.这两种方法都可以大大加快大型数据集上的重 ...

  2. ARM V8A体系结构-第十二章 The Memory Management Unit

    概述 内存管理单元(MMU)的一个重要功能是使系统能够运行多个任务,作为独立的程序在它们自己的私有虚拟内存空间中运行.他们不需要了解系统的物理内存映射,也就是硬件实际使用的地址,或者可能同时执行的其他 ...

  3. ARM V8A体系结构-第十九章 ARMv8 Models

    概述 平台模型(如本章中描述的模型)允许在不需要实际硬件的情况下开发软件.软件模型从程序员的角度提供处理器和设备的模型.模型的功能行为等效于实际硬件.为了实现快速的模拟执行速度,牺牲了绝对计时精度.这 ...

  4. ARM V8A体系结构-第十四章 多核处理器

    概述 ARMv8-A体系结构为包含多个处理元素的系统提供了高水平的支持.Cortex-A57MPCore和Cortex-A53MPCore处理器等ARM多核处理器可以包含一到四个核.使用Cortex- ...

  5. linux编程是否含7,第7章Linux编程简介.ppt

    第7章Linux编程简介 ARM 应用系统设计第7章 Linux编程简介 佘黎煌 东北大学信息科学与工程学院 电子信息工程研究所 嵌入式Linux概况 现在 Linux 广泛用于各类计算应用,不仅包括 ...

  6. ARM裸机篇(五)——异常和中断

    linux系列目录: linux基础篇(一)--GCC和Makefile编译过程 linux基础篇(二)--静态和动态链接 ARM裸机篇(一)--i.MX6ULL介绍 ARM裸机篇(二)--i.MX6 ...

  7. 【ARMv8 编程】ARMv8 指令集介绍

    ARMv8 架构中引入的最重要的变化之一是增加了 64 位指令集.该指令集补充了现有的 32 位指令集架构.这种增加提供了对 64 位宽整数寄存器和数据操作的访问,以及使用 64 位长度的内存指针的能 ...

  8. subd计算机系统结构,计算机体系结构第2章试题答案.doc

    计算机体系结构第2章试题答案.doc (9页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.90 积分 一 填空题1.堆栈型 通用寄存器型2.累加器型 ...

  9. Android深度探索--HAL与驱动开发----第五章读书笔记

    第五章主要学习了搭建S3C6410开发板的测试环境.首先要了解到S3C6410是一款低功耗.高性价比的RISC处理器它是基于ARMI1内核,广泛应用于移动电话和通用处理等领域. 开发板从技术上说与我们 ...

最新文章

  1. LightHouse/归并排序
  2. Linux创建文件自动消失,Linux中没有文件创建时间的概念
  3. Python读写json文件中文编码问题
  4. avalon2学习教程04显示隐藏处理
  5. python组合数据分类_Python 数据可视化:分类特征统计图
  6. 超级计算机适用于科学计算,中国科学院
  7. 51nod1551-集合交易【hall定理,最大权闭合图,网络流】
  8. linux下Hbase的常用shell命令
  9. Oracle:view 添加主键
  10. 优学院java架构52破解_2021年优学院Java程序设计(山西工程职业学院)课后习题答案...
  11. 34. login-shell 和 环境变量
  12. Android信鸽推送全解
  13. 冬瓜哥的PC机上唯独它9年没换!
  14. 3种方式构造HTTP请求详解(HTTP4)
  15. global全局对象
  16. 公司用的非标普通自动化用单片机还是plc_自动化专业现在吃香吗?
  17. LaTex使用技巧10:公式中的各种英文字体
  18. Photoshop CC 2019快速选择工具的抠图
  19. es6 Promise是什么?
  20. oracle基础教学:如何设置外键

热门文章

  1. 原创,禁用userinit.exe,无法进入系统解决办法
  2. 宣传片制作,你不知道的重点有哪些
  3. android studio 使用checkstyle全攻略
  4. C++中头文件和源文件详细介绍
  5. Nitro PDF用户记录数据库被盗
  6. 12306的技术升级
  7. EXCEL VBA 自定义函数 招标代理费计算
  8. oracle shutdown 卡死,Oracle shutdown immediate无法关闭数据库解决方法
  9. 单招计算机英语面试口语,单招面试英语自我介绍范文五篇
  10. 你知道edi许可证的具体区别吗?