[HN Gopher] Writing a RISC-V Emulator in Rust
       ___________________________________________________________________
        
       Writing a RISC-V Emulator in Rust
        
       Author : signa11
       Score  : 95 points
       Date   : 2025-10-26 07:34 UTC (15 hours ago)
        
 (HTM) web link (book.rvemu.app)
 (TXT) w3m dump (book.rvemu.app)
        
       | quantummagic wrote:
       | Just a heads-up that only the first three chapters are available
       | so far. Apparently there will be ten, when finished.
        
         | what wrote:
         | Those chapters were written 5 years ago, doubt they'll get
         | around to finishing it. But I think the repo has code for all
         | 10?
        
       | sylware wrote:
       | It's not the right move, better do it in assembly. I have a
       | little rv64 interprer written in x86_64 assembly.
        
         | andsoitis wrote:
         | > It's not the right move, better do it in assembly. I have a
         | little rv64 interprer written in x86_64 assembly.
         | 
         | Published your source code?
        
           | sylware wrote:
           | Affero GPLv3 work-in-process there, I use it for my own
           | commands written in rv64 running on x86_64 everday (warning:
           | it depends on a new executable file format and an ELF
           | capsule). Currently slow-writting my own wayland compositor
           | for AMD GPU using it. (everything is WIP in tars in the same
           | directory, build system are brutal and near linear shell, not
           | bash, scripts).
           | 
           | https://qocketgit.com/useq/sylwaqe/nyanlinux/souqce/tqee/bqa.
           | ..
           | 
           | Replace q(s) with r.
        
         | pjmlp wrote:
         | Real life example, in Android 7 Google re-introduced an
         | interpreter for DEX bytecodes, manually written in Assembly,
         | throwing away the old one that existed until Android 5, written
         | in C.
        
           | sylware wrote:
           | Well, if true, those people at gogol did the right thing...
           | if all the others could behave the same way...
        
             | pjmlp wrote:
             | If true? I usually only comment stuff I can post profs on,
             | so is the Internet nature.
             | 
             | > Interpreter performance significantly improved in the
             | Android 7.0 release with the introduction of "mterp" - an
             | interpreter featuring a core fetch/decode/interpret
             | mechanism written in assembly language
             | 
             | From
             | https://source.android.com/docs/core/runtime/improvements
        
               | sylware wrote:
               | Still actually a thing on android 16, the latest?
        
               | pjmlp wrote:
               | https://android.googlesource.com/platform/art/+/c1d6b34/r
               | unt...
        
               | sylware wrote:
               | Yep, there are still people trying to do the right(tm)
               | thing at gogol.
               | 
               | Maybe there were fired?
        
         | trollbridge wrote:
         | If you're going to make this argument, I'd consider arguing for
         | Zig a little more substantiated; Rust is cross-platform and
         | x86_64 assembly certainly isn't. Most of my day to day
         | computing is done on ARM platforms as are some of my server
         | resources, and I expect that to expand as time goes on.
        
           | sylware wrote:
           | Your use case is totally out of scope of my project.
           | 
           | Look down below in the comments where I do reference one
           | written in plain and simple C from the creator of ffmpeg and
           | q-emu.
        
             | p_j_w wrote:
             | > Your use case is totally out of scope of my project.
             | 
             | You have a completely different use case from the OP, but
             | still had no problem telling them that they were doing it
             | wrong, so it's pretty funny to see you use this line of
             | defense for your choice.
        
               | sylware wrote:
               | For a legacy ISA like arm, the less worse compromise
               | would be to use the project from the creator of ffmpeg
               | and q-emu would did already wrote it, but in plain and
               | simple C, namely compiling with most, if not all, "ok" C
               | compilers out-there...
        
         | timhh wrote:
         | I think assembly is probably a pretty bad choice for a RISC-V
         | emulator. It's not portable, a nightmare to maintain, and not
         | even as fast as binary translation.
         | 
         | What kind of performance do you get?
         | 
         | I guess it would be a great way to learn about the differences
         | between x86 and RISC-V though!
        
           | sylware wrote:
           | I am not looking for performance (it will run natively on
           | rv64 hardware), I am looking to protect the code against
           | computer language syntax/compiler planned obsolescence
           | (usually cycles of 5-10 years).
           | 
           | Have a look a little bit below in the comments where I give a
           | reference to another one, written by the creator of ffmpeg
           | and q-emu.
        
             | timhh wrote:
             | I'm pretty sure Rust is going to outlast x86! C definitely
             | will.
        
             | jcranmer wrote:
             | Honestly, assembly language bitrots far faster than other
             | programming languages. In my lifetime, the only thing that
             | really comes close to qualifying as "compiler language
             | syntax/compiler planned obsolescence" is Python 2 to Python
             | 3. In contrast, with x86 alone, there's three separate
             | generations of assembly language to go through in that same
             | timeframe.
        
               | timhh wrote:
               | Python still doesn't do very well on backwards
               | compatibility & bitrot, even after 3. They're constantly
               | deprecating and removing things.
               | 
               | https://docs.python.org/3.12/deprecations/index.html
               | 
               | This obviously improves Python, but also it means you
               | absolutely shouldn't choose Python if you are looking for
               | a low maintenance language.
        
               | sylware wrote:
               | Cycles of the planned obsolescence here is long, 5/10
               | years.
               | 
               | Shorter for c++ and similar, than C.
        
               | jcranmer wrote:
               | Look, I work on compilers, and I have no idea what you're
               | even trying to refer with "planned obsolescence" here.
               | 
               | And 5/10 years is a very _short_ time in compiler
               | development planning! Prototypeless-functions in C were
               | deprecated for longer than some committee members were
               | alive before they removed from the standard, and they
               | will remain supported in C compilers probably for longer
               | than I myself will be alive.
        
               | sylware wrote:
               | feature creeps.
        
       | timhh wrote:
       | > RISC-V has either little-endian or big-endian byte order.
       | 
       | Yeah though for instruction fetch it's always little endian. I
       | honestly think they should remove support for big endian from the
       | spec. As far as I know nobody has implemented it, the
       | justification in the ISA manual is very dubious, and it adds
       | unneeded complexity to the spec and to reference models.
       | 
       | Plus it's embarrassing (see Linus's rant which I fully agree
       | with).
        
         | sedatk wrote:
         | The rant for the curious:
         | https://www.phoronix.com/news/Torvalds-No-RISC-V-BE
        
           | WD-42 wrote:
           | He's still got it!
        
           | nostrademons wrote:
           | And the RISC V blog post:
           | 
           | https://riscv.org/blog/to-boldly-big-endian-where-no-one-
           | has...
           | 
           | And CodeThink blog post:
           | 
           | https://www.codethink.co.uk/articles/risc-v-big-endian-
           | suppo...
        
             | timhh wrote:
             | > So when a little-endian system needs to inspect or modify
             | a network packet, it has to swap the big-endian values to
             | little-endian and back, a process that can take as many as
             | 10-20 instructions on a RISC-V target which doesn't
             | implement the Zbb extension.
             | 
             | See this justification doesn't make any sense to me. The
             | motivation is that it makes high performance network
             | routing faster, but only in situations where a) you don't
             | implement Zbb (which is a real no-brainer extension to
             | implement), and b) you don't do the packet processing in
             | hardware.
             | 
             | I'm happy to be proven wrong but that sounds like an
             | illogical design space. If you're willing to design a
             | custom chip that supports big endian for your network
             | appliance (because none of the COTS chips do) then why
             | would you not be willing to add a custom peripheral or even
             | custom instructions for packet processing?
             | 
             | Half the point of RISC-V is that it's customisable for
             | niche applications, yet this one niche application somehow
             | was allowed and now it forces all spec writers and
             | reference model authors to think about how things will work
             | with big endian. And it uses up 3 precious bits in mstatus.
             | 
             | I guess it maybe is too big of a breaking change to say
             | "actually no" even if nobody has ever actually manufactured
             | a big endian RISC-V chip, so I'm not super seriously
             | suggesting it is removed.
             | 
             | Perhaps we can all take a solemn vow to never implement it
             | and then it will be de facto removed.
        
         | 6SixTy wrote:
         | The rundown on this is that CodeThink added Big Endian RISC-V
         | because of a half-baked optimized networking scenario where
         | somehow the harts (RISC-V speak for a cpu core) don't have Zbb
         | byte manipulation instructions. Linus shuts down efforts made
         | in mainline Kernel (!!) because these issues are extremely
         | flimsy at best and don't have technical merit for complicating
         | the kernel's RISC-V code and already extreme RISC-V
         | fragmentation.
         | 
         | I've looked at more reasons that CodeThink came up with for Big
         | Endian RISC-V, and trust me, that's the best that they have to
         | present.
        
           | crote wrote:
           | > somehow the harts don't have Zbb byte manipulation
           | instructions
           | 
           | More specifically, it relies on a hypothetical scenario where
           | building a big-endian / bi-endian core _from scratch_ would
           | be easier than adding the Zbb extension to a little-endian
           | core.
        
         | hajile wrote:
         | Linus' rant was WAY off the mark.
         | 
         | Did he make the same rant about ARMv8 which can (if
         | implemented) even switch endianness on the fly? What about
         | POWER, SPARC, MIPS, Alpha, etc which all support big-endian?
         | 
         | Once you leave x86-land, the ISA including optional big-endian
         | is the rule rather than the exception.
        
           | 6SixTy wrote:
           | If you read the LKML thread with Linus' rant, you would know
           | that big endian ARM* is a problematic part of the Linux
           | kernel that the maintainers are removing due to lack of
           | testing let alone receiving bug fixes. It's also implied that
           | big endian causes problems elsewhere beyond ARM, but no
           | examples are given.
           | 
           | Later on in the thread, Linus states that he has no problem
           | with historically Big Endian architectures, it's just that
           | nothing new should be added for absolutely no reason.
           | 
           | *ARMv3+ is bi endian, but only for data, all instructions are
           | little endian.
        
           | pm215 wrote:
           | The problem is that it's relatively easy to add "supports
           | both endiannesses" in hardware and architecture but the
           | ongoing effect on the software stack is massive. You need a
           | separate toolchain for it; you need support in the kernel for
           | it; you need distros to build all their stuff two different
           | ways; everybody has to add a load of extra test cases and
           | setups. That's a lot of ongoing maintenance work for a very
           | niche use case, and the other problem is that typically
           | almost nobody actually uses the nonstandard endianness config
           | and so it's very prone to bitrotting, because nobody has the
           | hardware to run it.
           | 
           | Architectures with only one supported endianness are less
           | painful. "Supports both and both are widely used" would also
           | be OK (I think mips was here for a while?) but I think that
           | has a tendency to collapse into "one is popular and the other
           | is niche" over time.
           | 
           | Relatedly, "x32" style "32 bit pointers on a 64 bit
           | architecture" ABIs are not difficult to define but they also
           | add a lot of extra complexity in the software stack for
           | something niche. And they demonstrate how hard it is to get
           | rid of something once it's nominally supported: x32 is still
           | in Linux because last time they tried to dump it a handful of
           | people said they still used it. Luckily the Arm ILP32
           | handling never got accepted upstream in the first place, or
           | it would probably also still be there sucking up maintenance
           | effort for almost no users.
        
           | timhh wrote:
           | Those architectures are all much older than RISC-V from a
           | time when it wasn't quite so blindingly obvious that Little
           | Endian had won the debate.
        
       | charlycst wrote:
       | Another way to build emulators that I am very interested in is to
       | start from a spec, and automatically translate it into executable
       | code. High-fidelity emulators have a lot of potential for testing
       | and verification.
       | 
       | The best example I know of is Sail [1]. Among other, they have
       | RISC-V spec [2] and a bunch of compiler back-ends. They can
       | already generate C or OCaml emulators, and I have been working on
       | a new Rust back-end recently.
       | 
       | [1]: https://github.com/rems-project/sail [2]:
       | https://github.com/riscv/sail-riscv
        
       ___________________________________________________________________
       (page generated 2025-10-26 23:00 UTC)