auipc/jalr question

325 views
Skip to first unread message

ct

unread,
May 12, 2022, 9:28:46 AM5/12/22
to RISC-V SW Dev
I am working on a project to port some existing C code to risc-v. Working with auipc/jalr has presented a major road block. Any assistance from the community would be appreciated.

I'm attempting to compute a relative jump offset between two functions in C. I've computed the offset between both functions. The offset is negative. The offset is stored into a ptrdiff_t, the upper 20 bits of the offset are masked off into a ptrdiff_t, the upper 20 bits are packed into an auipc instruction, the lower 12 bits of the offset are masked off into a ptrdiff_t, the lower 12 bits are packed into a jalr instruction. The jalr's destination is set to x0. When the code executes, it segfaults on a jump to an address that is well outside a range that makes any sense given the inputs.

This seems like it should be a fairly straightforward problem, gdb is showing all the values and bits are in order and yet...a segfault. Is there something I've missed reading the specification? The system my code runs on is a sifive, hifive-unleashed environment.

Thanks in advance for both your time and attention,

Chris

Andreas Schwab

unread,
May 12, 2022, 10:02:16 AM5/12/22
to ct, RISC-V SW Dev
On Mai 12 2022, ct wrote:

> I'm attempting to compute a relative jump offset between two functions in
> C. I've computed the offset between both functions. The offset is negative.
> The offset is stored into a ptrdiff_t, the upper 20 bits of the offset are
> masked off into a ptrdiff_t, the upper 20 bits are packed into an auipc
> instruction, the lower 12 bits of the offset are masked off into a
> ptrdiff_t, the lower 12 bits are packed into a jalr instruction.

You need to take into account that the jalr offset is sign-extended
before it is added to the base register. Thus you need to adjust the
auipc offset if bit 11 of the jalr offset is set.

--
Andreas Schwab, SUSE Labs, sch...@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

ct

unread,
May 13, 2022, 9:21:41 AM5/13/22
to RISC-V SW Dev, Andreas Schwab, RISC-V SW Dev, ct
Andreas,

Thank you for the quick response, progress has been made. There is a specific mechanism for handling the 11th bit that clarifies the situation.

For interested parties, the kernel community has a nice explainer for handling this situation. Some folks on the sifive forums have suggested this situation and technique get mentioned in the ISA specification. I'm not sure where the forum for voting on that is but, I could not more strongly encourage pointing this out in the ISA specification.


Emil Berthings comment (found in the link above) from the kernel list is below, it's been copied for future reference:

"
RISC-V can do PC-relative jumps with a 32bit range using the following two instructions:

    auipc    t0, imm20    ; t0 = PC + imm20 * 2^12    
    jalr    ra, t0, imm12    ; ra = PC + 4, PC = t0 + imm12,

Crucially both the 20bit immediate imm20 and the 12bit immediate imm12 are treated as two's-complement signed values. For this reason the immediates are usually calculated like this:

    imm20 = (offset + 0x800) >> 12
    imm12 = offset & 0xfff

...where offset is the signed offset from the auipc instruction. When the 11th bit of offset is 0 the addition of 0x800 doesn't change the top 20 bits and imm12 considered positive. When the 11th bit is 1 the carry of the addition by 0x800 means imm20 is one higher, but since imm12 is then considered negative the two's complement representation means it all cancels out nicely.

However, this addition by 0x800 (2^11) means an offset greater than or equal to 2^31 - 2^11 would overflow so imm20 is considered negative and result in a backwards jump. Similarly the lower range of offset is also moved down by 2^11 and hence the true 32bit range is

    [-2^31 - 2^11, 2^31 - 2^11)

Signed-off-by: Emil Renner Berthing <ker...@esmil.dk>

ct

unread,
May 18, 2022, 8:40:51 AM5/18/22
to RISC-V SW Dev, ct, RISC-V SW Dev
Also posting this for future reference:


The sections "absolute addressing" and "relative addressing" demonstrates another technique to handle the sign bit.

Chris

Bruce Hoult

unread,
May 18, 2022, 6:51:30 PM5/18/22
to ct, RISC-V SW Dev
Why is there "+1" in those examples? Surely the whole point of %hi() and %lo() is that they already do the right thing?

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/ed8f6243-12ad-4f3f-9690-e6a4c9cdb8acn%40groups.riscv.org.

Sober Liu

unread,
May 18, 2022, 11:49:34 PM5/18/22
to Bruce Hoult, ct, RISC-V SW Dev

I guess the +1 is to demo the ability of the relocators that can support an offset.

 

From: Bruce Hoult <br...@hoult.org>
Sent: Thursday, May 19, 2022 6:51 AM
To: ct <ct.c...@gmail.com>
Cc: RISC-V SW Dev <sw-...@groups.riscv.org>
Subject: Re: [sw-dev] auipc/jalr question

 

External email: Use caution opening links or attachments

 

Reply all
Reply to author
Forward
0 new messages