I’m just completely confused about what it is that you are doing.
Is this code in initial setup, before any user mode code is ever run? Or is it run in a trap handler?
What are you running it on? Does the hardware even have user mode?
I have no idea where this comes from:
IMM rs1 funct3 rd opcode
001000000000 00010 001 00110 0111100
It doesn’t make sense as an opcode with last two bits 00 is a 16 bit instruction, but something appears to be trying to interpret it as an I-format 32 bit instruction.
Running it together and disassembling it:
bruce@rip:~$ echo '.word 0x2001133c' >foo.s
bruce@rip:~$ riscv64-unknown-elf-gcc foo.s -c -march=rv32gc -mabi=ilp32
bruce@rip:~$ riscv64-unknown-elf-objdump -d foo.o
foo.o: file format elf32-littleriscv
Disassembly of section .text:
0: 133c addi a5,sp,424
2: 2001 jal 0x2
That’s a pretty big stack frame if something needs to add 424 to it. And 0x2001 is also a 16 bit instruction, an unconditional jump-and-link to itself in rv32 or an addiw with illegal destination register x0 in rv64.
Describing what you’re doing in English prose doesn’t help much as 90% of programming errors are the code not saying what you think it’s saying.
I can’t look at your rust code as I’m getting “bad gateway” from nginx.
In any case most of us here don’t know or use Rust, so you’d be better off posting your linked binary in elf or even hex form somewhere (but better elf).
Or get everything working in straight asm or asm and C before you try to make it work with a compiler that we really don’t know the behavior of.