# felix86 and the case for JIT emulating x86 on RISC-V hardware

> felix86 is a Linux userspace emulator that runs x86 and x86-64 programs on RISC-V processors, using a just-in-time recompiler and the RISC-V Vector Extension to cover SIMD up to AVX2. It is a research-grade project with a compatibility list rather than a claim of completeness.

**OFFTKP/felix86** — Run x86 and x86-64 games on RISC‑V Linux

- Repository: https://github.com/OFFTKP/felix86
- Website: https://felix86.com
- Stars: 703 · Forks: 35
- Language: C++
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/offtkp-felix86

## The approach is a JIT, not an interpreter

felix86 is a Linux userspace emulator that allows you to run x86 and x86-64 programs on RISC-V processors, and the word that matters in that sentence is userspace. It is not a virtual machine and not a full system emulator. It runs programs the way you would run them, on top of the Linux kernel that is already there, which is what makes it usable on a RISC-V board rather than only in a hypervisor.

The mechanism is a just-in-time recompiler. Rather than decoding and interpreting each x86 instruction, the emulator translates x86 code into RISC-V code at run time and lets the host processor execute the translated version. That is the same general strategy a JIT uses on a virtual machine, applied across an instruction set boundary.

The payoff of that strategy is that the hot path ends up as native RISC-V code, which is the whole reason to prefer a JIT over an interpreter when the goal is running something that expects real performance.

The costs are the usual ones. A JIT needs to be able to translate every instruction the program uses, and it needs somewhere to put translated code, and it has to handle the case where the program does something it has not seen before.

The project describes itself as being started for several reasons, including gaining a deeper understanding of x86-64, RISC-V, Linux and high-level emulation, exploring optimizing compilers and JITs including SSA, register allocation and optimisation passes, learning low level details such as signals, syscalls and program loading, and taking on a fun and challenging project. The homepage is felix86.com, the licence is MIT, and the primary language is C++.

## The RISC-V Vector Extension is what makes AVX2 affordable

The feature list has four items, and one of them is the technical heart of the project.

felix86 uses the RISC-V Vector Extension for SIMD extensions up to AVX2. That is a specific and quite clever piece of engineering. AVX2 is 256-bit wide SIMD, and the RISC-V Vector Extension is a variable-length vector unit, so a translator can map a 256-bit AVX2 operation onto two RISC-V vector registers of 128 bits, or onto a single one depending on the configuration. Instead of emulating vector instructions one lane at a time, which would be catastrophically slow, the emulator uses the host's own vector hardware.

This is why the feature list mentions it separately from the JIT. The JIT handles the general case, and the vector path is the special case that decides whether anything CPU-bound is usable.

Two of the other features matter for what you can run. It supports RVA23 hardware and many optional extensions, which is about the baseline the RISC-V profile and the extension set. And it uses the host libraries in some cases for improved performance, which is a shortcut that means some of the burden of an emulation is handed to the platform rather than reimplemented.

The last feature, the just-in-time recompiler, is the one everything else hangs off.

## Installation is a curl script that also fetches a rootfs

The getting started section is remarkably short, and there is a reason for that.

On Ubuntu, Debian, Bianbu and possibly other distributions, the documented command is:

```bash
bash <(curl -fsSL https://install.felix86.com)
```

That command downloads and runs a script which installs felix86 and a rootfs of your choice. Two things are worth pausing on.

The first is that a rootfs is part of the install. Emulating x86 on RISC-V means the x86 program needs an x86 Linux environment to run against, and rather than requiring you to assemble one, the installer brings a prepared filesystem along. That is what makes the getting started path a single command rather than a setup guide.

The second is that the install path pipes a script from the network straight into a shell. That is convenient and it is a decision to make consciously, particularly in a locked-down environment, where fetching and running a remote script is often blocked outright. The project also points at documentation for developers and users at felix86.com/docs, which is the place to look for a route that does not involve the one-liner.

For anyone evaluating the project without RISC-V hardware to hand, the compatibility list at felix86.com/compat is the first thing to read after the feature list, because it tells you what is known to work.

## The dependency list explains how the x86 side is handled

The dependencies section is a good map of how much of this is hand written and how much is assembled from other people’s work.

FEX contributes its comprehensive unit test suite, which is a significant thing to inherit since a test suite is the part of a project that defines correct behaviour. Biscuit is used for RISC-V code emission, so the actual translation target is somebody else’s compiler backend rather than hand-rolled assembly. Zydis handles decoding and disassembly on the x86 side, so the emulator is not writing its own x86 decoder either.

Then the supporting cast. Catch2 for unit testing, fmt for string formatting, nlohmann/json for JSON parsing, and tomlc17 for TOML parsing. And berkeley-softfloat-3 for x87 80-bit float emulation, which is a specific and necessary dependency: the x87 stack is an unusual piece of the x86 architecture and emulating it correctly is its own problem.

