1

Im trying to compile bland c code to an elf format executable by a RV32i processor.

However when I enable optimizations (-Os or -O2) the resulting assembly contains compressed Instructions which I can not execute. All my selfmade code is being compiled into normal rv32i instructions, only the helper functions* are being compiled to C-Instructions. How can I disable C-Instructions completely?

With helper functions I mean __riscv_save_0, __riscv_restore_0, __riscv_save_4, ...

I compile code using

riscv32-unknown-elf-gcc $(CFLAGS) -T link.ld $(SRCS) -o $@ -lgcc

with CFLAGS being:

-g -O2 -msave-restore -mabi=ilp32 -march=rv32i --specs=nosys.specs -nostdlib -Wall -Wl,-gc-sections -ffunction-sections -ffreestanding -fno-builtin

The Disassembly looks like this - with optimizations on: (all my code for some reason without C-instructions and all the helper functions with C-instructions)

00000174 <__riscv_save_0>:
174:    1141                    addi    sp,sp,-16
176:    c04a                    sw  s2,0(sp)
178:    c226                    sw  s1,4(sp)
17a:    c422                    sw  s0,8(sp)
17c:    c606                    sw  ra,12(sp)
17e:    8282                    jr  t0
...
00000198 <__riscv_restore_0>:
198:    4902                    lw  s2,0(sp)
19a:    4492                    lw  s1,4(sp)
19c:    4422                    lw  s0,8(sp)
19e:    40b2                    lw  ra,12(sp)
1a0:    0141                    addi    sp,sp,16
1a2:    8082                    ret
...
000001c4 <main>:
1c4:    fb1ff2ef            jal t0,174 <__riscv_save_0>
1c8:    034000ef            jal ra,1fc <func_a>
1cc:    00000537            lui a0,0x0
1d0:    00000613            li  a2,0
1d4:    00000593            li  a1,0
1d8:    1a450513            addi a0,a0,420
1dc:    098000ef            jal ra,274 <func_b>
1e0:    00000537            lui a0,0x0
1e4:    00000613            li  a2,0
1e8:    00000593            li  a1,0
1ec:    1b450513            addi a0,a0,436
1f0:    084000ef            jal ra,274 <func_b>
1f4:    154000ef            jal ra,348 <func_c>
1f8:    fa1ff06f            j   198 <__riscv_restore_0>
Sun.
  • 73
  • 7
  • It looks like maybe you are disassembling the linker output. Try to find out if the compiler generated the helper functions, or if they are obtained from the library instead. That should help you narrow down the source of the issue. You can do that by disassembling the object files to see if those functions and/or any compressed instructions are present in the compiler output, pre-linker. (You can see that `main` could have used compressed instructions, but didn't.) – Erik Eidt Apr 15 '21 at 14:57
  • as far as I can tell these functions come from the -lgcc library – Sun. Apr 15 '21 at 15:35
  • whenever I don't include -lgcc during compilation. It throws an error that __riscv_restore_0,... are not found – Sun. Apr 15 '21 at 15:36
  • They're pretty small, you can provide your own equivalent? Or maybe don't use `-msave_restore`?? Otherwise, there must be a proper version of the library for `-march=rv32i` vs., say `-march=rv32imac`, but I don't know how gcc is supposed to work in that regard. – Erik Eidt Apr 15 '21 at 16:41
  • Edit: when I exclude -msave_restore everything compiles to none C-instructions :) But these helper functions are a great addition to code optimisation. It would be great if you have any other clue to replace them with proper none C implementations. – Sun. Apr 15 '21 at 17:05
  • I found where save and restore are implemented: https://github.com/gcc-mirror/gcc/tree/master/libgcc/config/riscv/save-restore.S – Sun. Apr 15 '21 at 17:07
  • They seem to be only a few lines long, surely you can provide your own that avoid using compressed instructions, no? Or perhaps assemble the source you found using the `-march=rv32i`? – Erik Eidt Apr 15 '21 at 17:08
  • if I overwrite these labes, they will simply not be used – Sun. Apr 15 '21 at 17:25
  • I don't understand what you mean by overwrite. You can provide your own non-compressed versions of these and then remove -lgcc, no? – Erik Eidt Apr 15 '21 at 17:39
  • Good point. I tried it, and it works. But this will get rid of all the cool features of the libgcc. like software floats, which I will definitely need – Sun. Apr 15 '21 at 21:26

1 Answers1

2

Ok, I found an answer to my problem.

While compiling you can change what architecture to use. But the libraries used in the build are generated whilst building the toolchain.

Thus I made the mistake of building the Risc-V toolchain with the RV32IC architecture but wanted them to be used in a RV32I project only.

So the workaround is to simply recompile the toolchain with RV32I.

Sun.
  • 73
  • 7