To speed up decoding, the basic RISC-V ISA puts the most important fields in one place in each instruction. As you can see in the table of command formats,
- The main opcode is always in bits 0-6.
- The destination register, if present, is always in bits 7-11.
- The first source register, if present, is always in bits 15-19.
- The second source register, if present, is always in bits 20-24.
Other bits are used for the lower opcode or other data for the instruction ( funct3 in bits 12-14 and funct7 in bits 25-31) and for immediate. How many bits can be used for immediate depends on the number of registers present in the instruction:
- Instructions with one destination address and two source registers (R-type) do not have immediate effect, for example, adding two registers (
ADD ); - Instructions with one addressee and one source register (I-type) have 12 bits for immediate, for example, with the addition of one register with immediate (
ADDI ); - Instructions with two source registers and no destination register (S-type), for example instructions for the store, also have 12 bits for immediate, but they must be in another place, because the register numbers are also in another place;
- Finally, commands with only the destination register and without a secondary operation code (U-type), such as
LUI , can use 20 bits for immediate (the main operation code and the destination register number together need 12 bits).
Now think from a different perspective, instructions that will use these immediate meanings. The simplest users, I-direct and S-direct, only need a 12-bit value with an extended icon. U-immediate instructions need immediate upper bits of a 32-bit value. Finally, branch / branch instructions need to be expanded directly in the low-order bits of the value, with the exception of the low-order bit, which will always be zero, since RISC-V instructions are always aligned at even addresses.
But why are the first bits shuffled? Think this time about a physical circuit that decodes the nearest field. Since this is a hardware implementation, the bits will be decoded in parallel; each bit in the output line will have a multiplexer to select which input bit it comes from. The larger the multiplexer, the more expensive and slower it is.
Thus, the "shuffling" of the immediate bits in the instruction coding is to make each direct bit of each output as few options as possible for the instruction input bits. For example, immediate bit 1 can come only from bit 8 of an instruction (S-immediate or B-immediate), 21 (I-immediate or J-immediate) or a constant zero (command U-immediate or R-type that does not have immediate) . Immediate bit 0 may come from instruction bits 7 (S-immediate), 20 (I-immediate) or constant zero. Direct bit 5 can only come from instruction bit 25 or constant zero. And so on.
The instruction bit 31 is a special case: for RV-64, bits 32-63 immediate are always copies of instruction bits. This high splitter adds a delay that would be even greater if it also needed a multiplexer, so it has only one parameter (different from constant zero, which can be processed later in the pipeline, ignoring everything instantaneous).
It is also interesting to note that you only need the main operation code (bit 0-6) to know how to decode directly, so immediate decoding can be performed in parallel with decoding the rest of the instruction.
So, answering the questions:
- Type SB doubles the range of branches, since instructions are always aligned at even addresses;
- The UJ type has the same general command format as the U-type, but the immediate value is in the lower bits instead of the upper bits;
- The immediate bits are shuffled to reduce the cost of decoding the immediate value by reducing the number of options for each output immediate bit;
- The table “immediate preparation according to RISC-V instructions” shows various kinds of immediate values ​​that can be decoded from the RISC-V instruction and from where each bit in the instruction arrives;
- They are created for each immediate output bit using the main opcode (bit 0-6) to select the bits of the input instruction.