我一直想知道一件事,但是首先,要做出的一个假设是,由宏操作产生的所有μop都可以具有与宏操作相同的rip
(我很确定IQ对于每个IFETCH块都有一个rip
,并且解码器可以根据以下公式轻松转换rip
+宏操作rip
的宏操作的偏移量长度信息)。对于SnB上的每个逻辑核心,IDQ是8行32字节(在最近的微体系结构中可能是64字节,但我不确定),这引出了IDQ中μop格式的问题-是否有地址每条IDQ行和一条jmp
指令都会导致开始新行,类似于μop缓存;根据优化手册page 47的解释,这里的32字节对齐区域可以跨越3种方式,但最终的方式必须以jmp
结尾,这样才能重新开始获取通过将流水线引导至该地址来访问下一个指令窗口(该地址也可能跳回到μop缓存中,或者可能必须启动旧式解码流水线)。如果IDQ具有相同的结构,则可以轻松地将μop缓存方式移至IDQ(因此,我确实认为IDQ可以在每行的开头而不是每个指令具有单个地址,因为它没有如果该行上的指令具有连续的rip
并且分支,返回等之后的一条指令将在新行上,则需要)。它也将允许LSD锁定并更有效地检测循环,因为它仅需扫描行首的8个地址以检查其是否与jmp
地址相同。但是,我不确定LSD是如何精确实现的。信号源似乎将28μops的值固定为可以检测到的最大环路。
Stack Engine也很复杂,它如何进行同步操作。阅读堆栈引擎上的 microarchitecture.pdf 中的Agner fog的部分,表明同步μop插入到mov
或add
之前,导致它需要rsp
同步,因此,如果原始rip
或ret
之前有mov
,则必须采用该指令的add
(这样才能与{{1 }}在任何处理rsp
,BEU?(*)的端口上检查RSB预测。我还建议堆栈引擎与解码器一起工作,以便它与解码器同时插入,因此以后不必为了插入而随指令移动。在将ret
相对于行开始处的地址计算rip
时,在将它们发送给ROB时,在同步操作上还必须有一个位指示,以通知分配器以减少其字节。在同步操作之后,它也可以为指令开始新的一行,但这似乎很昂贵。
之所以停止此逻辑失效,是因为指令的rip
无法从该行的μop字节偏移量到该行起始地址的地址得出,宏操作的长度与μop的长度不同。这可以通过使每条IDQ行分别对应一个宏操作来解决(将任何同步操作附加到该行的末尾,即一行上的mov
+ synchop和我之前提到的ret
,在下面的地形图中,每行的开头都带有rip
,我想这似乎很浪费。我唯一想到的替代方法是为每个宏操作内联标记地址,这似乎很麻烦。
有人有什么要补充或纠正的方式吗?
(*)确实链接到如何处理分支预测错误的问题,例如,当将预测采用的分支指令分配给RS时,参数之一可能是ROB的rip
BEU后输入指令可能会误导管道。当分配了ret
时,其中一个参数必须是uop之后的uop的ROB条目,而另一个参数必须是rsp
,以便可以与其进行比较。