我一直想知道有一段时间,但首先,一个假设是宏操作产生的所有微操作都可能与rip
宏操作相同(我很确定 IQ 会rip
为每个IFETCH 块和解码器可以根据长度信息轻松地将rip
+ 宏操作的偏移量转换为宏操作的偏移量)。rip
IDQ 是 SnB 上每个逻辑核心的 8 行 32 字节(在最近的微架构中可能是 64 字节,但我不确定),这引出了 IDQ 中微操作格式的问题——是否有地址每个 IDQ 行和一条jmp
指令都会启动一个新行,类似于μop 缓存;在哪里,根据我从第 47 页的解释在优化手册中,一个 32 字节对齐的区域可以跨越 3 路,但最后的路必须以 a 结尾,jmp
以便它可以通过将流水线引导到该地址来重新启动下一个指令窗口的获取(也可以跳回μop 缓存或可能必须启动旧的解码管道)。如果 IDQ 具有相同的结构,它将允许将 μop 缓存方式轻松移动到 IDQ(所以我觉得 IDQ 可以在每行的开头而不是每条指令都有一个地址,因为它没有如果线路上的说明连续,则需要rip
s 和分支、返回等之后的指令将在新行上)。它还允许 LSD 更有效地锁定和检测循环,因为它只需要扫描行开头的 8 个地址以检查它是否与例如jmp
地址相同。但同样,我不确定 LSD 是如何精确实现的。消息来源似乎将 28 μops 的值固定为可以检测到的最大环路。
还有 Stack Engine 的复杂性以及它如何放置同步操作;阅读 Stack Engine 上 microarchitecture.pdf 中Agner fog 的部分显示同步 μop 插入在mov
or之前add
导致它需要同步,rsp
因此如果在原始or之前rip
有 a ,则必须采用该指令可以将其与检查任何端口句柄的 RSB 预测进行比较ret
mov
add
rsp
ret
, BEU?(*))。我还建议堆栈引擎与解码器一起工作,以便它在解码器插入的同时插入,这样它就不必稍后沿着指令移动以插入它。同步操作上还必须有一个位指示,以通知分配器在计算rip
相对于行首地址的 s 时将其字节折扣,然后将它们发布到 ROB。它也可以在同步操作之后为指令开始一个新行,但这似乎很昂贵。
阻止这个逻辑死在它的轨道上的事情很简单,rip
因为宏操作的长度不是与μops的长度相同。这可以通过让每个 IDQ 行对应一个宏操作来解决(将任何同步操作附加到行的末尾,即mov
+synchop 在一行上,ret
而我之前提到的,在下面的地形上,带有rip
at每行的开头),我想这似乎很浪费。我能想到的唯一选择是为每个看起来很混乱的宏操作内联标记地址。
有没有人有任何关于如何实施的补充或更正?
(*) 这确实与如何处理分支错误预测的问题相关联,例如,当将预测采用的分支指令分配给 RS 时,其中一个参数可能是rip
该指令的 ROB 条目在 BEU 之后的引导错误预测的管道。分配a 时ret
,其中一个参数必须是它之后的 uop 的 ROB 条目,另一个参数是 the ,rsp
以便可以与它进行比较。