xinzha:
通常来说软件人员并不关心流水线的细节,尤其是上层软件程序员,甚至驱动工程师都不需要了解流水线,但是对于一个真正的系统底层工程师来说,了解流水线的一个比较重要的意义就是当出现问题时,能够精确定位到产生问题的那条指令,从而精确跟踪问题,还有就是异常处理程序执行完成后根据LR寄存器的值来正确返回也需要对流水线的了解。不过有些情况下体制就不能保证精确定位,比如说有writebuffer的时候,你的写指令即使会发生错误(例如地址错误、权限错误、器件错误等),也是在数个周期之后,当写指令真正出现在总线上时才会激起异常,其原因是因为速度匹配问题,写数据需要通过writebuffer来完成,发生异常的时刻已经离发出写指令的时刻不匹配了。当发生异常的时候,犯罪分子和发生异常时所在模式的pc的匹配关系如下:Dataabortpc-8,因为dataabort只有进入执行阶段才能被发现,这时第三条指令已经被取指。IRQpc-8,IRQ发生时刻不可预知,在当前指令执行完之后响应,所以pc也是第三条的地址。FIQpc-8,原理同上。PrefetchAbortpc-4,这个最绕,是预取指时发生错误造成的,但是如果这条指令不进入执行阶段就不会造成异常,比如说前面一条是jmp。所以我猜测在它进入执行之前,kernel已经知道出错,pc不再更新,保持为它下一条指令的位置。SWI和UNDEF和上一条一样,都是在译码阶段kernel已经知道会发生异常,不再更新pc,但是进入执行阶段才会激起异常,所以异常地址也都是pc-4。今天来讨论一下对齐问题,在ARM7,即armv4中,规定如果访问int类型数据时给出的指针地址的低2位不为0的话,系统会自动将低两位的1抹平,即强制四字节对其,这样的问题就是如果你的数据偏偏就是不对齐的,cpu拿到的数据就是不正确的,bug由此产生。在ARM9(我接触的是arm926ejs)中,如果访问int型数据,低2位不为0,那么cpu直接挂住,一个dataabort。在ARM11之后的版本中支持了非对齐访问,是在总线上拆分然后拼接来实现的,也就是说如果你访问int时给出的地址不是4字节对齐,那么总线上会出现两个int访问,然后把数据拼接起来送给cpu,这些对于cpu是不可见的,但是会导致速度下降,总线占用率上升。此功能可以通过修改cp15中来关闭,实现跟以前版本一样的对齐方式。需要说明的是这里的int是4字节而不是2字节。另外一点是对齐问题并不是专指四字节对齐,很多初学者或者有一定经验的人都会犯这个错误,认为只有四字节对齐才会出问题。实际上对齐指的是数据边界对齐,也就是说longlong数据要8字节对齐,int要4字节对齐,short要2字节对齐,byte自然是怎么对都齐了。