-
Notifications
You must be signed in to change notification settings - Fork 10
Description
Toolchain issue with auipcc instructions in compiled C.
Commit: 6d22636
(also observed with earlier versions)
The offsets used in the calculation of PCC-relative targets are observed to be incorrect. The offsets appear not to have been adjusted for the fact that the AUIPCC instruction employs an 11-bit shifted constant rather than the RV-standard 12-bit offset. This has been observed to occur when the ensuing instruction is 'clc' (as in the pseudo-op 'cllc'), cincaddrimm or cjalr, as in this demonstration of a simple function call.
In every case that's been studied, the correct target address may be obtained by adding the literal constant from the 'auipcc <>' into the calculated address a second time, i.e. calculating as if that constant were still 12-bit shifted as per the RV standard.
Note: the file cheriot_toolchain.cmake shows the compilation switches being used; since this is our first use of C and CHERI on a large codebase, please do check the options used.
Update: the significant variable in this specific failure is the disabling of linker relaxations, but with more extensive source trees, the same faults occurs even with linker relaxations enabled.
This simple reproduction consists of a simple C/C++ file (test_case.c and test_case.cc; the code is the same) and a contrived assembler file - test_space.S - that ensures the target address is sufficiently far from the call site that auipcc must have a non-zero offset.
Build instructions:
cmake -B build
cmake --build build
Output:
- test_c - ELF file compiled from C source
- test_cc - ELF file compiled from C++ source
Relevant disassembly from 'test_c':
00200080 <start>:
; start():
200080: 17 13 00 00 auipcc ct1, 1
200084: 67 00 83 81 cjr -2024(ct1)
...
00200898 <start2>:
; start2():
200898: 6f 00 50 00 j 0x20109c <start2+0x804>
20089c: 73 10 00 c0 unimp
2008a0: 73 10 00 c0 unimp
The above disassembly shows the error in test_c but you may also simulate it using the included Verilator build of Sunburst chip:
./Vtop_chip_verilator -E build/test_c | more
Output from simulation of test_c (C compilation)
Simulation of Sunburst Chip
===========================
Tracing can be toggled by sending SIGUSR1 to this process:
$ kill -USR1 88228
USBDPI: Monitor output file created at /home/adrianl/toolchain_bug/usb0.log. Works well with tail:
$ tail -f /home/adrianl/toolchain_bug/usb0.log
UART: Created /dev/pts/1 for uart0. Connect to it with any terminal program, e.g.
$ screen /dev/pts/1
UART: Additionally writing all UART output to 'uart0.log'.
Simulation running, end by pressing CTRL-c.
TOP.top_chip_verilator.u_top_chip_system.u_core_ibex.u_ibex_top_tracing.u_ibex_tracer.unnamedblk1: Writing execution trace to trace_core_00000000.log
25: Illegal instruction (hart 0) at PC 0x00200098: 0xc0001073
33: Illegal instruction (hart 0) at PC 0x00200000: 0x0001145b
41: Illegal instruction (hart 0) at PC 0x00200000: 0x0001145b
49: Illegal instruction (hart 0) at PC 0x00200000: 0x0001145b
The trace log output is:
Time Cycle PC Insn Decoded instruction Register and memory contents
18 5 00200080 00001317 CH.auipcc c6, 0x1 x6=0x00200880+0x15e3e0000
22 7 00200084 81830067 CH.cjalr c0,-2024(c6) x6:0x00200880+0x15e3e0000 x0=0x00000000+0x000000000
30 11 00200098 c0001073 -->csrrw x0,cycle,x0 x0:0x00000000 x0=0x00000000
38 15 00200000 0000 -->c.unimp
46 19 00200000 0000 -->c.unimp
54 23 00200000 0000 -->c.unimp
Compilation with linker relaxations enabled
The corresponding output from the build, where the auipcc/cjalr is replaced with a simple cjal instruction, is fine:
./Vtop_chip_verilator -E build/test_cc | more
Output from simulation of test_c/cc
Simulation of Sunburst Chip
===========================
Tracing can be toggled by sending SIGUSR1 to this process:
$ kill -USR1 88213
USBDPI: Monitor output file created at /home/adrianl/toolchain_bug/usb0.log. Works well with tail:
$ tail -f /home/adrianl/toolchain_bug/usb0.log
UART: Created /dev/pts/1 for uart0. Connect to it with any terminal program, e.g.
$ screen /dev/pts/1
UART: Additionally writing all UART output to 'uart0.log'.
Simulation running, end by pressing CTRL-c.
Time Cycle PC Insn Decoded instruction Register and memory contents
18 5 00200080 0190006f CH.cjal c0,200898 x0=0x00000000+0x000000000
26 9 00200898 0050006f CH.cjal c0,20109c x0=0x00000000+0x000000000
34 13 0020109c 10500073 wfi
Source files for reproducing this issue: source.zip
Simulator binary (x64 Linux): simulator.zip