ARM体系架构 1.ARM体系结构介绍 ARM公司主要向客户提供处理器IP。ARM体系结构是一种硬件规范,主要用来约定指令集、芯片内部体系结构等。以指令集为例,ARM体系结构并没规定每一条指令在硬件IP中如何实现,只是约定了每条指令的格式、行为规范、参数等。为了降低客户基于ARM体系结构开发处理器(processor 或 core)的难度,ARM公司通常在发布新版本的体系结构之后,根据不同的应用需求开发出兼容该体系结构的处理器(processor 或 core)IP,然后授权给客户。客户获得ARM设计的处理器IP后,基于其定制和设计自己的SOC。以ARMv8体系结构为例,ARM公司先后开发出Cortex-A53、Cortex-A55、Cortex-A72、Cortex-A73等多款处理器IP。ARM架构为 processor 或 core的设计提供了基础,通常我们可以将processor 或 core称为Processing Element(PE)。 2. ARM的处理架构和微架构 2.1 什么是处理器架构? 主要指的是处理器的功能规范和架构指定处理器的行为方式,例如它有什么指令以及指令做什么,而不包括如何做,架构视为硬件和软件之间的规则。该架构描述了软件可以依赖硬件提供哪些功能。一些功能是可选的,我们将在稍后的微架构部分讨论。架构可能会规定:
2.2 什么是处理器的微架构? 架构(Architecture)不会告诉您处理器是如何构建和工作的。处理器的构建和设计被称为微架构,微架构( micro-architecture)规定了处理器应该如何工作,我们上述提到的”ARM公司根据某个版本的体系结构来设计处理器IP“ 就是微架构,如Cortex-A53 和Cortex-A72 都是基于Armv8-A 架构实现的微架构。微架构通常包括: 几级Cache和Cache Size大小,几级流水线每条指令执行的周期等。 例如Cortex-A53和Cortex-A72都是Armv8-A架构的实现。这意味着它们具有相同的架构,但它们具有非常不同的微架构,如下图所示:
Intel Nehalem mico-architecture Cortex-A系列(Application) 面向应用场景的架构(Application Profile)。该系列支持基于内存管理单(MMU)的虚拟内存系统体系结构(VMSA)。它支持A64、A32和T32指令集。面向性能密集型系统的应用处理器内核。主要针对日益增长的消费娱乐和无线产品设计,用于具有高计算要求、运行丰富操作系统及提供交互媒体和图形体验的应用领域,如智能手机、平板电脑、汽车娱乐系统、数字电视,智能本、电子阅读器、家用网络、家用网关和其他各种产品。 Cortex-R系列(Real-time) 面向实时应用的高性能内核。主要针对需要运行实时操作的系统应用,面向如汽车制动系统、动力传动解决方案、大容量存储控制器等深层嵌入式实时应用。R系列,面向实时场景的架构配置。该系列支持基于内存保护单(MPU)的受保护内存系统体系结构(PMSA)。它支持A32和T32指令集。 Cortex-M系列(Microcontroller) 面向各类嵌入式应用的微控制器内核。该系列面向微控制器领域,主要针对成本和功耗敏感的应用,如智能测量、人机接口设备、汽车和工业控制系统、家用电器、消费性产品和医疗器械等。M系列,面向微处理器的架构。该系列实现了一个为低延迟中断处理而设计的程序员模型(programmers’ model),该模型具有寄存器硬件堆栈和对中断处理程序的高级语言支持。它支持T32指令集的变种。 Cortex-SC系列(SecurCore) 除了上述三大系列之外,还有一个主打安全的Cortex-SC系列(SC:SecureCore),主要用于政府安全芯片。 ARM学习文档:参考ARM官方文档Documentation – Arm DeveloperARMv8-A Architecture Reference ManualGICv3/V4 SpecificationAMBA4 and AMBA5 specificationsTechnical Reference Manual (TRM)Configurations and integration Guidesarm_cortex_a78_trm__0101_05_en.pdfDDI0487J_a_a-profile_architecture_reference_manual.pdfIHI0069H_gic_architecture_specification.pdfIHI0050F_amba_chi_architecture_spec.pdfGICv3_v4_overview.pdf ARMv8体系架构做了许多改变,除了处理器的性能有了较大提升之外,还引入了很多新特性。超大物理地址空间。使处理器能够访问超过4GB的物理内存。64位的虚拟地址空间。这将使虚拟内存超过4GB限制,在桌面应用和服务器中是重要的提升。通用寄存器增多。提供了31个64位的通用寄存器,可以减少栈的使用(函数传参可使用8个寄存器),从而提升性能。 新增16KB和64KB的页面。有助于降低转换表(TLB)的未命中率和深度。 基于PC指针的相对寻址范围加大。支持+/-4GB的寻址范围,提高内存空间访问效率。 信号事件自动化。有助于实现低功耗、高性能的自旋锁。 全新异常模式。降低了操作系统和虚拟机监控程序软件的复杂性。 高效的缓存管理。用户空间缓存操作提高了动态代码生成效率。提供快速清除data cache的指令。 高速硬件加密。比软件加密性能高3~10倍。对于小粒度的加解密很高效,例如http加载和发布:为C++11、C11、Java内存模型设计。使用消除显式内存屏障指令保证线程安全。 NEON双精度浮点高级SIMD。这使得SIMD矢量化能够应用于更广泛的算法集,例如,科学计算、高性能计算(HPC)和超级计算机。 3. ARMv8体系结构中的基本概念 ARM处理器实现的是精简指令集的体系结构,在ARMv8体系结构中,新出现了如下基本概念和定义。 3.1 处理机(Processing Element, PE) 在ARM公司的技术手册中定义,把处理器处理事务的过程抽象为处理机,可以理解为ARM Core。 3.2 执行状态(Execution State) 处理器运行的环境,包括寄存器位宽、支持的指令集、异常模型、内存管理以及编程模型等。 ARMv8定义了两个执行状态。ARMv8-A有两种执行模式,一种是AArch64执行模式,另一种是AArch32执行模式。执行状态定义处理单(Processing Element, PE)的执行环境,包括以下内容:支持的寄存器宽度支持的指令集异常模型虚拟存储系统(Virtual Memory System Architecture, VMSA)架构程序员模型 AArch64为64位执行状态。对应上述内容,此执行状态:提供31个64位通用寄存器,其中X30用作过程链接寄存器(Procedure Link Register)。提供64位程序计数器(PC)、堆栈指针(SP)和异常链接寄存器(ELRs)。提供32个128位寄存器以支持SIMD矢量和标量浮点运算。提供单一指令集A64。定义ARMv8异常模型,该模型最多有四个异常级别EL0-EL3,它们提供执行权限层次结构。支持64位虚拟寻址。定义一系列与PSTATE相关的寄存器。A64指令集包括能直接操作各种PSTATE寄存器的指令。使用后缀命名每个系统寄存器,该后缀指示可以访问寄存器的最低异常级别。 AArch32为32位执行状态。对应上述内容,此执行状态:提供13个32位通用寄存器和一个32位PC、一个32位SP寄存器和一个32位链接寄存器(Link Register,LR)。链接寄存器用作异常链接寄存器和过程链接寄存器。其中一些寄存器有多个备份寄存器,用于不同的处理器工作模式。同样功能的寄存器在不同的处理器运行模式下可能对应不同的物理寄存器,这些寄存器被称为备份寄存器。为了从Hyp(hypervisor)模式异常返回,提供一个异常链接寄存器。提供32个64位寄存器,用于对高级SIMD矢量和标量浮点计算的支持。提供两个指令集,A32和T32。支持基于处理器工作模式的ARMv7-A异常模型,并将其映射到基于异常级别的ARMv8异常模型。使用32位虚拟地址。使用单个当前程序状态寄存器(CPSR)保存处理器状态。在AArch64和AArch32执行状态之间进行转换称为内部处理(inter processing)。 3.3 ARMv8指令集 A64指令集:运行在AArch64状态下,提供64位指令集支持。A32指令集:运行在AArch32状态下,提供32位指令集支持。T32指令集:运行在AArch32状态下,提供16位和32位指令集支持。需要注意的是:A64指令集和A32指令集是不兼容的,是两套完全不同的指令集。A64指令集和A32指令集的宽度一样,都是32位,而不是64位ARM core 提供的两种指令集:ARM / Thumb 指令宽度和CPU位数的区别指令宽度 一条指令所占的内存字节数。在指令集中单条指令的宽度,指令本身编译成二进制机器码所占内存空间的大小。CPU位数 一条指令所能实现一次处理数据的位数。单条指令一次处理数据的位数,CPU的位是指一条指令一次性可处理的数据量是多少(bit位),一般和CPU中寄存器的位数有关。 ARM / Thumb指令集:ARM-V8:向下兼容ARM-v7架构ARM指令集:支持64位 / 32位。一条指令占用32位内存空间Thumb指令集:支持32位 / 16位。一条指令占用16位内存空间注:不管ARM是支持64位还是32位,ARM指令集中每条指令都占32位空间。不管Thumb是支持32位还是16位,Thumb指令集中每条指令都占16位空间。ARM和Thumb指令集的区别:ARM指令集功能更全,性能更高。thumb指令集比ARM指令集指令密度要大 3.4 ARM处理器的异常级别 在ARMv8中,程序总是运行在四种异常状态中的一种。在AArch64中,异常级别决定特权级别,与ARMv7中定义的特权级别类似。异常级别决定特权级别,例如ELn对应PLn。n越大则特权等级越高。在所有ARMv8架构中,特权等级的不同有着不同的操作权限,它类似于计算机中常见保护域的概念。不用的特权级别如下所示:EL0 应用程序EL1 操作系统内核EL2 虚拟化EL3 低级固件,包含安全监控等 4. ARM架构的寄存器概述 4.1 ARM32寄存器 ARM32 处理器共有7种不同的处理器模式,在每一种处理器模式中有一组相应的寄存器组。任意时刻(也就是任意的处理器模式下),可见的寄存器包括 15 个通用寄存器( R0~R14)、一个或两个状态寄存器及程序计数器( PC )。在所有的寄存器中,有些是各模式共用的同一个物理寄存器:有一些寄存器是各模式自己拥有的独立的物理寄存器。未备份寄存器(Unbanked Registers) 未备份寄存器包括 R0~R7。对于每一个未备份寄存器来说,在所有的处理器模式下指的都是同一个物理寄存器。在异常中断造成处理器模式切换时,由于不同的处理器模式使用相同的物理寄存器,可能造成寄存器中数据被破坏。 未备份寄存器没有被系统用于特别的用途,任何可采用通用寄存器的应用场合,都可以使用未备份寄存器。备份寄存器( Banked Registers ) 对于备份寄存器 R8~R12 来说,每个寄存器对应两个不同的物理寄存器。例如,当使用快速中断模式 下的寄存器时,寄存器R8和寄存器R9分别记作R8_fiq、R9_fiq;当使用用户模式下的寄存器时,寄存器R8和寄存器R9分别记作 R8_usr、R9_usr 等。在这两种情况下,使用的是不同的物理寄存器。系统没有将这几个寄存器用于任何特殊用途,但是当中断处理非常简单,仅仅使用R8 ~ R14寄存器时,FIQ 处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理过程非常迅速。 寄存器R13在ARM中常用作栈指针。在ARM指令集中,这只是一种习惯的用法,并没有任何指令强制性地使用R13作为栈指针,用户也可以使用其他的寄存器作为栈指针;而在 Thumb 指令集中,有一些指令强制性地使用R13作为栈指针。 每一种异常模式拥有自己的物理的R13(sp 栈指针)。应用程序初始化该R13(sp 栈指针),使其指向该异常模式专用的栈地址。当进入异常模式时,可以将需要使用的寄存器保存在 R13 所指的栈中。当退出异常处理程序时,将保存在 R13 所指的栈中的寄存器值弹出。这样就使异常处理程序不会破坏被它所中断的程序的运行现场。 寄存器 R14 又被称为连接寄存器(Link Register,LR),在 ARM 体系中具有下面两种特殊的作用: 每一种处理器模式自己的物理 R14 中存放着当前子程序的返回地址。当通过 BL 或 BLX 指令调用子程序时,R14 被设置成该子程序的返回地址。在子程序中,当把 R14 的值复制到程序计数器PC中时,子程序即返回。可以通过下面两种方式实现这种子程序的返回操作。执行下面任何一条指令:MOV PC, LRBX LR 当异常中断发生时,该异常模式特定的物理 R14 被设置成该异常模式将要返回的地址,对于有些异常模式,R14 的值可能与将返回的地址有一个常数的偏移量。R14 寄存器也可以作为通用寄存器使用。PC(R15)程序控制寄存器 程序计数器 PC,即 R15。PC(Program control register)为程序指针,PC 指向哪里,CPU 就会执行哪条指令(所以程序跳转时就是把目标地址代码放到 PC 中);整个 CPU 中只有一个 PC(CPSR 也只有一个,但 SPSR 有 5 个);程序计数器 R15 又被记作 PC 。它虽然可以作为一般的通用寄存器使用,但是有一些指令在使用 R15 时有一些特殊限制。当违反了这些限制时,该指令执行的结果将是不可预料的。由于ARM 采用了流水线机制,当正确读取了 PC 的值时,该值为当前指令地址值加 8 个字节。也就是说,对于ARM 指令集来说,PC 指向当前指令的下两条指令的地址。由于 ARM 指令是字对齐的,PC值的第 0 位和第 1 位总为 0.CPSR程序状态寄存器 CPSR(当前程序状态寄存器) 可以在任何处理器模式下被访问。在用户级编程时用于存储条件码。CPSR包含条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。每一种处理器模式下都有一个专用的物理状态寄存器,称为SPSR(备份程序状态寄存器)。当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。在异常中断程序退出时,可以用SPSR中保存的值来恢复CPSR。 由于用户模式和系统模式不是异常中断模式,所以它们没有SPSR。 当在用户模式或系统模式中访问SPSR时,将会产生不可预知的结果。
从上表得知,通用寄存器一共有34个物理寄存器R0~R7共8个寄存器用于任意ModeR8~R12有两组共10个寄存器:一组用于FIQ,一组用于其他ModeR13共有8个物理寄存器,usr和sys共用一个,其他7个mode分别用一个R14共有7个物理寄存器,usr和sys共用一个,hyp使用的寄存器是特殊寄存器ELR_hyp(不属于通用寄存器),其他6个mode分别用一个R15只有一个物理寄存器USR和SYS Mode共享相同的通用寄存器ARM32共有1个CPSR(Current Program Status Register)所有的CPU mode下都共享一个CPSR7个备用的SPSR(Saved Program Status Register)usr和sys没有备份的SPSR之外,其他CPU mode都有一个自己的SPSR 4.2 ARM64寄存器 4.2.1通用寄存器 ARM64通用寄存器不再像ARM32那样根据CPU mode设置相应的物理备份,而是所有EL下共享一堆通用寄存器,如下图:X0~X7X8~X15X16~X23X24~X30XR(X8)IP0(X16)Callee-saved(X24~28)Parameter/result registers(X0~X7)(otherwise corruptible)Corruptible Resister(X9~15)IP1(X17)PR(X18)Callee-saved(X19~23)FP(X29) callee-savedLR(X30) x0-x30 64bit 通用寄存器 如果有需要可以当做32bit使用:W0-W30。其中x0 – x7:这 8 个寄存器主要用来存储传递参数 。如果参数超过 8 个,则会通过栈来传递 ;x0 也用来存放上文方法的返回值。 FP(x29) 64bit寄存器 保存栈帧地址,栈底指针,指向当前方法栈的底部。 LR(x30) 寄存器(64bit) 通常称x30为程序链接寄存器,因为这个寄存器会记录着当前方法的调用方地址 ,即当前方法调用完成时应该返回的位置。例如我们遇到 Crash 要方法堆栈,其本质就是不断的向上递归每一个x30寄存器的记录状态(也就是栈上 X30 寄存器的内容)来找到上层调用方。 SP 寄存器(64bit) 保存栈指针,使用 SP/WSP来进行对SP寄存器的访问。指向当前方法栈的顶部。 PC 64bit 程序计数器,俗称PC指针,总是指向即将要执行的下一条指令,在arm64中,软件是不能改写PC寄存器的。 CPSR 64bit 状态寄存器 综述如下, ARM64共有31个64位通用寄存器,PC寄存器属于特殊寄存器,需要使用特殊指令进行访问X0~X7:参数寄存器,用作临时寄存器或可以保存的调用者保存的寄存器变量函数内的中间值X8:保存子程序的返回地址,尽量不要使用X9~X15:调用者保存的临时寄存器 如果调用者使用下面这些寄存器,需要提前把这些寄存器的值保存在自己的堆栈中,使用结束后恢复X16~X17:子程序内部调用临时寄存器X18:平台寄存器,尽量不要使用X19~X28:被调用者保存的临时寄存器 被调用者使用下面这些寄存器,也需要提前把寄存器的值保存在自己的堆栈中,使用后恢复X29:帧指针寄存器(FP)X30:连接寄存器(LR) 4.2.2栈指针SP寄存器 每个实现的EL都会有专用的栈指针寄存器SP_EL0、SP_EL1:如果EL2实现了,SP_EL2,如果EL3实现了,SP_EL3 ARM64通用寄存器可以分别当作64位和32位的寄存器使用31 个64-bit 寄存器,X0-X30.31 个32-bit 寄存器,W0-W30. 4.2.3 PC 64bit 程序计数器 俗称PC指针,总是指向即将要执行的下一条指令,在arm64中,软件是不能改写PC寄存器的。 CPU取指后,自动更新PC指针的值。 4.2.4 ARM64状态寄存器 ARM64使用PSTATE(Process State)来替换ARM32中的CPSR,PSTATE(process state)是一些状态位.一些位仅在aarch32 state下使用、一些位仅在aarch64 state下使用、一些位可以同时在aarch32/aarch64 state下使用;在aarch64中,可以通过MSR/MRS指令访问特殊寄存器(special-purpose)的方式读写这些位. 除了这些特殊寄存器中表示的位,PSTATE的其它位都是不能访问的.1. 这些特殊的寄存器位包含 : NZCV、DAIF、CurrentEL、SPSel、PAN、UAO、DIT、SSBS可以使用MRS/MSR指令,直接读写这些寄存器2. 可以使用MSR/MRS操作这两个寄存器DAIFSet、DAIFClr,直接对某一位置1或清0 ARM64一共有3个SPSR(Saved Program Status Registers),分别为SPSR_EL1,SPSR_EL2,SPSR_EL3 触发异常时,保存当前的PSTATE(CPSR)的状态。 当这个 异常处理程序在aarch64时,异常既可以来自aarch64,也可以来自aarch32
4.3 ARM32 和ARM64的指令对比 ARMv8架构继承ARMv7与之前处理器技术的基础,除对现有的16/32bit的Thumb2指令支持,也向前兼容了现有的A32(ARM 32bit)指令集,基于64bit的AArch64架构,除了新增A64(ARM 64bit)指令集外,也扩充了现有的A32(ARM 32bit)和T32(Thumb2 32bit)指令集,另外还新增加了CRYPTO(加密)模块支持。AArch32AArch64提供13个32bit通用寄存器R0~R12,一个32bit PC指针(R15),堆栈指针SP(R13),链接寄存器LR(R14)提供31个64bit 通用寄存器X0~X30(W0~W30低32位),其中X30是程序链接寄存器LR提供一个32bit异常链接寄存器ELR,用于Hyp mode下的异常返回。提供一个64bit PC指针,堆栈指针SPx,异常链接寄存ELRx提供32个64bit SMID向量和标量floating-point支持提供32个128bit SIMD向量和标量floating-point支持提供两个指令集A32(32bit),T32(16/32bit)定义Armv8异常登记ELx(x<4),x越大登记越高,权限越大兼容ARMv7的异常模型定义一组PSTATE,用以保存PE(Processing Element)状态协处理器只支持CP10、CP11、CP14、CP15没有协处理器概念 在ARM64架构下,CPU提供了33个寄存器, 其中前31个(0~30)是通用寄存器 (general-purpose integer registers),最后2个(31,32)是专用寄存器(sp寄存器和 pc 寄存器)。寄存器说明X0寄存器用来保存返回值或传参X1~X7寄存器用来保存函数的传参X8寄存器也可以用来保存返回值X9~X28寄存器一般寄存器无特殊用途X29(FP)寄存器用来保存栈底地址X30 (LR)寄存器用来保存返回地址X31 (SP)寄存器用来保存栈顶地址X32(PC)寄存器用来保存当前执行的指令地址 4.4 ARM64的常用指令操作 5. ARMv7和ARMv8的异常等级 5.1 异常等级描述 在ARMv7体系结构中,处理器的模式可以在特权软件控制下更改(CPSR寄存器),也可以在发生异常时自动更改。当发生异常时,内核保存当前执行状态和返回地址,进入所需模式,并可能禁用硬件中断。应用程序以最低特权级别PL0(以前的非特权模式)运行。操作系统在PL1上运行,系统中的虚拟化扩展在PL2上运行管理程序。安全监视器作为在安全和非安全(正常)世界之间移动的网关,也可以在PL1上运行。PL(Privilege Level)优先级:PL0代表用户态和PL1代表系统态; 此外,ARM将PL又划分为7种详细的Mode,其中1种(usr)属于PL0,另外6种属于PL1。分别为可以在一个物理硬件平台虚拟出多个虚拟化硬件平台供不同的用户使用。ARM为了支持虚拟化扩展,新增了一个PL等级PL2,并新增了Hypervisor Mode,Hyp仅存在于Non-Secure World。
ARMv7的异常模式 与在ARMv7(AArch32)中一样,当发生异常时,处理器将更改为支持异常处理的异常级别(模式)
ARMv8的异常模式 异常级别之间的切换遵循以下规则: 1.切换到更高的异常级别,例如从EL0到EL1,表示软件执行权限增加 2.异常不能被切换到较低的异常级别 3.EL0级别没有异常处理,除非在高级的异常等级中需要处理 4.异常打破正常的程序流程,高于EL0的异常程序的执行入口是定义的异常向量表。异常包含如下情况: IRQ或FIQ中断 内存异常 未定义的指令 系统调用。允许用户对操作系统进行系统调用。安全监视器或陷入虚拟机监控程序 5.通过执行ERET指令来结束异常处理并返回到上一个异常级别 6.从异常返回可以保持在相同的异常级别,也可以输入较低的异常级别。无法切换到更高的异常级别 7.安全状态会随着异常级别的变化而变化,从EL3重新调用到非安全状态时除外。 5.2 异常等级切换
ERET指令用于异常返回,返回地址和处理器状态是从当前EL(exception level)下的ELR和SPSR寄存器中恢复的。即ELR寄存器中的值就是BL1最后跳转的目的地址,SPSR寄存器的值就是跳转之后处理器的状态。所以在代码中重点这两个值的初始化处理异常的流程将PSTATE寄存器内容保存到对应等级的SPSR_ELx中(保存PSTATE现场)保存返回地址到对应等级的ELR_ELx寄存器中(保存返回地址)将PSTATE中的DAIF设1,即关闭调试异常、SError、IRQ和FIQ设置对应异常等级下的栈指针,自动切换SP到SP_ELx切换到对应目标异常等级,跳转到异常向量表执行 以上都是处理器自动完成的,OS所需要做的事就是从中断向量表开始,根据发生的异常类型,跳转到合适的异常向量。当异常处理完后,执行eret指令从异常返回。eret 指令会从ELR_ELx中恢复PC指针并且从SPSR_ELx中恢复到PSTATE中。 对EL2/EL3的系统调用: SVC指令可以用来从EL0的用户应用程序调用到EL1的内核。HVC和SMC系统调用指令以类似的方式将处理器移动到EL2和EL3。当处理器在EL0(应用程序)执行时,它不能直接调用管理程序(EL2)或安全监视器(EL3)。这只有在EL1和以上的地方才有可能。因此,应用程序必须使用SVC来调用内核,并允许内核代表它们调用更高的异常级别。 在操作系统内核(EL1),软件可以用HVC指令调用管理程序(EL2),或用SMC指令调用安全监视器(EL3)。如果处理器是用EL3实现的,就可以提供让EL2从EL1捕获SMC指令的能力。如果没有EL3,SMC是未分配的,并在当前的异常级别触发。
ARMv8异常调用 6.Arm的指令执行 6.1 指令集的流水线(pipeline)概述 经典处理器架构的流水线是5级流水线:取指,译码,发射,执行,写回
Cortex-A77的流水线微架构 流水线: 流水线技术是一种将每条指令分解为多步,并让各步操作重叠,从而实现几条指令并行处理的技术。程序中的指令仍是一条条顺序执行,但可以预先取若干条指令,并在当前指令尚未执行完时,提前启动后续指令的另一些操作步骤。这样显然可以加速一段程序的运行过程。 超流水线: 超级流水线以增加流水线级数的方法来缩短机器周期,相同的时间内超级流水线执行了更多的机器指令。采用简单指令以加快执行速度是所有流水线的共同特点,但超级流水线配置了多个功能部件和指令译码电路,采用多条流水线并行处理,还有多个寄存器端口和总线,可以同时执行多个操作,因此比普通流水线执行的更快,在一个机器周期内可以流出多条指令。 一般而言,CPU执行一条指令需要经过以下阶段:取指->译码->地址生成->取操作数->执行->写回,每个阶段都要消耗一个时钟周期,同时每个阶段的计算结果在周期结束以前都要发送到阶段之间的锁存器上,可以供下一个阶段使用。 超标量: 超标量(superscalar)是指在CPU中有一条以上的流水线,并且每时钟周期内可以完成一条以上的指令,这种设计就叫超标量技术。 其实质是以空间换取时间。而超流水线是通过细化流水、提高主频,使得在一个机器周期内完成一个甚至多个操作,其实质是以时间换取空间。 6.2 指令相关性 先写后读(Read After Write, RAW)指令A: R1 = R2 + R3指令B:R5 = R1 + R4先读后写(Write After Read, WAR)指令A: R1 = R2 + R3指令B:R2 = R5 + R4先写后写(Write After Write, WAW)指令A: R1 = R2 + R3指令B:R1 = R5 + R4 6.3 超标量 超标量技术能够在一个时钟周期内执行多个指令,实现指令级的并行,有效提高了指令级别的并行效率。指令首先进入流水线(pipeline)的前端(Front-End),包括预取(fetch)和译码(decode),经过分发(dispatch)和调度(scheduler)后进入执行单,最后提交执行结果。所有执行采用顺序方式(In-Order)通过前端,并采用乱序方式(out of order)进行发射,然后乱序执行,最后用顺序方式提交结果。 超标量(Superscalar)是指在CPU中有一条以上的流水线,并且每时钟周期内可以完成一条以上的指令,这种设计就叫超标量技术。其实质是以空间换取时间。而超流水线是通过细化流水、提高主频,使得在一个机器周期内完成一个甚至多个操作,其实质是以时间换取空间。 超标量CPU的工作流程如下:Fetch(取指令):这部分负责从I-Cache中取指令,I-Cache负责存储最近常用的指令;分支预测器(Branch Prediction)用来决定下一条指令的PC值。Decode(解码):识别指令的类型Register Renaming(寄存器重命名):解决WAW和WAR这两种“伪相关性”,需要使用寄存器重命名的方法,将指令集中定义的逻辑寄存器重命名为处理器内部使用的物理寄存器。物理寄存器的个数更多于逻辑寄存器,处理器可以调度更多可以并行执行的指令。将存在RAW的寄存器进行标记,后续通过旁路网络(bypassing network)解决存在的“真相关性”。Dispatch(分发):被重命名之后的指令会按照程序中的规定顺序,写到发射队列(Issue Queue)、重排序缓存(ROB)和Store Buffer等部件中。Issue(发射):经过流水线的分发(Dispatch)阶段之后,指令被写到了发射队列(Issue Queue)中,仲裁(select)电路回从这个部件中挑选出合适的指令送到FU中执行。RegisterFile Read(读取寄存器):被仲裁电路选中的指令需要从物理寄存器堆(Physical Register File,PRF)中读取操作数Execute(执行):各种FU单执行Writeback(写回):将FU计算的结果写到物理寄存器(PRF)中,通过旁路网络将计算结果送到需要的地方。Commit(提交):这个阶段起主要作用的部件是重排序缓存(ROB),它将乱序执行的指令拉回到程序中规定的顺序。 6.4 乱序执行 乱序执行(Out-of-Order Execution): 超标量CPU最典型特性就是乱序执行,Out-of-Order Execution,简称OoOE或OOE。超标量CPU会处理多种算法,因为不同指令的运算周期数不同,例如乘法运算所需的时间周期就比加法运算长很多,所以如果一个需要很长时间的指令后面紧跟着需要使用其结果的指令的话,就会浪费很多时间,所以打乱指令的执行顺序就很重要。针对乱序执行有不少的算法,但是归根到底都是以保留栈为基础进行设计的。保留栈的核心思想,是把译码完成后的指令根据各自的指令种类,将译码后的指令送往各自的保留栈中保存下来,如果该指令所有操作数都已准备齐全,则可以开始进行乱序发射。注意,执行可以乱序,但提交不可以,否则就出现错误了。 在处理器中,先后执行的指令之间经常具有相关性(例如后一条指令用到前一条指令向寄存器写入的结果),因此早期简单的处理器使后续指令停顿,直到其所需的资源已经由前序指令准备就绪。Tomasulo算法则通过动态调度的方式,在不影响结果正确性的前提下,重新排列指令实际执行的顺序(乱序执行),这种算法是1966年Robert Tomasulo 发明,沿用至今。该算法使用了寄存器重命名机制。指令之间具有数据相关性(例如后条指令的源寄存器恰好是前条指令要写入的目标寄存器),进行动态调度时必须避免三类冒险(即流水线停顿):写后读(Read-after-Write, RAW)、写后写(Write-after-Write, WAW)、读后写(Write-after-Read, WAR)。第一种冒险也被称为真数据相关(True Data Dependence),而后两种冒险称为伪相关,伪相关并不一定导致流水线停顿,它们可以由寄存器重命名来予以解决,乱序执行的关键就是识别伪相关。 寄存器重命名有两种,一种就是将一体系架构寄存器ARF(Architected Register File)动态映射到一个专门的物理寄存器堆PRF(Physical Register File)上,消除WAW和WAR冒险。由一个Mapping Table负责管理和查询,这个重命名的过程对用户透明,用户只能看到ARF。读出指令和动作后先把这些都保存在保留站(Reservation Stations)中,然后CDB(公共数据总线)上进行广播,看这个计算结果有没有作为是其他指令源操作数的。如果保留站发现有,就会更新保留站源操作数的值。这样就代替了流水线寄存器。这种办法有可能出现不按顺序提交,因此无法实用。八十年代后对算法做了改进,增加了ROB(Reorder Buffer),在Tomasulo算法把指令分为Issue,Execute, 和Write Result三步的基础上,增加一步,称为Commit(交付,后提交)。Commit的功能是指令将其结果交付给(写入)目的寄存器或存储单。必须增加一硬件缓冲存储器(buffer),供Write Result这一步存放已获得的结果,并可以提供给其它指令应用这些结果。当指令进入Commit这一步时,将结果从buffer中拷贝到目的寄存器或存储单。这一硬件缓冲存储器称为重排序缓冲(ROB,Reorder Buffer)。ROB保证指令顺序发射(issue/dispatch),乱序执行(execute),顺序提交(commit)。通过Reorder buffer(ROB),可以实现Precise Exception和HW Speculation,同时由于ROB保证指令顺序提交,顺便也消除了WAR和WAW 冒险。Precise Exception(精确异常) 的意思是当指令出现异常时(除0、page fault等),前面的指令已经完成,后面的指令不能对寄存器、内存等进行修改,即与顺序执行的效果一样。 超标量处理器中,WAW、WAR和RAW这三种相关性都会阻碍指令的乱序执行:
为了解决乱序执行时解决WAW和WAR这两种相关性,需要对寄存器进行重命名(register renaming) 超标量处理器中的各个阶段如下:Fetch(取指令):这部分负责从I-Cache中取指令,I-Cache负责存储最近常用的指令;分支预测器用来决定下一条指令的PC值。Decode(解码):识别指令的类型Register Renaming(寄存器重命名):解决WAW和WAR这两种“伪相关性”,需要使用寄存器重命名的方法,将指令集中定义的逻辑寄存器重命名为处理器内部使用的物理寄存器。物理寄存器的个数更多余逻辑寄存器,处理器可以调度更多可以并行执行的指令。将存在RAW的寄存器进行标记,后续通过旁路网络(bypassing network)解决存在的“真相关性”。Dispatch(分发):被重命名之后的指令会按照程序中的规定的顺序,写到发射队列(Issue Queue)、重排序缓存(ROB)和Store Buffer等部件中Issue(发射):经过流水线的分发(Dispatch)阶段之后,指令被写到了发射队列(Issue Queue)中,仲裁(select)电路回从这个部件中挑选出合适的指令送到FU中执行。Register File Read(读取寄存器):被仲裁电路选中的指令需要从物理寄存器堆(Physical Register File, PRF)中读取操作数Execute(执行):各种FU单执行Write back(写回):将FU计算的结果写到物理寄存器(PRF)中,通过旁路网络将计算结果送到需要的地方。Commit(提交):这个阶段起主要作用的部件是重排序缓存(ROB),它将乱序执行的指令拉回到程序中规定的顺序
Cortex A9的指令执行过程
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/82735.html