The project also uses binary tests from other projects to verify correct behaviour and prevent regressions, and those are collected in a separate repository under the felix86-emu organisation.

So the division of labour is clear. The parts that define the project are the JIT strategy, the vector translation and the system-call and signal layer, and the parts it reuses are decoding, code generation, floating point and the test corpus.

## The repository layout shows where the work is

The top-level entries of the repository tell you what the project is made of, and two of the names are unusual enough to be worth a look.

There is src/ for the implementation, tests/ for the test code, docs/ for the documentation, and external/ for the dependencies that are not fetched by a package manager. There is a CMakeLists.txt at the root with a riscv.cmake alongside it, which is how you build a cross-compiled RISC-V project, and a CheckGit.cmake, which is a build-time check that the working tree is what the build expects.

The two that stand out are counts/ and latencies/. A directory called latencies is the shape of a project that measures how long its translated code takes, and counts is the shape of one that counts instructions or blocks. Both point to a deliberate practice of measuring the emulator against something rather than assuming it is fast.

The .clang-format file at the root confirms the C++ toolchain, and FUNDING.yml alongside the licence file are the ordinary markers of a project that takes sponsorship.

The last structural point is about the surrounding community. The repository carries a good-first-issue topic tag, which is a signal that the project intends to be approachable by newcomers, and it links a Discord server for questions.

## Where felix86 is the wrong tool

The first and clearest case is a program that depends on instructions the emulator does not implement. The project publishes a compatibility list rather than claiming completeness, and the honest reading of that is that there are x86 programs it cannot run, or can run but not quickly. For a tool that exists to run specific binaries, that list is the specification, and you should read it before anything else.

The second case is latency-sensitive work. A JIT with a translation step has a warm-up cost, and a program that runs briefly pays it in full. For a long-running service the amortisation is fine. For a benchmark that measures the first second, the numbers describe the translator rather than the program.

The third is the RISC-V Vector Extension dependency. Mapping AVX2 onto it is what makes compute-heavy x86 code viable, but it means the host needs a vector-capable RISC-V implementation. On a board without it, the SIMD paths either do not apply or are slow, and the compatibility behaviour may differ from what the feature list implies.

The fourth is the shape of the project itself. The stated motivations are learning and exploration, and the release numbering is a calendar version, 26.08, 26.09 and 26.10 for August, September and October 2026, with the last push on 2026-10-18. A project on that cadence is moving fast, and fast-moving emulator projects change behaviour between releases in ways a stable dependency would not.

## Conclusion

felix86 suits a developer with RISC-V hardware who needs to run an x86 binary, particularly a binary whose SIMD code the RISC-V Vector Extension can absorb, and it suits anyone studying how a modern emulator is put together. It does not suit someone expecting every x86 program to run, because the project publishes a compatibility list rather than a completeness claim, and it does not suit a game that depends on instructions the JIT does not implement. Before you rely on it, check the compatibility list for the specific title or tool, and note that the installer is a curl-and-bash script that also fetches a rootfs, so a restricted environment needs a different route.

## FAQ

### What is felix86?

It is a Linux userspace emulator that allows you to run x86 and x86-64 programs on RISC-V processors. It uses a just-in-time recompiler rather than interpretation, and it uses the RISC-V Vector Extension to provide SIMD support up to AVX2.

### How do I install felix86?

On Ubuntu, Debian, Bianbu and possibly others, run bash <(curl -fsSL https://install.felix86.com). That downloads and runs a script which installs felix86 along with a rootfs of your choice. Project documentation for developers and users is at felix86.com/docs.

### How does felix86 handle x86 SIMD instructions?

It uses the RISC-V Vector Extension for SIMD extensions up to AVX2, so vector work is carried out by the host's own vector hardware rather than emulated lane by lane. The project also supports RVA23 hardware and many optional extensions, and uses host libraries in some cases for better performance.

### What can felix86 actually run?

The project publishes a compatibility list at felix86.com/compat rather than claiming completeness, and that list is the specification for what is known to work. The project is used for running x86 and x86-64 games on RISC-V Linux, and its stated motivation includes understanding emulation and exploring JITs.

### What does felix86 depend on?

It relies on FEX for its unit test suite, Biscuit for RISC-V code emission, Zydis for x86 decoding and disassembly, berkeley-softfloat-3 for x87 80-bit float emulation, Catch2 for unit testing, fmt for string formatting, nlohmann/json for JSON and tomlc17 for TOML. It also uses binary tests from other projects to check behaviour and prevent regressions.

## Sources

- [License: MIT](https://github.com/OFFTKP/felix86/blob/master/LICENSE)
- [OFFTKP/felix86 on GitHub](https://github.com/OFFTKP/felix86)
- [Project website](https://felix86.com)
- [README](https://github.com/OFFTKP/felix86/blob/master/README.md)
- [Releases](https://github.com/OFFTKP/felix86/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/offtkp-felix86
