我目前正在构建一个支持多种寻址模式的小型CPU解释器,包括寄存器延迟和置换。它采用经典的IF-ID-EX-MEM-WB RISC管道。在流水线的哪个阶段是解码的地址模式操作数的值。例如:
addw r9,(r2),8(r3)
在什么阶段(r2)和8(r3)将被解码为它们的实际值?
答案 0 :(得分:1)
这是一个有趣的问题。
RISC架构的一个属性是寄存器寄存器操作。也就是说,诸如ADD之类的计算指令的所有操作数必须已经在寄存器中。这使RISC实现能够享受常规管道,例如您在问题中提到的IF-ID-EX-MEM-WB管道。此约束还简化了内存访问和异常。例如,如果从存储器读取数据的唯一指令是加载指令,并且如果这些指令只有像寄存器+位移这样的简单寻址模式,那么给定的指令最多只能产生一个存储器保护异常。
相比之下,CISC架构通常允许丰富的操作数寻址模式,例如寄存器间接寻址,并在您的问题中编入索引。这些体系结构的实现通常具有不规则的管道,在操作数可用于计算(ADD等)之前,可能会因为一个或多个存储器访问而停止。
尽管如此,微架构已成功实现了CISC架构的流水线化。例如,Intel 486有一个管道,可以将操作数和结果读入/写入内存。因此,当实现ADD [eax],42时,有一个流水线阶段从8 KB d-cache读取[eax],执行add的流水线阶段,以及另一个将总和写回[eax]的流水线阶段
由于CISC指令和操作数使用是动态混合且不规则的,因此您的流水线设计要么必须相当长,才能解决最坏情况,例如:多个内存读取访问操作数,内存写入读写结果,或者必须停止管道以在必要时插入额外的内存访问。
因此,为了适应这些CISCy地址模式,您可能需要IF-ID-EA-RD1-RD2-EX-WR流水线(EA = eff addr,RD1 =读取操作1,RD2 =读取操作2,WR =写入结果到RAM或reg文件)。
快乐的黑客攻击。
答案 1 :(得分:1)
正如Jan Gray指出的那样,你提到的CISC指令addw r9, (r2), 8(r3)
不会直接映射到IF-ID-EX-MEM-WB RISC管道。
但是,您可能还会考虑打破CISC,而不是创建一个IF-ID-EA-RD1-RD2-EX-WR管道(我认为这种情况无论如何都适用于此情况,至少不在我的表示法中)。指导进入类似RISC的微指令
tmp1 := load Memory[ r2 ]
tmp2 := load Memory[ 8+r3 ]
r9 := addw tmp1 + tmp2
用这个uop(微操作)分解, 地址计算(r2)和8(r3)将在各自的EX管道中完成, 以及MEM管道中及其周围的实际内存访问。
正如Jan所提到的,i486有一个不同的管道,即所谓的load-op管道: IF-ID-AGU-MEM-EX-WB,其中AGU是地址生成单元/管道。
这允许不同的uop分解
tmp1 := load Memory[ r2 ]
r9 := addw tmp1 + load Memory[ 8+r3 ]
在AGU管道中完成地址计算(r2)和8(r3)。
答案 2 :(得分:0)
正如Jan Gray上面提到的,您尝试执行的指令并不适用于此管道。您需要在MEM阶段加载数据,并在EX阶段(在mem之前)对其进行一些数学运算。
要回答另一个相关问题,如果你想这样做:
Load R9, 8(R3)
值 - 修改操作数的值'的值在EX阶段计算。