auipc rd, imm20
(add upper immediate to pc
):
add imm20 << 12
to the address of this instruction and write
the result in register rd
jalr rd, imm12(rs)
(jump and link register):
set pc
to rs + imm12
(sign-extended, LSB cleared);
write pc + 4
to register rd
jalr rs
:
pseudoinstruction for jalr ra, 0(rs)
ret
: set pc
to ra
,
pseudoinstruction for jalr zero, 0(ra)
call imm32
(usually with gcc -S
):
PC-relative call with 32-bit offset,
pseudoinstruction for auipc ra, imm32_hi
; jalr ra, imm32_lo(ra)
long bar(long x)
{
return x;
}
long foo(long x)
{
return bar(x) + 1;
}
long main(void)
{
return foo(0) + foo(1);
}
$ riscv64-unknown-elf-gcc -O -fno-omit-frame-pointer -mcmodel=medany -mno-relax -fno-pie -no-pie -fno-inline -o foo foo.c
$ riscv64-unknown-elf-objdump -d foo
...
0000000000010188 <bar>:
10188: 1141 addi sp,sp,-16
1018a: e422 sd s0,8(sp)
1018c: 0800 addi s0,sp,16
1018e: 6422 ld s0,8(sp)
10190: 0141 addi sp,sp,16
10192: 8082 ret
0000000000010194 <foo>:
10194: 1141 addi sp,sp,-16
10196: e406 sd ra,8(sp)
10198: e022 sd s0,0(sp)
1019a: 0800 addi s0,sp,16
1019c: 00000097 auipc ra,0x0
101a0: fec080e7 jalr -20(ra) # 10188 <bar>
101a4: 0505 addi a0,a0,1
101a6: 60a2 ld ra,8(sp)
101a8: 6402 ld s0,0(sp)
101aa: 0141 addi sp,sp,16
101ac: 8082 ret
00000000000101ae <main>:
101ae: 1101 addi sp,sp,-32
101b0: ec06 sd ra,24(sp)
101b2: e822 sd s0,16(sp)
101b4: e426 sd s1,8(sp)
101b6: 1000 addi s0,sp,32
101b8: 4501 li a0,0
101ba: 00000097 auipc ra,0x0
101be: fda080e7 jalr -38(ra) # 10194 <foo>
101c2: 84aa mv s1,a0
101c4: 4505 li a0,1
101c6: 00000097 auipc ra,0x0
101ca: fce080e7 jalr -50(ra) # 10194 <foo>
101ce: 9526 add a0,a0,s1
101d0: 60e2 ld ra,24(sp)
101d2: 6442 ld s0,16(sp)
101d4: 64a2 ld s1,8(sp)
101d6: 6105 addi sp,sp,32
101d8: 8082 ret
...
.
.
.
+-> +----------------+ |
| | main's ra | |
| | previous s0/fp ----+
| | saved s1 |
| | ... |
| +----------------+ <-+
| | foo's ra @main | |
+---- previous s0/fp | |
+----------------+ |
.
.
.
kernel/printf.c
)
*(volatile int *)0 = 0;
to exec()
in kernel/exec.c
&
run make qemu-tracevoid backtrace(uint64 fp) { ... }
yourself-fno-omit-frame-pointer
scause 0x000000000000000f
sepc=0x0000000080004d7c stval=0x0000000000000000
PANIC: kerneltrap
[<0x0000000080000594>] panic+0x46/0x62
[<0x000000008000292a>] kerneltrap+0xa8/0xcc
[<0x0000000080005dd4>] kernelvec+0x44/0x90
[<0x0000000080005bb6>] sys_exec+0xde/0x128
[<0x0000000080002b02>] syscall+0x3e/0x6c
[<0x00000000800027ec>] usertrap+0x6a/0x100
stvec
register (kernel/trap.c
)stvec
printf("%d\n", *(volatile int *)0x4000000000);
to main
in user/call.c
sepc
)lw
instructionkernel/trampoline.S
)usertrap
in kernel/trap.c
)scause
: 13 (0xd), “load access fault”sepc
: pc of the faulted instructionstval
: the virtual memory addressusertrap
in kernel/trap.c
) to continue instead of killing the process?$ call
usertrap(): unexpected scause 0x000000000000000d pid=3
sepc=0x0000000000000028 stval=0x0000004000000000
ecall
instructionuser/usys.S
, using a0-a6 as arguments and a7 as the syscall numberusertrap
(kernel/trap.c
) -> syscall
(kernel/syscall.c
), using a7 again to dispatch