Instruction Predecode
Some other questions that we probably want to answer with information gathered during predecode:
- If there are no branches, this fetch block is expected to always fall through to the next-sequential fetch block (ignoring the possibility of an exception)
- Does a branch target lie inside/outside this fetch block?
- Despite the existence of branch instructions, is it still possible for this fetch block to fall through to the next-sequential fetch block?
After completing a transaction, the fetch unit passes a fetch block to the predecoders. There is one predecode unit for each instruction in the block. Each predecode unit determines the following:
- The immediate encoding format
- The fully-expanded 32-bit immediate offset used to calculate a branch target
- Whether or not an instruction is a control-flow operation, ie.
- An unconditional jump (
JAL
) - An unconditional direct jump (
JALR
) - A conditional branch (
B{EQ,GE,GEU,LT,LTU,NE}
) - A call (
JAL
whererd == x1
) - A return (
JALR
wherers1 == x1
)
- An unconditional jump (
This allows for control-flow instructions to be discovered shortly after fetch. Predecode output flows into the branch prediction pipeline, where it is used to [in]validate a previous prediction made for the corresponding fetch block.
It'd be nice to extract all immediates up-front here. This makes a nice separation between "predecode handling immediate operands" and "decode handling register operands." However, this amounts to a lot of wires (a full 32-bit immediate for each instruction in a fetch block), even before we completely decode the instruction. On top of that, these need to be stored somewhere.