ARM条件码
流水线 条件执行 条件码 CPSR
在聊条件码之前我们先说说「流水线(pipeline)」,其实流水线技术是现代工业文明的一个典型象征,它是「效率」的代名词,流水线机制的产生让作业效率大幅提升。
一项任务(Task)的完成伴随着很多步骤(step),每个步骤都需要一个对应的工作者(worker)完成。理论上一个Task从开始到完成所需要的时间是相对固定不变的,显然,如果只有一项工作(totally only one)需要完成,那么不管多少个worker来做,它的完成时间并不会因此缩短,在这种场景下多worker是没有意义的。
worker就是所谓的pipeline(流水线),真正发挥流水线威力的地方在于「批量处理同质化的任务」
如上图,有4个worker,一辆车从等候到完成,需要经过这4个worker的工序,这个是无法减少的,流水线的优势在于,当开足马力进行生产时,每个worker都会投入工作不会闲着,这样,当时间过去T8时,已经生产了4台车,平均一台车用时T8/4 = T2,而如果不使用流水线技术,一台车用时T4,这就是流水线的魅力。
以上就是一个4级流水线的工作场景,效率是显著的,理论上而言似乎流水线级数越多,单个task平均用时越短,但实际囿于硬件和管理等开销,不能无限制的细分下去。(显然,不存在可以无限细分的步骤)
在ARM中,一般设有3级流水线,分别对应「一级.取址」「二级.解码」「三级.执行」
观察示意图,流水线要能够高效稳定的运行有一个前提,就是流水线的每一级所用时长需要相差无几,不然就存在下一级流水线等待上一级流水线的情况(反之亦然),结果就是worker工作不饱和,效率不稳定。
而最佳流水线(图2)就是一个非常经典理想的场景,每一个周期(cycle)都有一条指令被执行,而这些指令操作都发生在寄存器之间(没有与内存进行数据交互,这样地址总线和数据总线就不存在被占用的情况),流水线容量得到了充分的发挥,指令周期为1。
实际上(图3),寄存器与内存之间存在着频繁的交互,arm汇编中,ldr指令将数据从内存加载进寄存器中,str将寄存器中的数据放入内存中,这两种操作都会占用指令/数据总线,如紧随ldr指令的writeback(回写)操作便会占据一个指令周期,这样在1个CPU指令周期下无法完成ldr指令,这样接下来流水线只能使用stall(缓停)来等上一级执行完毕
图4是非常常见的分支流水线,BL为带链接跳转(B先跳转到目的地址,最终还需要返回到linker寄存器中的地址),以上(图4)就有2条指令并未Execute,因为跳转指令跳过了,这就造成了取指和解码的「浪费」,好在是三级流水线,所白费的功夫并不多。(BL花费了3个指令周期)
-
周期1: 内核被告知有中断 IRQ在现行指令执行完之前不会被响应( MUL and LDM/STM 指令会有长的延迟) 解码阶段:中断被解码(中断已使能,设置了相应标志位… )。如果中断被使能和服务,正常的指令将不会被解码。
-
周期 2: 此时总是进入ARM状态. 执行中断 ( 获取IR向量的地址), 保存 CPSR 于 SPSR, 改变CPSR模式为 IRQ 模式并禁止进一步的 IRQ 中断输入。
-
周期 3: 保存 PC (0x800C) 于 r14_irq, 从IRQ异常处理向量处取指
-
周期 4: 解码向量表中的指令; 调整r14irq 为0x8008
-
周期 4和 5: 无有用的指令取指, 由于周期 6的跳转
-
周期 6: 取异常处理子程序的第一条指令; 从子程序返回:
SUBS pc,lr,#4 -
这将恢复工作模式并从响应中断前的下一条指令处取指,如果有多个中断,需堆栈保存返回地址。 注意最大的FIQ响应延迟为 29个周期(而非Thumb状态的28周期!)
ARM有一个叫做
CPSR(Current Program Status Register)的特殊寄存器,其中按照以下结构存放着当前程序的运行状态![image.png]()
图6.CPSR寄存器结构 前4位[31:28]的
NZCV,也就是:Negative, Zero, Carry, oVerflow。它们的值是由ALU(逻辑运算单元)在每一次运算后根据自己的运算结果更新的:(其实不是每一次,只有指令的第20位为1时才更新)
- N = 1则上次运算结果为负,= 0则为正
- Z = 1则上次运算结果为零,= 0则非零
- C = 1则上次运算产生进位,= 0则没有进位
- V = 1则上次运算产生溢出,= 0则没有溢出
在
ARM机器码中,高4bit是条件执行码,ARM指令是否执行取决这4bit数据
图7.条件码 ARM指令中,开头的4bit机器码通常都是1110,表示无条件执行。ARM汇编指令中的各种后缀就是图7表格中的助记符。B就是无条件跳转指令,机器码头4bit就是1110。条件码为0000,该指令在且仅在CPSR中Z = 1时被执行
条件码为1000,该指令在且仅在CPSR中C = 1 && Z = 0时被执行
条件码为1110,无条件执行该指令
使用条件指令来避免分支跳转从而避免浪费流水线的原理是:
1、instruct
2、instruct
3、condition-jump instruct
4、instruct
5、instruct
非条件指令会在第3步时根据跳转条件进行跳转,这样第4步就可能不会执行,从而浪费了第4步的流水线。而条件执行则是CPU顺序往下执行,不过不符合条件的指令并不会产生效果(不会修改相应的寄存器或者内存等)
其实,条件码看似高效,但不可避免的存在一些致命缺陷,理由很简单,3级流水线本身「可浪费」的空间并不太大,及时被浪费了,也不过2级(取址、译码)被浪费,而对于条件执行而言,
if(condition){//w1}else{w2},可能w1的指令数更多,而显然此刻执行w1是做的无用功。故,
ARM64已弃用条件码。
posted on 2021-12-27 23:59 shadow_fan 阅读(759) 评论(0) 收藏 举报

浙公网安备 33010602011771号