根据指令使用数据的方式,指令系统可分为堆栈型、累加器型和寄存器型。寄存器型又可以进一步分为寄存器-寄存器型和寄存器-存储器型。
- 堆栈型。堆栈型指令又称零地址指令,其操作数都在栈顶,在运算指令中不需要指定操作数,默认对栈顶数据进行运算并将结果压回栈顶。
- 累加器型。累加器型指令又称单地址指令,包含一个隐含操作数——累加器,另一个操作数在指令中指定,结果写回累加器中。
- 寄存器-存储器型。在这种类型的指令系统中,每个操作数都由指令显式指定,操作数为寄存器和内存单元。
- 寄存器-寄存器型。在这种类型的指令系统中,每个操作数也由指令显式指定,但除了访存指令外的其他指令的操作数都只能是寄存器。
寄存器-寄存器型指令系统中,运算指令的操作数只能来自寄存器,不能来自存储器,所有的访存都必须显式的通过load和store指令来完成,所以寄存器-寄存器型又被称为load-store型。使用寄存器的优势在于,寄存器的访问速度快,便于编译器的调度优化,并可以充分利用局部性原理,大量的操作可以在寄存器中完成。此外,寄存器-寄存器型的另一个优势是寄存器之间的相关性容易判断,容易实现流水线、多发射和乱序执行等方法。当今的指令系统主要是寄存器-寄存器型。
说了这么多,就是想强调一下在Armv8-A中寄存器的重要性。
在AArch64应用级角度,一个PE(Process Element)具有下列寄存器:
31个通用寄存器, R0 - R30,其中64-bit的寄存器命名为X0 – X30,而32位的寄存器命名为W0 -W30。
零寄存器XZR(64-bit)和WZR(32-bit)。
一个64-bit的堆栈指针(Stack Pointer)寄存器,堆栈指针的最低有效32位可以使用寄存器WSP访问。
一个64-bit的程序计数器(Program Counter),用于保存当前指令地址。软件无法直接写入PC。
32个SIMD(Single Instruction Multiple Data)&FP(Float Point)寄存器,V0 – V31。其中,128-bit的寄存器命名为Q0 -Q31;64-bit的命名为D0 – D31;32-bit的命名为S0 – S31;16-bit的命名为H0 -H31;8-bit的命名为B0 – B31。
一个64-bit的SIMD&FP控制寄存器FPCR。
一个64-bit的SIMD&FP状态寄存器FPSR。
三十二个可扩展向量寄存器(Scalable Vector registers),Z0 – Z31,寄存器宽度取决于具体实现,在128-1024 bit之间。
十六个可扩展断言寄存器(Scalable Predicate registers),P0 - P15。
一个专用SVE第一故障寄存器FFR(First Fault Register)。
一个处理器状态寄存器PSTATE,它是处理器状态信息的集合,包括条件标记寄存器NZCV,异常屏蔽寄存器DAIF,SP选择寄存器SPSEL、异常等级寄存器CurrentEL等。下图是PSTATE的字段定义。
在AArch64下,PSTATE字段使用以下专用(Special-Purpose)寄存器访问,通过MRS指令直接读取,通过MSR指令直接写入。
下图是PSTATE用到的特殊寄存器。
NZCV寄存器比较简单,如下图。N是负数条件标志位,如果最后一个标志设置指令的结果为负,则N=1;Z是0条件标志位,如果最后一个标志设置指令的结果为零,则Z=1,否则Z=0;C是进位条件标志位,如果最后一个标志设置指令导致进位情况发生,则C=1;V是溢出条件标志位,如果最后一个标志设置指令导致溢出情况发生,则V=1。其它位是保留位。
DAIF是异常屏蔽寄存器,如下图。D是处理器状态调试屏蔽位;A是系统错误(SError)中断屏蔽位;I是IRQ屏蔽位;F是FIQ屏蔽位。其它位是保留位。
CurrentEL是当前异常等级寄存器,如下图,只有两个有效位。EL编码,0b00表示EL0;0b01表示EL1;0b10表示EL2;0b11表示EL3.
SPSel(Stack Pointer Select)是堆栈指针选择寄存器,如下图,只有一个有效位。0b0表示在所有异常级别使用SP_EL0;0b1表示在异常级别ELx使用SP_ELx。
PAN(Privileged Access Never)是特权访问禁止寄存器,如下图。0b0表示特权读写不被此机制禁用;0b1表示禁用对EL0级别可访问地址的特权读写访问。
UAO(User Access Override)是用户访问覆盖寄存器,如下图。
DIT(Data Independent Timing)是数据独立时序寄存器,如下图。0b0表示该架构没有说明任何指令的时序属性。
SSBS是Speculative Store Bypass Safe(翻译不出来了)。0b0表示不允许硬件进行推测性load/store。
TCO(Tag Check Override)是标记检查覆盖寄存器,如下图。改为表示是否允许全局禁用内存标记检查。0b0表示load/store不受影响;0b1表示load/store不被检查。
ALLINT(All Interrupt Mask Bit)是全部中断屏蔽寄存器,如下图。
AArch64的专用寄存器除了上述,还有很多其它的。
此外,AArch64中还有大量的系统寄存器(System Registers)。系统寄存器为执行控制、状态和一般系统配置提供支持。大多数系统寄存器在EL0异常等级时不可访问。然而,一些系统寄存器可以配置为允许执行在EL0等级的软件进行访问。可以从EL0访问的寄存器包括:
- Cache ID registers
- Debug registers
- Performance Monitors registers
- Activity Monitors registers
- Thread ID registers
- Timer registers
前面讲GIC的时候提到过,ARM把一些中断相关的寄存器从GIC中剥离出来,放到了CPU interface中。在GICv2时,这些寄存器可以设计成系统寄存器,也可以设计成寻址访问的寄存器,但是到了GICv3,要求这些寄存器必须是系统寄存器。
对于系统寄存器的访问,也是通过MSR和MRS指令。
本次介绍的寄存器只是AArch64中全部寄存器的冰山一角,实际的寄存器远远多于今天提到的这些。
原作者:老秦谈芯