目录
2.1 Instruction alignment 指令对齐
2.2 Unaligned data access 非对齐数据访问
2.3 SCTLR.A Alignment check enable
3.1 Instruction alignment 指令对齐
3.2 Alignment of data accesses 对齐数据访问
3.3 普通Load 和Store指令(包括单寄存器和多寄存器)
3.4 Load-Exclusive/ Store-Exclusive 和Atomic 指令
3.7 FEAT_LSE2, Large System Extensions v2
如果非对齐访问出错,可以考虑以下问题:
- 当前架构是否支持非对齐数据访问。
- 系统控制寄存器SCTLR.A是否打开对齐访问检查功能。
- 使用的指令是否支持非对齐访问。
- 操作的对象(SP,PC,Normal memory,Device memory)是否支持非对齐访问。
- 当前系统所使用的是大端还是小端。
1,对齐传输和非对齐传输
参考Cortex-M3与Cortex-M4权威指南 第6.6章:
由于存储器系统为32位的(至少从编程模型的角度来看是这样的),大小为32位(4 byte(字节),或 1 word(字))或16位(2字节,或半字)可以是对齐也可以是不对齐的。
对齐传输的意思是地址值为大小(以字节为单位)的整数倍。例如,字大小的对齐传输可以执行的地址为0x00000000、0x00000004、···、0x00001000、0x00001004等;类似地,半字大小的对齐传输可以执行的地址则为0x00000000、0x00000002、···、0x00001000、0x00001002等。
对齐和非对齐传输的实例下图所示。
一般来说,多数经典ARM处理器(如ARM7 /ARM9 /ARM10)都只允许对齐传输。这就意味着在访问存储器时,字传输地址的bit[1]和bit[0]为0,而半字传输地址的bit[0]为0。例如,字数据可位于0x1000或0x1004,而不能位于0x1001、0x1002或0x1003,对于半字数据,地址可以为 0x1000 或 0x1002,而不能为 0x1001。所有的字节传输都是对齐的。
Cortex-M3和Cortex-M4处理器都支持普通存储器访问(如LDR、LDRH,STR以及STRH 指令)的非对齐数据传输。
另外还有一些限制:
- 多加载/存储指令不支持非对齐传输。
- 栈操作指令(PUSH/POP)必须是对齐的。
- 独占式访问,Exclusive Access(如 LDREX 或 STREX)必须是对齐的,否则就会触发错误异常(使用错误)。
- 位段操作不支持非对齐传输,因为其结果是不可预测的。
当非对齐传输是由处理器发起时,它们实际上会被处理器的总线接口单元转换为多个对齐传输。这个转换是不可见的,因此应用程序开发人员无须考虑这个问题。
不过,当产生非对齐传输时,它会被拆分为几个对齐传输,因此本次数据访问会花费更多的时钟周期,可能对需要高性能的情形不利。若追求更高的性能,确保数据处于合适的对齐是有必要的。
多数情况下,C编译器不会产生非对齐传输,它只会在以下情况中出现:
- 直接操作指针。
- 包含非对齐数据的数据结构增加“_packed”属性。
- 内联/嵌入式汇编代码。
2,AArch32 Alignment support
2.1 Instruction alignment 指令对齐
A32 指令是 字对齐的(word-aligned)。
T32 指令是 半字对齐的(halfword-aligned)。
2.2 Unaligned data access 非对齐数据访问
在ARM A系列的实现中,通过一些Load/Store 指令是支持对Normal memory进行非对齐数据访问的。关于Normal memory和device memory的细节描述,可以参考博文:ARMv8内存属性与类型(Memory types and attributes)简介_arm 内存属性_SOC罗三炮的博客-CSDN博客
如下图红框中所示,有一部分的 Load/Store指令可以实现非对齐访问,比如最常用的LDR与STR指令。当然前提是,系统控制寄存器SCTLR里的对齐检查位没有被enable,即SCTLR.A = 0:
- 通过设置 SCTLR.A 位,可以控制除了Hyp mode外,其他任何模式下的对齐访问。
- 通过设置HSCTLR.A 位,可以控制Hyp mode下的对齐访问。
任何对Device memory的非对齐访问,都会产生对齐异常。
2.3 SCTLR.A Alignment check enable
SCTLR.A位控制住系统对Normal memory的非对齐访问。在PL0或者PL1下,检查对齐错误:
- SCTLR.A = 0, reset value,disable 对齐错误检查,在PL0或者PL1时,不会检查 Load/Store指令对一个或者多个寄存器进行操作时,访问的数据元素的大小与地址是否对齐。
- SCTLR.A = 1,enable 对齐错误检查,在PL0或者PL1时,不会检查 Load/Store指令对一个或者多个寄存器进行操作时,访问的数据元素的大小与地址是否对齐。如果发现非对齐访问,会产生Data Abort 异常。
此外,Load/store exclusive 和load-acquire/store-release指令自带对齐检查,所以会忽略SCTLR.A的值。
3,AArch64 Alignment support (B2.5 )
3.1 Instruction alignment 指令对齐
A64 指令是 字对齐的(word-aligned)。
3.2 Alignment of data accesses 对齐数据访问
同A32一样,任何对Device memory属性的非对齐访问,都会造成对齐错误,产生Data Abort异常。
对于Normal memory的非对齐访问,其行为取决于:
- 内存访问的指令(比如 load、store)
- 被访问的内存的内存属性(比如Normal 或者Device)
- SCTLR_ELx.{A, nAA}的值,是否打开对齐访问检查。
- FEAT_LSE2 属性是否实现。
3.3 普通Load 和Store指令(包括单寄存器和多寄存器)
对于 普通的Load 和Store指令(不是Exclusive access、Atomic、SETG* Memory Copy and Memory Set等指令),无论是单寄存器操作还是多寄存器操作,如果被访问的地址与被访问的数据元素的大小不一致(非对齐访问),则:
- 如果SCTLR_ELx.A = 1,将会产生一个对齐错误。
- 如果SCTLR_ELx.A = 0,将执行非对齐访问(Normal memory)。
对于 普通的Load 和Store指令,非对齐访问的定义是基于被访问元素的大小,而不是整个内存访问的大小。
3.4 Load-Exclusive/ Store-Exclusive 和Atomic 指令
对于Load-Exclusive/ Store-Exclusive 和Atomic 指令,如果SCTLR_ELx.A = 1,将会产生一个对齐错误。
如果SCTLR_ELx.A = 0,这取决于FEAT_LSE2,具体分析可以查看文档:DDI0487G_a_armv8_arm.pdf。
如果FEAT_LSE2特性没有被实现,如果访问没有与数据结构大小对齐的地址,这些指令将会产生对齐错误。
3.5 Non-atomic Load-Acquire/Store-Release指令
对于非exclusive 或者atomic的Load-Acquire/Store-Release指令,
如果SCTLR_ELx.A = 1,将会产生一个对齐错误。
如果SCTLR_ELx.A = 0,如果FEAT_LSE2特性没有被实现,如果访问没有与数据结构大小对齐的地址,这些指令将会产生对齐错误。
3.7 FEAT_LSE2, Large System Extensions v2
FEAT_LSE2为 load和store操作引入 单次拷贝原子性需求(single-copy atomicity requirements)以及对齐访问需求(alignment requirements)。
- This feature is supported in AArch64 state only.
- This feature is OPTIONAL in Armv8.2 implementations.
- This feature is mandatory in Armv8.4 implementations
可通过ID_AA64MMFR2_EL1的AT位来查看是否实现了该属性。
与对齐的访问相比,未对齐的访问通常需要额外的周期(cycles)才能完成。
3.8 对齐访问SP寄存器
64 bit宽的Stack Pointer 寄存器,堆栈指针需要16个byte对齐。
当堆栈指针被用作计算的基址时,不管指令应用了任何偏移量,其中堆栈指针的[3:0]位不是0b0000,这就是非对齐的堆栈指针。处理器可以配置为:如果load/store指令使用了未对齐的堆栈指针,处理器将生成栈指针未对齐异常。
伪代码如下:
通过判断 SCTLR的 SA0或者SA位是否为0,从而决定是否产生栈指针非对齐异常。
3.9 对齐访问 PC寄存器
64 bit宽的Program Counter 寄存器里保存着当前执行的指令的地址。如果执行A64 指令的时候不是 字对齐(word-aligned),将会产生PC 对齐错误。
PC对齐检查将生成一个与指令获取相关的PC对齐错误异常,在AArch64状态时,试图从架构上执行一条指令,该指令是用未对齐的PC获取的。非对齐的PC是指PC的[1:0]位不是0b00,也就是地址需要以0、4 、 8 、c结尾,比如PC可以为0x1000或0x1004,而不能为0x1001、0x1002或0x1003
一个PC 非对齐异常将会 把Exception Syndrome Register (ESR)寄存器的EC 位写入 0x22,并且会产生一系列的错误。
检查PC非对齐异常的伪代码如下:
参考文章: