Why does JALR encode the LSB of the offset?
Asked Answered
L

2

6

We know that jal specifies a 21-bit offset. However, it does not encode a 21-bit offset but a 20-bit one. The reason is that the least significant bit of an address is always zero because the smallest possible RISC-V instruction is 2 bytes, so this bit is not encoded in the instruction.

By encoding the offset this way it can provide a jumping range of ±1MiB. If jal did encode the LSB, it would offer just a ±512KiB jumping range.

However, the jalr instruction, which specifies a 12-bit offset, does encode the LSB. This reduces the jumping range to ±2kiB (instead of ±4kiB). I know that jalr uses the I-type format, which is the same as addi and the LSB of the immediate has to be encoded for this kind of instructions. However, I see no reason why the least significant bit has to be encoded for jalr.

Ladyfinger answered 25/12, 2019 at 18:12 Comment(2)
Unlike many other questions like this, the creators of this instruction set are still alive I assume and you can attempt to reach them. Understand that decisions like these are not always technical, but just what they happened to chose. Perhaps range was not relevant, implementation of the logic may have been more important than jump range. In either case it was someones or some meeting or some groups opinion to choose that path and doesnt have to have a technical/fixed/sane reason.Homogony
The names of the authors should be in the risc-v spec you can contact one or more of them directly for this opinion based question.Homogony
E
9

JALR is used for two relatively distinct purposes:

  • indirect branches, e.g.
    • function return
    • indirect function calls (e.g. function pointers; vtables/virtual dispatch), and,
  • mid-far branches (in a two instruction sequence, with 32-bit pc-relative range).

For the former, indirect branches, the immediate value is always 0, which is to say that effectively no immediate is used at all!

For the latter, this instruction is used in conjunction with AUIPC, which forms the upper 20 bits of pc-relative addressing — and JALR is used then in conjunction to form the lower 12-bits, for a total pc-relative offset of 32-bits.

However, AUIPC is used both for far branches, as well as for pc-relative data access.  Thus, they both share the 12-bit offset — the load/store's using their 12-bit immediate, and the JALR following suit by also using a 12-bit immediate field just like loads & stores.  The designers chose to share AUIPC rather than to have a two different AUIPC for these two uses (reference from code-to-code vs. reference from code-to-data).

In summary, the range of JALR is mostly not important, as long as it can supply the remaining 12-bits to complement AUIPC's 20 bits.  Sure there are other approaches, but this does have the advantage of reusing and requiring only one AUIPC instruction.

Ethicize answered 25/12, 2019 at 23:1 Comment(0)
T
3

The rationale has been stated in RISC-V spec:

Note that the JALR instruction does not treat the 12-bit immediate as multiples of 2 bytes, unlike the conditional branch instructions. This avoids one more immediate format in hardware. In practice, most uses of JALR will have either a zero immediate or be paired with a LUI or AUIPC, so the slight reduction in range is not significant.

Clearing the least-significant bit when calculating the JALR target address both simplifies the hardware slightly and allows the low bit of function pointers to be used to store auxiliary information. Although there is potentially a slight loss of error checking in this case, in practice jumps to an incorrect instruction address will usually quickly raise an exception.

Transmigrant answered 27/8, 2020 at 14:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.