I'm currently building a small CPU interpreter that has support several addressing modes, including register-deferred and displacement. It utilizes the classic IF-ID-EX-MEM-WB RISC-pipeline. In what stage of the pipeline is the value for an address-moded operand decoded. For example:
addw r9, (r2), 8(r3)
In what stage i开发者_StackOverflow社区s (r2) and 8(r3) would be decoded into their actual values?
It's a funny question.
One property of RISC architectures is register-register operation. That is, all operands for computation instructions such as ADD must already be in registers. This enables RISC implementations to enjoy a regular pipeline such as the IF-ID-EX-MEM-WB pipeline you mention in your question. This constraint also simplifies memory accesses and exceptions. For example, if the only instructions to read data from memory are load instructions, and if these instructions have only a simple addressing mode like register+displacement, then a given instruction can incur at most one memory protection exception.
In contrast, CISC architectures typically permit rich operand addressing modes, such as register indirect, and indexed as in your question. Implementations of these architectures often have an irregular pipeline, which may stall as one or more memory accesses are incurred before the operands are available for the computation (ADD etc.).
Nonetheless, microarchitects have successfully pipelined CISC architectures. For example, the Intel 486 had a pipeline that enabled operands and results to be read/written to memory. So when implementing ADD [eax],42, there was a pipeline stage to read [eax] from the 8 KB d-cache, a pipeline stage to perform the add, and another pipeline stage to write-back the sum to [eax].
Since CISC instruction and operand usage is dynamically quite mixed and irregular, your pipeline design would either have to be rather long to account for the worst case, e.g. multiple memory reads to access operands and a memory write to write-back a result, or it would have to stall the pipeline to insert the additional memory accesses when necessary.
So to accomodate these CISCy addressng modes, you might need a IF-ID-EA-RD1-RD2-EX-WR pipeline (EA=eff addr, RD1=read op 1, RD2=read op 2, WR=write result to RAM or reg file).
Happy hacking.
As Jan Gray pointed out, the CISC instruction you mention addw r9, (r2), 8(r3)
does not map directly onto a IF-ID-EX-MEM-WB RISC pipeline.
But rather than creating a IF-ID-EA-RD1-RD2-EX-WR pipeline (which I don't think works for ths case anyway, at least not in my notation), you might also consider breaking the CISC instruction up into RISC-like microinstructions
tmp1 := load Memory[ r2 ]
tmp2 := load Memory[ 8+r3 ]
r9 := addw tmp1 + tmp2
With this uop (micro-operation) decomposition, the address computations (r2) and 8(r3) would be done in their respective EX pipestages, and the actual memory access in and around the MEM pipestage.
As Jan mentions, the i486 had a different pipeline, a so-called load-op pipeline: IF-ID-AGU-MEM-EX-WB, where AGU is the address generation unit / pipestage.
This permits a different uop decomposition
tmp1 := load Memory[ r2 ]
r9 := addw tmp1 + load Memory[ 8+r3 ]
with the address computations (r2) and 8(r3) done in the AGU pipestage.
As Jan Gray mentioned above, the instruction you are trying to execute doesn't really work for this pipeline. You need to load the data in the MEM stage, and do some math on it in the EX stage (which is before mem).
To answer another related question though, if you wanted to do:
Load R9, 8(R3)
The value for the 'value for the value-modded operand' is calculated in the EX stage.
精彩评论