ARM
arm体积小功耗低性能高,支持thumb ARM双指令集,兼容8/16位器件;大量使用寄存器,指令定长,寻址简单。
ARM是32位架构,Word 32bit, half Word 16bit.
模式
用户模式是用户程序的模式,没权限操作其他硬件和数据,只能通过软中断或异常切换。
系统模式和用户模式共用一套资源,且权限更高。
中断模式可以自由访问硬件资源。不然CPU直接可以访问所有硬件资源效率太低。
快速中断紧急一些,处理快速问题。
管理模式svc:软中断swi处理或者板子上电/rst时的模式,主要用于系统初始化。
中止模式:访问非法地址时的异常,如segment fault。预取指令中止或数据中止异常进入中止模式(预取指令中止是指令没问题,但是指令指的地址找不到)。
未定义模式:软件仿真,或无法识别指令时进入。
Monitor:安全监测。
这些模式的切换可以通过软件或者EXTI Exception改变。
异常有精确和非精确,无法嵌套只能一个个处理。
寄存器
除了sys和usr是共用一组寄存器,其他模式之间都是有一部分通用寄存器(33个,对于Cortex-A来说),一部分当前模式独有的状态寄存器(7个)。
- R0-R7:未分组寄存器。这些寄存器所有模式下都指向同一批寄存器,因此模式切换的时候可能出问题。
- R8-R14:分组寄存器,分低位高位,一些指令可以分组执行提高效率。高位比如R13的SP和R14的LR。(R8-R12快中断和其他模式不一样,物理上有两组R8-R12的寄存器;而R13 14有7个物理寄存器,sys和usr模式下是一样的,其他模式下各自有一个R13 R14)
- R15 PC:程序计数器。
r13 堆栈寄存器,由高位向低位存储。
刚刚了解到r13是7种模式下各有一个的,因此用途在于当模式切换的时候,堆栈指针可以保存各自模式下需要保存的寄存器,便于恢复。
r14 链接寄存器,用于保存程序运行位置(即各个模式下PC的值),多模式切换时返回有用。
pc的最低位一般没用,arm是[31:2]位保存pc,[1:0]位=0;thumb是[31:1]保存pc。因此寻址0x40008001和寻址0x40008000没区别。
pc=当前程序执行位置+8,因为取指是预取 提前多取一点装载一下,然后解码执行。
cpsr 当前程序状态寄存器,cpsr是所有模式共用的。
- m位:[4:0],指代处理器模式位,如10000是usr mode。
- t位,j位:[5] [24],指代寄存器是arm/thumb等状态。
- i位:[7],是否启用中断,1禁止IRQ。
- nzcv:[31:28] 条件位,比如根据这些位的值决定跳转到什么模式。
spsr 每种模式下自己专用的物理状态寄存器,用于异常发生时备份cpsr。sys usr没有spsr因为他俩不是异常模式。
协处理器
arm允许协处理器扩展指令集。比如控制cache,存储管理单元mmu,异常向量表地址设置等。了解即可,用到的时候再深入学习。
流水线
取指,移码,执行。这些都是串行的话,或者都给cpu做,效率极低。就像手术台上的大夫要完成重要的手术操作,护士辅助可以递工具准备药剂,而不是拿工具也要大夫自己亲自去拿。
一个程序需要三个步骤都来一遍,3个周期。但是我们可以依次开始更多的指令,比如一个周期入一个程序,一个周琦出一个指令,效率将大幅度提高。
最佳流水线:反应周期2
但是实际上并非这么理想的每一个都是一个指令周期,因为有许多总线要传输数据,外存拷过来的数据更慢。
LDR流水线:
执行ldr装载等指令时,需要先通过指令和数据总线把数据存入指定寄存器中,再写回原寄存器。在此期间其他并行的指令无法解码无法执行,因此只能延时stall。
分支流水线:反应周期2
如图,BL指令要跳转到AND指令。
第2周期,Linkret做了两件事,第一是预取目的地址指令,预取AND指令。第二是保存当前函数返回位置,即把SUB的地址存入r14链接寄存器中,因此占用总线无法解码执行。
第3周期跳转,解码and的指令,预取下一条指令,且修改r14值,因为前面介绍过r14最后两位没用,清零以便简单返回。
中断流水线:反应周期7
周期1:收到中断,不急,先把add指令执行完了。
周期2:保存cpsr到spsr,修改cpsr的当前模式改为中断模式,禁止中断进一步输入。
周期3:保存中断函数返回地址lr=当前pc=0x800c加了2条指令后的地址,预取指令。
周期4:跳转过去解码,且调整r14 lr=0x8008.
周期5:根据lr跳转回原函数对应位置。
周期6:根据lr修改回pc.