Yes, you're right, in this case offset and immediate are essentially the same thing. In the RISC-V ISA, you'll see immediates for memory operations (loads and stores) referred to as "offsets" because of the way they are used -- they're added to the value held in register rs1
to derive the final memory address being loaded from / stored to, so they can be thought of as the "offset" from the address in rs1
.
In the case of the C.LD
(compressed load doubleword) instruction specifically, you can think of the immediate as being an unsigned number that is eight bits long, with bits indexed 0 to 7. The bits are distributed into two locations in the instruction so that the rd
and rs1
field can be in the same bit positions across instruction types. (This is obviously a bit confusing to read as a human, but it makes it easier to implement the hardware.) The last three bits of the immediate (the bits indexed 0, 1, and 2) are not encoded, because they're assumed to be 0 -- the byte address of a doubleword is assumed to be doubleword (64-bit / 8-byte) aligned, meaning it must be divisible by 8.
For a bit more clarity since you asked about how to implement the instruction, as an example, let me break down the instruction 0x5074
:
| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 |
The immediate comes from bits [6:5|12:10]. Bits [12:10] represent bits 5, 4, and 3 of the immediate, and bits [6:5] represent bits 7 and 6 of the immediate. In this case, that's 100
and 11
. That's only 5 bits, so the whole immediate becomes 11100000
-- we plug in 0's for bits 2, 1, and 0 of the immediate. The immediate is zero-extended, so it becomes 0x0000_00e0
, or 224
in decimal. (Note the zero-extension -- many RISC-V immediates, including for the standard load word instruction, are sign-extended).
I know your question was specifically about the immediate, but if it's useful, as for the rest of the instruction:
Bits [1:0] here are the opcode, 00
. This is one of the compressed instruction opcodes (non-compressed instructions have 7-bit opcodes, and bits [1:0] are 11
). Bits [15:13], which are 010
, are the opcode for a C.LD instruction.
rd
, the register destination, is in bits [4:2], which in this case are 101
. If we look at the compressed instruction register mapping table, we see that means that the register destination is x13
or a3
. rs1
, register source 1, is in bits [9:7], which are 000
. This maps to register x8
or s0
.
So, in summary, the implementation of this instruction means taking the value stored in rs1
, adding it to imm
, which is zero-extended, and loading a doubleword (64bits) from that location in memory into rd
. For the instruction 0x5074
, the immediate of 224 is added to the contents of register x8
, a doubleword is retrieved from the resulting address in memory, and the value is stored in register x13
.