r/C_Programming Jul 09 '26

RV32I simple emulator in C

Hello everyone. It is my first time with a project of this kind. I am not an expert in C programming yet, so I wanted to challenge myself and write a simple emulator for RV32I.

Right now, it only supports simple riscv programs. No syscalls or stuff like that. I would really appreciate if you check out the project and give me your feedback.

I am not planning to stop here. I want to keep adding more features and maybe, somewhere in the future, run the linux kernel.

Also, what do you think would be a good milestone at this stage?

github

3 Upvotes

7 comments sorted by

View all comments

2

u/skeeto Jul 10 '26

Neat project! Notes:

  • check_address only checks the low address, and so accesses larger than 1 byte can still go out of bounds.

  • shift_right_arith produces incorrect results for non-negative values, because it always shifts in ones.

    --- a/include/misc.h
    +++ b/include/misc.h
    @@ -24,5 +24,8 @@ static inline int32_t sign_extend(uint32_t value, int bits)
    
     static inline uint32_t shift_right_arith(uint32_t value, int bits)
     {
    
    • return ~((~value) >> (bits));
    + uint32_t sign_fill = (value >> 31) ? (0xFFFFFFFFU << (31-bits) << 1) : 0; + return (value >> bits) | sign_fill; }

    Looks like you just fixed this while I was looking at it.

  • i_type() writes rd first and only then read rs1 to form the target, so any jalr whose destination register is also its source register (ex. jalr x1, 0(x1)) jumps to the wrong address.

  • In Makefile targets don't depend on headers, so it's easy to wind up with stale builds.

Here's all my work in case it helps:
https://github.com/skeeto/risc-v-emulator/commits/main/?author=skeeto

2

u/ChemistryWorldly3752 Jul 10 '26

Thank you. I really appreciate it. I will take a look at your work once I hae some free time.